]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/beam.cc
(stop_translation_timestep):
[lilypond.git] / lily / beam.cc
index 03daef5faa7c7807e37a1d309a6886935afa5c03..60b6944a804bc5f5b4889c527f4dbe61f9984267 100644 (file)
@@ -14,8 +14,11 @@ TODO:
   
   - Determine auto knees based on positions if it's set by the user.
 
-  - rounded corners.
+  - the code is littered with * and / staff_space calls for
+    #'positions. Consider moving to real-world coordinates?
 
+    Problematic issue is user tweaks (user tweaks are in staff-coordinates.) 
+  
 Notes:
 
 
@@ -71,11 +74,8 @@ Beam::add_stem (Grob *me, Grob *s)
 Real
 Beam::get_thickness (Grob * me)
 {
-  SCM th = me->get_grob_property ("thickness");
-  if (gh_number_p (th))
-    return gh_scm2double (th)* Staff_symbol_referencer::staff_space (me);
-  else
-    return 0.0;
+  return robust_scm2double (me->get_grob_property ("thickness"), 0)
+    * Staff_symbol_referencer::staff_space (me);
 }
 
 /* Return the translation between 2 adjoining beams. */
@@ -83,8 +83,16 @@ Real
 Beam::get_beam_translation (Grob *me)
 {
   SCM func = me->get_grob_property ("space-function");
-  SCM s = gh_call2 (func, me->self_scm (), scm_int2num (get_beam_count (me)));
-  return gh_scm2double (s);
+
+  if (gh_procedure_p (func))
+    {
+      SCM s = gh_call2 (func, me->self_scm (), scm_int2num (get_beam_count (me)));
+      return gh_scm2double (s);
+    }
+  else
+    {
+      return 0.81;
+    }
 }
 
 /* Maximum beam_count. */
@@ -111,7 +119,7 @@ Beam::space_function (SCM smob, SCM beam_count)
   Grob *me = unsmob_grob (smob);
   
   Real staff_space = Staff_symbol_referencer::staff_space (me);
-  Real line = me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
+  Real line = Staff_symbol_referencer::line_thickness (me);
   Real thickness = get_thickness (me);
   
   Real beam_translation = gh_scm2int (beam_count) < 4
@@ -295,11 +303,17 @@ Beam::connect_beams (Grob *me)
     }
  }
 
