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
{
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));
}
}
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);
- }
- }
}
return;
x_refpoint_ = ties[0];
- details_.from_grob (ties[0]);
for (int i = 0; i < ties.size (); i++)
{
x_refpoint_ = dynamic_cast<Spanner*> (ties[i])->get_bound (LEFT)->common_refpoint (x_refpoint_, X_AXIS);
x_refpoint_ = dynamic_cast<Spanner*> (ties[i])->get_bound (RIGHT)->common_refpoint (x_refpoint_, X_AXIS);
}
+
+ details_.from_grob (ties[0]);
Direction d = LEFT;
do
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);
}
chord_outlines_[RIGHT].push (right_entry);
}
+
+Tie_configuration*
+Tie_formatting_problem::get_configuration (int pos, Direction dir)
+{
+ pair<int,int> 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<Tie_configuration> confs;
+
+ int region_size = 3;
+ for (int i = 0; i < region_size; i ++)
+ {
+ confs.push (generate_configuration (pos + i * dir, dir));
+ }
+
+ Array<Real> 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;
+}