X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fbezier.cc;h=a68c03907d047eaa49db73aa8f051e8ea22b586e;hb=1d509b27723ea1c359b51c0f2fe623a32867d6f9;hp=f230d1057d49b0ddb608f87af9d65b9eedbadc70;hpb=4bb29573149a0ffa1f881c5e38a0fe68e9e76b67;p=lilypond.git diff --git a/lily/bezier.cc b/lily/bezier.cc index f230d1057d..a68c03907d 100644 --- a/lily/bezier.cc +++ b/lily/bezier.cc @@ -81,6 +81,17 @@ Bezier::get_other_coordinate (Axis a, Real x) const return curve_coordinate (ts[0], other); } +vector +Bezier::get_other_coordinates (Axis a, Real x) const +{ + Axis other = other_axis (a); + vector ts = solve_point (a, x); + vector sols; + for (vsize i = 0; i < ts.size (); i++) + sols.push_back (curve_coordinate (ts[i], other)); + return sols; +} + Real Bezier::curve_coordinate (Real t, Axis a) const { @@ -202,6 +213,55 @@ Bezier::solve_point (Axis ax, Real coordinate) const return filter_solutions (sol); } +/** + For the portion of the curve between L and R along axis AX, + return the bounding box limit in direction D along the cross axis to AX. + If there is no portion between L and R, return 0.0 and report error. +*/ +Real +Bezier::minmax (Axis ax, Real l, Real r, Direction d) const +{ + Axis bx = other_axis (ax); + + // The curve could hit its bounding box limit along BX at: + // points where the curve is parallel to AX, + Offset vec (0.0, 0.0); + vec[ax] = 1.0; + vector sols (solve_derivative (vec)); + // or endpoints of the curve, + sols.push_back (0.999); + sols.push_back (0.001); + // (using points just inside the ends, so that an endpoint is evaulated + // if it falls within rounding error of L or R and the curve lies inside) + + Interval iv; + for (vsize i = sols.size (); i--;) + { + Offset p (curve_point (sols[i])); + if (p[ax] >= l && p[ax] <= r) + iv.add_point (p[bx]); + } + + // or intersections of the curve with the bounding lines at L and R. + Interval lr (l, r); + Direction dir = LEFT; + do + { + vector v = get_other_coordinates (ax, lr[dir]); + for (vsize i = v.size (); i--;) + iv.add_point (v[i]); + } + while (flip (&dir) != LEFT); + + if (iv.is_empty ()) + { + programming_error ("Bezier curve does not cross region of concern"); + return 0.0; + } + + return iv.at (d); +} + /** Compute the bounding box dimensions in direction of A. */