Exemplo n.º 1
0
        /// <summary>
        /// Returns the lines that go to make this up based on the set of points
        /// provided which are assumed to be on the line.
        /// </summary>
        /// <param name="PtsOnLine">The points defining how the line is to be split.</param>
        /// <param name="LineSet">The line set to recieve the result.</param>
        public override void GetSubLines(List <C2DPoint> PtsOnLine, List <C2DLineBase> LineSet)
        {
            // if there are no points on the line to split on then add a copy of this and return.
            int usPointsCount = PtsOnLine.Count;

            if (usPointsCount == 0)
            {
                LineSet.Add(new C2DArc(this));
                return;
            }
            else
            {
                // Make a copy of the points for sorting.
                C2DPointSet TempPts = new C2DPointSet();
                TempPts.MakeCopy(PtsOnLine);

                if (usPointsCount > 1)         // They need sorting
                {
                    // Make a line from the mid point of my line to the start
                    C2DLine CenToStart = new C2DLine(Line.GetMidPoint(), Line.point);
                    // Now sort the points according to the order in which they will be encountered
                    if (ArcOnRight)
                    {
                        TempPts.SortByAngleToLeft(CenToStart);
                    }
                    else
                    {
                        TempPts.SortByAngleToRight(CenToStart);
                    }
                }

                C2DPoint ptCentre = new C2DPoint(GetCircleCentre());

                // Add the line from the start of this to the first.
                C2DLine NewLine = new C2DLine(Line.point, TempPts[0]);
                LineSet.Add(new C2DArc(NewLine, Radius,
                                       NewLine.IsOnRight(ptCentre), ArcOnRight));

                // Add all the sub lines.
                for (int i = 1; i < usPointsCount; i++)
                {
                    NewLine.Set(TempPts[i - 1], TempPts[i]);
                    LineSet.Add(new C2DArc(NewLine, Radius,
                                           NewLine.IsOnRight(ptCentre), ArcOnRight));
                }
                // Add the line from the last point on this to the end of this.
                NewLine.Set(TempPts[TempPts.Count - 1], Line.GetPointTo());
                LineSet.Add(new C2DArc(NewLine, Radius,
                                       NewLine.IsOnRight(ptCentre), ArcOnRight));
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Static version of Fermat point function.
        /// </summary>
        public static C2DPoint GetFermatPoint(C2DPoint pt1, C2DPoint pt2, C2DPoint pt3)
        {
            var Line12 = new C2DLine(pt1, pt2);
            var Line23 = new C2DLine(pt2, pt3);
            var Line31 = new C2DLine(pt3, pt1);

            var dAng2 = Constants.conPI - Line12.vector.AngleBetween(Line23.vector);

            if (dAng2 >= Constants.conTWOTHIRDPI) // greater than 120 degrees
            {
                return(new C2DPoint(pt2));
            }
            else if (dAng2 < Constants.conTHIRDPI)  // if less than 60 then 1 of the other 2 could be greater than 120
            {
                var dAng3 = Constants.conPI - Line23.vector.AngleBetween(Line31.vector);
                if (dAng3 >= Constants.conTWOTHIRDPI)     // greater than 120 degrees
                {
                    return(new C2DPoint(pt3));
                }
                else if ((Constants.conPI - dAng2 - dAng3) >= Constants.conTWOTHIRDPI) // if least angle is greater than 120
                {
                    return(new C2DPoint(pt1));
                }
            }

            var bClockwise = Line12.IsOnRight(pt3);

            if (bClockwise)
            {
                Line12.vector.TurnLeft(Constants.conTHIRDPI);                   // 60 degrees
                Line23.vector.TurnLeft(Constants.conTHIRDPI);                   // 60 degrees
            }
            else
            {
                Line12.vector.TurnRight(Constants.conTHIRDPI);          // 60 degrees
                Line23.vector.TurnRight(Constants.conTHIRDPI);          // 60 degrees
            }

            Line12.SetPointFrom(pt3);
            Line23.SetPointFrom(pt1);

            var  IntPt = new List <C2DPoint>();
            bool B1 = true, B2 = true;

            if (Line12.Crosses(Line23, IntPt, ref B1, ref B2, false))
            {
                return(IntPt[0]);
            }
            else
            {
                Debug.Assert(false);
            }

            return(new C2DPoint(0, 0));
        }
Exemplo n.º 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);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Static version of Fermat point function.
        /// </summary>
        public static C2DPoint GetFermatPoint(C2DPoint pt1, C2DPoint pt2, C2DPoint pt3)
        {
            C2DLine Line12 = new C2DLine(pt1, pt2);
            C2DLine Line23 = new C2DLine(pt2, pt3);
            C2DLine Line31 = new C2DLine(pt3, pt1);

            double dAng2 = Constants.conPI - Line12.vector.AngleBetween(Line23.vector);
            if (dAng2 >= Constants.conTWOTHIRDPI) // greater than 120 degrees
            {
	            return new C2DPoint(pt2);
            }
            else if (dAng2 < Constants.conTHIRDPI)  // if less than 60 then 1 of the other 2 could be greater than 120
            {
                double dAng3 = Constants.conPI - Line23.vector.AngleBetween(Line31.vector);
	            if (dAng3 >= Constants.conTWOTHIRDPI) // greater than 120 degrees
	            {
		            return new C2DPoint(pt3);
	            }
                else if ((Constants.conPI - dAng2 - dAng3) >= Constants.conTWOTHIRDPI) // if least angle is greater than 120
	            {
		            return new C2DPoint(pt1);
	            }
            }

            bool bClockwise = Line12.IsOnRight(pt3);

            if (bClockwise)
            {
	            Line12.vector.TurnLeft(Constants.conTHIRDPI);		// 60 degrees
	            Line23.vector.TurnLeft(Constants.conTHIRDPI);		// 60 degrees
            }
            else
            {
	            Line12.vector.TurnRight(Constants.conTHIRDPI);	// 60 degrees
	            Line23.vector.TurnRight(Constants.conTHIRDPI);	// 60 degrees
            }
        	
            Line12.SetPointFrom(pt3);
            Line23.SetPointFrom(pt1);	
        	
            List<C2DPoint> IntPt = new List<C2DPoint>();
            bool B1 = true, B2 = true;
            if (Line12.Crosses(Line23,  IntPt, ref B1, ref B2, false))
            {
	            return IntPt[0];
            }
            else
            {
	            Debug.Assert(false);
            }	

            return 	new C2DPoint(0, 0);
        }
Exemplo n.º 5
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);
			        }
		        }
	        }
        }