+
+/*
+  TODO: should not make beams per stem, but per Y-level.
+ */
 MAKE_SCHEME_CALLBACK (Beam, brew_molecule, 1);
 SCM
 Beam::brew_molecule (SCM grob)
 {
   Grob *me = unsmob_grob (grob);
+  position_beam (me);
+  
   Link_array<Grob> stems=
     Pointer_group_interface__extract_grobs (me, (Grob*)0, "stems");
   Grob* xcommon = common_refpoint_of_array (stems, me, X_AXIS);
@@ -327,6 +341,8 @@ Beam::brew_molecule (SCM grob)
   else
     pos= ly_scm2interval (posns);
 
+
+  pos *= Staff_symbol_referencer::staff_space (me); 
   Real dy = pos.delta ();
   Real dydx = (dy && dx) ? dy/dx : 0;
   
@@ -335,12 +351,9 @@ Beam::brew_molecule (SCM grob)
 
   SCM last_beaming = SCM_EOL;;
   Real last_xposn = -1;
-  Real last_width = -1 ;
+  Real last_stem_width = -1 ;
 
-  Real gap_length =0.0;
-  SCM scm_gap = me->get_grob_property ("gap");
-  if (gh_number_p (scm_gap))
-    gap_length = gh_scm2double (scm_gap);
+  Real gap_length =robust_scm2double ( me->get_grob_property ("gap"), 0.0);
   
   Molecule the_beam;
   Real lt = me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
@@ -351,7 +364,7 @@ Beam::brew_molecule (SCM grob)
       
       SCM this_beaming = st ? st->get_grob_property ("beaming") : SCM_EOL;
       Real xposn = st ? st->relative_coordinate (xcommon, X_AXIS) : 0.0;
-      Real stem_width = st ? gh_scm2double (st->get_grob_property ("thickness")) *lt : 0 ;
+      Real stem_width = st ? robust_scm2double (st->get_grob_property ("thickness"), 1.0) *lt : 0 ;
       Direction stem_dir = st ? to_dir (st->get_grob_property ("direction")) : CENTER;
       /*
        We do the space left of ST, with lfliebertjes pointing to the
@@ -392,29 +405,28 @@ Beam::brew_molecule (SCM grob)
        how much to stick out for beams across linebreaks
        */
       Real break_overshoot = 3.0;
-      Real w = (i>0 && st)? xposn - last_xposn : break_overshoot;
-      Real stem_offset = 0.0;
-      Real width_corr = 0.0;
-      if (i == 1)
-       {
-         stem_offset -= last_width/2;
-         width_corr += last_width/2;
-       }
-         
-      if (i == stems.size() -1)
+      Real w = (i > 0 && st) ? xposn - last_xposn : break_overshoot;
+
+      Real stem_offset =0.0;
+      if (i > 0)
        {
-         width_corr += stem_width/2;
+         w += last_stem_width / 2;
+         stem_offset = -last_stem_width / 2;
        }
 
-         
-      Molecule whole = Lookup::beam (dydx, w + width_corr, thick);
+      if (st)
+       w += stem_width/ 2 ;
+      
+
+      Real blot = me->get_paper ()->get_realvar (ly_symbol2scm ("blotdiameter"));
+      Molecule whole = Lookup::beam (dydx, w, thick, blot);
       Molecule gapped;
 
       int gap_count = 0;
       if (gh_number_p (me->get_grob_property ("gap-count")))
        {
          gap_count = gh_scm2int (me->get_grob_property ("gap-count"));
-         gapped = Lookup::beam (dydx, w + width_corr - 2 * gap_length, thick);
+         gapped = Lookup::beam (dydx, w - 2 * gap_length, thick, blot);
 
          full_beams.sort (default_compare);
          if (stem_dir == UP)
@@ -459,7 +471,7 @@ Beam::brew_molecule (SCM grob)
          Real w = (i>0 && st) ? (xposn - last_xposn) : break_overshoot;
          w = w/2 <? nw_f;
 
-         Molecule half = Lookup::beam (dydx, w, thick);
+         Molecule half = Lookup::beam (dydx, w, thick, blot);
          for (int j = lfliebertjes.size(); j--;)
            {
              Molecule b (half);
@@ -478,7 +490,7 @@ Beam::brew_molecule (SCM grob)
 
 
       last_xposn = xposn;
-      last_width = stem_width;
+      last_stem_width = stem_width;
       last_beaming = this_beaming;
     }
 
@@ -786,22 +798,32 @@ SCM
 Beam::after_line_breaking (SCM smob)
 {
   Grob *me = unsmob_grob (smob);
-  
+
+  position_beam (me);
+  return SCM_UNSPECIFIED;
+}
+
+void
+Beam::position_beam (Grob *me)
+{
+  if (to_boolean (me->get_grob_property ("positioning-done")))
+    return ;
+
+  me->set_grob_property ("positioning-done", SCM_BOOL_T);
+
   /* Copy to mutable list. */
   SCM s = ly_deep_copy (me->get_grob_property ("positions"));
   me->set_grob_property ("positions", s);
 
   if (ly_car (s) == SCM_BOOL_F)
     {
-
       // one wonders if such genericity is necessary  --hwn.
       SCM callbacks = me->get_grob_property ("position-callbacks");
       for (SCM i = callbacks; gh_pair_p (i); i = ly_cdr (i))
-       gh_call1 (ly_car (i), smob);
+       gh_call1 (ly_car (i), me->self_scm ());
     }
 
   set_stem_lengths (me);  
-  return SCM_UNSPECIFIED;
 }
 
 
@@ -871,7 +893,7 @@ Beam::least_squares (SCM smob)
        {
          /* FIXME. -> UP */
          Direction d = (Direction) (sign (chord.delta ()) * UP);
-         pos[d] = gh_scm2double (me->get_grob_property ("thickness")) / 2;
+         pos[d] = get_thickness (me) / 2;
          pos[-d] = - pos[d];
        }
       else
@@ -885,12 +907,6 @@ Beam::least_squares (SCM smob)
         where the second part goes.
        */
 
-      y = pos[LEFT];
-      dy = pos[RIGHT]- y;
-      dydx = dy/dx;
-
-
-
     }
   else
     {
@@ -913,6 +929,11 @@ Beam::least_squares (SCM smob)
       pos = Interval (y, (y+dy));
     }
 
+  /*
+    "position" is relative to the staff.
+   */
+  pos *= 1/ Staff_symbol_referencer::staff_space (me); 
+  
   me->set_grob_property ("positions", ly_interval2scm (pos));
  
   return SCM_UNSPECIFIED;
@@ -962,6 +983,9 @@ Beam::shift_region_to_valid (SCM grob)
   Real dx = lvs->relative_coordinate (commonx, X_AXIS) - x0;
 
   Interval pos = ly_scm2interval ( me->get_grob_property ("positions"));
+
+  pos  *= Staff_symbol_referencer::staff_space (me);
+  
   Real dy = pos.delta();
   Real y = pos[LEFT];
   Real dydx =dy/dx;
@@ -1013,7 +1037,10 @@ Beam::shift_region_to_valid (SCM grob)
       else
        y = feasible_left_point.center ();
     }
