/// <summary> /// Static version of InCentre function. /// </summary> public static C2DPoint GetInCentre(C2DPoint pt1, C2DPoint pt2, C2DPoint pt3) { // Set up a line to bisect the lines from 1 to 2 and 1 to 3 var Line1 = new C2DLine(pt1, pt2); var Line2 = new C2DLine(pt1, pt3); Line1.SetLength(Line2.GetLength()); var Line12Bisect = new C2DLine(pt1, pt3.GetMidPoint(Line1.GetPointTo())); // Set up a line to bisect the lines from 2 to 1 and 2 to 3 var Line3 = new C2DLine(pt2, pt1); var Line4 = new C2DLine(pt2, pt3); Line3.SetLength(Line4.GetLength()); var Line34Bisect = new C2DLine(pt2, pt3.GetMidPoint(Line3.GetPointTo())); // Now intersect the 2 lines and find the point. var Int = new List <C2DPoint>(); // Add the intersection even if there isn't one (i.e. infinite lines) bool B1 = true, B2 = true; Line12Bisect.Crosses(Line34Bisect, Int, ref B1, ref B2, true); Debug.Assert(Int.Count == 1); return(Int[0]); }
/// <summary> /// Returns the distance from this to the other line. /// </summary> /// <param name="Other">The Other line.</param> /// <param name="ptOnThis">Output. The closest point on this.</param> /// <param name="ptOnOther">Output. The closest point on the other line.</param> public double Distance(C2DLine Other, C2DPoint ptOnThis , C2DPoint ptOnOther) { // First, project the other line onto this and if it falls entirely below it or // above it then 1. There is no intersection, 2. This is closest to one end on this line. C2DPoint ptOtherP2 = new C2DPoint(Other.GetPointTo()); C2DVector vThisP1OtherP1 = new C2DVector(point, Other.point); C2DVector vThisP1OtherP2 = new C2DVector(point, ptOtherP2); C2DPoint ptThisP2 = new C2DPoint(GetPointTo()); double dOtherP1Proj = vThisP1OtherP1.Dot(vector); double dOtherP2Proj = vThisP1OtherP2.Dot(vector); // If they are both less than 0 then the projection falls below the line. if (dOtherP1Proj <= 0 && dOtherP2Proj <= 0) { ptOnThis.Set(point); return Other.Distance(point, ptOnOther); } // Now modify the projection so it is the length along this line. double dThisLength = GetLength(); dOtherP1Proj = dOtherP1Proj / dThisLength; dOtherP2Proj = dOtherP2Proj / dThisLength; // If the projections are both above the line then the second point is closest if (dOtherP1Proj >= dThisLength && dOtherP2Proj >= dThisLength) { ptOnThis.Set(ptThisP2); return Other.Distance( ptThisP2, ptOnOther); } // This hasn't worked so try the same on the other line. C2DVector vOtherP1ThisP1 = new C2DVector (Other.point, point); C2DVector vOtherP1ThisP2 = new C2DVector(Other.point, ptThisP2); double dThisP1Proj = vOtherP1ThisP1.Dot(Other.vector); double dThisP2Proj = vOtherP1ThisP2.Dot(Other.vector); // If they are both less than 0 then the projection falls below the line. if (dThisP1Proj <= 0 && dThisP2Proj <= 0) { ptOnOther.Set( Other.point); return Distance(Other.point, ptOnThis); } // Now modify the projection so it is the length along this line. double dOtherLength = Other.GetLength(); dThisP1Proj = dThisP1Proj / dOtherLength; dThisP2Proj = dThisP2Proj / dOtherLength; // If the projections are both above the line then the second point is closest if (dThisP1Proj >= dOtherLength && dThisP2Proj >= dOtherLength) { ptOnOther.Set(ptOtherP2); return Distance( ptOtherP2, ptOnThis); } // Now test for an intersection. List<C2DPoint> IntPoint = new List<C2DPoint>(); bool B1 = true, B2 = true; if (this.Crosses(Other, IntPoint,ref B1, ref B2, false)) { ptOnOther.Set(IntPoint[0]); ptOnThis.Set(IntPoint[0]); return 0; } // Otherwise, there MUST be a point projection on one of the lines otherwise both // lines project on either side of each other which is impossible. // So find the distances to all these projections and take the minimum. double dDist = 0; double dMinDist = 0; bool bSet = false; C2DPoint ptOnThisTemp = new C2DPoint(); C2DPoint ptOnOtherTemp = new C2DPoint(); // Is the other lines first point projected on this? if (dOtherP1Proj >= 0 && dOtherP1Proj <= dThisLength) { // If so find the point on this line and get distance to it. double dFactor = dOtherP1Proj / dThisLength; ptOnThisTemp.Set(new C2DPoint(point.x + vector.i * dFactor, point.y + vector.j * dFactor) ); dMinDist = Other.point.Distance(ptOnThisTemp); bSet = true; ptOnOther.Set(Other.point); ptOnThis.Set(ptOnThisTemp); } // Is the other lines second point projected onto this? if (dOtherP2Proj >= 0 && dOtherP2Proj <= dThisLength) { // If so find the point on this and then the distance. Is it less? double dFactor = dOtherP2Proj / dThisLength; ptOnThisTemp.Set( new C2DPoint(point.x + vector.i * dFactor, point.y + vector.j * dFactor) ); dDist = ptOtherP2.Distance(ptOnThisTemp); if (!bSet || dDist < dMinDist) { ptOnOther.Set(ptOtherP2); ptOnThis.Set(ptOnThisTemp); dMinDist = dDist; bSet = true; } } // Is the first point on this projected onto the other line? if (dThisP1Proj >= 0 && dThisP1Proj <= dOtherLength) { // If so find the point and the distance. Is it less? double dFactor = dThisP1Proj / dOtherLength; ptOnOtherTemp.Set( new C2DPoint(Other.point.x + Other.vector.i * dFactor, Other.point.y + Other.vector.j * dFactor)); dDist = point.Distance(ptOnOtherTemp); if (!bSet || dDist < dMinDist) { ptOnThis.Set(point); ptOnOther.Set(ptOnOtherTemp); dMinDist = dDist; bSet = true; } } // Is the second point on this projected onto the other line? if (dThisP2Proj >= 0 && dThisP2Proj <= dOtherLength) { // If so find the point and the distance. Is it less? double dFactor = dThisP2Proj / dOtherLength; ptOnOtherTemp.Set( new C2DPoint(Other.point.x + Other.vector.i * dFactor, Other.point.y + Other.vector.j * dFactor)); dDist = ptThisP2.Distance(ptOnOtherTemp); if (!bSet || dDist < dMinDist) { ptOnThis.Set(ptThisP2); ptOnOther.Set(ptOnOtherTemp); dMinDist = dDist; bSet = true; } } Debug.Assert( bSet ); // Now return the minimum distance return dMinDist; }
/// <summary> /// Static version of InCentre function. /// </summary> public static C2DPoint GetInCentre(C2DPoint pt1, C2DPoint pt2, C2DPoint pt3) { // Set up a line to bisect the lines from 1 to 2 and 1 to 3 C2DLine Line1 = new C2DLine(pt1, pt2); C2DLine Line2 = new C2DLine(pt1, pt3); Line1.SetLength( Line2.GetLength() ); C2DLine Line12Bisect = new C2DLine( pt1, pt3.GetMidPoint( Line1.GetPointTo())); // Set up a line to bisect the lines from 2 to 1 and 2 to 3 C2DLine Line3 = new C2DLine(pt2, pt1); C2DLine Line4 = new C2DLine(pt2, pt3); Line3.SetLength( Line4.GetLength() ); C2DLine Line34Bisect = new C2DLine(pt2, pt3.GetMidPoint(Line3.GetPointTo())); // Now intersect the 2 lines and find the point. List<C2DPoint> Int = new List<C2DPoint>(); // Add the intersection even if there isn't one (i.e. infinite lines) bool B1 = true, B2 = true; Line12Bisect.Crosses(Line34Bisect, Int, ref B1, ref B2, true); Debug.Assert (Int.Count == 1); return Int[0]; }
/// <summary> /// Distance to a point. /// </summary> /// <param name="ptTest">The test point.</param> /// <param name="ptOnThis">Output. The closest point on the triangle.</param> public double Distance(C2DPoint ptTest, C2DPoint ptOnThis) { double dArea = GetAreaSigned(); bool BTemp = true; // Construct the lines. C2DLine Line12 = new C2DLine(P1, P2); C2DLine Line23 = new C2DLine(P2, P3); C2DLine Line31 = new C2DLine(P3, P1); if (dArea == 0) { // Colinear so find the biggest line and return the distance from that double d1 = Line12.GetLength(); double d2 = Line23.GetLength(); double d3 = Line31.GetLength(); if (d1 > d2 && d1 > d3) return Line12.Distance(ptTest, ptOnThis); else if (d2 > d3) return Line23.Distance(ptTest, ptOnThis); else return Line31.Distance(ptTest, ptOnThis); } // Find out it the triangle is clockwise or not. bool bClockwise = dArea < 0; // Set up some pointers to record the lines that the point is "above", "above" meaning that the // point is on the opposite side of the line to the rest of the triangle C2DLine LineAbove1 = null; C2DLine LineAbove2 = null; // Find out which Lines have the point above. if ( Line12.IsOnRight( ptTest ) ^ bClockwise ) // if the pt is on the opposite side to the triangle LineAbove1 = Line12; if ( Line23.IsOnRight( ptTest ) ^ bClockwise) { if (LineAbove1 != null) LineAbove2 = Line23; else LineAbove1 = Line23; } if ( Line31.IsOnRight( ptTest ) ^ bClockwise) { if (LineAbove1 != null) { // We can't have all the lines with the point above. Debug.Assert(LineAbove2 != null); LineAbove2 = Line31; } else LineAbove1 = Line31; } // Check for containment (if there isn't a single line that its above then it must be inside) if (LineAbove1 == null) { // Pt inside so project onto all the lines and find the closest projection (there must be one). // Set up a record of the point projection on the lines. C2DPoint ptOnLine = new C2DPoint(); bool bSet = false; double dMinDist = 0; if (ptTest.ProjectsOnLine(Line12, ptOnLine, ref BTemp)) { dMinDist = ptTest.Distance(ptOnLine); ptOnThis.Set(ptOnLine); bSet = true; } if (ptTest.ProjectsOnLine(Line23, ptOnLine, ref BTemp)) { double dDist = ptTest.Distance(ptOnLine); if (!bSet || dDist < dMinDist) { dMinDist = dDist; ptOnThis.Set(ptOnLine); bSet = true; } } if (ptTest.ProjectsOnLine(Line31, ptOnLine, ref BTemp)) { double dDist = ptTest.Distance(ptOnLine); if (!bSet || dDist < dMinDist) { dMinDist = dDist; ptOnThis.Set(ptOnLine); bSet = true; } } Debug.Assert(bSet); return -dMinDist; //-ve if inside } else if (LineAbove2 == null) { // it is only above 1 of the lines so simply return the distance to that line return LineAbove1.Distance(ptTest, ptOnThis); } else { // It's above 2 lines so first check them both for projection. Can only be projected on 1. // If the point can be projected onto the line then that's the closest point. C2DPoint ptOnLine = new C2DPoint(); if (ptTest.ProjectsOnLine(LineAbove1, ptOnLine, ref BTemp)) { ptOnThis = ptOnLine; return ptOnLine.Distance(ptTest); } else if (ptTest.ProjectsOnLine(LineAbove2, ptOnLine, ref BTemp)) { ptOnThis = ptOnLine; return ptOnLine.Distance(ptTest); } else { // The point doesn't project onto either line so find the closest point if (LineAbove1 == Line12) { if (LineAbove2 == Line23) { ptOnThis = P2; return ptTest.Distance(P2); } else { ptOnThis = P1; return ptTest.Distance(P1); } } else { ptOnThis = P3; return ptTest.Distance(P3); } } } }
/// <summary> /// Distance to a line, returns the closest point on the circle and the line. /// </summary> /// <param name="Line">Line to calculate the distance to.</param> /// <param name="ptOnThis">Closest point on the circle to recieve the result.</param> /// <param name="ptOnOther">Closest point on the line to recieve the result.</param> public double Distance(C2DLine Line, C2DPoint ptOnThis, C2DPoint ptOnOther) { CInterval ProjInt = new CInterval(); Project(Line, ProjInt); if (ProjInt.dMax < 0) { // This means that the circle projects entirely "below" the line so the nearest point // To this is the first point on the line and there are no interections. ptOnOther.Set(Line.point); return(Distance(Line.point, ptOnThis)); } double dLength = Line.GetLength(); if (ProjInt.dMin > dLength) { // This means that the circle projects entirely "above" the line so the nearest point // To this is the second point on the line and there are no interections. C2DPoint ptClosest = new C2DPoint(Line.GetPointTo()); ptOnOther.Set(ptClosest); return(Distance(ptClosest, ptOnThis)); } // Now find out if there's an intersection. List <C2DPoint> IntPts = new List <C2DPoint>(); if (Crosses(Line, IntPts)) { ptOnThis.Set(IntPts[0]); ptOnOther.Set(IntPts[0]); return(0); } // Now find out if the line is entirely inside if (ProjInt.dMin > 0 && ProjInt.dMax < dLength && this.Contains(Line.point)) { double d1 = Distance(Line.point, ptOnThis); C2DPoint ptThisTemp = new C2DPoint(); double d2 = Distance(Line.GetPointTo(), ptThisTemp); Debug.Assert(d1 < 0 && d2 < 0); if (d2 > d1) // NOTE USE OF > AS d2 and d1 are -ve. { ptOnThis.Set(ptThisTemp); ptOnOther.Set(Line.GetPointTo()); return(d2); } else { ptOnOther.Set(Line.point); return(d1); } } // We now know the line is entirely outside. // Now find out if this is closest to a point on the line. double dCenOnLine = (ProjInt.dMax + ProjInt.dMin) / 2.0; if (dCenOnLine > 0) { if (dCenOnLine < dLength) { // The centre is projected on the line double dFactor = dCenOnLine / dLength; C2DVector vProj = new C2DVector(Line.vector); vProj.Multiply(dFactor); C2DPoint ptOnLine = new C2DPoint(Line.point.GetPointTo(vProj)); ptOnOther.Set(ptOnLine); return(Distance(ptOnLine, ptOnThis)); } else { // The centre is projected above the line. C2DPoint ptClosest = new C2DPoint(Line.GetPointTo()); ptOnOther.Set(ptClosest); return(Distance(ptClosest, ptOnThis)); } } else { // This means that the circle projects entirely "below" the line. ptOnOther.Set(Line.point); return(Distance(Line.point, ptOnThis)); } }
/// <summary> /// Distance to a point. /// </summary> /// <param name="ptTest">The test point.</param> /// <param name="ptOnThis">Output. The closest point on the triangle.</param> public double Distance(C2DPoint ptTest, C2DPoint ptOnThis) { var dArea = GetAreaSigned(); var BTemp = true; // Construct the lines. var Line12 = new C2DLine(P1, P2); var Line23 = new C2DLine(P2, P3); var Line31 = new C2DLine(P3, P1); if (dArea == 0) { // Colinear so find the biggest line and return the distance from that var d1 = Line12.GetLength(); var d2 = Line23.GetLength(); var d3 = Line31.GetLength(); if (d1 > d2 && d1 > d3) { return(Line12.Distance(ptTest, ptOnThis)); } else if (d2 > d3) { return(Line23.Distance(ptTest, ptOnThis)); } else { return(Line31.Distance(ptTest, ptOnThis)); } } // Find out it the triangle is clockwise or not. var bClockwise = dArea < 0; // Set up some pointers to record the lines that the point is "above", "above" meaning that the // point is on the opposite side of the line to the rest of the triangle C2DLine LineAbove1 = null; C2DLine LineAbove2 = null; // Find out which Lines have the point above. if (Line12.IsOnRight(ptTest) ^ bClockwise) // if the pt is on the opposite side to the triangle { LineAbove1 = Line12; } if (Line23.IsOnRight(ptTest) ^ bClockwise) { if (LineAbove1 != null) { LineAbove2 = Line23; } else { LineAbove1 = Line23; } } if (Line31.IsOnRight(ptTest) ^ bClockwise) { if (LineAbove1 != null) { // We can't have all the lines with the point above. Debug.Assert(LineAbove2 != null); LineAbove2 = Line31; } else { LineAbove1 = Line31; } } // Check for containment (if there isn't a single line that its above then it must be inside) if (LineAbove1 == null) { // Pt inside so project onto all the lines and find the closest projection (there must be one). // Set up a record of the point projection on the lines. var ptOnLine = new C2DPoint(); var bSet = false; double dMinDist = 0; if (ptTest.ProjectsOnLine(Line12, ptOnLine, ref BTemp)) { dMinDist = ptTest.Distance(ptOnLine); ptOnThis.Set(ptOnLine); bSet = true; } if (ptTest.ProjectsOnLine(Line23, ptOnLine, ref BTemp)) { var dDist = ptTest.Distance(ptOnLine); if (!bSet || dDist < dMinDist) { dMinDist = dDist; ptOnThis.Set(ptOnLine); bSet = true; } } if (ptTest.ProjectsOnLine(Line31, ptOnLine, ref BTemp)) { var dDist = ptTest.Distance(ptOnLine); if (!bSet || dDist < dMinDist) { dMinDist = dDist; ptOnThis.Set(ptOnLine); bSet = true; } } Debug.Assert(bSet); return(-dMinDist); //-ve if inside } else if (LineAbove2 == null) { // it is only above 1 of the lines so simply return the distance to that line return(LineAbove1.Distance(ptTest, ptOnThis)); } else { // It's above 2 lines so first check them both for projection. Can only be projected on 1. // If the point can be projected onto the line then that's the closest point. var ptOnLine = new C2DPoint(); if (ptTest.ProjectsOnLine(LineAbove1, ptOnLine, ref BTemp)) { ptOnThis = ptOnLine; return(ptOnLine.Distance(ptTest)); } else if (ptTest.ProjectsOnLine(LineAbove2, ptOnLine, ref BTemp)) { ptOnThis = ptOnLine; return(ptOnLine.Distance(ptTest)); } else { // The point doesn't project onto either line so find the closest point if (LineAbove1 == Line12) { if (LineAbove2 == Line23) { ptOnThis = P2; return(ptTest.Distance(P2)); } else { ptOnThis = P1; return(ptTest.Distance(P1)); } } else { ptOnThis = P3; return(ptTest.Distance(P3)); } } } }
/// <summary> /// Returns the distance from this to the other line. /// </summary> /// <param name="Other">The Other line.</param> /// <param name="ptOnThis">Output. The closest point on this.</param> /// <param name="ptOnOther">Output. The closest point on the other line.</param> public double Distance(C2DLine Other, C2DPoint ptOnThis, C2DPoint ptOnOther) { // First, project the other line onto this and if it falls entirely below it or // above it then 1. There is no intersection, 2. This is closest to one end on this line. var ptOtherP2 = new C2DPoint(Other.GetPointTo()); var vThisP1OtherP1 = new C2DVector(point, Other.point); var vThisP1OtherP2 = new C2DVector(point, ptOtherP2); var ptThisP2 = new C2DPoint(GetPointTo()); var dOtherP1Proj = vThisP1OtherP1.Dot(vector); var dOtherP2Proj = vThisP1OtherP2.Dot(vector); // If they are both less than 0 then the projection falls below the line. if (dOtherP1Proj <= 0 && dOtherP2Proj <= 0) { ptOnThis.Set(point); return(Other.Distance(point, ptOnOther)); } // Now modify the projection so it is the length along this line. var dThisLength = GetLength(); dOtherP1Proj = dOtherP1Proj / dThisLength; dOtherP2Proj = dOtherP2Proj / dThisLength; // If the projections are both above the line then the second point is closest if (dOtherP1Proj >= dThisLength && dOtherP2Proj >= dThisLength) { ptOnThis.Set(ptThisP2); return(Other.Distance(ptThisP2, ptOnOther)); } // This hasn't worked so try the same on the other line. var vOtherP1ThisP1 = new C2DVector(Other.point, point); var vOtherP1ThisP2 = new C2DVector(Other.point, ptThisP2); var dThisP1Proj = vOtherP1ThisP1.Dot(Other.vector); var dThisP2Proj = vOtherP1ThisP2.Dot(Other.vector); // If they are both less than 0 then the projection falls below the line. if (dThisP1Proj <= 0 && dThisP2Proj <= 0) { ptOnOther.Set(Other.point); return(Distance(Other.point, ptOnThis)); } // Now modify the projection so it is the length along this line. var dOtherLength = Other.GetLength(); dThisP1Proj = dThisP1Proj / dOtherLength; dThisP2Proj = dThisP2Proj / dOtherLength; // If the projections are both above the line then the second point is closest if (dThisP1Proj >= dOtherLength && dThisP2Proj >= dOtherLength) { ptOnOther.Set(ptOtherP2); return(Distance(ptOtherP2, ptOnThis)); } // Now test for an intersection. var IntPoint = new List <C2DPoint>(); bool B1 = true, B2 = true; if (this.Crosses(Other, IntPoint, ref B1, ref B2, false)) { ptOnOther.Set(IntPoint[0]); ptOnThis.Set(IntPoint[0]); return(0); } // Otherwise, there MUST be a point projection on one of the lines otherwise both // lines project on either side of each other which is impossible. // So find the distances to all these projections and take the minimum. double dDist = 0; double dMinDist = 0; var bSet = false; var ptOnThisTemp = new C2DPoint(); var ptOnOtherTemp = new C2DPoint(); // Is the other lines first point projected on this? if (dOtherP1Proj >= 0 && dOtherP1Proj <= dThisLength) { // If so find the point on this line and get distance to it. var dFactor = dOtherP1Proj / dThisLength; ptOnThisTemp.Set(new C2DPoint(point.x + vector.i * dFactor, point.y + vector.j * dFactor)); dMinDist = Other.point.Distance(ptOnThisTemp); bSet = true; ptOnOther.Set(Other.point); ptOnThis.Set(ptOnThisTemp); } // Is the other lines second point projected onto this? if (dOtherP2Proj >= 0 && dOtherP2Proj <= dThisLength) { // If so find the point on this and then the distance. Is it less? var dFactor = dOtherP2Proj / dThisLength; ptOnThisTemp.Set(new C2DPoint(point.x + vector.i * dFactor, point.y + vector.j * dFactor)); dDist = ptOtherP2.Distance(ptOnThisTemp); if (!bSet || dDist < dMinDist) { ptOnOther.Set(ptOtherP2); ptOnThis.Set(ptOnThisTemp); dMinDist = dDist; bSet = true; } } // Is the first point on this projected onto the other line? if (dThisP1Proj >= 0 && dThisP1Proj <= dOtherLength) { // If so find the point and the distance. Is it less? var dFactor = dThisP1Proj / dOtherLength; ptOnOtherTemp.Set(new C2DPoint(Other.point.x + Other.vector.i * dFactor, Other.point.y + Other.vector.j * dFactor)); dDist = point.Distance(ptOnOtherTemp); if (!bSet || dDist < dMinDist) { ptOnThis.Set(point); ptOnOther.Set(ptOnOtherTemp); dMinDist = dDist; bSet = true; } } // Is the second point on this projected onto the other line? if (dThisP2Proj >= 0 && dThisP2Proj <= dOtherLength) { // If so find the point and the distance. Is it less? var dFactor = dThisP2Proj / dOtherLength; ptOnOtherTemp.Set(new C2DPoint(Other.point.x + Other.vector.i * dFactor, Other.point.y + Other.vector.j * dFactor)); dDist = ptThisP2.Distance(ptOnOtherTemp); if (!bSet || dDist < dMinDist) { ptOnThis.Set(ptThisP2); ptOnOther.Set(ptOnOtherTemp); dMinDist = dDist; bSet = true; } } Debug.Assert(bSet); // Now return the minimum distance return(dMinDist); }
/// <summary> /// Distance to a line, returns the closest point on the circle and the line. /// </summary> /// <param name="Line">Line to calculate the distance to.</param> /// <param name="ptOnThis">Closest point on the circle to recieve the result.</param> /// <param name="ptOnOther">Closest point on the line to recieve the result.</param> public double Distance(C2DLine Line, C2DPoint ptOnThis, C2DPoint ptOnOther) { CInterval ProjInt = new CInterval(); Project(Line, ProjInt); if (ProjInt.dMax < 0) { // This means that the circle projects entirely "below" the line so the nearest point // To this is the first point on the line and there are no interections. ptOnOther.Set(Line.point); return Distance(Line.point, ptOnThis); } double dLength = Line.GetLength(); if (ProjInt.dMin > dLength) { // This means that the circle projects entirely "above" the line so the nearest point // To this is the second point on the line and there are no interections. C2DPoint ptClosest = new C2DPoint(Line.GetPointTo()); ptOnOther.Set( ptClosest ); return Distance(ptClosest, ptOnThis); } // Now find out if there's an intersection. List<C2DPoint> IntPts = new List<C2DPoint>(); if (Crosses(Line, IntPts)) { ptOnThis.Set( IntPts[0]); ptOnOther.Set( IntPts[0]); return 0; } // Now find out if the line is entirely inside if (ProjInt.dMin > 0 && ProjInt.dMax < dLength && this.Contains(Line.point)) { double d1 = Distance(Line.point, ptOnThis); C2DPoint ptThisTemp = new C2DPoint(); double d2 = Distance(Line.GetPointTo(), ptThisTemp); Debug.Assert(d1 < 0 && d2 < 0); if (d2 > d1) // NOTE USE OF > AS d2 and d1 are -ve. { ptOnThis.Set(ptThisTemp); ptOnOther.Set(Line.GetPointTo()); return d2; } else { ptOnOther.Set(Line.point); return d1; } } // We now know the line is entirely outside. // Now find out if this is closest to a point on the line. double dCenOnLine = (ProjInt.dMax + ProjInt.dMin) / 2.0; if (dCenOnLine > 0) { if (dCenOnLine < dLength) { // The centre is projected on the line double dFactor = dCenOnLine / dLength; C2DVector vProj = new C2DVector(Line.vector); vProj.Multiply( dFactor); C2DPoint ptOnLine = new C2DPoint( Line.point.GetPointTo(vProj)); ptOnOther.Set( ptOnLine ); return Distance(ptOnLine, ptOnThis); } else { // The centre is projected above the line. C2DPoint ptClosest = new C2DPoint (Line.GetPointTo()); ptOnOther.Set(ptClosest); return Distance(ptClosest, ptOnThis); } } else { // This means that the circle projects entirely "below" the line. ptOnOther.Set( Line.point); return Distance(Line.point, ptOnThis); } }