Exemplo n.º 1
0
        /// <summary>Used by <see cref="CountWindings(PointF,PointF*,int)"/>.</summary>
        /// <remarks>
        /// Algorithm as given on <a href="http://softsurfer.com/Archive/algorithm_0103/algorithm_0103.htm">http://softsurfer.com/Archive/algorithm_0103/algorithm_0103.htm</a>.
        /// </remarks>
        private static int IsLeft(PointF point0, PointF point1, PointF testPoint)
        {
            // this is a dot product of the vector test to p0, with a normal to the vector p0 to p1.
            float result = (point1.X - point0.X) * (testPoint.Y - point0.Y) - (testPoint.X - point0.X) * (point1.Y - point0.Y);

            return(FloatComparer.Compare(result, 0, 1));
        }
Exemplo n.º 2
0
        /// <summary>
        /// Computes the intersection between two line segments, if a solution exists.
        /// </summary>
        /// <param name="p1">One endpoint of one line segment.</param>
        /// <param name="p2">The other endpoint of one line segment.</param>
        /// <param name="q1">One endpoint of the other line segment.</param>
        /// <param name="q2">The other endpoint of the other line segment.</param>
        /// <param name="intersection">The intersection between the two line segments, if a solution exists.</param>
        /// <returns>True if the intersection exists; False otherwise.</returns>

        //TODO (CR February 2011) - High (SDK release): Name? GetLineSegmentIntersection : Nullable<Point>
        public static bool IntersectLineSegments(PointF p1, PointF p2, PointF q1, PointF q2, out PointF intersection)
        {
            // find the solution to the line equations in matrix form
            // P1 + s(P2-P1) = Q1 + t(Q2-Q1)
            // => P1 + s(P2-P1) = Q1 - t(Q1-Q2)
            // => [P2-P1 Q1-Q2] * [s t]^T = Q1-P1
            // => [s t]^T = [P2-P1 Q1-Q2]^-1 * [Q1-P1]

            // use double precision floating point variables to minimize precision loss

            // compute elements of the matrix M
            double m11 = p2.X - p1.X;             // M[R1C1]
            double m12 = q1.X - q2.X;             // M[R1C2]
            double m21 = p2.Y - p1.Y;             // M[R2C1]
            double m22 = q1.Y - q2.Y;             // M[R2C2]

            // compute determinant of the matrix M
            double determinant = m11 * m22 - m12 * m21;         // det(M)

            if (!FloatComparer.AreEqual(determinant, 0))
            {
                // compute elements of the inverted matrix M^-1
                double v11 = m22 / determinant;
                double v12 = -m12 / determinant;
                double v21 = -m21 / determinant;
                double v22 = m11 / determinant;

                // compute elements of the RHS vector
                double r1 = q1.X - p1.X;
                double r2 = q1.Y - p1.Y;

                // left-multiply inverted matrix with RHS to get solution of {s,t}
                double s = v11 * r1 + v12 * r2;
                double t = v21 * r1 + v22 * r2;

                //TODO (CR February 2011) - Medium (SDK release): tolerance seems arbitrary.  Should add an overload that accepts the tolerance.

                // the solution {s,t} represents the intersection of the lines
                // for line segments, we must therefore further restrict the valid range of {s,t} to [0,1]
                const int tolerance = 100000;                 // allow additional tolerance due to amount of floating-point computation
                if (FloatComparer.Compare(s, 0, tolerance) >= 0 && FloatComparer.Compare(s, 1, tolerance) <= 0 &&
                    FloatComparer.Compare(t, 0, tolerance) >= 0 && FloatComparer.Compare(t, 1, tolerance) <= 0)
                {
                    intersection = new PointF((float)(p1.X + s * m11), (float)(p1.Y + s * m21));
                    return(true);
                }
            }

            intersection = PointF.Empty;
            return(false);
        }