Exemple #1
0
        /// <summary>
        /// Distance between this and the test point.
        /// </summary>
        /// <param name="TestPoint">The test point.</param>
        /// <param name="ptOnThis">The closest point on this to the given point as a returned value.</param>
        public override double Distance(C2DPoint TestPoint, C2DPoint ptOnThis)
        {
            C2DPoint  ptCen       = new C2DPoint(GetCircleCentre());
            C2DCircle Circle      = new C2DCircle(ptCen, Radius);
            C2DPoint  ptOnCircle  = new C2DPoint();
            double    dCircleDist = Circle.Distance(TestPoint, ptOnCircle);

            if (ArcOnRight ^ Line.IsOnRight(ptOnCircle))
            {
                // The closest point on the circle isn't on the curve
                double d1 = TestPoint.Distance(Line.point);
                double d2 = TestPoint.Distance(Line.GetPointTo());

                if (d1 < d2)
                {
                    ptOnThis.Set(Line.point);
                    return(d1);
                }
                else
                {
                    ptOnThis.Set(Line.GetPointTo());
                    return(d2);
                }
            }
            else
            {
                // The closest point on the circle IS on the curve
                ptOnThis.Set(ptOnCircle);
                return(Math.Abs(dCircleDist));
            }
        }
        /// <summary>
        /// Returns the distance from this to the point.
        /// </summary>
        /// <param name="TestPoint">The test pointt.</param>
        /// <param name="ptOnThis">Output. The closest point on this.</param>
        public override double Distance(C2DPoint TestPoint, C2DPoint ptOnThis)
        {
            var vP1ToPoint  = new C2DVector(point, TestPoint);
            var dLength     = GetLength();
            var dProjLength = vP1ToPoint.Dot(vector);

            if (dProjLength < 0)
            {
                ptOnThis.Set(point);

                return(TestPoint.Distance(point));
            }
            else
            {
                dProjLength = dProjLength / dLength;
                if (dProjLength < dLength)
                {
                    // The projection is on the line
                    var dFactorOnLine = dProjLength / dLength;
                    var PtOnLine      = new C2DPoint(point.x + vector.i * dFactorOnLine,
                                                     point.y + vector.j * dFactorOnLine);
                    ptOnThis.Set(PtOnLine);
                    return(TestPoint.Distance(PtOnLine));
                }
                else
                {
                    ptOnThis.Set(GetPointTo());

                    return(TestPoint.Distance(GetPointTo()));
                }
            }
        }
Exemple #3
0
        /// <summary>
        /// Distance between this and another straight line.
        /// </summary>
        /// <param name="TestLine">The test line.</param>
        /// <param name="ptOnThis">The closest point on this to the other as a returned value.</param>
        /// <param name="ptOnOther">The closest point on the other to this as a returned value.</param>
        public double Distance(C2DLine TestLine, C2DPoint ptOnThis, C2DPoint ptOnOther)
        {
            C2DCircle Circle = new C2DCircle(GetCircleCentre(), Radius);

            double dCircDist = Circle.Distance(TestLine, ptOnThis, ptOnOther);
            double dDist     = 0;

            if (TestLine.IsOnRight(ptOnThis) ^ ArcOnRight)
            {
                // The point found isn't on this.
                // This means the 2 closest points cannot be ON both lines, we must have a end point as one.

                ptOnThis.Set(Line.point);
                dDist = TestLine.Distance(ptOnThis, ptOnOther);

                C2DPoint ptThisTemp  = new C2DPoint(Line.GetPointTo());
                C2DPoint ptOtherTemp = new C2DPoint();
                double   d2          = TestLine.Distance(ptThisTemp, ptOtherTemp);
                if (d2 < dDist)
                {
                    dDist = d2;
                    ptOnThis.Set(ptThisTemp);
                    ptOnOther.Set(ptOtherTemp);
                }
                // If the line was outside the circle then stop here as no need to go any further.
                // This is because the closest point on this must be one of the end points.
                if (dCircDist < 0)
                {
                    double d3 = Distance(TestLine.point, ptThisTemp);
                    if (d3 < dDist)
                    {
                        dDist = d3;
                        ptOnThis.Set(ptThisTemp);
                        ptOnOther.Set(Line.point);
                    }
                    double d4 = Distance(TestLine.GetPointTo(), ptThisTemp);
                    if (d4 < dDist)
                    {
                        dDist = d4;
                        ptOnThis.Set(ptThisTemp);
                        ptOnOther.Set(Line.GetPointTo());
                    }
                }
            }
            else
            {
                dDist = Math.Abs(dCircDist);
            }

            //    ptOnThis.Set(ptThis);
            //    ptOnOther.Set(ptOther);

            return(dDist);
        }
Exemple #4
0
        /// <summary>
        /// Distance from the polygon provided.
        /// </summary>
        /// <param name="Poly">Polygon to find the distance to.</param>
        /// <param name="ptOnThis">Closest point on this to recieve the result.</param>
        /// <param name="ptOnOther">Closest point on the other to recieve the result.</param>
        public double Distance(C2DPolyBase Poly, C2DPoint ptOnThis, C2DPoint ptOnOther)
        {
            var ptOnThisResult  = new C2DPoint();
            var ptOnOtherResult = new C2DPoint();


            var dResult = _Rim.Distance(Poly, ptOnThis, ptOnOther);

            if (dResult == 0)
            {
                return(0);
            }

            ptOnThisResult.Set(ptOnThis);
            ptOnOtherResult.Set(ptOnOther);

            var bInside = dResult < 0;

            dResult = Math.Abs(dResult);

            for (var i = 0; i < _Holes.Count; i++)
            {
                var dDist = _Holes[i].Distance(Poly, ptOnThis, ptOnOther);
                if (dDist == 0)
                {
                    return(0);
                }


                if (dDist < 0)
                {
                    bInside = false;
                }
                if (Math.Abs(dDist) < dResult)
                {
                    ptOnThisResult.Set(ptOnThis);
                    ptOnOtherResult.Set(ptOnOther);

                    dResult = Math.Abs(dDist);
                }
            }

            ptOnThis.Set(ptOnThisResult);
            ptOnOther.Set(ptOnOtherResult);

            if (bInside)
            {
                return(dResult);
            }
            else
            {
                return(-dResult);
            }
        }
