Пример #1
0
        /// <summary>
        /// Gets the point on the curve determined by the factor as a new object.
        /// </summary>
        public C2DPoint GetPointOn(double dFactorFromStart)
        {
            Debug.Assert(IsValid(), "Invalid arc defined, function failure.");
            // make 2 lines from the centre to the ends of the line
            C2DPoint ptCentre = new C2DPoint(GetCircleCentre());

            C2DLine CenToStart = new C2DLine(ptCentre, Line.point);

            C2DLine CenToEnd = new C2DLine(ptCentre, Line.GetPointTo());

            if (!ArcOnRight)            // clockwise
            {
                // Find the angle from one to the other and muliply it by the factor
                // before turning the line's vector by the result.
                double dAngleToRight = CenToStart.vector.AngleToRight(CenToEnd.vector);
                double dNewAngle     = dAngleToRight * dFactorFromStart;
                CenToStart.vector.TurnRight(dNewAngle);
                return(CenToStart.GetPointTo());
            }
            else        // anticlockwise
            {
                double dAngleToLeft = CenToStart.vector.AngleToLeft(CenToEnd.vector);
                double dNewAngle    = dAngleToLeft * dFactorFromStart;
                CenToStart.vector.TurnLeft(dNewAngle);
                return(CenToStart.GetPointTo());
            }
        }
Пример #2
0
        /// <summary>
        /// True if the ray provided (infinite line starting from the first point) crosses this.
        /// </summary>
        /// <param name="Ray">The other line to test.</param>
        /// <param name="IntersectionPts">Output. The intersection points.</param>
        public bool CrossesRay(C2DLine Ray, List <C2DPoint> IntersectionPts)
        {
            var p1 = point;
            var p2 = GetPointTo();

            var p3 = Ray.point;
            var p4 = Ray.GetPointTo();

            var Ua = (p4.x - p3.x) * (p1.y - p3.y) - (p4.y - p3.y) * (p1.x - p3.x);
            var Ub = (p2.x - p1.x) * (p1.y - p3.y) - (p2.y - p1.y) * (p1.x - p3.x);

            var dDenominator = (p4.y - p3.y) * (p2.x - p1.x) - (p4.x - p3.x) * (p2.y - p1.y);

            if (dDenominator == 0)
            {
                return(false);
            }

            Ua = Ua / dDenominator;
            Ub = Ub / dDenominator;

            var bResult = (Ua >= 0 && Ua <= 1) && (Ub >= 0);

            if (bResult)
            {
                IntersectionPts.Add(new C2DPoint(p1.x + Ua * (p2.x - p1.x), p1.y + Ua * (p2.y - p1.y)));
            }

            return(bResult);
        }
Пример #3
0
        /// <summary>
        /// True if this line would cross the other if this were infinite.
        /// </summary>
        /// <param name="Other">The other line to test.</param>
        public bool WouldCross(C2DLine Other)
        {
            var bPointOnRight   = IsOnRight(Other.point);
            var bPointToOnRight = IsOnRight(Other.GetPointTo());

            return(bPointOnRight ^ bPointToOnRight);
        }
Пример #4
0
        /// <summary>
        /// Static version of InCentre function.
        /// </summary>
        public static C2DPoint GetInCentre(C2DPoint pt1, C2DPoint pt2, C2DPoint pt3)
        {
            // Set up a line to bisect the lines from 1 to 2 and 1 to 3
            var Line1 = new C2DLine(pt1, pt2);
            var Line2 = new C2DLine(pt1, pt3);

            Line1.SetLength(Line2.GetLength());
            var Line12Bisect = new C2DLine(pt1, pt3.GetMidPoint(Line1.GetPointTo()));

            // Set up a line to bisect the lines from 2 to 1 and 2 to 3
            var Line3 = new C2DLine(pt2, pt1);
            var Line4 = new C2DLine(pt2, pt3);

            Line3.SetLength(Line4.GetLength());
            var Line34Bisect = new C2DLine(pt2, pt3.GetMidPoint(Line3.GetPointTo()));

            // Now intersect the 2 lines and find the point.
            var Int = new List <C2DPoint>();

            // Add the intersection even if there isn't one (i.e. infinite lines)
            bool B1 = true, B2 = true;

            Line12Bisect.Crosses(Line34Bisect, Int, ref B1, ref B2, true);

            Debug.Assert(Int.Count == 1);

            return(Int[0]);
        }
