From: Han-Wen Nienhuys Date: Fri, 20 Jan 2006 17:38:34 +0000 (+0000) Subject: * input/regression/tie-chord.ly: use generateTiePattern to X-Git-Tag: release/2.7.28~5 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=d445cda01e4d86896f55fd1cf2ccbaba8cb7917a;p=lilypond.git * input/regression/tie-chord.ly: use generateTiePattern to simplify file. * lily/tie-formatting-problem.cc (peak_around): new function. (score_configuration): use sliding criterion for staff line collisions. (score_configuration): idem for dot collisions. (generate_configuration): use separate stem_gap for gap to stem. * lily/include/tie-formatting-problem.hh (struct Tie_details): separate penalty factors for x and y distance. (struct Tie_details): separate penalties for tip and center line collisions. --- diff --git a/ChangeLog b/ChangeLog index 31fa0c1a72..2d481225fb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,17 @@ -<<<<<<< ChangeLog +2006-01-20 Han-Wen Nienhuys + + * input/regression/tie-chord.ly: use generateTiePattern to + simplify file. + + * lily/tie-formatting-problem.cc (peak_around): new function. + (score_configuration): use sliding criterion for staff line collisions. + (score_configuration): idem for dot collisions. + (generate_configuration): use separate stem_gap for gap to stem. + + * lily/include/tie-formatting-problem.hh (struct Tie_details): + separate penalty factors for x and y distance. + (struct Tie_details): separate penalties for tip and center line collisions. + 2006-01-19 Han-Wen Nienhuys * lily/tie-formatting-problem.cc (generate_configuration): make @@ -13,14 +26,12 @@ * lily/staff-symbol-referencer.cc (on_line): rename from on_staffline -======= 2006-01-18 Han-Wen Nienhuys * ly/music-functions-init.ly: remove duplicate tag. * lily/include/*.hh: GCC 4.1 fixes. ->>>>>>> 1.4455 006-01-16 Erlend Aasland * Documentation/user/global.itely: fix typos; @bugs -> @refbugs diff --git a/input/regression/tie-chord.ly b/input/regression/tie-chord.ly index 74b448a027..d6035a0ea6 100644 --- a/input/regression/tie-chord.ly +++ b/input/regression/tie-chord.ly @@ -20,54 +20,84 @@ each system. " raggedright = ##t } + + +generateTiePattern += #(def-music-function (parser location is-long chords) (boolean? ly:music?) + + " + +translate x y z to x~x y~y z~z + +" + + (define (chord->tied-chord chord) + (let* + ((ch1 (ly:music-deep-copy chord)) + (ch2 (ly:music-deep-copy chord)) + (dur1 (ly:make-duration + (if is-long + 1 2))) + (dur2 (ly:make-duration + (if is-long + 3 2)))) + + (for-each (lambda (e) + (ly:music-set-property! e 'duration dur1)) + (ly:music-property ch1 'elements)) + + (for-each (lambda (e) + (ly:music-set-property! e 'duration dur2)) + (ly:music-property ch2 'elements)) + + (set! (ly:music-property ch1 'elements) + (cons + (make-music 'TieEvent) + (ly:music-property ch1 'elements))) + + (list ch1 ch2))) + + (make-music 'SequentialMusic 'elements (apply append + (map chord->tied-chord (ly:music-property chords 'elements))))) + +baseChords = +\applyMusic #(lambda (mus) + (ly:music-property mus 'element)) +\relative c'' { + + + + + + + + + + + +} + testShort = { - \time 4/4 \key c \major - \relative c'' { - % c ~ c - ~ - ~ - ~ - ~ - ~ - } - - \relative c' { - ~ - ~ - - ~ - ~ - 4 ~ - } + \generateTiePattern ##f \baseChords } testLong = { - \time 5/8 \key c \major - \relative c'' { - 2 ~ 8 - 2 ~ 8 - 2 ~ 8 - 2 ~ 8 - 2 ~ 8 - } - - \relative c' { - 2 ~ 8 - 2 ~ 8 - 2 ~ 8 - 2 ~ 8 - 2 ~ 8 - } + \generateTiePattern ##t \baseChords } \new Voice -{ \testShort \break +{ + \time 2/4 + + \testShort \break \transpose c d \testShort \break + \time 5/8 \testLong \break \transpose c d \testLong \break } + diff --git a/lily/include/tie-formatting-problem.hh b/lily/include/tie-formatting-problem.hh index 3325d53380..f311ef682c 100644 --- a/lily/include/tie-formatting-problem.hh +++ b/lily/include/tie-formatting-problem.hh @@ -25,18 +25,22 @@ struct Tie_details Real ratio_; Real staff_space_; Real x_gap_; + Real stem_gap_; Real between_length_limit_; Real wrong_direction_offset_penalty_; - Real distance_penalty_factor_; Real length_penalty_factor_; Real min_length_; - Real staff_line_clearance_; + Real tip_staff_line_clearance_; + Real center_staff_line_clearance_; Real staff_line_collision_penalty_; Real dot_collision_clearance_; Real dot_collision_penalty_; Real tie_column_monotonicity_penalty_; Real tie_tie_collision_penalty_; Real tie_tie_collision_distance_; + Real horizontal_distance_penalty_factor_; + Real vertical_distance_penalty_factor_; + Real intra_space_threshold_; Grob *staff_symbol_referencer_; @@ -71,6 +75,7 @@ struct Tie_configuration_variation class Tie_formatting_problem { Drul_array< Array > chord_outlines_; + Drul_array< Box > stem_extents_; set dot_positions_; Interval dot_x_; Array specifications_; diff --git a/lily/tie-formatting-problem.cc b/lily/tie-formatting-problem.cc index 03293c564b..91a96d48b1 100644 --- a/lily/tie-formatting-problem.cc +++ b/lily/tie-formatting-problem.cc @@ -22,6 +22,16 @@ #include "tie.hh" #include "warn.hh" +/* + 0 at threshold, 1 at 0, with 1/x falloff. + */ +Real peak_around (Real epsilon, Real threshold, Real x) +{ + if (x < 0) + return 1.0; + return max (- epsilon * (x - threshold) / ((x + epsilon) * threshold), 0.0); +} + Interval Tie_formatting_problem::get_attachment (Real y) const { @@ -116,7 +126,7 @@ Tie_formatting_problem::set_chord_outline (Link_array bounds, insert_extent_into_skyline (&chord_outlines_[d], Box (x,y), Y_AXIS, -d); - + stem_extents_[d].unite (Box (x,y)); if (d == LEFT) { @@ -155,7 +165,6 @@ Tie_formatting_problem::from_tie (Grob *tie) { Link_array ties; ties.push (tie); - from_ties (ties); details_.from_grob (tie); @@ -313,15 +322,20 @@ Tie_formatting_problem::generate_configuration (int pos, Direction dir) const Real h = conf->height (details_); if (!conf->delta_y_) { - if (h < 0.5 * details_.staff_space_) + /* + TODO: make sliding criterion? + */ + if (h < details_.intra_space_threshold_ * 0.5 * details_.staff_space_) { - if (!Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_, pos)) + if (!Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_, pos) + && fabs (pos) < 2 * Staff_symbol_referencer::staff_radius (details_.staff_symbol_referencer_)) { conf->center_tie_vertically (details_); } else if (Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_, pos)) { - conf->delta_y_ += dir * 0.2 * details_.staff_space_; + conf->delta_y_ += dir * + details_.tip_staff_line_clearance_ * 0.5 * details_.staff_space_; } } else @@ -331,7 +345,7 @@ Tie_formatting_problem::generate_configuration (int pos, Direction dir) const int round_pos = int (my_round (top_pos)); /* TODO: should use other variable? */ - Real clearance = details_.staff_line_clearance_; + Real clearance = details_.center_staff_line_clearance_; if (fabs (top_pos - round_pos) < clearance && Staff_symbol_referencer::on_staff_line (details_.staff_symbol_referencer_, round_pos)) @@ -342,7 +356,22 @@ Tie_formatting_problem::generate_configuration (int pos, Direction dir) const } } + conf->attachment_x_ = get_attachment (y + conf->delta_y_); conf->attachment_x_.widen ( - details_.x_gap_); + + Direction d = LEFT; + do + { + Real y = conf->position_ * details_.staff_space_ * 0.5 + conf->delta_y_; + if (stem_extents_[d][X_AXIS].is_empty () + || !stem_extents_[d][Y_AXIS].contains (y)) + continue; + + conf->attachment_x_[d] = + d* min (d * conf->attachment_x_[d], + d * (stem_extents_[d][X_AXIS][-d] - d * details_.stem_gap_)); + } + while (flip (&d) != LEFT); return conf; } @@ -356,7 +385,21 @@ Tie_formatting_problem::score_aptitude (Tie_configuration const &conf, if (sign (curve_y - tie_y) != conf.dir_) penalty += details_.wrong_direction_offset_penalty_; - penalty += details_.distance_penalty_factor_ * fabs (curve_y - tie_y); + penalty += details_.vertical_distance_penalty_factor_ * fabs (curve_y - tie_y); + + + Direction d = LEFT; + do + { + if (!spec.note_head_drul_[d]) + continue; + + Interval head_x = spec.note_head_drul_[d]->extent (x_refpoint_, X_AXIS); + Real dist = head_x.distance (conf.attachment_x_[d]); + penalty += details_.horizontal_distance_penalty_factor_ * dist; + } + while (flip (&d) != LEFT); + return penalty; } @@ -375,19 +418,24 @@ Tie_formatting_problem::score_configuration (Tie_configuration const &conf) cons Real top_y = tip_y + conf.dir_ * height; Real top_pos = 2 * top_y / details_.staff_space_; Real round_top_pos = rint (top_pos); - if (fabs (top_pos - round_top_pos) < details_.staff_line_clearance_ - && Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_, + if (Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_, int (round_top_pos)) && Staff_symbol_referencer::staff_radius (details_.staff_symbol_referencer_) > top_y) { - penalty += details_.staff_line_collision_penalty_; + penalty += + details_.staff_line_collision_penalty_ + * peak_around (0.1 * details_.center_staff_line_clearance_, + details_.center_staff_line_clearance_, + fabs (top_pos - round_top_pos)); } - if (fabs (tip_pos - rint (tip_pos)) < details_.staff_line_clearance_ - && Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_, - int (rint (tip_pos)))) + if (Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_, + int (rint (tip_pos)))) { - penalty += details_.staff_line_collision_penalty_; + penalty += details_.staff_line_collision_penalty_ + * peak_around (0.1 * details_.tip_staff_line_clearance_, + details_.tip_staff_line_clearance_, + fabs (tip_pos - rint (tip_pos))); } if (!dot_x_.is_empty ()) @@ -404,10 +452,11 @@ Tie_formatting_problem::score_configuration (Tie_configuration const &conf) cons i != dot_positions_.end (); i ++) { int dot_pos = (*i); - if (fabs (dot_pos * details_.staff_space_ * 0.5 - y) < details_.dot_collision_clearance_) - { - penalty += details_.dot_collision_penalty_; - } + penalty += + details_.dot_collision_penalty_ + * peak_around (.1 * details_.dot_collision_clearance_, + details_.dot_collision_clearance_, + fabs (dot_pos * details_.staff_space_ * 0.5 - y)); } } } @@ -512,16 +561,18 @@ Tie_formatting_problem::score_ties_configuration (Ties_configuration const &ties if (edge <= last_edge) score += details_.tie_column_monotonicity_penalty_; if (center <= last_center) - score +=details_. tie_column_monotonicity_penalty_; + score += details_.tie_column_monotonicity_penalty_; score += - details_.tie_tie_collision_penalty_ - * max (details_.tie_tie_collision_distance_ - fabs (center - last_center), 0.0) - / details_.tie_tie_collision_distance_; + details_.tie_tie_collision_penalty_ * + peak_around (0.1 * details_.tie_tie_collision_distance_, + details_.tie_tie_collision_distance_, + fabs (center - last_center)); score += - details_.tie_tie_collision_penalty_ - * max (details_.tie_tie_collision_distance_ - fabs (edge - last_edge), 0.0) - / details_.tie_tie_collision_distance_; + details_.tie_tie_collision_penalty_ * + peak_around (0.1 * details_.tie_tie_collision_distance_, + details_.tie_tie_collision_distance_, + fabs (edge - last_edge)); } last_edge = edge; @@ -570,12 +621,16 @@ Tie_formatting_problem::generate_base_chord_configuration () * 0.5 * details_.staff_space_; } else - conf.position_ = specifications_[i].position_; - + { + conf.position_ = specifications_[i].position_; + } ties_config.push (conf); } set_ties_config_standard_directions (&ties_config); + for (int i = 0; i < ties_config.size (); i++) + if (!specifications_[i].manual_position_) + ties_config[i].position_ += ties_config[i].dir_; ties_config = generate_ties_configuration (ties_config); @@ -589,7 +644,7 @@ Tie_formatting_problem::generate_optimal_chord_configuration () Array vars = get_variations (base); Ties_configuration best = base; - Real best_score = score_ties_configuration (best); + Real best_score = score_ties (best); /* This simply is 1-opt: we have K substitions, and we try applying @@ -600,8 +655,7 @@ Tie_formatting_problem::generate_optimal_chord_configuration () Ties_configuration variant = base; variant[vars[i].index_] = *vars[i].suggestion_; - Real score = (score_ties_configuration (variant) - + score_ties_aptitude (variant)); + Real score = score_ties (variant); if (score < best_score) { best = variant; @@ -682,7 +736,8 @@ Tie_formatting_problem::get_variations (Ties_configuration const &ties) { Tie_configuration_variation var; var.index_ = i; - var.suggestion_ = get_configuration (ties[i].position_, + var.suggestion_ = get_configuration (specifications_[i].position_ + - ties[i].dir_, -ties[i].dir_); vars.push (var); @@ -692,8 +747,9 @@ Tie_formatting_problem::get_variations (Ties_configuration const &ties) { Tie_configuration_variation var; var.index_ = i-1; - var.suggestion_ = get_configuration (ties[i-1].position_, - -ties[i-1].dir_); + var.suggestion_ = get_configuration (specifications_[i-1].position_ + - ties[i-1].dir_, + - ties[i-1].dir_); vars.push (var); } @@ -703,8 +759,22 @@ Tie_formatting_problem::get_variations (Ties_configuration const &ties) last_center = center; } + /* TODO: switch off? */ + Direction d = DOWN; + do + { + if (ties.boundary (d, 0).dir_ == d) + { + Tie_configuration_variation var; + var.index_ = (d == DOWN) ? 0 : ties.size () - 1; + var.suggestion_ = get_configuration (ties.boundary (d, 0).position_ + d, + d); + vars.push (var); + } + } + while (flip (&d) != DOWN); + return vars; - } void diff --git a/lily/tie-helper.cc b/lily/tie-helper.cc index 6da15c0c3c..2e3f4b826c 100644 --- a/lily/tie-helper.cc +++ b/lily/tie-helper.cc @@ -15,14 +15,17 @@ #include "tie-formatting-problem.hh" -#define get_real_detail(src, defvalue) robust_scm2double(ly_assoc_get (ly_symbol2scm (src), details, SCM_EOL), defvalue) +/* + this is a macro because we want ly_symbol2scm() + */ +#define get_real_detail(src, defvalue) \ + robust_scm2double(ly_assoc_get (ly_symbol2scm (src), details, SCM_EOL), defvalue) void Tie_details::from_grob (Grob *me) { staff_symbol_referencer_ = me; staff_space_ = Staff_symbol_referencer::staff_space (me); - x_gap_ = robust_scm2double (me->get_property ("x-gap"), 0.2); SCM details = me->get_property ("details"); @@ -31,19 +34,24 @@ Tie_details::from_grob (Grob *me) between_length_limit_ = get_real_detail ("between-length-limit", 1.0); wrong_direction_offset_penalty_ = get_real_detail("wrong-direction-offset-penalty", 10); - distance_penalty_factor_ = get_real_detail("distance-penalty-factor", 5); + length_penalty_factor_ = get_real_detail("length-penalty-factor", 1.0); min_length_ = get_real_detail("min-length", 0.333); // in half-space - staff_line_clearance_ = get_real_detail ("staff-line-clearance", 0.4); + center_staff_line_clearance_ = get_real_detail ("center-staff-line-clearance", 0.4); + tip_staff_line_clearance_ = get_real_detail ("tip-staff-line-clearance", 0.4); staff_line_collision_penalty_ = get_real_detail("staff-line-collision-penalty", 5); dot_collision_clearance_ = get_real_detail ( "dot-collision-clearance", 0.25); dot_collision_penalty_ = get_real_detail ( "dot-collision-penalty", 0.25); - + x_gap_ = get_real_detail ("note-head-gap", 0.2); + stem_gap_ = get_real_detail ("stem-gap", 0.3); tie_column_monotonicity_penalty_ = get_real_detail ("tie-column-monotonicity-penalty", 100); tie_tie_collision_penalty_ = get_real_detail ("tie-tie-collision-penalty", 30); tie_tie_collision_distance_ = get_real_detail ("tie-tie-collision-distance", .25); + horizontal_distance_penalty_factor_ = get_real_detail ("horizontal-distance-penalty-factor", 5); + vertical_distance_penalty_factor_ = get_real_detail ("vertical-distance-penalty-factor", 5); + intra_space_threshold_ = get_real_detail ("intra-space-threshold", 1.0); } Tie_details::Tie_details () diff --git a/scm/define-grobs.scm b/scm/define-grobs.scm index 0d3cab0815..4eba1d8e23 100644 --- a/scm/define-grobs.scm +++ b/scm/define-grobs.scm @@ -1716,8 +1716,15 @@ (direction . ,Tie::calc_direction) (stencil . ,Tie::print) (details . ((ratio . 0.333) - (staff-line-clearance . 0.6) + (center-staff-line-clearance . 0.6) + (tip-staff-line-clearance . 0.45) + (note-head-gap . 0.2) + (stem-gap . 0.35) (height-limit . 1.0) + (horizontal-distance-penalty-factor . 10) + (tie-tie-collision-distance . 0.45) + (tie-tie-collision-penalty . 25.0) + (intra-space-threshold . 1.25) (between-length-limit . 1.0))) (thickness . 1.0) (meta . ((class . Spanner)