Beispiel #1
0
        public static Intersection QuadraticBezierLineSegmentIntersection0(
            double p1X, double p1Y,
            double p2X, double p2Y,
            double p3X, double p3Y,
            double a1X, double a1Y,
            double a2X, double a2Y,
            double epsilon = Epsilon)
        {
            var min    = MinPointTests.MinPoint(a1X, a1Y, a2X, a2Y);
            var max    = MaxPointTests.MaxPoint(a1X, a1Y, a2X, a2Y);
            var result = new Intersection(IntersectionStates.NoIntersection);
            var a      = new Vector2D(p2X, p2Y) * (-2);
            var c2     = new Vector2D(p1X, p1Y) + (a + new Vector2D(p3X, p3Y));

            a = new Vector2D(p1X, p1Y) * (-2);
            var b     = new Vector2D(p2X, p2Y) * 2;
            var c1    = a + b;
            var c0    = new Point2D(p1X, p1Y);
            var n     = new Point2D(a1Y - a2Y, a2X - a1X);
            var cl    = (a1X * a2Y) - (a2X * a1Y);
            var roots = QuadraticRootsTests.QuadraticRoots(
                DotProduct2Vector2DTests.DotProduct2D(n.X, n.Y, c2.I, c2.J),
                DotProduct2Vector2DTests.DotProduct2D(n.X, n.Y, c1.I, c1.J),
                DotProduct2Vector2DTests.DotProduct2D(n.X, n.Y, c0.X + cl, c0.Y + cl),
                epsilon);

            for (var i = 0; i < roots.Count; i++)
            {
                var t = roots[i];
                if (0 <= t && t <= 1)
                {
                    var p4 = InterpolateLinear2DTests.LinearInterpolate2D(t, p1X, p1Y, p2X, p2Y);
                    var p5 = InterpolateLinear2DTests.LinearInterpolate2D(t, p2X, p2Y, p3X, p3Y);
                    var p6 = InterpolateLinear2DTests.LinearInterpolate2D(t, p4.X, p4.Y, p5.X, p5.Y);
                    if (a1X == a2X)
                    {
                        if (min.Y <= p6.Y && p6.Y <= max.Y)
                        {
                            result.State = IntersectionStates.Intersection;
                            result.AppendPoint(p6);
                        }
                    }
                    else if (a1Y == a2Y)
                    {
                        if (min.X <= p6.X && p6.X <= max.X)
                        {
                            result.State = IntersectionStates.Intersection;
                            result.AppendPoint(p6);
                        }
                    }
                    else if (GreaterThanOrEqualTests.GreaterThanOrEqual(p6.X, p6.Y, min.X, min.Y) && LessThanOrEqualTests.LessThanOrEqual(p6.X, p6.Y, max.X, max.Y))
                    {
                        result.State = IntersectionStates.Intersection;
                        result.AppendPoint(p6);
                    }
                }
            }
            return(result);
        }
Beispiel #2
0
        public static Intersection LineLineSegmentIntersection0(
            double aX, double aY, // Line
            double bX, double bY,
            double cX, double cY, // Segment
            double dX, double dY,
            double epsilon = Epsilon)
        {
            //test for parallel case
            var denom = ((dY - cY) * (bX - aX)) - ((dX - cX) * (bY - aY));

            if (Abs(denom) < epsilon)
            {
                return(new Intersection(IntersectionStates.NoIntersection));
            }

            //calculate segment parameter and ensure its within bounds
            var t = (((bX - aX) * (aY - cY)) - ((bY - aY) * (aX - cX))) / denom;

            if (t < 0d || t > 1d)
            {
                return(new Intersection(IntersectionStates.NoIntersection));
            }

            //store actual intersection
            var result = new Intersection(IntersectionStates.Intersection);

            result.AppendPoint(new Point2D(cX + ((dX - cX) * t), cY + ((dY - cY) * t)));
            return(result);
        }
Beispiel #3
0
        public static Intersection CubicBezierLineSegmentIntersection1(
            double p0x, double p0y,
            double p1x, double p1y,
            double p2x, double p2y,
            double p3x, double p3y,
            double l0x, double l0y,
            double l1x, double l1y,
            double epsilon = Epsilon)
        {
            _ = epsilon;
            // ToDo: Figure out why this can't handle intersection with horizontal lines.
            var I = new Intersection(IntersectionStates.NoIntersection);

            var A = l1y - l0y;                                 //A=y2-y1
            var B = l0x - l1x;                                 //B=x1-x2
            var C = (l0x * (l0y - l1y)) + (l0y * (l1x - l0x)); //C=x1*(y1-y2)+y1*(x2-x1)

            var xCoeff = CubicBezierBernsteinBasisTests.CubicBezierBernsteinBasis(p0x, p1x, p2x, p3x);
            var yCoeff = CubicBezierBernsteinBasisTests.CubicBezierBernsteinBasis(p0y, p1y, p2y, p3y);

            var r = CubicRootsTests.CubicRoots(
                /* t^3 */ (A * xCoeff.D) + (B * yCoeff.D),
                /* t^2 */ (A * xCoeff.C) + (B * yCoeff.C),
                /* t^1 */ (A * xCoeff.B) + (B * yCoeff.B),
                /* 1 */ (A * xCoeff.A) + (B * yCoeff.A) + C
                );

            /*verify the roots are in bounds of the linear segment*/
            for (var i = 0; i < 3; i++)
            {
                var t = r[i];

                var x = (xCoeff.D * t * t * t) + (xCoeff.C * t * t) + (xCoeff.B * t) + xCoeff.A;
                var y = (yCoeff.D * t * t * t) + (yCoeff.C * t * t) + (yCoeff.B * t) + yCoeff.A;

                /*above is intersection point assuming infinitely long line segment,
                 * make sure we are also in bounds of the line*/
                double m;
                m = (l1x - l0x) != 0 ? (x - l0x) / (l1x - l0x) : (y - l0y) / (l1y - l0y);

                /*in bounds?*/
                if (t < 0 || t > 1d || m < 0 || m > 1d)
                {
                    x = 0; // -100;  /*move off screen*/
                    y = 0; // -100;
                }
                else
                {
                    /*intersection point*/
                    I.AppendPoint(new Point2D(x, y));
                    I.State = IntersectionStates.Intersection;
                }
            }
            return(I);
        }
        public static Intersection EllipseEllipseIntersection(
            double h1, double k1, double a1, double b1, double cos1, double sin1,
            double h2, double k2, double a2, double b2, double cos2, double sin2,
            double epsilon = double.Epsilon)
        {
            if (sin2 == 1d || sin2 == -1d)
            {
                cos2 = 0d;
            }

            // Polynomials representing the Ellipses.
            var a = RotatedEllipseConicSectionPolynomialTests.EllipseConicPolynomial(h1, k1, a1, b1, cos1, sin1);
            var b = RotatedEllipseConicSectionPolynomialTests.EllipseConicPolynomial(h2, k2, a2, b2, cos2, sin2);

            var yRoots = new Polynomial(ConicSectionBezoutTests.ConicSectionBezout(a, b)).Trim().Roots();

            var norm0 = ((a.a * a.a) + (2d * a.b * a.b) + (a.c * a.c)) * epsilon;
            //var norm1 = ((b.a * b.a) + (2d * b.b * b.b) + (b.c * b.c)) * epsilon;

            var result = new Intersection(IntersectionStates.NoIntersection);

            for (var y = 0; y < yRoots.Length; y++)
            {
                var xRoots = new Polynomial(
                    a.a,
                    a.d + (yRoots[y] * a.b),
                    a.f + (yRoots[y] * (a.e + (yRoots[y] * a.c))),
                    epsilon).Trim().Roots();
                for (var x = 0; x < xRoots.Length; x++)
                {
                    var test = (((a.a * xRoots[x]) + (a.b * yRoots[y]) + a.d) * xRoots[x]) + (((a.c * yRoots[y]) + a.e) * yRoots[y]) + a.f;
                    if (Abs(test) < norm0)
                    {
                        test = (((b.a * xRoots[x]) + (b.b * yRoots[y]) + b.d) * xRoots[x]) + (((b.c * yRoots[y]) + b.e) * yRoots[y]) + b.f;
                        if (Abs(test) < 1d)//norm1) // Using norm1 breaks when an ellipse intersects certain other ellipses.
                        {
                            result.AppendPoint(new Point2D(xRoots[x], yRoots[y]));
                        }
                    }
                }
            }

            if (result.Items.Count > 0)
            {
                result.State = IntersectionStates.Intersection;
            }

            return(result);
        }
