#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
{
insert_extent_into_skyline (&chord_outlines_[d], Box (x,y), Y_AXIS, -d);
-
+ stem_extents_[d].unite (Box (x,y));
if (d == LEFT)
{
{
Link_array<Grob> ties;
ties.push (tie);
-
from_ties (ties);
details_.from_grob (tie);
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
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))
}
}
+ 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;
}
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;
}
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 ())
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));
}
}
}
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;
* 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);
Array<Tie_configuration_variation> 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
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;
{
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);
{
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);
}
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
#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");
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 ()