/// <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)); }
/// <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); }