+  
   pos = Interval (y, (y+dy));
+  pos *= 1/ Staff_symbol_referencer::staff_space (me);
+  
   me->set_grob_property ("positions", ly_interval2scm (pos));
   return SCM_UNSPECIFIED;
 }
@@ -1137,6 +1164,8 @@ Beam::check_concave (SCM smob)
     {
       Interval pos = ly_scm2interval (me->get_grob_property ("positions"));
       Real r = pos.linear_combination (0);
+
+      r /= Staff_symbol_referencer::staff_space (me);
       me->set_grob_property ("positions", ly_interval2scm (Interval (r, r)));
       me->set_grob_property ("least-squares-dy", gh_double2scm (0));
     }
@@ -1162,6 +1191,8 @@ Beam::slope_damping (SCM smob)
   if (damping)
     {
       Interval pos = ly_scm2interval (me->get_grob_property ("positions"));
+      pos *= Staff_symbol_referencer::staff_space (me);
+      
       Real dy = pos.delta ();
 
       Grob *fvs  = first_visible_stem (me);
@@ -1178,6 +1209,8 @@ Beam::slope_damping (SCM smob)
       Real damped_dy = dydx * dx;
       pos[LEFT] += (dy - damped_dy) / 2;
       pos[RIGHT] -= (dy - damped_dy) / 2;
+
+      pos *= 1/ Staff_symbol_referencer::staff_space (me);
       
       me->set_grob_property ("positions", ly_interval2scm (pos));
     }
@@ -1263,6 +1296,7 @@ Beam::set_stem_lengths (Grob *me)
   
   Interval pos = ly_scm2interval (me->get_grob_property ("positions"));
   Real staff_space = Staff_symbol_referencer::staff_space (me);
+  pos  *= staff_space;
 
   bool gap = false;
   Real thick =0.0;