Exemple #5
0
        /// <summary>
        /// Distance to a another.
        /// </summary>
        /// <param name="Other">The other triangle.</param>
        /// <param name="ptOnThis">Output. The closest point on the triangle.</param>
        /// <param name="ptOnOther">Output. The closest point on the other triangle.</param>
        public double Distance(C2DTriangle Other, C2DPoint ptOnThis, C2DPoint ptOnOther)
        {
            var ptTemp   = new C2DPoint();
            var dMinDist = Distance(Other.P1, ptOnThis);

            ptOnOther.Set(Other.P1);

            var dDist = Distance(Other.P2, ptTemp);

            if (dDist < dMinDist)
            {
                ptOnOther.Set(Other.P2);
                ptOnThis.Set(ptTemp);

                dMinDist = dDist;
            }

            dDist = Distance(Other.P3, ptTemp);
            if (dDist < dMinDist)
            {
                ptOnOther.Set(Other.P3);
                ptOnThis.Set(ptTemp);
                dMinDist = dDist;
            }

            dDist = Other.Distance(P1, ptTemp);
            if (dDist < dMinDist)
            {
                ptOnOther.Set(ptTemp);
                ptOnThis.Set(P1);
                dMinDist = dDist;
            }

            dDist = Other.Distance(P2, ptTemp);
            if (dDist < dMinDist)
            {
                ptOnOther.Set(ptTemp);
                ptOnThis.Set(P2);
                dMinDist = dDist;
            }

            dDist = Other.Distance(P3, ptTemp);
            if (dDist < dMinDist)
            {
                ptOnOther.Set(ptTemp);
                ptOnThis.Set(P3);
                dMinDist = dDist;
            }

            return(dMinDist);
        }
        /// <summary>
        /// True if the point projects onto the line given and returns the point on the line.
        /// Also returns whether the line projects above or below the line if relevant.
        /// </summary>
        /// <param name="line">The line to project this on.</param>
        /// <param name="ptOnLine">The point to recieve the result.</param>
        /// <param name="bAbove">The flag to indicate whether it projects above or below.</param>
        public bool ProjectsOnLine(C2DLine line, C2DPoint ptOnLine,
                                   ref bool bAbove)
        {
            var vecthis = new C2DVector(x - line.point.x, y - line.point.y);
            var dProj   = vecthis.Dot(line.vector);

            if (dProj < 0)
            {
                bAbove = false;
                return(false);
            }

            var dLength = line.vector.GetLength();

            dProj /= dLength;

            if (dProj > dLength)
            {
                bAbove = true;
                return(false);
            }

            var dFactor = dProj / dLength;

            var vProj = new C2DVector(line.vector);

            vProj.Multiply(dFactor);
            ptOnLine.Set(line.point.x + vProj.i, line.point.y + vProj.j);
            return(true);
        }
Exemple #7
0
        /// <summary>
        /// True if the point projects onto the line given and returns the point on the line.
        /// Also returns whether the line projects above or below the line if relevant.
        /// </summary>
        /// <param name="Line">The line to project this on.</param>
        /// <param name="ptOnLine">The point to recieve the result.</param>
        /// <param name="bAbove">The flag to indicate whether it projects above or below.</param>
        public bool ProjectsOnLine(C2DLine Line, C2DPoint ptOnLine,
                                   ref bool bAbove)
        {
            C2DVector vecthis = new C2DVector(x - Line.point.x, y - Line.point.y);
            double    dProj   = vecthis.Dot(Line.vector);

            if (dProj < 0)
            {
                bAbove = false;
                return(false);
            }

            double dLength = Line.vector.GetLength();

            dProj /= dLength;

            if (dProj > dLength)
            {
                bAbove = true;
                return(false);
            }

            double dFactor = dProj / dLength;

            C2DVector vProj = new C2DVector(Line.vector);

            vProj.Multiply(dFactor);
            ptOnLine.Set(Line.point.x + vProj.i, Line.point.y + vProj.j);
            return(true);
        }
Exemple #8
0
        /// <summary>
        /// Distance to a point, returns the closest point on the circle.
        /// </summary>
        /// <param name="TestPoint">Point to calculate the distance to.</param>
        /// <param name="ptOnThis">Closest point on the circle to recieve the result.</param>
        public double Distance(C2DPoint TestPoint, C2DPoint ptOnThis)
        {
            double dDist = _Centre.Distance(TestPoint);

            if (dDist == 0)
            {
                // point is the centre so just arbitrary point to the circle
                C2DVector V1 = new C2DVector(Radius, 0);
                ptOnThis.Set(_Centre.GetPointTo(V1));
            }
            else
            {
                // find the point on the circle.
                C2DLine LineCenToPt = new C2DLine(_Centre, TestPoint);
                LineCenToPt.vector.SetLength(Radius);
                ptOnThis.Set(LineCenToPt.GetPointTo());
            }

            return(dDist - Radius);       // -ve indicates inside.
        }
        /// <summary>
        /// Returns the distance from this to the point with this as a ray.
        /// </summary>
        /// <param name="TestPoint"></param>
        /// <param name="ptOnThis"></param>
        /// <returns></returns>
        public double DistanceAsRay(C2DPoint TestPoint, C2DPoint ptOnThis)
        {
            var vP1ToPoint = new C2DVector(point, TestPoint);

            // The projection is on the line
            var dFactorOnLine = vP1ToPoint.Dot(vector) / (vector.i * vector.i + vector.j * vector.j);

            ptOnThis.Set(point.x + vector.i * dFactorOnLine,
                         point.y + vector.j * dFactorOnLine);
            return(TestPoint.Distance(ptOnThis));
        }
