LEFT | RIGHT |
1 /* | 1 /* |
2 This file is part of LilyPond, the GNU music typesetter. | 2 This file is part of LilyPond, the GNU music typesetter. |
3 | 3 |
4 Copyright (C) 1997--2012 Han-Wen Nienhuys <hanwen@xs4all.nl> | 4 Copyright (C) 1997--2012 Han-Wen Nienhuys <hanwen@xs4all.nl> |
5 Jan Nieuwenhuizen <janneke@gnu.org> | 5 Jan Nieuwenhuizen <janneke@gnu.org> |
6 | 6 |
7 LilyPond is free software: you can redistribute it and/or modify | 7 LilyPond is free software: you can redistribute it and/or modify |
8 it under the terms of the GNU General Public License as published by | 8 it under the terms of the GNU General Public License as published by |
9 the Free Software Foundation, either version 3 of the License, or | 9 the Free Software Foundation, either version 3 of the License, or |
10 (at your option) any later version. | 10 (at your option) any later version. |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 { | 186 { |
187 beam_ = dynamic_cast<Spanner *> (me); | 187 beam_ = dynamic_cast<Spanner *> (me); |
188 unquanted_y_ = ys; | 188 unquanted_y_ = ys; |
189 | 189 |
190 /* | 190 /* |
191 If 'ys' are finite, use them as starting points for y-positions of the | 191 If 'ys' are finite, use them as starting points for y-positions of the |
192 ends of the beam, instead of the best-fit through the natural ends of | 192 ends of the beam, instead of the best-fit through the natural ends of |
193 the stems. Otherwise, we want to do initial slope calculations. | 193 the stems. Otherwise, we want to do initial slope calculations. |
194 */ | 194 */ |
195 do_initial_slope_calculations_ = false; | 195 do_initial_slope_calculations_ = false; |
196 for(LEFT_and_RIGHT(d)) | 196 for (LEFT_and_RIGHT (d)) |
197 do_initial_slope_calculations_ |= isinf (unquanted_y_[d]) || isnan (unquante
d_y_[d]); | 197 do_initial_slope_calculations_ |= isinf (unquanted_y_[d]) || isnan (unquante
d_y_[d]); |
198 | 198 |
199 /* | 199 /* |
200 Calculations are relative to a unit-scaled staff, i.e. the quants are | 200 Calculations are relative to a unit-scaled staff, i.e. the quants are |
201 divided by the current staff_space_. | 201 divided by the current staff_space_. |
202 */ | 202 */ |
203 staff_space_ = Staff_symbol_referencer::staff_space (beam_); | 203 staff_space_ = Staff_symbol_referencer::staff_space (beam_); |
204 beam_thickness_ = Beam::get_beam_thickness (beam_) / staff_space_; | 204 beam_thickness_ = Beam::get_beam_thickness (beam_) / staff_space_; |
205 line_thickness_ = Staff_symbol_referencer::line_thickness (beam_) / staff_spac
e_; | 205 line_thickness_ = Staff_symbol_referencer::line_thickness (beam_) / staff_spac
e_; |
206 | 206 |
(...skipping 29 matching lines...) Expand all Loading... |
236 vector<Grob *> collisions; | 236 vector<Grob *> collisions; |
237 | 237 |
238 for (vsize j = 0; j < fake_collisions.size (); j++) | 238 for (vsize j = 0; j < fake_collisions.size (); j++) |
239 if (fake_collisions[j]->get_system () == beams[i]->get_system ()) | 239 if (fake_collisions[j]->get_system () == beams[i]->get_system ()) |
240 collisions.push_back (fake_collisions[j]); | 240 collisions.push_back (fake_collisions[j]); |
241 | 241 |
242 Grob *common[2]; | 242 Grob *common[2]; |
243 for (int a = 2; a--;) | 243 for (int a = 2; a--;) |
244 common[a] = common_refpoint_of_array (stems, beams[i], Axis (a)); | 244 common[a] = common_refpoint_of_array (stems, beams[i], Axis (a)); |
245 | 245 |
246 for(LEFT_and_RIGHT(d)) | 246 for (LEFT_and_RIGHT (d)) |
247 common[X_AXIS] = beams[i]->get_bound (d)->common_refpoint (common[X_AXIS
], X_AXIS); | 247 common[X_AXIS] = beams[i]->get_bound (d)->common_refpoint (common[X_AXIS
], X_AXIS); |
248 | 248 |
249 // positions of the endpoints of this beam segment, including any overhang
s | 249 // positions of the endpoints of this beam segment, including any overhang
s |
250 const Interval x_pos = robust_scm2interval (beams[i]->get_property ("X-pos
itions"), | 250 const Interval x_pos = robust_scm2interval (beams[i]->get_property ("X-pos
itions"), |
251 Interval (0.0, 0.0)); | 251 Interval (0.0, 0.0)); |
252 | 252 |
253 Drul_array<Grob *> edge_stems (Beam::first_normal_stem (beams[i]), | 253 Drul_array<Grob *> edge_stems (Beam::first_normal_stem (beams[i]), |
254 Beam::last_normal_stem (beams[i])); | 254 Beam::last_normal_stem (beams[i])); |
255 | 255 |
256 Drul_array<bool> dirs_found (0, 0); | 256 Drul_array<bool> dirs_found (0, 0); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
298 is_knee_ |= dirs_found[DOWN] && dirs_found[UP]; | 298 is_knee_ |= dirs_found[DOWN] && dirs_found[UP]; |
299 | 299 |
300 staff_radius_ = Staff_symbol_referencer::staff_radius (beams[i]); | 300 staff_radius_ = Staff_symbol_referencer::staff_radius (beams[i]); |
301 edge_beam_counts_ = Drul_array<int> | 301 edge_beam_counts_ = Drul_array<int> |
302 (Stem::beam_multiplicity (stems[0]).length () + 1, | 302 (Stem::beam_multiplicity (stems[0]).length () + 1, |
303 Stem::beam_multiplicity (stems.back ()).length () + 1
); | 303 Stem::beam_multiplicity (stems.back ()).length () + 1
); |
304 | 304 |
305 // TODO - why are we dividing by staff_space_? | 305 // TODO - why are we dividing by staff_space_? |
306 beam_translation_ = Beam::get_beam_translation (beams[i]) / staff_space_; | 306 beam_translation_ = Beam::get_beam_translation (beams[i]) / staff_space_; |
307 | 307 |
308 for(LEFT_and_RIGHT(d)) | 308 for (LEFT_and_RIGHT (d)) |
309 { | 309 { |
310 quant_range_[d].set_full (); | 310 quant_range_[d].set_full (); |
311 if (!edge_stems[d]) | 311 if (!edge_stems[d]) |
312 continue; | 312 continue; |
313 | 313 |
314 Real stem_offset = edge_stems[d]->relative_coordinate (common[Y_AXIS],
Y_AXIS) | 314 Real stem_offset = edge_stems[d]->relative_coordinate (common[Y_AXIS],
Y_AXIS) |
315 - beams[i]->relative_coordinate (common[Y_AXIS], Y_
AXIS); | 315 - beams[i]->relative_coordinate (common[Y_AXIS], Y_
AXIS); |
316 Interval heads = Stem::head_positions (edge_stems[d]) * 0.5 * staff_sp
ace_; | 316 Interval heads = Stem::head_positions (edge_stems[d]) * 0.5 * staff_sp
ace_; |
317 | 317 |
318 Direction ed = edge_dirs_[d]; | 318 Direction ed = edge_dirs_[d]; |
(...skipping 23 matching lines...) Expand all Loading... |
342 if (b[X_AXIS][RIGHT] < x_pos[LEFT] || b[X_AXIS][LEFT] > x_pos[RIGHT]) | 342 if (b[X_AXIS][RIGHT] < x_pos[LEFT] || b[X_AXIS][LEFT] > x_pos[RIGHT]) |
343 continue; | 343 continue; |
344 if (b[X_AXIS].is_empty () || b[Y_AXIS].is_empty ()) | 344 if (b[X_AXIS].is_empty () || b[Y_AXIS].is_empty ()) |
345 continue; | 345 continue; |
346 | 346 |
347 b[X_AXIS] += (x_span_ - x_pos[LEFT]); | 347 b[X_AXIS] += (x_span_ - x_pos[LEFT]); |
348 b[Y_AXIS] -= my_y; | 348 b[Y_AXIS] -= my_y; |
349 Real width = b[X_AXIS].length (); | 349 Real width = b[X_AXIS].length (); |
350 Real width_factor = sqrt (width / staff_space_); | 350 Real width_factor = sqrt (width / staff_space_); |
351 | 351 |
352 for(LEFT_and_RIGHT(d)) | 352 for (LEFT_and_RIGHT (d)) |
353 add_collision (b[X_AXIS][d], b[Y_AXIS], width_factor); | 353 add_collision (b[X_AXIS][d], b[Y_AXIS], width_factor); |
354 | 354 |
355 Grob *stem = unsmob_grob (collisions[j]->get_object ("stem")); | 355 Grob *stem = unsmob_grob (collisions[j]->get_object ("stem")); |
356 if (stem && Stem::has_interface (stem) && Stem::is_normal_stem (stem)) | 356 if (stem && Stem::has_interface (stem) && Stem::is_normal_stem (stem)) |
357 { | 357 { |
358 colliding_stems.insert (stem); | 358 colliding_stems.insert (stem); |
359 } | 359 } |
360 } | 360 } |
361 | 361 |
362 for (set<Grob *>::const_iterator it (colliding_stems.begin ()); it != coll
iding_stems.end (); it++) | 362 for (set<Grob *>::const_iterator it (colliding_stems.begin ()); it != coll
iding_stems.end (); it++) |
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
779 vector<Interval> forbidden_intervals; | 779 vector<Interval> forbidden_intervals; |
780 | 780 |
781 for (vsize i = 0; i < collisions_.size (); i++) | 781 for (vsize i = 0; i < collisions_.size (); i++) |
782 { | 782 { |
783 if (collisions_[i].x_ < 0 || collisions_[i].x_ > x_span_) | 783 if (collisions_[i].x_ < 0 || collisions_[i].x_ > x_span_) |
784 continue; | 784 continue; |
785 | 785 |
786 if (collisions_[i].y_.length () < min_y_size) | 786 if (collisions_[i].y_.length () < min_y_size) |
787 continue; | 787 continue; |
788 | 788 |
789 for(LEFT_and_RIGHT(d)) | 789 for (LEFT_and_RIGHT (d)) |
790 { | 790 { |
791 Real dy = slope * collisions_[i].x_; | 791 Real dy = slope * collisions_[i].x_; |
792 | 792 |
793 Interval disallowed; | 793 Interval disallowed; |
794 for(DOWN_and_UP(yd)) | 794 for (DOWN_and_UP (yd)) |
795 { | 795 { |
796 Real left_y = collisions_[i].y_[yd] - dy; | 796 Real left_y = collisions_[i].y_[yd] - dy; |
797 disallowed[yd] = left_y; | 797 disallowed[yd] = left_y; |
798 } | 798 } |
799 | 799 |
800 forbidden_intervals.push_back (disallowed); | 800 forbidden_intervals.push_back (disallowed); |
801 } | 801 } |
802 } | 802 } |
803 | 803 |
804 vector_sort (forbidden_intervals, Interval::left_less); | 804 vector_sort (forbidden_intervals, Interval::left_less); |
805 Real beam_left_y = unquanted_y_[LEFT]; | 805 Real beam_left_y = unquanted_y_[LEFT]; |
806 Interval feasible_beam_placements (beam_left_y, beam_left_y); | 806 Interval feasible_beam_placements (beam_left_y, beam_left_y); |
807 | 807 |
808 Interval_minefield minefield (feasible_beam_placements, 0.0); | 808 Interval_minefield minefield (feasible_beam_placements, 0.0); |
809 for (vsize i = 0; i < forbidden_intervals.size (); i++) | 809 for (vsize i = 0; i < forbidden_intervals.size (); i++) |
810 minefield.add_forbidden_interval (forbidden_intervals[i]); | 810 minefield.add_forbidden_interval (forbidden_intervals[i]); |
811 minefield.solve (); | 811 minefield.solve (); |
812 feasible_beam_placements = minefield.feasible_placements (); | 812 feasible_beam_placements = minefield.feasible_placements (); |
813 | 813 |
814 // if the beam placement falls out of the feasible region, we push it | 814 // if the beam placement falls out of the feasible region, we push it |
815 // to infinity so that it can never be a feasible candidate below | 815 // to infinity so that it can never be a feasible candidate below |
816 for(DOWN_and_UP(d)) | 816 for (DOWN_and_UP (d)) |
817 { | 817 { |
818 if (!feasible_left_point.contains (feasible_beam_placements[d])) | 818 if (!feasible_left_point.contains (feasible_beam_placements[d])) |
819 feasible_beam_placements[d] = d * infinity_f; | 819 feasible_beam_placements[d] = d * infinity_f; |
820 } | 820 } |
821 | 821 |
822 if ((feasible_beam_placements[UP] == infinity_f && feasible_beam_placements[DO
WN] == -infinity_f) && !feasible_left_point.is_empty ()) | 822 if ((feasible_beam_placements[UP] == infinity_f && feasible_beam_placements[DO
WN] == -infinity_f) && !feasible_left_point.is_empty ()) |
823 { | 823 { |
824 // We are somewhat screwed: we have a collision, but at least | 824 // We are somewhat screwed: we have a collision, but at least |
825 // there is a way to satisfy stem length constraints. | 825 // there is a way to satisfy stem length constraints. |
826 beam_left_y = point_in_interval (feasible_left_point, 2.0); | 826 beam_left_y = point_in_interval (feasible_left_point, 2.0); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
871 } | 871 } |
872 | 872 |
873 for (vsize i = 0; i < unshifted_quants.size (); i++) | 873 for (vsize i = 0; i < unshifted_quants.size (); i++) |
874 for (vsize j = 0; j < unshifted_quants.size (); j++) | 874 for (vsize j = 0; j < unshifted_quants.size (); j++) |
875 { | 875 { |
876 Beam_configuration *c | 876 Beam_configuration *c |
877 = Beam_configuration::new_config (unquanted_y_, | 877 = Beam_configuration::new_config (unquanted_y_, |
878 Interval (unshifted_quants[i], | 878 Interval (unshifted_quants[i], |
879 unshifted_quants[j])); | 879 unshifted_quants[j])); |
880 | 880 |
881 for(LEFT_and_RIGHT(d)) | 881 for (LEFT_and_RIGHT (d)) |
882 { | 882 { |
883 if (!quant_range_[d].contains (c->y[d])) | 883 if (!quant_range_[d].contains (c->y[d])) |
884 { | 884 { |
885 delete c; | 885 delete c; |
886 c = NULL; | 886 c = NULL; |
887 break; | 887 break; |
888 } | 888 } |
889 } | 889 } |
890 if (c) | 890 if (c) |
891 scores->push_back (c); | 891 scores->push_back (c); |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1075 convex. Otherwise a symmetric knee beam (up/down/up/down) | 1075 convex. Otherwise a symmetric knee beam (up/down/up/down) |
1076 does not have an optimum in the middle. */ | 1076 does not have an optimum in the middle. */ |
1077 if (is_knee_) | 1077 if (is_knee_) |
1078 ideal_score = pow (ideal_score, 1.1); | 1078 ideal_score = pow (ideal_score, 1.1); |
1079 | 1079 |
1080 score[d] += length_pen * ideal_score; | 1080 score[d] += length_pen * ideal_score; |
1081 count[d]++; | 1081 count[d]++; |
1082 } | 1082 } |
1083 | 1083 |
1084 /* Divide by number of stems, to make the measure scale-free. */ | 1084 /* Divide by number of stems, to make the measure scale-free. */ |
1085 for(DOWN_and_UP(d)) | 1085 for (DOWN_and_UP (d)) |
1086 score[d] /= max (count[d], 1); | 1086 score[d] /= max (count[d], 1); |
1087 | 1087 |
1088 /* | 1088 /* |
1089 sometimes, two perfectly symmetric kneed beams will have the same score | 1089 sometimes, two perfectly symmetric kneed beams will have the same score |
1090 and can either be quanted up or down. | 1090 and can either be quanted up or down. |
1091 | 1091 |
1092 we choose the quanting in the direction of the slope so that the first stem | 1092 we choose the quanting in the direction of the slope so that the first stem |
1093 always seems longer, reaching to the second, rather than squashed. | 1093 always seems longer, reaching to the second, rather than squashed. |
1094 */ | 1094 */ |
1095 if (is_knee_ && count[LEFT] == count[RIGHT] && count[LEFT] == 1 && unquanted_y
_.delta ()) | 1095 if (is_knee_ && count[LEFT] == count[RIGHT] && count[LEFT] == 1 && unquanted_y
_.delta ()) |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1189 Beam_scoring_problem::score_forbidden_quants (Beam_configuration *config) const | 1189 Beam_scoring_problem::score_forbidden_quants (Beam_configuration *config) const |
1190 { | 1190 { |
1191 Real dy = config->y.delta (); | 1191 Real dy = config->y.delta (); |
1192 | 1192 |
1193 Real extra_demerit = parameters_.SECONDARY_BEAM_DEMERIT | 1193 Real extra_demerit = parameters_.SECONDARY_BEAM_DEMERIT |
1194 / max (edge_beam_counts_[LEFT], edge_beam_counts_[RIGHT])
; | 1194 / max (edge_beam_counts_[LEFT], edge_beam_counts_[RIGHT])
; |
1195 | 1195 |
1196 Real dem = 0.0; | 1196 Real dem = 0.0; |
1197 Real eps = parameters_.BEAM_EPS; | 1197 Real eps = parameters_.BEAM_EPS; |
1198 | 1198 |
1199 for(LEFT_and_RIGHT(d)) | 1199 for (LEFT_and_RIGHT (d)) |
1200 { | 1200 { |
1201 for (int j = 1; j <= edge_beam_counts_[d]; j++) | 1201 for (int j = 1; j <= edge_beam_counts_[d]; j++) |
1202 { | 1202 { |
1203 Direction stem_dir = edge_dirs_[d]; | 1203 Direction stem_dir = edge_dirs_[d]; |
1204 | 1204 |
1205 /* | 1205 /* |
1206 The 2.2 factor is to provide a little leniency for | 1206 The 2.2 factor is to provide a little leniency for |
1207 borderline cases. If we do 2.0, then the upper outer line | 1207 borderline cases. If we do 2.0, then the upper outer line |
1208 will be in the gap of the (2, sit) quant, leading to a | 1208 will be in the gap of the (2, sit) quant, leading to a |
1209 false demerit. | 1209 false demerit. |
(...skipping 30 matching lines...) Expand all Loading... |
1240 } | 1240 } |
1241 } | 1241 } |
1242 | 1242 |
1243 if (max (edge_beam_counts_[LEFT], edge_beam_counts_[RIGHT]) >= 2) | 1243 if (max (edge_beam_counts_[LEFT], edge_beam_counts_[RIGHT]) >= 2) |
1244 { | 1244 { |
1245 Real straddle = 0.0; | 1245 Real straddle = 0.0; |
1246 Real sit = (beam_thickness_ - line_thickness_) / 2; | 1246 Real sit = (beam_thickness_ - line_thickness_) / 2; |
1247 Real inter = 0.5; | 1247 Real inter = 0.5; |
1248 Real hang = 1.0 - (beam_thickness_ - line_thickness_) / 2; | 1248 Real hang = 1.0 - (beam_thickness_ - line_thickness_) / 2; |
1249 | 1249 |
1250 for(LEFT_and_RIGHT(d)) | 1250 for (LEFT_and_RIGHT (d)) |
1251 { | 1251 { |
1252 if (edge_beam_counts_[d] >= 2 | 1252 if (edge_beam_counts_[d] >= 2 |
1253 && fabs (config->y[d] - edge_dirs_[d] * beam_translation_) < staff
_radius_ + inter) | 1253 && fabs (config->y[d] - edge_dirs_[d] * beam_translation_) < staff
_radius_ + inter) |
1254 { | 1254 { |
1255 // TODO up/down symmetry. | 1255 // TODO up/down symmetry. |
1256 if (edge_dirs_[d] == UP && dy <= eps | 1256 if (edge_dirs_[d] == UP && dy <= eps |
1257 && fabs (my_modf (config->y[d]) - sit) < eps) | 1257 && fabs (my_modf (config->y[d]) - sit) < eps) |
1258 dem += extra_demerit; | 1258 dem += extra_demerit; |
1259 | 1259 |
1260 if (edge_dirs_[d] == DOWN && dy >= eps | 1260 if (edge_dirs_[d] == DOWN && dy >= eps |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1302 Real scale_free | 1302 Real scale_free |
1303 = max (parameters_.COLLISION_PADDING - dist, 0.0) | 1303 = max (parameters_.COLLISION_PADDING - dist, 0.0) |
1304 / parameters_.COLLISION_PADDING; | 1304 / parameters_.COLLISION_PADDING; |
1305 demerits | 1305 demerits |
1306 += collisions_[i].base_penalty_ * | 1306 += collisions_[i].base_penalty_ * |
1307 pow (scale_free, 3) * parameters_.COLLISION_PENALTY; | 1307 pow (scale_free, 3) * parameters_.COLLISION_PENALTY; |
1308 } | 1308 } |
1309 | 1309 |
1310 config->add (demerits, "C"); | 1310 config->add (demerits, "C"); |
1311 } | 1311 } |
LEFT | RIGHT |