]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/beam.cc
biem fix
[lilypond.git] / lily / beam.cc
index 15df1eaf68f5644e3b7b9ce3a174ac0f423b58ff..c24d348c00052db936e7a44b2013e1154c9e3de2 100644 (file)
   * Rewrite stem_beams.
 
   * Use Number_pair i.s.o Interval to represent (yl, yr).
   * 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" 
 #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 DAMPING_DIRECTIION_PENALTY = 800;
 const int MUSICAL_DIRECTION_FACTOR = 400;
 const int IDEAL_SLOPE_FACTOR = 10;
+const int REGION_SIZE = 2;
 
 
 static Real
 
 
 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;
 
       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);
       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];
 
     }
 
   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)
   /*
     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));
     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;
   
   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;
 
   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;
       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_;
 
       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_);
 
   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 ())
     {
   
   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.
 
        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)
        */
       /* 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;
        }
        {
          pos = ideal;
        }
+
+      y = pos[LEFT];
+      dy = pos[RIGHT]- y;
+      dydx = dy/dx;
     }
   else
     {
       Array<Offset> ideals;
     }
   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;
       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_));
        }
                               Stem::calc_stem_info (s).ideal_y_));
        }
-      Real y; 
-      Real dydx;
       minimise_least_squares (&dydx, &y, ideals);
 
       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));
       me->set_grob_property ("least-squares-dy", gh_double2scm (dy));
-
       pos = Interval (y, (y+dy));
     }
 
   me->set_grob_property ("positions", ly_interval2scm (pos));
       pos = Interval (y, (y+dy));
     }
 
   me->set_grob_property ("positions", ly_interval2scm (pos));
   return SCM_UNSPECIFIED;
 }
 
   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)
 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.
   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)
  */
 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 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);
 
   Real thick = gh_scm2double (me->get_grob_property ("thickness"));
   Real interbeam = get_interbeam (me);