#include "pitch.hh"
#include "warn.hh"
#include "accidental-placement.hh"
-
+#include "note-column.hh"
+#include "group-interface.hh"
+#include "note-collision.hh"
MAKE_SCHEME_CALLBACK(Accidental_placement,extent_callback, 2);
SCM
}
};
+static Interval all_accidental_vertical_extent;
+Real ape_priority (Accidental_placement_entry const * a)
+{
+ Real c = a->vertical_extent_.center();
+
+ /*
+ far from center means we can fold more. Hopefully.
+ */
+ Real center_distance =
+ fabs(c - all_accidental_vertical_extent[LEFT]) >?
+ fabs(c - all_accidental_vertical_extent[RIGHT]);
+
+ return 20 * a->vertical_extent_.length () + center_distance;
+}
+
+
int ape_compare (Accidental_placement_entry *const &a,
Accidental_placement_entry *const &b)
{
- return sign (a->vertical_extent_.length () - b->vertical_extent_.length());
+ return sign (ape_priority (a) - ape_priority(b));
}
/*
Grob *commony =0 ;
+
+ /*
+ First we must extract *all* pointers. We can only determine
+ extents if we're sure that we've found the right common refpoint
+ */
+ Link_array<Grob> note_cols, heads;
for (int i= apes.size (); i--;)
- commony = common_refpoint_of_array (apes[i]->grobs_, commony, Y_AXIS);
+ {
+ Accidental_placement_entry * ape = apes[i];
+ for (int j = ape->grobs_.size(); j--;)
+ {
+ Grob * a = ape->grobs_[j];
+
+ commony = commony->common_refpoint (a, Y_AXIS);
+ Grob *head = a->get_parent (Y_AXIS);
+
+ Grob * col = head->get_parent (X_AXIS);
+ if (Note_column::has_interface (col))
+ note_cols.push (col);
+ else
+ heads.push (head);
+ }
+ }
+
+ /*
+ This is a little kludgy: to get all notes, we look if there are
+ collisions as well.
+ */
+ for (int i = note_cols.size() ; i--;)
+ {
+ Grob *c = note_cols[i]->get_parent (X_AXIS);
+ if (Note_collision_interface::has_interface (c))
+ {
+ Link_array<Grob> gs =
+ Pointer_group_interface__extract_grobs (c, (Grob*)0, "elements");
+
+ note_cols.concat (gs);
+ }
+ }
+
+ for (int i = note_cols.size() ; i--;)
+ {
+ heads.concat (Pointer_group_interface__extract_grobs (note_cols[i],
+ (Grob*)0,
+ "note-heads"));
+
+ }
+ heads.default_sort();
+ heads.uniq();
+ commony = common_refpoint_of_array (heads, commony, Y_AXIS);
- Link_array<Grob> heads;
+
for (int i= apes.size (); i--;)
{
Accidental_placement_entry * ape = apes[i];
- ape->left_skyline_ = empty_skyline ( LEFT);
- ape->right_skyline_ = empty_skyline ( RIGHT);
+ ape->left_skyline_ = empty_skyline (LEFT);
+ ape->right_skyline_ = empty_skyline (RIGHT);
for (int j = apes[i]->grobs_.size(); j--;)
{
b[X_AXIS] = a->extent (me, X_AXIS);
b[Y_AXIS] = a->extent (commony, Y_AXIS);
- Grob *head = a->get_parent (Y_AXIS);
- heads.push (head);
- commony = commony->common_refpoint (head, Y_AXIS);
-
ape->extents_.push (b);
-
/*
TODO: replace the extents of a flat by combination of two
}
}
+
+ Interval total;
for (int i = apes.size(); i--;)
{
Interval y ;
y.unite (apes[i]->extents_[j][Y_AXIS]);
}
apes[i]->vertical_extent_ = y;
+ total.unite (y);
}
-
+ all_accidental_vertical_extent = total;
apes.sort (&ape_compare);
Accidental_placement_entry * head_ape = new Accidental_placement_entry;
if (gh_number_p (rs))
head_ape->offset_ -= gh_scm2double (rs);
- Real padding = 0.1;
+
+ Real padding = 0.2;
+ SCM spad = me->get_grob_property ("padding");
+ if (gh_number_p (spad))
+ padding = gh_scm2double (spad);
+
apes.push (head_ape);
for (int i= apes.size () -1 ; i-- > 0;)
{
Accidental_placement_entry *ape = apes[i];
Real d = 0.0;
- /*
- confusing naming: left_skyline is a skyline pointing to the
- left. It is on the right of the curent entry.
- */
-
int j = i+1;
do {
- Array<Skyline_entry> const *right_sky =
- (j < apes.size())
- ? &apes[j]->left_skyline_
- : &head_skyline;
-
d = - skyline_meshing_distance (ape->right_skyline_,
- *right_sky);
+ apes[j]->left_skyline_);
if (!isinf(d)
|| j + 1 == apes.size())
ADD_INTERFACE(Accidental_placement,
"accidental-placement-interface",
"Take care of complex accidental collisions.",
- "left-padding right-padding accidentals alignment-done")
+ "left-padding padding right-padding accidentals alignment-done")