* lexer-gcc-3.1.sh: Remove.
[lilypond/patrick.git] / lily / beam-concave.cc
blob47ee57bbf512f81dddd178b619857cc8ec553e8f
1 /*
2 Determine whether a beam is concave.
3 */
5 #include "pointer-group-interface.hh"
6 #include "std-vector.hh"
7 #include "stem.hh"
8 #include "beam.hh"
9 #include "staff-symbol-referencer.hh"
10 #include "directional-element-interface.hh"
12 bool
13 is_concave_single_notes (vector<int> const &positions, Direction beam_dir)
15 Interval covering;
16 covering.add_point (positions[0]);
17 covering.add_point (positions.back ());
19 bool above = false;
20 bool below = false;
21 bool concave = false;
24 notes above and below the interval covered by 1st and last note.
26 for (vsize i = 1; i < positions.size () - 1; i++)
28 above = above || (positions[i] > covering[UP]);
29 below = below || (positions[i] < covering[DOWN]);
32 concave = concave || (above && below);
34 A note as close or closer to the beam than begin and end, but the
35 note is reached in the opposite direction as the last-first dy
37 int dy = positions.back () - positions[0];
38 int closest = max (beam_dir * positions.back (), beam_dir * positions[0]);
39 for (vsize i = 2; !concave && i < positions.size () - 1; i++)
41 int inner_dy = positions[i] - positions[i - 1];
42 if (sign (inner_dy) != sign (dy)
43 && (beam_dir * positions[i] >= closest
44 || beam_dir * positions[i - 1] >= closest))
45 concave = true;
48 bool all_closer = true;
49 for (vsize i = 1; all_closer && i < positions.size () - 1; i++)
51 all_closer = all_closer
52 && (beam_dir * positions[i] > closest);
55 concave = concave || all_closer;
56 return concave;
59 Real
60 calc_positions_concaveness (vector<int> const &positions, Direction beam_dir)
62 Real dy = positions.back () - positions[0];
63 Real slope = dy / Real (positions.size () - 1);
64 Real concaveness = 0.0;
65 for (vsize i = 1; i < positions.size () - 1; i++)
67 Real line_y = slope * i + positions[0];
69 concaveness += max (beam_dir * (positions[i] - line_y), 0.0);
72 concaveness /= positions.size ();
75 Normalize. For dy = 0, the slope ends up as 0 anyway, so the
76 scaling of concaveness doesn't matter much.
78 if (dy)
79 concaveness /= fabs (dy);
80 return concaveness;
84 MAKE_SCHEME_CALLBACK (Beam, calc_concaveness, 1);
85 SCM
86 Beam::calc_concaveness (SCM smob)
88 Grob *me = unsmob_grob (smob);
90 vector<Grob*> stems
91 = extract_grob_array (me, "stems");
93 if (is_knee (me))
94 return scm_from_double (0.0);
96 Direction beam_dir = CENTER;
97 for (vsize i = stems.size (); i--;)
99 if (Stem::is_invisible (stems[i]))
100 stems.erase (stems.begin () + i);
101 else
103 if (Direction dir = get_grob_direction (stems[i]))
104 beam_dir = dir;
108 if (stems.size () <= 2)
109 return SCM_UNSPECIFIED;
111 vector<int> close_positions;
112 vector<int> far_positions;
113 for (vsize i = 0; i < stems.size (); i++)
116 For chords, we take the note head that is closest to the beam.
118 Hmmm.. wait, for the beams in the last measure of morgenlied,
119 this doesn't look so good. Let's try the heads farthest from
120 the beam.
123 Interval posns = Stem::head_positions (stems[i]);
125 close_positions.push_back ((int) rint (posns[beam_dir]));
126 far_positions.push_back ((int) rint (posns[-beam_dir]));
129 Real concaveness = 0.0;
131 if (is_concave_single_notes (far_positions, beam_dir))
133 concaveness = 10000;
135 else
137 concaveness = (calc_positions_concaveness (far_positions, beam_dir)
138 + calc_positions_concaveness (close_positions, beam_dir)) / 2;
141 return scm_from_double (concaveness);