Beispiel #5
0
        public static Intersection LineLineSegmentIntersection1(
            double a1X, double a1Y,
            double a2X, double a2Y,
            double b1X, double b1Y,
            double b2X, double b2Y,
            double epsilon = Epsilon)
        {
            _ = epsilon;
            Intersection result;
            var          ua_t = ((b2X - b1X) * (a1Y - b1Y)) - ((b2Y - b1Y) * (a1X - b1X));
            var          ub_t = ((a2X - a1X) * (a1Y - b1Y)) - ((a2Y - a1Y) * (a1X - b1X));
            var          u_b  = ((b2Y - b1Y) * (a2X - a1X)) - ((b2X - b1X) * (a2Y - a1Y));

            if (u_b != 0)
            {
                var ua = ua_t / u_b;
                var ub = ub_t / u_b;
                if (//true
                    //0 <= ua && ua <= 1
                    //&&
                    0 <= ub && ub <= 1
                    )
                {
                    result = new Intersection(IntersectionStates.Intersection);
                    result.AppendPoint(new Point2D(a1X + (ua * (a2X - a1X)), a1Y + (ua * (a2Y - a1Y))));
                    //result.AppendPoint(new Point2D(b1X + ub * (b2X - b1X), b1Y + ub * (b2Y - b1Y)));
                }
                else
                {
                    result = new Intersection(IntersectionStates.NoIntersection);
                }
            }
            else
            {
                if (ua_t == 0 || ub_t == 0)
                {
                    result = new Intersection(IntersectionStates.Coincident | IntersectionStates.Parallel | IntersectionStates.Intersection);
                    result.AppendPoints(new List <(double X, double Y)> {
                        (b1X, b1Y), (b2X, b2Y)
                    });
                }
                else
                {
                    result = new Intersection(IntersectionStates.Parallel | IntersectionStates.NoIntersection);
                }
            }
            return(result);
        }
Beispiel #6
0
        public static Intersection LineLineSegmentIntersection2(
            double x0, double y0,
            double x1, double y1,
            double x2, double y2,
            double x3, double y3,
            double epsilon = Epsilon)
        {
            _ = epsilon;
            var result = new Intersection(IntersectionStates.NoIntersection);

            // Translate lines to origin.
            var u1 = x1 - x0;
            var v1 = y1 - y0;
            var u2 = x3 - x2;
            var v2 = y3 - y2;

            // Calculate the determinant of the coefficient matrix.
            var determinant = (v2 * u1) - (u2 * v1);

            // Check if the lines are parallel or coincident.
            if (Abs(determinant) < Epsilon)
            {
                return(result);
            }

            // Find the index where the intersection point lies on the line.
            //var s = ((x0 - x2) * v1 + (y2 - y0) * u1) / -determinant;
            var t = (((x2 - x0) * v2) + ((y0 - y2) * u2)) / determinant;

            // Check whether the point is on the segment.
            if (t >= 0d && t <= 1d)
            {
                result = new Intersection(IntersectionStates.Intersection);
                result.AppendPoint(new Point2D(x0 + (t * u1), y0 + (t * v1)));
            }

            return(result);
        }
