- me->set_grob_property ("positions", ly_interval2scm (pos));
- return SCM_UNSPECIFIED;
-}
-
-
-MAKE_SCHEME_CALLBACK (Beam, check_concave, 1);
-SCM
-Beam::check_concave (SCM smob)
-{
- Grob *me = unsmob_grob (smob);
-
- Link_array<Grob> stems =
- Pointer_group_interface__extract_grobs (me, (Grob*) 0, "stems");
-
- for (int i = 0; i < stems.size ();)
- {
- if (Stem::invisible_b (stems[i]))
- stems.del (i);
- else
- i++;
- }
-
- if (stems.size () < 3)
- return SCM_UNSPECIFIED;
-
-
- /* Concaveness #1: If distance of an inner notehead to line between
- two outer noteheads is bigger than CONCAVENESS-GAP (2.0ss),
- beam is concave (Heinz Stolba).
-
- In the case of knees, the line connecting outer heads is often
- not related to the beam slope (it may even go in the other
- direction). Skip the check when the outer stems point in
- different directions. --hwn
-
- */
- bool concaveness1 = false;
- SCM gap = me->get_grob_property ("concaveness-gap");
- if (gh_number_p (gap)
- && Stem::get_direction(stems.top ())
- == Stem::get_direction(stems[0]))
- {
- Real r1 = gh_scm2double (gap);
- Real dy = Stem::chord_start_y (stems.top ())
- - Stem::chord_start_y (stems[0]);
-
-
- Real slope = dy / (stems.size () - 1);
-
- Real y0 = Stem::chord_start_y (stems[0]);
- for (int i = 1; i < stems.size () - 1; i++)
- {
- Real c = (Stem::chord_start_y (stems[i]) - y0) - i * slope;
- if (c > r1)
- {
- concaveness1 = true;
- break;
- }
- }
- }
-
-
- /* Concaveness #2: Sum distances of inner noteheads that fall
- outside the interval of the two outer noteheads.
-
- We only do this for beams where first and last stem have the same
- direction. --hwn.
-
-
- Note that "convex" stems compensate for "concave" stems.
- (is that intentional?) --hwn.
- */
-
- Real concaveness2 = 0;
- SCM thresh = me->get_grob_property ("concaveness-threshold");
- Real r2 = infinity_f;
- if (!concaveness1 && gh_number_p (thresh)
- && Stem::get_direction(stems.top ())
- == Stem::get_direction(stems[0]))
- {
- r2 = gh_scm2double (thresh);
-
- Direction dir = Stem::get_direction(stems.top ());
- Real concave = 0;
- Interval iv (Stem::chord_start_y (stems[0]),
- Stem::chord_start_y (stems.top ()));
-
- if (iv[MAX] < iv[MIN])
- iv.swap ();
-
- for (int i = 1; i < stems.size () - 1; i++)
- {
- Real f = Stem::chord_start_y (stems[i]);
- concave += ((f - iv[MAX] ) >? 0) +
- ((f - iv[MIN] ) <? 0);
- }
- concave *= dir;
- concaveness2 = concave / (stems.size () - 2);
-
- /*
-
- ugh: this is the a kludge to get
- input/regression/beam-concave.ly to behave as
- baerenreiter.
-
- */
-
- /*
- huh? we're dividing twice (which is not scalable) meaning that
- the longer the beam, the more unlikely it will be
- concave. Maybe you would even expect the other way around??
-
- --hwn.
-
- */
- concaveness2 /= (stems.size () - 2);
- }
-
- /* TODO: some sort of damping iso -> plain horizontal */
- if (concaveness1 || concaveness2 > r2)
- {
- Drul_array<Real> pos = ly_scm2interval (me->get_grob_property ("positions"));
- Real r = linear_combination (pos, 0);
-
- r /= Staff_symbol_referencer::staff_space (me);
- me->set_grob_property ("positions", ly_interval2scm (Drul_array<Real> (r, r)));
- me->set_grob_property ("least-squares-dy", gh_double2scm (0));
- }
-