X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fbeam-concave.cc;h=48d45c859945eaa87ded018191bb9ab421b7b640;hb=079be3c9a14d13e594cb1c1924058322a93ca1b5;hp=edd95394a50f38f7e5cd1337d9ac6129075f818d;hpb=4b975f3177880e16e759f67be4517f67109c2633;p=lilypond.git diff --git a/lily/beam-concave.cc b/lily/beam-concave.cc index edd95394a5..48d45c8599 100644 --- a/lily/beam-concave.cc +++ b/lily/beam-concave.cc @@ -1,21 +1,39 @@ +/* + beam-concave.cc -- implement Concaveness for beams. + + source file of the GNU LilyPond music typesetter + + (c) 2004 Han-Wen Nienhuys + +*/ + /* Determine whether a beam is concave. -*/ -#include + A beam is concave when the middle notes get closer to the + beam than the left and right edge notes. + + This is determined in two ways: by looking at the positions of the + middle notes, or by looking at the deviation of the inside notes + compared to the line connecting first and last. + + The tricky thing is what to do with beams with chords. There are no + real guidelines in this case. +*/ #include "pointer-group-interface.hh" -#include "array.hh" #include "stem.hh" #include "beam.hh" +#include "grob.hh" #include "staff-symbol-referencer.hh" +#include "directional-element-interface.hh" bool -is_concave_single_notes (Array const &positions, Direction beam_dir) +is_concave_single_notes (vector const &positions, Direction beam_dir) { Interval covering; covering.add_point (positions[0]); - covering.add_point (positions.top ()); + covering.add_point (positions.back ()); bool above = false; bool below = false; @@ -24,7 +42,7 @@ is_concave_single_notes (Array const &positions, Direction beam_dir) /* notes above and below the interval covered by 1st and last note. */ - for (int i = 1; i < positions.size () - 1; i++) + for (vsize i = 1; i + 1 < positions.size (); i++) { above = above || (positions[i] > covering[UP]); below = below || (positions[i] < covering[DOWN]); @@ -35,9 +53,9 @@ is_concave_single_notes (Array const &positions, Direction beam_dir) A note as close or closer to the beam than begin and end, but the note is reached in the opposite direction as the last-first dy */ - int dy = positions.top () - positions[0]; - int closest = max (beam_dir * positions.top (), beam_dir * positions[0]); - for (int i = 2; !concave && i < positions.size () - 1; i++) + int dy = positions.back () - positions[0]; + int closest = max (beam_dir * positions.back (), beam_dir * positions[0]); + for (vsize i = 2; !concave && i + 1 < positions.size (); i++) { int inner_dy = positions[i] - positions[i - 1]; if (sign (inner_dy) != sign (dy) @@ -47,7 +65,7 @@ is_concave_single_notes (Array const &positions, Direction beam_dir) } bool all_closer = true; - for (int i = 1; all_closer && i < positions.size () - 1; i++) + for (vsize i = 1; all_closer && i + 1 < positions.size (); i++) { all_closer = all_closer && (beam_dir * positions[i] > closest); @@ -58,12 +76,12 @@ is_concave_single_notes (Array const &positions, Direction beam_dir) } Real -calc_concaveness (Array const &positions, Direction beam_dir) +calc_positions_concaveness (vector const &positions, Direction beam_dir) { - Real dy = positions.top () - positions[0]; + Real dy = positions.back () - positions[0]; Real slope = dy / Real (positions.size () - 1); Real concaveness = 0.0; - for (int i = 1; i < positions.size () - 1; i++) + for (vsize i = 1; i + 1 < positions.size (); i++) { Real line_y = slope * i + positions[0]; @@ -81,36 +99,37 @@ calc_concaveness (Array const &positions, Direction beam_dir) return concaveness; } -MAKE_SCHEME_CALLBACK (Beam, check_concave, 1); + +MAKE_SCHEME_CALLBACK (Beam, calc_concaveness, 1); SCM -Beam::check_concave (SCM smob) +Beam::calc_concaveness (SCM smob) { Grob *me = unsmob_grob (smob); - Link_array stems + vector stems = extract_grob_array (me, "stems"); if (is_knee (me)) - return SCM_UNSPECIFIED; + return scm_from_double (0.0); Direction beam_dir = CENTER; - for (int i = stems.size (); i--;) + for (vsize i = stems.size (); i--;) { - if (Stem::is_invisible (stems[i])) - stems.del (i); - else + if (Stem::is_normal_stem (stems[i])) { - if (Direction dir = Stem::get_direction (stems[i])) + if (Direction dir = get_grob_direction (stems[i])) beam_dir = dir; } + else + stems.erase (stems.begin () + i); } if (stems.size () <= 2) - return SCM_UNSPECIFIED; + return scm_from_int (0); - Array close_positions; - Array far_positions; - for (int i = 0; i < stems.size (); i++) + vector close_positions; + vector far_positions; + for (vsize i = 0; i < stems.size (); i++) { /* For chords, we take the note head that is closest to the beam. @@ -118,30 +137,27 @@ Beam::check_concave (SCM smob) Hmmm.. wait, for the beams in the last measure of morgenlied, this doesn't look so good. Let's try the heads farthest from the beam. - */ Interval posns = Stem::head_positions (stems[i]); - close_positions.push ((int) rint (posns[beam_dir])); - far_positions.push ((int) rint (posns[-beam_dir])); + close_positions.push_back ((int) rint (posns[beam_dir])); + far_positions.push_back ((int) rint (posns[-beam_dir])); } - if (is_concave_single_notes (far_positions, beam_dir)) - { - Drul_array pos = ly_scm2interval (me->get_property ("positions")); - Real r = linear_combination (pos, 0.0); + Real concaveness = 0.0; - r /= Staff_symbol_referencer::staff_space (me); - me->set_property ("positions", ly_interval2scm (Drul_array (r, r))); - me->set_property ("least-squares-dy", scm_from_double (0)); + if (is_concave_single_notes (beam_dir == UP ? close_positions : far_positions, beam_dir)) + { + concaveness = 10000; } else { - Real concaveness = (calc_concaveness (far_positions, beam_dir) - + calc_concaveness (close_positions, beam_dir)) / 2; - - me->set_property ("concaveness", scm_from_double (concaveness)); + concaveness = (calc_positions_concaveness (far_positions, beam_dir) + + calc_positions_concaveness (close_positions, beam_dir)) / 2; } - return SCM_UNSPECIFIED; + return scm_from_double (concaveness); } + + +