Beispiel #7
0
        public static Intersection QuadraticBezierLineSegmentIntersection1(
            double p1X, double p1Y,
            double p2X, double p2Y,
            double p3X, double p3Y,
            double a1X, double a1Y,
            double a2X, double a2Y,
            double epsilon = Epsilon)
        {
            _ = epsilon;
            var intersections = new Intersection(IntersectionStates.NoIntersection);

            // inverse line normal
            var normal = new Point2D(a1Y - a2Y, a2X - a1X);

            // Q-coefficients
            var c2 = new Point2D(p1X + (p2X * -2) + p3X, p1Y + (p2Y * -2) + p3Y);
            var c1 = new Point2D((p1X * -2) + (p2X * 2), (p1Y * -2) + (p2Y * 2));
            var c0 = new Point2D(p1X, p1Y);

            // Transform to line
            var coefficient = (a1X * a2Y) - (a2X * a1Y);
            var a           = (normal.X * c2.X) + (normal.Y * c2.Y);
            var b           = ((normal.X * c1.X) + (normal.Y * c1.Y)) / a;
            var c           = ((normal.X * c0.X) + (normal.Y * c0.Y) + coefficient) / a;

            // solve the roots
            var roots = new List <double>();
            var d     = (b * b) - (4 * c);

            if (d > 0)
            {
                var e = Sqrt(d);
                roots.Add((-b + Sqrt(d)) / 2d);
                roots.Add((-b - Sqrt(d)) / 2d);
            }
            else if (d == 0)
            {
                roots.Add(-b / 2d);
            }

            // Calculate the solution points
            for (var i = 0; i < roots.Count; i++)
            {
                var minX = Min(a1X, a2X);
                var minY = Min(a1Y, a2Y);
                var maxX = Max(a1X, a2X);
                var maxY = Max(a1Y, a2Y);
                var t    = roots[i];
                if (t >= 0 && t <= 1)
                {
                    // Possible point -- pending bounds check
                    var point = new Point2D(
                        InterpolateLinear1DTests.LinearInterpolate1D(t, InterpolateLinear1DTests.LinearInterpolate1D(t, p1X, p2X), InterpolateLinear1DTests.LinearInterpolate1D((double)t, (double)p2X, (double)p3X)),
                        InterpolateLinear1DTests.LinearInterpolate1D(t, InterpolateLinear1DTests.LinearInterpolate1D(t, p1Y, p2Y), InterpolateLinear1DTests.LinearInterpolate1D(t, p2Y, p3Y)));
                    var x      = point.X;
                    var y      = point.Y;
                    var result = new Intersection(IntersectionStates.Intersection);
                    // bounds checks
                    if (a1X == a2X && y >= minY && y <= maxY)
                    {
                        // vertical line
                        intersections.AppendPoint(point);
                    }
                    else if (a1Y == a2Y && x >= minX && x <= maxX)
                    {
                        // horizontal line
                        intersections.AppendPoint(point);
                    }
                    else if (x >= minX && y >= minY && x <= maxX && y <= maxY)
                    {
                        // line passed bounds check
                        intersections.AppendPoint(point);
                    }
                }
            }
            return(intersections);
        }
Beispiel #8
0
        public static Intersection UnrotatedEllipseLineSegmentIntersection0(
            double centerX, double centerY,
            double rx, double ry,
            double a1X, double a1Y,
            double a2X, double a2Y,
            double epsilon = Epsilon)
        {
            _ = epsilon;
            var          origin = new Vector2D(a1X, a1Y);
            var          dir    = new Vector2D(a1X, a1Y, a2X, a2Y);
            var          diff   = origin - new Vector2D(centerX, centerY);
            var          mDir   = new Vector2D(dir.I / (rx * rx), dir.J / (ry * ry));
            var          mDiff  = new Vector2D(diff.I / (rx * rx), diff.J / (ry * ry));
            var          a      = DotProduct2Vector2DTests.DotProduct2D(dir.I, dir.J, mDir.I, mDir.J);
            var          b      = DotProduct2Vector2DTests.DotProduct2D(dir.I, dir.J, mDiff.I, mDiff.J);
            var          c      = DotProduct2Vector2DTests.DotProduct2D(diff.I, diff.J, mDiff.I, mDiff.J) - 1d;
            var          d      = (b * b) - (a * c);
            Intersection result;

            if (d < 0)
            {
                result = new Intersection(IntersectionStates.Outside);
            }
            else if (d > 0)
            {
                var root = Sqrt(d);
                var t_a  = (-b - root) / a;
                var t_b  = (-b + root) / a;
                if ((t_a < 0 || 1 < t_a) && (t_b < 0 || 1 < t_b))
                {
                    result = (t_a < 0 && t_b < 0) || (t_a > 1 && t_b > 1) ? new Intersection(IntersectionStates.Outside) : new Intersection(IntersectionStates.Inside);
                }
                else
                {
                    result = new Intersection(IntersectionStates.Intersection);
                    if (0 <= t_a && t_a <= 1)
                    {
                        result.AppendPoint(InterpolateLinear2DTests.LinearInterpolate2D(t_a, a1X, a1Y, a2X, a2Y));
                    }

                    if (0 <= t_b && t_b <= 1)
                    {
                        result.AppendPoint(InterpolateLinear2DTests.LinearInterpolate2D(t_b, a1X, a1Y, a2X, a2Y));
                    }
                }
            }
            else
            {
                var t = -b / a; if (0 <= t && t <= 1)
                {
                    result = new Intersection(IntersectionStates.Intersection);
                    result.AppendPoint(InterpolateLinear2DTests.LinearInterpolate2D(t, a1X, a1Y, a2X, a2Y));
                }
                else
                {
                    result = new Intersection(IntersectionStates.Outside);
                }
            }

            return(result);
        }
Beispiel #9
0
        public static Intersection UnrotatedEllipseLineSegmentIntersection2(
            double cx, double cy,
            double rx, double ry,
            double x0, double y0,
            double x1, double y1,
            double epsilon = Epsilon)
        {
            var result = new Intersection(IntersectionStates.NoIntersection);

            // If the ellipse or line segment are empty, return no intersections.
            if ((rx == 0d) || (ry == 0d) ||
                ((x0 == x1) && (y0 == y1)))
            {
                return(result);
            }

            // Translate the line to put the ellipse centered at the origin.
            var u1 = x0 - cx;
            var v1 = y0 - cy;
            var u2 = x1 - cx;
            var v2 = y1 - cy;

            // Calculate the quadratic parameters.
            var a = ((u2 - u1) * (u2 - u1) / (rx * rx)) + ((v2 - v1) * (v2 - v1) / (ry * ry));
            var b = (2d * u1 * (u2 - u1) / (rx * rx)) + (2d * v1 * (v2 - v1) / (ry * ry));
            var c = (u1 * u1 / (rx * rx)) + (v1 * v1 / (ry * ry)) - 1d;

            // Calculate the discriminant.
            var discriminant = (b * b) - (4d * a * c);

            if ((a <= epsilon) || (discriminant < 0))
            {
                // No real solutions.
            }
            else if (discriminant == 0)
            {
                // One real possible solution.
                var t = 0.5d * -b / a;

                // Add the points if it is between the end points of the line segment.
                if ((t >= 0d) && (t <= 1d))
                {
                    result.AppendPoint(new Point2D(u1 + ((u2 - u1) * t) + cx, v1 + ((v2 - v1) * t) + cy));
                    result.State = IntersectionStates.Intersection;
                }
            }
            else if (discriminant > 0)
            {
                // Two real possible solutions.
                var t1 = 0.5d * (-b + Sqrt(discriminant)) / a;
                var t2 = 0.5d * (-b - Sqrt(discriminant)) / a;

                // Add the points if they are between the end points of the line segment.
                if ((t1 >= 0d) && (t1 <= 1d))
                {
                    result.AppendPoint(new Point2D(u1 + ((u2 - u1) * t1) + cx, v1 + ((v2 - v1) * t1) + cy));
                    result.State = IntersectionStates.Intersection;
                }

                if ((t2 >= 0d) && (t2 <= 1d))
                {
                    result.AppendPoint(new Point2D(u1 + ((u2 - u1) * t2) + cx, v1 + ((v2 - v1) * t2) + cy));
                    result.State = IntersectionStates.Intersection;
                }
            }

            return(result);
        }