Exemple #10
0
        /// <summary>
        /// True if this crosses the line and returns the intersectin points.
        /// </summary>
        /// <param name="Line">The line.</param>
        /// <param name="IntersectionPts">The point set to recieve the result.</param>
        public bool Crosses(C2DLine Line, List <C2DPoint> IntersectionPts)
        {
            double x1 = Line.point.x;
            double x2 = Line.point.x + Line.vector.i;
            double x3 = _Centre.x;

            double y1 = Line.point.y;
            double y2 = Line.point.y + Line.vector.j;
            double y3 = _Centre.y;

            double r = Radius;

            double a = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);

            double b = 2 * ((x2 - x1) * (x1 - x3) + (y2 - y1) * (y1 - y3));

            double c = x3 * x3 + y3 * y3 + x1 * x1 + y1 * y1 - 2 * (x3 * x1 + y3 * y1) - r * r;

            double u = -b / (2 * a);

            C2DPoint ptClosestToCen = new C2DPoint();

            if (u < 0)
            {
                ptClosestToCen.Set(Line.point);
            }
            else if (u > 1)
            {
                ptClosestToCen.Set(Line.GetPointTo());
            }
            else
            {
                C2DVector V1 = new C2DVector(Line.vector);
                V1.Multiply(u);
                ptClosestToCen = Line.point.GetPointTo(V1);
            }

            double dDist = ptClosestToCen.Distance(_Centre);

            if (dDist > Radius)
            {
                return(false);
            }
            else
            {
                // Calculate the points.
                double d1 = b * b - 4 * a * c;
                Debug.Assert(d1 >= 0);

                if (d1 < 0)
                {
                    return(false);
                }
                else if (d1 == 0)
                {
                    double p1 = -b / (2 * a);
                    IntersectionPts.Add(Line.GetPointOn(p1));
                    return(true);
                }
                else
                {
                    d1 = Math.Sqrt(d1);
                    double p1 = (-b + d1) / (2 * a);
                    double p2 = (-b - d1) / (2 * a);

                    bool bResult = false;
                    if (p2 >= 0 && p2 <= 1)
                    {
                        bResult = true;
                        IntersectionPts.Add(Line.GetPointOn(p2));
                    }

                    if (p1 >= 0 && p1 <= 1)
                    {
                        bResult = true;
                        IntersectionPts.Add(Line.GetPointOn(p1));
                    }

                    return(bResult);
                }
            }
        }
        /// <summary>
        /// True if the point projects onto the line given and returns the point on the line.
        /// Also returns whether the line projects above or below the line if relevant.
        /// </summary>
        /// <param name="Line">The line to project this on.</param>
        /// <param name="ptOnLine">The point to recieve the result.</param>
        /// <param name="bAbove">The flag to indicate whether it projects above or below.</param>
        public bool ProjectsOnLine(C2DLine Line,  C2DPoint ptOnLine , 
		    ref bool bAbove)
        {
            C2DVector vecthis = new C2DVector(x - Line.point.x, y - Line.point.y);
            double dProj = vecthis.Dot(Line.vector);

            if (dProj < 0)
            {
                bAbove = false;
                return false;
            }

            double dLength = Line.vector.GetLength();

            dProj /= dLength;

            if (dProj > dLength)
            {
                bAbove = true;
                return false;
            }

            double dFactor = dProj / dLength;

            C2DVector vProj = new C2DVector(Line.vector);
            vProj.Multiply(dFactor);
            ptOnLine.Set(Line.point.x + vProj.i, Line.point.y + vProj.j);
            return true;
        }
        /// <summary>
        /// Distance from the polygon provided.
        /// </summary>
        /// <param name="Poly">Polygon to find the distance to.</param> 
        /// <param name="ptOnThis">Closest point on this to recieve the result.</param> 
        /// <param name="ptOnOther">Closest point on the other to recieve the result.</param> 
        public double Distance(C2DPolyBase Poly, C2DPoint ptOnThis, C2DPoint ptOnOther) 
        {
	        C2DPoint ptOnThisResult = new C2DPoint();
	        C2DPoint ptOnOtherResult = new C2DPoint();


            double dResult = _Rim.Distance(Poly, ptOnThis, ptOnOther);

	        if (dResult == 0)
		        return 0;

		    ptOnThisResult.Set(ptOnThis); 
		    ptOnOtherResult.Set(ptOnOther); 

	        bool bInside = dResult < 0;
	        dResult = Math.Abs(dResult);

	        for (int i = 0; i < _Holes.Count; i++)
	        {
		        double dDist = _Holes[i].Distance(Poly, ptOnThis, ptOnOther); 
		        if (dDist == 0)
			        return 0;
        		

		        if (dDist < 0)
			        bInside = false;
		        if (Math.Abs(dDist) < dResult)
		        {
				    ptOnThisResult.Set(ptOnThis); 
				    ptOnOtherResult.Set(ptOnOther); 

			        dResult = Math.Abs(dDist);
		        }
	        }

		    ptOnThis.Set(ptOnThisResult); 
		    ptOnOther.Set(ptOnOtherResult); 

	        if (bInside)
		        return dResult;
	        else
		        return - dResult;
        }
        /// <summary>
        /// Distance of the poly from the shape. 
        /// </summary> 
        /// <param name="Other">The other polygon test.</param> 
        /// <param name="ptOnThis">Output. The closest point on this.</param> 
        /// <param name="ptOnOther">The closest point on the other.</param> 
        public double Distance(C2DPolyBase Other, C2DPoint ptOnThis, C2DPoint ptOnOther)
        {
	        if (Lines.Count == 0)
		        return 0;

	        if (Other.Lines.Count == 0)
		        return 0;

	        if (Other.LineRects.Count != Other.Lines.Count)
		        return 0;

	        if (Lines.Count != LineRects.Count)
		        return 0;

	        // First we find the closest line rect to the other's bounding rectangle.
	        int usThisClosestLineGuess = 0;
	        C2DRect OtherBoundingRect = Other.BoundingRect;
	        double dClosestDist = LineRects[0].Distance(OtherBoundingRect);
	        for (int i = 1; i < LineRects.Count; i++)
	        {
		        double dDist = LineRects[i].Distance(OtherBoundingRect);
		        if (dDist < dClosestDist)
		        {
			        dClosestDist = dDist;
			        usThisClosestLineGuess = i;
		        }
	        }
	        // Now cycle through all the other poly's line rects to find the closest to the
	        // guessed at closest line on this.
	        int usOtherClosestLineGuess = 0;
	        dClosestDist = Other.LineRects[0].Distance(LineRects[usThisClosestLineGuess]);
	        for (int j = 1; j < Other.LineRects.Count; j++)
	        {
		        double dDist = Other.LineRects[j].Distance(LineRects[usThisClosestLineGuess]);
		        if (dDist < dClosestDist)
		        {
			        dClosestDist = dDist;
			        usOtherClosestLineGuess = j;
		        }
	        }

	        // Now we have a guess at the 2 closest lines.
	        double dMinDistGuess = Lines[usThisClosestLineGuess].Distance(
							        Other.Lines[usOtherClosestLineGuess],
							        ptOnThis,
							        ptOnOther);
	        // If its 0 then return 0.
	        if (dMinDistGuess == 0)
		        return 0;

	        C2DPoint ptOnThisTemp = new C2DPoint();
	        C2DPoint ptOnOtherTemp = new C2DPoint();

	        // Now go through all of our line rects and only check further if they are closer
	        // to the other's bounding rect than the min guess.
	        for (int i = 0; i < Lines.Count; i++)
	        {
		        if (LineRects[i].Distance( OtherBoundingRect ) <  dMinDistGuess)
		        {
			        for (  int j = 0 ; j < Other.Lines.Count ; j++)
			        {
				        double dDist = Lines[i].Distance(Other.Lines[j],
													        ptOnThisTemp,
													        ptOnOtherTemp);
        				
				        if (dDist < dMinDistGuess)
				        {	
						    ptOnThis.Set(ptOnThisTemp);
					        ptOnOther.Set(ptOnOtherTemp);

					        if (dDist == 0)
						        return 0;

					        dMinDistGuess = dDist; 
				        }
			        }
		        }
	        }

	        // if we are here, there is no intersection but the other could be inside this or vice-versa
	        if ( BoundingRect.Contains(Other.BoundingRect)
		        && Contains(ptOnOtherTemp)  )
	        {
		        dMinDistGuess *= -1.0;
	        }
	        else if ( Other.BoundingRect.Contains(BoundingRect)
		        && Other.Contains( ptOnThisTemp ))
	        {
		        dMinDistGuess *= -1.0;
	        }

	        return dMinDistGuess;
        }
