コード例 #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);
        }
コード例 #2
0
        /// <summary>
        /// Calculate the geometry of points offset at a specified distance. aka Double Line.
        /// </summary>
        /// <param name="pointA">First reference point.</param>
        /// <param name="pointB">First inclusive point.</param>
        /// <param name="pointC">Second inclusive point.</param>
        /// <param name="pointD">Second reference point.</param>
        /// <param name="offsetDistance">Offset Distance</param>
        /// <returns></returns>
        /// <acknowledgment>
        /// Suppose you have 4 points; A, B C, and D. With Lines AB, BC, and CD.<BR/>
        ///<BR/>
        ///                 B1         BC1       C1<BR/>
        ///                   |\¯B¯¯¯¯¯BC¯¯¯C¯¯¯/|<BR/>
        ///                   | \--------------/ |<BR/>
        ///                   | |\____________/| |<BR/>
        ///                   | | |B2  BC2 C2| | |<BR/>
        ///                 AB| | |          | | |CD<BR/>
        ///                AB1| | |AB2    CD2| | |CD1<BR/>
        ///                   | | |          | | |<BR/>
        ///                   | | |          | | |<BR/>
        ///               A1  A  A2      D2  D  D1<BR/>
        ///
        /// </acknowledgment>
        public static Point2D[] CenteredOffsetLinePoints(Point2D pointA, Point2D pointB, Point2D pointC, Point2D pointD, double offsetDistance)
        {
            // To get the vectors of the angles at each corner B and C, Normalize the Unit Delta Vectors along AB, BC, and CD.
            var UnitVectorAB = pointB - pointA;

            UnitVectorAB = new Vector2D(Normalize2DVectorTests.Normalize(UnitVectorAB.I, UnitVectorAB.J));
            var UnitVectorBC = pointC - pointB;

            UnitVectorBC = new Vector2D(Normalize2DVectorTests.Normalize(UnitVectorBC.I, UnitVectorBC.J));
            var UnitVectorCD = pointD - pointC;

            UnitVectorCD = new Vector2D(Normalize2DVectorTests.Normalize(UnitVectorCD.I, UnitVectorCD.J));


            //  Find the Perpendicular of the outside vectors
            var PerpendicularAB = new Vector2D(PerpendicularClockwiseVectorTests.PerpendicularClockwise(UnitVectorAB.I, UnitVectorAB.J));
            var PerpendicularCD = new Vector2D(PerpendicularClockwiseVectorTests.PerpendicularClockwise(UnitVectorCD.I, UnitVectorCD.J));

            //  Normalized Vectors pointing out from B and C.
            var OutUnitVectorB = UnitVectorAB - UnitVectorBC;

            OutUnitVectorB = new Vector2D(Normalize2DVectorTests.Normalize(OutUnitVectorB.I, OutUnitVectorB.J));
            var OutUnitVectorC = UnitVectorCD - UnitVectorBC;

            OutUnitVectorC = new Vector2D(Normalize2DVectorTests.Normalize(OutUnitVectorC.I, OutUnitVectorC.J));

            //  The distance out from B is the radius / Cos(theta) where theta is the angle
            //  from the perpendicular of BC of the UnitVector. The cosine can also be
            //  calculated by doing the dot product of  Unit(Perpendicular(AB)) and
            //  UnitVector.
            var BPointScale = DotProduct2Vector2DTests.DotProduct2D(PerpendicularAB.I, PerpendicularAB.J, OutUnitVectorB.I, OutUnitVectorB.J) * offsetDistance;
            var CPointScale = DotProduct2Vector2DTests.DotProduct2D(PerpendicularCD.I, PerpendicularCD.J, OutUnitVectorC.I, OutUnitVectorC.J) * offsetDistance;

            OutUnitVectorB *= CPointScale;
            OutUnitVectorC *= BPointScale;

            // Corners of the parallelogram to draw
            var Out = new Point2D[] {
                pointC + OutUnitVectorC,
                pointB + OutUnitVectorB,
                pointB - OutUnitVectorB,
                pointC - OutUnitVectorC,
                pointC + OutUnitVectorC
            };

            return(Out);
        }
コード例 #3
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);
        }
コード例 #4
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);
        }
コード例 #5
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);
        }