void
Beam_collision_engraver::stop_translation_timestep ()
{
+ /*
+ First, for all grobs that fall to the left of a beam during
+ a timestep (i.e. clefs, time signatures), add these to
+ the beams that are currently active.
+ */
for (vsize i = 0; i < covered_interior_grobs_.size (); i++)
for (vsize j = 0; j < active_beams_.size (); j++)
Pointer_group_interface::add_grob (active_beams_[j], ly_symbol2scm ("covered-grobs"), covered_interior_grobs_[i]);
covered_interior_grobs_.clear ();
+ /*
+ If a signaled beam is already in active_beams_, we erase it so as
+ not to have a beam represented in active_beams_ more than once.
+ */
+
for (vsize i = 0; i < active_beams_.size (); i++)
for (vsize j = 0; j < signaled_beams_.size (); j++)
if (active_beams_[i] == signaled_beams_[j])
}
/*
- hack.
- in auto beaming, end beams are signaled with their beams at a later timestep.
- we need to scrub these.
+ In auto beaming, beams both begin and end during the same timestep.
+ This means that if there is a beam that is both in signaled_beams_ and
+ end_beams_, it must either be an auto beam (likely) or a beam that
+ has no notes under it (highly unlikely). In either case, we cannot account
+ for the grobs under this beam, and we erase it from signaled beams.
*/
for (vsize i = 0; i < end_beams_.size (); i++)
for (vsize j = 0; j < signaled_beams_.size (); j++)
break;
}
+ /*
+ We want to know how big active beams was originally so that we do not
+ get any cyclical dependencies (see below).
+ */
vsize orig_size = active_beams_.size ();
+ /*
+ All signaled beams that are left now become active beams that are fair
+ game to collect covered grobs.
+ */
for (vsize i=0; i < signaled_beams_.size (); i++)
active_beams_.push_back (signaled_beams_[i]);
+ /*
+ Add all covered grobs that fall to the right of a beam (like noteheads)
+ as to covered-grobs of the beam. Note that noteheads that part of a beam
+ are not added to that list, as note heads should not never collide with
+ their own beams due to minimum stem length penalties in beam-quanting.cc.
+ */
for (vsize i = 0; i < covered_grobs_.size (); i++)
for (vsize j = 0; j < active_beams_.size (); j++)
{
covered_grobs_.clear ();
+ /*
+ This is where cyclical dependencies are avoided. In beam collision avoidance,
+ beams often need to avoid other beams. To do this, they need to know the beam's
+ position. But, if that second beam needs to know the first beam's position, we
+ have a cyclical dependency. So, we only ever add signaled beams to active_beams_
+ that existed BEFORE this time step. This is controlled by the orig_size variable.
+ The for loop stops before it gets to the signaled beams added above so that beams
+ added during this timestep are never dependent on each other for positioning.
+ */
for (vsize i = 0; i < signaled_beams_.size (); i++)
for (vsize j = 0; j < orig_size; j++)
Pointer_group_interface::add_grob (active_beams_[j], ly_symbol2scm ("covered-grobs"), signaled_beams_[i]);
signaled_beams_.clear ();
+ /*
+ If the end of a beam has been announced, it is no longer active. So, remove this beam
+ from active_beams_.
+ */
for (vsize i = 0; i < end_beams_.size (); i++)
for (vsize j = 0; j < active_beams_.size (); j++)
if (end_beams_[i] == active_beams_[j])