#include "tie-formatting-problem.hh"
+#include "axis-group-interface.hh"
#include "paper-column.hh"
-#include "bezier.hh"
+#include "bezier.hh"
#include "directional-element-interface.hh"
#include "libc-extension.hh"
#include "misc.hh"
#include "note-head.hh"
#include "rhythmic-head.hh"
-#include "spanner.hh"
+#include "spanner.hh"
#include "staff-symbol-referencer.hh"
#include "stem.hh"
#include "tie-configuration.hh"
return attachments;
}
-Tie_formatting_problem::Tie_formatting_problem()
+Tie_formatting_problem::Tie_formatting_problem ()
{
x_refpoint_ = 0;
+ y_refpoint_ = 0;
+ use_horizontal_spacing_ = true;
}
Tie_formatting_problem::~Tie_formatting_problem ()
{
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;
- y.add_point (Stem::stem_end_position (stem) * staff_space * .5);
+
+ 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]
*/
boxes.push_back (Box (x, y));
- stem_extents_[key].unite (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));
+ flag_box.translate ( Offset (x[RIGHT], X_AXIS));
boxes.push_back (flag_box);
}
}
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]);
}
extract_grob_set (stem, "note-heads", heads);
- for (vsize i = 0; i < heads.size(); i ++)
+ for (vsize i = 0; i < heads.size (); i ++)
{
- if (find (bounds.begin(), bounds.end (), dynamic_cast<Item*> (heads[i])) != bounds.end ())
- continue;
-
- /*
- other untied notes in the same chord.
- */
+ if (find (bounds.begin (), bounds.end (), dynamic_cast<Item*> (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));
-
+ 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 && dir == RIGHT)
+ 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])));
}
}
{
Interval x;
Interval y;
- if (head_boxes.size())
+ if (head_boxes.size ())
{
Box b = boundary (head_boxes, updowndir, 0);
x = b[X_AXIS];
chord_outlines_[key] = Skyline (boxes, details_.skyline_padding_, Y_AXIS, -dir);
if (bounds[0]->break_status_dir ())
{
- Real x = robust_relative_extent (bounds[0], x_refpoint_, X_AXIS)[-dir];
-
- chord_outlines_[key].set_minimum_height (x);
+ 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));
+
+ chord_outlines_[key].set_minimum_height (iv[-dir]);
}
else
{
return;
x_refpoint_ = ties[0];
+ y_refpoint_ = ties[0];
for (vsize 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);
+ Spanner *tie = dynamic_cast<Spanner*> (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_ = r->common_refpoint (x_refpoint_, X_AXIS);
+
+ if (!l->break_status_dir ())
+ y_refpoint_ = l->common_refpoint (y_refpoint_, Y_AXIS);
+ if (!r->break_status_dir ())
+ y_refpoint_ = r->common_refpoint (y_refpoint_, Y_AXIS);
}
details_.from_grob (ties[0]);
{
Item *it = dynamic_cast<Spanner*> (ties[i])->get_bound (d);
if (it->break_status_dir ())
- {
- Item *sep
- = dynamic_cast<Item*> (unsmob_grob (ties[i]->get_object ("separation-item")));
- if (sep && sep->get_column () == it->get_column ())
- it = sep;
+ it = it->get_column ();
- bounds.push_back (it);
- }
- else
- {
- bounds.push_back (it);
- }
+ bounds.push_back (it);
}
set_chord_outline (bounds, d);
{
if (semi_ties.empty ())
return;
-
+
+ use_horizontal_spacing_ = false;
details_.from_grob (semi_ties[0]);
vector<Item*> heads;
specifications_.push_back (spec);
}
- x_refpoint_ = semi_ties [0];
+ x_refpoint_ = semi_ties[0];
+ y_refpoint_ = semi_ties[0];
+
for (vsize i = 0; i < semi_ties.size (); i++)
- x_refpoint_ = semi_ties[i]->common_refpoint (x_refpoint_, X_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);
+ {
+ 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);
size.
*/
- if (h < details_.intra_space_threshold_ * 0.5 * details_.staff_space_)
+ 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 (!Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_, pos)
- && abs (pos) < 2 * Staff_symbol_referencer::staff_radius (details_.staff_symbol_referencer_))
+ if (h < details_.intra_space_threshold_ * 0.5 * details_.staff_space_)
{
- 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_;
+ 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))
+ else
{
- Real new_y = (round_pos + clearance * conf->dir_) * 0.5 * details_.staff_space_;
- conf->delta_y_ = (new_y - top_y);
+ 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_)
{
}
{
- Real p = details_.vertical_distance_penalty_factor_ * convex_amplifier (1.0, fabs (curve_y - tie_y));
+ Real relevant_dist = max (fabs (curve_y - tie_y) - 0.5, 0.0);
+ Real p = details_.vertical_distance_penalty_factor_ * convex_amplifier (1.0, 0.9, relevant_dist);
if (ties_conf)
ties_conf->add_tie_score (p, tie_idx, "vdist");
else
TODO: flatten with log or sqrt.
*/
Real p = details_.horizontal_distance_penalty_factor_
- * convex_amplifier (1.25, dist);
+ * convex_amplifier (1.25, 1.0, dist);
if (ties_conf)
ties_conf->add_tie_score (p, tie_idx,
(d == LEFT) ? "lhdist" : "rhdist");
while (flip (&d) != LEFT);
if (ties_conf
- && ties_conf->size() == 1)
+ && ties_conf->size () == 1)
{
Direction d = LEFT;
Drul_array<Grob*> stems (0, 0);
}
+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;
+ }
+ Slice empty;
+ return empty;
+}
+
/*
Score a configuration, ie. how well these ties looks without regard
to the note heads that they should connect to.
fabs (top_pos - round_top_pos)),
"line center");
}
-
- if (Staff_symbol_referencer::on_line (details_.staff_symbol_referencer_,
- int (rint (tip_pos))))
+
+ int rounded_tip_pos = int (rint (tip_pos));
+ 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_))
+ )
{
conf->add_score (details_.staff_line_collision_penalty_
* peak_around (0.1 * details_.tip_staff_line_clearance_,
);
vars.push_back (var);
}
- if (i == ties.size() && !specifications_[i].has_manual_position_
+ if (i == ties.size () && !specifications_[i].has_manual_position_
&& ties[i].dir_ == UP)
{
Tie_configuration_variation var;
if (to_boolean (x_refpoint_->layout ()
->lookup_variable (ly_symbol2scm ("debug-tie-scoring"))))
{
- for (vsize i = 0; i < base.size(); i++)
+ for (vsize i = 0; i < base.size (); i++)
{
string card = base.complete_tie_card (i);
specifications_[i].tie_grob_->set_property ("quant-score",