]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/beam.cc
* lily/context.cc (Context): take key argument in ctor.
[lilypond.git] / lily / beam.cc
index 91b0fb55434813ae54de019268432ddbbbdbc220..b8d5018927029fe1d53e02c56a827651ddfeb561 100644 (file)
@@ -28,6 +28,7 @@ Notes:
 
 #include <math.h> // tanh.
 
 
 #include <math.h> // tanh.
 
+#include "interval-set.hh"
 #include "stencil.hh" 
 #include "directional-element-interface.hh"
 #include "beaming.hh"
 #include "stencil.hh" 
 #include "directional-element-interface.hh"
 #include "beaming.hh"
@@ -35,7 +36,7 @@ Notes:
 #include "misc.hh"
 #include "least-squares.hh"
 #include "stem.hh"
 #include "misc.hh"
 #include "least-squares.hh"
 #include "stem.hh"
-#include "paper-def.hh"
+#include "output-def.hh"
 #include "lookup.hh"
 #include "group-interface.hh"
 #include "staff-symbol-referencer.hh"
 #include "lookup.hh"
 #include "group-interface.hh"
 #include "staff-symbol-referencer.hh"
@@ -43,8 +44,6 @@ Notes:
 #include "spanner.hh"
 #include "warn.hh"
 
 #include "spanner.hh"
 #include "warn.hh"
 
-bool debug_beam_quanting_flag;
-
 
 #if DEBUG_QUANTING
 #include "text-item.hh"  // debug output.
 
 #if DEBUG_QUANTING
 #include "text-item.hh"  // debug output.