Пример #5
0
        /// <summary>
        /// Returns the centroid.
        /// </summary>
        public C2DPoint GetCentroid()
        {
            // Find the area first. Do it explicitly as we may need bits of the calc later.
            var dSegAng = Arc.GetSegmentAngle();
            var bBig    = Arc.ArcOnRight == Arc.CentreOnRight;

            var dRadius       = Arc.Radius;
            var dRadiusSquare = dRadius * dRadius;
            var dCircleArea   = dRadiusSquare * Constants.conPI;
            var dArea         = dRadiusSquare * ((dSegAng - Math.Sin(dSegAng)) / 2);

            // Find the maximum length of the small segment along the direction of the line.
            var dLength = Arc.Line.GetLength();
            // Now find the average height of the segment over that line
            var dHeight = dArea / dLength;

            // Find the centre point on the line and the centre of the circle
            var ptLineCen   = new C2DPoint(Arc.Line.GetMidPoint());
            var ptCircleCen = new C2DPoint(Arc.GetCircleCentre());

            // Set up a line from the mid point on the line to the circle centre
            // then set the length of it to the average height divided by 2. The end
            // point of the line is then the centroid. If we are using the small bit,
            // The line needs to be reversed.
            var Line = new C2DLine(ptLineCen, ptCircleCen);

            Line.vector.Reverse();

            Line.vector.SetLength(dHeight / 2);

            if (bBig)
            {
                var ptSmallCen = new C2DPoint(Line.GetPointTo());
                // Return the weighted average of the 2 centroids.

                ptCircleCen.Multiply(dCircleArea);
                ptSmallCen.Multiply(dArea);
                var pRes = ptCircleCen - ptSmallCen;
                pRes.Multiply(1.0 / (dCircleArea - dArea));
                return(pRes);
                //     return ( new C2DPoint(ptCircleCen * dCircleArea - ptSmallCen * dArea) ) / ( dCircleArea - dArea);
            }
            else
            {
                return(Line.GetPointTo());
            }
        }
Пример #6
0
 /// <summary>
 /// Draws a line.
 /// </summary>
 public void Draw(C2DLine Line, Graphics graphics, Pen pen)
 {
     C2DPoint pt1 = Line.GetPointFrom();
     C2DPoint pt2 = Line.GetPointTo();
     this.ScaleAndOffSet(pt1);
     this.ScaleAndOffSet(pt2);
     graphics.DrawLine(pen, (int)pt1.x, (int)pt1.y, (int)pt2.x, (int)pt2.y);
 }
Пример #7
0
        /// <summary>
        /// Draws a line.
        /// </summary>
        public void Draw(C2DLine Line, Graphics graphics, Pen pen)
        {
            C2DPoint pt1 = Line.GetPointFrom();
            C2DPoint pt2 = Line.GetPointTo();

            this.ScaleAndOffSet(pt1);
            this.ScaleAndOffSet(pt2);
            graphics.DrawLine(pen, (int)pt1.x, (int)pt1.y, (int)pt2.x, (int)pt2.y);
        }
Пример #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);
        }
Пример #9
0
        /// <summary>
        /// Function to join the 2 lines at the point where they do / would intersect. If they do then
        /// the lines are clipped to remove the smallest part of the line. Returns false if they
        /// cannot be joined.
        /// </summary>
        /// <param name="Other">The other line</param>
        public bool Join(C2DLine Other)
        {
            var p1 = point;
            var p2 = GetPointTo();

            var p3 = Other.point;
            var p4 = Other.GetPointTo();

            var Ua = (p4.x - p3.x) * (p1.y - p3.y) - (p4.y - p3.y) * (p1.x - p3.x);
            var Ub = (p2.x - p1.x) * (p1.y - p3.y) - (p2.y - p1.y) * (p1.x - p3.x);

            var dDenominator = (p4.y - p3.y) * (p2.x - p1.x) - (p4.x - p3.x) * (p2.y - p1.y);

            if (dDenominator == 0)
            {
                return(false);
            }

            Ua = Ua / dDenominator;
            Ub = Ub / dDenominator;

            var IntPt = new C2DPoint(p1.x + Ua * (p2.x - p1.x), p1.y + Ua * (p2.y - p1.y));

            if (Ua >= 0.5)
            {
                this.SetPointTo(IntPt);
            }
            else
            {
                this.SetPointFrom(IntPt);
            }

            if (Ub >= 0.5)
            {
                Other.SetPointTo(IntPt);
            }
            else
            {
                Other.SetPointFrom(IntPt);
            }

            return(true);
        }
