+
+void
+Tie_formatting_problem::set_ties_config_standard_directions (Ties_configuration *tie_configs)
+{
+ if (tie_configs->empty ())
+ return ;
+
+ if (!tie_configs->at (0).dir_)
+ {
+ if (tie_configs->size () == 1)
+ tie_configs->at (0).dir_ = Direction (sign (tie_configs->at (0).position_));
+
+ if (!tie_configs->at (0).dir_)
+ tie_configs->at (0).dir_ = DOWN;
+ }
+
+ if (!tie_configs->back ().dir_)
+ tie_configs->back ().dir_ = UP;
+
+ /*
+ Seconds
+ */
+ 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 ();
+ 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;
+ }
+ 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;
+ }
+ }
+
+ for (vsize i = 1; i + 1 < tie_configs->size (); i++)
+ {
+ Tie_configuration &conf = tie_configs->at (i);
+ if (conf.dir_)
+ continue;
+
+ Direction position_dir =
+ Direction (sign (conf.position_));
+ if (!position_dir)
+ position_dir = DOWN;
+
+ conf.dir_ = position_dir;
+ }
+}
+
+Tie_configuration_variation::Tie_configuration_variation ()
+{
+ index_ = 0;
+ suggestion_ = 0;
+}
+
+vector<Tie_configuration_variation>
+Tie_formatting_problem::generate_extremal_tie_variations (Ties_configuration const &ties) const
+{
+ vector<Tie_configuration_variation> vars;
+ Direction d = DOWN;
+ do
+ {
+ 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);
+ }
+ }
+ while (flip (&d) != DOWN);
+
+ return vars;
+}
+
+vector<Tie_configuration_variation>
+Tie_formatting_problem::generate_single_tie_variations (Ties_configuration const &ties) const
+{
+ vector<Tie_configuration_variation> vars;
+
+ int sz = details_.single_tie_region_size_;
+ if (specifications_[0].has_manual_position_)
+ sz = 1;
+ 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);
+ }
+ return vars;
+}
+
+
+vector<Tie_configuration_variation>
+Tie_formatting_problem::generate_collision_variations (Ties_configuration const &ties) const
+{
+ Real center_distance_tolerance = 0.25;
+
+ vector<Tie_configuration_variation> 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);
+ }
+
+ }
+
+ last_center = center;
+ }
+
+
+ return vars;
+}
+
+void
+Tie_formatting_problem::set_manual_tie_configuration (SCM manual_configs)
+{
+ vsize k = 0;
+ for (SCM s = manual_configs;
+ scm_is_pair (s) && k < specifications_.size (); s = scm_cdr (s))
+ {
+ 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 ++;
+ }
+}
+
+
+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"))))
+ {
+ 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));
+ }
+ }
+#endif
+}