From d9077f60257f3d9b9f2d9114e33f4a448f0d1430 Mon Sep 17 00:00:00 2001 From: hanwen Date: Mon, 15 Jul 2002 19:36:35 +0000 Subject: [PATCH] * lily/beam-quanting.cc (score_forbidden_quants): split beam quanting functionality. (quanting): argh. Forgot how linear interpolation works. Bugfix. * lily/beam.cc (quanting): bugfix. Behave sanely when no visible stems. --- ChangeLog | 7 + input/tutorial/brahms-tweaked.ly | 4 +- lily/beam-quanting.cc | 417 +++++++++++++++++++++++++++++ lily/beam.cc | 432 ++----------------------------- lily/include/beam.hh | 11 +- 5 files changed, 461 insertions(+), 410 deletions(-) create mode 100644 lily/beam-quanting.cc diff --git a/ChangeLog b/ChangeLog index 40221f33ad..fa4ee54028 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2002-07-15 Han-Wen Nienhuys + * lily/beam-quanting.cc (score_forbidden_quants): split beam + quanting functionality. + (quanting): argh. Forgot how linear interpolation works. Bugfix. + + + * Documentation/index.texi (Top): add whole-big-page documentation. + * lily/side-position-interface.cc (general_side_position): Subtract parent offset iso. adding it. (Huh? How could this have worked?) diff --git a/input/tutorial/brahms-tweaked.ly b/input/tutorial/brahms-tweaked.ly index c7d6ee75b0..f25b3299f1 100644 --- a/input/tutorial/brahms-tweaked.ly +++ b/input/tutorial/brahms-tweaked.ly @@ -14,7 +14,9 @@ \dynamicUp \property Voice.DynamicLineSpanner \override #'padding = #5.0 \tieUp - fis16( \> d \! b \translator Staff = down \clef treble g ~ < g8 )e> } \\ + fis16( \> d \! b \translator Staff = down + \stemUp + \clef treble g ~ < g8 )e> } \\ { s16 \property Voice.Stem \set #'transparent = ##t d' diff --git a/lily/beam-quanting.cc b/lily/beam-quanting.cc new file mode 100644 index 0000000000..e224ea6273 --- /dev/null +++ b/lily/beam-quanting.cc @@ -0,0 +1,417 @@ +#include + +#include "grob.hh" +#include "staff-symbol-referencer.hh" +#include "beam.hh" +#include "stem.hh" +#include "paper-def.hh" +#include "group-interface.hh" +#include "align-interface.hh" + +const int INTER_QUANT_PENALTY = 1000; +const int SECONDARY_BEAM_DEMERIT = 15; +const int STEM_LENGTH_DEMERIT_FACTOR = 5; + +// possibly ridiculous, but too short stems just won't do +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; + + +static Real +shrink_extra_weight (Real x) +{ + return fabs (x) * ((x < 0) ? 1.5 : 1.0); +} + + +struct Quant_score +{ + Real yl; + Real yr; + Real demerits; +}; + + +/* + TODO: + + - Make all demerits customisable + + - One sensible check per demerit (what's this --hwn) + + - Add demerits for quants per se, as to forbid a specific quant + entirely + +*/ + +int best_quant_score_idx (Array const & qscores) +{ + Real best = 1e6; + int best_idx = -1; + for (int i = qscores.size (); i--;) + { + if (qscores[i].demerits < best) + { + best = qscores [i].demerits ; + best_idx = i; + } + } + + return best_idx; +} + +MAKE_SCHEME_CALLBACK (Beam, quanting, 1); +SCM +Beam::quanting (SCM smob) +{ + Grob *me = unsmob_grob (smob); + + SCM s = me->get_grob_property ("positions"); + Real yl = gh_scm2double (gh_car (s)); + Real yr = gh_scm2double (gh_cdr (s)); + + Real ss = Staff_symbol_referencer::staff_space (me); + Real thickness = gh_scm2double (me->get_grob_property ("thickness")) / ss; + Real slt = me->paper_l ()->get_var ("linethickness") / ss; + + + SCM sdy = me->get_grob_property ("least-squares-dy"); + Real dy_mus = gh_number_p (sdy) ? gh_scm2double (sdy) : 0.0; + + Real straddle = 0.0; + Real sit = (thickness - slt) / 2; + Real inter = 0.5; + Real hang = 1.0 - (thickness - slt) / 2; + Real quants [] = {straddle, sit, inter, hang }; + + int num_quants = int (sizeof (quants)/sizeof (Real)); + Array quantsl; + Array quantsr; + + /* + going to REGION_SIZE == 2, yields another 0.6 second with + wtk1-fugue2. + + + (result indexes between 70 and 575) ? --hwn. + + */ + + + + /* + Do stem computations. These depend on YL and YR linearly, so we can + precompute for every stem 2 factors. + */ + Link_array stems= + Pointer_group_interface__extract_grobs (me, (Grob*)0, "stems"); + Array stem_infos; + Array base_lengths; + Array stem_xposns; + + Drul_array 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); + 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 + stem_y != 0.0, when we're cross staff. + + */ + bool french = to_boolean (me->get_grob_property ("french-beaming")); + for (int i= 0; i < stems.size(); i++) + { + Grob*s = stems[i]; + stem_infos.push (Stem::calc_stem_info (s)); + dirs_found[stem_infos.top ().dir_] = true; + + bool f = french && i > 0&& (i < stems.size () -1); + base_lengths.push (calc_stem_y (me, s, common, xl, xr, + Interval (0,0), f)); + stem_xposns.push (s->relative_coordinate (common[X_AXIS], X_AXIS)); + } + + bool xstaff= false; + if (lvs && fvs) + { + Grob *commony = fvs->common_refpoint (lvs, Y_AXIS); + xstaff = Align_interface::has_interface (commony); + } + + Direction ldir = Direction (stem_infos[0].dir_); + Direction rdir = Direction (stem_infos.top ().dir_); + bool knee_b = dirs_found[LEFT] && dirs_found[RIGHT]; + + + int region_size = REGION_SIZE; + /* + Knees are harder, lets try some more possibilities for knees. + */ + if (knee_b) + region_size += 2; + + 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)); + } + + Array qscores; + + for (int l =0; l < quantsl.size (); l++) + for (int r =0; r < quantsr.size (); r++) + { + Quant_score qs; + qs.yl = quantsl[l]; + qs.yr = quantsr[r]; + qs.demerits = 0.0; + + qscores.push (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--;) + if (qscores[i].demerits < 100) + { + qscores[i].demerits + += score_slopes_dy (me, qscores[i].yl, qscores[i].yr, + dy_mus, yr- yl, xstaff); + } + + Real rad = Staff_symbol_referencer::staff_radius (me); + int beam_count = get_beam_count (me); + Real beam_space = beam_count < 4 + ? (2*ss + slt - thickness) / 2.0 + : (3*ss + slt - thickness) / 3.0; + + for (int i = qscores.size (); i--;) + if (qscores[i].demerits < 100) + { + qscores[i].demerits + += score_forbidden_quants (me, qscores[i].yl, qscores[i].yr, + rad, slt, thickness, beam_space, + beam_count, ldir, rdir); + } + + + for (int i = qscores.size (); i--;) + if (qscores[i].demerits < 100) + { + qscores[i].demerits + += score_stem_lengths (stems, stem_infos, + base_lengths, stem_xposns, + xl, xr, + knee_b, + me, qscores[i].yl, qscores[i].yr); + } + + + int best_idx = best_quant_score_idx (qscores); + me->set_grob_property ("positions", + gh_cons (gh_double2scm (qscores[best_idx].yl), + gh_double2scm (qscores[best_idx].yr)) + ); + +#if DEBUG_QUANTING + + // debug quanting + me->set_grob_property ("quant-score", + gh_double2scm (qscores[best_idx].demerits)); + me->set_grob_property ("best-idx", gh_int2scm (best_idx)); +#endif + + return SCM_UNSPECIFIED; +} + +Real +Beam::score_stem_lengths (Link_arraystems, + Array stem_infos, + Array base_stem_ys, + Array stem_xs, + Real xl, Real xr, + bool knee, + Grob*me, + Real yl, Real yr) +{ + Real demerit_score = 0.0 ; + Real pen = STEM_LENGTH_LIMIT_PENALTY; + + for (int i=0; i < stems.size (); i++) + { + Grob* s = stems[i]; + if (Stem::invisible_b (s)) + continue; + + Real x = stem_xs[i]; + Real dx = xr-xl; + Real beam_y = yr *(x - xl)/dx + yl * ( xr - x)/dx; + Real current_y = beam_y + base_stem_ys[i]; + + Stem_info info = stem_infos[i]; + Direction d = info.dir_; + + demerit_score += pen + * (0 >? (info.dir_ * (info.shortest_y_ - current_y))); + + demerit_score += STEM_LENGTH_DEMERIT_FACTOR + * shrink_extra_weight (d * current_y - info.dir_ * info.ideal_y_); + } + + demerit_score *= 2.0 / stems.size (); + + return demerit_score; +} + +Real +Beam::score_slopes_dy (Grob *me, + Real yl, Real yr, + Real dy_mus, Real dy_damp, + bool xstaff) +{ + Real dy = yr - yl; + + Real dem = 0.0; + if (sign (dy_damp) != sign (dy)) + { + dem += DAMPING_DIRECTIION_PENALTY; + } + + dem += MUSICAL_DIRECTION_FACTOR * (0 >? (fabs (dy) - fabs (dy_mus))); + + + Real slope_penalty = IDEAL_SLOPE_FACTOR; + + /* + Xstaff beams tend to use extreme slopes to get short stems. We + put in a penalty here. + */ + if (xstaff) + slope_penalty *= 10; + + dem += shrink_extra_weight (fabs (dy_damp) - fabs (dy))* slope_penalty; + return dem; +} + +static Real +my_modf (Real x) +{ + return x - floor (x); +} + +Real +Beam::score_forbidden_quants (Grob*me, + Real yl, Real yr, + Real rad, + Real slt, + Real thickness, Real beam_space, + int beam_count, + Direction ldir, Direction rdir) +{ + Real dy = yr - yl; + + Real dem = 0.0; + if (fabs (yl) < rad && fabs ( my_modf (yl) - 0.5) < 1e-3) + dem += INTER_QUANT_PENALTY; + if (fabs (yr) < rad && fabs ( my_modf (yr) - 0.5) < 1e-3) + dem += INTER_QUANT_PENALTY; + + // todo: use beam_count of outer stems. + if (beam_count >= 2) + { + + Real straddle = 0.0; + Real sit = (thickness - slt) / 2; + Real inter = 0.5; + Real hang = 1.0 - (thickness - slt) / 2; + + + if (fabs (yl - ldir * beam_space) < rad + && fabs (my_modf (yl) - inter) < 1e-3) + dem += SECONDARY_BEAM_DEMERIT; + if (fabs (yr - rdir * beam_space) < rad + && fabs (my_modf (yr) - inter) < 1e-3) + dem += SECONDARY_BEAM_DEMERIT; + + Real eps = 1e-3; + + /* + Can't we simply compute the distance between the nearest + staffline and the secondary beam? That would get rid of the + silly case analysis here (which is probably not when we have + different beam-thicknesses.) + + --hwn + */ + + + // hmm, without Interval/Drul_array, you get ~ 4x same code... + if (fabs (yl - ldir * beam_space) < rad + inter) + { + if (ldir == UP && dy <= eps + && fabs (my_modf (yl) - sit) < eps) + dem += SECONDARY_BEAM_DEMERIT; + + if (ldir == DOWN && dy >= eps + && fabs (my_modf (yl) - hang) < eps) + dem += SECONDARY_BEAM_DEMERIT; + } + + if (fabs (yr - rdir * beam_space) < rad + inter) + { + if (rdir == UP && dy >= eps + && fabs (my_modf (yr) - sit) < eps) + dem += SECONDARY_BEAM_DEMERIT; + + if (rdir == DOWN && dy <= eps + && fabs (my_modf (yr) - hang) < eps) + dem += SECONDARY_BEAM_DEMERIT; + } + + if (beam_count >= 3) + { + if (fabs (yl - 2 * ldir * beam_space) < rad + inter) + { + if (ldir == UP && dy <= eps + && fabs (my_modf (yl) - straddle) < eps) + dem += SECONDARY_BEAM_DEMERIT; + + if (ldir == DOWN && dy >= eps + && fabs (my_modf (yl) - straddle) < eps) + dem += SECONDARY_BEAM_DEMERIT; + } + + if (fabs (yr - 2 * rdir * beam_space) < rad + inter) + { + if (rdir == UP && dy >= eps + && fabs (my_modf (yr) - straddle) < eps) + dem += SECONDARY_BEAM_DEMERIT; + + if (rdir == DOWN && dy <= eps + && fabs (my_modf (yr) - straddle) < eps) + dem += SECONDARY_BEAM_DEMERIT; + } + } + } + + return dem; +} + + diff --git a/lily/beam.cc b/lily/beam.cc index 7c40e0758f..f6768176db 100644 --- a/lily/beam.cc +++ b/lily/beam.cc @@ -31,7 +31,6 @@ Notes: #include // tanh. -#include "align-interface.hh" #include "molecule.hh" #include "directional-element-interface.hh" #include "beaming.hh" @@ -57,23 +56,6 @@ Notes: #endif -const int INTER_QUANT_PENALTY = 1000; -const int SECONDARY_BEAM_DEMERIT = 15; -const int STEM_LENGTH_DEMERIT_FACTOR = 5; -// possibly ridiculous, but too short stems just won't do -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 REGION_SIZE = 2; - - -static Real -shrink_extra_weight (Real x) -{ - return fabs (x) * ((x < 0) ? 1.5 : 1.0); -} - void Beam::add_stem (Grob *me, Grob *s) { @@ -515,7 +497,6 @@ Beam::consider_auto_knees (Grob *me, Direction d) Real staff_space = Staff_symbol_referencer::staff_space (me); Real gap = gh_scm2double (scm) / staff_space; - Link_array stems= Pointer_group_interface__extract_grobs (me, (Grob*)0, "stems"); @@ -629,378 +610,6 @@ Beam::after_line_breaking (SCM smob) return SCM_UNSPECIFIED; } -struct Quant_score -{ - Real yl; - Real yr; - Real demerits; -}; - - -/* - TODO: - - - Make all demerits customisable - - - One sensible check per demerit (what's this --hwn) - - - Add demerits for quants per se, as to forbid a specific quant - entirely - -*/ -MAKE_SCHEME_CALLBACK (Beam, quanting, 1); -SCM -Beam::quanting (SCM smob) -{ - Grob *me = unsmob_grob (smob); - - SCM s = me->get_grob_property ("positions"); - Real yl = gh_scm2double (gh_car (s)); - Real yr = gh_scm2double (gh_cdr (s)); - - Real ss = Staff_symbol_referencer::staff_space (me); - Real thickness = gh_scm2double (me->get_grob_property ("thickness")) / ss; - Real slt = me->paper_l ()->get_var ("linethickness") / ss; - - - SCM sdy = me->get_grob_property ("least-squares-dy"); - Real dy_mus = gh_number_p (sdy) ? gh_scm2double (sdy) : 0.0; - - Real straddle = 0.0; - Real sit = (thickness - slt) / 2; - Real inter = 0.5; - Real hang = 1.0 - (thickness - slt) / 2; - Real quants [] = {straddle, sit, inter, hang }; - - int num_quants = int (sizeof (quants)/sizeof (Real)); - Array quantsl; - Array quantsr; - - /* - going to REGION_SIZE == 2, yields another 0.6 second with - wtk1-fugue2. - - - (result indexes between 70 and 575) ? --hwn. - - */ - - - - /* - Do stem computations. These depend on YL and YR linearly, so we can - precompute for every stem 2 factors. - */ - Link_array stems= - Pointer_group_interface__extract_grobs (me, (Grob*)0, "stems"); - Array stem_infos; - Array lbase_lengths; - Array rbase_lengths; - - Drul_array dirs_found(0,0); - Grob *common_y = common_refpoint_of_array (stems, me, Y_AXIS); - - bool french = to_boolean (me->get_grob_property ("french-beaming")); - for (int i= 0; i < stems.size(); i++) - { - Grob*s = stems[i]; - stem_infos.push (Stem::calc_stem_info (s)); - dirs_found[stem_infos.top ().dir_] = true; - - Real b = calc_stem_y (me, s, common_y , Interval (1,0), french && i > 0&& (i < stems.size () -1)); - lbase_lengths.push (b); - - Real a = calc_stem_y (me, s, common_y , Interval (0,1), french && i > 0&& (i < stems.size () -1)); - rbase_lengths.push (a); - } - - Direction ldir = Direction (stem_infos[0].dir_); - Direction rdir = Direction (stem_infos.top ().dir_); - bool knee_b = dirs_found[LEFT] && dirs_found[RIGHT]; - - - int region_size = REGION_SIZE; - /* - Knees are harder, lets try some more possibilities for knees. - */ - if (knee_b) - region_size += 2; - - 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)); - } - - Array qscores; - - for (int l =0; l < quantsl.size (); l++) - for (int r =0; r < quantsr.size (); r++) - { - Quant_score qs; - qs.yl = quantsl[l]; - qs.yr = quantsr[r]; - qs.demerits = 0.0; - - qscores.push (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. - - */ - - - Grob *fvs = first_visible_stem (me); - Grob *lvs = last_visible_stem (me); - - bool xstaff= false; - if (lvs && fvs) - { - Grob *commony = fvs->common_refpoint (lvs, Y_AXIS); - xstaff = Align_interface::has_interface (commony); - } - - for (int i = qscores.size (); i--;) - if (qscores[i].demerits < 100) - { - qscores[i].demerits - += score_slopes_dy (me, qscores[i].yl, qscores[i].yr, - dy_mus, yr- yl, xstaff); - } - - Real rad = Staff_symbol_referencer::staff_radius (me); - int beam_count = get_beam_count (me); - Real beam_space = beam_count < 4 - ? (2*ss + slt - thickness) / 2.0 - : (3*ss + slt - thickness) / 3.0; - - for (int i = qscores.size (); i--;) - if (qscores[i].demerits < 100) - { - qscores[i].demerits - += score_forbidden_quants (me, qscores[i].yl, qscores[i].yr, - rad, slt, thickness, beam_space, - beam_count, ldir, rdir); - } - - - for (int i = qscores.size (); i--;) - if (qscores[i].demerits < 100) - { - qscores[i].demerits - += score_stem_lengths (stems, stem_infos, - lbase_lengths, rbase_lengths, - knee_b, - me, qscores[i].yl, qscores[i].yr); - } - - - Real best = 1e6; - int best_idx = -1; - for (int i = qscores.size (); i--;) - { - if (qscores[i].demerits < best) - { - best = qscores [i].demerits ; - best_idx = i; - } - } - - - me->set_grob_property ("positions", - gh_cons (gh_double2scm (qscores[best_idx].yl), - gh_double2scm (qscores[best_idx].yr)) - ); - -#if DEBUG_QUANTING - - // debug quanting - me->set_grob_property ("quant-score", - gh_double2scm (qscores[best_idx].demerits)); - me->set_grob_property ("best-idx", gh_int2scm (best_idx)); -#endif - - return SCM_UNSPECIFIED; -} - -Real -Beam::score_stem_lengths (Link_arraystems, - Array stem_infos, - Array left_factor, - Array right_factor, - bool knee, - Grob*me, - Real yl, Real yr) -{ - Real demerit_score = 0.0 ; - Real pen = STEM_LENGTH_LIMIT_PENALTY; - - for (int i=0; i < stems.size (); i++) - { - Grob* s = stems[i]; - if (Stem::invisible_b (s)) - continue; - - Real current_y = - yl * left_factor[i] + right_factor[i]* yr; - - Stem_info info = stem_infos[i]; - Direction d = info.dir_; - - demerit_score += pen - * ( 0 >? (info.dir_ * (info.shortest_y_ - current_y))); - - demerit_score += STEM_LENGTH_DEMERIT_FACTOR - * shrink_extra_weight (d * current_y - info.dir_ * info.ideal_y_); - } - - demerit_score *= 2.0 / stems.size (); - - return demerit_score; -} - -Real -Beam::score_slopes_dy (Grob *me, - Real yl, Real yr, - Real dy_mus, Real dy_damp, - bool xstaff) -{ - Real dy = yr - yl; - - Real dem = 0.0; - if (sign (dy_damp) != sign (dy)) - { - dem += DAMPING_DIRECTIION_PENALTY; - } - - dem += MUSICAL_DIRECTION_FACTOR * (0 >? (fabs (dy) - fabs (dy_mus))); - - - Real slope_penalty = IDEAL_SLOPE_FACTOR; - - /* - Xstaff beams tend to use extreme slopes to get short stems. We - put in a penalty here. - */ - if (xstaff) - slope_penalty *= 10; - - dem += shrink_extra_weight (fabs (dy_damp) - fabs (dy))* slope_penalty; - return dem; -} - -static Real -my_modf (Real x) -{ - return x - floor (x); -} - -Real -Beam::score_forbidden_quants (Grob*me, - Real yl, Real yr, - Real rad, - Real slt, - Real thickness, Real beam_space, - int beam_count, - Direction ldir, Direction rdir) -{ - Real dy = yr - yl; - - Real dem = 0.0; - if (fabs (yl) < rad && fabs ( my_modf (yl) - 0.5) < 1e-3) - dem += INTER_QUANT_PENALTY; - if (fabs (yr) < rad && fabs ( my_modf (yr) - 0.5) < 1e-3) - dem += INTER_QUANT_PENALTY; - - // todo: use beam_count of outer stems. - if (beam_count >= 2) - { - - Real straddle = 0.0; - Real sit = (thickness - slt) / 2; - Real inter = 0.5; - Real hang = 1.0 - (thickness - slt) / 2; - - - if (fabs (yl - ldir * beam_space) < rad - && fabs (my_modf (yl) - inter) < 1e-3) - dem += SECONDARY_BEAM_DEMERIT; - if (fabs (yr - rdir * beam_space) < rad - && fabs (my_modf (yr) - inter) < 1e-3) - dem += SECONDARY_BEAM_DEMERIT; - - Real eps = 1e-3; - - /* - Can't we simply compute the distance between the nearest - staffline and the secondary beam? That would get rid of the - silly case analysis here (which is probably not when we have - different beam-thicknesses.) - - --hwn - */ - - - // hmm, without Interval/Drul_array, you get ~ 4x same code... - if (fabs (yl - ldir * beam_space) < rad + inter) - { - if (ldir == UP && dy <= eps - && fabs (my_modf (yl) - sit) < eps) - dem += SECONDARY_BEAM_DEMERIT; - - if (ldir == DOWN && dy >= eps - && fabs (my_modf (yl) - hang) < eps) - dem += SECONDARY_BEAM_DEMERIT; - } - - if (fabs (yr - rdir * beam_space) < rad + inter) - { - if (rdir == UP && dy >= eps - && fabs (my_modf (yr) - sit) < eps) - dem += SECONDARY_BEAM_DEMERIT; - - if (rdir == DOWN && dy <= eps - && fabs (my_modf (yr) - hang) < eps) - dem += SECONDARY_BEAM_DEMERIT; - } - - if (beam_count >= 3) - { - if (fabs (yl - 2 * ldir * beam_space) < rad + inter) - { - if (ldir == UP && dy <= eps - && fabs (my_modf (yl) - straddle) < eps) - dem += SECONDARY_BEAM_DEMERIT; - - if (ldir == DOWN && dy >= eps - && fabs (my_modf (yl) - straddle) < eps) - dem += SECONDARY_BEAM_DEMERIT; - } - - if (fabs (yr - 2 * rdir * beam_space) < rad + inter) - { - if (rdir == UP && dy >= eps - && fabs (my_modf (yr) - straddle) < eps) - dem += SECONDARY_BEAM_DEMERIT; - - if (rdir == DOWN && dy <= eps - && fabs (my_modf (yr) - straddle) < eps) - dem += SECONDARY_BEAM_DEMERIT; - } - } - } - - return dem; -} - - - MAKE_SCHEME_CALLBACK (Beam, least_squares, 1); SCM Beam::least_squares (SCM smob) @@ -1380,27 +989,23 @@ where_are_the_whole_beams(SCM beaming) /* Calculate the Y position of the stem-end, given the Y-left, Y-right - in POS, and for stem S. + in POS for stem S. This Y position is relative to S. */ Real -Beam::calc_stem_y (Grob *me, Grob* s, Grob * common_y, Interval pos, bool french) +Beam::calc_stem_y (Grob *me, Grob* s, Grob ** common, + Real xl, Real xr, + Interval pos, bool french) { Real beam_space = get_beam_space (me); - // ugh -> use commonx - Grob * fvs = first_visible_stem (me); - Grob *lvs = last_visible_stem (me); - Real x0 = fvs ? fvs->relative_coordinate (0, X_AXIS) : 0.0; - Real dx = fvs ? lvs->relative_coordinate (0, X_AXIS) - x0 : 0.0; - Real r = s->relative_coordinate (0, X_AXIS) - x0; + Real r = s->relative_coordinate (common[X_AXIS], X_AXIS) - xl; Real dy = pos.delta (); + Real dx = xr - xl; Real stem_y_beam0 = (dy && dx ? r / dx * dy : 0) + pos[LEFT]; - - Direction my_dir = Directional_element_interface::get (s); SCM beaming = s->get_grob_property ("beaming"); @@ -1419,8 +1024,8 @@ Beam::calc_stem_y (Grob *me, Grob* s, Grob * common_y, Interval pos, bool french stem_y +=bm[my_dir] * beam_space; } - Real id = me->relative_coordinate (common_y, Y_AXIS) - - s->relative_coordinate (common_y, Y_AXIS); + Real id = me->relative_coordinate (common[Y_AXIS], Y_AXIS) + - s->relative_coordinate (common[Y_AXIS], Y_AXIS); return stem_y + id; } @@ -1438,21 +1043,34 @@ Beam::set_stem_lengths (Grob *me) if (stems.size () <= 1) return; - Grob *common = common_refpoint_of_array (stems, me, Y_AXIS); + Grob *common[2]; + for (int a = 2; a--;) + common[a] = common_refpoint_of_array (stems, me, Axis(a)); + Interval pos = ly_scm2interval (me->get_grob_property ("positions")); Real staff_space = Staff_symbol_referencer::staff_space (me); bool french = to_boolean (me->get_grob_property ("french-beaming")); - + + + // ugh -> use commonx + Grob * fvs = first_visible_stem (me); + Grob *lvs = last_visible_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; + for (int i=0; i < stems.size (); i++) { Grob* s = stems[i]; if (Stem::invisible_b (s)) continue; - Real stem_y = calc_stem_y (me, s, common , pos, french && i > 0&& (i < stems.size () -1)); + Real stem_y = calc_stem_y (me, s, common, + xl, xr, + pos, french && i > 0&& (i < stems.size () -1)); - Stem::set_stemend (s, 2* stem_y / staff_space); + Stem::set_stemend (s, 2* stem_y / staff_space); } } diff --git a/lily/include/beam.hh b/lily/include/beam.hh index 2816f7abfc..bc3fc1ea50 100644 --- a/lily/include/beam.hh +++ b/lily/include/beam.hh @@ -41,7 +41,8 @@ public: static Real score_slopes_dy (Grob*, Real,Real,Real,Real, bool); static Real score_stem_lengths (Link_array, Array, - Array, Array, + Array, Array, + Real, Real, bool,Grob*,Real , Real); static Real score_forbidden_quants (Grob*, Real, Real, Real, Real, Real, Real, @@ -53,10 +54,16 @@ private: static void set_stem_directions (Grob*, Direction ); static void consider_auto_knees (Grob*, Direction d); static void set_stem_shorten (Grob*); - static Real calc_stem_y (Grob*, Grob* s, Grob*c, Interval pos, bool french); + static Real calc_stem_y (Grob*, Grob* s, Grob**c, + Real, Real, + Interval pos, bool french); static void set_stem_lengths (Grob*); static int forced_stem_count (Grob*); }; +const int REGION_SIZE = 2; +#define DEBUG_QUANTING 0 + + #endif /* BEAM_HH */ -- 2.39.5