+
+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_
+ = (tie_configs->size () > 1) ? DOWN : details_.neutral_direction_;
+ }
+
+ 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;
+ }
+}
+
+vector<Tie_configuration_variation>
+Tie_formatting_problem::generate_extremal_tie_variations (Ties_configuration const &ties) const
+{
+ vector<Tie_configuration_variation> vars;
+ for (int i = 1; i <= details_.multi_tie_region_size_; i++)
+ {
+ Drul_array<Tie_configuration *> 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);
+ }
+ }
+
+ 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++)
+ {
+ 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_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.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;
+}
+
+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 ("annotation",
+ ly_string2scm (card));
+ }
+ }
+#endif
+}