Пример #10
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.
        }
Пример #11
0
        /// <summary>
        /// Gets the point half way along the curve as a new object.
        /// </summary>
        public C2DPoint GetMidPoint()
        {
            Debug.Assert(IsValid(), "Invalid arc defined, cannot calculate midpoint");
            // Make a line from the circle centre to the middle of the line
            C2DPoint ptCentre = new C2DPoint(GetCircleCentre());

            C2DPoint ptLineCentre = new C2DPoint(Line.GetMidPoint());

            C2DLine CenToMid = new C2DLine(ptCentre, ptLineCentre);

            if (CenToMid.vector.i == 0 && CenToMid.vector.j == 0)
            {
                // The centre of the line is the same as the centre of the circle
                // i.e. this arc is 180 degrees or half a circle.
                CenToMid.Set(Line);
                CenToMid.SetPointFrom(ptLineCentre);
                if (ArcOnRight)
                {
                    CenToMid.vector.TurnRight();
                }
                else
                {
                    CenToMid.vector.TurnLeft();
                }
            }
            else
            {
                // extend it to the edge of the arc
                CenToMid.SetLength(Radius);
                // if the arc on the opposite side to the centre then reverse the line.
                if (ArcOnRight == CentreOnRight)
                {
                    CenToMid.vector.Reverse();
                }
            }

            return(CenToMid.GetPointTo());
        }
Пример #12
0
        /// <summary>
        /// True if this line crosses the other. Returns the point is a collection is provided.
        /// Returns whether it would cross on this or on the other. Can opt to get the point
        /// where the cross would occur (if not parallel) even if they don't cross.
        /// </summary>
        /// <param name="Other">The other line</param>
        /// <param name="IntersectionPts">To recieve the result</param>
        /// <param name="bOnThis">Output. True is the intersection would be on this line.</param>
        /// <param name="bOnOther">Output. True is the intersection would be on the other line.</param>
        /// <param name="bAddPtIfFalse">Input. True to add the intersection point even if there is no intersection.</param>
        /// <returns></returns>
        public bool Crosses(C2DLine Other, List <C2DPoint> IntersectionPts,
                            ref bool bOnThis, ref bool bOnOther, bool bAddPtIfFalse)
        {
            bOnThis  = false;
            bOnOther = false;

            var p1 = point;
            var p2 = GetPointTo();

            var p3 = Other.point;
            var p4 = Other.GetPointTo();

            var Ua = (p4.x - p3.x) * (p1.y - p3.y) - (p4.y - p3.y) * (p1.x - p3.x);
            var Ub = (p2.x - p1.x) * (p1.y - p3.y) - (p2.y - p1.y) * (p1.x - p3.x);

            var dDenominator = (p4.y - p3.y) * (p2.x - p1.x) - (p4.x - p3.x) * (p2.y - p1.y);

            if (dDenominator == 0)
            {
                return(false);
            }

            Ua = Ua / dDenominator;
            Ub = Ub / dDenominator;

            bOnThis  = (Ua >= 0 && Ua < 1);             // For ints we need the line to be the point set [a,b);
            bOnOther = (Ub >= 0 && Ub < 1);             // For ints we need the line to be the point set [a,b);
            var bResult = bOnThis && bOnOther;

            if (bAddPtIfFalse || bResult)
            {
                IntersectionPts.Add(new C2DPoint(p1.x + Ua * (p2.x - p1.x), p1.y + Ua * (p2.y - p1.y)));
            }

            return(bResult);
        }
Пример #13
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);
                }
            }
        }
Пример #14
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.
        }