Beispiel #10
0
        public static Intersection UnrotatedEllipticalArcLineSegmentIntersection0(
            double cx, double cy,
            double rx, double ry,
            double startAngle, double sweepAngle,
            double x0, double y0,
            double x1, double y1, double epsilon = Epsilon)
        {
            _ = epsilon;
            // Initialize the resulting intersection structure.
            var result = new Intersection(IntersectionStates.NoIntersection);

            // Translate the line to put the ellipse centered at the origin.
            var origin = new Vector2D(x0, y0);
            var dir    = new Vector2D(x0, y0, x1, y1);
            var diff   = origin - new Vector2D(cx, cy);
            var mDir   = new Vector2D(dir.I / (rx * rx), dir.J / (ry * ry));
            var mDiff  = new Vector2D(diff.I / (rx * rx), diff.J / (ry * ry));

            // Calculate the quadratic parameters.
            var a = DotProduct2Vector2DTests.DotProduct2D(dir.I, dir.J, mDir.I, mDir.J);
            var b = DotProduct2Vector2DTests.DotProduct2D(dir.I, dir.J, mDiff.I, mDiff.J);
            var c = DotProduct2Vector2DTests.DotProduct2D(diff.I, diff.J, mDiff.I, mDiff.J) - 1d;

            // Calculate the discriminant of the quadratic. The 4 is omitted.
            var discriminant = (b * b) - (a * c);

            // Check whether line segment is outside of the ellipse.
            if (discriminant < 0d)
            {
                return(new Intersection(IntersectionStates.Outside));
            }

            // Find the start and end angles.
            var sa = EllipticalPolarAngleTests.EllipticalPolarAngle(startAngle, rx, ry);
            var ea = EllipticalPolarAngleTests.EllipticalPolarAngle(startAngle + sweepAngle, rx, ry);

            // Get the ellipse rotation transform.
            var cosT = Cos(0d);
            var sinT = Sin(0d);

            // Ellipse equation for an ellipse at origin for the chord end points.
            var u1 = rx * Cos(sa);
            var v1 = -(ry * Sin(sa));
            var u2 = rx * Cos(ea);
            var v2 = -(ry * Sin(ea));

            // Find the points of the chord.
            var sX = cx + ((u1 * cosT) + (v1 * sinT));
            var sY = cy + ((u1 * sinT) - (v1 * cosT));
            var eX = cx + ((u2 * cosT) + (v2 * sinT));
            var eY = cy + ((u2 * sinT) - (v2 * cosT));

            if (discriminant > 0d)
            {
                // Two real possible solutions.
                var root = Sqrt(discriminant);
                var t1   = (-b - root) / a;
                var t2   = (-b + root) / a;
                if ((t1 < 0d || 1d < t1) && (t2 < 0d || 1d < t2))
                {
                    result = (t1 < 0d && t2 < 0d) || (t1 > 1d && t2 > 1d) ? new Intersection(IntersectionStates.Outside) : new Intersection(IntersectionStates.Inside);
                }
                else
                {
                    var p = InterpolateLinear2DTests.LinearInterpolate2D(t1, x0, y0, x1, y1);
                    // Find the determinant of the chord.
                    var determinant = ((sX - p.X) * (eY - p.Y)) - ((eX - p.X) * (sY - p.Y));

                    // Check whether the point is on the side of the chord as the center.
                    if (0d <= t1 && t1 <= 1d && (Sign(determinant) != Sign(sweepAngle)))
                    {
                        result.AppendPoint(p);
                    }

                    p = InterpolateLinear2DTests.LinearInterpolate2D(t2, x0, y0, x1, y1);
                    // Find the determinant of the chord.
                    determinant = ((sX - p.X) * (eY - p.Y)) - ((eX - p.X) * (sY - p.Y));
                    if (0d <= t2 && t2 <= 1 && (Sign(determinant) != Sign(sweepAngle)))
                    {
                        result.AppendPoint(p);
                    }
                }
            }
            else // discriminant == 0.
            {
                // One real possible solution.
                var t = -b / a;
                if (t >= 0d && t <= 1d)
                {
                    var p = InterpolateLinear2DTests.LinearInterpolate2D(t, x0, y0, x1, y1);

                    // Find the determinant of the matrix representing the chord.
                    var determinant = ((sX - p.X) * (eY - p.Y)) - ((eX - p.X) * (sY - p.Y));

                    // Add the point if it is on the sweep side of the chord.
                    if (Sign(determinant) != Sign(sweepAngle))
                    {
                        result.AppendPoint(InterpolateLinear2DTests.LinearInterpolate2D(t, x0, y0, x1, y1));
                    }
                }
                else
                {
                    result = new Intersection(IntersectionStates.Outside);
                }
            }

            if (result.Count > 0)
            {
                result.State |= IntersectionStates.Intersection;
            }

            return(result);
        }
        public static Intersection CircleLineSegmentIntersection1(
            double cX, double cY,
            double r,
            double lAX, double lAY,
            double lBX, double lBY,
            double epsilon = Epsilon)
        {
            _ = epsilon;
            var result = new Intersection(IntersectionStates.NoIntersection);

            // If the circle or line segment are empty, return no intersections.
            if ((r == 0d) || ((lAX == lBX) && (lAY == lBY)))
            {
                return(result);
            }

            var dx = lBX - lAX;
            var dy = lBY - lAY;

            // Calculate the quadratic parameters.
            var a = (dx * dx) + (dy * dy);
            var b = 2 * ((dx * (lAX - cX)) + (dy * (lAY - cY)));
            var c = ((lAX - cX) * (lAX - cX)) + ((lAY - cY) * (lAY - cY)) - (r * r);

            // Calculate the discriminant.
            var discriminant = (b * b) - (4d * a * c);

            if ((a <= Epsilon) || (discriminant < 0))
            {
                // No real solutions.
            }
            else if (discriminant == 0)
            {
                // One possible solution.
                var t = -b / (2 * a);

                // Add the points if they are between the end points of the line segment.
                if ((t >= 0d) && (t <= 1d))
                {
                    result = new Intersection(IntersectionStates.Intersection);
                    result.AppendPoint(new Point2D(lAX + (t * dx), lAY + (t * dy)));
                }
            }
            else if (discriminant > 0)
            {
                // Two possible solutions.
                var t1 = (-b + Sqrt(discriminant)) / (2 * a);
                var t2 = (-b - Sqrt(discriminant)) / (2 * a);

                // Add the points if they are between the end points of the line segment.
                result = new Intersection(IntersectionStates.Intersection);
                if ((t1 >= 0d) && (t1 <= 1d))
                {
                    result.AppendPoint(new Point2D(lAX + (t1 * dx), lAY + (t1 * dy)));
                }

                if ((t2 >= 0d) && (t2 <= 1d))
                {
                    result.AppendPoint(new Point2D(lAX + (t2 * dx), lAY + (t2 * dy)));
                }
            }

            return(result);
        }
