public static double CubicBezierLength( double ax, double ay, double bx, double by, double cx, double cy, double dx, double dy) { const int steps = 10;// Probably should be a parameter. double t; (double X, double Y)previous_dot = (0d, 0d); var length = 0d; for (var i = 0; i <= steps; i++) { t = (double)i / steps; var dot = InterpolateCubic2DTests.CubicInterpolate2D(t, ax, ay, bx, by, cx, cy, dx, dy); if (i > 0) { var x_diff = dot.X - previous_dot.X; var y_diff = dot.Y - previous_dot.Y; length += Sqrt((x_diff * x_diff) + (y_diff * y_diff)); } previous_dot = dot; } return(length); }
/// <summary> /// Build the LUT. /// </summary> /// <param name="a">The a.</param> /// <param name="b">The b.</param> /// <param name="c">The c.</param> /// <param name="d">The d.</param> /// <returns>The <see cref="List{Point2D}"/>.</returns> /// <acknowledgment> /// http://stackoverflow.com/questions/27053888/how-to-get-time-value-from-bezier-curve-given-length/27071218#27071218 /// </acknowledgment> public static List <Point2D> BuildLUT(Point2D a, Point2D b, Point2D c, Point2D d) { var Lut = new List <Point2D>(100); for (double t = 0; t <= 1; t += 0.01) { Lut[(int)(t * 100)] = new Point2D(InterpolateCubic2DTests.CubicInterpolate2D(t, a.X, a.Y, b.X, b.Y, c.X, c.Y, d.X, d.Y)); } return(Lut); }
public static (double X, double Y)? CubicBezierSelfIntersection1(double x0, double y0, double x1, double y1, double x2, double y2, double x3, double y3) { var(xCurveA, xCurveB, xCurveC, xCurveD) = CubicBezierBernsteinBasisTests.CubicBezierBernsteinBasis(x0, x1, x2, x3); (var a, var b) = (xCurveD == 0d) ? (xCurveC, xCurveB) : (xCurveC / xCurveD, xCurveB / xCurveD); var(yCurveA, yCurveB, yCurveC, yCurveD) = CubicBezierBernsteinBasisTests.CubicBezierBernsteinBasis(y0, y1, y2, y3); (var p, var q) = (yCurveD == 0d) ? (yCurveC, yCurveB) : (yCurveC / yCurveD, yCurveB / yCurveD); if (a == p || q == b) { return(null); } var k = (q - b) / (a - p); var poly = new double[] { (-k * k * k) - (a * k * k) - (b * k), (3 * k * k) + (2 * k * a) + (2 * b), -3 * k, 2 }; var roots = CubicRootsTests.CubicRoots(poly[3], poly[2], poly[1], poly[0]) .OrderByDescending(c => c).ToArray(); if (roots.Length != 3) { return(null); } if (roots[0] >= 0d && roots[0] <= 1d && roots[2] >= 0d && roots[2] <= 1d) { return(InterpolateCubic2DTests.CubicInterpolate2D(roots[0], x0, y0, x1, y1, x2, y2, x3, y3)); } return(null); }
public static List <SpeedTester> TestHarness() { var trials = 10000; var tests = new Dictionary <object[], TestCaseResults> { { new object[] { 100, (Func <double, (double X, double Y)>)((i) => InterpolateCubic2DTests.CubicInterpolate2D(5d, i, 0d, 5d, 10d, 15d, 20d, 15d, 30d)) }, new TestCaseResults(description: "", trials: trials, expectedReturnValue: Tau, epsilon: double.Epsilon) },
public static Rectangle2D CubicBezierBounds1( double ax, double ay, double bx, double by, double cx, double cy, double dx, double dy) { var sortOfCloseLength = (int)CubicBezierSegmentLengthTests.CubicBezierArcLength(ax, ay, bx, by, cx, cy, dx, dy); var points = new List <(double X, double Y)>(FunctionalInterpolationTests.Interpolate0to1(sortOfCloseLength, (i) => InterpolateCubic2DTests.CubicInterpolate2D(i, ax, ay, bx, by, cx, cy, dx, dy))); var left = points[0].X; var top = points[0].Y; var right = points[0].X; var bottom = points[0].Y; foreach (var(X, Y) in points) { // ToDo: Measure performance impact of overwriting each time. left = X <= left ? X : left; top = Y <= top ? Y : top; right = X >= right ? X : right; bottom = Y >= bottom ? Y : bottom; } return(Rectangle2D.FromLTRB(left, top, right, bottom)); }