+ Real damped_dy = slope * x_span_;
+
+ set_minimum_dy (beam_, &damped_dy);
+
+ unquanted_y_[LEFT] += (dy - damped_dy) / 2;
+ unquanted_y_[RIGHT] -= (dy - damped_dy) / 2;
+ }
+}
+
+void
+Beam_scoring_problem::shift_region_to_valid ()
+{
+ if (!normal_stem_count_)
+ return;
+
+ Real beam_dy = unquanted_y_[RIGHT] - unquanted_y_[LEFT];
+ Real slope = x_span_ ? beam_dy / x_span_ : 0.0;
+
+ /*
+ Shift the positions so that we have a chance of finding good
+ quants (i.e. no short stem failures.)
+ */
+ Interval feasible_left_point;
+ feasible_left_point.set_full ();
+
+ for (vsize i = 0; i < stem_infos_.size (); i++)
+ {
+ // TODO - check for invisible here...
+ Real left_y
+ = stem_infos_[i].shortest_y_
+ - slope * stem_xpositions_ [i];
+
+ /*
+ left_y is now relative to the stem S. We want relative to
+ ourselves, so translate:
+ */
+ left_y += stem_ypositions_[i];
+ Interval flp;
+ flp.set_full ();
+ flp[-stem_infos_[i].dir_] = left_y;
+
+ feasible_left_point.intersect (flp);
+ }
+
+ vector<Grob *> filtered;
+ /*
+ We only update these for objects that are too large for quanting
+ to find a workaround. Typically, these are notes with
+ stems, and timesig/keysig/clef, which take out the entire area
+ inside the staff as feasible.
+
+ The code below disregards the thickness and multiplicity of the
+ beam. This should not be a problem, as the beam quanting will
+ take care of computing the impact those exactly.
+ */
+ Real min_y_size = 2.0;
+
+ // A list of intervals into which beams may not fall
+ vector<Interval> forbidden_intervals;
+
+ for (vsize i = 0; i < collisions_.size (); i++)
+ {
+ if (collisions_[i].x_ < 0 || collisions_[i].x_ > x_span_)
+ continue;
+
+ if (collisions_[i].y_.length () < min_y_size)
+ continue;
+
+ Direction d = LEFT;
+ do
+ {
+ Real dy = slope * collisions_[i].x_;
+
+ Direction yd = DOWN;
+ Interval disallowed;
+ do
+ {
+ Real left_y = collisions_[i].y_[yd] - dy;
+ disallowed[yd] = left_y;
+ }
+ while (flip (&yd) != DOWN);
+
+ forbidden_intervals.push_back (disallowed);
+ }
+ while (flip (&d) != LEFT);
+ }
+
+ vector_sort (forbidden_intervals, Interval::left_less);
+ Real beam_left_y = unquanted_y_[LEFT];
+ Interval feasible_beam_placements (beam_left_y, beam_left_y);
+
+ Interval_minefield minefield (feasible_beam_placements, 0.0);
+ for (vsize i = 0; i < forbidden_intervals.size (); i++)
+ minefield.add_forbidden_interval (forbidden_intervals[i]);
+ minefield.solve ();
+ feasible_beam_placements = minefield.feasible_placements ();
+
+ // if the beam placement falls out of the feasible region, we push it
+ // to infinity so that it can never be a feasible candidate below
+ Direction d = DOWN;
+ do
+ {
+ if (!feasible_left_point.contains (feasible_beam_placements[d]))
+ feasible_beam_placements[d] = d * infinity_f;
+ }
+ while (flip (&d) != DOWN);
+
+ if ((feasible_beam_placements[UP] == infinity_f && feasible_beam_placements[DOWN] == -infinity_f) && !feasible_left_point.is_empty ())
+ {
+ // We are somewhat screwed: we have a collision, but at least
+ // there is a way to satisfy stem length constraints.
+ beam_left_y = point_in_interval (feasible_left_point, 2.0);
+ }
+ else if (!feasible_left_point.is_empty ())
+ {
+ // Only one of them offers is feasible solution. Pick that one.
+ if (abs (beam_left_y - feasible_beam_placements[DOWN]) > abs (beam_left_y - feasible_beam_placements[UP]))
+ beam_left_y = feasible_beam_placements[UP];
+ else
+ beam_left_y = feasible_beam_placements[DOWN];
+ }
+ else
+ {
+ // We are completely screwed.
+ beam_->warning (_ ("no viable initial configuration found: may not find good beam slope"));
+ }
+
+ unquanted_y_ = Drul_array<Real> (beam_left_y, (beam_left_y + beam_dy));
+}
+
+void
+Beam_scoring_problem::generate_quants (vector<Beam_configuration *> *scores) const
+{
+ int region_size = (int) parameters_.REGION_SIZE;
+
+ // Knees and collisions are harder, lets try some more possibilities
+ if (is_knee_)
+ region_size += 2;
+ if (collisions_.size ())
+ region_size += 2;
+
+ Real straddle = 0.0;
+ Real sit = (beam_thickness_ - line_thickness_) / 2;
+ Real inter = 0.5;
+ Real hang = 1.0 - (beam_thickness_ - line_thickness_) / 2;
+ Real base_quants [] = {straddle, sit, inter, hang};
+ int num_base_quants = int (sizeof (base_quants) / sizeof (Real));