Example #1
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);
			        }
		        }
	        }
        }
Example #2
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));
                    }
                }
            }
        }