X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fbezier.cc;h=0a0f4cfc6ff3f18962548c44bf391e9ba99762ad;hb=a4d6cf4907b5ec9a897f2d8f142b0452222433d0;hp=ce84ce8da89c7623c68548539c49112c67b4c481;hpb=1b99f1907fb77b0f3a0e65725776782c3eeaa025;p=lilypond.git diff --git a/lily/bezier.cc b/lily/bezier.cc index ce84ce8da8..0a0f4cfc6f 100644 --- a/lily/bezier.cc +++ b/lily/bezier.cc @@ -213,49 +213,59 @@ Bezier::solve_point (Axis ax, Real coordinate) const return filter_solutions (sol); } +/** + Assuming AX is X_AXIS, and D is UP, finds the + maximum value of curve_coordinate(t, Y_AXIS) subject to + l <= curve_coordinate(t, X_AXIS) <= r. +*/ Real Bezier::minmax (Axis ax, Real l, Real r, Direction d) const { - return minmax (ax, l, r, d, 0, 0); -} - -Real -Bezier::minmax (Axis axis, Real l, Real r, Direction d, vsize left_index, vsize right_index) const -{ - Axis other = other_axis (axis); + Axis other = other_axis (ax); Interval lr (l, r); - Drul_array > sol; + vector solutions; + + // Possible solutions are: + // t = 0 or 1, or... + solutions.push_back (0); + solutions.push_back (1); + + // t is a critical point for the other-axis polynomial, or... + Polynomial p_prime (polynomial (other)); + p_prime.differentiate (); + vector criticals = p_prime.solve (); + solutions.insert (solutions.end (), criticals.begin (), criticals.end ()); + + // t solves curve_coordinate(t, X_AXIS) = l or r. Direction dir = LEFT; do { - Polynomial p (polynomial (axis)); + Polynomial p (polynomial (ax)); p.coefs_[0] -= lr[dir]; - sol[dir] = filter_solutions (p.solve ()); + vector sol = p.solve (); + solutions.insert (solutions.end (), sol.begin (), sol.end ()); } while (flip (&dir) != LEFT); - if (!sol[LEFT].size () || !sol[RIGHT].size ()) + Polynomial p (polynomial (ax)); + Polynomial other_p (polynomial (other)); + vector values; + for (vsize i = solutions.size (); i--;) { - programming_error ("no solution found for Bezier intersection"); - return 0.0; + Real t = solutions[i]; + if (t >= 0 && t <= 1 && p.eval (t) >= l && p.eval (t) <= r) + values.push_back (other_p.eval (t)); } - Polynomial p (polynomial (other)); - - Drul_array indices(left_index, right_index); - do + if (values.empty ()) { - vector_sort (sol[dir], less ()); - if (!Interval (0, sol[LEFT].size () - 1).contains (indices[dir])) - { - programming_error ("requested bezier solution outside range of solutions. defaulting to lowest solution."); - indices[dir] = 0; - } + programming_error ("no solution found for Bezier intersection"); + return 0.0; } - while (flip (&dir) != LEFT); - return p.minmax (sol[LEFT][indices[LEFT]], sol[RIGHT][indices[RIGHT]], d != LEFT); + vector_sort (values, less ()); + return (d == DOWN) ? values[0] : values.back (); } /**