Exemple #14
0
        /// <summary>
        /// The distance between this and another arc.
        /// </summary>
        /// <param name="Other">The test point.</param>
        /// <param name="ptOnThis">The closest point on this to the other as a returned value.</param>
        /// <param name="ptOnOther">The closest point on the other to this as a returned value.</param>     
        public double Distance(C2DArc Other,  C2DPoint ptOnThis,  C2DPoint ptOnOther)
        {
	        List<C2DPoint> IntPts1 = new List<C2DPoint>();
	        List<C2DPoint> IntPts2 = new List<C2DPoint>();

	        C2DPoint ptThisCen = new C2DPoint( GetCircleCentre() );
	        C2DPoint ptOtherCen = new C2DPoint(Other.GetCircleCentre());

	        C2DCircle CircleThis = new C2DCircle( ptThisCen, Radius);
	        C2DCircle CircleOther = new C2DCircle( ptOtherCen, Other.Radius );

	        if (CircleThis.Crosses(  CircleOther ,  IntPts1 ) )
	        {
		        for (int i = 0; i < IntPts1.Count; i++)
		        {
			        if (  (Line.IsOnRight( IntPts1[i] ) == ArcOnRight ) &&
				          (Other.Line.IsOnRight( IntPts1[i] ) == Other.ArcOnRight )     )
			        {
					    ptOnThis.Set(IntPts1[i]);
					    ptOnOther.Set(IntPts1[i]);
				        return 0;
			        }
		        }

		        IntPts1.Clear();
	        }


	        C2DLine LineCenToOther = new C2DLine();
	        LineCenToOther.point = new C2DPoint(ptThisCen);
	        LineCenToOther.vector = new C2DVector(ptThisCen, ptOtherCen);
	        LineCenToOther.GrowFromCentre( Math.Max(Radius, Other.Radius) * 10);

	        double dMinDist = 1.7E308;
	        double dDist = 0;

	        if ( Crosses(LineCenToOther,  IntPts1) && Other.Crosses(LineCenToOther,  IntPts2))
	        {
		        for (int i = 0 ; i < IntPts1.Count; i++)
		        {
			        for (int j = 0 ; j < IntPts2.Count; j++)
			        {
				        dDist = IntPts1[i].Distance(IntPts2[j]);
				        if (dDist < dMinDist)
				        {
						    ptOnThis.Set( IntPts1[i]);
						    ptOnOther.Set( IntPts2[j]);

					        dMinDist = dDist;
				        }
			        }
		        }
	        }

	        C2DPoint ptOnThisTemp = new C2DPoint();
	        dDist = Distance(Other.GetPointFrom(),  ptOnThisTemp);
	        if (dDist < dMinDist)
	        {
			    ptOnThis.Set(ptOnThisTemp);
			    ptOnOther.Set(Other.GetPointFrom());

		        dMinDist = dDist;
	        }

	        dDist = Distance(Other.GetPointTo(),  ptOnThisTemp);
	        if (dDist < dMinDist)
	        {
			    ptOnThis.Set(ptOnThisTemp);
			    ptOnOther.Set(Other.GetPointTo());

		        dMinDist = dDist;
	        }

	        C2DPoint ptOnOtherTemp = new C2DPoint();
	        dDist = Other.Distance(GetPointFrom(),  ptOnOtherTemp);
	        if (dDist < dMinDist)
	        {
			    ptOnThis.Set( GetPointFrom());
			    ptOnOther.Set( ptOnOtherTemp);
		        dMinDist = dDist;
	        }

	        dDist = Other.Distance(GetPointTo(),  ptOnOtherTemp);
	        if (dDist < dMinDist)
	        {
			    ptOnThis.Set( GetPointTo());
			    ptOnOther.Set( ptOnOtherTemp);
		        dMinDist = dDist;
	        }

	        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);
            }
        }
