From cebb2444373e19ff9ad0319b6f95a49225a0bee0 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Sat, 1 Jun 2002 11:34:21 +0000 Subject: [PATCH] biem fix --- ChangeLog | 6 + flower/include/interval.hh | 1 + flower/include/interval.tcc | 8 + input/bugs/bizarre-beam.ly | 3 +- input/regression/beam-extreme.ly | 20 +- input/regression/beam-multiple-cross-staff.ly | 4 +- lily/beam.cc | 188 ++++++++++++------ lily/include/beam.hh | 1 + lily/stem.cc | 16 +- scm/grob-description.scm | 3 + 10 files changed, 178 insertions(+), 72 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4bb64bf7ce..ad3eab6108 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2002-06-01 Han-Wen + + * lily/beam.cc (shift_region_to_valid): Try to shift positions + after slope-damping and concaveness check, so that short-stems are + not violated. + 2002-06-01 Jan Nieuwenhuizen * lily/beam.cc (quanting): Increase REGION_SIZE to 4 by default. diff --git a/flower/include/interval.hh b/flower/include/interval.hh index c4e9d4e718..0d445b2366 100644 --- a/flower/include/interval.hh +++ b/flower/include/interval.hh @@ -52,6 +52,7 @@ struct Interval_t : public Drul_array { T length () const; T delta () const; void set_empty () ; + void set_full (); bool empty_b () const { return elem (LEFT) > elem (RIGHT); } bool contains_b (Interval_t const&) const; Interval_t () { diff --git a/flower/include/interval.tcc b/flower/include/interval.tcc index 94ad71f578..60f23fab09 100644 --- a/flower/include/interval.tcc +++ b/flower/include/interval.tcc @@ -60,6 +60,14 @@ Interval_t::set_empty () elem (RIGHT) = (T) -infinity (); } +template +void +Interval_t::set_full () +{ + elem (LEFT) = (T) -infinity (); + elem (RIGHT) = (T) infinity (); +} + template T Interval_t::length () const diff --git a/input/bugs/bizarre-beam.ly b/input/bugs/bizarre-beam.ly index 166376e7b8..b1abf20a70 100644 --- a/input/bugs/bizarre-beam.ly +++ b/input/bugs/bizarre-beam.ly @@ -2,7 +2,8 @@ \score{ \notes {g''4 [ g''] \notes\relative c'{ - \times 2/3{[d16 fis' d,]} \times 2/3{[cis g'' cis,,]} + + \times 2/3{[d16 fis' d,]} \times 2/3{[cis g'' cis,,]} a'16 cis a, g''' % Used to give a nice beam directed upwards. <{\stemUp a,,4:32} \context Voice=lower{\stemDown d,:32}> diff --git a/input/regression/beam-extreme.ly b/input/regression/beam-extreme.ly index 2cdc7ae801..754553c765 100644 --- a/input/regression/beam-extreme.ly +++ b/input/regression/beam-extreme.ly @@ -14,18 +14,34 @@ extreme = \notes\relative c'' { [c16 c'' a f] \stemUp [c,,32 c'' a f] - r4 + + %%%%%%% + \stemBoth + \times 2/3{[d16 fis' d,]} \times 2/3{[cis g'' cis,,]} + a'16 cis a, g''' % Used to give a nice beam directed upwards. + \stemBoth + + \transpose c' { + \stemDown [e'8 e e'] + } } + \score { { % If we want to test extreme beams, % we should not have them auto-kneed \property Voice.Beam \override #'auto-knee-gap = ##f \extreme + + + %% what does this test? --hwn +%{ \property Voice.Beam \override #'slope-limit = #1000 \extreme + %} } \paper{ - linewidth=-1. +% raggedright = ##t + linewidth = -1 } } diff --git a/input/regression/beam-multiple-cross-staff.ly b/input/regression/beam-multiple-cross-staff.ly index f4e325bf07..a627df8d32 100644 --- a/input/regression/beam-multiple-cross-staff.ly +++ b/input/regression/beam-multiple-cross-staff.ly @@ -18,7 +18,9 @@ to the last beam. \context Staff = SB \relative c' { \clef bass [b8 b16 \stemUp b,,16 ] - [b8 b16 \stemDown b''16 b ] + + g'4\rest + [b,8 b16 \stemDown b''16 b ] } > diff --git a/lily/beam.cc b/lily/beam.cc index 15df1eaf68..c24d348c00 100644 --- a/lily/beam.cc +++ b/lily/beam.cc @@ -21,13 +21,11 @@ * Rewrite stem_beams. * Use Number_pair i.s.o Interval to represent (yl, yr). + */ -/* snapnie now also works */ -#define SNAPNIE - #include // tanh. #include "molecule.hh" @@ -63,6 +61,7 @@ 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 @@ -452,39 +451,26 @@ Beam::quanting (SCM smob) stem_infos.push (Stem::calc_stem_info (s)); dirs_found[stem_infos.top ().dir_] = true; -#ifdef SNAPNIE Real b = calc_stem_y (me, s, Interval (1,0), false); lbase_lengths.push (b); Real a = calc_stem_y (me, s, Interval (0,1), false); rbase_lengths.push (a); -#endif } Direction ldir = Direction (stem_infos[0].dir_); Direction rdir = Direction (stem_infos.top ().dir_); bool knee_b = dirs_found[LEFT] && dirs_found[RIGHT]; - /* - This - - \score { - \context Staff \notes { - \stemDown [e'8 e e'] - } - } - - breaks with REGION_SIZE < 4 - */ - int REGION_SIZE = 4; + int region_size = REGION_SIZE; /* Knees are harder, lets try some more possibilities for knees. */ if (knee_b) - REGION_SIZE += 2; + region_size += 2; - for (int i = -REGION_SIZE ; i < REGION_SIZE; i++) + for (int i = -region_size ; i < region_size; i++) for (int j = 0; j < num_quants; j++) { quantsl.push (i + quants[j] + int (yl)); @@ -587,42 +573,14 @@ Beam::score_stem_lengths (Link_arraystems, Real demerit_score = 0.0 ; Real pen = STEM_LENGTH_LIMIT_PENALTY; -#if 0 - if (knee) - pen = sqrt(pen); -#endif - - Real x0 = first_visible_stem (me)->relative_coordinate (0, X_AXIS); - Real dx = last_visible_stem (me)->relative_coordinate (0, X_AXIS) - x0; - for (int i=0; i < stems.size (); i++) { Grob* s = stems[i]; if (Stem::invisible_b (s)) continue; -#ifdef SNAPNIE - /* for a two-stemmed, interstaff beam knee up/down: - - \score { - \context PianoStaff \notes\relative c' < - \context Staff = lh { - \stemDown [c8 \translator Staff = rh \stemUp a'' ] - } - \context Staff = rh \relative c' s4 - > - } - - with yl = -5.8 (about ideal) - and yr = -1 (ridiculous pos) - this yields current_y = -8.1 (about ideal) */ - Real current_y = yl * left_factor[i] + right_factor[i]* yr; -#else - Real f = (s->relative_coordinate (0, X_AXIS) - x0) / dx; - Real current_y = yl + f * (yr - yl); -#endif Stem_info info = stem_infos[i]; Direction d = info.dir_; @@ -781,6 +739,29 @@ Beam::least_squares (SCM smob) Interval ideal (Stem::calc_stem_info (first_visible_stem (me)).ideal_y_, Stem::calc_stem_info (last_visible_stem (me)).ideal_y_); + + + + Array x_posns ; + Link_array stems= + Pointer_group_interface__extract_grobs (me, (Item*)0, "stems"); + Grob *common = stems[0]; + for (int i=1; i < stems.size (); i++) + common = stems[i]->common_refpoint (common, X_AXIS); + + Real x0 = first_visible_stem (me)->relative_coordinate (common, X_AXIS); + for (int i=0; i < stems.size (); i++) + { + Item* s = stems[i]; + + Real x = s->relative_coordinate (common, X_AXIS) - x0; + x_posns.push (x); + } + Real dx = last_visible_stem (me)->relative_coordinate (common, X_AXIS) - x0; + + Real y =0; + Real dydx = 0; + Real dy = 0; if (!ideal.delta ()) { @@ -789,11 +770,10 @@ Beam::least_squares (SCM smob) /* - TODO : use scoring for this. + TODO -- use scoring for this. complicated, because we take stem-info.ideal for determining beam slopes. - */ /* Make simple beam on middle line have small tilt */ if (!ideal[LEFT] && chord.delta () && count == 2) @@ -811,39 +791,118 @@ Beam::least_squares (SCM smob) { pos = ideal; } + + y = pos[LEFT]; + dy = pos[RIGHT]- y; + dydx = dy/dx; } else { Array ideals; - - // ugh -> use commonx - Real x0 = first_visible_stem (me)->relative_coordinate (0, X_AXIS); - Link_array stems= - Pointer_group_interface__extract_grobs (me, (Item*)0, "stems"); - for (int i=0; i < stems.size (); i++) { Item* s = stems[i]; if (Stem::invisible_b (s)) continue; - ideals.push (Offset (s->relative_coordinate (0, X_AXIS) - x0, + ideals.push (Offset (x_posns[i], Stem::calc_stem_info (s).ideal_y_)); } - Real y; - Real dydx; minimise_least_squares (&dydx, &y, ideals); - Real dx = last_visible_stem (me)->relative_coordinate (0, X_AXIS) - x0; - Real dy = dydx * dx; + dy = dydx * dx; me->set_grob_property ("least-squares-dy", gh_double2scm (dy)); - pos = Interval (y, (y+dy)); } me->set_grob_property ("positions", ly_interval2scm (pos)); + return SCM_UNSPECIFIED; } + +/* + We can't combine with previous function, since check concave and + slope damping comes first. + */ +MAKE_SCHEME_CALLBACK (Beam, shift_region_to_valid, 1); +SCM +Beam::shift_region_to_valid (SCM grob) +{ + Grob *me = unsmob_grob (grob); + /* + Code dup. + */ + Array x_posns ; + Link_array stems= + Pointer_group_interface__extract_grobs (me, (Item*)0, "stems"); + Grob *common = stems[0]; + for (int i=1; i < stems.size (); i++) + common = stems[i]->common_refpoint (common, X_AXIS); + + Real x0 = first_visible_stem (me)->relative_coordinate (common, X_AXIS); + for (int i=0; i < stems.size (); i++) + { + Item* s = stems[i]; + + Real x = s->relative_coordinate (common, X_AXIS) - x0; + x_posns.push (x); + } + Real dx = last_visible_stem (me)->relative_coordinate (common, X_AXIS) - x0; + + Interval pos = ly_scm2interval ( me->get_grob_property ("positions")); + Real dy = pos.delta(); + Real y = pos[LEFT]; + Real dydx =dy/dx; + + + /* + Shift the positions so that we have a chance of finding good + quants (i.e. no short stem failures.) + */ + Interval feasible_left_point; + feasible_left_point.set_full (); + for (int i=0; i < stems.size (); i++) + { + Item* s = stems[i]; + if (Stem::invisible_b (s)) + continue; + + + Direction d = Stem::get_direction (s); + + + /* + TODO: use real beam space function + */ + Real left_y = Stem::calc_stem_info (s).shortest_y_ + - dydx * (x_posns [i] - x0); + + Interval flp ; + flp.set_full (); + flp[-d] = left_y; + + feasible_left_point.intersect (flp); + } + + if (feasible_left_point.empty_b()) + { + warning (_("Not sure that we can find a nice beam slope (no viable initial configuration found).")); + } + else if (!feasible_left_point.elem_b(y)) + { + if (isinf (feasible_left_point[DOWN])) + y = feasible_left_point[UP] - REGION_SIZE; + else if (isinf (feasible_left_point[UP])) + y = feasible_left_point[DOWN]+ REGION_SIZE; + else + y = feasible_left_point.center (); + } + pos = Interval (y, (y+dy)); + me->set_grob_property ("positions", ly_interval2scm (pos)); + return SCM_UNSPECIFIED; +} + + MAKE_SCHEME_CALLBACK (Beam, check_concave, 1); SCM Beam::check_concave (SCM smob) @@ -1005,6 +1064,9 @@ Beam::slope_damping (SCM smob) in POS, and for stem S. If CORRECT, correct for multiplicity of beam in case of knees. + + + TODO: junk CORRECT from this. */ Real Beam::calc_stem_y (Grob *me, Grob* s, Interval pos, bool correct) @@ -1012,10 +1074,6 @@ Beam::calc_stem_y (Grob *me, Grob* s, Interval pos, bool correct) int beam_multiplicity = get_multiplicity (me); int stem_multiplicity = (Stem::duration_log (s) - 2) >? 0; - int first_multiplicity = (Stem::duration_log (first_visible_stem (me)) - - 2) >? 0; - int last_multiplicity = (Stem::duration_log (last_visible_stem (me)) - - 2) >? 0; Real thick = gh_scm2double (me->get_grob_property ("thickness")); Real interbeam = get_interbeam (me); diff --git a/lily/include/beam.hh b/lily/include/beam.hh index 3dca255c19..91198c8a64 100644 --- a/lily/include/beam.hh +++ b/lily/include/beam.hh @@ -35,6 +35,7 @@ public: DECLARE_SCHEME_CALLBACK (least_squares, (SCM)); DECLARE_SCHEME_CALLBACK (check_concave, (SCM)); DECLARE_SCHEME_CALLBACK (slope_damping, (SCM)); + DECLARE_SCHEME_CALLBACK (shift_region_to_valid, (SCM)); DECLARE_SCHEME_CALLBACK (quanting, (SCM)); static Real score_slopes_dy (Grob*, Real,Real,Real,Real); static Real score_stem_lengths (Link_array, diff --git a/lily/stem.cc b/lily/stem.cc index 61f4688c28..16fa3f2579 100644 --- a/lily/stem.cc +++ b/lily/stem.cc @@ -807,11 +807,11 @@ Stem::calc_stem_info (Grob*me) // to calculate where secondary, ternary beams will go. if (multiplicity && first_dir == mydir) ideal_y += thick + (multiplicity - 1) * interbeam_f; - - Real shortest_y = ideal_y; ideal_y += stem_length; - shortest_y += minimum_length; + + + Real shortest_y = ideal_y -stem_length + minimum_length; /* lowest beam of (UP) beam must never be lower than second staffline @@ -845,6 +845,16 @@ Stem::calc_stem_info (Grob*me) ideal_y -= gh_scm2double (s); Grob *common = me->common_refpoint (beam, Y_AXIS); + + /* + UGH -> THIS CAUSES ASYMETRY: the same beam can start/end on + different staffs. + + TODO: the beam calculation should probably also use + relative_coordinate() for the Y positions of all beams. + + + */ Real interstaff_f = mydir * (me->relative_coordinate (common, Y_AXIS) - beam->relative_coordinate (common, Y_AXIS)); diff --git a/scm/grob-description.scm b/scm/grob-description.scm index 9d6f5587ad..dae0d5d8a2 100644 --- a/scm/grob-description.scm +++ b/scm/grob-description.scm @@ -112,6 +112,7 @@ (position-callbacks . (,Beam::least_squares ,Beam::check_concave ,Beam::slope_damping + ,Beam::shift_region_to_valid ,Beam::quanting )) @@ -796,6 +797,8 @@ (molecule-callback . ,Stem::brew_molecule) (thickness . 1.3) (beamed-lengths . (0.0 2.5 2.0 1.5)) + + ;; (beamed-minimum-lengths . (0.0 1.5 1.25 1.0)) ;; Stems in unnatural (forced) direction should be shortened, -- 2.39.5