]> git.donarmstrong.com Git - lilypond.git/commitdiff
note-collision: rework horizontal shifts; issue 1774,2196
authorKeith OHara <k-ohara5a5a@oco.net>
Sun, 24 Aug 2014 08:48:17 +0000 (01:48 -0700)
committerKeith OHara <k-ohara5a5a@oco.net>
Sat, 6 Sep 2014 06:35:26 +0000 (23:35 -0700)
Also allow duplicate 'horizontal-shift's without the "too many clashing
note-columns" warning.

Documentation/learning/fundamental.itely
Documentation/notation/simultaneous.itely
Documentation/snippets/new/suppressing-warnings-for-clashing-note-columns.ly [new file with mode: 0644]
input/regression/beam-multiple-cross-staff.ly
input/regression/collisions.ly
input/regression/stem-tremolo-note-collision.ly
lily/note-collision.cc
lily/stem.cc

index c64af67ed473d7116901149afe108c447848a065..bcf449f276274270cf8692172fd9d4860cd4ee17 100644 (file)
@@ -801,7 +801,7 @@ later sections.
   \\  % Voice two
     {
       % Ignore these for now - they are explained in Ch 4
-      \once \override NoteColumn.ignore-collision = ##t
+      \once \override NoteColumn.force-hshift = #0
       <ees, c>2
       \once \override NoteColumn.force-hshift = #0.5
       des2
@@ -851,7 +851,7 @@ not understand.
   \\  % Voice two
     { \voiceTwoStyle
       % Ignore these for now - they are explained in Ch 4
-      \once \override NoteColumn.ignore-collision = ##t
+      \once \override NoteColumn.force-hshift = #0
       <ees, c>2
       \once \override NoteColumn.force-hshift = #0.5
       des2
index c139853fc1d3b10e2f2b6c6b39c2c61817382a11..70846342e718020fb934a543fbff9ed956aac731 100644 (file)
@@ -290,9 +290,8 @@ interpreted in different voices.
 @cindex collisions, ignoring
 
 @knownissues
-If notes from two or more voices, with stems in the same direction, are
-placed at the same position on the staff and have no shift (or have the
-same shift specified), the message:
+If notes from two or more voices, with no shifts specified,
+have stems in the same direction, the message
 
 @example
 warning: ignoring too many clashing note columns
diff --git a/Documentation/snippets/new/suppressing-warnings-for-clashing-note-columns.ly b/Documentation/snippets/new/suppressing-warnings-for-clashing-note-columns.ly
new file mode 100644 (file)
index 0000000..cf6fe93
--- /dev/null
@@ -0,0 +1,27 @@
+\version "2.19.14"
+
+\header {
+  lsrtags = "simultaneous-notes, tweaks-and-overrides"
+
+  texidoc = "
+If notes from two voices with stems in the same direction are placed at
+the same position, but the voices have no voice-specific shifts
+specified, the error message @samp{warning: ignoring too many clashing
+note columns} will appear when compiling the LilyPond file.  This
+message can be suppressed by setting the @code{'ignore-collision}
+property of the @code{NoteColumn} object to @code{#t}. Please note that
+this does not just suppress warnings  but stops LilyPond trying to
+resolve collisions at all and so may have  unintended results unless
+used with care.
+"
+  doctitle = "Suppressing warnings for clashing note columns"
+}
+
+ignore = \override NoteColumn.ignore-collision = ##t
+
+\relative c' {
+  \new Staff <<
+    \new Voice{ \ignore \stemDown f2 g }
+    \new Voice{ c2 \stemDown c, }
+  >>
+}
index 7827e3d723ecdf35d647fff5e67873e14a4d9240..0c382b2f762e20e76e8e3146bc5da9b6b37b8b74 100644 (file)
@@ -14,17 +14,17 @@ to the last beam.
 
 \context PianoStaff \relative c' <<
   \new Staff = SA {
-    \stemDown
-    c8[ c16 \change Staff = SB \stemUp c16 ]
-    \stemNeutral
+    \voiceTwo
+    c8[ c16 \change Staff = SB \voiceOne c16 ]
+    \oneVoice
     f[ g \change Staff = SA a c] 
   }
   \new Staff = SB \relative c' {
     \clef bass
-    b8[ b16 \stemUp b,,16 ]
+    b8[ b16 \voiceOne b,,16 ]
 
     g'4\rest
-    b,8[ b16 \stemDown b''16 b ]
+    b,8[ b16 \voiceTwo b''16 b ]
   }
   
 >>
index c94254378b5b409d32fe929bcffb7a637b1f7826..5b03483b6bf4abea02f8c48394bd6b7feae47d5e 100644 (file)
@@ -39,6 +39,24 @@ hairyChord = \context Staff  \relative c''
   ais
 >>
 
+minims = <<
+  { e''2 e'' e' d' } \\
+  c'' \\
+  { c' c' c' c' } \\
+  g' >>
+
+semibreves = <<
+  { e''1 e'' e' d' } \\
+  c'' \\
+  { c' c' c' c' } \\
+  g' >>
+
+sequence = <<
+  \new Voice { \voiceOne g''1 e''2 d'' e'' d'' }
+  \new Voice { \voiceThree c''2 b' a'1 b' }
+  \new Voice { \voiceFour g'1 e'2 f'2 a'1 }
+  \new Voice { \voiceTwo c'1 c'2 d' e'2 d' }
+>>
 
   {
     \transpose c c' {
@@ -47,6 +65,9 @@ hairyChord = \context Staff  \relative c''
       \threevoice
     }
     \hairyChord
+    \break
+    \minims \bar "||"
+    \semibreves \bar "||"
+    \sequence
   }
-  
 
index 6b5b32a93ca56b546b2372cef3a4a0a426547997..b7b21428498741a7bc98824c75fd1a7a29cb1800 100644 (file)
@@ -6,8 +6,6 @@ best as possible and issue a warning otherwise.
 "
 }
 
-#(ly:expect-warning (_ "ignoring too many clashing note columns"))
-
 {
 <<
    {  b'4 f'2. }
@@ -17,4 +15,4 @@ best as possible and issue a warning otherwise.
      \repeat tremolo 32 <b g'>32
    }
 >>
-}
\ No newline at end of file
+}
index 79a65845759b259e6b1bb6e9fafa84ca51b9b979..0008bad23ab2e0f1fdad97ff7a35b143510791b0 100644 (file)
 #include "stem.hh"
 #include "warn.hh"
 
