]> git.donarmstrong.com Git - lilypond.git/commitdiff
biem fix
authorHan-Wen Nienhuys <hanwen@xs4all.nl>
Sat, 1 Jun 2002 11:34:21 +0000 (11:34 +0000)
committerHan-Wen Nienhuys <hanwen@xs4all.nl>
Sat, 1 Jun 2002 11:34:21 +0000 (11:34 +0000)
ChangeLog
flower/include/interval.hh
flower/include/interval.tcc
input/bugs/bizarre-beam.ly
input/regression/beam-extreme.ly
input/regression/beam-multiple-cross-staff.ly
lily/beam.cc
lily/include/beam.hh
lily/stem.cc
scm/grob-description.scm

index 4bb64bf7cefae0338ff5e739f3c67ab5f9defaab..ad3eab610885a913338fb404d591eab045c67185 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2002-06-01  Han-Wen  <hanwen@cs.uu.nl>
+
+       * lily/beam.cc (shift_region_to_valid): Try to shift positions
+       after slope-damping and concaveness check, so that short-stems are
+       not violated.
+
 2002-06-01  Jan Nieuwenhuizen  <janneke@gnu.org>
 
        * lily/beam.cc (quanting): Increase REGION_SIZE to 4 by default.
index c4e9d4e718de4322915e999db7b9d21eaa2a26d0..0d445b2366677daf90441384c5f7eb989f8d01cf 100644 (file)
@@ -52,6 +52,7 @@ struct Interval_t : public Drul_array<T> {
   T length () const;
   T delta () const;
   void set_empty () ;
+  void set_full ();
   bool empty_b () const { return elem (LEFT) > elem (RIGHT); }
   bool contains_b (Interval_t<T> const&) const;
   Interval_t () {
index 94ad71f5785081d892b8ba23f06755d1a1b04dfc..60f23fab09b88dde2ef9c73633b0cef23504cf8b 100644 (file)
@@ -60,6 +60,14 @@ Interval_t<T>::set_empty ()
   elem (RIGHT) = (T) -infinity ();
 }
 
+template<class T>
+void
+Interval_t<T>::set_full ()
+{
+  elem (LEFT) = (T) -infinity ();
+  elem (RIGHT) = (T) infinity ();
+}
+
 template<class T>
 T
 Interval_t<T>::length () const 
index 166376e7b8a9302ee49ee68637226eeaa164ac18..b1abf20a703df2bf231685ba86d5727fe0bc4d9d 100644 (file)
@@ -2,7 +2,8 @@
 
 \score{ \notes {g''4 [<e'''8 g> g'']
 \notes\relative c'{
-   \times 2/3{[d16 fis' d,]} \times 2/3{[cis g'' cis,,]}
+
+    \times 2/3{[d16 fis' d,]} \times 2/3{[cis g'' cis,,]}
   a'16 cis a, g''' % Used to give a nice beam directed upwards.
   <{\stemUp a,,4:32} \context Voice=lower{\stemDown d,:32}>
 
index 2cdc7ae801c225aae342bfc8e659b0d51ea15e7f..754553c765b512a77b98e486f456dfe4c40a1a6b 100644 (file)
@@ -14,18 +14,34 @@ extreme = \notes\relative c'' {
   [c16 c'' a f]
   \stemUp 
   [c,,32 c'' a f]
-  r4
+
+  %%%%%%%
+  \stemBoth
+  \times 2/3{[d16 fis' d,]} \times 2/3{[cis g'' cis,,]}
+  a'16 cis a, g''' % Used to give a nice beam directed upwards.
+  \stemBoth
+
+  \transpose c' {
+         \stemDown [e'8 e e']
+      }
 }
+
 \score {
   {
     % If we want to test extreme beams,
     % we should not have them auto-kneed
     \property Voice.Beam \override #'auto-knee-gap = ##f
     \extreme
+
+
+    %% what does this test? --hwn
+%{
     \property Voice.Beam \override #'slope-limit = #1000
     \extreme
+    %}
   }
   \paper{
-    linewidth=-1.
+%    raggedright = ##t
+    linewidth = -1
   }
 }
index f4e325bf07bcc011b95636df5d2d30077d9b4d9a..a627df8d32919e431eb5f89d3390851bbb7ff8ad 100644 (file)
@@ -18,7 +18,9 @@ to the last beam.
             \context Staff = SB \relative c' {
 \clef bass
                 [b8 b16 \stemUp b,,16 ]
-                [b8 b16 \stemDown b''16 b ]
+
+                g'4\rest
+                [b,8 b16 \stemDown b''16 b ]
             }       
             
             >
index 15df1eaf68f5644e3b7b9ce3a174ac0f423b58ff..c24d348c00052db936e7a44b2013e1154c9e3de2 100644 (file)
   * Rewrite stem_beams.
 
   * Use Number_pair i.s.o Interval to represent (yl, yr).
+
   
   */
 
 
-/* snapnie now also works */
-#define SNAPNIE
-
 #include <math.h> // tanh.
 
 #include "molecule.hh" 
@@ -63,6 +61,7 @@ const int STEM_LENGTH_LIMIT_PENALTY = 5000;
 const int DAMPING_DIRECTIION_PENALTY = 800;
 const int MUSICAL_DIRECTION_FACTOR = 400;
 const int IDEAL_SLOPE_FACTOR = 10;
+const int REGION_SIZE = 2;
 
 
 static Real
@@ -452,39 +451,26 @@ Beam::quanting (SCM smob)
       stem_infos.push (Stem::calc_stem_info (s));
       dirs_found[stem_infos.top ().dir_] = true;
 
-#ifdef SNAPNIE
       Real b = calc_stem_y (me, s, Interval (1,0), false);
       lbase_lengths.push (b);
 
       Real a = calc_stem_y (me, s, Interval (0,1), false);
       rbase_lengths.push (a);
-#endif      
     }
 
   Direction ldir = Direction (stem_infos[0].dir_);
   Direction rdir = Direction (stem_infos.top ().dir_);
   bool knee_b = dirs_found[LEFT] && dirs_found[RIGHT];
 
-  /*
-    This
-    
-      \score {
-        \context Staff \notes {
-         \stemDown [e'8 e e']
-       }
-      }
-      
-    breaks with REGION_SIZE < 4
-  */
-  int REGION_SIZE = 4;
 
+  int region_size = REGION_SIZE;
   /*
     Knees are harder, lets try some more possibilities for knees. 
    */
   if (knee_b)
-    REGION_SIZE += 2;
+    region_size += 2;
   
-  for (int i = -REGION_SIZE ; i < REGION_SIZE; i++)
+  for (int i = -region_size ; i < region_size; i++)
     for (int j = 0; j < num_quants; j++)
       {
        quantsl.push (i + quants[j] + int (yl));
@@ -587,42 +573,14 @@ Beam::score_stem_lengths (Link_array<Grob>stems,
   Real demerit_score = 0.0 ;
   Real pen = STEM_LENGTH_LIMIT_PENALTY;
   
-#if 0
-  if (knee)
-    pen = sqrt(pen);
-#endif
-  
-  Real x0 = first_visible_stem (me)->relative_coordinate (0, X_AXIS);
-  Real dx = last_visible_stem (me)->relative_coordinate (0, X_AXIS) - x0;
-
   for (int i=0; i < stems.size (); i++)
     {
       Grob* s = stems[i];
       if (Stem::invisible_b (s))
        continue;
 
-#ifdef SNAPNIE
-      /* for a two-stemmed, interstaff beam knee up/down:
-
-      \score {
-        \context PianoStaff \notes\relative c' <
-          \context Staff = lh {
-            \stemDown [c8 \translator Staff = rh \stemUp a'' ]
-          }
-          \context Staff = rh \relative c' s4
-        >
-      }
-
-        with yl = -5.8 (about ideal)
-        and yr = -1 (ridiculous pos)
-        this yields current_y = -8.1 (about ideal) */
-
       Real current_y =
        yl * left_factor[i] + right_factor[i]* yr;
-#else
-      Real f = (s->relative_coordinate (0, X_AXIS) - x0) / dx;
-      Real current_y = yl + f * (yr - yl);
-#endif      
 
       Stem_info info = stem_infos[i];
       Direction d = info.dir_;
@@ -781,6 +739,29 @@ Beam::least_squares (SCM smob)
 
   Interval ideal (Stem::calc_stem_info (first_visible_stem (me)).ideal_y_,
                  Stem::calc_stem_info (last_visible_stem (me)).ideal_y_);
+
+
+
+  Array<Real> x_posns ;
+  Link_array<Item> stems=
+    Pointer_group_interface__extract_grobs (me, (Item*)0, "stems");
+  Grob *common = stems[0];
+  for (int i=1; i < stems.size (); i++)
+    common = stems[i]->common_refpoint (common, X_AXIS);
+
+  Real x0 = first_visible_stem (me)->relative_coordinate (common, X_AXIS);
+  for (int i=0; i < stems.size (); i++)
+    {
+      Item* s = stems[i];
+
+      Real x = s->relative_coordinate (common, X_AXIS) - x0;
+      x_posns.push (x);
+    }
+  Real dx = last_visible_stem (me)->relative_coordinate (common, X_AXIS) - x0;
+
+  Real y =0;  
+  Real dydx = 0;
+  Real dy = 0;
   
   if (!ideal.delta ())
     {
@@ -789,11 +770,10 @@ Beam::least_squares (SCM smob)
 
 
       /*
-       TODO  : use scoring for this.
+       TODO -- use scoring for this.
 
        complicated, because we take stem-info.ideal for determining
        beam slopes.
-       
        */
       /* Make simple beam on middle line have small tilt */
       if (!ideal[LEFT] && chord.delta () && count == 2)
@@ -811,39 +791,118 @@ Beam::least_squares (SCM smob)
        {
          pos = ideal;
        }
+
+      y = pos[LEFT];
+      dy = pos[RIGHT]- y;
+      dydx = dy/dx;
     }
   else
     {
       Array<Offset> ideals;
-
-      // ugh -> use commonx
-      Real x0 = first_visible_stem (me)->relative_coordinate (0, X_AXIS);
-      Link_array<Item> stems=
-       Pointer_group_interface__extract_grobs (me, (Item*)0, "stems");
-
       for (int i=0; i < stems.size (); i++)
        {
          Item* s = stems[i];
          if (Stem::invisible_b (s))
            continue;
-         ideals.push (Offset (s->relative_coordinate (0, X_AXIS) - x0,
+         ideals.push (Offset (x_posns[i],
                               Stem::calc_stem_info (s).ideal_y_));
        }
-      Real y; 
-      Real dydx;
       minimise_least_squares (&dydx, &y, ideals);
 
-      Real dx = last_visible_stem (me)->relative_coordinate (0, X_AXIS) - x0;
-      Real dy = dydx * dx;
+      dy = dydx * dx;
       me->set_grob_property ("least-squares-dy", gh_double2scm (dy));
-
       pos = Interval (y, (y+dy));
     }
 
   me->set_grob_property ("positions", ly_interval2scm (pos));
   return SCM_UNSPECIFIED;
 }
 
+
+/*
+  We can't combine with previous function, since check concave and
+  slope damping comes first.
+ */
+MAKE_SCHEME_CALLBACK (Beam, shift_region_to_valid, 1);
+SCM
+Beam::shift_region_to_valid (SCM grob)
+{
+  Grob *me = unsmob_grob (grob);
+  /*
+    Code dup.
+   */
+  Array<Real> x_posns ;
+  Link_array<Item> stems=
+    Pointer_group_interface__extract_grobs (me, (Item*)0, "stems");
+  Grob *common = stems[0];
+  for (int i=1; i < stems.size (); i++)
+    common = stems[i]->common_refpoint (common, X_AXIS);
+
+  Real x0 = first_visible_stem (me)->relative_coordinate (common, X_AXIS);
+  for (int i=0; i < stems.size (); i++)
+    {
+      Item* s = stems[i];
+
+      Real x = s->relative_coordinate (common, X_AXIS) - x0;
+      x_posns.push (x);
+    }
+  Real dx = last_visible_stem (me)->relative_coordinate (common, X_AXIS) - x0;
+
+  Interval pos = ly_scm2interval ( me->get_grob_property ("positions"));
+  Real dy = pos.delta();
+  Real y = pos[LEFT];
+  Real dydx =dy/dx;
+
+  
+  /*
+    Shift the positions so that we have a chance of finding good
+    quants (i.e. no short stem failures.)
+   */
+  Interval feasible_left_point;
+  feasible_left_point.set_full ();
+  for (int i=0; i < stems.size (); i++)
+    {
+      Item* s = stems[i];
+      if (Stem::invisible_b (s))
+       continue;
+
+
+      Direction d = Stem::get_direction (s);
+
+
+      /*
+       TODO: use real beam space function 
+      */
+      Real left_y = Stem::calc_stem_info (s).shortest_y_
+       - dydx * (x_posns [i] - x0);
+
+      Interval flp ;
+      flp.set_full ();
+      flp[-d] = left_y;
+
+      feasible_left_point.intersect (flp);
+    }
+      
+  if (feasible_left_point.empty_b())
+    {
+      warning (_("Not sure that we can find a nice beam slope (no viable initial configuration found)."));
+    }
+  else if (!feasible_left_point.elem_b(y))
+    {
+      if (isinf (feasible_left_point[DOWN]))
+       y = feasible_left_point[UP] - REGION_SIZE;
+      else if (isinf (feasible_left_point[UP]))
+       y = feasible_left_point[DOWN]+ REGION_SIZE;
+      else
+       y = feasible_left_point.center ();
+    }
+  pos = Interval (y, (y+dy));
+  me->set_grob_property ("positions", ly_interval2scm (pos));
+  return SCM_UNSPECIFIED;
+}
+
+
 MAKE_SCHEME_CALLBACK (Beam, check_concave, 1);
 SCM
 Beam::check_concave (SCM smob)
@@ -1005,6 +1064,9 @@ Beam::slope_damping (SCM smob)
   in POS, and for stem S.
 
   If CORRECT, correct for multiplicity of beam in case of knees.
+
+
+  TODO: junk CORRECT from this.
  */
 Real
 Beam::calc_stem_y (Grob *me, Grob* s, Interval pos, bool correct)
@@ -1012,10 +1074,6 @@ Beam::calc_stem_y (Grob *me, Grob* s, Interval pos, bool correct)
   int beam_multiplicity = get_multiplicity (me);
   int stem_multiplicity = (Stem::duration_log (s) - 2) >? 0;
   
-  int first_multiplicity = (Stem::duration_log (first_visible_stem (me))
-                           - 2) >? 0;
-  int last_multiplicity = (Stem::duration_log (last_visible_stem (me))
-                          - 2) >? 0;
 
   Real thick = gh_scm2double (me->get_grob_property ("thickness"));
   Real interbeam = get_interbeam (me);
index 3dca255c19d77fbdab61d146055c59099ed67596..91198c8a649d9204a8e3c7889c9e5f83ea966b1f 100644 (file)
@@ -35,6 +35,7 @@ public:
   DECLARE_SCHEME_CALLBACK (least_squares, (SCM));
   DECLARE_SCHEME_CALLBACK (check_concave, (SCM));
   DECLARE_SCHEME_CALLBACK (slope_damping, (SCM));
+  DECLARE_SCHEME_CALLBACK (shift_region_to_valid, (SCM));  
   DECLARE_SCHEME_CALLBACK (quanting, (SCM));
   static Real score_slopes_dy (Grob*, Real,Real,Real,Real);
   static Real score_stem_lengths (Link_array<Grob>,
index 61f4688c280012d6b572bb588810075d618350dd..16fa3f2579e21fc0311aa6c693b8ca18be34cf8a 100644 (file)
@@ -807,11 +807,11 @@ Stem::calc_stem_info (Grob*me)
   // to calculate where secondary, ternary beams will go.
   if (multiplicity && first_dir == mydir)
     ideal_y += thick + (multiplicity - 1) * interbeam_f;
-  
-  Real shortest_y = ideal_y; 
 
   ideal_y += stem_length;
-  shortest_y += minimum_length;
+
+  
+  Real shortest_y = ideal_y -stem_length + minimum_length; 
 
   /*
     lowest beam of (UP) beam must never be lower than second staffline
@@ -845,6 +845,16 @@ Stem::calc_stem_info (Grob*me)
     ideal_y -= gh_scm2double (s);
 
   Grob *common = me->common_refpoint (beam, Y_AXIS);
+
+  /*
+    UGH -> THIS CAUSES ASYMETRY: the same beam can start/end on
+    different staffs.
+
+    TODO: the beam calculation should probably also use
+    relative_coordinate() for the Y positions of all beams.
+
+    
+   */
   Real interstaff_f = mydir *
     (me->relative_coordinate (common, Y_AXIS)
      - beam->relative_coordinate (common, Y_AXIS));
index 9d6f5587ad8638e3020f596bfb1996231206624d..dae0d5d8a207d8d6b3c4efaf9c9e574fee800e8a 100644 (file)
        (position-callbacks . (,Beam::least_squares
                               ,Beam::check_concave
                               ,Beam::slope_damping
+                              ,Beam::shift_region_to_valid
                               ,Beam::quanting
                              ))
 
        (molecule-callback . ,Stem::brew_molecule)
        (thickness . 1.3)
        (beamed-lengths . (0.0 2.5 2.0 1.5))
+
+       ;; 
        (beamed-minimum-lengths . (0.0 1.5 1.25 1.0))
 
        ;;  Stems in unnatural (forced) direction should be shortened,