Exemple #16
0
        /// <summary>
        /// Distance between this and another straight line.
        /// </summary>
        /// <param name="TestLine">The test line.</param>
        /// <param name="ptOnThis">The closest point on this to the other as a returned value.</param>
        /// <param name="ptOnOther">The closest point on the other to this as a returned value.</param>   
        public double Distance(C2DLine TestLine,  C2DPoint ptOnThis,  C2DPoint ptOnOther) 
        {
	        C2DCircle Circle = new C2DCircle( GetCircleCentre(), Radius);

            double dCircDist = Circle.Distance(TestLine,  ptOnThis,  ptOnOther);
	        double dDist = 0;

            if (TestLine.IsOnRight(ptOnThis) ^ ArcOnRight)
	        {
		        // The point found isn't on this. 
		        // This means the 2 closest points cannot be ON both lines, we must have a end point as one.

                ptOnThis.Set(Line.point);
                dDist = TestLine.Distance(ptOnThis,  ptOnOther);

                C2DPoint ptThisTemp = new C2DPoint(Line.GetPointTo());
		        C2DPoint ptOtherTemp = new C2DPoint();
                double d2 = TestLine.Distance(ptThisTemp,  ptOtherTemp);
		        if (d2 < dDist)
		        {
			        dDist = d2;
                    ptOnThis.Set(ptThisTemp);
                    ptOnOther.Set(ptOtherTemp);
		        }
		        // If the line was outside the circle then stop here as no need to go any further.
		        // This is because the closest point on this must be one of the end points.
		        if (dCircDist < 0)
		        {
                    double d3 = Distance(TestLine.point,  ptThisTemp);
			        if (d3 < dDist)
			        {
				        dDist = d3;
                        ptOnThis.Set(ptThisTemp);
                        ptOnOther.Set(Line.point);
			        }
                    double d4 = Distance(TestLine.GetPointTo(),  ptThisTemp);
			        if (d4 < dDist)
			        {
				        dDist = d4;
                        ptOnThis.Set(ptThisTemp);
                        ptOnOther.Set(Line.GetPointTo());
			        }	
		        }
	        }
	        else
	        {
		        dDist = Math.Abs(dCircDist);
	        }

		//    ptOnThis.Set(ptThis);
		//    ptOnOther.Set(ptOther);

	        return dDist;


        }
        /// <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>
        /// True if this crosses the line and returns the intersectin points.
        /// </summary>
        /// <param name="Line">The line.</param> 
        /// <param name="IntersectionPts">The point set to recieve the result.</param> 
        public bool Crosses(C2DLine Line,  List<C2DPoint> IntersectionPts)
        {
            double x1 = Line.point.x;
            double x2 = Line.point.x + Line.vector.i;
            double x3 = _Centre.x;

            double y1 = Line.point.y;
            double y2 = Line.point.y + Line.vector.j;
            double y3 = _Centre.y;

            double r = Radius;

            double a = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);

            double b = 2 * ((x2 - x1) * (x1 - x3) + (y2 - y1) * (y1 - y3));

            double c = x3 * x3 + y3 * y3 + x1 * x1 + y1 * y1 - 2 * (x3 * x1 + y3 * y1) - r * r;

            double u = -b / (2 * a);

            C2DPoint ptClosestToCen = new C2DPoint();

            if (u < 0)
            {
                ptClosestToCen.Set( Line.point );
            }
            else if (u > 1)
            {
                ptClosestToCen.Set( Line.GetPointTo());
            }
            else
            {
                C2DVector V1 = new C2DVector(Line.vector);
                V1.Multiply(u);
                ptClosestToCen = Line.point.GetPointTo(V1);
            }

            double dDist = ptClosestToCen.Distance(_Centre);

            if (dDist > Radius)
            {
                return false;
            }
            else
            {
                // Calculate the points.
                double d1 = b * b - 4 * a * c;
                Debug.Assert(d1 >= 0);

                if (d1 < 0)
                    return false;
                else if (d1 == 0)
                {
                    double p1 = -b / (2 * a);
                    IntersectionPts.Add(Line.GetPointOn(p1));
                    return true;
                }
                else
                {
                    d1 = Math.Sqrt(d1);
                    double p1 = (-b + d1) / (2 * a);
                    double p2 = (-b - d1) / (2 * a);

                    bool bResult = false;
                    if (p2 >= 0 && p2 <= 1)
                    {
                        bResult = true;
                        IntersectionPts.Add(Line.GetPointOn(p2));
                    }

                    if (p1 >= 0 && p1 <= 1)
                    {
                        bResult = true;
                        IntersectionPts.Add(Line.GetPointOn(p1));
                    }

                    return bResult;
                }
            }
        }
        /// <summary>
        /// Distance to a circle, returns the closest point on both circles.
        /// </summary>
        /// <param name="Other">Circle to calculate the distance to.</param> 
        /// <param name="ptOnThis">Closest point on this circle to recieve the result.</param> 
        /// <param name="ptOnOther">Closest point on the other circle to recieve the result.</param> 
        public double Distance(C2DCircle Other,  C2DPoint ptOnThis,  C2DPoint ptOnOther)
        {
            double dCenCenDist = _Centre.Distance(Other.Centre);
            double dOtherRadius = Other.Radius;

            //    C2DPoint ptThis;
             //   C2DPoint ptOther;
            double dDist = dCenCenDist - Radius - dOtherRadius;

            if (dDist > 0 )
            {
                // they do not interect and they are outside each other.
                    C2DLine Line = new C2DLine(_Centre, Other.Centre);
                    Line.vector.SetLength( Radius);
                    ptOnThis.Set( Line.GetPointTo() );

                    Line.vector.Reverse();
                    Line.SetPointFrom(Other.Centre);
                    Line.vector.SetLength(Other.Radius);
                    ptOnOther.Set(Line.GetPointTo());
            }
            else
            {
                if ( (dCenCenDist + Radius) < dOtherRadius)
                {
                    // This is inside the other
                    dDist =  dCenCenDist + Radius  - dOtherRadius ; // -ve if inside
                        C2DVector vec = new C2DVector( Other.Centre, Centre);
                        vec.Multiply(   Radius   /dCenCenDist  ); // set the vector to be the length of my radius.
                        ptOnThis.Set( _Centre.GetPointTo( vec));
                        vec.Multiply(   dDist   /Radius  ); // set the vector to be the distance.
                        ptOnOther.Set(ptOnThis.GetPointTo( vec));

                }
                else if ( (dCenCenDist + dOtherRadius) < Radius)
                {
                    // The other is inside this.
                    dDist = dCenCenDist + dOtherRadius -  Radius; // -ve if inside
                        C2DVector vec = new C2DVector( _Centre, Other.Centre);
                        vec.Multiply (   dOtherRadius   /dCenCenDist  ); // set the vector to be the length of my radius.
                        ptOnOther.Set( Other.Centre.GetPointTo( vec));
                        vec.Multiply(   dDist   /  dOtherRadius  ); // set the vector to be the distance.
                        ptOnThis.Set(ptOnOther.GetPointTo( vec));

                }
                else
                {
                    // there is an intersection
                    dDist = 0;
                    List<C2DPoint> Ints = new List<C2DPoint>();
                    if (Crosses(Other,  Ints))
                    {
                        ptOnThis.Set(Ints[0]);
                        ptOnOther.Set(ptOnThis);
                    }
                    else
                    {
                        Debug.Assert(false);
                        return 0;
                    }
                }
            }

              //      if (ptOnThis)
            //        *ptOnThis = ptThis;
              //      if (ptOnOther)
            //        *ptOnOther = ptOther;

            return dDist;
        }