Beispiel #12
0
        public static Intersection QuadraticBezierSegmentQuadraticBezierSegmentIntersection1(
            double a1X, double a1Y, double a2X, double a2Y, double a3X, double a3Y,
            double b1X, double b1Y, double b2X, double b2Y, double b3X, double b3Y,
            double epsilon = Epsilon)
        {
            var result = new Intersection(IntersectionStates.NoIntersection);

            // ToDo: Break early if the AABB bounding box of the curve does not intersect.
            // ToDo: Figure out if the following can be broken out of the vector structs.

            var c12 = new Vector2D(a1X - (a2X * 2) + a3X, a1Y - (a2Y * 2) + a3Y);
            var c11 = new Vector2D(2 * (a2X - a1X), 2 * (a2Y - a1Y));
            // c10 is a1X and a1Y

            var c22 = new Vector2D(b1X - (b2X * 2) + b3X, b1Y - (b2Y * 2) + b3Y);
            var c21 = new Vector2D(2 * (b2X - b1X), 2 * (b2Y - b1Y));
            // c20 is b1X and b1Y

            var a = (c12.I * c11.J) - (c11.I * c12.J);

            var b = (c22.I * c11.J) - (c11.I * c22.J);
            var c = (c21.I * c11.J) - (c11.I * c21.J);
            var d = (c11.I * (a1Y - b1Y)) - (c11.J * (b1X - a1X));

            var e = (-c22.I * c12.J) - (c12.I * c22.J);
            var f = (c21.I * c12.J) - (c12.I * c21.J);
            var g = (c12.I * (a1Y - b1Y)) - (c12.J * (b1X - a1X));

            IList <double> roots;

            if ((a * d) - (g * g) == 0)
            {
                var v0 = (a * c) - (2 * f * g);
                var v1 = (a * b) - (f * f) - (2 * e * g);
                var v2 = -2 * e * f;
                var v3 = -e * e;
                roots = CubicRootsTests.CubicRoots(
                    /* t^3 */ -v3,
                    /* t^2 */ -v2,
                    /* t^1 */ -v1,
                    /* C */ -v0,
                    epsilon);
            }
            else
            {
                var v0 = (a * d) - (g * g);
                var v1 = (a * c) - (2 * f * g);
                var v2 = (a * b) - (f * f) - (2 * e * g);
                var v3 = -2 * e * f;
                var v4 = -e * e;
                roots = QuarticRootsTests.QuarticRoots(
                    /* t^4 */ -v4,
                    /* t^3 */ -v3,
                    /* t^2 */ -v2,
                    /* t^1 */ -v1,
                    /* C */ -v0,
                    epsilon);
            }

            //roots.Reverse();
            foreach (var s in roots)
            {
                var point = new Point2D(
                    (c22.I * s * s) + (c21.I * s) + b1X,
                    (c22.J * s * s) + (c21.J * s) + b1Y);
                if (s >= 0 && s <= 1)
                {
                    var v0     = a1X - point.X;
                    var v1     = c11.I;
                    var v2     = c12.I;
                    var xRoots = QuadraticRootsTests.QuadraticRoots(
                        /* t^2 */ -v2,
                        /* t^1 */ -v1,
                        /* C */ -v0,
                        epsilon);
                    v0 = a1Y - point.Y;
                    v1 = c11.J;
                    v2 = c12.J;
                    var yRoots = QuadraticRootsTests.QuadraticRoots(
                        /* t^2 */ -v2,
                        /* t^1 */ -v1,
                        /* C */ -v0,
                        epsilon);

                    if (xRoots.Count > 0 && yRoots.Count > 0)
                    {
                        // Find the nearest matching x and y roots in the ranges 0 < x < 1; 0 < y < 1.
                        foreach (var xRoot in xRoots)
                        {
                            if (xRoot >= 0 && xRoot <= 1)
                            {
                                foreach (var yRoot in yRoots)
                                {
                                    var t = xRoot - yRoot;
                                    if ((t >= 0 ? t : -t) < 0.1)
                                    {
                                        result.AppendPoint(point);
                                        goto checkRoots; // Break through two levels of foreach loops. Using goto for performance.
                                    }
                                }
                            }
                        }
                        checkRoots :;
                    }
                }
            }

            if (result.Items.Count > 0)
            {
                result.State = IntersectionStates.Intersection;
            }

            return(result);
        }