@@ -1423,6 +1457,9 @@ Beam::rest_collision_callback (SCM element_smob, SCM axis)
 {
   Grob *rest = unsmob_grob (element_smob);
   Axis a = (Axis) gh_scm2int (axis);
+
+  if (gh_number_p (rest->get_grob_property ("staff-position")))
+    return gh_int2scm (0);
   
   assert (a == Y_AXIS);
 
@@ -1440,55 +1477,51 @@ Beam::rest_collision_callback (SCM element_smob, SCM axis)
   SCM s = beam->get_grob_property ("positions");
   if (gh_pair_p (s) && gh_number_p (ly_car (s)))
     pos = ly_scm2interval (s);
+  Real staff_space = Staff_symbol_referencer::staff_space (rest);
+
+  pos  *= staff_space;
+  
 
   Real dy = pos.delta ();
+  
   // ugh -> use commonx
   Real x0 = first_visible_stem (beam)->relative_coordinate (0, X_AXIS);
   Real dx = last_visible_stem (beam)->relative_coordinate (0, X_AXIS) - x0;
   Real dydx = dy && dx ? dy/dx : 0;
   
   Direction d = Stem::get_direction (stem);
-  Real stem_y = (pos[LEFT]
-                + (stem->relative_coordinate (0, X_AXIS) - x0) * dydx)
-    * d;
+  Real stem_y = pos[LEFT] + (stem->relative_coordinate (0, X_AXIS) - x0) * dydx;
   
   Real beam_translation = get_beam_translation (beam);
-  Real beam_thickness = gh_scm2double (beam->get_grob_property ("thickness"));
+  Real beam_thickness = Beam::get_thickness (beam);
+  
   int beam_count = get_direction_beam_count (beam, d);
-  Real height_of_my_beams = beam_thickness
+  Real height_of_my_beams = beam_thickness / 2
     + (beam_count - 1) * beam_translation;
-  Real beam_y = stem_y - height_of_my_beams + beam_thickness / 2.0;
+  Real beam_y = stem_y - d * height_of_my_beams;
 
-  Real staff_space = Staff_symbol_referencer::staff_space (rest);
+  Grob *common_y = rest->common_refpoint (beam, Y_AXIS);
 
-  /* Better calculate relative-distance directly, rather than using
-     rest_dim? */
-  Grob *common_x = rest->common_refpoint (beam, Y_AXIS);
-  Real rest_dim = rest->extent (common_x, Y_AXIS)[d] / staff_space * d;
+  Real rest_dim = rest->extent (common_y, Y_AXIS)[d];
+  Real minimum_distance =
+    staff_space * robust_scm2double (rest->get_grob_property ("minimum-distance"), 0.0);
 
-  Real minimum_distance = gh_scm2double
-    (rest->get_grob_property ("minimum-beam-collision-distance"));
+  Real shift = d * (((beam_y - d * minimum_distance) - rest_dim) * d  <? 0.0);
 
-  Real distance = beam_y - rest_dim;
-  Real shift = 0;
-  if (distance < 0)
-    shift = minimum_distance - distance;
-  else if (minimum_distance > distance)
-    shift = minimum_distance - distance;
-      
-  int stafflines = Staff_symbol_referencer::line_count (rest);
+  shift /= staff_space;
+  Real rad = Staff_symbol_referencer::line_count (rest) * staff_space / 2;
 
   /* Always move discretely by half spaces */
-  Real discrete_shift = ceil (shift * 2.0) / 2.0;
+  shift = ceil (fabs (shift * 2.0)) / 2.0 * sign (shift);
 
   /* Inside staff, move by whole spaces*/
-  if ((rest->extent (common_x, Y_AXIS)[d] + discrete_shift) * d
-      < stafflines / 2.0
-      ||(rest->extent (common_x, Y_AXIS)[-d] + discrete_shift) * -d
-      < stafflines / 2.0)
-    discrete_shift = ceil (discrete_shift);
+  if ((rest->extent (common_y, Y_AXIS)[d] + staff_space * shift) * d
+      < rad
+      || (rest->extent (common_y, Y_AXIS)[-d] + staff_space * shift) * -d
+      < rad)
+    shift = ceil (fabs (shift)) *sign (shift);
 
-  return gh_double2scm (-d * discrete_shift);
+  return gh_double2scm (staff_space * shift);
 }
 
 bool
@@ -1553,6 +1586,6 @@ ADD_INTERFACE (Beam, "beam-interface",
 "the ideal slope, how close the result is to the ideal stems, etc.). We "
 "take the best scoring combination. "
 ,
-  "knee position-callbacks concaveness-gap concaveness-threshold dir-function quant-score auto-knee-gap gap gap-count chord-tremolo beamed-stem-shorten shorten least-squares-dy damping flag-width-function neutral-direction positions space-function thickness");
+  "knee positioning-done position-callbacks concaveness-gap concaveness-threshold dir-function quant-score auto-knee-gap gap gap-count chord-tremolo beamed-stem-shorten shorten least-squares-dy damping flag-width-function neutral-direction positions space-function thickness");