/// <summary> /// Finds the endpoint of the segments P and Q which /// is closest to the other segment. /// This is a reasonable surrogate for the true /// intersection points in ill-conditioned cases /// (e.g. where two segments are nearly coincident, /// or where the endpoint of one segment lies almost on the other segment). /// </summary> /// <remarks> /// This replaces the older CentralEndpoint heuristic, /// which chose the wrong endpoint in some cases /// where the segments had very distinct slopes /// and one endpoint lay almost on the other segment. /// </remarks> /// <param name="p1">an endpoint of segment P</param> /// <param name="p2">an endpoint of segment P</param> /// <param name="q1">an endpoint of segment Q</param> /// <param name="q2">an endpoint of segment Q</param> /// <returns>the nearest endpoint to the other segment</returns> private static Coordinate NearestEndpoint(Coordinate p1, Coordinate p2, Coordinate q1, Coordinate q2) { Coordinate nearestPt = p1; double minDist = CGAlgorithms.DistancePointLine(p1, q1, q2); double dist = CGAlgorithms.DistancePointLine(p2, q1, q2); if (dist < minDist) { minDist = dist; nearestPt = p2; } dist = CGAlgorithms.DistancePointLine(q1, p1, p2); if (dist < minDist) { minDist = dist; nearestPt = q1; } dist = CGAlgorithms.DistancePointLine(q2, p1, p2); if (dist < minDist) { minDist = dist; nearestPt = q2; } return(nearestPt); }
private void TryDist(Coordinate p, Coordinate p0, Coordinate p1) { double dist = CGAlgorithms.DistancePointLine(p, p0, p1); if (dist < _minDist) { _minDist = dist; Intersection = p; } }
/// <summary> /// Computes the distance from a point to a sequence of line segments. /// </summary> /// <param name="p">A point</param> /// <param name="line">A sequence of contiguous line segments defined by their vertices</param> /// <returns>The minimum distance between the point and the line segments</returns> /// <exception cref="ArgumentException">If there are too few points to make up a line (at least one?)</exception> public static double DistancePointLine(Coordinate p, Coordinate[] line) { if (line.Length == 0) { throw new ArgumentException("Line array must contain at least one vertex"); } // this handles the case of length = 1 double minDistance = p.Distance(line[0]); for (int i = 0; i < line.Length - 1; i++) { double dist = CGAlgorithms.DistancePointLine(p, line[i], line[i + 1]); if (dist < minDistance) { minDistance = dist; } } return(minDistance); }
/// <summary> /// Computes the distance from a line segment AB to a line segment CD. /// Note: NON-ROBUST! /// </summary> /// <param name="A">A point of one line.</param> /// <param name="B">The second point of the line (must be different to A).</param> /// <param name="C">One point of the line.</param> /// <param name="D">Another point of the line (must be different to A).</param> /// <returns>The distance from line segment AB to line segment CD.</returns> public static double DistanceLineLine(Coordinate A, Coordinate B, Coordinate C, Coordinate D) { // check for zero-length segments if (A.Equals(B)) { return(CGAlgorithms.DistancePointLine(A, C, D)); } if (C.Equals(D)) { return(CGAlgorithms.DistancePointLine(D, A, B)); } // AB and CD are line segments /* * from comp.graphics.algo * * Solving the above for r and s yields * (Ay-Cy)(Dx-Cx)-(Ax-Cx)(Dy-Cy) * r = ----------------------------- (eqn 1) * (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx) * * (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay) * s = ----------------------------- (eqn 2) * (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx) * * Let P be the position vector of the * intersection point, then * P=A+r(B-A) or * Px=Ax+r(Bx-Ax) * Py=Ay+r(By-Ay) * By examining the values of r & s, you can also determine some other limiting * conditions: * If 0<=r<=1 & 0<=s<=1, intersection exists * r<0 or r>1 or s<0 or s>1 line segments do not intersect * If the denominator in eqn 1 is zero, AB & CD are parallel * If the numerator in eqn 1 is also zero, AB & CD are collinear. */ double r_top = (A.Y - C.Y) * (D.X - C.X) - (A.X - C.X) * (D.Y - C.Y); double r_bot = (B.X - A.X) * (D.Y - C.Y) - (B.Y - A.Y) * (D.X - C.X); double s_top = (A.Y - C.Y) * (B.X - A.X) - (A.X - C.X) * (B.Y - A.Y); double s_bot = (B.X - A.X) * (D.Y - C.Y) - (B.Y - A.Y) * (D.X - C.X); if ((r_bot == 0) || (s_bot == 0)) { return(Math .Min( CGAlgorithms.DistancePointLine(A, C, D), Math.Min( CGAlgorithms.DistancePointLine(B, C, D), Math.Min(CGAlgorithms.DistancePointLine(C, A, B), CGAlgorithms.DistancePointLine(D, A, B))))); } double s = s_top / s_bot; double r = r_top / r_bot; if ((r < 0) || (r > 1) || (s < 0) || (s > 1)) { // no intersection return(Math .Min( CGAlgorithms.DistancePointLine(A, C, D), Math.Min( CGAlgorithms.DistancePointLine(B, C, D), Math.Min(CGAlgorithms.DistancePointLine(C, A, B), CGAlgorithms.DistancePointLine(D, A, B))))); } return(0.0); // intersection exists }