Exemplo n.º 6
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));
                    }
                }
            }
        }
Exemplo n.º 7
0
        /// <summary>
	    /// Returns the lines that go to make this up based on the set of points 
	    /// provided which are assumed to be on the line.
        /// </summary>
        /// <param name="PtsOnLine">The points defining how the line is to be split.</param> 
        /// <param name="LineSet">The line set to recieve the result.</param> 
        public override void GetSubLines(List<C2DPoint> PtsOnLine,  List<C2DLineBase> LineSet) 
        {
            
	        // if there are no points on the line to split on then add a copy of this and return.
	        int usPointsCount = PtsOnLine.Count;
	        if (usPointsCount == 0 )
	        {
		        LineSet.Add(new C2DArc(this));
		        return;
	        }
	        else
	        {
		        // Make a copy of the points for sorting.
		        C2DPointSet TempPts = new C2DPointSet();
		        TempPts.MakeCopy(PtsOnLine);

		        if (usPointsCount > 1) // They need sorting
		        {
			        // Make a line from the mid point of my line to the start
			        C2DLine CenToStart = new C2DLine( Line.GetMidPoint(), Line.point );
			        // Now sort the points according to the order in which they will be encountered
			        if (ArcOnRight)
				        TempPts.SortByAngleToLeft( CenToStart );
			        else
				        TempPts.SortByAngleToRight( CenToStart );
		        }

		        C2DPoint ptCentre = new C2DPoint(GetCircleCentre());

		        // Add the line from the start of this to the first.
		        C2DLine NewLine = new C2DLine( Line.point, TempPts[0] );
                LineSet.Add(new C2DArc(NewLine, Radius,
                                          NewLine.IsOnRight(ptCentre), ArcOnRight));

		        // Add all the sub lines.
		        for (int i = 1; i < usPointsCount; i++)
		        {
                    NewLine.Set(TempPts[i - 1], TempPts[i]);
                    LineSet.Add(new C2DArc(NewLine, Radius,
                                            NewLine.IsOnRight(ptCentre), ArcOnRight));
		        }
		        // Add the line from the last point on this to the end of this.
                NewLine.Set(TempPts[TempPts.Count - 1], Line.GetPointTo());
                LineSet.Add(new C2DArc(NewLine, Radius,
                                           NewLine.IsOnRight(ptCentre), ArcOnRight));
	        }
            
        }
Exemplo n.º 8
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;


        }