Exemple #20
0
        /// <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));
            }
        }
Exemple #21
0
        /// <summary>
        /// Returns the distance from this to the point. 
        /// </summary>
        /// <param name="TestPoint">The test pointt.</param>
        /// <param name="ptOnThis">Output. The closest point on this.</param>
        public override double Distance(C2DPoint TestPoint,  C2DPoint ptOnThis)
        {
	        C2DVector vP1ToPoint = new C2DVector(point, TestPoint);
	        double dLength = GetLength();
	        double dProjLength = vP1ToPoint.Dot(vector);

	        if (dProjLength < 0)
	        {
			    ptOnThis.Set(point);

		        return TestPoint.Distance(point);
	        }
	        else
	        {
		        dProjLength = dProjLength / dLength;
		        if (dProjLength < dLength)
		        {
			        // The projection is on the line
			        double dFactorOnLine = dProjLength / dLength;
			        C2DPoint PtOnLine = new C2DPoint(point.x + vector.i * dFactorOnLine, 
							          point.y + vector.j * dFactorOnLine);
			        ptOnThis.Set(PtOnLine);
			        return TestPoint.Distance(PtOnLine);
		        }
		        else
		        {
			        ptOnThis .Set(GetPointTo());

			        return TestPoint.Distance( GetPointTo() );
		        }
	        }
        }