Пример #15
0
        /// <summary>
        /// Own cross creation. Line-line intersection Wikipedia
        /// </summary>
        /// <param name="Other"></param>
        /// <returns></returns>
        public bool Crosses(C2DLine Other)
        {
            C2DPoint p1 = point;
            C2DPoint p2 = GetPointTo();

            C2DPoint p3 = Other.point;
            C2DPoint p4 = Other.GetPointTo();

            double Ua = (p1.x * p2.y - p1.y * p2.x) * (p3.x - p4.x) - (p1.x - p2.x) * (p3.x * p4.y - p3.y * p4.x);
            double Ub = (p1.x * p2.y - p1.y * p2.x) * (p3.y - p4.y) - (p1.y - p2.y) * (p3.x * p4.y - p3.y * p4.x);

            double dDenominator = (p1.x - p2.x) * (p3.y - p4.y) - (p1.y - p2.y) * (p3.x - p4.x);

            if (dDenominator == 0)
                return false;

            Ua = Ua / dDenominator;
            Ub = Ub / dDenominator;

            bool result = (Ua >= 0 && Ua < 1) && (Ub >= 0 && Ub < 1);

            return result;
        }
Пример #16
0
        /// <summary>
        /// Static version of InCentre function.
        /// </summary>
        public static C2DPoint GetInCentre(C2DPoint pt1, C2DPoint pt2, C2DPoint pt3)
        {
	        // Set up a line to bisect the lines from 1 to 2 and 1 to 3
	        C2DLine Line1 = new C2DLine(pt1, pt2);
	        C2DLine Line2 = new C2DLine(pt1, pt3);
	        Line1.SetLength( Line2.GetLength() );
	        C2DLine Line12Bisect = new C2DLine(  pt1, pt3.GetMidPoint( Line1.GetPointTo()));

	        // Set up a line to bisect the lines from 2 to 1 and 2 to 3
	        C2DLine Line3 = new C2DLine(pt2, pt1);
	        C2DLine Line4 = new C2DLine(pt2, pt3);
	        Line3.SetLength( Line4.GetLength() );
            C2DLine Line34Bisect = new C2DLine(pt2, pt3.GetMidPoint(Line3.GetPointTo()));

	        // Now intersect the 2 lines and find the point.
	        List<C2DPoint> Int = new List<C2DPoint>();

	        // Add the intersection even if there isn't one (i.e. infinite lines)
            bool B1 = true, B2 = true;
	        Line12Bisect.Crosses(Line34Bisect,  Int, ref B1, ref B2, true);

	        Debug.Assert (Int.Count == 1);

	        return Int[0];
        }
Пример #17
0
        /// <summary>
        /// Gets the point on the curve determined by the factor as a new object.
        /// </summary>
        public C2DPoint GetPointOn(double dFactorFromStart) 
        {
	        Debug.Assert(IsValid(), "Invalid arc defined, function failure." );
	        // make 2 lines from the centre to the ends of the line
	        C2DPoint ptCentre = new C2DPoint(GetCircleCentre());

	        C2DLine CenToStart = new C2DLine(ptCentre, Line.point);

	        C2DLine CenToEnd = new C2DLine(ptCentre, Line.GetPointTo());

	        if ( !ArcOnRight)	// clockwise
	        {
		        // Find the angle from one to the other and muliply it by the factor
		        // before turning the line's vector by the result.
		        double dAngleToRight = CenToStart.vector.AngleToRight( CenToEnd.vector );
		        double dNewAngle = dAngleToRight* dFactorFromStart;
		        CenToStart.vector.TurnRight( dNewAngle );
		        return CenToStart.GetPointTo();
	        }
	        else	// anticlockwise
	        {
		        double dAngleToLeft = CenToStart.vector.AngleToLeft( CenToEnd.vector );
		        double dNewAngle = dAngleToLeft* dFactorFromStart;
		        CenToStart.vector.TurnLeft( dNewAngle );
		        return CenToStart.GetPointTo();
	        }
        }
Пример #18
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);
        }
Пример #19
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;
        }