-void
+Real
 check_meshing_chords (Grob *me,
-                      Drul_array<vector<Real> > *offsets,
-                      Drul_array<vector<Slice> > const &extents,
-                      Drul_array<vector<Grob *> > const &clash_groups)
+                      Grob *clash_up, Grob *clash_down)
 
 {
-  if (!extents[UP].size () || !extents[DOWN].size ())
-    return;
-
-  Grob *clash_up = clash_groups[UP][0];
-  Grob *clash_down = clash_groups[DOWN][0];
-
   /* Every note column should have a stem, but avoid a crash. */
   if (!Note_column::get_stem (clash_up) || !Note_column::get_stem (clash_down))
-    return;
+    return 0.0;
 
   Drul_array<Grob *> stems (Note_column::get_stem (clash_down),
                             Note_column::get_stem (clash_up));
@@ -65,7 +57,7 @@ check_meshing_chords (Grob *me,
 
   /* Too far apart to collide. */
   if (ups[0] > dps.back () + 1)
-    return;
+    return 0.0;
 
   /* If the chords just 'touch' their extreme noteheads,
      then we can align their stems.
@@ -359,11 +351,7 @@ check_meshing_chords (Grob *me,
         }
     }
 
-  for (UP_and_DOWN (d))
-    {
-      for (vsize i = 0; i < clash_groups[d].size (); i++)
-        (*offsets)[d][i] += d * shift_amount;
-    }
+  return shift_amount;
 }
 
 MAKE_SCHEME_CALLBACK (Note_collision_interface, calc_positioning_done, 1)
@@ -471,37 +459,11 @@ SCM
 Note_collision_interface::automatic_shift (Grob *me,
                                            Drul_array<vector<Grob *> > clash_groups)
 {
-  Drul_array < vector<int> > shifts;
   SCM tups = SCM_EOL;
 
-  for (UP_and_DOWN (d))
-    {
-      vector<int> &shift (shifts[d]);
-      vector<Grob *> &clashes (clash_groups[d]);
-
-      for (vsize i = 0; i < clashes.size (); i++)
-        {
-          SCM sh
-            = clashes[i]->get_property ("horizontal-shift");
-
-          if (scm_is_number (sh))
-            shift.push_back (scm_to_int (sh));
-          else
-            shift.push_back (0);
-        }
-
-      for (vsize i = 1; i < shift.size (); i++)
-        {
-          if (shift[i - 1] == shift[i])
-            {
-              clashes[0]->warning (_ ("ignoring too many clashing note columns"));
-              return tups;
-            }
-        }
-    }
-
   Drul_array<vector<Slice> > extents;
-  Drul_array<vector<Real> > offsets;
+  Drul_array<Slice> extent_union;
+  Drul_array<vector<Grob *> > stems;
   for (UP_and_DOWN (d))
     {
       for (vsize i = 0; i < clash_groups[d].size (); i++)
@@ -510,10 +472,16 @@ Note_collision_interface::automatic_shift (Grob *me,
           s[LEFT]--;
           s[RIGHT]++;
           extents[d].push_back (s);
-          offsets[d].push_back (d * 0.5 * i);
+          extent_union[d].unite (s);
+          stems[d].push_back (Note_column::get_stem (clash_groups[d][i]));
         }
     }
 
+  Real inner_offset
+    = (clash_groups[UP].size () && clash_groups[DOWN].size ())
+      ? check_meshing_chords (me, clash_groups[UP][0], clash_groups[DOWN][0])
+      : 0.0;
+
   /*
    * do horizontal shifts of each direction
    *
@@ -522,17 +490,46 @@ Note_collision_interface::automatic_shift (Grob *me,
    *  x||
    *   x|
   */
-
+  Drul_array<vector<Real> > offsets;
   for (UP_and_DOWN (d))
     {
-      for (vsize i = 1; i < clash_groups[d].size (); i++)
+      Real offset = inner_offset;
+      vector<int> shifts;
+      for (vsize i = 0; i < clash_groups[d].size (); i++)
         {
-          Slice prev = extents[d][i - 1];
-          prev.intersect (extents[d][i]);
-          if (prev.length () > 0
-              || (extents[-d].size () && d * (extents[d][i][-d] - extents[-d][0][d]) < 0))
-            for (vsize j = i; j < clash_groups[d].size (); j++)
-              offsets[d][j] += d * 0.5;
+          Grob *col = clash_groups[d][i];
+          SCM sh = col->get_property ("horizontal-shift");
+          shifts.push_back (robust_scm2int (sh, 0));
+
+          if (i == 0)
+            offset = inner_offset;
+          else if (shifts[i] == shifts[i - 1])
+            {
+              // Match the previous notecolumn offset,
+              // but warn if the user did not set these equal shifts explictly
+              if (!scm_is_number (sh))
+                col->warning (_ ("ignoring too many clashing note columns"));
+            }
+          else if (extents[d][i][UP] > extents[d][i - 1][DOWN]
+                   && extents[d][i][DOWN] < extents[d][i - 1][UP])
+            offset += 1.0; // fully clear the inner-voice heads
+          else
+            {
+              // check if we cross the inner voice
+              if (d * extents[d][i][-d] >= d * extents[d][i - 1][d])
+                offset += Stem::is_valid_stem (stems[d][i - 1])
+                          ? 1.0 : 0.5;
+              else if (Stem::is_valid_stem (stems[d][i]))
+                offset += 0.5;
+              // check if we cross the opposite-stemmed voices
+              if (d * extents[d][i][-d] < d * extent_union[-d][d])
+                offset = max (offset, 0.5);
+              if (extents[-d].size ()
+                  && extents[d][i][UP] > extents[-d][0][DOWN]
+                  && extents[d][i][DOWN] < extents[-d][0][UP])
+                offset = max (offset, 1.0);
+            }
+          offsets[d].push_back (d * offset);
         }
     }
 
@@ -546,18 +543,9 @@ Note_collision_interface::automatic_shift (Grob *me,
 
       if (dc)
         for (vsize j = i + 1; j < clash_groups[UP].size (); j++)
-          {
-            Grob *stem = Note_column::get_stem (clash_groups[UP][j]);
-            Side_position_interface::add_support (dc, stem);
-          }
+          Side_position_interface::add_support (dc, stems[UP][j]);
     }
 
-  /*
-    Check if chords are meshing
-  */
-
-  check_meshing_chords (me, &offsets, extents, clash_groups);
-
   for (UP_and_DOWN (d))
     {
       for (vsize i = 0; i < clash_groups[d].size (); i++)
index 0a72fcf01953b1d276c57a64c9782e82a6844d6a..a809c170df7a70e7716a5b1d971c87cd9f889f2e 100644 (file)
@@ -835,6 +835,8 @@ Stem::is_valid_stem (Grob *me)
 {
   /* TODO: make the stem start a direction ?
      This is required to avoid stems passing in tablature chords.  */
+  if (!me)
+    return false;
   Grob *lh = get_reference_head (me);
   Grob *beam = Grob::unsmob (me->get_object ("beam"));