]> git.donarmstrong.com Git - lilypond.git/blob - lily/beam-quanting.cc
Run grand-replace for 2012
[lilypond.git] / lily / beam-quanting.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 1997--2012 Han-Wen Nienhuys <hanwen@xs4all.nl>
5   Jan Nieuwenhuizen <janneke@gnu.org>
6
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
9   the Free Software Foundation, either version 3 of the License, or
10   (at your option) any later version.
11
12   LilyPond is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "beam-scoring-problem.hh"
22
23 #include <algorithm>
24 #include <queue>
25 #include <set>
26 using namespace std;
27
28 #include "align-interface.hh"
29 #include "beam.hh"
30 #include "direction.hh"
31 #include "directional-element-interface.hh"
32 #include "grob.hh"
33 #include "grob-array.hh"
34 #include "item.hh"
35 #include "international.hh"
36 #include "interval-minefield.hh"
37 #include "least-squares.hh"
38 #include "libc-extension.hh"
39 #include "main.hh"
40 #include "note-head.hh"
41 #include "output-def.hh"
42 #include "pointer-group-interface.hh"
43 #include "spanner.hh"
44 #include "staff-symbol-referencer.hh"
45 #include "stencil.hh"
46 #include "stem.hh"
47 #include "warn.hh"
48
49 Real
50 get_detail (SCM alist, SCM sym, Real def)
51 {
52   SCM entry = scm_assq (sym, alist);
53
54   if (scm_is_pair (entry))
55     return robust_scm2double (scm_cdr (entry), def);
56   return def;
57 }
58
59 void
60 Beam_quant_parameters::fill (Grob *him)
61 {
62   SCM details = him->get_property ("details");
63
64   // General
65   BEAM_EPS = get_detail (details, ly_symbol2scm ("beam-eps"), 1e-3);
66   REGION_SIZE = get_detail (details, ly_symbol2scm ("region-size"), 2);
67
68   // forbidden quants
69   SECONDARY_BEAM_DEMERIT = get_detail (details, ly_symbol2scm ("secondary-beam-demerit"), 10.0);
70   STEM_LENGTH_DEMERIT_FACTOR = get_detail (details, ly_symbol2scm ("stem-length-demerit-factor"), 5);
71   HORIZONTAL_INTER_QUANT_PENALTY = get_detail (details, ly_symbol2scm ("horizontal-inter-quant"), 500);
72
73   STEM_LENGTH_LIMIT_PENALTY = get_detail (details, ly_symbol2scm ("stem-length-limit-penalty"), 5000);
74   DAMPING_DIRECTION_PENALTY = get_detail (details, ly_symbol2scm ("damping-direction-penalty"), 800);
75   HINT_DIRECTION_PENALTY = get_detail (details, ly_symbol2scm ("hint-direction-penalty"), 20);
76   MUSICAL_DIRECTION_FACTOR = get_detail (details, ly_symbol2scm ("musical-direction-factor"), 400);
77   IDEAL_SLOPE_FACTOR = get_detail (details, ly_symbol2scm ("ideal-slope-factor"), 10);
78   ROUND_TO_ZERO_SLOPE = get_detail (details, ly_symbol2scm ("round-to-zero-slope"), 0.02);
79
80   // Collisions
81   COLLISION_PENALTY = get_detail (details, ly_symbol2scm ("collision-penalty"), 500);
82   COLLISION_PADDING = get_detail (details, ly_symbol2scm ("collision-padding"), 0.5);
83   STEM_COLLISION_FACTOR = get_detail (details, ly_symbol2scm ("stem-collision-factor"), 0.1);
84 }
85
86 // Add x if x is positive, add |x|*fac if x is negative.
87 static Real
88 shrink_extra_weight (Real x, Real fac)
89 {
90   return fabs (x) * ((x < 0) ? fac : 1.0);
91 }
92
93 /****************************************************************/
94
95 Beam_configuration::Beam_configuration ()
96 {
97   y = Interval (0.0, 0.0);
98   demerits = 0.0;
99   next_scorer_todo = ORIGINAL_DISTANCE;
100 }
101
102 bool Beam_configuration::done () const
103 {
104   return next_scorer_todo >= NUM_SCORERS;
105 }
106
107 void Beam_configuration::add (Real demerit, const string &reason)
108 {
109   demerits += demerit;
110
111 #if DEBUG_BEAM_SCORING
112   if (demerit)
113     score_card_ += to_string (" %s %.2f", reason.c_str (), demerit);
114 #endif
115 }
116
117 Beam_configuration *Beam_configuration::new_config (Interval start,
118                                                     Interval offset)
119 {
120   Beam_configuration *qs = new Beam_configuration;
121   qs->y = Interval (int (start[LEFT]) + offset[LEFT],
122                     int (start[RIGHT]) + offset[RIGHT]);
123
124   // This orders the sequence so we try combinations closest to the
125   // the ideal offset first.
126   Real start_score = abs (offset[RIGHT]) + abs (offset[LEFT]);
127   qs->demerits = start_score / 1000.0;
128   qs->next_scorer_todo = ORIGINAL_DISTANCE + 1;
129
130   return qs;
131 }
132
133 Real
134 Beam_scoring_problem::y_at (Real x, Beam_configuration const *p) const
135 {
136   return p->y[LEFT] + x * p->y.delta () / x_span_;
137 }
138
139 /****************************************************************/
140
141 /*
142   TODO:
143
144   - Make all demerits customisable
145
146   - Add demerits for quants per se, as to forbid a specific quant
147   entirely
148 */
149
150 // This is a temporary hack to see how much we can gain by using a
151 // priority queue on the beams to score.
152 static int score_count = 0;
153 LY_DEFINE (ly_beam_score_count, "ly:beam-score-count", 0, 0, 0,
154            (),
155            "count number of beam scores.")
156 {
157   return scm_from_int (score_count);
158 }
159
160 void Beam_scoring_problem::add_collision (Real x, Interval y,
161                                           Real score_factor)
162 {
163   // We used to screen for quant range, but no more.
164
165   Beam_collision c;
166   c.beam_y_.set_empty ();
167
168   for (vsize j = 0; j < segments_.size (); j++)
169     {
170       if (segments_[j].horizontal_.contains (x))
171         c.beam_y_.add_point (segments_[j].vertical_count_ * beam_translation_);
172       if (segments_[j].horizontal_[LEFT] > x)
173         break;
174     }
175   c.beam_y_.widen (0.5 * beam_thickness_);
176
177   c.x_ = x;
178
179   y *= 1 / staff_space_;
180   c.y_ = y;
181   c.base_penalty_ = score_factor;
182   collisions_.push_back (c);
183 }
184
185 void Beam_scoring_problem::init_instance_variables (Grob *me, Drul_array<Real> ys, bool align_broken_intos)
186 {
187   beam_ = dynamic_cast<Spanner *> (me);
188   unquanted_y_ = ys;
189
190   /*
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
193     the stems.  Otherwise, we want to do initial slope calculations.
194   */
195   do_initial_slope_calculations_ = false;
196   Direction d = LEFT;
197   do
198     do_initial_slope_calculations_ |= isinf (unquanted_y_[d]) || isnan (unquanted_y_[d]);
199   while (flip (&d) != LEFT);
200
201   /*
202     Calculations are relative to a unit-scaled staff, i.e. the quants are
203     divided by the current staff_space_.
204   */
205   staff_space_ = Staff_symbol_referencer::staff_space (beam_);
206   beam_thickness_ = Beam::get_beam_thickness (beam_) / staff_space_;
207   line_thickness_ = Staff_symbol_referencer::line_thickness (beam_) / staff_space_;
208
209   // This is the least-squares DY, corrected for concave beams.
210   musical_dy_ = robust_scm2double (beam_->get_property ("least-squares-dy"), 0);
211
212   vector<Spanner *> beams;
213   align_broken_intos_ = align_broken_intos;
214   if (align_broken_intos_)
215     {
216       Spanner *orig = dynamic_cast<Spanner *> (beam_->original ());
217       if (!orig)
218         align_broken_intos_ = false;
219       else if (!orig->broken_intos_.size ())
220         align_broken_intos_ = false;
221       else
222         beams.insert (beams.end (), orig->broken_intos_.begin (), orig->broken_intos_.end ());
223     }
224   if (!align_broken_intos_)
225     beams.push_back (beam_);
226
227   /*
228     x_span_ is a single scalar, cumulatively summing the length of all the
229     segments the parent beam was broken-into.
230   */
231   x_span_ = 0.0;
232   is_knee_ = false;
233   normal_stem_count_ = 0;
234   for (vsize i = 0; i < beams.size (); i++)
235     {
236       extract_grob_set (beams[i], "stems", stems);
237       extract_grob_set (beams[i], "covered-grobs", fake_collisions);
238       vector<Grob *> collisions;
239
240       for (vsize j = 0; j < fake_collisions.size (); j++)
241         if (fake_collisions[j]->get_system () == beams[i]->get_system ())
242           collisions.push_back (fake_collisions[j]);
243
244       Grob *common[2];
245       for (int a = 2; a--;)
246         common[a] = common_refpoint_of_array (stems, beams[i], Axis (a));
247
248       Direction d = LEFT;
249       do
250         common[X_AXIS] = beams[i]->get_bound (d)->common_refpoint (common[X_AXIS], X_AXIS);
251       while (flip (&d) != LEFT);
252
253       // positions of the endpoints of this beam segment, including any overhangs
254       const Interval x_pos = robust_scm2interval (beams[i]->get_property ("X-positions"),
255                                                   Interval (0.0, 0.0));
256
257       Drul_array<Grob *> edge_stems (Beam::first_normal_stem (beams[i]),
258                                      Beam::last_normal_stem (beams[i]));
259
260       Drul_array<bool> dirs_found (0, 0);
261
262       Real my_y = beams[i]->relative_coordinate (common[Y_AXIS], Y_AXIS);
263
264       Interval beam_width (-1.0, -1.0);
265       for (vsize j = 0; j < stems.size (); j++)
266         {
267           Grob *s = stems[j];
268           beam_multiplicity_.push_back (Stem::beam_multiplicity (stems[j]));
269           head_positions_.push_back (Stem::head_positions (stems[j]));
270           is_normal_.push_back (Stem::is_normal_stem (stems[j]));
271
272           Stem_info si (Stem::get_stem_info (s));
273           si.scale (1 / staff_space_);
274           stem_infos_.push_back (si);
275           chord_start_y_.push_back (Stem::chord_start_y (s));
276           dirs_found[si.dir_] = true;
277
278           bool f = to_boolean (s->get_property ("french-beaming"))
279                    && s != edge_stems[LEFT] && s != edge_stems[RIGHT];
280
281           Real y = Beam::calc_stem_y (beams[i], s, common, x_pos[LEFT], x_pos[RIGHT], CENTER,
282                                       Interval (0, 0), f);
283           base_lengths_.push_back (y / staff_space_);
284           stem_xpositions_.push_back (s->relative_coordinate (common[X_AXIS], X_AXIS) - x_pos[LEFT] + x_span_);
285           stem_ypositions_.push_back (s->relative_coordinate (common[Y_AXIS], Y_AXIS) - my_y);
286
287           if (is_normal_.back ())
288             {
289               if (beam_width[LEFT] == -1.0)
290                 beam_width[LEFT] = stem_xpositions_.back ();
291               beam_width[RIGHT] = stem_xpositions_.back ();
292             }
293         }
294
295       edge_dirs_ = Drul_array<Direction> (CENTER, CENTER);
296       normal_stem_count_ += Beam::normal_stem_count (beams[i]);
297       if (normal_stem_count_)
298         edge_dirs_ = Drul_array<Direction> (stem_infos_[0].dir_,
299                                             stem_infos_.back ().dir_);
300
301       is_xstaff_ = Align_interface::has_interface (common[Y_AXIS]);
302       is_knee_ |= dirs_found[DOWN] && dirs_found[UP];
303
304       staff_radius_ = Staff_symbol_referencer::staff_radius (beams[i]);
305       edge_beam_counts_ = Drul_array<int>
306                           (Stem::beam_multiplicity (stems[0]).length () + 1,
307                            Stem::beam_multiplicity (stems.back ()).length () + 1);
308
309       // TODO - why are we dividing by staff_space_?
310       beam_translation_ = Beam::get_beam_translation (beams[i]) / staff_space_;
311
312       d = LEFT;
313       do
314         {
315           quant_range_[d].set_full ();
316           if (!edge_stems[d])
317             continue;
318
319           Real stem_offset = edge_stems[d]->relative_coordinate (common[Y_AXIS], Y_AXIS)
320                              - beams[i]->relative_coordinate (common[Y_AXIS], Y_AXIS);
321           Interval heads = Stem::head_positions (edge_stems[d]) * 0.5 * staff_space_;
322
323           Direction ed = edge_dirs_[d];
324           heads.widen (0.5 * staff_space_
325                        + (edge_beam_counts_[d] - 1) * beam_translation_ + beam_thickness_ * .5);
326           quant_range_[d][-ed] = heads[ed] + stem_offset;
327         }
328       while (flip (&d) != LEFT);
329
330       segments_ = Beam::get_beam_segments (beams[i]);
331       vector_sort (segments_, beam_segment_less);
332       for (vsize j = 0; j < segments_.size (); j++)
333         segments_[j].horizontal_ += (x_span_ - x_pos[LEFT]);
334
335       set<Grob *> colliding_stems;
336       for (vsize j = 0; j < collisions.size (); j++)
337         {
338           if (!collisions[j]->is_live ())
339             continue;
340
341           if (Beam::has_interface (collisions[j]) && Beam::is_cross_staff (collisions[j]))
342             continue;
343
344           Box b;
345           for (Axis a = X_AXIS; a < NO_AXES; incr (a))
346             b[a] = collisions[j]->extent (common[a], a);
347
348           if (b[X_AXIS][RIGHT] < x_pos[LEFT] || b[X_AXIS][LEFT] > x_pos[RIGHT])
349             continue;
350           if (b[X_AXIS].is_empty () || b[Y_AXIS].is_empty ())
351             continue;
352
353           b[X_AXIS] += (x_span_ - x_pos[LEFT]);
354           b[Y_AXIS] -= my_y;
355           Real width = b[X_AXIS].length ();
356           Real width_factor = sqrt (width / staff_space_);
357
358           Direction d = LEFT;
359           do
360             add_collision (b[X_AXIS][d], b[Y_AXIS], width_factor);
361           while (flip (&d) != LEFT);
362
363           Grob *stem = unsmob_grob (collisions[j]->get_object ("stem"));
364           if (stem && Stem::has_interface (stem) && Stem::is_normal_stem (stem))
365             {
366               colliding_stems.insert (stem);
367             }
368         }
369
370       for (set<Grob *>::const_iterator it (colliding_stems.begin ()); it != colliding_stems.end (); it++)
371         {
372           Grob *s = *it;
373           Real x = (s->extent (common[X_AXIS], X_AXIS) - x_pos[LEFT] + x_span_).center ();
374
375           Direction stem_dir = get_grob_direction (*it);
376           Interval y;
377           y.set_full ();
378           y[-stem_dir] = Stem::chord_start_y (*it) + (*it)->relative_coordinate (common[Y_AXIS], Y_AXIS)
379                          - my_y;
380
381           Real factor = parameters_.STEM_COLLISION_FACTOR;
382           if (!unsmob_grob (s->get_object ("beam")))
383             factor = 1.0;
384           add_collision (x, y, factor);
385         }
386       x_span_ += beams[i]->spanner_length ();
387     }
388 }
389
390 Beam_scoring_problem::Beam_scoring_problem (Grob *me, Drul_array<Real> ys, bool align_broken_intos)
391 {
392   beam_ = dynamic_cast<Spanner *> (me);
393   unquanted_y_ = ys;
394   align_broken_intos_ = align_broken_intos;
395
396   parameters_.fill (me);
397   init_instance_variables (me, ys, align_broken_intos);
398   if (do_initial_slope_calculations_)
399     {
400       least_squares_positions ();
401       slope_damping ();
402       shift_region_to_valid ();
403     }
404 }
405
406 // Assuming V is not empty, pick a 'reasonable' point inside V.
407 static Real
408 point_in_interval (Interval v, Real dist)
409 {
410   if (isinf (v[DOWN]))
411     return v[UP] - dist;
412   else if (isinf (v[UP]))
413     return v[DOWN] + dist;
414   else
415     return v.center ();
416 }
417
418 /* Set stem's shorten property if unset.
419
420 TODO:
421 take some y-position (chord/beam/nearest?) into account
422 scmify forced-fraction
423
424 This is done in beam because the shorten has to be uniform over the
425 entire beam.
426 */
427
428 void
429 set_minimum_dy (Grob *me, Real *dy)
430 {
431   if (*dy)
432     {
433       /*
434         If dy is smaller than the smallest quant, we
435         get absurd direction-sign penalties.
436       */
437
438       Real ss = Staff_symbol_referencer::staff_space (me);
439       Real beam_thickness = Beam::get_beam_thickness (me) / ss;
440       Real slt = Staff_symbol_referencer::line_thickness (me) / ss;
441       Real sit = (beam_thickness - slt) / 2;
442       Real inter = 0.5;
443       Real hang = 1.0 - (beam_thickness - slt) / 2;
444
445       *dy = sign (*dy) * max (fabs (*dy),
446                               min (min (sit, inter), hang));
447     }
448 }
449
450 void
451 Beam_scoring_problem::no_visible_stem_positions ()
452 {
453   if (!head_positions_.size ())
454     {
455       unquanted_y_ = Interval (0, 0);
456       return;
457     }
458
459   Interval head_positions;
460   Slice multiplicity;
461   for (vsize i = 0; i < head_positions_.size (); i++)
462     {
463       head_positions.unite (head_positions_[i]);
464       multiplicity.unite (beam_multiplicity_[i]);
465     }
466
467   Direction dir = get_grob_direction (beam_);
468
469   if (!dir)
470     programming_error ("The beam should have a direction by now.");
471
472   Real y = head_positions.linear_combination (dir)
473            * 0.5 * staff_space_
474            + dir * beam_translation_ * (multiplicity.length () + 1);
475
476   unquanted_y_ = Interval (y, y);
477 }
478
479 vsize
480 Beam_scoring_problem::first_normal_index ()
481 {
482   for (vsize i = 0; i < is_normal_.size (); i++)
483     if (is_normal_[i])
484       return i;
485
486   beam_->programming_error ("No normal stems, but asking for first normal stem index.");
487   return 0;
488 }
489
490 vsize
491 Beam_scoring_problem::last_normal_index ()
492 {
493   for (vsize i = is_normal_.size (); i--;)
494     if (is_normal_[i])
495       return i;
496
497   beam_->programming_error ("No normal stems, but asking for first normal stem index.");
498   return 0;
499 }
500
501 void
502 Beam_scoring_problem::least_squares_positions ()
503 {
504   if (!normal_stem_count_)
505     {
506       no_visible_stem_positions ();
507       return;
508     }
509
510   if (stem_infos_.size () < 1)
511     return;
512
513   vsize fnx = first_normal_index ();
514   vsize lnx = last_normal_index ();
515
516   Interval ideal (stem_infos_[fnx].ideal_y_ + stem_ypositions_[fnx],
517                   stem_infos_[lnx].ideal_y_ + stem_ypositions_[lnx]);
518
519   Real y = 0;
520   Real slope = 0;
521   Real dy = 0;
522   Real ldy = 0.0;
523   if (!ideal.delta ())
524     {
525       Interval chord (chord_start_y_[0],
526                       chord_start_y_.back ());
527
528       /* Simple beams (2 stems) on middle line should be allowed to be
529          slightly sloped.
530
531          However, if both stems reach middle line,
532          ideal[LEFT] == ideal[RIGHT] and ideal.delta () == 0.
533
534          For that case, we apply artificial slope */
535       if (!ideal[LEFT] && chord.delta () && stem_infos_.size () == 2)
536         {
537           /* FIXME. -> UP */
538           Direction d = (Direction) (sign (chord.delta ()) * UP);
539           unquanted_y_[d] = Beam::get_beam_thickness (beam_) / 2;
540           unquanted_y_[-d] = -unquanted_y_[d];
541         }
542       else
543         unquanted_y_ = ideal;
544
545       ldy = unquanted_y_[RIGHT] - unquanted_y_[LEFT];
546     }
547   else
548     {
549       vector<Offset> ideals;
550       for (vsize i = 0; i < stem_infos_.size (); i++)
551         if (is_normal_[i])
552           ideals.push_back (Offset (stem_xpositions_[i],
553                                     stem_infos_[i].ideal_y_
554                                     + stem_ypositions_[i]));
555
556       minimise_least_squares (&slope, &y, ideals);
557
558       dy = slope * x_span_;
559
560       set_minimum_dy (beam_, &dy);
561
562       ldy = dy;
563       unquanted_y_ = Interval (y, (y + dy));
564     }
565
566   musical_dy_ = ldy;
567   beam_->set_property ("least-squares-dy", scm_from_double (musical_dy_));
568 }
569
570 /*
571   Determine whether a beam is concave.
572
573   A beam is concave when the middle notes get closer to the
574   beam than the left and right edge notes.
575
576   This is determined in two ways: by looking at the positions of the
577   middle notes, or by looking at the deviation of the inside notes
578   compared to the line connecting first and last.
579
580   The tricky thing is what to do with beams with chords. There are no
581   real guidelines in this case.
582 */
583
584 bool
585 is_concave_single_notes (vector<int> const &positions, Direction beam_dir)
586 {
587   Interval covering;
588   covering.add_point (positions[0]);
589   covering.add_point (positions.back ());
590
591   bool above = false;
592   bool below = false;
593   bool concave = false;
594
595   /*
596     notes above and below the interval covered by 1st and last note.
597   */
598   for (vsize i = 1; i + 1 < positions.size (); i++)
599     {
600       above = above || (positions[i] > covering[UP]);
601       below = below || (positions[i] < covering[DOWN]);
602     }
603
604   concave = concave || (above && below);
605   /*
606     A note as close or closer to the beam than begin and end, but the
607     note is reached in the opposite direction as the last-first dy
608   */
609   int dy = positions.back () - positions[0];
610   int closest = max (beam_dir * positions.back (), beam_dir * positions[0]);
611   for (vsize i = 2; !concave && i + 1 < positions.size (); i++)
612     {
613       int inner_dy = positions[i] - positions[i - 1];
614       if (sign (inner_dy) != sign (dy)
615           && (beam_dir * positions[i] >= closest
616               || beam_dir * positions[i - 1] >= closest))
617         concave = true;
618     }
619
620   bool all_closer = true;
621   for (vsize i = 1; all_closer && i + 1 < positions.size (); i++)
622     {
623       all_closer = all_closer
624                    && (beam_dir * positions[i] > closest);
625     }
626
627   concave = concave || all_closer;
628   return concave;
629 }
630
631 Real
632 calc_positions_concaveness (vector<int> const &positions, Direction beam_dir)
633 {
634   Real dy = positions.back () - positions[0];
635   Real slope = dy / Real (positions.size () - 1);
636   Real concaveness = 0.0;
637   for (vsize i = 1; i + 1 < positions.size (); i++)
638     {
639       Real line_y = slope * i + positions[0];
640
641       concaveness += max (beam_dir * (positions[i] - line_y), 0.0);
642     }
643
644   concaveness /= positions.size ();
645
646   /*
647     Normalize. For dy = 0, the slope ends up as 0 anyway, so the
648     scaling of concaveness doesn't matter much.
649   */
650   if (dy)
651     concaveness /= fabs (dy);
652   return concaveness;
653 }
654
655 Real
656 Beam_scoring_problem::calc_concaveness ()
657 {
658   SCM conc = beam_->get_property ("concaveness");
659   if (scm_is_number (conc))
660     return scm_to_double (conc);
661
662   if (is_knee_)
663     return 0.0;
664
665   Direction beam_dir = CENTER;
666   for (vsize i = is_normal_.size (); i--;)
667     if (is_normal_[i] && stem_infos_[i].dir_)
668       beam_dir = stem_infos_[i].dir_;
669
670   if (normal_stem_count_ <= 2)
671     return 0.0;
672
673   vector<int> close_positions;
674   vector<int> far_positions;
675   for (vsize i = 0; i < is_normal_.size (); i++)
676     if (is_normal_[i])
677       {
678         /*
679           For chords, we take the note head that is closest to the beam.
680
681           Hmmm.. wait, for the beams in the last measure of morgenlied,
682           this doesn't look so good. Let's try the heads farthest from
683           the beam.
684         */
685
686         close_positions.push_back ((int) rint (head_positions_[i][beam_dir]));
687         far_positions.push_back ((int) rint (head_positions_[i][-beam_dir]));
688       }
689
690   Real concaveness = 0.0;
691
692   if (is_concave_single_notes (beam_dir == UP ? close_positions : far_positions, beam_dir))
693     {
694       concaveness = 10000;
695     }
696   else
697     {
698       concaveness = (calc_positions_concaveness (far_positions, beam_dir)
699                      + calc_positions_concaveness (close_positions, beam_dir)) / 2;
700     }
701
702   return concaveness;
703 }
704
705 void
706 Beam_scoring_problem::slope_damping ()
707 {
708   if (normal_stem_count_ <= 1)
709     return;
710
711   SCM s = beam_->get_property ("damping");
712   Real damping = scm_to_double (s);
713   Real concaveness = calc_concaveness ();
714   if (concaveness >= 10000)
715     {
716       unquanted_y_[LEFT] = unquanted_y_[RIGHT];
717       musical_dy_ = 0;
718       damping = 0;
719     }
720
721   if (damping)
722     {
723       Real dy = unquanted_y_[RIGHT] - unquanted_y_[LEFT];
724
725       Real slope = dy && x_span_ ? dy / x_span_ : 0;
726
727       slope = 0.6 * tanh (slope) / (damping + concaveness);
728
729       Real damped_dy = slope * x_span_;
730
731       set_minimum_dy (beam_, &damped_dy);
732
733       unquanted_y_[LEFT] += (dy - damped_dy) / 2;
734       unquanted_y_[RIGHT] -= (dy - damped_dy) / 2;
735     }
736 }
737
738 void
739 Beam_scoring_problem::shift_region_to_valid ()
740 {
741   if (!normal_stem_count_)
742     return;
743
744   Real beam_dy = unquanted_y_[RIGHT] - unquanted_y_[LEFT];
745   Real slope = x_span_ ? beam_dy / x_span_ : 0.0;
746
747   /*
748     Shift the positions so that we have a chance of finding good
749     quants (i.e. no short stem failures.)
750   */
751   Interval feasible_left_point;
752   feasible_left_point.set_full ();
753
754   for (vsize i = 0; i < stem_infos_.size (); i++)
755     {
756       // TODO - check for invisible here...
757       Real left_y
758         = stem_infos_[i].shortest_y_
759           - slope * stem_xpositions_ [i];
760
761       /*
762         left_y is now relative to the stem S. We want relative to
763         ourselves, so translate:
764       */
765       left_y += stem_ypositions_[i];
766       Interval flp;
767       flp.set_full ();
768       flp[-stem_infos_[i].dir_] = left_y;
769
770       feasible_left_point.intersect (flp);
771     }
772
773   vector<Grob *> filtered;
774   /*
775     We only update these for objects that are too large for quanting
776     to find a workaround.  Typically, these are notes with
777     stems, and timesig/keysig/clef, which take out the entire area
778     inside the staff as feasible.
779
780     The code below disregards the thickness and multiplicity of the
781     beam.  This should not be a problem, as the beam quanting will
782     take care of computing the impact those exactly.
783   */
784   Real min_y_size = 2.0;
785
786   // A list of intervals into which beams may not fall
787   vector<Interval> forbidden_intervals;
788
789   for (vsize i = 0; i < collisions_.size (); i++)
790     {
791       if (collisions_[i].x_ < 0 || collisions_[i].x_ > x_span_)
792         continue;
793
794       if (collisions_[i].y_.length () < min_y_size)
795         continue;
796
797       Direction d = LEFT;
798       do
799         {
800           Real dy = slope * collisions_[i].x_;
801
802           Direction yd = DOWN;
803           Interval disallowed;
804           do
805             {
806               Real left_y = collisions_[i].y_[yd] - dy;
807               disallowed[yd] = left_y;
808             }
809           while (flip (&yd) != DOWN);
810
811           forbidden_intervals.push_back (disallowed);
812         }
813       while (flip (&d) != LEFT);
814     }
815
816   vector_sort (forbidden_intervals, Interval::left_less);
817   Real beam_left_y = unquanted_y_[LEFT];
818   Interval feasible_beam_placements (beam_left_y, beam_left_y);
819
820   Interval_minefield minefield (feasible_beam_placements, 0.0);
821   for (vsize i = 0; i < forbidden_intervals.size (); i++)
822     minefield.add_forbidden_interval (forbidden_intervals[i]);
823   minefield.solve ();
824   feasible_beam_placements = minefield.feasible_placements ();
825
826   // if the beam placement falls out of the feasible region, we push it
827   // to infinity so that it can never be a feasible candidate below
828   Direction d = DOWN;
829   do
830     {
831       if (!feasible_left_point.contains (feasible_beam_placements[d]))
832         feasible_beam_placements[d] = d * infinity_f;
833     }
834   while (flip (&d) != DOWN);
835
836   if ((feasible_beam_placements[UP] == infinity_f && feasible_beam_placements[DOWN] == -infinity_f) && !feasible_left_point.is_empty ())
837     {
838       // We are somewhat screwed: we have a collision, but at least
839       // there is a way to satisfy stem length constraints.
840       beam_left_y = point_in_interval (feasible_left_point, 2.0);
841     }
842   else if (!feasible_left_point.is_empty ())
843     {
844       // Only one of them offers is feasible solution. Pick that one.
845       if (abs (beam_left_y - feasible_beam_placements[DOWN]) > abs (beam_left_y - feasible_beam_placements[UP]))
846         beam_left_y = feasible_beam_placements[UP];
847       else
848         beam_left_y = feasible_beam_placements[DOWN];
849     }
850   else
851     {
852       // We are completely screwed.
853       beam_->warning (_ ("no viable initial configuration found: may not find good beam slope"));
854     }
855
856   unquanted_y_ = Drul_array<Real> (beam_left_y, (beam_left_y + beam_dy));
857 }
858
859 void
860 Beam_scoring_problem::generate_quants (vector<Beam_configuration *> *scores) const
861 {
862   int region_size = (int) parameters_.REGION_SIZE;
863
864   // Knees and collisions are harder, lets try some more possibilities
865   if (is_knee_)
866     region_size += 2;
867   if (collisions_.size ())
868     region_size += 2;
869
870   Real straddle = 0.0;
871   Real sit = (beam_thickness_ - line_thickness_) / 2;
872   Real inter = 0.5;
873   Real hang = 1.0 - (beam_thickness_ - line_thickness_) / 2;
874   Real base_quants [] = {straddle, sit, inter, hang};
875   int num_base_quants = int (sizeof (base_quants) / sizeof (Real));
876
877   /*
878     Asymetry ? should run to <= region_size ?
879   */
880   vector<Real> unshifted_quants;
881   for (int i = -region_size; i < region_size; i++)
882     for (int j = 0; j < num_base_quants; j++)
883       {
884         unshifted_quants.push_back (i + base_quants[j]);
885       }
886
887   for (vsize i = 0; i < unshifted_quants.size (); i++)
888     for (vsize j = 0; j < unshifted_quants.size (); j++)
889       {
890         Beam_configuration *c
891           = Beam_configuration::new_config (unquanted_y_,
892                                             Interval (unshifted_quants[i],
893                                                       unshifted_quants[j]));
894
895         Direction d = LEFT;
896         do
897           {
898             if (!quant_range_[d].contains (c->y[d]))
899               {
900                 delete c;
901                 c = NULL;
902                 break;
903               }
904           }
905         while (flip (&d) != LEFT);
906         if (c)
907           scores->push_back (c);
908       }
909
910 }
911
912 void Beam_scoring_problem::one_scorer (Beam_configuration *config) const
913 {
914   score_count++;
915   switch (config->next_scorer_todo)
916     {
917     case SLOPE_IDEAL:
918       score_slope_ideal (config);
919       break;
920     case SLOPE_DIRECTION:
921       score_slope_direction (config);
922       break;
923     case SLOPE_MUSICAL:
924       score_slope_musical (config);
925       break;
926     case FORBIDDEN:
927       score_forbidden_quants (config);
928       break;
929     case STEM_LENGTHS:
930       score_stem_lengths (config);
931       break;
932     case COLLISIONS:
933       score_collisions (config);
934       break;
935     case HORIZONTAL_INTER:
936       score_horizontal_inter_quants (config);
937       break;
938
939     case NUM_SCORERS:
940     case ORIGINAL_DISTANCE:
941     default:
942       assert (false);
943     }
944   config->next_scorer_todo++;
945 }
946
947 Beam_configuration *
948 Beam_scoring_problem::force_score (SCM inspect_quants, const vector<Beam_configuration *> &configs) const
949 {
950   Drul_array<Real> ins = ly_scm2interval (inspect_quants);
951   Real mindist = 1e6;
952   Beam_configuration *best = NULL;
953   for (vsize i = 0; i < configs.size (); i++)
954     {
955       Real d = fabs (configs[i]->y[LEFT] - ins[LEFT]) + fabs (configs[i]->y[RIGHT] - ins[RIGHT]);
956       if (d < mindist)
957         {
958           best = configs[i];
959           mindist = d;
960         }
961     }
962   if (mindist > 1e5)
963     programming_error ("cannot find quant");
964
965   while (!best->done ())
966     one_scorer (best);
967
968   return best;
969 }
970
971 Drul_array<Real>
972 Beam_scoring_problem::solve () const
973 {
974   vector<Beam_configuration *> configs;
975   generate_quants (&configs);
976
977   if (configs.empty ())
978     {
979       programming_error ("No viable beam quanting found.  Using unquanted y value.");
980       return unquanted_y_;
981     }
982
983   if (to_boolean (beam_->get_property ("skip-quanting")))
984     return unquanted_y_;
985
986   Beam_configuration *best = NULL;
987
988   bool debug
989     = to_boolean (beam_->layout ()->lookup_variable (ly_symbol2scm ("debug-beam-scoring")));
990   SCM inspect_quants = beam_->get_property ("inspect-quants");
991   if (scm_is_pair (inspect_quants))
992     {
993       debug = true;
994       best = force_score (inspect_quants, configs);
995     }
996   else
997     {
998       std::priority_queue < Beam_configuration *, std::vector<Beam_configuration *>,
999           Beam_configuration_less > queue;
1000       for (vsize i = 0; i < configs.size (); i++)
1001         queue.push (configs[i]);
1002
1003       /*
1004         TODO
1005
1006         It would be neat if we generated new configurations on the
1007         fly, depending on the best complete score so far, eg.
1008
1009         if (best->done()) {
1010           if (best->demerits < sqrt(queue.size())
1011             break;
1012           while (best->demerits > sqrt(queue.size()) {
1013             generate and insert new configuration
1014           }
1015         }
1016
1017         that would allow us to do away with region_size altogether.
1018       */
1019       while (true)
1020         {
1021           best = queue.top ();
1022           if (best->done ())
1023             break;
1024
1025           queue.pop ();
1026           one_scorer (best);
1027           queue.push (best);
1028         }
1029     }
1030
1031   Interval final_positions = best->y;
1032
1033 #if DEBUG_BEAM_SCORING
1034   if (debug)
1035     {
1036       // debug quanting
1037       int completed = 0;
1038       for (vsize i = 0; i < configs.size (); i++)
1039         {
1040           if (configs[i]->done ())
1041             completed++;
1042         }
1043
1044       string card = best->score_card_ + to_string (" c%d/%d", completed, configs.size ());
1045       beam_->set_property ("annotation", ly_string2scm (card));
1046     }
1047 #endif
1048
1049   junk_pointers (configs);
1050   if (align_broken_intos_)
1051     {
1052       Interval normalized_endpoints = robust_scm2interval (beam_->get_property ("normalized-endpoints"), Interval (0, 1));
1053       Real y_length = final_positions[RIGHT] - final_positions[LEFT];
1054
1055       final_positions[LEFT] += normalized_endpoints[LEFT] * y_length;
1056       final_positions[RIGHT] -= (1 - normalized_endpoints[RIGHT]) * y_length;
1057     }
1058
1059   return final_positions;
1060 }
1061
1062 void
1063 Beam_scoring_problem::score_stem_lengths (Beam_configuration *config) const
1064 {
1065   Real limit_penalty = parameters_.STEM_LENGTH_LIMIT_PENALTY;
1066   Drul_array<Real> score (0, 0);
1067   Drul_array<int> count (0, 0);
1068
1069   for (vsize i = 0; i < stem_xpositions_.size (); i++)
1070     {
1071       if (!is_normal_[i])
1072         continue;
1073
1074       Real x = stem_xpositions_[i];
1075       Real dx = x_span_;
1076       Real beam_y = dx
1077                     ? config->y[RIGHT] * x / dx + config->y[LEFT] * (x_span_ - x) / dx
1078                     : (config->y[RIGHT] + config->y[LEFT]) / 2;
1079       Real current_y = beam_y + base_lengths_[i];
1080       Real length_pen = parameters_.STEM_LENGTH_DEMERIT_FACTOR;
1081
1082       Stem_info info = stem_infos_[i];
1083       Direction d = info.dir_;
1084
1085       score[d] += limit_penalty * max (0.0, (d * (info.shortest_y_ - current_y)));
1086
1087       Real ideal_diff = d * (current_y - info.ideal_y_);
1088       Real ideal_score = shrink_extra_weight (ideal_diff, 1.5);
1089
1090       /* We introduce a power, to make the scoring strictly
1091          convex. Otherwise a symmetric knee beam (up/down/up/down)
1092          does not have an optimum in the middle. */
1093       if (is_knee_)
1094         ideal_score = pow (ideal_score, 1.1);
1095
1096       score[d] += length_pen * ideal_score;
1097       count[d]++;
1098     }
1099
1100   /* Divide by number of stems, to make the measure scale-free. */
1101   Direction d = DOWN;
1102   do
1103     score[d] /= max (count[d], 1);
1104   while (flip (&d) != DOWN);
1105
1106   /*
1107     sometimes, two perfectly symmetric kneed beams will have the same score
1108     and can either be quanted up or down.
1109
1110     we choose the quanting in the direction of the slope so that the first stem
1111     always seems longer, reaching to the second, rather than squashed.
1112   */
1113   if (is_knee_ && count[LEFT] == count[RIGHT] && count[LEFT] == 1 && unquanted_y_.delta ())
1114     score[Direction (sign (unquanted_y_.delta ()))] += score[Direction (sign (unquanted_y_.delta ()))] < 1.0 ? 0.01 : 0.0;
1115
1116   config->add (score[LEFT] + score[RIGHT], "L");
1117 }
1118
1119 void
1120 Beam_scoring_problem::score_slope_direction (Beam_configuration *config) const
1121 {
1122   Real dy = config->y.delta ();
1123   Real damped_dy = unquanted_y_.delta ();
1124   Real dem = 0.0;
1125   /*
1126     DAMPING_DIRECTION_PENALTY is a very harsh measure, while for
1127     complex beaming patterns, horizontal is often a good choice.
1128
1129     TODO: find a way to incorporate the complexity of the beam in this
1130     penalty.
1131   */
1132   if (sign (damped_dy) != sign (dy))
1133     {
1134       if (!dy)
1135         {
1136           if (fabs (damped_dy / x_span_) > parameters_.ROUND_TO_ZERO_SLOPE)
1137             dem += parameters_.DAMPING_DIRECTION_PENALTY;
1138           else
1139             dem += parameters_.HINT_DIRECTION_PENALTY;
1140         }
1141       else
1142         dem += parameters_.DAMPING_DIRECTION_PENALTY;
1143     }
1144
1145   config->add (dem, "Sd");
1146 }
1147
1148 // Score for going against the direction of the musical pattern
1149 void
1150 Beam_scoring_problem::score_slope_musical (Beam_configuration *config) const
1151 {
1152   Real dy = config->y.delta ();
1153   Real dem = parameters_.MUSICAL_DIRECTION_FACTOR
1154              * max (0.0, (fabs (dy) - fabs (musical_dy_)));
1155   config->add (dem, "Sm");
1156 }
1157
1158 // Score deviation from calculated ideal slope.
1159 void
1160 Beam_scoring_problem::score_slope_ideal (Beam_configuration *config) const
1161 {
1162   Real dy = config->y.delta ();
1163   Real damped_dy = unquanted_y_.delta ();
1164   Real dem = 0.0;
1165
1166   Real slope_penalty = parameters_.IDEAL_SLOPE_FACTOR;
1167
1168   /* Xstaff beams tend to use extreme slopes to get short stems. We
1169      put in a penalty here. */
1170   if (is_xstaff_)
1171     slope_penalty *= 10;
1172
1173   /* Huh, why would a too steep beam be better than a too flat one ? */
1174   dem += shrink_extra_weight (fabs (damped_dy) - fabs (dy), 1.5)
1175          * slope_penalty;
1176
1177   config->add (dem, "Si");
1178 }
1179
1180 static Real
1181 my_modf (Real x)
1182 {
1183   return x - floor (x);
1184 }
1185
1186 // TODO - there is some overlap with forbidden quants, but for
1187 // horizontal beams, it is much more serious to have stafflines
1188 // appearing in the wrong place, so we have a separate scorer.
1189 void
1190 Beam_scoring_problem::score_horizontal_inter_quants (Beam_configuration *config) const
1191 {
1192   if (config->y.delta () == 0.0
1193       && abs (config->y[LEFT]) < staff_radius_ * staff_space_)
1194     {
1195       Real yshift = config->y[LEFT] - 0.5 * staff_space_;
1196       if (fabs (my_round (yshift) - yshift) < 0.01 * staff_space_)
1197         config->add (parameters_.HORIZONTAL_INTER_QUANT_PENALTY, "H");
1198     }
1199 }
1200
1201 /*
1202   TODO: The fixed value SECONDARY_BEAM_DEMERIT is probably flawed:
1203   because for 32nd and 64th beams the forbidden quants are relatively
1204   more important than stem lengths.
1205 */
1206 void
1207 Beam_scoring_problem::score_forbidden_quants (Beam_configuration *config) const
1208 {
1209   Real dy = config->y.delta ();
1210
1211   Real extra_demerit = parameters_.SECONDARY_BEAM_DEMERIT
1212                        / max (edge_beam_counts_[LEFT], edge_beam_counts_[RIGHT]);
1213
1214   Direction d = LEFT;
1215   Real dem = 0.0;
1216   Real eps = parameters_.BEAM_EPS;
1217
1218   do
1219     {
1220       for (int j = 1; j <= edge_beam_counts_[d]; j++)
1221         {
1222           Direction stem_dir = edge_dirs_[d];
1223
1224           /*
1225             The 2.2 factor is to provide a little leniency for
1226             borderline cases. If we do 2.0, then the upper outer line
1227             will be in the gap of the (2, sit) quant, leading to a
1228             false demerit.
1229           */
1230           Real gap1 = config->y[d] - stem_dir * ((j - 1) * beam_translation_ + beam_thickness_ / 2 - line_thickness_ / 2.2);
1231           Real gap2 = config->y[d] - stem_dir * (j * beam_translation_ - beam_thickness_ / 2 + line_thickness_ / 2.2);
1232
1233           Interval gap;
1234           gap.add_point (gap1);
1235           gap.add_point (gap2);
1236
1237           for (Real k = -staff_radius_;
1238                k <= staff_radius_ + eps; k += 1.0)
1239             if (gap.contains (k))
1240               {
1241                 Real dist = min (fabs (gap[UP] - k), fabs (gap[DOWN] - k));
1242
1243                 /*
1244                   this parameter is tuned to grace-stem-length.ly
1245                   retuned from 0.40 to 0.39 by MS because of slight increases
1246                   in gap.length () resulting from measuring beams at real ends
1247                   instead of from the middle of stems.
1248
1249                   TODO:
1250                   This function needs better comments so we know what is forbidden
1251                   and why.
1252                 */
1253                 Real fixed_demerit = 0.39;
1254
1255                 dem += extra_demerit
1256                        * (fixed_demerit
1257                           + (1 - fixed_demerit) * (dist / gap.length ()) * 2);
1258               }
1259         }
1260     }
1261   while ((flip (&d)) != LEFT);
1262
1263   if (max (edge_beam_counts_[LEFT], edge_beam_counts_[RIGHT]) >= 2)
1264     {
1265       Real straddle = 0.0;
1266       Real sit = (beam_thickness_ - line_thickness_) / 2;
1267       Real inter = 0.5;
1268       Real hang = 1.0 - (beam_thickness_ - line_thickness_) / 2;
1269
1270       Direction d = LEFT;
1271       do
1272         {
1273           if (edge_beam_counts_[d] >= 2
1274               && fabs (config->y[d] - edge_dirs_[d] * beam_translation_) < staff_radius_ + inter)
1275             {
1276               // TODO up/down symmetry.
1277               if (edge_dirs_[d] == UP && dy <= eps
1278                   && fabs (my_modf (config->y[d]) - sit) < eps)
1279                 dem += extra_demerit;
1280
1281               if (edge_dirs_[d] == DOWN && dy >= eps
1282                   && fabs (my_modf (config->y[d]) - hang) < eps)
1283                 dem += extra_demerit;
1284             }
1285
1286           if (edge_beam_counts_[d] >= 3
1287               && fabs (config->y[d] - 2 * edge_dirs_[d] * beam_translation_) < staff_radius_ + inter)
1288             {
1289               // TODO up/down symmetry.
1290               if (edge_dirs_[d] == UP && dy <= eps
1291                   && fabs (my_modf (config->y[d]) - straddle) < eps)
1292                 dem += extra_demerit;
1293
1294               if (edge_dirs_[d] == DOWN && dy >= eps
1295                   && fabs (my_modf (config->y[d]) - straddle) < eps)
1296                 dem += extra_demerit;
1297             }
1298         }
1299       while (flip (&d) != LEFT);
1300     }
1301
1302   config->add (dem, "F");
1303 }
1304
1305 void
1306 Beam_scoring_problem::score_collisions (Beam_configuration *config) const
1307 {
1308   Real demerits = 0.0;
1309   for (vsize i = 0; i < collisions_.size (); i++)
1310     {
1311       Interval collision_y = collisions_[i].y_;
1312       Real x = collisions_[i].x_;
1313
1314       Real center_beam_y = y_at (x, config);
1315       Interval beam_y = center_beam_y + collisions_[i].beam_y_;
1316
1317       Real dist = infinity_f;
1318       if (!intersection (beam_y, collision_y).is_empty ())
1319         dist = 0.0;
1320       else
1321         dist = min (beam_y.distance (collision_y[DOWN]),
1322                     beam_y.distance (collision_y[UP]));
1323
1324       Real scale_free
1325         = max (parameters_.COLLISION_PADDING - dist, 0.0)
1326           / parameters_.COLLISION_PADDING;
1327       demerits
1328       += collisions_[i].base_penalty_ *
1329          pow (scale_free, 3) * parameters_.COLLISION_PENALTY;
1330     }
1331
1332   config->add (demerits, "C");
1333 }