]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/beam-quanting.cc
Run `make grand-replace'.
[lilypond.git] / lily / beam-quanting.cc
index 5b9b2dbaed808658d9a714472cf634161d2f3152..cf933d500bc3d3071d1386fdb172e8391bb51465 100644 (file)
@@ -3,7 +3,7 @@
 
   source file of the GNU LilyPond music typesetter
 
-  (c) 1997--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
+  (c) 1997--2008 Han-Wen Nienhuys <hanwen@xs4all.nl>
   Jan Nieuwenhuizen <janneke@gnu.org>
 */
 
@@ -12,6 +12,7 @@
 #include <algorithm>
 using namespace std;
 
+#include "grob.hh"
 #include "align-interface.hh"
 #include "international.hh"
 #include "output-def.hh"
@@ -19,6 +20,7 @@ using namespace std;
 #include "staff-symbol-referencer.hh"
 #include "stem.hh"
 #include "warn.hh"
+#include "main.hh"
 
 Real
 get_detail (SCM alist, SCM sym, Real def)
@@ -35,15 +37,17 @@ Beam_quant_parameters::fill (Grob *him)
 {
   SCM details = him->get_property ("details");
 
+  /* 
+     TODO: The default values should be copied to define-grobs.scm.
+   */
   INTER_QUANT_PENALTY = get_detail (details, ly_symbol2scm ("inter-quant-penalty"), 1000.0);
   SECONDARY_BEAM_DEMERIT = get_detail (details, ly_symbol2scm ("secondary-beam-demerit"), 10.0);
   STEM_LENGTH_DEMERIT_FACTOR = get_detail (details, ly_symbol2scm ("stem-length-demerit-factor"), 5);
   REGION_SIZE = get_detail (details, ly_symbol2scm ("region-size"), 2);
   BEAM_EPS = get_detail (details, ly_symbol2scm ("beam-eps"), 1e-3);
-
-  // possibly ridiculous, but too short stems just won't do
   STEM_LENGTH_LIMIT_PENALTY = get_detail (details, ly_symbol2scm ("stem-length-limit-penalty"), 5000);
   DAMPING_DIRECTION_PENALTY = get_detail (details, ly_symbol2scm ("damping-direction-penalty"), 800);
+  HINT_DIRECTION_PENALTY = get_detail (details, ly_symbol2scm ("hint-direction-penalty"), 20);
   MUSICAL_DIRECTION_FACTOR = get_detail (details, ly_symbol2scm ("musical-direction-factor"), 400);
   IDEAL_SLOPE_FACTOR = get_detail (details, ly_symbol2scm ("ideal-slope-factor"), 10);
   ROUND_TO_ZERO_SLOPE = get_detail (details, ly_symbol2scm ("round-to-zero-slope"), 0.02);
@@ -61,8 +65,8 @@ struct Quant_score
   Real yr;
   Real demerits;
 
-#if DEBUG_QUANTING
-  std::string score_card_;
+#if DEBUG_BEAM_SCORING
+  string score_card_;
 #endif
 };
 
@@ -78,7 +82,7 @@ struct Quant_score
 */
 
 int
-best_quant_score_idx (std::vector<Quant_score> const &qscores)
+best_quant_score_idx (vector<Quant_score> const &qscores)
 {
   Real best = 1e6;
   int best_idx = -1;
@@ -109,7 +113,6 @@ Beam::quanting (SCM smob, SCM posns)
   /*
     Calculations are relative to a unit-scaled staff, i.e. the quants are
     divided by the current staff_space.
-
   */
   Real ss = Staff_symbol_referencer::staff_space (me);
   Real thickness = Beam::get_thickness (me) / ss;
@@ -123,14 +126,13 @@ Beam::quanting (SCM smob, SCM posns)
   Real quants [] = {straddle, sit, inter, hang };
 
   int num_quants = int (sizeof (quants) / sizeof (Real));
-  std::vector<Real> quantsl;
-  std::vector<Real> quantsr;
+  vector<Real> quantsl;
+  vector<Real> quantsr;
 
   /*
     going to REGION_SIZE == 2, yields another 0.6 second with
     wtk1-fugue2.
 
-
     (result indexes between 70 and 575)  ? --hwn.
 
   */
@@ -139,27 +141,25 @@ Beam::quanting (SCM smob, SCM posns)
     Do stem computations.  These depend on YL and YR linearly, so we can
     precompute for every stem 2 factors.
   */
-  Link_array<Grob> stems
+  vector<Grob*> stems
     = extract_grob_array (me, "stems");
-  std::vector<Stem_info> stem_infos;
-  std::vector<Real> base_lengths;
-  std::vector<Real> stem_xposns;
+  vector<Stem_info> stem_infos;
+  vector<Real> base_lengths;
+  vector<Real> stem_xposns;
 
   Drul_array<bool> dirs_found (0, 0);
   Grob *common[2];
   for (int a = 2; a--;)
     common[a] = common_refpoint_of_array (stems, me, Axis (a));
 
-  Grob *fvs = first_visible_stem (me);
-  Grob *lvs = last_visible_stem (me);
+  Grob *fvs = first_normal_stem (me);
+  Grob *lvs = last_normal_stem (me);
   Real xl = fvs ? fvs->relative_coordinate (common[X_AXIS], X_AXIS) : 0.0;
   Real xr = fvs ? lvs->relative_coordinate (common[X_AXIS], X_AXIS) : 0.0;
 
   /*
-    We store some info to quickly interpolate.
-
-    Sometimes my head is screwed on backwards.  The stemlength are
-    AFFINE linear in YL and YR. If YL == YR == 0, then we might have
+    We store some info to quickly interpolate.  The stemlength are
+    affine linear in YL and YR. If YL == YR == 0, then we might have
     stem_y != 0.0, when we're cross staff.
 
   */
@@ -175,17 +175,19 @@ Beam::quanting (SCM smob, SCM posns)
       bool f = to_boolean (s->get_property ("french-beaming"))
        && s != lvs && s != fvs;
 
-      base_lengths.push_back (calc_stem_y (me, s, common, xl, xr,
-                                     Interval (0, 0), f) / ss);
-      stem_xposns.push_back (s->relative_coordinate (common[X_AXIS], X_AXIS));
-    }
+      if (Stem::is_normal_stem (s))
+       {
+         base_lengths.push_back (calc_stem_y (me, s, common, xl, xr, CENTER, 
+                                              Interval (0, 0), f) / ss);
+       }
+      else
+       {
+         base_lengths.push_back (0);
+       }
 
-  bool xstaff = false;
-  if (lvs && fvs)
-    {
-      Grob *commony = fvs->common_refpoint (lvs, Y_AXIS);
-      xstaff = Align_interface::has_interface (commony);
+      stem_xposns.push_back (s->relative_coordinate (common[X_AXIS], X_AXIS));
     }
+  bool xstaff = Align_interface::has_interface (common[Y_AXIS]);
 
   Direction ldir = Direction (stem_infos[0].dir_);
   Direction rdir = Direction (stem_infos.back ().dir_);
@@ -209,7 +211,7 @@ Beam::quanting (SCM smob, SCM posns)
        quantsr.push_back (i + quants[j] + int (yr));
       }
 
-  std::vector<Quant_score> qscores;
+  vector<Quant_score> qscores;
 
   for (vsize l = 0; l < quantsl.size (); l++)
     for (vsize r = 0; r < quantsr.size (); r++)
@@ -234,7 +236,7 @@ Beam::quanting (SCM smob, SCM posns)
                                xstaff, &parameters);
       qscores[i].demerits += d;
 
-#if DEBUG_QUANTING
+#if DEBUG_BEAM_SCORING
       qscores[i].score_card_ += to_string ("S%.2f", d);
 #endif
     }
@@ -255,7 +257,7 @@ Beam::quanting (SCM smob, SCM posns)
                                         edge_beam_counts, ldir, rdir, &parameters);
        qscores[i].demerits += d;
 
-#if DEBUG_QUANTING
+#if DEBUG_BEAM_SCORING
        qscores[i].score_card_ += to_string (" F %.2f", d);
 #endif
       }
@@ -270,16 +272,16 @@ Beam::quanting (SCM smob, SCM posns)
                                     qscores[i].yl, qscores[i].yr, &parameters);
        qscores[i].demerits += d;
 
-#if DEBUG_QUANTING
+#if DEBUG_BEAM_SCORING
        qscores[i].score_card_ += to_string (" L %.2f", d);
 #endif
       }
 
   int best_idx = best_quant_score_idx (qscores);
 
-#if DEBUG_QUANTING
+#if DEBUG_BEAM_SCORING
   SCM inspect_quants = me->get_property ("inspect-quants");
-  if (to_boolean (me->layout ()->lookup_variable (ly_symbol2scm ("debug-beam-quanting")))
+  if (to_boolean (me->layout ()->lookup_variable (ly_symbol2scm ("debug-beam-scoring")))
       && scm_is_pair (inspect_quants))
     {
       Drul_array<Real> ins = ly_scm2interval (inspect_quants);
@@ -295,7 +297,7 @@ Beam::quanting (SCM smob, SCM posns)
            }
        }
       if (mindist > 1e5)
-       programming_error ("can't find quant");
+       programming_error ("cannot find quant");
     }
 #endif
 
@@ -311,15 +313,15 @@ Beam::quanting (SCM smob, SCM posns)
                                          qscores[best_idx].yr);
     }
   
-#if DEBUG_QUANTING
+#if DEBUG_BEAM_SCORING
   if (best_idx >= 0
-      && to_boolean (me->layout ()->lookup_variable (ly_symbol2scm ("debug-beam-quanting"))))
+      && to_boolean (me->layout ()->lookup_variable (ly_symbol2scm ("debug-beam-scoring"))))
     {
       qscores[best_idx].score_card_ += to_string ("i%d", best_idx);
 
       // debug quanting
       me->set_property ("quant-score",
-                       scm_makfrom0str (qscores[best_idx].score_card_.c_str ()));
+                       ly_string2scm (qscores[best_idx].score_card_));
     }
 #endif
 
@@ -327,10 +329,10 @@ Beam::quanting (SCM smob, SCM posns)
 }
 
 Real
-Beam::score_stem_lengths (Link_array<Grob> const &stems,
-                         std::vector<Stem_info> const &stem_infos,
-                         std::vector<Real> const &base_stem_ys,
-                         std::vector<Real> const &stem_xs,
+Beam::score_stem_lengths (vector<Grob*> const &stems,
+                         vector<Stem_info> const &stem_infos,
+                         vector<Real> const &base_stem_ys,
+                         vector<Real> const &stem_xs,
                          Real xl, Real xr,
                          bool knee,
                          Real yl, Real yr,
@@ -344,7 +346,7 @@ Beam::score_stem_lengths (Link_array<Grob> const &stems,
   for (vsize i = 0; i < stems.size (); i++)
     {
       Grob *s = stems[i];
-      if (Stem::is_invisible (s))
+      if (!Stem::is_normal_stem (s))
        continue;
 
       Real x = stem_xs[i];
@@ -375,8 +377,7 @@ Beam::score_stem_lengths (Link_array<Grob> const &stems,
   Direction d = DOWN;
   do
     score[d] /= max (count[d], 1);
-  while (flip (&d) != DOWN)
-    ;
+  while (flip (&d) != DOWN);
 
   return score[LEFT] + score[RIGHT];
 }
@@ -399,10 +400,19 @@ Beam::score_slopes_dy (Real yl, Real yr,
     TODO: find a way to incorporate the complexity of the beam in this
     penalty.
   */
-  if (fabs (dy / dx) > parameters->ROUND_TO_ZERO_SLOPE
-      && sign (dy_damp) != sign (dy))
-    dem += parameters->DAMPING_DIRECTION_PENALTY;
-
+  if (sign (dy_damp) != sign (dy))
+    {
+      if (!dy)
+       {
+         if (fabs (dy_damp / dx) > parameters->ROUND_TO_ZERO_SLOPE)
+           dem += parameters->DAMPING_DIRECTION_PENALTY;
+         else
+           dem += parameters->HINT_DIRECTION_PENALTY;
+       }
+      else
+       dem += parameters->DAMPING_DIRECTION_PENALTY;
+    }
+  
   dem += parameters->MUSICAL_DIRECTION_FACTOR
     * max (0.0, (fabs (dy) - fabs (dy_mus)));