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);
        }
예제 #2
0
        /// <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);
        }
예제 #3
0
        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) },
예제 #5
0
        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));
        }