@@ -79,10 +78,10 @@ Beam::get_beam_translation (Grob *me)
 {
   SCM func = me->get_property ("space-function");
 
 {
   SCM func = me->get_property ("space-function");
 
-  if (is_procedure (func))
+  if (ly_c_procedure_p (func))
     {
       SCM s = scm_call_2 (func, me->self_scm (), scm_int2num (get_beam_count (me)));
     {
       SCM s = scm_call_2 (func, me->self_scm (), scm_int2num (get_beam_count (me)));
-      return ly_scm2double (s);
+      return scm_to_double (s);
     }
   else
     {
     }
   else
     {
@@ -95,9 +94,9 @@ int
 Beam::get_beam_count (Grob *me) 
 {
   int m = 0;
 Beam::get_beam_count (Grob *me) 
 {
   int m = 0;
-  for (SCM s = me->get_property ("stems"); is_pair (s); s = ly_cdr (s))
+  for (SCM s = me->get_property ("stems"); scm_is_pair (s); s = scm_cdr (s))
     {
     {
-      Grob *stem = unsmob_grob (ly_car (s));
+      Grob *stem = unsmob_grob (scm_car (s));
       m = m >? (Stem::beam_multiplicity (stem).length () + 1);
     }
   return m;
       m = m >? (Stem::beam_multiplicity (stem).length () + 1);
     }
   return m;
@@ -117,7 +116,7 @@ Beam::space_function (SCM smob, SCM beam_count)
   Real line = Staff_symbol_referencer::line_thickness (me);
   Real thickness = get_thickness (me);
   
   Real line = Staff_symbol_referencer::line_thickness (me);
   Real thickness = get_thickness (me);
   
-  Real beam_translation = ly_scm2int (beam_count) < 4
+  Real beam_translation = scm_to_int (beam_count) < 4
     ? (2*staff_space + line - thickness) / 2.0
     : (3*staff_space + line - thickness) / 3.0;
   
     ? (2*staff_space + line - thickness) / 2.0
     : (3*staff_space + line - thickness) / 3.0;
   
@@ -155,7 +154,7 @@ Beam::before_line_breaking (SCM smob)
        {
          me->warning (_ ("removing beam with less than two stems"));
 
        {
          me->warning (_ ("removing beam with less than two stems"));
 
-         unsmob_grob (ly_car (stems))->set_property ("beam", SCM_EOL);
+         unsmob_grob (scm_car (stems))->set_property ("beam", SCM_EOL);
          me->suicide ();
 
          return SCM_UNSPECIFIED;
          me->suicide ();
 
          return SCM_UNSPECIFIED;
@@ -201,7 +200,7 @@ position_with_maximal_common_beams (SCM left_beaming, SCM right_beaming,
                                    Direction left_dir,
                                    Direction right_dir)
 {
                                    Direction left_dir,
                                    Direction right_dir)
 {
-  Slice lslice = int_list_to_slice (ly_cdr (left_beaming));
+  Slice lslice = int_list_to_slice (scm_cdr (left_beaming));
 
   int best_count = 0;
   int best_start = 0;
 
   int best_count = 0;
   int best_start = 0;
@@ -209,9 +208,9 @@ position_with_maximal_common_beams (SCM left_beaming, SCM right_beaming,
        (i - lslice[left_dir])* left_dir <= 0 ; i+= left_dir) 
     {
       int count =0;
        (i - lslice[left_dir])* left_dir <= 0 ; i+= left_dir) 
     {
       int count =0;
-      for ( SCM s = ly_car (right_beaming); is_pair (s); s = ly_cdr (s))
+      for ( SCM s = scm_car (right_beaming); scm_is_pair (s); s = scm_cdr (s))
        {
        {
-         int k = - right_dir * ly_scm2int (ly_car (s)) + i;
+         int k = - right_dir * scm_to_int (scm_car (s)) + i;
          if (scm_c_memq (scm_int2num (k), left_beaming) != SCM_BOOL_F)
            count ++;
        }
          if (scm_c_memq (scm_int2num (k), left_beaming) != SCM_BOOL_F)
            count ++;
        }
@@ -242,7 +241,7 @@ Beam::connect_beams (Grob *me)
       SCM this_beaming = this_stem->get_property ("beaming");
 
       Direction this_dir = get_grob_direction (this_stem);
       SCM this_beaming = this_stem->get_property ("beaming");
 
       Direction this_dir = get_grob_direction (this_stem);
-      if (is_pair (last_beaming) && is_pair (this_beaming))
+      if (scm_is_pair (last_beaming) && scm_is_pair (this_beaming))
        {
          int start_point = position_with_maximal_common_beams
            (last_beaming, this_beaming,
        {
          int start_point = position_with_maximal_common_beams
            (last_beaming, this_beaming,
@@ -257,10 +256,10 @@ Beam::connect_beams (Grob *me)
              
              new_slice.set_empty ();
              SCM s = index_get_cell (this_beaming, d);
              
              new_slice.set_empty ();
              SCM s = index_get_cell (this_beaming, d);
-             for (; is_pair (s); s = ly_cdr (s))
+             for (; scm_is_pair (s); s = scm_cdr (s))
                {
                  int new_beam_pos =
                {
                  int new_beam_pos =
-                   start_point - this_dir * ly_scm2int (ly_car (s));
+                   start_point - this_dir * scm_to_int (scm_car (s));
 
                  new_slice.add_point (new_beam_pos);
                  scm_set_car_x (s, scm_int2num (new_beam_pos));
 
                  new_slice.add_point (new_beam_pos);
                  scm_set_car_x (s, scm_int2num (new_beam_pos));
@@ -276,10 +275,10 @@ Beam::connect_beams (Grob *me)
       else
        {
          scm_set_car_x ( this_beaming, SCM_EOL);
       else
        {
          scm_set_car_x ( this_beaming, SCM_EOL);
-         SCM s = ly_cdr (this_beaming);
-         for (; is_pair (s); s = ly_cdr (s))
+         SCM s = scm_cdr (this_beaming);
+         for (; scm_is_pair (s); s = scm_cdr (s))
            {
            {
-             int np = - this_dir * ly_scm2int (ly_car (s));
+             int np = - this_dir * scm_to_int (scm_car (s));
              scm_set_car_x (s, scm_int2num (np));
              last_int.add_point (np);
            }
              scm_set_car_x (s, scm_int2num (np));
              last_int.add_point (np);
            }
@@ -290,7 +289,7 @@ Beam::connect_beams (Grob *me)
          scm_set_cdr_x (this_beaming, SCM_EOL);
        }
 
          scm_set_cdr_x (this_beaming, SCM_EOL);
        }
 
-      if (scm_ilength (ly_cdr (this_beaming)) > 0)
+      if (scm_ilength (scm_cdr (this_beaming)) > 0)
        {
          last_beaming = this_beaming;
          last_dir = this_dir;
        {
          last_beaming = this_beaming;
          last_dir = this_dir;
@@ -339,10 +338,10 @@ Beam::print (SCM grob)
   else
     pos= ly_scm2realdrul (posns);
 
   else
     pos= ly_scm2realdrul (posns);
 
-  scale_drul (  &pos,  Staff_symbol_referencer::staff_space (me));
+  scale_drul (&pos,  Staff_symbol_referencer::staff_space (me));
   
   Real dy = pos[RIGHT] - pos[LEFT];
   
   Real dy = pos[RIGHT] - pos[LEFT];
-  Real dydx = (dy && dx) ? dy/dx : 0;
+  Real slope = (dy && dx) ? dy/dx : 0;
   
   Real thick = get_thickness (me);
   Real bdy = get_beam_translation (me);
   
   Real thick = get_thickness (me);
   Real bdy = get_beam_translation (me);
@@ -351,10 +350,10 @@ Beam::print (SCM grob)
   Real last_xposn = -1;
   Real last_stem_width = -1 ;
 
   Real last_xposn = -1;
   Real last_stem_width = -1 ;
 
-  Real gap_length =robust_scm2double ( me->get_property ("gap"), 0.0);
+  Real gap_length = robust_scm2double (me->get_property ("gap"), 0.0);
   
   Stencil the_beam;
   
   Stencil the_beam;
-  Real lt = me->get_paper ()->get_dimension (ly_symbol2scm ("linethickness"));
+  Real lt = me->get_layout ()->get_dimension (ly_symbol2scm ("linethickness"));
   
   for (int i = 0; i<= stems.size (); i++)
     {
   
   for (int i = 0; i<= stems.size (); i++)
     {
@@ -369,18 +368,18 @@ Beam::print (SCM grob)
        right from the left stem, and rfliebertjes pointing left from
        right stem.
        */
        right from the left stem, and rfliebertjes pointing left from
        right stem.
        */
-      SCM left = (i>0) ? ly_cdr (last_beaming) : SCM_EOL;
-      SCM right = st ? ly_car (this_beaming) : SCM_EOL;
+      SCM left = (i > 0) ? scm_cdr (last_beaming) : SCM_EOL;
+      SCM right = st ? scm_car (this_beaming) : SCM_EOL;
 
       Array<int> full_beams;
       Array<int> lfliebertjes;
       Array<int> rfliebertjes;   
 
       for (SCM s = left;
 
       Array<int> full_beams;
       Array<int> lfliebertjes;
       Array<int> rfliebertjes;   
 
       for (SCM s = left;
-          is_pair (s); s =ly_cdr (s))
+          scm_is_pair (s); s =scm_cdr (s))
        {
        {
-         int b = ly_scm2int (ly_car (s));
-         if (scm_c_memq (ly_car (s), right) != SCM_BOOL_F)
+         int b = scm_to_int (scm_car (s));
+         if (scm_c_memq (scm_car (s), right) != SCM_BOOL_F)
            {
              full_beams.push (b);
            }
            {
              full_beams.push (b);
            }
@@ -390,10 +389,10 @@ Beam::print (SCM grob)
            }
        }
       for (SCM s = right;
            }
        }
       for (SCM s = right;
-          is_pair (s); s =ly_cdr (s))
+          scm_is_pair (s); s =scm_cdr (s))
        {
        {
-         int b = ly_scm2int (ly_car (s));
-         if (scm_c_memq (ly_car (s), left) == SCM_BOOL_F)
+         int b = scm_to_int (scm_car (s));
+         if (scm_c_memq (scm_car (s), left) == SCM_BOOL_F)
            {
              rfliebertjes.push (b);
            }
            {
              rfliebertjes.push (b);
            }
@@ -416,15 +415,15 @@ Beam::print (SCM grob)
        w += stem_width/ 2 ;
       
 
        w += stem_width/ 2 ;
       
 
-      Real blot = me->get_paper ()->get_dimension (ly_symbol2scm ("blotdiameter"));
-      Stencil whole = Lookup::beam (dydx, w, thick, blot);
+      Real blot = me->get_layout ()->get_dimension (ly_symbol2scm ("blotdiameter"));
+      Stencil whole = Lookup::beam (slope, w, thick, blot);
       Stencil gapped;
 
       int gap_count = 0;
       Stencil gapped;
 
       int gap_count = 0;
-      if (is_number (me->get_property ("gap-count")))
+      if (scm_is_number (me->get_property ("gap-count")))
        {
        {
-         gap_count = ly_scm2int (me->get_property ("gap-count"));
-         gapped = Lookup::beam (dydx, w - 2 * gap_length, thick, blot);
+         gap_count = scm_to_int (me->get_property ("gap-count"));
+         gapped = Lookup::beam (slope, w - 2 * gap_length, thick, blot);
 
          full_beams.sort (default_compare);
          if (stem_dir == UP)
 
          full_beams.sort (default_compare);
          if (stem_dir == UP)
@@ -442,7 +441,7 @@ Beam::print (SCM grob)
              b.translate_axis (gap_length, X_AXIS);
            }
          b.translate_axis (last_xposn -  x0 + stem_offset, X_AXIS);
              b.translate_axis (gap_length, X_AXIS);
            }
          b.translate_axis (last_xposn -  x0 + stem_offset, X_AXIS);
-         b.translate_axis (dydx * (last_xposn - x0) + bdy * full_beams[j], Y_AXIS);
+         b.translate_axis (slope * (last_xposn - x0) + bdy * full_beams[j], Y_AXIS);
 
          the_beam.add_stencil (b);           
        }
 
          the_beam.add_stencil (b);           
        }
@@ -457,7 +456,7 @@ Beam::print (SCM grob)
 
              SCM proc = me->get_property ("flag-width-function");
              SCM result = scm_call_1 (proc, scm_int2num (t));
 
              SCM proc = me->get_property ("flag-width-function");
              SCM result = scm_call_1 (proc, scm_int2num (t));
-             nw_f = ly_scm2double (result);
+             nw_f = scm_to_double (result);
            }
          else
            nw_f = break_overshoot / 2;
            }
          else
            nw_f = break_overshoot / 2;
@@ -481,20 +480,20 @@ Beam::print (SCM grob)
            lw = me->get_bound (RIGHT)->relative_coordinate (xcommon, X_AXIS)
              - last_xposn;
 
            lw = me->get_bound (RIGHT)->relative_coordinate (xcommon, X_AXIS)
              - last_xposn;
 
-         Stencil rhalf = Lookup::beam (dydx, rw, thick, blot);
-         Stencil lhalf = Lookup::beam (dydx, lw, thick, blot);
+         Stencil rhalf = Lookup::beam (slope, rw, thick, blot);
+         Stencil lhalf = Lookup::beam (slope, lw, thick, blot);
          for (int j = lfliebertjes.size (); j--;)
            {
              Stencil b (lhalf);
              b.translate_axis (last_xposn -  x0, X_AXIS);
          for (int j = lfliebertjes.size (); j--;)
            {
              Stencil b (lhalf);
              b.translate_axis (last_xposn -  x0, X_AXIS);
-             b.translate_axis (dydx * (last_xposn-x0) + bdy * lfliebertjes[j], Y_AXIS);
+             b.translate_axis (slope * (last_xposn-x0) + bdy * lfliebertjes[j], Y_AXIS);
              the_beam.add_stencil (b);       
            }
          for (int j = rfliebertjes.size (); j--;)
            {
              Stencil b (rhalf);
              b.translate_axis (xposn -  x0 - rw , X_AXIS);
              the_beam.add_stencil (b);       
            }
          for (int j = rfliebertjes.size (); j--;)
            {
              Stencil b (rhalf);
              b.translate_axis (xposn -  x0 - rw , X_AXIS);
-             b.translate_axis (dydx * (xposn-x0 -rw) + bdy * rfliebertjes[j], Y_AXIS);
+             b.translate_axis (slope * (xposn-x0 -rw) + bdy * rfliebertjes[j], Y_AXIS);
              the_beam.add_stencil (b);       
            }
        }
              the_beam.add_stencil (b);       
            }
        }
@@ -510,8 +509,8 @@ Beam::print (SCM grob)
 
 #if (DEBUG_QUANTING)
   SCM quant_score = me->get_property ("quant-score");
 
 #if (DEBUG_QUANTING)
   SCM quant_score = me->get_property ("quant-score");
-  if (debug_beam_quanting_flag
-      && is_string (quant_score))
+  if (to_boolean (me->get_layout ()->lookup_variable (ly_symbol2scm ("debug-beam-quanting")))
+      && scm_is_string (quant_score))
     {
       
       /*
     {
       
       /*
@@ -522,13 +521,13 @@ Beam::print (SCM grob)
       String str;
       SCM properties = Font_interface::text_font_alist_chain (me);
 
       String str;
       SCM properties = Font_interface::text_font_alist_chain (me);
 
-      Stencil tm = *unsmob_stencil (Text_item::interpret_markup
-        (me->get_paper ()->self_scm (), properties, quant_score));
-      the_beam.add_at_edge (Y_AXIS, UP, tm, 5.0, 0);
+      Direction stem_dir = stems.size() ? to_dir (stems[0]->get_property ("direction")) : UP;
+    
+      Stencil tm = *unsmob_stencil (Text_interface::interpret_markup
+        (me->get_layout ()->self_scm (), properties, quant_score));
+      the_beam.add_at_edge (Y_AXIS, stem_dir, tm, 1.0, 0);
     }
 #endif
     }
 #endif
-    
-  
   
   return the_beam.smobbed_copy ();
 }
   
   return the_beam.smobbed_copy ();
 }
@@ -548,7 +547,7 @@ Beam::get_default_dir (Grob *me)
   Link_array<Grob> stems=
        Pointer_group_interface__extract_grobs (me, (Grob*)0, "stems");
 
   Link_array<Grob> stems=
        Pointer_group_interface__extract_grobs (me, (Grob*)0, "stems");
 
-  for (int i=0; i <stems.size (); i++)
+  for (int i=0; i < stems.size (); i++)
     do {
       Grob *s = stems[i];
       Direction sd = get_grob_direction (s);
     do {
       Grob *s = stems[i];
       Direction sd = get_grob_direction (s);
@@ -570,7 +569,7 @@ Beam::get_default_dir (Grob *me)
                    scm_cons (scm_int2num (total[UP]),
                             scm_int2num (total[DOWN])));
 
                    scm_cons (scm_int2num (total[UP]),
                             scm_int2num (total[DOWN])));
 
-  if (is_number (s) && ly_scm2int (s))
+  if (scm_is_number (s) && scm_to_int (s))
     return to_dir (s);
   
   /* If dir is not determined: get default */
     return to_dir (s);
   
   /* If dir is not determined: get default */
@@ -597,65 +596,6 @@ Beam::set_stem_directions (Grob *me, Direction d)
     }
 }
 
     }
 }
 
-/*
-  A union of intervals in the real line.
-
-  Abysmal performance (quadratic) for large N, hopefully we don't have
-  that large N. In any case, this should probably be rewritten to use
-  a balanced tree.
- */
-struct Int_set
-{
-  Array<Interval> allowed_regions_;
-
-  Int_set ()
-  {
-    set_full ();
-  }
-
-  void set_full ()
-  {
-    allowed_regions_.clear ();
-    Interval s;
-    s.set_full ();
-    allowed_regions_.push (s);
-  }
-
-  void remove_interval (Interval rm)
-  {
-    for (int i = 0; i < allowed_regions_.size (); )
-      {
-       Interval s = rm;
-
-       s.intersect (allowed_regions_[i]);
-
-       if (!s.is_empty ())
-         {
-           Interval before = allowed_regions_[i];
-           Interval after = allowed_regions_[i];
-
-           before[RIGHT] = s[LEFT];
-           after[LEFT] = s[RIGHT];
-
-           if (!before.is_empty () && before.length () > 0.0)
-             {
-               allowed_regions_.insert (before, i);
-               i++;
-             }
-           allowed_regions_.del (i);
-           if (!after.is_empty () && after.length () > 0.0)
-             {
-               allowed_regions_.insert (after, i);
-               i++;
-             }
-         }
-       else
-         i++;
-      }
-  }
-};
-
-
 /*
   Only try horizontal beams for knees.  No reliable detection of
   anything else is possible here, since we don't know funky-beaming
 /*
   Only try horizontal beams for knees.  No reliable detection of
   anything else is possible here, since we don't know funky-beaming
@@ -666,12 +606,12 @@ void
 Beam::consider_auto_knees (Grob* me)
 {
   SCM scm = me->get_property ("auto-knee-gap");
 Beam::consider_auto_knees (Grob* me)
 {
   SCM scm = me->get_property ("auto-knee-gap");
-  if (!is_number (scm))
+  if (!scm_is_number (scm))
     return ;
 
     return ;
 
-  Real threshold = ly_scm2double (scm);
+  Real threshold = scm_to_double (scm);
   
   
-  Int_set gaps;
+  Interval_set gaps;
 
   gaps.set_full ();
 
 
   gaps.set_full ();
 
@@ -791,7 +731,7 @@ Beam::set_stem_shorten (Grob *me)
   
   SCM shorten_elt =
     robust_list_ref (beam_count -1, shorten_list);
   
   SCM shorten_elt =
     robust_list_ref (beam_count -1, shorten_list);
-  Real shorten_f = ly_scm2double (shorten_elt) * staff_space;
+  Real shorten_f = scm_to_double (shorten_elt) * staff_space;
 
   /* your similar cute comment here */
   shorten_f *= forced_fraction;
 
   /* your similar cute comment here */
   shorten_f *= forced_fraction;
@@ -817,6 +757,8 @@ Beam::after_line_breaking (SCM smob)
 void
 Beam::position_beam (Grob *me)
 {
 void
 Beam::position_beam (Grob *me)
 {
+  if (!me->is_live ())
+    return ;
   if (to_boolean (me->get_property ("positioning-done")))
     return ;
 
   if (to_boolean (me->get_property ("positioning-done")))
     return ;
 
@@ -826,18 +768,41 @@ Beam::position_beam (Grob *me)
   SCM s = ly_deep_copy (me->get_property ("positions"));
   me->set_property ("positions", s);
 
   SCM s = ly_deep_copy (me->get_property ("positions"));
   me->set_property ("positions", s);
 
-  if (ly_car (s) == SCM_BOOL_F)
+  if (scm_car (s) == SCM_BOOL_F)
     {
       // one wonders if such genericity is necessary  --hwn.
       SCM callbacks = me->get_property ("position-callbacks");
     {
       // one wonders if such genericity is necessary  --hwn.
       SCM callbacks = me->get_property ("position-callbacks");
-      for (SCM i = callbacks; is_pair (i); i = ly_cdr (i))
-       scm_call_1 (ly_car (i), me->self_scm ());
+      for (SCM i = callbacks; scm_is_pair (i); i = scm_cdr (i))
+       scm_call_1 (scm_car (i), me->self_scm ());
     }
 
   set_stem_lengths (me);  
 }
 
 
     }
 
   set_stem_lengths (me);  
 }
 
 
+void
+set_minimum_dy (Grob *me, Real * dy)
+{
+  if (*dy)
+    {
+      /*
+       If dy is smaller than the smallest quant, we
+       get absurd direction-sign penalties. 
+      */
+         
+      Real ss = Staff_symbol_referencer::staff_space (me);
+      Real thickness = Beam::get_thickness (me) / ss ;
+      Real slt = Staff_symbol_referencer::line_thickness (me) / ss;
+      Real sit = (thickness - slt) / 2;
+      Real inter = 0.5;
+      Real hang = 1.0 - (thickness - slt) / 2;
+         
+      *dy = sign (*dy) * (fabs (*dy)
+                       >?
+                       (sit <? inter <? hang));
+    }
+}
+
 /*
   Compute  a first approximation to the beam slope.
  */
 /*
   Compute  a first approximation to the beam slope.
  */
@@ -885,7 +850,7 @@ Beam::least_squares (SCM smob)
 
   
   Real y =0;  
 
   
   Real y =0;  
-  Real dydx = 0;
+  Real slope = 0;
   Real dy = 0;
   
   if (!ideal.delta ())
   Real dy = 0;
   
   if (!ideal.delta ())
@@ -914,11 +879,11 @@ Beam::least_squares (SCM smob)
 
       /*
        For broken beams this doesn't work well. In this case, the
 
       /*
        For broken beams this doesn't work well. In this case, the
-        slope esp. of the first part of a broken beam should predict
-        where the second part goes.
-       */
+       slope esp. of the first part of a broken beam should predict
+       where the second part goes.
+      */
       me->set_property ("least-squares-dy",
       me->set_property ("least-squares-dy",
-                            scm_make_real (pos[RIGHT] - pos[LEFT]));
+                       scm_make_real (pos[RIGHT] - pos[LEFT]));
     }
   else
     {
     }
   else
     {
@@ -934,9 +899,11 @@ Beam::least_squares (SCM smob)
                               - my_y));
        }
       
                               - my_y));
        }
       
-      minimise_least_squares (&dydx, &y, ideals);
+      minimise_least_squares (&slope, &y, ideals);
 
 
-      dy = dydx * dx;
+      dy = slope * dx;
+
+      set_minimum_dy (me,&dy);
       me->set_property ("least-squares-dy", scm_make_real (dy));
       pos = Interval (y, (y+dy));
     }
       me->set_property ("least-squares-dy", scm_make_real (dy));
       pos = Interval (y, (y+dy));
     }
@@ -956,10 +923,10 @@ Beam::least_squares (SCM smob)
   We can't combine with previous function, since check concave and
   slope damping comes first.
 
   We can't combine with previous function, since check concave and
   slope damping comes first.
 
-TODO: we should use the concaveness to control the amount of damping
-applied.
+  TODO: we should use the concaveness to control the amount of damping
+  applied.
   
   
- */
+*/
 MAKE_SCHEME_CALLBACK (Beam, shift_region_to_valid, 1);
 SCM
 Beam::shift_region_to_valid (SCM grob)
 MAKE_SCHEME_CALLBACK (Beam, shift_region_to_valid, 1);
 SCM
 Beam::shift_region_to_valid (SCM grob)
@@ -1000,7 +967,7 @@ Beam::shift_region_to_valid (SCM grob)
   
   Real dy = pos[RIGHT] - pos[LEFT];
   Real y = pos[LEFT];
   
   Real dy = pos[RIGHT] - pos[LEFT];
   Real y = pos[LEFT];
-  Real dydx =dy/dx;
+  Real slope =dy/dx;
 
   
   /*
 
   
   /*
@@ -1019,7 +986,7 @@ Beam::shift_region_to_valid (SCM grob)
 
       Real left_y =
        Stem::get_stem_info (s).shortest_y_
 
       Real left_y =
        Stem::get_stem_info (s).shortest_y_
-       - dydx * x_posns [i];
+       - slope * x_posns [i];
 
       /*
        left_y is now relative to the stem S. We want relative to
 
       /*
        left_y is now relative to the stem S. We want relative to
@@ -1055,121 +1022,6 @@ Beam::shift_region_to_valid (SCM grob)
   return SCM_UNSPECIFIED;
 }
 
   return SCM_UNSPECIFIED;
 }
 
-MAKE_SCHEME_CALLBACK (Beam, check_concave, 1);
-SCM
-Beam::check_concave (SCM smob)
-{
-  Grob *me = unsmob_grob (smob);
-
-  Link_array<Grob> stems = 
-    Pointer_group_interface__extract_grobs (me, (Grob*) 0, "stems");
-
-  Direction beam_dir = CENTER;
-  for (int i = 0; i < stems.size ();)
-    {
-      if (Stem::is_invisible (stems[i]))
-       stems.del (i);
-      else
-       {
-         if (Direction sd = Stem::get_direction (stems[i]))
-           {
-             /*
-               Don't do knee beams.
-              */
-             if (beam_dir && sd && sd != beam_dir)
-               return SCM_UNSPECIFIED;
-             
-             beam_dir = sd;
-           }
-         i++;
-       }
-    }
-  
-  if (stems.size () < 3)
-    return SCM_UNSPECIFIED;
-
-
-  /* Concaveness #1: If distance of an inner notehead to line between
-     two outer noteheads is bigger than CONCAVENESS-GAP (2.0ss),
-     beam is concave (Heinz Stolba).
-
-     In the case of knees, the line connecting outer heads is often
-     not related to the beam slope (it may even go in the other
-     direction). Skip the check when the outer stems point in
-     different directions. --hwn
-     
-  */
-  bool is_concave1 = false;
-  SCM gap = me->get_property ("concaveness-gap");
-  if (is_number (gap))
-    {
-      Real r1 = ly_scm2double (gap);
-      Real dy = Stem::chord_start_y (stems.top ())
-       - Stem::chord_start_y (stems[0]);
-
-      
-      Real slope = dy / (stems.size () - 1);
-      
-      Real y0 = Stem::chord_start_y (stems[0]);
-      for (int i = 1; i < stems.size () - 1; i++)
-       {
-         Real c =
-           beam_dir *((Stem::chord_start_y (stems[i]) - y0) - i * slope);
-         if (c - r1 > 0)
-           {
-             is_concave1 = true;
-             break;
-           }
-       }
-    }
-
-    
-  /* Concaveness #2: Sum distances of inner noteheads that fall
-     outside the interval of the two outer noteheads.
-
-     We only do this for beams where first and last stem have the same
-     direction. --hwn.
-
-
-     Note that "convex" stems compensate for "concave" stems.
-     (is that intentional?) --hwn.
-  */
-  
-  Real concaveness2 = 0;
-  SCM thresh = me->get_property ("concaveness-threshold");
-  Real r2 = infinity_f;
-  if (!is_concave1 && is_number (thresh))
-    {
-      r2 = ly_scm2double (thresh);
-      
-      Interval iv;
-      iv.add_point (Stem::chord_start_y (stems[0]));
-      iv.add_point (Stem::chord_start_y (stems.top ()));
-      
-      for (int i = 1; i < stems.size () - 1; i++)
-       {
-         Real f = Stem::chord_start_y (stems[i]);
-         concaveness2 += ( (f - iv[MAX] ) >? 0) +
-           ( (f - iv[MIN] ) <? 0);
-       }
-      
-      concaveness2 *= beam_dir / (stems.size () - 2);
-    }
-  
-  /* TODO: some sort of damping iso -> plain horizontal */
-  if (is_concave1 || concaveness2 > r2)
-    {
-      Drul_array<Real> pos = ly_scm2interval (me->get_property ("positions"));
-      Real r = linear_combination (pos, 0);
-
-      r /= Staff_symbol_referencer::staff_space (me);
-      me->set_property ("positions", ly_interval2scm (Drul_array<Real> (r, r)));
-      me->set_property ("least-squares-dy", scm_make_real (0));
-    }
-
-  return SCM_UNSPECIFIED;
-}
-
 /* This neat trick is by Werner Lemberg,
    damped = tanh (slope)
    corresponds with some tables in [Wanske] CHECKME */
 /* This neat trick is by Werner Lemberg,
    damped = tanh (slope)
    corresponds with some tables in [Wanske] CHECKME */