Пример #20
0
        /// <summary>
        /// True if this line crosses the other. Returns the point is a collection is provided.
        /// Returns whether it would cross on this or on the other. Can opt to get the point 
        /// where the cross would occur (if not parallel) even if they don't cross.
        /// </summary>
        /// <param name="Other">The other line</param>
        /// <param name="IntersectionPts">To recieve the result</param>
        /// <param name="bOnThis">Output. True is the intersection would be on this line.</param>
        /// <param name="bOnOther">Output. True is the intersection would be on the other line.</param>
        /// <param name="bAddPtIfFalse">Input. True to add the intersection point even if there is no intersection.</param>
        /// <returns></returns>
        public bool Crosses(C2DLine Other,  List<C2DPoint> IntersectionPts , 
		    ref bool bOnThis, ref bool bOnOther, bool bAddPtIfFalse)
        {
	        bOnThis = false;
	        bOnOther = false;

	        C2DPoint p1 = point;
	        C2DPoint p2 = GetPointTo();

	        C2DPoint p3 = Other.point;
	        C2DPoint p4 = Other.GetPointTo();

	        double Ua = (p4.x - p3.x)*(p1.y - p3.y) - (p4.y - p3.y) * (p1.x - p3.x);
	        double Ub = (p2.x - p1.x)*(p1.y - p3.y) - (p2.y - p1.y) * (p1.x - p3.x);

	        double dDenominator = (p4.y - p3.y)*(p2.x - p1.x) - (p4.x - p3.x) * (p2.y - p1.y);

	        if (dDenominator == 0) 
                return false;

	        Ua = Ua / dDenominator;
	        Ub = Ub / dDenominator;

	        bOnThis = (Ua >= 0 && Ua < 1);		// For ints we need the line to be the point set [a,b);
	        bOnOther = (Ub >= 0 && Ub < 1);		// For ints we need the line to be the point set [a,b);
	        bool bResult  = bOnThis && bOnOther;

	        if (bAddPtIfFalse || bResult)
	        {
		        IntersectionPts.Add(new C2DPoint(p1.x + Ua*(p2.x - p1.x) , p1.y + Ua*(p2.y - p1.y)));
	        }

	        return (bResult); 

        }
Пример #21
0
        /// <summary>
        /// Gets the point half way along the curve as a new object.
        /// </summary>
        public C2DPoint GetMidPoint() 
        {
	        Debug.Assert(IsValid(), "Invalid arc defined, cannot calculate midpoint");
	        // Make a line from the circle centre to the middle of the line
	        C2DPoint ptCentre = new C2DPoint(GetCircleCentre());

	        C2DPoint ptLineCentre = new C2DPoint(Line.GetMidPoint());

	        C2DLine CenToMid = new C2DLine(ptCentre, ptLineCentre);

	        if ( CenToMid.vector.i == 0 && CenToMid.vector.j == 0)
	        {
		        // The centre of the line is the same as the centre of the circle
		        // i.e. this arc is 180 degrees or half a circle.
		        CenToMid.Set(Line);
		        CenToMid.SetPointFrom( ptLineCentre );
		        if ( ArcOnRight )
			        CenToMid.vector.TurnRight();
		        else
			        CenToMid.vector.TurnLeft();
	        }
	        else
	        {
		        // extend it to the edge of the arc
		        CenToMid.SetLength( Radius );
		        // if the arc on the opposite side to the centre then reverse the line.
		        if ( ArcOnRight == CentreOnRight)
		        {
			        CenToMid.vector.Reverse();
		        }
	        }

	        return CenToMid.GetPointTo();

        }
Пример #22
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;


        }
Пример #23
0
        /// <summary>
        /// True if the ray provided (infinite line starting from the first point) crosses this. 
        /// </summary>
        /// <param name="Ray">The other line to test.</param>
        /// <param name="IntersectionPts">Output. The intersection points.</param>
	    public bool CrossesRay(C2DLine Ray,  List<C2DPoint> IntersectionPts)
        {
	        C2DPoint p1 = point;
	        C2DPoint p2 = GetPointTo();

	        C2DPoint p3 = Ray.point;
	        C2DPoint p4 = Ray.GetPointTo();

	        double Ua = (p4.x - p3.x)*(p1.y - p3.y) - (p4.y - p3.y) * (p1.x - p3.x);
	        double Ub = (p2.x - p1.x)*(p1.y - p3.y) - (p2.y - p1.y) * (p1.x - p3.x);

	        double dDenominator = (p4.y - p3.y)*(p2.x - p1.x) - (p4.x - p3.x) * (p2.y - p1.y);

	        if (dDenominator == 0) 
                return false;

	        Ua = Ua / dDenominator;
	        Ub = Ub / dDenominator;

	        bool bResult = (Ua >= 0 && Ua <= 1) && (Ub >= 0);

	        if (bResult)
	        {
		        IntersectionPts.Add(new C2DPoint(p1.x + Ua*(p2.x - p1.x) , p1.y + Ua*(p2.y - p1.y)));
	        }

	        return bResult;
        }
