/// <summary> /// Returns a vertex representing the closest point on this line segment from a given vertex /// </summary> /// <param name="point">The point we want to be close to</param> /// <param name="isInfiniteLine">If true treat the line as infinitly long</param> /// <param name="endPointFlag">Outputs 0 if the vertex is on the line segment, 1 if beyond P0, 2 if beyong P1 and -1 if P1=P2</param> /// <returns>The point on this segment or infinite line that is closest to the given point</returns> public Vertex ClosestPointTo(Vertex point, bool isInfiniteLine, out EndPointInteraction endPointFlag) { // If the points defining this segment are the same, we treat the segment as a point // special handling to avoid 0 in denominator later if (P2.X == P1.X && P2.Y == P1.Y) { endPointFlag = EndPointInteraction.P1equalsP2; return(P1); } //http://softsurfer.com/Archive/algorithm_0102/algorithm_0102.htm Vector v = ToVector(); // vector from p1 to p2 in the segment v.Z = 0; Vector w = new Vector(P1.ToCoordinate(), point.ToCoordinate()); // vector from p1 to Point w.Z = 0; double c1 = w.Dot(v); // the dot product represents the projection onto the line if (c1 < 0) { endPointFlag = EndPointInteraction.PastP1; if (!isInfiniteLine) // The closest point on the segment to Point is p1 { return(P1); } } double c2 = v.Dot(v); if (c2 <= c1) { endPointFlag = EndPointInteraction.PastP2; if (!isInfiniteLine) // The closest point on the segment to Point is p2 { return(P2); } } // The closest point on the segment is perpendicular to the point, // but somewhere on the segment between P1 and P2 endPointFlag = EndPointInteraction.OnLine; double b = c1 / c2; v = v.Multiply(b); Vertex pb = new Vertex(P1.X + v.X, P1.Y + v.Y); return(pb); }
/// <summary> /// Returns a vertex representing the closest point on this line segment from a given vertex /// </summary> /// <param name="point">The point we want to be close to</param> /// <param name="isInfiniteLine">If true treat the line as infinitly long</param> /// <param name="endPointFlag">Outputs 0 if the vertex is on the line segment, 1 if beyond P0, 2 if beyong P1 and -1 if P1=P2</param> /// <returns>The point on this segment or infinite line that is closest to the given point</returns> public Vertex ClosestPointTo(Vertex point, bool isInfiniteLine, out EndPointInteraction endPointFlag) { // If the points defining this segment are the same, we treat the segment as a point // special handling to avoid 0 in denominator later if (P2.X == P1.X && P2.Y == P1.Y) { endPointFlag = EndPointInteraction.P1equalsP2; return P1; } //http://softsurfer.com/Archive/algorithm_0102/algorithm_0102.htm Vector v = ToVector(); // vector from p1 to p2 in the segment v.Z = 0; Vector w = new Vector(P1.ToCoordinate(), point.ToCoordinate()); // vector from p1 to Point w.Z = 0; double c1 = w.Dot(v); // the dot product represents the projection onto the line if (c1 < 0) { endPointFlag = EndPointInteraction.PastP1; if (!isInfiniteLine) // The closest point on the segment to Point is p1 return P1; } double c2 = v.Dot(v); if (c2 <= c1) { endPointFlag = EndPointInteraction.PastP2; if (!isInfiniteLine) // The closest point on the segment to Point is p2 return P2; } // The closest point on the segment is perpendicular to the point, // but somewhere on the segment between P1 and P2 endPointFlag = EndPointInteraction.OnLine; double b = c1 / c2; v = v.Multiply(b); Vertex pb = new Vertex(P1.X + v.X, P1.Y + v.Y); return pb; }