From 069bab10a0735111453d9b3b45b9aff26b1d750b Mon Sep 17 00:00:00 2001 From: Mike Solomon Date: Fri, 8 Apr 2011 18:45:50 -0400 Subject: [PATCH] Adds collision-voice-only property to beams. The default is ##f, meaning that beams will attempt to not collide with all of the grobs they cover. Setting this to ##t only polices collisions within a voice. --- input/regression/beam-collision-voice-only.ly | 14 ++++++ lily/beam-collision-engraver.cc | 50 +++++++++++-------- lily/beam.cc | 1 + lily/grob-info.cc | 6 +++ lily/include/grob-info.hh | 1 + scm/define-grob-properties.scm | 2 + 6 files changed, 54 insertions(+), 20 deletions(-) create mode 100644 input/regression/beam-collision-voice-only.ly diff --git a/input/regression/beam-collision-voice-only.ly b/input/regression/beam-collision-voice-only.ly new file mode 100644 index 0000000000..42755a4a4d --- /dev/null +++ b/input/regression/beam-collision-voice-only.ly @@ -0,0 +1,14 @@ +\version "2.13.59" +\header { + texidoc = "Beam collision can be tweaked to only apply to the grobs +within the beam's original voice." +} + +\relative c' { + \time 5/4 + << { c8[ s c ] } \\ { s8 c' s8 } >> + c,[ des' ] + \override Staff . Beam #'collision-voice-only = ##t + << { c,8[ s c ] } \\ { s8 c' s8 } >> + c,[ des'! ] +} diff --git a/lily/beam-collision-engraver.cc b/lily/beam-collision-engraver.cc index bdaa557570..0f89eac89e 100644 --- a/lily/beam-collision-engraver.cc +++ b/lily/beam-collision-engraver.cc @@ -26,8 +26,8 @@ class Beam_collision_engraver : public Engraver { protected: - vector beams_; - vector covered_grobs_; + vector beams_; + vector covered_grobs_; DECLARE_ACKNOWLEDGER (note_head); DECLARE_ACKNOWLEDGER (accidental); @@ -67,41 +67,51 @@ Beam_collision_engraver::finalize () if (!covered_grobs_.size ()) return; - vector_sort (covered_grobs_, Grob::less); - vector_sort (beams_, Grob::less); + vector_sort (covered_grobs_, Grob_info::less); + vector_sort (beams_, Grob_info::less); vsize start = 0; for (vsize i = 0; i < beams_.size (); i++) { - Interval_t beam_spanned_rank_ = beams_[i]->spanned_rank_interval (); + Grob *beam_grob = beams_[i].grob (); + Context *beam_context = beams_[i].context (); + + Interval_t beam_spanned_rank_ = beam_grob->spanned_rank_interval (); // Start considering grobs at the first grob whose end falls at or after the beam's beginning. - while (covered_grobs_[start]->spanned_rank_interval ()[RIGHT] < beam_spanned_rank_[LEFT]) + while (covered_grobs_[start].grob ()->spanned_rank_interval ()[RIGHT] < beam_spanned_rank_[LEFT]) start++; // Stop when the grob's beginning comes after the beam's end. for (vsize j = start; j < covered_grobs_.size (); j++) { - Interval_t covered_grob_spanned_rank = covered_grobs_[j]->spanned_rank_interval (); + Grob *covered_grob = covered_grobs_[j].grob (); + Context *covered_grob_context = covered_grobs_[j].context (); + + Interval_t covered_grob_spanned_rank = covered_grob->spanned_rank_interval (); if ((covered_grob_spanned_rank[LEFT] > beam_spanned_rank_[RIGHT] - || !covered_grob_has_interface (covered_grobs_[j], beams_[i]))) + || !covered_grob_has_interface (covered_grob, beam_grob))) break; /* Only consider grobs whose end falls at or after the beam's beginning. - If the grob is a beam, it cannot start before beams_[i] + If the grob is a beam, it cannot start before beams_[i]. + Also, if the user wants to check for collisions only in the beam's voice, + then make sure the beam and the covered_grob are in the same voice. */ if ((covered_grob_spanned_rank[RIGHT] >= beam_spanned_rank_[LEFT]) - && !(Beam::has_interface (covered_grobs_[j]) + && !(to_boolean (beam_grob->get_property ("collision-voice-only")) + && (covered_grob_context != beam_context)) + && !(Beam::has_interface (covered_grob) && (covered_grob_spanned_rank[LEFT] <= beam_spanned_rank_[LEFT]))) { // Do not consider note heads attached to the beam. bool my_beam = false; - if (Grob *stem = unsmob_grob (covered_grobs_[j]->get_object ("stem"))) + if (Grob *stem = unsmob_grob (covered_grob->get_object ("stem"))) if (Grob *beam = unsmob_grob (stem->get_object ("beam"))) - if (beam == beams_[i]) + if (beam == beam_grob) my_beam = true; if (!my_beam) - Pointer_group_interface::add_grob (beams_[i], ly_symbol2scm ("covered-grobs"), covered_grobs_[j]); + Pointer_group_interface::add_grob (beam_grob, ly_symbol2scm ("covered-grobs"), covered_grob); } } } @@ -110,39 +120,39 @@ Beam_collision_engraver::finalize () void Beam_collision_engraver::acknowledge_note_head (Grob_info i) { - covered_grobs_.push_back (i.grob ()); + covered_grobs_.push_back (i); } void Beam_collision_engraver::acknowledge_accidental (Grob_info i) { if (i.grob ()->internal_has_interface (ly_symbol2scm ("inline-accidental-interface"))) - covered_grobs_.push_back (i.grob ()); + covered_grobs_.push_back (i); } void Beam_collision_engraver::acknowledge_clef (Grob_info i) { - covered_grobs_.push_back (i.grob ()); + covered_grobs_.push_back (i); } void Beam_collision_engraver::acknowledge_key_signature (Grob_info i) { - covered_grobs_.push_back (i.grob ()); + covered_grobs_.push_back (i); } void Beam_collision_engraver::acknowledge_time_signature (Grob_info i) { - covered_grobs_.push_back (i.grob ()); + covered_grobs_.push_back (i); } void Beam_collision_engraver::acknowledge_beam (Grob_info i) { - beams_.push_back (i.grob ()); - covered_grobs_.push_back (i.grob ()); + beams_.push_back (i); + covered_grobs_.push_back (i); } #include "translator.icc" diff --git a/lily/beam.cc b/lily/beam.cc index 6ae2ed4819..f39bf9f62c 100644 --- a/lily/beam.cc +++ b/lily/beam.cc @@ -1819,6 +1819,7 @@ ADD_INTERFACE (Beam, "clip-edges " "concaveness " "collision-interfaces " + "collision-voice-only " "covered-grobs " "damping " "details " diff --git a/lily/grob-info.cc b/lily/grob-info.cc index fb1f366b9e..f02e836e75 100644 --- a/lily/grob-info.cc +++ b/lily/grob-info.cc @@ -94,3 +94,9 @@ Grob_info::ultimate_event_cause () const } return unsmob_stream_event (cause); } + +bool +Grob_info::less (Grob_info i, Grob_info j) +{ + return Grob::less (i.grob (), j.grob ()); +} diff --git a/lily/include/grob-info.hh b/lily/include/grob-info.hh index cbe5a5f9df..f9390fff44 100644 --- a/lily/include/grob-info.hh +++ b/lily/include/grob-info.hh @@ -48,6 +48,7 @@ public: Item *item () const; Spanner *spanner () const; + static bool less (Grob_info i, Grob_info j); }; #endif // STAFFELEMINFO_HH diff --git a/scm/define-grob-properties.scm b/scm/define-grob-properties.scm index 62d7cf070c..3381cb9e27 100644 --- a/scm/define-grob-properties.scm +++ b/scm/define-grob-properties.scm @@ -172,6 +172,8 @@ edges of beams?") delimiter. If equal or smaller, the bracket/brace/line is removed.") (collision-interfaces ,list? "A list of interfaces for which automatic beam-collision resolution is run.") + (collision-voice-only ,boolean? "Does automatic beam collsion apply +only to the voice in which the beam was created?") (color ,color? "The color of this grob.") (common-shortest-duration ,ly:moment? "The most common shortest note length. This is used in spacing. Enlarging this sets the score -- 2.39.5