X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Ftie-formatting-problem.cc;h=905718469cf0b7e696366219b37c6cee5acf4169;hb=a6a51abfd0195a3cf7d6ea095cf69808852f21ce;hp=6aa5feb3b1b04e139db3829810472c3590e58581;hpb=eeb973b4126dad28bd9f60ab2af772c919401e23;p=lilypond.git diff --git a/lily/tie-formatting-problem.cc b/lily/tie-formatting-problem.cc index 6aa5feb3b1..905718469c 100644 --- a/lily/tie-formatting-problem.cc +++ b/lily/tie-formatting-problem.cc @@ -1,12 +1,24 @@ /* - tie-formatting-problem.cc -- implement Tie_formatting_problem + This file is part of LilyPond, the GNU music typesetter. - source file of the GNU LilyPond music typesetter + Copyright (C) 2005--2015 Han-Wen Nienhuys - (c) 2005--2007 Han-Wen Nienhuys + LilyPond is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + LilyPond is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with LilyPond. If not, see . */ +#include #include "tie-formatting-problem.hh" #include "axis-group-interface.hh" @@ -17,6 +29,7 @@ #include "misc.hh" #include "note-head.hh" #include "rhythmic-head.hh" +#include "semi-tie.hh" #include "spanner.hh" #include "staff-symbol-referencer.hh" #include "stem.hh" @@ -34,7 +47,7 @@ Tie_formatting_problem::print_ties_configuration (Ties_configuration const *ties char const *man_pos = (specifications_[i].has_manual_position_) ? "(M)" : ""; char const *man_dir = (specifications_[i].has_manual_dir_) ? "(M)" : ""; char const *dir = (ties->at (i).dir_ == UP) ? "up" : "dn"; - + printf ("(P%d%s, %s%s) ", ties->at (i).position_, man_pos, dir, man_dir); } printf ("\n"); @@ -43,19 +56,18 @@ Tie_formatting_problem::print_ties_configuration (Ties_configuration const *ties Interval Tie_formatting_problem::get_attachment (Real y, Drul_array columns) const { - Interval attachments (0,0); - Direction d = LEFT; - do + Interval attachments (0, 0); + + for (LEFT_and_RIGHT (d)) { Tuple2 key (columns[d], int (d)); Chord_outline_map::const_iterator i (chord_outlines_.find (key)); if (i == chord_outlines_.end ()) - programming_error ("Cannot find chord outline"); + programming_error ("Cannot find chord outline"); else - attachments[d] = i->second.height (y); + attachments[d] = i->second.height (y); } - while (flip (&d) != LEFT); - + return attachments; } @@ -74,9 +86,9 @@ Tie_formatting_problem::~Tie_formatting_problem () } void -Tie_formatting_problem::set_column_chord_outline (vector bounds, - Direction dir, - int column_rank) +Tie_formatting_problem::set_column_chord_outline (vector bounds, + Direction dir, + int column_rank) { Real staff_space = Staff_symbol_referencer::staff_space (bounds[0]); @@ -87,15 +99,15 @@ Tie_formatting_problem::set_column_chord_outline (vector bounds, for (vsize i = 0; i < bounds.size (); i++) { Grob *head = bounds[i]; - if (!Note_head::has_interface (head)) - continue; - + if (!has_interface (head)) + continue; + if (!stem) - stem = unsmob_grob (head->get_object ("stem")); - + stem = unsmob (head->get_object ("stem")); + Real p = Staff_symbol_referencer::get_position (head); - Interval y ((p-1) * 0.5 * staff_space, - (p+1) * 0.5 * staff_space); + Interval y ((p - 1) * 0.5 * staff_space, + (p + 1) * 0.5 * staff_space); Interval x = head->extent (x_refpoint_, X_AXIS); head_boxes.push_back (Box (x, y)); @@ -103,21 +115,21 @@ Tie_formatting_problem::set_column_chord_outline (vector bounds, Grob *dots = Rhythmic_head::get_dots (head); if (dir == LEFT && dots) - { - Interval x = dots->extent (x_refpoint_, X_AXIS); - int p = int (Staff_symbol_referencer::get_position (dots)); - - /* - TODO: shouldn't this use column-rank dependent key? - */ - dot_positions_.insert (p); - dot_x_.unite (x); - - Interval y (dots->extent (dots, Y_AXIS)); - y.translate (p * staff_space * 0.5); - - boxes.push_back (Box (x, y)); - } + { + Interval x = dots->extent (x_refpoint_, X_AXIS); + int p = int (Staff_symbol_referencer::get_position (dots)); + + /* + TODO: shouldn't this use column-rank dependent key? + */ + dot_positions_.insert (p); + dot_x_.unite (x); + + Interval y (dots->extent (dots, Y_AXIS)); + y.translate (p * staff_space * 0.5); + + boxes.push_back (Box (x, y)); + } } Tuple2 key (column_rank, int (dir)); @@ -125,117 +137,119 @@ Tie_formatting_problem::set_column_chord_outline (vector bounds, if (stem) { if (Stem::is_normal_stem (stem)) - { - Interval x; - x.add_point (stem->relative_coordinate (x_refpoint_, X_AXIS)); - x.widen (staff_space / 20); // ugh. - Interval y; - - Real stem_end_position = 0.0; - if (Stem::is_cross_staff (stem)) - stem_end_position = get_grob_direction (stem) * infinity_f; - else - { - if (use_horizontal_spacing_ || !Stem::get_beam (stem)) - stem_end_position = Stem::stem_end_position (stem) * staff_space * .5; - else - stem_end_position = Stem::note_head_positions (stem)[get_grob_direction (stem)] - * staff_space * .5; - } - - y.add_point (stem_end_position); - - Direction stemdir = get_grob_direction (stem); - y.add_point (Stem::head_positions (stem)[-stemdir] - * staff_space * .5); - - /* - add extents of stem. - */ - boxes.push_back (Box (x, y)); - - stem_extents_[key].unite (Box (x, y)); - - if (dir == LEFT) - { - Box flag_box = Stem::get_translated_flag (stem).extent_box (); - flag_box.translate ( Offset (x[RIGHT], X_AXIS)); - boxes.push_back (flag_box); - } - } + { + Interval x; + x.add_point (stem->relative_coordinate (x_refpoint_, X_AXIS)); + x.widen (staff_space / 20); // ugh. + Interval y; + + Real stem_end_position = 0.0; + if (Stem::is_cross_staff (stem)) + stem_end_position = get_grob_direction (stem) * infinity_f; + else + { + if (use_horizontal_spacing_ || !Stem::get_beam (stem)) + stem_end_position = stem->extent (stem, Y_AXIS)[get_grob_direction (stem)]; + else + // May want to change this to the stem's pure height... + stem_end_position = Stem::head_positions (stem)[get_grob_direction (stem)] + * staff_space * .5; + } + + y.add_point (stem_end_position); + + Direction stemdir = get_grob_direction (stem); + y.add_point (Stem::head_positions (stem)[-stemdir] + * staff_space * .5); + + /* + add extents of stem. + */ + boxes.push_back (Box (x, y)); + + stem_extents_[key].unite (Box (x, y)); + + if (dir == LEFT) + { + Grob *flag = Stem::flag (stem); + if (flag) + { + Grob *commony = stem->common_refpoint (flag, Y_AXIS); + boxes.push_back (Box (flag->extent (x_refpoint_, X_AXIS), + flag->extent (commony, Y_AXIS))); + } + } + } else - { - Grob *head = Stem::support_head (stem); - - /* - In case of invisible stem, don't pass x-center of heads. - */ - Real x_center = head->extent (x_refpoint_, X_AXIS).center (); - Interval x_ext; - x_ext[-dir] = x_center; - x_ext[dir] = infinity_f * dir; - Interval y_ext; - for (vsize j = 0; j < head_boxes.size (); j++) - y_ext.unite (head_boxes[j][Y_AXIS]); - - boxes.push_back (Box (x_ext, y_ext)); - } + { + Grob *head = Stem::support_head (stem); + + /* + In case of invisible stem, don't pass x-center of heads. + */ + Real x_center = head->extent (x_refpoint_, X_AXIS).center (); + Interval x_ext; + x_ext[-dir] = x_center; + x_ext[dir] = infinity_f * dir; + Interval y_ext; + for (vsize j = 0; j < head_boxes.size (); j++) + y_ext.unite (head_boxes[j][Y_AXIS]); + + boxes.push_back (Box (x_ext, y_ext)); + } extract_grob_set (stem, "note-heads", heads); - for (vsize i = 0; i < heads.size (); i ++) - { - if (find (bounds.begin (), bounds.end (), dynamic_cast (heads[i])) == bounds.end ()) - { - /* - other untied notes in the same chord. - */ - - Interval y = Staff_symbol_referencer::extent_in_staff (heads[i]); - Interval x = heads[i]->extent (x_refpoint_, X_AXIS); - boxes.push_back (Box (x, y)); - } - - Grob *acc = unsmob_grob (heads[i]->get_object ("accidental-grob")); - if (acc) - acc->get_property ("stencil"); /* trigger tie-related suicide */ - - if (acc && acc->is_live () && dir == RIGHT) - { - boxes.push_back (Box (acc->extent (x_refpoint_, X_AXIS), - Staff_symbol_referencer::extent_in_staff (acc))); - } - - head_positions_[column_rank].add_point (int (Staff_symbol_referencer::get_position (heads[i]))); - } - + for (vsize i = 0; i < heads.size (); i++) + { + if (find (bounds.begin (), bounds.end (), dynamic_cast (heads[i])) == bounds.end ()) + { + /* + other untied notes in the same chord. + */ + + Interval y = Staff_symbol_referencer::extent_in_staff (heads[i]); + Interval x = heads[i]->extent (x_refpoint_, X_AXIS); + boxes.push_back (Box (x, y)); + } + + Grob *acc = unsmob (heads[i]->get_object ("accidental-grob")); + if (acc) + acc->get_property ("after-line-breaking"); /* trigger tie-related suicide */ + + if (acc && acc->is_live () && dir == RIGHT) + { + boxes.push_back (Box (acc->extent (x_refpoint_, X_AXIS), + Staff_symbol_referencer::extent_in_staff (acc))); + } + + head_positions_[column_rank].add_point (int (Staff_symbol_referencer::get_position (heads[i]))); + } + } - - Direction updowndir = DOWN; - do + + for (DOWN_and_UP (updowndir)) { Interval x; Interval y; if (head_boxes.size ()) - { - Box b = boundary (head_boxes, updowndir, 0); - x = b[X_AXIS]; - x[-dir] = b[X_AXIS].linear_combination (-dir / 2); - y[-updowndir] = b[Y_AXIS][updowndir]; - y[updowndir] = updowndir * infinity_f; - } + { + Box b = boundary (head_boxes, updowndir, 0); + x = b[X_AXIS]; + x[-dir] = b[X_AXIS].linear_combination (-dir / 2); + y[-updowndir] = b[Y_AXIS][updowndir]; + y[updowndir] = updowndir * infinity_f; + } if (!x.is_empty ()) - boxes.push_back (Box (x, y)); + boxes.push_back (Box (x, y)); } - while (flip (&updowndir) != DOWN); - /* todo: the horizon_padding is somewhat arbitrary */ - chord_outlines_[key] = Skyline (boxes, details_.skyline_padding_, Y_AXIS, -dir); + chord_outlines_[key] = Skyline (boxes, Y_AXIS, -dir).padded (details_.skyline_padding_); if (bounds[0]->break_status_dir ()) { Interval iv (Axis_group_interface::staff_extent (bounds[0], x_refpoint_, X_AXIS, y_refpoint_, Y_AXIS)); if (iv.is_empty ()) - iv.add_point (bounds[0]->relative_coordinate (x_refpoint_, X_AXIS)); + iv.add_point (bounds[0]->relative_coordinate (x_refpoint_, X_AXIS)); chord_outlines_[key].set_minimum_height (iv[-dir]); } @@ -243,10 +257,10 @@ Tie_formatting_problem::set_column_chord_outline (vector bounds, { Interval x; for (vsize j = 0; j < head_boxes.size (); j++) - { - x.unite (head_boxes[j][X_AXIS]); - } - + { + x.unite (head_boxes[j][X_AXIS]); + } + chord_outlines_[key].set_minimum_height (x[dir]); } @@ -258,8 +272,8 @@ Tie_formatting_problem::set_column_chord_outline (vector bounds, } void -Tie_formatting_problem::set_chord_outline (vector bounds, - Direction dir) +Tie_formatting_problem::set_chord_outline (vector bounds, + Direction dir) { vector ranks; @@ -271,23 +285,21 @@ Tie_formatting_problem::set_chord_outline (vector bounds, for (vsize i = 0; i < ranks.size (); i++) { - vector col_items; - for (vsize j = 0; j < bounds.size (); j ++) - { - if (bounds[j]->get_column ()->get_rank () == ranks[i]) - col_items.push_back (bounds[j]); - } + vector col_items; + for (vsize j = 0; j < bounds.size (); j++) + { + if (bounds[j]->get_column ()->get_rank () == ranks[i]) + col_items.push_back (bounds[j]); + } set_column_chord_outline (col_items, dir, ranks[i]); } } - - void Tie_formatting_problem::from_tie (Grob *tie) { - vector ties; + vector ties; ties.push_back (tie); from_ties (ties); @@ -301,92 +313,91 @@ Tie_formatting_problem::common_x_refpoint () const } void -Tie_formatting_problem::from_ties (vector const &ties) +Tie_formatting_problem::from_ties (vector const &ties) { if (ties.empty ()) return; - + x_refpoint_ = ties[0]; y_refpoint_ = ties[0]; for (vsize i = 0; i < ties.size (); i++) { - Spanner *tie = dynamic_cast (ties[i]); + Spanner *tie = dynamic_cast (ties[i]); Item *l = tie->get_bound (LEFT); Item *r = tie->get_bound (RIGHT); - x_refpoint_ = l->common_refpoint (x_refpoint_, X_AXIS); + x_refpoint_ = l->common_refpoint (x_refpoint_, X_AXIS); x_refpoint_ = r->common_refpoint (x_refpoint_, X_AXIS); if (!l->break_status_dir ()) - y_refpoint_ = l->common_refpoint (y_refpoint_, Y_AXIS); + y_refpoint_ = l->common_refpoint (y_refpoint_, Y_AXIS); if (!r->break_status_dir ()) - y_refpoint_ = r->common_refpoint (y_refpoint_, Y_AXIS); + y_refpoint_ = r->common_refpoint (y_refpoint_, Y_AXIS); } details_.from_grob (ties[0]); - - Direction d = LEFT; - do + + for (LEFT_and_RIGHT (d)) { - vector bounds; - + vector bounds; + for (vsize i = 0; i < ties.size (); i++) - { - Item *it = dynamic_cast (ties[i])->get_bound (d); - if (it->break_status_dir ()) - it = it->get_column (); - - bounds.push_back (it); - } - + { + Spanner *tie = dynamic_cast (ties[i]); + Item *it = tie->get_bound (d); + if (it->break_status_dir ()) + it = it->get_column (); + + bounds.push_back (it); + } + set_chord_outline (bounds, d); } - while (flip (&d) != LEFT); - for (vsize i = 0; i < ties.size (); i++) { + Spanner *tie = dynamic_cast (ties[i]); Tie_specification spec; - spec.from_grob (ties[i]); - - do - { - spec.note_head_drul_[d] = Tie::head (ties[i], d); - spec.column_ranks_[d] = Tie::get_column_rank (ties[i], d); - } - while (flip (&d) != LEFT); + spec.from_grob (tie); + + for (LEFT_and_RIGHT (d)) + { + spec.note_head_drul_[d] = Tie::head (tie, d); + spec.column_ranks_[d] = Tie::get_column_rank (tie, d); + } specifications_.push_back (spec); } } void -Tie_formatting_problem::from_semi_ties (vector const &semi_ties, Direction head_dir) +Tie_formatting_problem::from_semi_ties (vector const &semi_ties, Direction head_dir) { if (semi_ties.empty ()) return; - use_horizontal_spacing_ = false; + use_horizontal_spacing_ = false; details_.from_grob (semi_ties[0]); - vector heads; + vector heads; int column_rank = -1; for (vsize i = 0; i < semi_ties.size (); i++) { + Item *semi_tie = dynamic_cast (semi_ties[i]); Tie_specification spec; - Item *head = unsmob_item (semi_ties[i]->get_object ("note-head")); - + Item *head = Semi_tie::head (semi_tie); + if (!head) - programming_error ("LV tie without head?!"); + programming_error ("LV tie without head?!"); if (head) - { - spec.position_ = int (Staff_symbol_referencer::get_position (head)); - } + { + spec.position_ = int (Staff_symbol_referencer::get_position (head)); + } + + spec.from_grob (semi_tie); - spec.from_grob (semi_ties[i]); - spec.note_head_drul_[head_dir] = head; - column_rank = Tie::get_column_rank (semi_ties[i], head_dir); + column_rank = Semi_tie::get_column_rank (semi_tie); spec.column_ranks_ = Drul_array (column_rank, column_rank); heads.push_back (head); specifications_.push_back (spec); @@ -397,13 +408,13 @@ Tie_formatting_problem::from_semi_ties (vector const &semi_ties, Directio for (vsize i = 0; i < semi_ties.size (); i++) { - x_refpoint_ = semi_ties[i]->common_refpoint (x_refpoint_, X_AXIS); - y_refpoint_ = semi_ties[i]->common_refpoint (y_refpoint_, Y_AXIS); + x_refpoint_ = semi_ties[i]->common_refpoint (x_refpoint_, X_AXIS); + y_refpoint_ = semi_ties[i]->common_refpoint (y_refpoint_, Y_AXIS); } for (vsize i = 0; i < heads.size (); i++) { - x_refpoint_ = heads[i]->common_refpoint (x_refpoint_, X_AXIS); - y_refpoint_ = heads[i]->common_refpoint (y_refpoint_, Y_AXIS) ; + x_refpoint_ = heads[i]->common_refpoint (x_refpoint_, X_AXIS); + y_refpoint_ = heads[i]->common_refpoint (y_refpoint_, Y_AXIS); } set_chord_outline (heads, head_dir); @@ -416,48 +427,47 @@ Tie_formatting_problem::from_semi_ties (vector const &semi_ties, Directio chord_outlines_[open_key].set_minimum_height (extremal - head_dir * 1.5); } - Tie_specification Tie_formatting_problem::get_tie_specification (int i) const { return specifications_[i]; } - /* - Return configuration, create it if necessary. + Return configuration, create it if necessary. */ -Tie_configuration* +Tie_configuration * Tie_formatting_problem::get_configuration (int pos, Direction dir, Drul_array columns, - bool tune_dy) const + bool tune_dy) const { - int key_components[] = { + int key_components[] + = + { pos, dir, columns[LEFT], columns[RIGHT] }; - Tuple key (key_components); - + Tuple key (key_components); + Tie_configuration_map::const_iterator f = possibilities_.find (key); if (f != possibilities_.end ()) { return (*f).second; } - Tie_configuration *conf = generate_configuration (pos, dir, columns, tune_dy); - ((Tie_formatting_problem*) this)->possibilities_[key] = conf; + ((Tie_formatting_problem *) this)->possibilities_[key] = conf; return conf; } -Tie_configuration* +Tie_configuration * Tie_formatting_problem::generate_configuration (int pos, Direction dir, - Drul_array columns, bool y_tune) const + Drul_array columns, bool y_tune) const { Tie_configuration *conf = new Tie_configuration; conf->position_ = pos; conf->dir_ = dir; - + conf->column_ranks_ = columns; - + Real y = conf->position_ * 0.5 * details_.staff_space_; if (dot_positions_.find (pos) != dot_positions_.end ()) @@ -465,79 +475,82 @@ Tie_formatting_problem::generate_configuration (int pos, Direction dir, conf->delta_y_ += dir * 0.25 * details_.staff_space_; y_tune = false; } - + if (y_tune && max (fabs (get_head_extent (columns[LEFT], LEFT, Y_AXIS)[dir] - y), - fabs (get_head_extent (columns[RIGHT], RIGHT, Y_AXIS)[dir] - y)) < 0.25 + fabs (get_head_extent (columns[RIGHT], RIGHT, Y_AXIS)[dir] - y)) < 0.25 && !Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_, pos)) { - conf->delta_y_ = - (get_head_extent (columns[LEFT], LEFT, Y_AXIS)[dir] - y) - + dir * details_.outer_tie_vertical_gap_; + conf->delta_y_ + = (get_head_extent (columns[LEFT], LEFT, Y_AXIS)[dir] - y) + + dir * details_.outer_tie_vertical_gap_; } if (y_tune) { conf->attachment_x_ = get_attachment (y + conf->delta_y_, conf->column_ranks_); - Real h = conf->height (details_); - + Real h = conf->height (details_); + /* - TODO: + TODO: + + - should make sliding criterion, should flatten ties if - - should make sliding criterion, should flatten ties if + - they're just the wrong (ie. touching line at top & bottom) + size. - - they're just the wrong (ie. touching line at top & bottom) - size. - */ + Interval staff_span + = Staff_symbol_referencer::staff_span (details_.staff_symbol_referencer_); + staff_span.widen (-1); + bool const within_staff = staff_span.contains (pos); if (head_positions_slice (columns[LEFT]).contains (pos) - || head_positions_slice (columns[RIGHT]).contains (pos) - || abs (pos) < 2 * Staff_symbol_referencer::staff_radius (details_.staff_symbol_referencer_)) - { - if (h < details_.intra_space_threshold_ * 0.5 * details_.staff_space_) - { - if (!Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_, pos) - && abs (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 * - details_.tip_staff_line_clearance_ * 0.5 * details_.staff_space_; - } - } - else - { - Real top_y = y + conf->delta_y_ + conf->dir_ * h; - Real top_pos = top_y / (0.5*details_.staff_space_); - int round_pos = int (my_round (top_pos)); - - /* TODO: should use other variable? */ - 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)) - { - Real new_y = (round_pos + clearance * conf->dir_) * 0.5 * details_.staff_space_; - conf->delta_y_ = (new_y - top_y); - } - } - } - } + || head_positions_slice (columns[RIGHT]).contains (pos) + || within_staff) + { + if (h < details_.intra_space_threshold_ * 0.5 * details_.staff_space_) + { + if (Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_, pos)) + { + conf->delta_y_ += dir * + details_.tip_staff_line_clearance_ * 0.5 * details_.staff_space_; + } + else if (within_staff) + { + conf->center_tie_vertically (details_); + } + } + else + { + Real top_y = y + conf->delta_y_ + conf->dir_ * h; + Real top_pos = top_y / (0.5 * details_.staff_space_); + int round_pos = int (my_round (top_pos)); + + /* TODO: should use other variable? */ + 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)) + { + Real new_y = (round_pos + clearance * conf->dir_) * 0.5 * details_.staff_space_; + conf->delta_y_ = (new_y - top_y); + } + } + } + } conf->attachment_x_ = get_attachment (y + conf->delta_y_, conf->column_ranks_); if (conf->height (details_) < details_.intra_space_threshold_ * 0.5 * details_.staff_space_) { /* - This is less sensible for long ties, since those are more - horizontal. + This is less sensible for long ties, since those are more + horizontal. */ Interval close_by = get_attachment (y - + conf->delta_y_ - + (dir * details_.intra_space_threshold_ * 0.25 - * details_.staff_space_), - conf->column_ranks_); - + + conf->delta_y_ + + (dir * details_.intra_space_threshold_ * 0.25 + * details_.staff_space_), + conf->column_ranks_); + conf->attachment_x_.intersect (close_by); } @@ -546,26 +559,24 @@ Tie_formatting_problem::generate_configuration (int pos, Direction dir, if (conf->column_span_length ()) { /* - avoid the stems that we attach to as well. We don't do this - for semities (span length = 0) + avoid the stems that we attach to as well. We don't do this + for semities (span length = 0) - It would be better to check D against HEAD-DIRECTION if - applicable. + It would be better to check D against HEAD-DIRECTION if + applicable. */ - Direction d = LEFT; - do - { - Real y = conf->position_ * details_.staff_space_ * 0.5 + conf->delta_y_; - if (get_stem_extent (conf->column_ranks_[d], d, X_AXIS).is_empty () - || !get_stem_extent (conf->column_ranks_[d], d, Y_AXIS).contains (y)) - continue; - - conf->attachment_x_[d] = - d * min (d * conf->attachment_x_[d], - d * (get_stem_extent (conf->column_ranks_[d], d, X_AXIS)[-d] - d * details_.stem_gap_)); - } - while (flip (&d) != LEFT); - } + for (LEFT_and_RIGHT (d)) + { + Real y = conf->position_ * details_.staff_space_ * 0.5 + conf->delta_y_; + if (get_stem_extent (conf->column_ranks_[d], d, X_AXIS).is_empty () + || !get_stem_extent (conf->column_ranks_[d], d, Y_AXIS).contains (y)) + continue; + + conf->attachment_x_[d] + = d * min (d * conf->attachment_x_[d], + d * (get_stem_extent (conf->column_ranks_[d], d, X_AXIS)[-d] - d * details_.stem_gap_)); + } + } return conf; } @@ -594,19 +605,19 @@ Tie_formatting_problem::get_stem_extent (int col, Direction d, Axis a) const */ Real Tie_formatting_problem::score_aptitude (Tie_configuration *conf, - Tie_specification const &spec, - Ties_configuration *ties_conf, int tie_idx) const + Tie_specification const &spec, + Ties_configuration *ties_conf, int tie_idx) const { Real penalty = 0.0; Real curve_y = conf->position_ * details_.staff_space_ * 0.5 + conf->delta_y_; Real tie_y = spec.position_ * details_.staff_space_ * 0.5; if (sign (curve_y - tie_y) != conf->dir_) { - Real p = details_.wrong_direction_offset_penalty_; + Real p = details_.wrong_direction_offset_penalty_; if (ties_conf) - ties_conf->add_tie_score (p, tie_idx, "wrong dir"); + ties_conf->add_tie_score (p, tie_idx, "wrong dir"); else - penalty += p; + penalty += p; } { @@ -615,81 +626,73 @@ Tie_formatting_problem::score_aptitude (Tie_configuration *conf, if (ties_conf) ties_conf->add_tie_score (p, tie_idx, "vdist"); else - penalty += p; + penalty += p; } - - Direction d = LEFT; - do + + for (LEFT_and_RIGHT (d)) { if (!spec.note_head_drul_[d]) - continue; - + continue; + Interval head_x = spec.note_head_drul_[d]->extent (x_refpoint_, X_AXIS); Real dist = head_x.distance (conf->attachment_x_[d]); - /* - TODO: flatten with log or sqrt. + TODO: flatten with log or sqrt. */ Real p = details_.horizontal_distance_penalty_factor_ - * convex_amplifier (1.25, 1.0, dist); + * convex_amplifier (1.25, 1.0, dist); if (ties_conf) - ties_conf->add_tie_score (p, tie_idx, - (d == LEFT) ? "lhdist" : "rhdist"); + ties_conf->add_tie_score (p, tie_idx, + (d == LEFT) ? "lhdist" : "rhdist"); else - penalty += p; + penalty += p; } - while (flip (&d) != LEFT); if (ties_conf && ties_conf->size () == 1) { - Direction d = LEFT; - Drul_array stems (0, 0); - do - { - if (!spec.note_head_drul_[d]) - continue; - - Grob *stem = unsmob_grob (spec.note_head_drul_[d]->get_object ("stem")); - if (stem - && Stem::is_normal_stem (stem)) - stems[d] = stem; - } - while (flip (&d) != LEFT); + Drul_array stems (0, 0); + for (LEFT_and_RIGHT (d)) + { + if (!spec.note_head_drul_[d]) + continue; + + Grob *stem = unsmob (spec.note_head_drul_[d]->get_object ("stem")); + if (stem + && Stem::is_normal_stem (stem)) + stems[d] = stem; + } bool tie_stem_dir_ok = true; bool tie_position_dir_ok = true; if (stems[LEFT] && !stems[RIGHT]) - tie_stem_dir_ok = conf->dir_ != get_grob_direction (stems[LEFT]); + tie_stem_dir_ok = conf->dir_ != get_grob_direction (stems[LEFT]); else if (!stems[LEFT] && stems[RIGHT]) - tie_stem_dir_ok = conf->dir_ != get_grob_direction (stems[RIGHT]); + tie_stem_dir_ok = conf->dir_ != get_grob_direction (stems[RIGHT]); else if (stems[LEFT] && stems[RIGHT] - && get_grob_direction (stems[LEFT]) == get_grob_direction (stems[RIGHT])) - tie_stem_dir_ok = conf->dir_ != get_grob_direction (stems[LEFT]); + && get_grob_direction (stems[LEFT]) == get_grob_direction (stems[RIGHT])) + tie_stem_dir_ok = conf->dir_ != get_grob_direction (stems[LEFT]); else if (spec.position_) - tie_position_dir_ok = conf->dir_ == sign (spec.position_); + tie_position_dir_ok = conf->dir_ == sign (spec.position_); if (!tie_stem_dir_ok) - ties_conf->add_score (details_.same_dir_as_stem_penalty_, "tie/stem dir"); + ties_conf->add_score (details_.same_dir_as_stem_penalty_, "tie/stem dir"); if (!tie_position_dir_ok) - ties_conf->add_score (details_.same_dir_as_stem_penalty_, "tie/pos dir"); + ties_conf->add_score (details_.same_dir_as_stem_penalty_, "tie/pos dir"); } - while (flip (&d) != LEFT); - return penalty; } - Slice Tie_formatting_problem::head_positions_slice (int rank) const { Position_extent_map::const_iterator i (head_positions_.find (rank)); if (i != head_positions_.end ()) { - return (*i).second; + return (*i).second; } Slice empty; return empty; @@ -704,69 +707,72 @@ Tie_formatting_problem::score_configuration (Tie_configuration *conf) const { if (conf->scored_) { - return ; + return; } - + Real length = conf->attachment_x_.length (); + Real length_penalty + = peak_around (0.33 * details_.min_length_, details_.min_length_, length); conf->add_score (details_.min_length_penalty_factor_ - * peak_around (0.33 * details_.min_length_, details_.min_length_, length), - "minlength"); - + * length_penalty, "minlength"); + 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 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); + Interval staff_span + = Staff_symbol_referencer::staff_span (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) + int (round_top_pos)) + && staff_span[UP] * 0.5 > top_y) { - conf->add_score ( - 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)), - "line center"); + conf->add_score (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)), + "line center"); } int rounded_tip_pos = int (rint (tip_pos)); + staff_span.widen (-1); if (Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_, rounded_tip_pos) && (head_positions_slice (conf->column_ranks_[LEFT]).contains (rounded_tip_pos) - || head_positions_slice (conf->column_ranks_[RIGHT]).contains (rounded_tip_pos) - || abs (rounded_tip_pos) < 2 * Staff_symbol_referencer::staff_radius (details_.staff_symbol_referencer_)) - ) + || head_positions_slice (conf->column_ranks_[RIGHT]).contains (rounded_tip_pos) + || staff_span.contains (rounded_tip_pos)) + ) { conf->add_score (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))), - "tipline"); + * peak_around (0.1 * details_.tip_staff_line_clearance_, + details_.tip_staff_line_clearance_, + fabs (tip_pos - rint (tip_pos))), + "tipline"); } if (!dot_x_.is_empty ()) { /* use left edge? */ Real x = dot_x_.center (); - + Bezier b = conf->get_transformed_bezier (details_); if (b.control_point_extent (X_AXIS).contains (x)) - { - Real y = b.get_other_coordinate (X_AXIS, x); - - for (set::const_iterator i (dot_positions_.begin ()); - i != dot_positions_.end (); i ++) - { - int dot_pos = (*i); - conf->add_score (details_.dot_collision_penalty_ - * peak_around (.1 * details_.dot_collision_clearance_, - details_.dot_collision_clearance_, - fabs (dot_pos * details_.staff_space_ * 0.5 - y)), - "dot collision"); - } - } + { + Real y = b.get_other_coordinate (X_AXIS, x); + + for (set::const_iterator i (dot_positions_.begin ()); + i != dot_positions_.end (); i++) + { + int dot_pos = (*i); + conf->add_score (details_.dot_collision_penalty_ + * peak_around (.1 * details_.dot_collision_clearance_, + details_.dot_collision_clearance_, + fabs (dot_pos * details_.staff_space_ * 0.5 - y)), + "dot collision"); + } + } } conf->scored_ = true; @@ -775,7 +781,7 @@ Tie_formatting_problem::score_configuration (Tie_configuration *conf) const void Tie_formatting_problem::score_ties_aptitude (Ties_configuration *ties) const { - if (ties->size () != specifications_.size ()) + if (ties->size () != specifications_.size ()) { programming_error ("Huh? Mismatch between sizes."); return; @@ -783,7 +789,7 @@ Tie_formatting_problem::score_ties_aptitude (Ties_configuration *ties) const for (vsize i = 0; i < ties->size (); i++) score_aptitude (&ties->at (i), specifications_[i], - ties, i); + ties, i); } void @@ -791,7 +797,7 @@ Tie_formatting_problem::score_ties (Ties_configuration *ties) const { if (ties->scored_) return; - + score_ties_configuration (ties); score_ties_aptitude (ties); ties->scored_ = true; @@ -805,33 +811,33 @@ Tie_formatting_problem::score_ties_configuration (Ties_configuration *ties) cons score_configuration (&ties->at (i)); ties->add_tie_score (ties->at (i).score (), i, "conf"); } - + Real last_edge = 0.0; Real last_center = 0.0; for (vsize i = 0; i < ties->size (); i++) { Bezier b (ties->at (i).get_transformed_bezier (details_)); - + Real center = b.curve_point (0.5)[Y_AXIS]; Real edge = b.curve_point (0.0)[Y_AXIS]; - + if (i) - { - if (edge <= last_edge) - ties->add_score (details_.tie_column_monotonicity_penalty_, "monoton edge"); - if (center <= last_center) - ties->add_score (details_.tie_column_monotonicity_penalty_, "monoton cent"); - - ties->add_score (details_.tie_tie_collision_penalty_ * - peak_around (0.1 * details_.tie_tie_collision_distance_, - details_.tie_tie_collision_distance_, - fabs (center - last_center)), - "tietie center"); - ties->add_score (details_.tie_tie_collision_penalty_ * - peak_around (0.1 * details_.tie_tie_collision_distance_, - details_.tie_tie_collision_distance_, - fabs (edge - last_edge)), "tietie edge"); - } + { + if (edge <= last_edge) + ties->add_score (details_.tie_column_monotonicity_penalty_, "monoton edge"); + if (center <= last_center) + ties->add_score (details_.tie_column_monotonicity_penalty_, "monoton cent"); + + ties->add_score (details_.tie_tie_collision_penalty_ * + peak_around (0.1 * details_.tie_tie_collision_distance_, + details_.tie_tie_collision_distance_, + fabs (center - last_center)), + "tietie center"); + ties->add_score (details_.tie_tie_collision_penalty_ * + peak_around (0.1 * details_.tie_tie_collision_distance_, + details_.tie_tie_collision_distance_, + fabs (edge - last_edge)), "tietie edge"); + } last_edge = edge; last_center = center; @@ -840,20 +846,21 @@ Tie_formatting_problem::score_ties_configuration (Ties_configuration *ties) cons if (ties->size () > 1) { ties->add_score (details_.outer_tie_length_symmetry_penalty_factor_ - * fabs (ties->at (0).attachment_x_.length () - ties->back ().attachment_x_.length ()), - "length symm"); - + * fabs (ties->at (0).attachment_x_.length () - ties->back ().attachment_x_.length ()), + "length symm"); + ties->add_score (details_.outer_tie_vertical_distance_symmetry_penalty_factor_ - * fabs (fabs (specifications_[0].position_ * 0.5 * details_.staff_space_ - - (ties->at (0).position_ * 0.5 * details_.staff_space_ - + ties->at (0).delta_y_)) - - - fabs (specifications_.back ().position_ * 0.5 * details_.staff_space_ - - (ties->back ().position_ * 0.5 * details_.staff_space_ - + ties->back ().delta_y_))), - "pos symmetry"); + * fabs (fabs (specifications_[0].position_ * 0.5 * details_.staff_space_ + - (ties->at (0).position_ * 0.5 * details_.staff_space_ + + ties->at (0).delta_y_)) + - + fabs (specifications_.back ().position_ * 0.5 * details_.staff_space_ + - (ties->back ().position_ * 0.5 * details_.staff_space_ + + ties->back ().delta_y_))), + "pos symmetry"); } } + /* Generate with correct X-attachments and beziers, copying delta_y_ from TIES_CONFIG if necessary. @@ -864,41 +871,41 @@ Tie_formatting_problem::generate_ties_configuration (Ties_configuration const &t Ties_configuration copy; for (vsize i = 0; i < ties_config.size (); i++) { - Tie_configuration * ptr = get_configuration (ties_config[i].position_, ties_config[i].dir_, - ties_config[i].column_ranks_, - !specifications_[i].has_manual_delta_y_); + Tie_configuration *ptr = get_configuration (ties_config[i].position_, ties_config[i].dir_, + ties_config[i].column_ranks_, + !specifications_[i].has_manual_delta_y_); if (specifications_[i].has_manual_delta_y_) - { - ptr->delta_y_ - = (specifications_[i].manual_position_ - ties_config[i].position_) - * 0.5 * details_.staff_space_; - } + { + ptr->delta_y_ + = (specifications_[i].manual_position_ - ties_config[i].position_) + * 0.5 * details_.staff_space_; + } copy.push_back (*ptr); } - + return copy; } Ties_configuration -Tie_formatting_problem::generate_base_chord_configuration () +Tie_formatting_problem::generate_base_chord_configuration () { Ties_configuration ties_config; - for (vsize i = 0; i < specifications_.size (); i ++) + for (vsize i = 0; i < specifications_.size (); i++) { Tie_configuration conf; if (specifications_[i].has_manual_dir_) - conf.dir_ = specifications_[i].manual_dir_; + conf.dir_ = specifications_[i].manual_dir_; if (specifications_[i].has_manual_position_) - { - conf.position_ = (int) my_round (specifications_[i].manual_position_); - if (specifications_[i].has_manual_delta_y_) - conf.delta_y_ = (specifications_[i].manual_position_ - conf.position_) - * 0.5 * details_.staff_space_; - } + { + conf.position_ = (int) my_round (specifications_[i].manual_position_); + if (specifications_[i].has_manual_delta_y_) + conf.delta_y_ = (specifications_[i].manual_position_ - conf.position_) + * 0.5 * details_.staff_space_; + } else - { - conf.position_ = specifications_[i].position_; - } + { + conf.position_ = specifications_[i].position_; + } conf.column_ranks_ = specifications_[i].column_ranks_; ties_config.push_back (conf); @@ -910,16 +917,16 @@ Tie_formatting_problem::generate_base_chord_configuration () ties_config[i].position_ += ties_config[i].dir_; ties_config = generate_ties_configuration (ties_config); - + return ties_config; } Ties_configuration Tie_formatting_problem::find_best_variation (Ties_configuration const &base, - vector const &vars) + vector const &vars) { Ties_configuration best = base; - + /* This simply is 1-opt: we have K substitions, and we try applying exactly every one for each. @@ -927,21 +934,20 @@ Tie_formatting_problem::find_best_variation (Ties_configuration const &base, for (vsize i = 0; i < vars.size (); i++) { Ties_configuration variant (base); - variant[vars[i].index_] = *vars[i].suggestion_; + for (vsize j = 0; j < vars[i].index_suggestion_pairs_.size (); j++) + variant[vars[i].index_suggestion_pairs_[j].first] = *vars[i].index_suggestion_pairs_[j].second; variant.reset_score (); score_ties (&variant); - + if (variant.score () < best.score ()) - { - best = variant; - } + { + best = variant; + } } return best; } - - Ties_configuration Tie_formatting_problem::generate_optimal_configuration () @@ -949,7 +955,7 @@ Tie_formatting_problem::generate_optimal_configuration () Ties_configuration base = generate_base_chord_configuration (); score_ties (&base); - vector vars; + vector vars; if (specifications_.size () > 1) vars = generate_collision_variations (base); else @@ -969,18 +975,18 @@ void Tie_formatting_problem::set_ties_config_standard_directions (Ties_configuration *tie_configs) { if (tie_configs->empty ()) - return ; + return; if (!tie_configs->at (0).dir_) { if (tie_configs->size () == 1) - tie_configs->at (0).dir_ = Direction (sign (tie_configs->at (0).position_)); + tie_configs->at (0).dir_ = Direction (sign (tie_configs->at (0).position_)); if (!tie_configs->at (0).dir_) - tie_configs->at (0).dir_ - = (tie_configs->size() > 1) ? DOWN : details_.neutral_direction_; + tie_configs->at (0).dir_ + = (tie_configs->size () > 1) ? DOWN : details_.neutral_direction_; } - + if (!tie_configs->back ().dir_) tie_configs->back ().dir_ = UP; @@ -990,68 +996,71 @@ Tie_formatting_problem::set_ties_config_standard_directions (Ties_configuration for (vsize i = 1; i < tie_configs->size (); i++) { Real diff = (tie_configs->at (i).position_ - -tie_configs->at (i-1).position_); - - Real span_diff - = specifications_[i].column_span () - specifications_[i-1].column_span (); + - tie_configs->at (i - 1).position_); + + Real span_diff + = specifications_[i].column_span () - specifications_[i - 1].column_span (); if (span_diff && fabs (diff) <= 2) - { - if (span_diff > 0) - tie_configs->at (i).dir_ = UP; - else if (span_diff < 0) - tie_configs->at (i-1).dir_ = DOWN; - } + { + if (span_diff > 0) + tie_configs->at (i).dir_ = UP; + else if (span_diff < 0) + tie_configs->at (i - 1).dir_ = DOWN; + } else if (fabs (diff) <= 1) - { - if (!tie_configs->at (i-1).dir_) - tie_configs->at (i-1).dir_ = DOWN; - if (!tie_configs->at (i).dir_) - tie_configs->at (i).dir_ = UP; - } + { + if (!tie_configs->at (i - 1).dir_) + tie_configs->at (i - 1).dir_ = DOWN; + if (!tie_configs->at (i).dir_) + tie_configs->at (i).dir_ = UP; + } } for (vsize i = 1; i + 1 < tie_configs->size (); i++) { Tie_configuration &conf = tie_configs->at (i); if (conf.dir_) - continue; + continue; - Direction position_dir = - Direction (sign (conf.position_)); + Direction position_dir + = Direction (sign (conf.position_)); if (!position_dir) - position_dir = DOWN; + position_dir = DOWN; conf.dir_ = position_dir; } } -Tie_configuration_variation::Tie_configuration_variation () -{ - index_ = 0; - suggestion_ = 0; -} - vector Tie_formatting_problem::generate_extremal_tie_variations (Ties_configuration const &ties) const { vector vars; - Direction d = DOWN; - do + for (int i = 1; i <= details_.multi_tie_region_size_; i++) { - if (boundary (ties, d, 0).dir_ == d - && !boundary (specifications_, d, 0).has_manual_position_) - for (int i = 1; i <= details_.multi_tie_region_size_; i++) - { - Tie_configuration_variation var; - var.index_ = (d == DOWN) ? 0 : ties.size () - 1; - var.suggestion_ = get_configuration (boundary (ties, d, 0).position_ - + d * i, d, - boundary (ties, d, 0).column_ranks_, - true); - vars.push_back (var); - } + Drul_array configs (0, 0); + for (DOWN_and_UP (d)) + { + const Tie_configuration &config = boundary (ties, d, 0); + if (config.dir_ == d + && !boundary (specifications_, d, 0).has_manual_position_) + { + Tie_configuration_variation var; + configs[d] = get_configuration (config.position_ + d * i, d, + config.column_ranks_, + true); + var.add_suggestion ((d == DOWN) ? 0 : ties.size () - 1, + configs[d]); + vars.push_back (var); + } + } + if (configs[LEFT] && configs[RIGHT]) + { + Tie_configuration_variation var; + var.add_suggestion (0, configs[DOWN]); + var.add_suggestion (ties.size () - 1, configs[UP]); + vars.push_back (var); + } } - while (flip (&d) != DOWN); return vars; } @@ -1064,124 +1073,118 @@ Tie_formatting_problem::generate_single_tie_variations (Ties_configuration const int sz = details_.single_tie_region_size_; if (specifications_[0].has_manual_position_) sz = 1; - for (int i = 0; i < sz; i ++) + for (int i = 0; i < sz; i++) { - Direction d = LEFT; - do - { - if (i == 0 - && ties[0].dir_ == d) - continue; - - int p = ties[0].position_ + i * d; - - if (!specifications_[0].has_manual_dir_ - || d == specifications_[0].manual_dir_) - { - Tie_configuration_variation var; - var.index_ = 0; - var.suggestion_ = get_configuration (p, - d, specifications_[0].column_ranks_, - !specifications_[0].has_manual_delta_y_); - vars.push_back (var); - } - } - while (flip (&d) != LEFT); + for (LEFT_and_RIGHT (d)) + { + if (i == 0 + && ties[0].dir_ == d) + continue; + + int p = ties[0].position_ + i * d; + + if (!specifications_[0].has_manual_dir_ + || d == specifications_[0].manual_dir_) + { + Tie_configuration_variation var; + var.add_suggestion (0, + get_configuration (p, + d, specifications_[0].column_ranks_, + !specifications_[0].has_manual_delta_y_)); + vars.push_back (var); + } + } } return vars; } - vector Tie_formatting_problem::generate_collision_variations (Ties_configuration const &ties) const { Real center_distance_tolerance = 0.25; - + vector vars; Real last_center = 0.0; for (vsize i = 0; i < ties.size (); i++) { Bezier b (ties[i].get_transformed_bezier (details_)); - + Real center = b.curve_point (0.5)[Y_AXIS]; - + if (i) - { - if (center <= last_center + center_distance_tolerance) - { - if (!specifications_[i].has_manual_dir_) - { - Tie_configuration_variation var; - var.index_ = i; - var.suggestion_ = get_configuration (specifications_[i].position_ - - ties[i].dir_, - - ties[i].dir_, - - ties[i].column_ranks_, - !specifications_[i].has_manual_delta_y_ - ); - - vars.push_back (var); - } - - if (!specifications_[i-1].has_manual_dir_) - { - Tie_configuration_variation var; - var.index_ = i-1; - var.suggestion_ = get_configuration (specifications_[i-1].position_ - - ties[i-1].dir_, - - ties[i-1].dir_, - specifications_[i-1].column_ranks_, - !specifications_[i-1].has_manual_delta_y_ - ); - - vars.push_back (var); - } - - if (i == 1 && !specifications_[i-1].has_manual_position_ - && ties[i-1].dir_ == DOWN) - { - Tie_configuration_variation var; - var.index_ = i-1; - var.suggestion_ = get_configuration (specifications_[i-1].position_ - 1, DOWN, - specifications_[i-1].column_ranks_, - !specifications_[i-1].has_manual_delta_y_ - - ); - vars.push_back (var); - } - if (i == ties.size () && !specifications_[i].has_manual_position_ - && ties[i].dir_ == UP) - { - Tie_configuration_variation var; - var.index_ = i; - var.suggestion_ = get_configuration (specifications_[i].position_ - + 1, UP, - specifications_[i].column_ranks_, - !specifications_[i].has_manual_delta_y_ - ); - vars.push_back (var); - } - } - else if (dot_positions_.find (ties[i].position_) != dot_positions_.end () - && !specifications_[i].has_manual_position_) - { - Tie_configuration_variation var; - var.index_ = i; - var.suggestion_ = get_configuration (ties[i].position_ + ties[i].dir_, - ties[i].dir_, - ties[i].column_ranks_, - !specifications_[i].has_manual_delta_y_ - ); - vars.push_back (var); - } - - } + { + if (center <= last_center + center_distance_tolerance) + { + if (!specifications_[i].has_manual_dir_) + { + Tie_configuration_variation var; + var.add_suggestion (i, + get_configuration (specifications_[i].position_ + - ties[i].dir_, + - ties[i].dir_, + + ties[i].column_ranks_, + !specifications_[i].has_manual_delta_y_ + )); + + vars.push_back (var); + } + + if (!specifications_[i - 1].has_manual_dir_) + { + Tie_configuration_variation var; + var.add_suggestion (i - 1, + get_configuration (specifications_[i - 1].position_ + - ties[i - 1].dir_, + - ties[i - 1].dir_, + specifications_[i - 1].column_ranks_, + !specifications_[i - 1].has_manual_delta_y_)); + + vars.push_back (var); + } + + if (i == 1 && !specifications_[i - 1].has_manual_position_ + && ties[i - 1].dir_ == DOWN) + { + Tie_configuration_variation var; + var.add_suggestion (i - 1, + get_configuration (specifications_[i - 1].position_ - 1, DOWN, + specifications_[i - 1].column_ranks_, + !specifications_[i - 1].has_manual_delta_y_ + )); + vars.push_back (var); + } + if (i == ties.size () && !specifications_[i].has_manual_position_ + && ties[i].dir_ == UP) + { + Tie_configuration_variation var; + var.add_suggestion (i, + get_configuration (specifications_[i].position_ + + 1, UP, + specifications_[i].column_ranks_, + !specifications_[i].has_manual_delta_y_ + )); + vars.push_back (var); + } + } + else if (dot_positions_.find (ties[i].position_) != dot_positions_.end () + && !specifications_[i].has_manual_position_) + { + Tie_configuration_variation var; + var.add_suggestion (i, + get_configuration (ties[i].position_ + ties[i].dir_, + ties[i].dir_, + ties[i].column_ranks_, + !specifications_[i].has_manual_delta_y_ + )); + vars.push_back (var); + } + + } last_center = center; } - return vars; } @@ -1194,40 +1197,40 @@ Tie_formatting_problem::set_manual_tie_configuration (SCM manual_configs) { SCM entry = scm_car (s); if (scm_is_pair (entry)) - { - Tie_specification &spec = specifications_[k]; - - if (scm_is_number (scm_car (entry))) - { - spec.has_manual_position_ = true; - spec.manual_position_ = scm_to_double (scm_car (entry)); - spec.has_manual_delta_y_ = (scm_inexact_p (scm_car (entry)) == SCM_BOOL_T); - } - - if (scm_is_number (scm_cdr (entry))) - { - spec.has_manual_dir_ = true; - spec.manual_dir_ = Direction (scm_to_int (scm_cdr (entry))); - } - } - k ++; + { + Tie_specification &spec = specifications_[k]; + + if (scm_is_number (scm_car (entry))) + { + spec.has_manual_position_ = true; + spec.manual_position_ = scm_to_double (scm_car (entry)); + /* TODO: check whether inexact? is an appropriate condition here */ + spec.has_manual_delta_y_ = (scm_is_true (scm_inexact_p (scm_car (entry)))); + } + + if (scm_is_number (scm_cdr (entry))) + { + spec.has_manual_dir_ = true; + spec.manual_dir_ = Direction (scm_to_int (scm_cdr (entry))); + } + } + k++; } } - void Tie_formatting_problem::set_debug_scoring (Ties_configuration const &base) { #if DEBUG_TIE_SCORING if (to_boolean (x_refpoint_->layout () - ->lookup_variable (ly_symbol2scm ("debug-tie-scoring")))) + ->lookup_variable (ly_symbol2scm ("debug-tie-scoring")))) { for (vsize i = 0; i < base.size (); i++) - { - string card = base.complete_tie_card (i); - specifications_[i].tie_grob_->set_property ("quant-score", - ly_string2scm (card)); - } + { + string card = base.complete_tie_card (i); + specifications_[i].tie_grob_->set_property ("annotation", + ly_string2scm (card)); + } } #endif -} +}