/// <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()); } }
/// <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); }
/// <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); }
/// <summary> /// Static version of InCentre function. /// </summary> public static C2DPoint GetInCentre(C2DPoint pt1, C2DPoint pt2, C2DPoint pt3) { // Set up a line to bisect the lines from 1 to 2 and 1 to 3 var Line1 = new C2DLine(pt1, pt2); var Line2 = new C2DLine(pt1, pt3); Line1.SetLength(Line2.GetLength()); var Line12Bisect = new C2DLine(pt1, pt3.GetMidPoint(Line1.GetPointTo())); // Set up a line to bisect the lines from 2 to 1 and 2 to 3 var Line3 = new C2DLine(pt2, pt1); var Line4 = new C2DLine(pt2, pt3); Line3.SetLength(Line4.GetLength()); var Line34Bisect = new C2DLine(pt2, pt3.GetMidPoint(Line3.GetPointTo())); // Now intersect the 2 lines and find the point. var Int = new List <C2DPoint>(); // Add the intersection even if there isn't one (i.e. infinite lines) bool B1 = true, B2 = true; Line12Bisect.Crosses(Line34Bisect, Int, ref B1, ref B2, true); Debug.Assert(Int.Count == 1); return(Int[0]); }
/// <summary> /// Returns the 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()); } }
/// <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); }
/// <summary> /// Distance between this and another straight line. /// </summary> /// <param name="TestLine">The test line.</param> /// <param name="ptOnThis">The closest point on this to the other as a returned value.</param> /// <param name="ptOnOther">The closest point on the other to this as a returned value.</param> public double Distance(C2DLine TestLine, C2DPoint ptOnThis, C2DPoint ptOnOther) { C2DCircle Circle = new C2DCircle(GetCircleCentre(), Radius); double dCircDist = Circle.Distance(TestLine, ptOnThis, ptOnOther); double dDist = 0; if (TestLine.IsOnRight(ptOnThis) ^ ArcOnRight) { // The point found isn't on this. // This means the 2 closest points cannot be ON both lines, we must have a end point as one. ptOnThis.Set(Line.point); dDist = TestLine.Distance(ptOnThis, ptOnOther); C2DPoint ptThisTemp = new C2DPoint(Line.GetPointTo()); C2DPoint ptOtherTemp = new C2DPoint(); double d2 = TestLine.Distance(ptThisTemp, ptOtherTemp); if (d2 < dDist) { dDist = d2; ptOnThis.Set(ptThisTemp); ptOnOther.Set(ptOtherTemp); } // If the line was outside the circle then stop here as no need to go any further. // This is because the closest point on this must be one of the end points. if (dCircDist < 0) { double d3 = Distance(TestLine.point, ptThisTemp); if (d3 < dDist) { dDist = d3; ptOnThis.Set(ptThisTemp); ptOnOther.Set(Line.point); } double d4 = Distance(TestLine.GetPointTo(), ptThisTemp); if (d4 < dDist) { dDist = d4; ptOnThis.Set(ptThisTemp); ptOnOther.Set(Line.GetPointTo()); } } } else { dDist = Math.Abs(dCircDist); } // ptOnThis.Set(ptThis); // ptOnOther.Set(ptOther); return(dDist); }
/// <summary> /// 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); }
/// <summary> /// Distance to a point, returns the closest point on the circle. /// </summary> /// <param name="TestPoint">Point to calculate the distance to.</param> /// <param name="ptOnThis">Closest point on the circle to recieve the result.</param> public double Distance(C2DPoint TestPoint, C2DPoint ptOnThis) { double dDist = _Centre.Distance(TestPoint); if (dDist == 0) { // point is the centre so just arbitrary point to the circle C2DVector V1 = new C2DVector(Radius, 0); ptOnThis.Set(_Centre.GetPointTo(V1)); } else { // find the point on the circle. C2DLine LineCenToPt = new C2DLine(_Centre, TestPoint); LineCenToPt.vector.SetLength(Radius); ptOnThis.Set(LineCenToPt.GetPointTo()); } return(dDist - Radius); // -ve indicates inside. }
/// <summary> /// 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()); }
/// <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); }
/// <summary> /// True if this crosses the line and returns the intersectin points. /// </summary> /// <param name="Line">The line.</param> /// <param name="IntersectionPts">The point set to recieve the result.</param> public bool Crosses(C2DLine Line, List <C2DPoint> IntersectionPts) { double x1 = Line.point.x; double x2 = Line.point.x + Line.vector.i; double x3 = _Centre.x; double y1 = Line.point.y; double y2 = Line.point.y + Line.vector.j; double y3 = _Centre.y; double r = Radius; double a = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1); double b = 2 * ((x2 - x1) * (x1 - x3) + (y2 - y1) * (y1 - y3)); double c = x3 * x3 + y3 * y3 + x1 * x1 + y1 * y1 - 2 * (x3 * x1 + y3 * y1) - r * r; double u = -b / (2 * a); C2DPoint ptClosestToCen = new C2DPoint(); if (u < 0) { ptClosestToCen.Set(Line.point); } else if (u > 1) { ptClosestToCen.Set(Line.GetPointTo()); } else { C2DVector V1 = new C2DVector(Line.vector); V1.Multiply(u); ptClosestToCen = Line.point.GetPointTo(V1); } double dDist = ptClosestToCen.Distance(_Centre); if (dDist > Radius) { return(false); } else { // Calculate the points. double d1 = b * b - 4 * a * c; Debug.Assert(d1 >= 0); if (d1 < 0) { return(false); } else if (d1 == 0) { double p1 = -b / (2 * a); IntersectionPts.Add(Line.GetPointOn(p1)); return(true); } else { d1 = Math.Sqrt(d1); double p1 = (-b + d1) / (2 * a); double p2 = (-b - d1) / (2 * a); bool bResult = false; if (p2 >= 0 && p2 <= 1) { bResult = true; IntersectionPts.Add(Line.GetPointOn(p2)); } if (p1 >= 0 && p1 <= 1) { bResult = true; IntersectionPts.Add(Line.GetPointOn(p1)); } return(bResult); } } }
/// <summary> /// Distance to a point, returns the closest point on the circle. /// </summary> /// <param name="TestPoint">Point to calculate the distance to.</param> /// <param name="ptOnThis">Closest point on the circle to recieve the result.</param> public double Distance(C2DPoint TestPoint, C2DPoint ptOnThis) { double dDist = _Centre.Distance(TestPoint); if (dDist == 0) { // point is the centre so just arbitrary point to the circle C2DVector V1 = new C2DVector( Radius, 0); ptOnThis.Set( _Centre.GetPointTo(V1)); } else { // find the point on the circle. C2DLine LineCenToPt = new C2DLine (_Centre, TestPoint); LineCenToPt.vector.SetLength(Radius); ptOnThis.Set(LineCenToPt.GetPointTo()); } return (dDist - Radius); // -ve indicates inside. }
/// <summary> /// 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; }
/// <summary> /// Static version of InCentre function. /// </summary> public static C2DPoint GetInCentre(C2DPoint pt1, C2DPoint pt2, C2DPoint pt3) { // Set up a line to bisect the lines from 1 to 2 and 1 to 3 C2DLine Line1 = new C2DLine(pt1, pt2); C2DLine Line2 = new C2DLine(pt1, pt3); Line1.SetLength( Line2.GetLength() ); C2DLine Line12Bisect = new C2DLine( pt1, pt3.GetMidPoint( Line1.GetPointTo())); // Set up a line to bisect the lines from 2 to 1 and 2 to 3 C2DLine Line3 = new C2DLine(pt2, pt1); C2DLine Line4 = new C2DLine(pt2, pt3); Line3.SetLength( Line4.GetLength() ); C2DLine Line34Bisect = new C2DLine(pt2, pt3.GetMidPoint(Line3.GetPointTo())); // Now intersect the 2 lines and find the point. List<C2DPoint> Int = new List<C2DPoint>(); // Add the intersection even if there isn't one (i.e. infinite lines) bool B1 = true, B2 = true; Line12Bisect.Crosses(Line34Bisect, Int, ref B1, ref B2, true); Debug.Assert (Int.Count == 1); return Int[0]; }
/// <summary> /// 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(); } }
/// <summary> /// Distance to a circle, returns the closest point on both circles. /// </summary> /// <param name="Other">Circle to calculate the distance to.</param> /// <param name="ptOnThis">Closest point on this circle to recieve the result.</param> /// <param name="ptOnOther">Closest point on the other circle to recieve the result.</param> public double Distance(C2DCircle Other, C2DPoint ptOnThis, C2DPoint ptOnOther) { double dCenCenDist = _Centre.Distance(Other.Centre); double dOtherRadius = Other.Radius; // C2DPoint ptThis; // C2DPoint ptOther; double dDist = dCenCenDist - Radius - dOtherRadius; if (dDist > 0) { // they do not interect and they are outside each other. C2DLine Line = new C2DLine(_Centre, Other.Centre); Line.vector.SetLength(Radius); ptOnThis.Set(Line.GetPointTo()); Line.vector.Reverse(); Line.SetPointFrom(Other.Centre); Line.vector.SetLength(Other.Radius); ptOnOther.Set(Line.GetPointTo()); } else { if ((dCenCenDist + Radius) < dOtherRadius) { // This is inside the other dDist = dCenCenDist + Radius - dOtherRadius; // -ve if inside C2DVector vec = new C2DVector(Other.Centre, Centre); vec.Multiply(Radius / dCenCenDist); // set the vector to be the length of my radius. ptOnThis.Set(_Centre.GetPointTo(vec)); vec.Multiply(dDist / Radius); // set the vector to be the distance. ptOnOther.Set(ptOnThis.GetPointTo(vec)); } else if ((dCenCenDist + dOtherRadius) < Radius) { // The other is inside this. dDist = dCenCenDist + dOtherRadius - Radius; // -ve if inside C2DVector vec = new C2DVector(_Centre, Other.Centre); vec.Multiply(dOtherRadius / dCenCenDist); // set the vector to be the length of my radius. ptOnOther.Set(Other.Centre.GetPointTo(vec)); vec.Multiply(dDist / dOtherRadius); // set the vector to be the distance. ptOnThis.Set(ptOnOther.GetPointTo(vec)); } else { // there is an intersection dDist = 0; List <C2DPoint> Ints = new List <C2DPoint>(); if (Crosses(Other, Ints)) { ptOnThis.Set(Ints[0]); ptOnOther.Set(ptOnThis); } else { Debug.Assert(false); return(0); } } } // if (ptOnThis) // *ptOnThis = ptThis; // if (ptOnOther) // *ptOnOther = ptOther; return(dDist); }
/// <summary> /// Distance to a circle, returns the closest point on both circles. /// </summary> /// <param name="Other">Circle to calculate the distance to.</param> /// <param name="ptOnThis">Closest point on this circle to recieve the result.</param> /// <param name="ptOnOther">Closest point on the other circle to recieve the result.</param> public double Distance(C2DCircle Other, C2DPoint ptOnThis, C2DPoint ptOnOther) { double dCenCenDist = _Centre.Distance(Other.Centre); double dOtherRadius = Other.Radius; // C2DPoint ptThis; // C2DPoint ptOther; double dDist = dCenCenDist - Radius - dOtherRadius; if (dDist > 0 ) { // they do not interect and they are outside each other. C2DLine Line = new C2DLine(_Centre, Other.Centre); Line.vector.SetLength( Radius); ptOnThis.Set( Line.GetPointTo() ); Line.vector.Reverse(); Line.SetPointFrom(Other.Centre); Line.vector.SetLength(Other.Radius); ptOnOther.Set(Line.GetPointTo()); } else { if ( (dCenCenDist + Radius) < dOtherRadius) { // This is inside the other dDist = dCenCenDist + Radius - dOtherRadius ; // -ve if inside C2DVector vec = new C2DVector( Other.Centre, Centre); vec.Multiply( Radius /dCenCenDist ); // set the vector to be the length of my radius. ptOnThis.Set( _Centre.GetPointTo( vec)); vec.Multiply( dDist /Radius ); // set the vector to be the distance. ptOnOther.Set(ptOnThis.GetPointTo( vec)); } else if ( (dCenCenDist + dOtherRadius) < Radius) { // The other is inside this. dDist = dCenCenDist + dOtherRadius - Radius; // -ve if inside C2DVector vec = new C2DVector( _Centre, Other.Centre); vec.Multiply ( dOtherRadius /dCenCenDist ); // set the vector to be the length of my radius. ptOnOther.Set( Other.Centre.GetPointTo( vec)); vec.Multiply( dDist / dOtherRadius ); // set the vector to be the distance. ptOnThis.Set(ptOnOther.GetPointTo( vec)); } else { // there is an intersection dDist = 0; List<C2DPoint> Ints = new List<C2DPoint>(); if (Crosses(Other, Ints)) { ptOnThis.Set(Ints[0]); ptOnOther.Set(ptOnThis); } else { Debug.Assert(false); return 0; } } } // if (ptOnThis) // *ptOnThis = ptThis; // if (ptOnOther) // *ptOnOther = ptOther; return dDist; }
/// <summary> /// 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); }
/// <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(); }
/// <summary> /// Distance between this and another straight line. /// </summary> /// <param name="TestLine">The test line.</param> /// <param name="ptOnThis">The closest point on this to the other as a returned value.</param> /// <param name="ptOnOther">The closest point on the other to this as a returned value.</param> public double Distance(C2DLine TestLine, C2DPoint ptOnThis, C2DPoint ptOnOther) { C2DCircle Circle = new C2DCircle( GetCircleCentre(), Radius); double dCircDist = Circle.Distance(TestLine, ptOnThis, ptOnOther); double dDist = 0; if (TestLine.IsOnRight(ptOnThis) ^ ArcOnRight) { // The point found isn't on this. // This means the 2 closest points cannot be ON both lines, we must have a end point as one. ptOnThis.Set(Line.point); dDist = TestLine.Distance(ptOnThis, ptOnOther); C2DPoint ptThisTemp = new C2DPoint(Line.GetPointTo()); C2DPoint ptOtherTemp = new C2DPoint(); double d2 = TestLine.Distance(ptThisTemp, ptOtherTemp); if (d2 < dDist) { dDist = d2; ptOnThis.Set(ptThisTemp); ptOnOther.Set(ptOtherTemp); } // If the line was outside the circle then stop here as no need to go any further. // This is because the closest point on this must be one of the end points. if (dCircDist < 0) { double d3 = Distance(TestLine.point, ptThisTemp); if (d3 < dDist) { dDist = d3; ptOnThis.Set(ptThisTemp); ptOnOther.Set(Line.point); } double d4 = Distance(TestLine.GetPointTo(), ptThisTemp); if (d4 < dDist) { dDist = d4; ptOnThis.Set(ptThisTemp); ptOnOther.Set(Line.GetPointTo()); } } } else { dDist = Math.Abs(dCircDist); } // ptOnThis.Set(ptThis); // ptOnOther.Set(ptOther); return dDist; }
/// <summary> /// 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; }
/// <summary> /// Returns the distance from this to the other line. /// </summary> /// <param name="Other">The Other line.</param> /// <param name="ptOnThis">Output. The closest point on this.</param> /// <param name="ptOnOther">Output. The closest point on the other line.</param> public double Distance(C2DLine Other, C2DPoint ptOnThis, C2DPoint ptOnOther) { // First, project the other line onto this and if it falls entirely below it or // above it then 1. There is no intersection, 2. This is closest to one end on this line. var ptOtherP2 = new C2DPoint(Other.GetPointTo()); var vThisP1OtherP1 = new C2DVector(point, Other.point); var vThisP1OtherP2 = new C2DVector(point, ptOtherP2); var ptThisP2 = new C2DPoint(GetPointTo()); var dOtherP1Proj = vThisP1OtherP1.Dot(vector); var dOtherP2Proj = vThisP1OtherP2.Dot(vector); // If they are both less than 0 then the projection falls below the line. if (dOtherP1Proj <= 0 && dOtherP2Proj <= 0) { ptOnThis.Set(point); return(Other.Distance(point, ptOnOther)); } // Now modify the projection so it is the length along this line. var dThisLength = GetLength(); dOtherP1Proj = dOtherP1Proj / dThisLength; dOtherP2Proj = dOtherP2Proj / dThisLength; // If the projections are both above the line then the second point is closest if (dOtherP1Proj >= dThisLength && dOtherP2Proj >= dThisLength) { ptOnThis.Set(ptThisP2); return(Other.Distance(ptThisP2, ptOnOther)); } // This hasn't worked so try the same on the other line. var vOtherP1ThisP1 = new C2DVector(Other.point, point); var vOtherP1ThisP2 = new C2DVector(Other.point, ptThisP2); var dThisP1Proj = vOtherP1ThisP1.Dot(Other.vector); var dThisP2Proj = vOtherP1ThisP2.Dot(Other.vector); // If they are both less than 0 then the projection falls below the line. if (dThisP1Proj <= 0 && dThisP2Proj <= 0) { ptOnOther.Set(Other.point); return(Distance(Other.point, ptOnThis)); } // Now modify the projection so it is the length along this line. var dOtherLength = Other.GetLength(); dThisP1Proj = dThisP1Proj / dOtherLength; dThisP2Proj = dThisP2Proj / dOtherLength; // If the projections are both above the line then the second point is closest if (dThisP1Proj >= dOtherLength && dThisP2Proj >= dOtherLength) { ptOnOther.Set(ptOtherP2); return(Distance(ptOtherP2, ptOnThis)); } // Now test for an intersection. var IntPoint = new List <C2DPoint>(); bool B1 = true, B2 = true; if (this.Crosses(Other, IntPoint, ref B1, ref B2, false)) { ptOnOther.Set(IntPoint[0]); ptOnThis.Set(IntPoint[0]); return(0); } // Otherwise, there MUST be a point projection on one of the lines otherwise both // lines project on either side of each other which is impossible. // So find the distances to all these projections and take the minimum. double dDist = 0; double dMinDist = 0; var bSet = false; var ptOnThisTemp = new C2DPoint(); var ptOnOtherTemp = new C2DPoint(); // Is the other lines first point projected on this? if (dOtherP1Proj >= 0 && dOtherP1Proj <= dThisLength) { // If so find the point on this line and get distance to it. var dFactor = dOtherP1Proj / dThisLength; ptOnThisTemp.Set(new C2DPoint(point.x + vector.i * dFactor, point.y + vector.j * dFactor)); dMinDist = Other.point.Distance(ptOnThisTemp); bSet = true; ptOnOther.Set(Other.point); ptOnThis.Set(ptOnThisTemp); } // Is the other lines second point projected onto this? if (dOtherP2Proj >= 0 && dOtherP2Proj <= dThisLength) { // If so find the point on this and then the distance. Is it less? var dFactor = dOtherP2Proj / dThisLength; ptOnThisTemp.Set(new C2DPoint(point.x + vector.i * dFactor, point.y + vector.j * dFactor)); dDist = ptOtherP2.Distance(ptOnThisTemp); if (!bSet || dDist < dMinDist) { ptOnOther.Set(ptOtherP2); ptOnThis.Set(ptOnThisTemp); dMinDist = dDist; bSet = true; } } // Is the first point on this projected onto the other line? if (dThisP1Proj >= 0 && dThisP1Proj <= dOtherLength) { // If so find the point and the distance. Is it less? var dFactor = dThisP1Proj / dOtherLength; ptOnOtherTemp.Set(new C2DPoint(Other.point.x + Other.vector.i * dFactor, Other.point.y + Other.vector.j * dFactor)); dDist = point.Distance(ptOnOtherTemp); if (!bSet || dDist < dMinDist) { ptOnThis.Set(point); ptOnOther.Set(ptOnOtherTemp); dMinDist = dDist; bSet = true; } } // Is the second point on this projected onto the other line? if (dThisP2Proj >= 0 && dThisP2Proj <= dOtherLength) { // If so find the point and the distance. Is it less? var dFactor = dThisP2Proj / dOtherLength; ptOnOtherTemp.Set(new C2DPoint(Other.point.x + Other.vector.i * dFactor, Other.point.y + Other.vector.j * dFactor)); dDist = ptThisP2.Distance(ptOnOtherTemp); if (!bSet || dDist < dMinDist) { ptOnThis.Set(ptThisP2); ptOnOther.Set(ptOnOtherTemp); dMinDist = dDist; bSet = true; } } Debug.Assert(bSet); // Now return the minimum distance return(dMinDist); }
/// <summary> /// True if this crosses the line and returns the intersectin points. /// </summary> /// <param name="Line">The line.</param> /// <param name="IntersectionPts">The point set to recieve the result.</param> public bool Crosses(C2DLine Line, List<C2DPoint> IntersectionPts) { double x1 = Line.point.x; double x2 = Line.point.x + Line.vector.i; double x3 = _Centre.x; double y1 = Line.point.y; double y2 = Line.point.y + Line.vector.j; double y3 = _Centre.y; double r = Radius; double a = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1); double b = 2 * ((x2 - x1) * (x1 - x3) + (y2 - y1) * (y1 - y3)); double c = x3 * x3 + y3 * y3 + x1 * x1 + y1 * y1 - 2 * (x3 * x1 + y3 * y1) - r * r; double u = -b / (2 * a); C2DPoint ptClosestToCen = new C2DPoint(); if (u < 0) { ptClosestToCen.Set( Line.point ); } else if (u > 1) { ptClosestToCen.Set( Line.GetPointTo()); } else { C2DVector V1 = new C2DVector(Line.vector); V1.Multiply(u); ptClosestToCen = Line.point.GetPointTo(V1); } double dDist = ptClosestToCen.Distance(_Centre); if (dDist > Radius) { return false; } else { // Calculate the points. double d1 = b * b - 4 * a * c; Debug.Assert(d1 >= 0); if (d1 < 0) return false; else if (d1 == 0) { double p1 = -b / (2 * a); IntersectionPts.Add(Line.GetPointOn(p1)); return true; } else { d1 = Math.Sqrt(d1); double p1 = (-b + d1) / (2 * a); double p2 = (-b - d1) / (2 * a); bool bResult = false; if (p2 >= 0 && p2 <= 1) { bResult = true; IntersectionPts.Add(Line.GetPointOn(p2)); } if (p1 >= 0 && p1 <= 1) { bResult = true; IntersectionPts.Add(Line.GetPointOn(p1)); } return bResult; } } }
/// <summary> /// True if 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); }
/// <summary> /// Distance to a line, returns the closest point on the circle and the line. /// </summary> /// <param name="Line">Line to calculate the distance to.</param> /// <param name="ptOnThis">Closest point on the circle to recieve the result.</param> /// <param name="ptOnOther">Closest point on the line to recieve the result.</param> public double Distance(C2DLine Line, C2DPoint ptOnThis, C2DPoint ptOnOther) { CInterval ProjInt = new CInterval(); Project(Line, ProjInt); if (ProjInt.dMax < 0) { // This means that the circle projects entirely "below" the line so the nearest point // To this is the first point on the line and there are no interections. ptOnOther.Set(Line.point); return(Distance(Line.point, ptOnThis)); } double dLength = Line.GetLength(); if (ProjInt.dMin > dLength) { // This means that the circle projects entirely "above" the line so the nearest point // To this is the second point on the line and there are no interections. C2DPoint ptClosest = new C2DPoint(Line.GetPointTo()); ptOnOther.Set(ptClosest); return(Distance(ptClosest, ptOnThis)); } // Now find out if there's an intersection. List <C2DPoint> IntPts = new List <C2DPoint>(); if (Crosses(Line, IntPts)) { ptOnThis.Set(IntPts[0]); ptOnOther.Set(IntPts[0]); return(0); } // Now find out if the line is entirely inside if (ProjInt.dMin > 0 && ProjInt.dMax < dLength && this.Contains(Line.point)) { double d1 = Distance(Line.point, ptOnThis); C2DPoint ptThisTemp = new C2DPoint(); double d2 = Distance(Line.GetPointTo(), ptThisTemp); Debug.Assert(d1 < 0 && d2 < 0); if (d2 > d1) // NOTE USE OF > AS d2 and d1 are -ve. { ptOnThis.Set(ptThisTemp); ptOnOther.Set(Line.GetPointTo()); return(d2); } else { ptOnOther.Set(Line.point); return(d1); } } // We now know the line is entirely outside. // Now find out if this is closest to a point on the line. double dCenOnLine = (ProjInt.dMax + ProjInt.dMin) / 2.0; if (dCenOnLine > 0) { if (dCenOnLine < dLength) { // The centre is projected on the line double dFactor = dCenOnLine / dLength; C2DVector vProj = new C2DVector(Line.vector); vProj.Multiply(dFactor); C2DPoint ptOnLine = new C2DPoint(Line.point.GetPointTo(vProj)); ptOnOther.Set(ptOnLine); return(Distance(ptOnLine, ptOnThis)); } else { // The centre is projected above the line. C2DPoint ptClosest = new C2DPoint(Line.GetPointTo()); ptOnOther.Set(ptClosest); return(Distance(ptClosest, ptOnThis)); } } else { // This means that the circle projects entirely "below" the line. ptOnOther.Set(Line.point); return(Distance(Line.point, ptOnThis)); } }
/// <summary> /// 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; }
/// <summary> /// Distance to a line, returns the closest point on the circle and the line. /// </summary> /// <param name="Line">Line to calculate the distance to.</param> /// <param name="ptOnThis">Closest point on the circle to recieve the result.</param> /// <param name="ptOnOther">Closest point on the line to recieve the result.</param> public double Distance(C2DLine Line, C2DPoint ptOnThis, C2DPoint ptOnOther) { CInterval ProjInt = new CInterval(); Project(Line, ProjInt); if (ProjInt.dMax < 0) { // This means that the circle projects entirely "below" the line so the nearest point // To this is the first point on the line and there are no interections. ptOnOther.Set(Line.point); return Distance(Line.point, ptOnThis); } double dLength = Line.GetLength(); if (ProjInt.dMin > dLength) { // This means that the circle projects entirely "above" the line so the nearest point // To this is the second point on the line and there are no interections. C2DPoint ptClosest = new C2DPoint(Line.GetPointTo()); ptOnOther.Set( ptClosest ); return Distance(ptClosest, ptOnThis); } // Now find out if there's an intersection. List<C2DPoint> IntPts = new List<C2DPoint>(); if (Crosses(Line, IntPts)) { ptOnThis.Set( IntPts[0]); ptOnOther.Set( IntPts[0]); return 0; } // Now find out if the line is entirely inside if (ProjInt.dMin > 0 && ProjInt.dMax < dLength && this.Contains(Line.point)) { double d1 = Distance(Line.point, ptOnThis); C2DPoint ptThisTemp = new C2DPoint(); double d2 = Distance(Line.GetPointTo(), ptThisTemp); Debug.Assert(d1 < 0 && d2 < 0); if (d2 > d1) // NOTE USE OF > AS d2 and d1 are -ve. { ptOnThis.Set(ptThisTemp); ptOnOther.Set(Line.GetPointTo()); return d2; } else { ptOnOther.Set(Line.point); return d1; } } // We now know the line is entirely outside. // Now find out if this is closest to a point on the line. double dCenOnLine = (ProjInt.dMax + ProjInt.dMin) / 2.0; if (dCenOnLine > 0) { if (dCenOnLine < dLength) { // The centre is projected on the line double dFactor = dCenOnLine / dLength; C2DVector vProj = new C2DVector(Line.vector); vProj.Multiply( dFactor); C2DPoint ptOnLine = new C2DPoint( Line.point.GetPointTo(vProj)); ptOnOther.Set( ptOnLine ); return Distance(ptOnLine, ptOnThis); } else { // The centre is projected above the line. C2DPoint ptClosest = new C2DPoint (Line.GetPointTo()); ptOnOther.Set(ptClosest); return Distance(ptClosest, ptOnThis); } } else { // This means that the circle projects entirely "below" the line. ptOnOther.Set( Line.point); return Distance(Line.point, ptOnThis); } }
/// <summary> /// Returns the distance from this to the other line. /// </summary> /// <param name="Other">The Other line.</param> /// <param name="ptOnThis">Output. The closest point on this.</param> /// <param name="ptOnOther">Output. The closest point on the other line.</param> public double Distance(C2DLine Other, C2DPoint ptOnThis , C2DPoint ptOnOther) { // First, project the other line onto this and if it falls entirely below it or // above it then 1. There is no intersection, 2. This is closest to one end on this line. C2DPoint ptOtherP2 = new C2DPoint(Other.GetPointTo()); C2DVector vThisP1OtherP1 = new C2DVector(point, Other.point); C2DVector vThisP1OtherP2 = new C2DVector(point, ptOtherP2); C2DPoint ptThisP2 = new C2DPoint(GetPointTo()); double dOtherP1Proj = vThisP1OtherP1.Dot(vector); double dOtherP2Proj = vThisP1OtherP2.Dot(vector); // If they are both less than 0 then the projection falls below the line. if (dOtherP1Proj <= 0 && dOtherP2Proj <= 0) { ptOnThis.Set(point); return Other.Distance(point, ptOnOther); } // Now modify the projection so it is the length along this line. double dThisLength = GetLength(); dOtherP1Proj = dOtherP1Proj / dThisLength; dOtherP2Proj = dOtherP2Proj / dThisLength; // If the projections are both above the line then the second point is closest if (dOtherP1Proj >= dThisLength && dOtherP2Proj >= dThisLength) { ptOnThis.Set(ptThisP2); return Other.Distance( ptThisP2, ptOnOther); } // This hasn't worked so try the same on the other line. C2DVector vOtherP1ThisP1 = new C2DVector (Other.point, point); C2DVector vOtherP1ThisP2 = new C2DVector(Other.point, ptThisP2); double dThisP1Proj = vOtherP1ThisP1.Dot(Other.vector); double dThisP2Proj = vOtherP1ThisP2.Dot(Other.vector); // If they are both less than 0 then the projection falls below the line. if (dThisP1Proj <= 0 && dThisP2Proj <= 0) { ptOnOther.Set( Other.point); return Distance(Other.point, ptOnThis); } // Now modify the projection so it is the length along this line. double dOtherLength = Other.GetLength(); dThisP1Proj = dThisP1Proj / dOtherLength; dThisP2Proj = dThisP2Proj / dOtherLength; // If the projections are both above the line then the second point is closest if (dThisP1Proj >= dOtherLength && dThisP2Proj >= dOtherLength) { ptOnOther.Set(ptOtherP2); return Distance( ptOtherP2, ptOnThis); } // Now test for an intersection. List<C2DPoint> IntPoint = new List<C2DPoint>(); bool B1 = true, B2 = true; if (this.Crosses(Other, IntPoint,ref B1, ref B2, false)) { ptOnOther.Set(IntPoint[0]); ptOnThis.Set(IntPoint[0]); return 0; } // Otherwise, there MUST be a point projection on one of the lines otherwise both // lines project on either side of each other which is impossible. // So find the distances to all these projections and take the minimum. double dDist = 0; double dMinDist = 0; bool bSet = false; C2DPoint ptOnThisTemp = new C2DPoint(); C2DPoint ptOnOtherTemp = new C2DPoint(); // Is the other lines first point projected on this? if (dOtherP1Proj >= 0 && dOtherP1Proj <= dThisLength) { // If so find the point on this line and get distance to it. double dFactor = dOtherP1Proj / dThisLength; ptOnThisTemp.Set(new C2DPoint(point.x + vector.i * dFactor, point.y + vector.j * dFactor) ); dMinDist = Other.point.Distance(ptOnThisTemp); bSet = true; ptOnOther.Set(Other.point); ptOnThis.Set(ptOnThisTemp); } // Is the other lines second point projected onto this? if (dOtherP2Proj >= 0 && dOtherP2Proj <= dThisLength) { // If so find the point on this and then the distance. Is it less? double dFactor = dOtherP2Proj / dThisLength; ptOnThisTemp.Set( new C2DPoint(point.x + vector.i * dFactor, point.y + vector.j * dFactor) ); dDist = ptOtherP2.Distance(ptOnThisTemp); if (!bSet || dDist < dMinDist) { ptOnOther.Set(ptOtherP2); ptOnThis.Set(ptOnThisTemp); dMinDist = dDist; bSet = true; } } // Is the first point on this projected onto the other line? if (dThisP1Proj >= 0 && dThisP1Proj <= dOtherLength) { // If so find the point and the distance. Is it less? double dFactor = dThisP1Proj / dOtherLength; ptOnOtherTemp.Set( new C2DPoint(Other.point.x + Other.vector.i * dFactor, Other.point.y + Other.vector.j * dFactor)); dDist = point.Distance(ptOnOtherTemp); if (!bSet || dDist < dMinDist) { ptOnThis.Set(point); ptOnOther.Set(ptOnOtherTemp); dMinDist = dDist; bSet = true; } } // Is the second point on this projected onto the other line? if (dThisP2Proj >= 0 && dThisP2Proj <= dOtherLength) { // If so find the point and the distance. Is it less? double dFactor = dThisP2Proj / dOtherLength; ptOnOtherTemp.Set( new C2DPoint(Other.point.x + Other.vector.i * dFactor, Other.point.y + Other.vector.j * dFactor)); dDist = ptThisP2.Distance(ptOnOtherTemp); if (!bSet || dDist < dMinDist) { ptOnThis.Set(ptThisP2); ptOnOther.Set(ptOnOtherTemp); dMinDist = dDist; bSet = true; } } Debug.Assert( bSet ); // Now return the minimum distance return dMinDist; }
/// <summary> /// 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(); }