@@ -1183,11 +1035,11 @@ Beam::slope_damping (SCM smob)
     return SCM_UNSPECIFIED;
 
   SCM s = me->get_property ("damping"); 
     return SCM_UNSPECIFIED;
 
   SCM s = me->get_property ("damping"); 
-  int damping = ly_scm2int (s);
+  Real damping = scm_to_double (s);
 
   if (damping)
     {
 
   if (damping)
     {
-      Drul_array<Real>  pos = ly_scm2interval (me->get_property ("positions"));
+      Drul_array<Real> pos = ly_scm2interval (me->get_property ("positions"));
       scale_drul (&pos,  Staff_symbol_referencer::staff_space (me));
       
       Real dy = pos[RIGHT] - pos[LEFT];
       scale_drul (&pos,  Staff_symbol_referencer::staff_space (me));
       
       Real dy = pos[RIGHT] - pos[LEFT];
@@ -1200,10 +1052,17 @@ Beam::slope_damping (SCM smob)
 
       Real dx = last_visible_stem (me)->relative_coordinate (commonx, X_AXIS)
        - first_visible_stem (me)->relative_coordinate (commonx, X_AXIS);
 
       Real dx = last_visible_stem (me)->relative_coordinate (commonx, X_AXIS)
        - first_visible_stem (me)->relative_coordinate (commonx, X_AXIS);
-      Real dydx = dy && dx ? dy/dx : 0;
-      dydx = 0.6 * tanh (dydx) / damping;
 
 
-      Real damped_dy = dydx * dx;
+      Real slope = dy && dx ? dy/dx : 0;
+
+      Real concaveness = robust_scm2double (me->get_property ("concaveness"), 0.0);
+      
+      slope = 0.6 * tanh (slope) / (damping + concaveness);
+
+      Real damped_dy = slope * dx;
+
+      set_minimum_dy (me, &damped_dy);
+      
       pos[LEFT] += (dy - damped_dy) / 2;
       pos[RIGHT] -= (dy - damped_dy) / 2;
 
       pos[LEFT] += (dy - damped_dy) / 2;
       pos[RIGHT] -= (dy - damped_dy) / 2;
 
@@ -1223,11 +1082,11 @@ where_are_the_whole_beams (SCM beaming)
 {
   Slice l; 
   
 {
   Slice l; 
   
-  for ( SCM s = ly_car (beaming); is_pair (s) ; s = ly_cdr (s))
+  for ( SCM s = scm_car (beaming); scm_is_pair (s) ; s = scm_cdr (s))
     {
     {
-      if (scm_c_memq (ly_car (s), ly_cdr (beaming)) != SCM_BOOL_F)
+      if (scm_c_memq (scm_car (s), scm_cdr (beaming)) != SCM_BOOL_F)
        
        
-       l.add_point (ly_scm2int (ly_car (s)));
+       l.add_point (scm_to_int (scm_car (s)));
     }
 
   return l;
     }
 
   return l;
@@ -1297,8 +1156,8 @@ Beam::set_stem_lengths (Grob *me)
 
   bool gap = false;
   Real thick =0.0;
 
   bool gap = false;
   Real thick =0.0;
-  if (is_number (me->get_property ("gap-count"))
-      &&ly_scm2int (me->get_property ("gap-count")))
+  if (scm_is_number (me->get_property ("gap-count"))
+      &&scm_to_int (me->get_property ("gap-count")))
     {
       gap = true;
       thick = get_thickness (me);
     {
       gap = true;
       thick = get_thickness (me);
@@ -1453,9 +1312,9 @@ SCM
 Beam::rest_collision_callback (SCM element_smob, SCM axis)
 {
   Grob *rest = unsmob_grob (element_smob);
 Beam::rest_collision_callback (SCM element_smob, SCM axis)
 {
   Grob *rest = unsmob_grob (element_smob);
-  Axis a = (Axis) ly_scm2int (axis);
+  Axis a = (Axis) scm_to_int (axis);
 
 
-  if (is_number (rest->get_property ("staff-position")))
+  if (scm_is_number (rest->get_property ("staff-position")))
     return scm_int2num (0);
   
   assert (a == Y_AXIS);
     return scm_int2num (0);
   
   assert (a == Y_AXIS);
@@ -1472,7 +1331,7 @@ Beam::rest_collision_callback (SCM element_smob, SCM axis)
 
   Drul_array<Real> pos (0, 0);
   SCM s = beam->get_property ("positions");
 
   Drul_array<Real> pos (0, 0);
   SCM s = beam->get_property ("positions");
-  if (is_pair (s) && is_number (ly_car (s)))
+  if (scm_is_pair (s) && scm_is_number (scm_car (s)))
     pos = ly_scm2interval (s);
   Real staff_space = Staff_symbol_referencer::staff_space (rest);
 
     pos = ly_scm2interval (s);
   Real staff_space = Staff_symbol_referencer::staff_space (rest);
 
@@ -1484,15 +1343,20 @@ Beam::rest_collision_callback (SCM element_smob, SCM axis)
   // 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;
   // 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;
+  Real slope = dy && dx ? dy/dx : 0;
   
   Direction d = Stem::get_direction (stem);
   
   Direction d = Stem::get_direction (stem);
-  Real stem_y = pos[LEFT] + (stem->relative_coordinate (0, X_AXIS) - x0) * dydx;
+  Real stem_y = pos[LEFT] + (stem->relative_coordinate (0, X_AXIS) - x0) * slope;
   
   Real beam_translation = get_beam_translation (beam);
   Real beam_thickness = Beam::get_thickness (beam);
   
   Real beam_translation = get_beam_translation (beam);
   Real beam_thickness = Beam::get_thickness (beam);
+
+  /*
+    TODO: this is not strictly correct for 16th knee beams. 
+   */
+  int beam_count =
+    Stem::beam_multiplicity (stem).length() + 1;
   
   
-  int beam_count = get_direction_beam_count (beam, d);
   Real height_of_my_beams = beam_thickness / 2
     + (beam_count - 1) * beam_translation;
   Real beam_y = stem_y - d * height_of_my_beams;
   Real height_of_my_beams = beam_thickness / 2
     + (beam_count - 1) * beam_translation;
   Real beam_y = stem_y - d * height_of_my_beams;
@@ -1501,7 +1365,8 @@ Beam::rest_collision_callback (SCM element_smob, SCM axis)
 
   Real rest_dim = rest->extent (common_y, Y_AXIS)[d];
   Real minimum_distance =
 
   Real rest_dim = rest->extent (common_y, Y_AXIS)[d];
   Real minimum_distance =
-    staff_space * robust_scm2double (rest->get_property ("minimum-distance"), 0.0);
+    + staff_space * (robust_scm2double (stem->get_property ("stemlet-length"), 0.0)
+                    + robust_scm2double (rest->get_property ("minimum-distance"), 0.0));
 
   Real shift = d * ( ((beam_y - d * minimum_distance) - rest_dim) * d  <? 0.0);
 
 
   Real shift = d * ( ((beam_y - d * minimum_distance) - rest_dim) * d  <? 0.0);
 
@@ -1525,14 +1390,14 @@ bool
 Beam::is_knee (Grob* me)
 {
   SCM k = me->get_property ("knee");
 Beam::is_knee (Grob* me)
 {
   SCM k = me->get_property ("knee");
-  if (is_boolean (k))
+  if (scm_is_bool (k))
     return ly_scm2bool (k);
 
   bool knee = false;
   int d = 0;
     return ly_scm2bool (k);
 
   bool knee = false;
   int d = 0;
-  for (SCM s = me->get_property ("stems"); is_pair (s); s = ly_cdr (s))
+  for (SCM s = me->get_property ("stems"); scm_is_pair (s); s = scm_cdr (s))
     {
     {
-      Direction dir = get_grob_direction (unsmob_grob (ly_car (s)));
+      Direction dir = get_grob_direction (unsmob_grob (scm_car (s)));
       if (d && d != dir)
        {
          knee = true;
       if (d && d != dir)
        {
          knee = true;
@@ -1571,10 +1436,10 @@ ADD_INTERFACE (Beam, "beam-interface",
               "The @code{thickness} property is the weight of beams, and is measured "
               "in  staffspace"
               ,
               "The @code{thickness} property is the weight of beams, and is measured "
               "in  staffspace"
               ,
-              "knee positioning-done position-callbacks concaveness-gap "
-              "concaveness-threshold dir-function quant-score auto-knee-gap gap "
+              "knee positioning-done position-callbacks "
+              "concaveness dir-function quant-score auto-knee-gap gap "
               "gap-count chord-tremolo beamed-stem-shorten shorten least-squares-dy "
               "gap-count chord-tremolo beamed-stem-shorten shorten least-squares-dy "
-              "damping flag-width-function neutral-direction positions space-function "
+              "damping inspect-quants flag-width-function neutral-direction positions space-function "
               "thickness");
 
 
               "thickness");