From ff153408e34e11baeed192695f3f6b8669928311 Mon Sep 17 00:00:00 2001 From: Keith OHara Date: Mon, 11 Nov 2013 17:24:56 -0800 Subject: [PATCH] slurs avoid stafflines: move far enough; issue 3628 --- lily/include/slur-score-parameters.hh | 2 ++ lily/include/slur-scoring.hh | 1 + lily/slur-configuration.cc | 34 +++++++++++++++++++-------- lily/slur-score-parameters.cc | 4 ++++ lily/slur-scoring.cc | 4 ++-- lily/slur.cc | 6 +++++ scm/layout-slur.scm | 2 ++ 7 files changed, 41 insertions(+), 12 deletions(-) diff --git a/lily/include/slur-score-parameters.hh b/lily/include/slur-score-parameters.hh index 75b1ae8e46..7db1ba417c 100644 --- a/lily/include/slur-score-parameters.hh +++ b/lily/include/slur-score-parameters.hh @@ -40,6 +40,8 @@ struct Slur_score_parameters Real free_head_distance_; Real extra_encompass_collision_distance_; Real extra_encompass_free_distance_; + Real gap_to_staffline_inside_; + Real gap_to_staffline_outside_; Real absolute_closeness_measure_; Real edge_slope_exponent_; Real close_to_edge_length_; diff --git a/lily/include/slur-scoring.hh b/lily/include/slur-scoring.hh index e5ff38d611..2fc069b902 100644 --- a/lily/include/slur-scoring.hh +++ b/lily/include/slur-scoring.hh @@ -100,6 +100,7 @@ struct Slur_score_state Drul_array base_attachments_; vector configurations_; Real staff_space_; + Real line_thickness_; Real thickness_; Slur_score_state (); diff --git a/lily/slur-configuration.cc b/lily/slur-configuration.cc index 332995ac99..46e9d917a1 100644 --- a/lily/slur-configuration.cc +++ b/lily/slur-configuration.cc @@ -43,27 +43,41 @@ avoid_staff_line (Slur_score_state const &state, && (state.extremes_[LEFT].staff_ == state.extremes_[RIGHT].staff_) && state.extremes_[LEFT].staff_ && state.extremes_[RIGHT].staff_) { - Real y = bez.curve_point (ts[0])[Y_AXIS]; + Real t = ts[0]; //the first (usually only) point where slur is horizontal + Real y = bez.curve_point (t)[Y_AXIS]; + // A Bezier curve at t moves 3t-3t² as far as the middle control points + Real factor = 3.0 * t * (1.0 - t); Grob *staff = state.extremes_[LEFT].staff_; Real p = 2 * (y - staff->relative_coordinate (state.common_[Y_AXIS], Y_AXIS)) / state.staff_space_; - Real const round = my_round (p); - Real const frac = p - round; - if (fabs (frac) < 4 * state.thickness_ - && Staff_symbol_referencer::on_staff_line (staff, int (round))) + int round_p = (int) my_round (p); + if (!Staff_symbol_referencer::on_staff_line (staff, round_p)) + round_p += (p > round_p) ? 1 : -1; + if (!Staff_symbol_referencer::on_staff_line (staff, round_p)) + return bez; + + Real const distance = (p - round_p) * state.staff_space_ / 2.0; + // Allow half the thickness of the slur at the point t, plus one basic + // blot-diameter (half for the slur outline, half for the staff line) + Real const min_distance = 0.5 * state.thickness_ * factor + + state.line_thickness_ + + ((state.dir_ * distance > 0.0) + ? state.parameters_.gap_to_staffline_inside_ + : state.parameters_.gap_to_staffline_outside_); + if (fabs (distance) < min_distance) { - Direction resolution_dir = frac ? state.dir_ : CENTER; + Direction resolution_dir = (distance > 0.0) ? UP : DOWN; - // TODO: parameter - Real newp = round + resolution_dir * 5 * state.thickness_; - - Real dy = (newp - p) * state.staff_space_ / 2.0; + Real dy = resolution_dir * (min_distance - fabs (distance)); + // Shape the curve, moving the horizontal point by factor * dy bez.control_[1][Y_AXIS] += dy; bez.control_[2][Y_AXIS] += dy; + // Move the entire curve by the remaining amount + bez.translate (Offset (0.0, dy - factor * dy)); } } return bez; diff --git a/lily/slur-score-parameters.cc b/lily/slur-score-parameters.cc index a8cbe4b7f9..789e31ea4b 100644 --- a/lily/slur-score-parameters.cc +++ b/lily/slur-score-parameters.cc @@ -56,6 +56,10 @@ Slur_score_parameters::fill (Grob *me) = get_detail (details, ly_symbol2scm ("max-slope-factor")); free_head_distance_ = get_detail (details, ly_symbol2scm ("free-head-distance")); + gap_to_staffline_inside_ + = get_detail (details, ly_symbol2scm ("gap-to-staffline-inside")); + gap_to_staffline_outside_ + = get_detail (details, ly_symbol2scm ("gap-to-staffline-outside")); absolute_closeness_measure_ = get_detail (details, ly_symbol2scm ("absolute-closeness-measure")); extra_object_collision_penalty_ diff --git a/lily/slur-scoring.cc b/lily/slur-scoring.cc index 47bb40611c..98e3f2a45d 100644 --- a/lily/slur-scoring.cc +++ b/lily/slur-scoring.cc @@ -226,8 +226,8 @@ Slur_score_state::fill (Grob *me) Slur::replace_breakable_encompass_objects (me); staff_space_ = Staff_symbol_referencer::staff_space (me); - Real lt = me->layout ()->get_dimension (ly_symbol2scm ("line-thickness")); - thickness_ = robust_scm2double (me->get_property ("thickness"), 1.0) * lt; + line_thickness_ = me->layout ()->get_dimension (ly_symbol2scm ("line-thickness")); + thickness_ = robust_scm2double (me->get_property ("thickness"), 1.0) * line_thickness_; dir_ = slur_direction (); parameters_.fill (me); diff --git a/lily/slur.cc b/lily/slur.cc index 0aa96c787d..10069aacd4 100644 --- a/lily/slur.cc +++ b/lily/slur.cc @@ -542,6 +542,12 @@ ADD_INTERFACE (Slur, "@item head-slur-distance-max-ratio\n" "The maximum value for the ratio of distance between a" " note head and slur.\n" + "@item gap-to-staffline-inside\n" + "Minimum gap inside the curve of the slur" + " where the slur is parallel to a staffline.\n" + "@item gap-to-staffline-outside\n" + "Minimum gap outside the curve of the slur" + " where the slur is parallel to a staffline.\n" "@item free-slur-distance\n" "The amount of vertical free space that must exist" " between adjacent slurs. This subproperty only works" diff --git a/scm/layout-slur.scm b/scm/layout-slur.scm index 7e5ab5858c..7ad02ec09e 100644 --- a/scm/layout-slur.scm +++ b/scm/layout-slur.scm @@ -28,6 +28,8 @@ (max-slope-factor . 10) (free-head-distance . 0.3) (free-slur-distance . 0.8) + (gap-to-staffline-inside . 0.2) + (gap-to-staffline-outside . 0.1) (extra-object-collision-penalty . 50) (accidental-collision . 3) (extra-encompass-free-distance . 0.3) -- 2.39.2