Beispiel #13
0
        public static Intersection CubicBezierLineIntersection0(
            double p1X, double p1Y,
            double p2X, double p2Y,
            double p3X, double p3Y,
            double p4X, double p4Y,
            double a1X, double a1Y,
            double a2X, double a2Y,
            double epsilon = Epsilon)
        {
            Vector2D a, b, c, d;
            Vector2D c3, c2, c1, c0;
            double   cl;
            Vector2D n;
            var      min    = MinPointTests.MinPoint(a1X, a1Y, a2X, a2Y);
            var      max    = MaxPointTests.MaxPoint(a1X, a1Y, a2X, a2Y);
            var      result = new Intersection(IntersectionStates.NoIntersection);

            a  = new Vector2D(p1X, p1Y) * (-1);
            b  = new Vector2D(p2X, p2Y) * 3;
            c  = new Vector2D(p3X, p3Y) * (-3);
            d  = a + (b + (c + new Vector2D(p4X, p4Y)));
            c3 = new Vector2D(d.I, d.J);
            a  = new Vector2D(p1X, p1Y) * 3;
            b  = new Vector2D(p2X, p2Y) * (-6);
            c  = new Vector2D(p3X, p3Y) * 3;
            d  = a + (b + c);
            c2 = new Vector2D(d.I, d.J);
            a  = new Vector2D(p1X, p1Y) * (-3);
            b  = new Vector2D(p2X, p2Y) * 3;
            c  = a + b;
            c1 = new Vector2D(c.I, c.J);
            c0 = new Vector2D(p1X, p1Y);
            n  = new Vector2D(a1Y - a2Y, a2X - a1X);
            cl = (a1X * a2Y) - (a2X * a1Y);
            var roots = CubicRootsTests.CubicRoots(
                DotProduct2Vector2DTests.DotProduct2D(n.I, n.J, c3.I, c3.J),
                DotProduct2Vector2DTests.DotProduct2D(n.I, n.J, c2.I, c2.J),
                DotProduct2Vector2DTests.DotProduct2D(n.I, n.J, c1.I, c1.J),
                DotProduct2Vector2DTests.DotProduct2D(n.I, n.J, c0.I + cl, c0.J + cl),
                epsilon);

            for (var i = 0; i < roots.Count; i++)
            {
                var t = roots[i];
                if (0 <= t && t <= 1)
                {
                    var p5  = InterpolateLinear2DTests.LinearInterpolate2D(t, p1X, p1Y, p2X, p2Y);
                    var p6  = InterpolateLinear2DTests.LinearInterpolate2D(t, p2X, p2Y, p3X, p3Y);
                    var p7  = InterpolateLinear2DTests.LinearInterpolate2D(t, p3X, p3Y, p4X, p4Y);
                    var p8  = InterpolateLinear2DTests.LinearInterpolate2D(t, p5.X, p5.Y, p6.X, p6.Y);
                    var p9  = InterpolateLinear2DTests.LinearInterpolate2D(t, p6.X, p6.Y, p7.X, p7.Y);
                    var p10 = InterpolateLinear2DTests.LinearInterpolate2D(t, p8.X, p8.Y, p9.X, p9.Y);
                    if (a1X == a2X)
                    {
                        result.State = IntersectionStates.Intersection;
                        result.AppendPoint(p10);
                    }
                    else if (a1Y == a2Y)
                    {
                        result.State = IntersectionStates.Intersection;
                        result.AppendPoint(p10);
                    }
                    else if (GreaterThanOrEqualTests.GreaterThanOrEqual(p10.X, p10.Y, min.X, min.Y) && LessThanOrEqualTests.LessThanOrEqual(p10.X, p10.Y, max.X, max.Y))
                    {
                        result.State = IntersectionStates.Intersection;
                        result.AppendPoint(p10);
                    }
                }
            }

            return(result);
        }
