-
- Drul_array<Real> ys;
- Direction d = LEFT;
- do
- {
- if (state.extremes_[d].slur_head_)
- ys[d] = state.extremes_[d].slur_head_->relative_coordinate (state.common_[Y_AXIS],
- Y_AXIS);
- else
- ys[d] = state.extremes_[d].neighbor_y_;
- }
- while (flip (&d) != LEFT);
-
- bool has_beams
- = (state.extremes_[LEFT].stem_ && Stem::get_beam (state.extremes_[LEFT].stem_))
- || (state.extremes_[RIGHT].stem_ && Stem::get_beam (state.extremes_[RIGHT].stem_));
-
- Real dy = ys[RIGHT] - ys[LEFT];
- for (int i = 0; i < state.scores_->size (); i++)
- {
- Offset slur_dz = (*state.scores_)[i].attachment_[RIGHT]
- - (*state.scores_)[i].attachment_[LEFT];
- Real slur_dy = slur_dz[Y_AXIS];
- Real demerit = 0.0;
-
- demerit += ((fabs (slur_dy / slur_dz[X_AXIS])
- - state.parameters_.max_slope_) >? 0)
- * state.parameters_.max_slope_factor_;
-
- /* 0.2: account for staffline offset. */
- Real max_dy = (fabs (dy) + 0.2);
- if (has_beams)
- max_dy += 1.0;
-
- demerit += state.parameters_.steeper_slope_factor_
- * ((fabs (slur_dy) -max_dy) >? 0);
-
- demerit += ((fabs (slur_dy/slur_dz[X_AXIS])
- - state.parameters_.max_slope_) >? 0)
- * state.parameters_.max_slope_factor_;
-
- if (sign (dy) == 0
- && sign (slur_dy) != 0)
- demerit += state.parameters_.non_horizontal_penalty_;
-
- if (sign (dy)
- && sign (slur_dy)
- && sign (slur_dy) != sign (dy))
- demerit += has_beams
- ? state.parameters_.same_slope_penalty_ / 10
- : state.parameters_.same_slope_penalty_;
-
-#if DEBUG_SLUR_QUANTING
- (*state.scores_)[i].score_card_ += to_string ("S%.2f", d);
-#endif
- (*state.scores_)[i].score_ += demerit;
- }
-
-
-
-}
-
-
-Real
-fit_factor (Offset dz_unit, Offset dz_perp,
- Bezier curve, Direction d, Array<Offset> const &avoid)
-{
- Real fit_factor = 0.0;
- Offset x0 = curve.control_[0];
- curve.translate (-x0);
- curve.rotate (-dz_unit.arg ());
- curve.scale (1, d);
-
- Interval curve_xext;
- curve_xext.add_point (curve.control_[0][X_AXIS]);
- curve_xext.add_point (curve.control_[3][X_AXIS]);
-
- for (int i = 0; i < avoid.size (); i++)
- {
- Offset z = (avoid[i] - x0) ;
- Offset p (dot_product (z, dz_unit),
- d* dot_product (z, dz_perp));
- if (!curve_xext.contains (p[X_AXIS]))
- continue;
-
- Real y = curve.get_other_coordinate (X_AXIS, p[X_AXIS]);
- if (y)
- {
- fit_factor = fit_factor >? (p[Y_AXIS] / y);
- }
- }
- return fit_factor;
-}
-
-
-Bezier
-get_bezier (Slur_score_state const &state,
- Drul_array<Offset> attachments,
- Real r_0, Real h_inf
- )
-{
- Link_array<Grob> encompasses = state.columns_;
-
- Array<Offset> avoid;
- for (int i = 0; i < encompasses.size (); i++)
- {
- if (state.extremes_[LEFT].note_column_ == encompasses[i]
- || state.extremes_[RIGHT].note_column_ == encompasses[i])
- continue;
-
- Encompass_info inf (get_encompass_info (state, encompasses[i]));
-
- Real y = state.dir_ * ((state.dir_ * inf.head_) >? (state.dir_ *inf.stem_));
-
- avoid.push (Offset (inf.x_, y + state.dir_ * state.parameters_.free_head_distance_));
- }
-
- Link_array<Grob> extra_encompasses
- = Pointer_group_interface__extract_grobs (state.slur_, (Grob *)0, "encompass-objects");
- for (int i = 0; i < extra_encompasses.size (); i++)
- if (Slur::has_interface (extra_encompasses[i]))
- {
- Grob * small_slur = extra_encompasses[i];
- Bezier b = Slur::get_curve (small_slur);
-
- Offset z = b.curve_point (0.5);
- z += Offset (small_slur->relative_coordinate (state.common_[X_AXIS], X_AXIS),
- small_slur->relative_coordinate (state.common_[Y_AXIS], Y_AXIS));
-
- z[Y_AXIS] += state.dir_ * state.parameters_.free_slur_distance_;
- avoid.push (z);
- }
-
- Offset dz = attachments[RIGHT]- attachments[LEFT];;
- Offset dz_unit = dz;
- dz_unit *= 1 / dz.length ();
- Offset dz_perp = dz_unit * Offset (0, 1);
-
- Real indent, height;
- get_slur_indent_height (&indent, &height, dz.length (), h_inf, r_0);
-
- Real excentricity = robust_scm2double (state.slur_->get_property ("excentricity"), 0);
- Bezier curve;
-
- Real x1 = (excentricity + indent);
- Real x2 = (excentricity - indent);
- curve.control_[0] = attachments[LEFT];
- curve.control_[1] = attachments[LEFT] + dz_perp * height * state.dir_ + dz_unit * x1;
- curve.control_[2] = attachments[RIGHT] + dz_perp * height * state.dir_
- + dz_unit * x2;
- curve.control_[3] = attachments[RIGHT];
-
- Real ff = fit_factor (dz_unit, dz_perp, curve, state.dir_, avoid);
- Real len = dz.length ();
-
- /* This condition,
-
- len^2 > 4h^2 + 3 (i 1/3len)^2 - 1/3 len^2
-
- is equivalent to:
-
- |bez' (0)| < | bez' (.5)|
-
- when (control2 - control1) has the same direction as
- (control3 - control0). */
-
- Real a1 = sqr (len) / 3.0;
- Real a2 = 0.75 * sqr (indent + len / 3.0);
- Real max_h;
- if (a1 >= a2)
- max_h = sqrt (a1 - a2);
- else
- {
- programming_error ("FIXME: max_h is broken; setting to length / 3");
- max_h = len / 3.0;
- }
- height = height >? ((height * ff) <? max_h);
-
- curve.control_[0] = attachments[LEFT];
- curve.control_[1] = attachments[LEFT] + dz_perp * height * state.dir_ + dz_unit * x1;
- curve.control_[2] = attachments[RIGHT] + dz_perp * height * state.dir_ + dz_unit * x2;
- curve.control_[3] = attachments[RIGHT];
-
- return curve;