Exemple #22
0
        /// <summary>
        /// Distance to a circle, returns the closest point on both circles.
        /// </summary>
        /// <param name="Other">Circle to calculate the distance to.</param>
        /// <param name="ptOnThis">Closest point on this circle to recieve the result.</param>
        /// <param name="ptOnOther">Closest point on the other circle to recieve the result.</param>
        public double Distance(C2DCircle Other, C2DPoint ptOnThis, C2DPoint ptOnOther)
        {
            double dCenCenDist  = _Centre.Distance(Other.Centre);
            double dOtherRadius = Other.Radius;

            //    C2DPoint ptThis;
            //   C2DPoint ptOther;
            double dDist = dCenCenDist - Radius - dOtherRadius;

            if (dDist > 0)
            {
                // they do not interect and they are outside each other.
                C2DLine Line = new C2DLine(_Centre, Other.Centre);
                Line.vector.SetLength(Radius);
                ptOnThis.Set(Line.GetPointTo());

                Line.vector.Reverse();
                Line.SetPointFrom(Other.Centre);
                Line.vector.SetLength(Other.Radius);
                ptOnOther.Set(Line.GetPointTo());
            }
            else
            {
                if ((dCenCenDist + Radius) < dOtherRadius)
                {
                    // This is inside the other
                    dDist = dCenCenDist + Radius - dOtherRadius;            // -ve if inside
                    C2DVector vec = new C2DVector(Other.Centre, Centre);
                    vec.Multiply(Radius / dCenCenDist);                     // set the vector to be the length of my radius.
                    ptOnThis.Set(_Centre.GetPointTo(vec));
                    vec.Multiply(dDist / Radius);                           // set the vector to be the distance.
                    ptOnOther.Set(ptOnThis.GetPointTo(vec));
                }
                else if ((dCenCenDist + dOtherRadius) < Radius)
                {
                    // The other is inside this.
                    dDist = dCenCenDist + dOtherRadius - Radius;              // -ve if inside
                    C2DVector vec = new C2DVector(_Centre, Other.Centre);
                    vec.Multiply(dOtherRadius / dCenCenDist);                 // set the vector to be the length of my radius.
                    ptOnOther.Set(Other.Centre.GetPointTo(vec));
                    vec.Multiply(dDist / dOtherRadius);                       // set the vector to be the distance.
                    ptOnThis.Set(ptOnOther.GetPointTo(vec));
                }
                else
                {
                    // there is an intersection
                    dDist = 0;
                    List <C2DPoint> Ints = new List <C2DPoint>();
                    if (Crosses(Other, Ints))
                    {
                        ptOnThis.Set(Ints[0]);
                        ptOnOther.Set(ptOnThis);
                    }
                    else
                    {
                        Debug.Assert(false);
                        return(0);
                    }
                }
            }

            //      if (ptOnThis)
            //        *ptOnThis = ptThis;
            //      if (ptOnOther)
            //        *ptOnOther = ptOther;

            return(dDist);
        }
        /// <summary>
        /// Distance to a point, returns the closest point on the circle.
        /// </summary>
        /// <param name="TestPoint">Point to calculate the distance to.</param> 
        /// <param name="ptOnThis">Closest point on the circle to recieve the result.</param> 
        public double Distance(C2DPoint TestPoint,  C2DPoint ptOnThis)
        {
            double dDist = _Centre.Distance(TestPoint);

            if (dDist == 0)
            {
                // point is the centre so just arbitrary point to the circle
                C2DVector V1 = new C2DVector( Radius, 0);
                ptOnThis.Set( _Centre.GetPointTo(V1));
            }
            else
            {
                // find the point on the circle.
                C2DLine LineCenToPt = new C2DLine (_Centre, TestPoint);
                LineCenToPt.vector.SetLength(Radius);
                ptOnThis.Set(LineCenToPt.GetPointTo());
            }

            return (dDist - Radius);  // -ve indicates inside.
        }
        /// <summary>
        /// Distance to a another.
        /// </summary>
        /// <param name="Other">The other triangle.</param>
        /// <param name="ptOnThis">Output. The closest point on the triangle.</param>
        /// <param name="ptOnOther">Output. The closest point on the other triangle.</param>
        public double Distance(C2DTriangle Other,  C2DPoint ptOnThis,  C2DPoint ptOnOther)
        {
            C2DPoint ptTemp = new C2DPoint();
            double dMinDist = Distance(Other.P1,  ptOnThis);
            ptOnOther.Set( Other.P1 );

            double dDist = Distance(Other.P2,  ptTemp);
            if (dDist < dMinDist)
            {
                ptOnOther.Set(Other.P2);
                ptOnThis.Set(ptTemp);

                dMinDist = dDist;
            }

            dDist = Distance(Other.P3,  ptTemp);
            if (dDist < dMinDist)
            {
                ptOnOther.Set( Other.P3);
                ptOnThis.Set(ptTemp);
                dMinDist = dDist;
            }

            dDist = Other.Distance(P1,  ptTemp);
            if (dDist < dMinDist)
            {
                ptOnOther.Set(ptTemp);
                ptOnThis.Set(P1);
                dMinDist = dDist;
            }

            dDist = Other.Distance(P2,  ptTemp);
            if (dDist < dMinDist)
            {
                ptOnOther.Set(ptTemp);
                ptOnThis.Set(P2);
                dMinDist = dDist;
            }

            dDist = Other.Distance(P3,  ptTemp);
            if (dDist < dMinDist)
            {
                ptOnOther.Set(ptTemp);
                ptOnThis.Set(P3);
                dMinDist = dDist;
            }

            return dMinDist;
        }
        /// <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);
        }
Exemple #26
0
        /// <summary>
        /// The distance between this and another arc.
        /// </summary>
        /// <param name="Other">The test point.</param>
        /// <param name="ptOnThis">The closest point on this to the other as a returned value.</param>
        /// <param name="ptOnOther">The closest point on the other to this as a returned value.</param>
        public double Distance(C2DArc Other, C2DPoint ptOnThis, C2DPoint ptOnOther)
        {
            List <C2DPoint> IntPts1 = new List <C2DPoint>();
            List <C2DPoint> IntPts2 = new List <C2DPoint>();

            C2DPoint ptThisCen  = new C2DPoint(GetCircleCentre());
            C2DPoint ptOtherCen = new C2DPoint(Other.GetCircleCentre());

            C2DCircle CircleThis  = new C2DCircle(ptThisCen, Radius);
            C2DCircle CircleOther = new C2DCircle(ptOtherCen, Other.Radius);

            if (CircleThis.Crosses(CircleOther, IntPts1))
            {
                for (int i = 0; i < IntPts1.Count; i++)
                {
                    if ((Line.IsOnRight(IntPts1[i]) == ArcOnRight) &&
                        (Other.Line.IsOnRight(IntPts1[i]) == Other.ArcOnRight))
                    {
                        ptOnThis.Set(IntPts1[i]);
                        ptOnOther.Set(IntPts1[i]);
                        return(0);
                    }
                }

                IntPts1.Clear();
            }


            C2DLine LineCenToOther = new C2DLine();

            LineCenToOther.point  = new C2DPoint(ptThisCen);
            LineCenToOther.vector = new C2DVector(ptThisCen, ptOtherCen);
            LineCenToOther.GrowFromCentre(Math.Max(Radius, Other.Radius) * 10);

            double dMinDist = 1.7E308;
            double dDist    = 0;

            if (Crosses(LineCenToOther, IntPts1) && Other.Crosses(LineCenToOther, IntPts2))
            {
                for (int i = 0; i < IntPts1.Count; i++)
                {
                    for (int j = 0; j < IntPts2.Count; j++)
                    {
                        dDist = IntPts1[i].Distance(IntPts2[j]);
                        if (dDist < dMinDist)
                        {
                            ptOnThis.Set(IntPts1[i]);
                            ptOnOther.Set(IntPts2[j]);

                            dMinDist = dDist;
                        }
                    }
                }
            }

            C2DPoint ptOnThisTemp = new C2DPoint();

            dDist = Distance(Other.GetPointFrom(), ptOnThisTemp);
            if (dDist < dMinDist)
            {
                ptOnThis.Set(ptOnThisTemp);
                ptOnOther.Set(Other.GetPointFrom());

                dMinDist = dDist;
            }

            dDist = Distance(Other.GetPointTo(), ptOnThisTemp);
            if (dDist < dMinDist)
            {
                ptOnThis.Set(ptOnThisTemp);
                ptOnOther.Set(Other.GetPointTo());

                dMinDist = dDist;
            }

            C2DPoint ptOnOtherTemp = new C2DPoint();

            dDist = Other.Distance(GetPointFrom(), ptOnOtherTemp);
            if (dDist < dMinDist)
            {
                ptOnThis.Set(GetPointFrom());
                ptOnOther.Set(ptOnOtherTemp);
                dMinDist = dDist;
            }

            dDist = Other.Distance(GetPointTo(), ptOnOtherTemp);
            if (dDist < dMinDist)
            {
                ptOnThis.Set(GetPointTo());
                ptOnOther.Set(ptOnOtherTemp);
                dMinDist = dDist;
            }

            return(dMinDist);
        }