Beispiel #14
0
        public static Intersection QuadraticBezierSegmentQuadraticBezierSegmentIntersection00(
            double a1X, double a1Y, double a2X, double a2Y, double a3X, double a3Y,
            double b1X, double b1Y, double b2X, double b2Y, double b3X, double b3Y,
            double epsilon = Epsilon)
        {
            // Initialize the intersection.
            var result = new Intersection(IntersectionStates.NoIntersection);

            // ToDo: Break early if the AABB of the ends and handles do not intersect.
            // ToDo: Break early if the AABB of the curve does not intersect.

            // Parametric matrix form of the Bézier curve
            var xCoeffA = QuadraticBezierBernsteinBasisTests.QuadraticBezierBernsteinBasis(a1X, a2X, a3X);
            var yCoeffA = QuadraticBezierBernsteinBasisTests.QuadraticBezierBernsteinBasis(a1Y, a2Y, a3Y);
            var xCoeffB = QuadraticBezierBernsteinBasisTests.QuadraticBezierBernsteinBasis(b1X, b2X, b3X);
            var yCoeffB = QuadraticBezierBernsteinBasisTests.QuadraticBezierBernsteinBasis(b1Y, b2Y, b3Y);

            IList <double> roots = new List <double>();

            if (yCoeffA.C == 0)
            {
                var v0 = xCoeffA.C * (yCoeffA.A - yCoeffB.A);
                var v1 = v0 - (xCoeffA.B * yCoeffA.B);
                var v2 = v0 + v1;
                var v3 = yCoeffA.B * yCoeffA.B;

                roots = QuarticRootsTests.QuarticRoots(
                    /* t^4 */ xCoeffA.C * yCoeffB.C * yCoeffB.C,
                    /* t^3 */ 2 * xCoeffA.C * yCoeffB.B * yCoeffB.C,
                    /* t^2 */ (xCoeffA.C * yCoeffB.B * yCoeffB.B) - (xCoeffB.C * v3) - (yCoeffB.C * v0) - (yCoeffB.C * v1),
                    /* t^1 */ (-xCoeffB.B * v3) - (yCoeffB.B * v0) - (yCoeffB.B * v1),
                    /* C^0 */ ((xCoeffA.A - xCoeffB.A) * v3) + ((yCoeffA.A - yCoeffB.A) * v1),
                    epsilon);
            }
            else
            {
                var v0 = (xCoeffA.C * yCoeffB.C) - (yCoeffA.C * xCoeffB.C);
                var v1 = (xCoeffA.C * yCoeffB.B) - (xCoeffB.B * yCoeffA.C);
                var v2 = (xCoeffA.B * yCoeffA.C) - (yCoeffA.B * xCoeffA.C);
                var v3 = yCoeffA.A - yCoeffB.A;
                var v4 = (yCoeffA.C * (xCoeffA.A - xCoeffB.A)) - (xCoeffA.C * v3);
                var v5 = (-yCoeffA.B * v2) + (yCoeffA.C * v4);
                var v6 = v2 * v2;
                roots = QuarticRootsTests.QuarticRoots(
                    /* t^4 */ v0 * v0,
                    /* t^3 */ 2 * v0 * v1,
                    /* t^2 */ ((-yCoeffB.C * v6) + (yCoeffA.C * v1 * v1) + (yCoeffA.C * v0 * v4) + (v0 * v5)) / yCoeffA.C,
                    /* t^1 */ ((-yCoeffB.B * v6) + (yCoeffA.C * v1 * v4) + (v1 * v5)) / yCoeffA.C,
                    /* C^0 */ ((v3 * v6) + (v4 * v5)) / yCoeffA.C,
                    epsilon);
            }

            foreach (var s in roots)
            {
                var point = new Point2D(
                    (xCoeffB.C * s * s) + (xCoeffB.B * s) + xCoeffB.A,
                    (yCoeffB.C * s * s) + (yCoeffB.B * s) + yCoeffB.A);
                if (s >= 0 && s <= 1)
                {
                    var xRoots = QuadraticRootsTests.QuadraticRoots(
                        /* t^2 */ -xCoeffA.C,
                        /* t^1 */ -xCoeffA.B,
                        /* C^0 */ -xCoeffA.A + point.X,
                        epsilon);
                    var yRoots = QuadraticRootsTests.QuadraticRoots(
                        /* t^2 */ -yCoeffA.C,
                        /* t^1 */ -yCoeffA.B,
                        /* C^0 */ -yCoeffA.A + point.Y,
                        epsilon);

                    if (xRoots.Count > 0 && yRoots.Count > 0)
                    {
                        // Find the nearest matching x and y roots in the ranges 0 < x < 1; 0 < y < 1.
                        foreach (var xRoot in xRoots)
                        {
                            if (xRoot >= 0 && xRoot <= 1)
                            {
                                foreach (var yRoot in yRoots)
                                {
                                    var t = xRoot - yRoot;
                                    if ((t >= 0 ? t : -t) < epsilon)
                                    {
                                        result.AppendPoint(point);
                                        goto checkRoots; // Break through two levels of foreach loops to exit early. Using goto for performance.
                                    }
                                }
                            }
                        }
                        checkRoots :;
                    }
                }
            }

            if (result.Items.Count > 0)
            {
                result.State = IntersectionStates.Intersection;
            }

            return(result);
        }
        public static Intersection EllipseLineSegmentIntersection1(
            double cx, double cy,
            double rx, double ry,
            double angle,
            double x0, double y0,
            double x1, double y1,
            double epsilon = Epsilon)
        {
            var result = new Intersection(IntersectionStates.NoIntersection);

            // If the ellipse or line segment are empty, return no intersections.
            if ((rx == 0d) || (ry == 0d) ||
                ((x0 == x1) && (y0 == y1)))
            {
                return(result);
            }

            // Get the Sine and Cosine of the angle.
            var sinA = Sin(angle);
            var cosA = Cos(angle);

            // Translate the line to put the ellipse centered at the origin.
            var u1 = x0 - cx;
            var v1 = y0 - cy;
            var u2 = x1 - cx;
            var v2 = y1 - cy;

            // Apply Rotation Transform to line at the origin.
            var u1A = 0 + ((u1 * cosA) - (v1 * sinA));
            var v1A = 0 + ((u1 * sinA) + (v1 * cosA));
            var u2A = 0 + ((u2 * cosA) - (v2 * sinA));
            var v2A = 0 + ((u2 * sinA) + (v2 * cosA));

            // Calculate the quadratic parameters.
            var a = ((u2A - u1A) * (u2A - u1A) / (rx * rx)) + ((v2A - v1A) * (v2A - v1A) / (ry * ry));
            var b = (2d * u1A * (u2A - u1A) / (rx * rx)) + (2d * v1A * (v2A - v1A) / (ry * ry));
            var c = (u1A * u1A / (rx * rx)) + (v1A * v1A / (ry * ry)) - 1d;

            // Calculate the discriminant.
            var discriminant = (b * b) - (4d * a * c);

            if ((a <= epsilon) || (discriminant < 0))
            {
                // No real solutions.
            }
            else if (discriminant == 0)
            {
                // One real possible solution.
                var t = 0.5d * -b / a;

                // Add the point if it is between the end points of the line segment.
                if ((t >= 0d) && (t <= 1d))
                {
                    result.AppendPoint(new Point2D(u1 + ((u2 - u1) * t) + cx, v1 + ((v2 - v1) * t) + cy));
                    result.State = IntersectionStates.Intersection;
                }
            }
            else if (discriminant > 0)
            {
                // Two real possible solutions.
                var t1 = 0.5d * (-b + Sqrt(discriminant)) / a;
                var t2 = 0.5d * (-b - Sqrt(discriminant)) / a;

                // Add the points if they are between the end points of the line segment.
                if ((t1 >= 0d) && (t1 <= 1d))
                {
                    result.AppendPoint(new Point2D(u1 + ((u2 - u1) * t1) + cx, v1 + ((v2 - v1) * t1) + cy));
                    result.State = IntersectionStates.Intersection;
                }

                if ((t2 >= 0d) && (t2 <= 1d))
                {
                    result.AppendPoint(new Point2D(u1 + ((u2 - u1) * t2) + cx, v1 + ((v2 - v1) * t2) + cy));
                    result.State = IntersectionStates.Intersection;
                }

                // ToDo: Figure out why the results are weird between 30 degrees and 5 degrees.
            }

            return(result);
        }
