2 Determine whether a beam is concave.
7 #include "group-interface.hh"
11 #include "interval.hh"
13 #include "staff-symbol-referencer.hh"
16 is_concave_single_notes (Array<int> positions, Direction beam_dir)
19 covering.add_point (positions[0]);
20 covering.add_point (positions.top ());
27 notes above and below the interval covered by 1st and last note.
29 for (int i = 1; i < positions.size () - 1; i++)
31 above = above || (positions[i] > covering[UP]);
32 below = below || (positions[i] < covering[DOWN]);
36 concave = concave || (above && below);
38 A note as close or closer to the beam than begin and end, but the
39 note is reached in the opposite direction as the last-first dy
41 int dy = positions.top() - positions[0];
42 int closest = (beam_dir * positions.top()) >? (beam_dir *positions[0]);
43 for (int i = 2; !concave && i < positions.size () - 1; i++)
45 int inner_dy = positions[i] - positions[i-1];
46 if (sign (inner_dy) != sign (dy)
47 && (beam_dir * positions[i] >= closest
48 || beam_dir * positions[i-1] >= closest))
52 bool all_closer = true;
53 for (int i = 1; all_closer && i < positions.size ()-1; i++)
55 all_closer = all_closer &&
56 (beam_dir * positions[i] > closest);
59 concave = concave || all_closer;
64 MAKE_SCHEME_CALLBACK (Beam, check_concave, 1);
66 Beam::check_concave (SCM smob)
68 Grob *me = unsmob_grob (smob);
70 Link_array<Grob> stems =
71 Pointer_group_interface__extract_grobs (me, (Grob*) 0, "stems");
74 return SCM_UNSPECIFIED;
76 Direction beam_dir = CENTER;
77 for (int i = stems.size (); i--; )
79 if (Stem::is_invisible (stems[i]))
83 if (Direction dir = Stem::get_direction (stems[i]))
88 if (stems.size () <= 2)
89 return SCM_UNSPECIFIED;
93 for (int i= 0; i < stems.size (); i++)
96 For chords, we take the note head that is closest to the beam.
98 Hmmm.. wait, for the beams in the last measure of morgenlied,
99 this doesn't look so good. Let's try the heads farthest from
103 Real pos = Stem::head_positions (stems[i])[-beam_dir];
105 positions.push ((int) rint (pos));
108 if (is_concave_single_notes (positions, beam_dir))
110 Drul_array<Real> pos = ly_scm2interval (me->get_property ("positions"));
111 Real r = linear_combination (pos, 0.0);
113 r /= Staff_symbol_referencer::staff_space (me);
114 me->set_property ("positions", ly_interval2scm (Drul_array<Real> (r, r)));
115 me->set_property ("least-squares-dy", scm_make_real (0));
119 Real dy = positions.top () - positions[0];
120 Real slope = dy / Real (positions.size() - 1);
121 Real concaveness = 0.0;
122 for (int i = 1; i < positions.size() - 1; i++)
124 Real line_y = slope * i + positions[0];
126 concaveness += (beam_dir * (positions[i] - line_y)) >? 0.0;
129 concaveness /= positions.size () ;
132 Normalize. For dy = 0, the slope ends up as 0 anyway, so the
133 scaling of concaveness doesn't matter much.
138 me->set_property ("concaveness", scm_from_double (concaveness));
141 return SCM_UNSPECIFIED;