From 94af2fb150edb6889a47bf5b4052a966f115e12a Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 16 Nov 2005 15:54:43 +0000 Subject: [PATCH] * lily/tie-formatting-problem.cc (find_optimal_tie_configuration): new function. Search region of 3 positions for best tie. (score_configuration): new function. (score_aptitude): new function. (generate_configuration): new function. (get_configuration): new function. (Tie_formatting_problem): new function * input/regression/page-top-space.ly: a6 for page-top-space demo. * lily/include/tie-formatting-problem.hh (class Tie_formatting_problem): add Tie_details to Tie_formatting_problem. Update calling conventions. --- ChangeLog | 10 ++ input/regression/page-top-space.ly | 2 + lily/include/tie-formatting-problem.hh | 18 +++ lily/include/tie.hh | 3 - lily/tie-formatting-problem.cc | 191 +++++++++++++++++++++---- lily/tie-helper.cc | 1 + lily/tie.cc | 14 +- 7 files changed, 201 insertions(+), 38 deletions(-) diff --git a/ChangeLog b/ChangeLog index a1d46bab13..47e2fc6435 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,15 @@ 2005-11-16 Han-Wen Nienhuys + * lily/tie-formatting-problem.cc (find_optimal_tie_configuration): + new function. Search region of 3 positions for best tie. + (score_configuration): new function. + (score_aptitude): new function. + (generate_configuration): new function. + (get_configuration): new function. + (Tie_formatting_problem): new function + + * input/regression/page-top-space.ly: a6 for page-top-space demo. + * stepmake/aclocal.m4: use $(if ) for config-FOOF.make * THANKS: add Eduardo Vieira & Ralph Little diff --git a/input/regression/page-top-space.ly b/input/regression/page-top-space.ly index 4e456773ce..ef5db63dd1 100644 --- a/input/regression/page-top-space.ly +++ b/input/regression/page-top-space.ly @@ -6,6 +6,8 @@ first system can be forced to be uniform." } \version "2.7.13" +#(set-default-paper-size "a6") + \book { \score { diff --git a/lily/include/tie-formatting-problem.hh b/lily/include/tie-formatting-problem.hh index 5adda8bb62..c3cc58926f 100644 --- a/lily/include/tie-formatting-problem.hh +++ b/lily/include/tie-formatting-problem.hh @@ -15,6 +15,8 @@ #include "skyline.hh" #include "lily-proto.hh" +#include +#include struct Tie_details { @@ -23,21 +25,37 @@ struct Tie_details Real staff_space_; Real x_gap_; Real between_length_limit_; + Grob *staff_symbol_referencer_; Tie_details (); void from_grob (Grob *); }; + +typedef map< pair, Tie_configuration *> Tie_configuration_map; + class Tie_formatting_problem { Drul_array< Array > chord_outlines_; + set dot_positions_; + Tie_configuration_map possibilities_; + + Tie_configuration *get_configuration (int position, Direction dir); + Tie_configuration *generate_configuration (int position, Direction dir); + Real score_configuration (Tie_configuration const&); + Real score_aptitude (Tie_configuration const&, int); + Grob *x_refpoint_; + + public: Tie_details details_; public: Tie_formatting_problem (); + ~Tie_formatting_problem (); + Tie_configuration find_optimal_tie_configuration (int p, Direction d); void from_ties (Link_array const &ties); void from_tie (Grob *tie); void from_lv_ties (Link_array const &); diff --git a/lily/include/tie.hh b/lily/include/tie.hh index 23c73a46c1..30be579611 100644 --- a/lily/include/tie.hh +++ b/lily/include/tie.hh @@ -14,7 +14,6 @@ #include "skyline.hh" - class Tie_configuration { @@ -45,10 +44,8 @@ class Ties_configuration { public: Array ties_; - }; - class Tie { public: diff --git a/lily/tie-formatting-problem.cc b/lily/tie-formatting-problem.cc index d02593c28b..36c81fe0a2 100644 --- a/lily/tie-formatting-problem.cc +++ b/lily/tie-formatting-problem.cc @@ -34,13 +34,16 @@ Tie_formatting_problem::get_attachment (Real y) const return attachments; } - - - Tie_formatting_problem::Tie_formatting_problem() { x_refpoint_ = 0; - +} + +Tie_formatting_problem::~Tie_formatting_problem () +{ + for (Tie_configuration_map::const_iterator i (possibilities_.begin ()); + i != possibilities_.end (); i++) + delete (*i).second; } void @@ -73,10 +76,13 @@ Tie_formatting_problem::set_chord_outline (Link_array bounds, { Interval x = dots->extent (x_refpoint_, X_AXIS); Interval y (-0.5, 0.5); - y.translate (Staff_symbol_referencer::get_position (dots)); - y *= staff_space * 0.5; + int p = int (Staff_symbol_referencer::get_position (dots)); + y.translate (p); + + dot_positions_.insert (p); - boxes.push (Box (x, y)); + y *= staff_space * 0.5; + // boxes.push (Box (x, y)); } } @@ -138,27 +144,6 @@ Tie_formatting_problem::set_chord_outline (Link_array bounds, Y_AXIS, -d); } while (flip (&updowndir) != DOWN); - - for (int i = 0; i < bounds.size (); i++) - { - if (!Note_head::has_interface (bounds[i])) - continue; - - - Grob *dots = unsmob_grob (bounds[i]->get_object ("dot")); - if (dots && d == LEFT) - { - Interval x = dots->extent (x_refpoint_, X_AXIS); - Real p = Staff_symbol_referencer::get_position (dots); - - Interval y (-1,1); - y *= (staff_space /4); - y.translate (p * staff_space * .5); - - insert_extent_into_skyline (&chord_outlines_[d], - Box (x,y), Y_AXIS, -d); - } - } } @@ -186,12 +171,13 @@ Tie_formatting_problem::from_ties (Link_array const &ties) return; x_refpoint_ = ties[0]; - details_.from_grob (ties[0]); for (int i = 0; i < ties.size (); i++) { x_refpoint_ = dynamic_cast (ties[i])->get_bound (LEFT)->common_refpoint (x_refpoint_, X_AXIS); x_refpoint_ = dynamic_cast (ties[i])->get_bound (RIGHT)->common_refpoint (x_refpoint_, X_AXIS); } + + details_.from_grob (ties[0]); Direction d = LEFT; do @@ -221,6 +207,9 @@ Tie_formatting_problem::from_lv_ties (Link_array const &lv_ties) for (int i = 0; i < lv_ties.size (); i++) { Item *head = unsmob_item (lv_ties[i]->get_object ("note-head")); + if (!head) + continue; + heads.push (head); } @@ -245,3 +234,147 @@ Tie_formatting_problem::from_lv_ties (Link_array const &lv_ties) chord_outlines_[RIGHT].push (right_entry); } + +Tie_configuration* +Tie_formatting_problem::get_configuration (int pos, Direction dir) +{ + pair key (pos, dir); + Tie_configuration_map::const_iterator f = possibilities_.find (key); + + if (f != possibilities_.end ()) + { + return (*f).second; + } + + + Tie_configuration *conf = generate_configuration (pos,dir); + possibilities_[key] = conf; + return conf; +} + +Tie_configuration* +Tie_formatting_problem::generate_configuration (int pos, Direction dir) +{ + Tie_configuration *conf = new Tie_configuration; + conf->position_ = pos; + conf->dir_ = dir; + Real y = conf->position_ * 0.5 * details_.staff_space_; + + if (dot_positions_.find (pos) != dot_positions_.end ()) + { + conf->delta_y_ += 0.25 * details_.staff_space_; + } + conf->attachment_x_ = get_attachment (y + conf->delta_y_); + + Real h = conf->height (details_); + if (!conf->delta_y_) + { + if (h < 0.5 * details_.staff_space_ + && !Staff_symbol_referencer::on_staffline (details_.staff_symbol_referencer_, pos)) + { + conf->center_tie_vertically (details_); + } + else if (h < 0.5 * details_.staff_space_ + && Staff_symbol_referencer::on_staffline (details_.staff_symbol_referencer_, pos)) + { + conf->delta_y_ += dir * 0.2 * details_.staff_space_; + } + } + + conf->attachment_x_.widen ( - details_.x_gap_); + return conf; +} + +Real +Tie_formatting_problem::score_aptitude (Tie_configuration const &conf, + int tie_position) +{ + Real wrong_direction_offset_penalty_; + Real distance_penalty_factor_; + + wrong_direction_offset_penalty_ = 10; + distance_penalty_factor_ = 5; + + Real penalty = 0.0; + Real curve_y = conf.position_ * details_.staff_space_ * 0.5 + conf.delta_y_; + Real tie_y = tie_position * details_.staff_space_ * 0.5; + if (sign (curve_y - tie_y) != conf.dir_) + penalty += wrong_direction_offset_penalty_; + + penalty += distance_penalty_factor_ * fabs (curve_y - tie_y); + return penalty; +} + + +Real +Tie_formatting_problem::score_configuration (Tie_configuration const &conf) +{ + Real length_penalty_factor = 1.0; + Real min_length = 0.333; + Real staff_line_clearance = 0.1; + Real staff_line_collision_penalty = 5; + + Real penalty = 0.0; + Real length = conf.attachment_x_.length (); + if (length < min_length) + penalty += length_penalty_factor / max (0.01, length); + + Real tip_pos = conf.position_ + conf.delta_y_ / 0.5 * details_.staff_space_; + Real tip_y = tip_pos * details_.staff_space_ * 0.5; + Real height = conf.height (details_); + + 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) < staff_line_clearance + && Staff_symbol_referencer::on_staffline (details_.staff_symbol_referencer_, + int (round_top_pos)) + && Staff_symbol_referencer::staff_radius (details_.staff_symbol_referencer_) > top_y) + { + penalty += staff_line_collision_penalty; + } + + if (fabs (tip_pos - rint (tip_pos)) < staff_line_clearance + && Staff_symbol_referencer::on_staffline (details_.staff_symbol_referencer_, + int (rint (tip_pos)))) + { + penalty += staff_line_collision_penalty; + } + + return penalty; +} + +Tie_configuration +Tie_formatting_problem::find_optimal_tie_configuration (int pos, Direction dir) +{ + Link_array confs; + + int region_size = 3; + for (int i = 0; i < region_size; i ++) + { + confs.push (generate_configuration (pos + i * dir, dir)); + } + + Array scores; + + int best_idx = -1; + Real best_score = 1e6; + for (int i = 0; i < confs.size (); i ++) + { + Real score = 0.0; + score += score_configuration (*confs[i]); + score += score_aptitude (*confs[i], pos); + + if (score < best_score) + { + best_score = score; + best_idx = i; + } + } + + Tie_configuration best = *confs[best_idx]; + for (int i = 0; i < confs.size (); i++) + delete confs[i]; + + return best; +} diff --git a/lily/tie-helper.cc b/lily/tie-helper.cc index 5410a0d942..23915a1d05 100644 --- a/lily/tie-helper.cc +++ b/lily/tie-helper.cc @@ -89,6 +89,7 @@ Tie_configuration::height (Tie_details const &details) const void Tie_details::from_grob (Grob *me) { + staff_symbol_referencer_ = me; staff_space_ = Staff_symbol_referencer::staff_space (me); SCM details = me->get_property ("details"); diff --git a/lily/tie.cc b/lily/tie.cc index b2ae46d966..5c756b7686 100644 --- a/lily/tie.cc +++ b/lily/tie.cc @@ -192,7 +192,7 @@ Tie::get_default_attachments (Spanner *me, Grob *common, Real gap, return attachments; } - + void Tie::get_configuration (Grob *me_grob, Tie_configuration *conf, @@ -406,14 +406,13 @@ Tie::set_default_control_points (Grob *me_grob) common = me->get_bound (LEFT)->common_refpoint (common, X_AXIS); common = me->get_bound (RIGHT)->common_refpoint (common, X_AXIS); - Tie_configuration conf; - int tie_position = (int) Tie::get_position (me); - conf.position_ = tie_position; - Tie_formatting_problem problem; problem.from_tie (me); - get_configuration (me, &conf, problem); + // get_configuration (me, &conf, problem); + int tie_position = (int) Tie::get_position (me); + Tie_configuration conf + = problem.find_optimal_tie_configuration (tie_position, get_grob_direction (me)); set_control_points (me, problem.common_x_refpoint (), conf, problem.details_); } @@ -522,3 +521,6 @@ ADD_INTERFACE (Tie, "direction " "thickness " "x-gap "); + + + -- 2.39.2