source file of the GNU LilyPond music typesetter
- (c) 1997--2005 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+ (c) 1997--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
Jan Nieuwenhuizen <janneke@gnu.org>
*/
#include "beam.hh"
#include <algorithm>
-#include <math.h>
+using namespace std;
-#include "warn.hh"
-#include "staff-symbol-referencer.hh"
-#include "stem.hh"
+#include "grob.hh"
+#include "align-interface.hh"
+#include "international.hh"
#include "output-def.hh"
#include "pointer-group-interface.hh"
-#include "align-interface.hh"
+#include "staff-symbol-referencer.hh"
+#include "stem.hh"
+#include "warn.hh"
+#include "main.hh"
Real
get_detail (SCM alist, SCM sym, Real def)
{
SCM entry = scm_assq (sym, alist);
-
+
if (scm_is_pair (entry))
- {
- return robust_scm2double (scm_cdr (entry), def);
- }
+ return robust_scm2double (scm_cdr (entry), def);
return def;
}
Beam_quant_parameters::fill (Grob *him)
{
SCM details = him->get_property ("details");
-
+
+ /*
+ TODO: put in 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);
Real yr;
Real demerits;
-#if DEBUG_QUANTING
- String score_card_;
+#if DEBUG_BEAM_SCORING
+ string score_card_;
#endif
};
*/
int
-best_quant_score_idx (Array<Quant_score> const &qscores)
+best_quant_score_idx (vector<Quant_score> const &qscores)
{
Real best = 1e6;
int best_idx = -1;
- for (int i = qscores.size (); i--;)
+ for (vsize i = qscores.size (); i--;)
{
if (qscores[i].demerits < best)
{
return best_idx;
}
-MAKE_SCHEME_CALLBACK (Beam, quanting, 1);
+MAKE_SCHEME_CALLBACK (Beam, quanting, 2);
SCM
-Beam::quanting (SCM smob)
+Beam::quanting (SCM smob, SCM posns)
{
Grob *me = unsmob_grob (smob);
-
Beam_quant_parameters parameters;
parameters.fill (me);
-
- SCM s = me->get_property ("positions");
- Real yl = scm_to_double (scm_car (s));
- Real yr = scm_to_double (scm_cdr (s));
+
+ Real yl = scm_to_double (scm_car (posns));
+ Real yr = scm_to_double (scm_cdr (posns));
/*
Calculations are relative to a unit-scaled staff, i.e. the quants are
Real quants [] = {straddle, sit, inter, hang };
int num_quants = int (sizeof (quants) / sizeof (Real));
- Array<Real> quantsl;
- Array<Real> quantsr;
+ vector<Real> quantsl;
+ vector<Real> quantsr;
/*
going to REGION_SIZE == 2, yields another 0.6 second with
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");
- Array<Stem_info> stem_infos;
- Array<Real> base_lengths;
- Array<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;
stem_y != 0.0, when we're cross staff.
*/
- for (int i = 0; i < stems.size (); i++)
+ for (vsize i = 0; i < stems.size (); i++)
{
Grob *s = stems[i];
Stem_info si (Stem::get_stem_info (s));
si.scale (1 / ss);
- stem_infos.push (si);
- dirs_found[stem_infos.top ().dir_] = true;
+ stem_infos.push_back (si);
+ dirs_found[stem_infos.back ().dir_] = true;
bool f = to_boolean (s->get_property ("french-beaming"))
&& s != lvs && s != fvs;
- base_lengths.push (calc_stem_y (me, s, common, xl, xr,
+ base_lengths.push_back (calc_stem_y (me, s, common, xl, xr,
Interval (0, 0), f) / ss);
- stem_xposns.push (s->relative_coordinate (common[X_AXIS], X_AXIS));
+ stem_xposns.push_back (s->relative_coordinate (common[X_AXIS], X_AXIS));
}
bool xstaff = false;
}
Direction ldir = Direction (stem_infos[0].dir_);
- Direction rdir = Direction (stem_infos.top ().dir_);
+ Direction rdir = Direction (stem_infos.back ().dir_);
bool is_knee = dirs_found[LEFT] && dirs_found[RIGHT];
int region_size = (int) parameters.REGION_SIZE;
-
+
/*
Knees are harder, lets try some more possibilities for knees.
*/
for (int i = -region_size; i < region_size; i++)
for (int j = 0; j < num_quants; j++)
{
- quantsl.push (i + quants[j] + int (yl));
- quantsr.push (i + quants[j] + int (yr));
+ quantsl.push_back (i + quants[j] + int (yl));
+ quantsr.push_back (i + quants[j] + int (yr));
}
- Array<Quant_score> qscores;
+ vector<Quant_score> qscores;
- for (int l = 0; l < quantsl.size (); l++)
- for (int r = 0; r < quantsr.size (); r++)
+ for (vsize l = 0; l < quantsl.size (); l++)
+ for (vsize r = 0; r < quantsr.size (); r++)
{
Quant_score qs;
qs.yl = quantsl[l];
qs.yr = quantsr[r];
qs.demerits = 0.0;
- qscores.push (qs);
+ qscores.push_back (qs);
}
/* This is a longish function, but we don't separate this out into
neat modular separate subfunctions, as the subfunctions would be
called for many values of YL, YR. By precomputing various
parameters outside of the loop, we can save a lot of time. */
- for (int i = qscores.size (); i--;)
+ for (vsize i = qscores.size (); i--;)
{
Real d = score_slopes_dy (qscores[i].yl, qscores[i].yr,
dy_mus, yr- yl,
xstaff, ¶meters);
qscores[i].demerits += d;
-#if DEBUG_QUANTING
+#if DEBUG_BEAM_SCORING
qscores[i].score_card_ += to_string ("S%.2f", d);
#endif
}
Real rad = Staff_symbol_referencer::staff_radius (me);
Drul_array<int> edge_beam_counts
(Stem::beam_multiplicity (stems[0]).length () + 1,
- Stem::beam_multiplicity (stems.top ()).length () + 1);
+ Stem::beam_multiplicity (stems.back ()).length () + 1);
Real beam_translation = get_beam_translation (me) / ss;
Real reasonable_score = (is_knee) ? 200000 : 100;
- for (int i = qscores.size (); i--;)
+ for (vsize i = qscores.size (); i--;)
if (qscores[i].demerits < reasonable_score)
{
Real d = score_forbidden_quants (qscores[i].yl, qscores[i].yr,
edge_beam_counts, ldir, rdir, ¶meters);
qscores[i].demerits += d;
-#if DEBUG_QUANTING
+#if DEBUG_BEAM_SCORING
qscores[i].score_card_ += to_string (" F %.2f", d);
#endif
}
- for (int i = qscores.size (); i--;)
+ for (vsize i = qscores.size (); i--;)
if (qscores[i].demerits < reasonable_score)
{
Real d = score_stem_lengths (stems, stem_infos,
qscores[i].yl, qscores[i].yr, ¶meters);
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->get_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);
- int i = 0;
-
Real mindist = 1e6;
- for (; i < qscores.size (); i++)
+ for (vsize i = 0; i < qscores.size (); i++)
{
Real d = fabs (qscores[i].yl- ins[LEFT]) + fabs (qscores[i].yr - ins[RIGHT]);
if (d < mindist)
}
}
if (mindist > 1e5)
- programming_error ("can't find quant");
+ programming_error ("cannot find quant");
}
#endif
+
+ Interval final_positions;
if (best_idx < 0)
{
warning (_ ("no feasible beam position"));
- me->set_property ("positions", ly_interval2scm (Interval (0,0)));
+ final_positions = Interval (0, 0);
}
else
- me->set_property ("positions",
- ly_interval2scm (Drul_array<Real> (qscores[best_idx].yl,
- qscores[best_idx].yr)));
-#if DEBUG_QUANTING
+ {
+ final_positions = Drul_array<Real> (qscores[best_idx].yl,
+ qscores[best_idx].yr);
+ }
+
+#if DEBUG_BEAM_SCORING
if (best_idx >= 0
- && to_boolean (me->get_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_.to_str0 ()));
+ ly_string2scm (qscores[best_idx].score_card_));
}
#endif
- return SCM_UNSPECIFIED;
+ return ly_interval2scm (final_positions);
}
Real
-Beam::score_stem_lengths (Link_array<Grob> const &stems,
- Array<Stem_info> const &stem_infos,
- Array<Real> const &base_stem_ys,
- Array<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,
- Beam_quant_parameters const*parameters
- )
+ Beam_quant_parameters const *parameters)
{
Real limit_penalty = parameters->STEM_LENGTH_LIMIT_PENALTY;
Drul_array<Real> score (0, 0);
Drul_array<int> count (0, 0);
- for (int i = 0; i < stems.size (); i++)
+ for (vsize i = 0; i < stems.size (); i++)
{
Grob *s = stems[i];
if (Stem::is_invisible (s))
Stem_info info = stem_infos[i];
Direction d = info.dir_;
- score[d] += limit_penalty * max (0.0, (d * (info.shortest_y_ - current_y)));
+ score[d] += limit_penalty * max (0.0, (d * (info.shortest_y_ - current_y)));
Real ideal_diff = d * (current_y - info.ideal_y_);
Real ideal_score = shrink_extra_weight (ideal_diff, 1.5);
Direction d = DOWN;
do
- {
- score[d] /= max (count[d], 1);
- }
- while (flip (&d) != DOWN);
+ score[d] /= max (count[d], 1);
+ while (flip (&d) != DOWN)
+ ;
return score[LEFT] + score[RIGHT];
}
Real dy_mus, Real dy_damp,
Real dx,
bool xstaff,
-
- Beam_quant_parameters const*parameters)
+
+ Beam_quant_parameters const *parameters)
{
Real dy = yr - yl;
Real dem = 0.0;
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))
+ if (sign (dy_damp) != sign (dy))
{
- dem += parameters->DAMPING_DIRECTION_PENALTY;
+ 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)));
+
+ dem += parameters->MUSICAL_DIRECTION_FACTOR
+ * max (0.0, (fabs (dy) - fabs (dy_mus)));
Real slope_penalty = parameters->IDEAL_SLOPE_FACTOR;
Real thickness, Real beam_translation,
Drul_array<int> beam_counts,
Direction ldir, Direction rdir,
-
- Beam_quant_parameters const*parameters)
+
+ Beam_quant_parameters const *parameters)
{
Real dy = yr - yl;
Drul_array<Real> y (yl, yr);