Exemple #27
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)
        {
            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));
                    }
                }
            }
        }
Exemple #28
0
        /// <summary>
        /// Returns the distance from this to the point with this as a ray.
        /// </summary>
        /// <param name="TestPoint"></param>
        /// <param name="ptOnThis"></param>
        /// <returns></returns>
        public double DistanceAsRay(C2DPoint TestPoint,  C2DPoint ptOnThis)
        {
	        C2DVector vP1ToPoint = new C2DVector(point, TestPoint);

	        // The projection is on the line
	        double dFactorOnLine = vP1ToPoint.Dot(vector) / (vector.i * vector.i + vector.j * vector.j);

            ptOnThis.Set(point.x + vector.i * dFactorOnLine,
                              point.y + vector.j * dFactorOnLine);
            return TestPoint.Distance(ptOnThis);
        }
        /// <summary>
        /// Distance of the poly from the shape.
        /// </summary>
        /// <param name="Other">The other polygon test.</param>
        /// <param name="ptOnThis">Output. The closest point on this.</param>
        /// <param name="ptOnOther">The closest point on the other.</param>
        public double Distance(C2DPolyBase Other, C2DPoint ptOnThis, C2DPoint ptOnOther)
        {
            if (Lines.Count == 0)
            {
                return(0);
            }

            if (Other.Lines.Count == 0)
            {
                return(0);
            }

            if (Other.LineRects.Count != Other.Lines.Count)
            {
                return(0);
            }

            if (Lines.Count != LineRects.Count)
            {
                return(0);
            }

            // First we find the closest line rect to the other's bounding rectangle.
            var    usThisClosestLineGuess = 0;
            var    OtherBoundingRect      = Other.BoundingRect;
            double dClosestDist           = LineRects[0].Distance(OtherBoundingRect);

            for (var i = 1; i < LineRects.Count; i++)
            {
                double dDist = LineRects[i].Distance(OtherBoundingRect);
                if (dDist < dClosestDist)
                {
                    dClosestDist           = dDist;
                    usThisClosestLineGuess = i;
                }
            }
            // Now cycle through all the other poly's line rects to find the closest to the
            // guessed at closest line on this.
            var usOtherClosestLineGuess = 0;

            dClosestDist = Other.LineRects[0].Distance(LineRects[usThisClosestLineGuess]);
            for (var j = 1; j < Other.LineRects.Count; j++)
            {
                double dDist = Other.LineRects[j].Distance(LineRects[usThisClosestLineGuess]);
                if (dDist < dClosestDist)
                {
                    dClosestDist            = dDist;
                    usOtherClosestLineGuess = j;
                }
            }

            // Now we have a guess at the 2 closest lines.
            double dMinDistGuess = Lines[usThisClosestLineGuess].Distance(
                Other.Lines[usOtherClosestLineGuess],
                ptOnThis,
                ptOnOther);

            // If its 0 then return 0.
            if (dMinDistGuess == 0)
            {
                return(0);
            }

            var ptOnThisTemp  = new C2DPoint();
            var ptOnOtherTemp = new C2DPoint();

            // Now go through all of our line rects and only check further if they are closer
            // to the other's bounding rect than the min guess.
            for (var i = 0; i < Lines.Count; i++)
            {
                if (LineRects[i].Distance(OtherBoundingRect) < dMinDistGuess)
                {
                    for (var j = 0; j < Other.Lines.Count; j++)
                    {
                        double dDist = Lines[i].Distance(Other.Lines[j],
                                                         ptOnThisTemp,
                                                         ptOnOtherTemp);

                        if (dDist < dMinDistGuess)
                        {
                            ptOnThis.Set(ptOnThisTemp);
                            ptOnOther.Set(ptOnOtherTemp);

                            if (dDist == 0)
                            {
                                return(0);
                            }

                            dMinDistGuess = dDist;
                        }
                    }
                }
            }

            // if we are here, there is no intersection but the other could be inside this or vice-versa
            if (BoundingRect.Contains(Other.BoundingRect) &&
                Contains(ptOnOtherTemp))
            {
                dMinDistGuess *= -1.0;
            }
            else if (Other.BoundingRect.Contains(BoundingRect) &&
                     Other.Contains(ptOnThisTemp))
            {
                dMinDistGuess *= -1.0;
            }

            return(dMinDistGuess);
        }
Exemple #30
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;

        }
Exemple #31
0
        /// <summary>
        /// Distance between this and the test point.
        /// </summary>
        /// <param name="TestPoint">The test point.</param>
        /// <param name="ptOnThis">The closest point on this to the given point as a returned value.</param>
        public override double Distance(C2DPoint TestPoint,  C2DPoint ptOnThis) 
        {
	        C2DPoint ptCen = new C2DPoint( GetCircleCentre());
	        C2DCircle Circle = new C2DCircle(ptCen, Radius);
	        C2DPoint ptOnCircle = new C2DPoint();
	        double dCircleDist = Circle.Distance(TestPoint,  ptOnCircle);

	        if (ArcOnRight ^ Line.IsOnRight(ptOnCircle))
	        {
		        // The closest point on the circle isn't on the curve
		        double d1 = TestPoint.Distance(Line.point);
		        double d2 = TestPoint.Distance(Line.GetPointTo());
        		
		        if (d1 < d2)
		        {
				    ptOnThis.Set(Line.point);
			        return d1;
		        }
		        else
		        {
			        ptOnThis.Set(Line.GetPointTo());
			        return d2;
		        }
	        }
	        else
	        {
		        // The closest point on the circle IS on the curve
		        ptOnThis.Set(ptOnCircle);
		        return Math.Abs(dCircleDist);
	        }


        }