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> const &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 calc_concaveness (Array<int> const &positions, Direction beam_dir)
66 Real dy = positions.top () - positions[0];
67 Real slope = dy / Real (positions.size() - 1);
68 Real concaveness = 0.0;
69 for (int i = 1; i < positions.size() - 1; i++)
71 Real line_y = slope * i + positions[0];
73 concaveness += (beam_dir * (positions[i] - line_y)) >? 0.0;
76 concaveness /= positions.size () ;
79 Normalize. For dy = 0, the slope ends up as 0 anyway, so the
80 scaling of concaveness doesn't matter much.
87 MAKE_SCHEME_CALLBACK (Beam, check_concave, 1);
89 Beam::check_concave (SCM smob)
91 Grob *me = unsmob_grob (smob);
93 Link_array<Grob> stems =
94 Pointer_group_interface__extract_grobs (me, (Grob*) 0, "stems");
97 return SCM_UNSPECIFIED;
99 Direction beam_dir = CENTER;
100 for (int i = stems.size (); i--; )
102 if (Stem::is_invisible (stems[i]))
106 if (Direction dir = Stem::get_direction (stems[i]))
111 if (stems.size () <= 2)
112 return SCM_UNSPECIFIED;
115 Array<int> close_positions;
116 Array<int> far_positions;
117 for (int i= 0; i < stems.size (); i++)
120 For chords, we take the note head that is closest to the beam.
122 Hmmm.. wait, for the beams in the last measure of morgenlied,
123 this doesn't look so good. Let's try the heads farthest from
127 Interval posns = Stem::head_positions (stems[i]);
129 close_positions.push ((int) rint (posns[beam_dir]));
130 far_positions.push ((int) rint (posns[-beam_dir]));
133 if (is_concave_single_notes (far_positions, beam_dir))
135 Drul_array<Real> pos = ly_scm2interval (me->get_property ("positions"));
136 Real r = linear_combination (pos, 0.0);
138 r /= Staff_symbol_referencer::staff_space (me);
139 me->set_property ("positions", ly_interval2scm (Drul_array<Real> (r, r)));
140 me->set_property ("least-squares-dy", scm_make_real (0));
144 Real concaveness = (calc_concaveness (far_positions, beam_dir)
145 + calc_concaveness (close_positions, beam_dir))/2;
148 me->set_property ("concaveness", scm_from_double (concaveness));
151 return SCM_UNSPECIFIED;