Beispiel #16
0
        public static Intersection ObliqueEllipseObliqueEllipseIntersection(
            double h1, double k1, double a1, double b1, double cos1, double sin1,
            double h2, double k2, double a2, double b2, double cos2, double sin2,
            double epsilon = double.Epsilon)
        {
            // If the ellipses aren't rotated, use the slightly faster Orthogonal method.
            if (cos1 == Cos0 && cos2 == Cos0 && sin1 == Sin0 && sin2 == Sin0)
            {
                return(OrthogonalEllipseOrthogonalEllipseIntersectionTests.OrthogonalEllipseOrthogonalEllipseIntersection(h1, k1, a1, b1, h2, k2, a2, b2, epsilon));
            }

            // If the angles are reflections of each other with slight loss of precision in sin cos, and they are the same height and size, the angle needs to be corrected.
            if (Abs(cos1 - cos2) < epsilon && Abs(sin1 + sin2) < epsilon && k1 == k2 && a1 == a2 && b1 == b2)
            {
                // Fix for Case 0.
                cos1 = cos2;
                sin1 = -sin2;
                // ToDo: Verify this fix with more tests.
                // What happens when the ellipses are swapped?
            }

            // If the ellipses are rotated at 90 degrees to each other, and their sizes are opposites, everything gets messed up. So, let's use Orthogonal intersection code.
            if (CrossProduct2Vector2DTests.CrossProduct2Vector2D(cos1, sin1, cos2, sin2) == 1d && a1 == b2 && a2 == b1)
            {
                // Rotate the center point of the second ellipse in the reverse angle about the center of the first ellipse to align with it.
                (h2, k2) = RotatePointAboutPointTests.RotatePoint(h2, k2, cos1, -sin1, h1, k1);

                // Rotate second ellipse Orthogonally.
                SwapTests.Swap(ref a2, ref b2);

                // Find the points of intersection.
                var intersection = OrthogonalEllipseOrthogonalEllipseIntersectionTests.OrthogonalEllipseOrthogonalEllipseIntersection(h1, k1, a1, b1, h2, k2, a2, b2, epsilon);

                // Rotate the points back forwards to the locations of the intersection.
                for (var i = 0; i < intersection.Items.Count; i++)
                {
                    // Rotate point.
                    intersection.Items[i] = RotatePointAboutPointTests.RotatePoint(intersection.Items[i].X, intersection.Items[i].Y, cos1, sin1, h1, k1);
                }

                // Return result.
                return(intersection);
            }

            // Polynomials representing the Ellipses.
            var e1 = EllipseConicSectionPolynomialTests.EllipseConicSectionPolynomial(h1, k1, a1, b1, cos1, sin1);
            var e2 = EllipseConicSectionPolynomialTests.EllipseConicSectionPolynomial(h2, k2, a2, b2, cos2, sin2);

            var yRoots = new Polynomial(ConicSectionBezoutTests.ConicSectionBezout(e1, e2)).Trim().Roots();

            // Double epsilon is too small for here.
            epsilon = 1e-6; //1e-3;
            var norm0 = ((e1.a * e1.a) + (2d * e1.b * e1.b) + (e1.c * e1.c)) * epsilon;
            var norm1 = ((e2.a * e2.a) + (2d * e2.b * e2.b) + (e2.c * e2.c)) * epsilon;

            var result = new Intersection(IntersectionStates.NoIntersection);

            foreach (var s in yRoots)
            {
                var xRoots = new Polynomial((
                                                a: e1.a,
                                                b: e1.d + (s * e1.b),
                                                c: e1.f + (s * (e1.e + (s * e1.c)))
                                                )).Trim().Roots();
                foreach (var t in xRoots)
                {
                    var test = (((e1.a * t) + (e1.b * s) + e1.d) * t) + (((e1.c * s) + e1.e) * s) + e1.f;
                    if (Abs(test) < norm0)
                    {
                        test = (((e2.a * t) + (e2.b * s) + e2.d) * t) + (((e2.c * s) + e2.e) * s) + e2.f;
                        if (Abs(test) < norm1)
                        {
                            result.AppendPoint(new Point2D(t, s));
                        }
                    }
                }
            }

            if (result.Items.Count > 0)
            {
                result.State = IntersectionStates.Intersection;
            }

            return(result);
        }
Beispiel #17
0
        public static Intersection QuadraticBezierSegmentQuadraticBezierSegmentIntersection0(
            double a1X, double a1Y, double a2X, double a2Y, double a3X, double a3Y,
            double b1X, double b1Y, double b2X, double b2Y, double b3X, double b3Y,
            double epsilon = Epsilon)
        {
            // Initialize the intersection.
            var result = new Intersection(IntersectionStates.NoIntersection);

            var xCoeffA = QuadraticBezierBernsteinBasisTests.QuadraticBezierBernsteinBasis(a1X, a2X, a3X);
            var yCoeffA = QuadraticBezierBernsteinBasisTests.QuadraticBezierBernsteinBasis(a1Y, a2Y, a3Y);
            var xCoeffB = QuadraticBezierBernsteinBasisTests.QuadraticBezierBernsteinBasis(b1X, b2X, b3X);
            var yCoeffB = QuadraticBezierBernsteinBasisTests.QuadraticBezierBernsteinBasis(b1Y, b2Y, b3Y);

            var a = (xCoeffA.C * yCoeffA.B) - (xCoeffA.B * yCoeffA.C);
            var b = (xCoeffB.C * yCoeffA.B) - (xCoeffA.B * yCoeffB.C);

            var c = (xCoeffB.B * yCoeffA.B) - (xCoeffA.B * yCoeffB.B);
            var d = (xCoeffA.B * (yCoeffA.A - yCoeffB.A)) - (yCoeffA.B * (xCoeffB.A - xCoeffA.A));
            var e = (xCoeffB.C * yCoeffA.C) - (xCoeffA.C * yCoeffB.C);
            var f = (xCoeffB.B * yCoeffA.C) - (xCoeffA.C * yCoeffB.B);
            var g = (xCoeffA.C * (yCoeffA.A - yCoeffB.A)) - (yCoeffA.C * (yCoeffB.A - xCoeffA.A));

            var roots = QuarticRootsTests.QuarticRoots(
                /* t^4 */ e * e,
                /* t^3 */ 2 * e * f,
                /* t^2 */ (-a * b) + (f * f) + (2 * e * g),
                /* t^1 */ (-a * c) + (2 * f * g),
                /* C */ (-a * d) + (g * g),
                epsilon);

            foreach (var s in roots)
            {
                var point = new Point2D(
                    (xCoeffB.C * s * s) + (xCoeffB.B * s) + xCoeffB.A,
                    (yCoeffB.C * s * s) + (yCoeffB.B * s) + yCoeffB.A);
                if (s >= 0 && s <= 1)
                {
                    var xRoots = QuadraticRootsTests.QuadraticRoots(
                        /* t^2 */ -xCoeffA.C,
                        /* t^1 */ -xCoeffA.B,
                        /* C */ -xCoeffA.A + point.X,
                        epsilon);
                    var yRoots = QuadraticRootsTests.QuadraticRoots(
                        /* t^2 */ -yCoeffA.C,
                        /* t^1 */ -yCoeffA.B,
                        /* C */ -yCoeffA.A + point.Y,
                        epsilon);

                    if (xRoots.Count > 0 && yRoots.Count > 0)
                    {
                        // Find the nearest matching x and y roots in the ranges 0 < x < 1; 0 < y < 1.
                        foreach (var xRoot in xRoots)
                        {
                            if (xRoot >= 0 && xRoot <= 1)
                            {
                                foreach (var yRoot in yRoots)
                                {
                                    var t = xRoot - yRoot;
                                    if ((t >= 0 ? t : -t) < 0.06) // ToDo: Find the error and replace 0.06 with epsilon.
                                    {
                                        result.AppendPoint(point);
                                        goto checkRoots; // Break through two levels of foreach loops. Using goto for performance.
                                    }
                                }
                            }
                        }
                        checkRoots :;
                    }
                }
            }

            if (result.Items.Count > 0)
            {
                result.State = IntersectionStates.Intersection;
            }

            return(result);
        }