Пример #24
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.
            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);
        }
Пример #25
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;
                }
            }
        }
Пример #26
0
        /// <summary>
        /// True if this line would cross the other if this were infinite.
        /// </summary>
        /// <param name="Other">The other line to test.</param>
	    public bool WouldCross(C2DLine Other)
        {
	        bool bPointOnRight = IsOnRight(Other.point);
	        bool bPointToOnRight = IsOnRight(Other.GetPointTo());

	        return (bPointOnRight^bPointToOnRight);
        }
Пример #27
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));
            }
        }
Пример #28
0
        /// <summary>
        /// Function to join the 2 lines at the point where they do / would intersect. If they do then
        /// the lines are clipped to remove the smallest part of the line. Returns false if they
        /// cannot be joined.
        /// </summary>
        /// <param name="Other">The other line</param>
        public bool Join(C2DLine Other)
        {
            C2DPoint p1 = point;
            C2DPoint p2 = GetPointTo();

            C2DPoint p3 = Other.point;
            C2DPoint p4 = Other.GetPointTo();

            double Ua = (p4.x - p3.x) * (p1.y - p3.y) - (p4.y - p3.y) * (p1.x - p3.x);
            double Ub = (p2.x - p1.x) * (p1.y - p3.y) - (p2.y - p1.y) * (p1.x - p3.x);

            double dDenominator = (p4.y - p3.y) * (p2.x - p1.x) - (p4.x - p3.x) * (p2.y - p1.y);

            if (dDenominator == 0)
                return false;

            Ua = Ua / dDenominator;
            Ub = Ub / dDenominator;

            C2DPoint IntPt = new C2DPoint(p1.x + Ua * (p2.x - p1.x), p1.y + Ua * (p2.y - p1.y));
            if ( Ua >=0.5)
                this.SetPointTo( IntPt );
            else
                this.SetPointFrom( IntPt );

            if ( Ub >=0.5)
                Other.SetPointTo( IntPt );
            else
                Other.SetPointFrom( IntPt );

            return true;
        }
Пример #29
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);
            }
        }
Пример #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;

        }
Пример #31
0
        /// <summary>
        /// Returns the centroid.
        /// </summary>
        public C2DPoint GetCentroid()
        {
            // Find the area first. Do it explicitly as we may need bits of the calc later.
            double dSegAng = Arc.GetSegmentAngle();
            bool bBig = Arc.ArcOnRight == Arc.CentreOnRight;

            double dRadius = Arc.Radius;
            double dRadiusSquare = dRadius * dRadius;
            double dCircleArea = dRadiusSquare * Constants.conPI;
            double dArea = dRadiusSquare * ( (dSegAng - Math.Sin(dSegAng)) / 2);

            // Find the maximum length of the small segment along the direction of the line.
            double dLength = Arc.Line.GetLength();
            // Now find the average height of the segment over that line
            double dHeight = dArea / dLength;

            // Find the centre point on the line and the centre of the circle
            C2DPoint ptLineCen = new C2DPoint(Arc.Line.GetMidPoint());
            C2DPoint ptCircleCen = new C2DPoint(Arc.GetCircleCentre());

            // Set up a line from the mid point on the line to the circle centre
            // then set the length of it to the average height divided by 2. The end
            // point of the line is then the centroid. If we are using the small bit,
            // The line needs to be reversed.
            C2DLine Line = new C2DLine( ptLineCen, ptCircleCen);

            Line.vector.Reverse();

            Line.vector.SetLength(  dHeight / 2 );

            if (bBig)
            {
                C2DPoint ptSmallCen = new C2DPoint(Line.GetPointTo());
                // Return the weighted average of the 2 centroids.

                ptCircleCen.Multiply(dCircleArea);
                ptSmallCen.Multiply(dArea);
                C2DPoint pRes = ptCircleCen - ptSmallCen;
                pRes.Multiply(1.0 / (dCircleArea - dArea));
                return pRes;
               //     return ( new C2DPoint(ptCircleCen * dCircleArea - ptSmallCen * dArea) ) / ( dCircleArea - dArea);
            }
            else
                return Line.GetPointTo();
        }