/// <summary> /// True if this crosses the straight line. /// </summary> /// <param name="TestLine">The other line.</param> /// <param name="IntersectionPts">The interection point list to recieve the result.</param> public bool Crosses(C2DLine TestLine, List <C2DPoint> IntersectionPts) { List <C2DPoint> IntPtsTemp = new List <C2DPoint>(); C2DCircle TestCircle = new C2DCircle(GetCircleCentre(), Radius); if (TestCircle.Crosses(TestLine, IntPtsTemp)) { for (int i = IntPtsTemp.Count - 1; i >= 0; i--) { if (Line.IsOnRight(IntPtsTemp[i]) ^ ArcOnRight || IntPtsTemp[i].PointEqualTo(Line.point) || IntPtsTemp[i].PointEqualTo(Line.GetPointTo())) { IntPtsTemp.RemoveAt(i); } } if (IntPtsTemp.Count == 0) { return(false); } else { IntersectionPts.InsertRange(0, IntPtsTemp); // .( IntersectionPts ); // IntersectionPts << IntPtsTemp; return(true); } } else { return(false); } }
/// <summary> /// Gets the points that are furthest apart. /// </summary> /// <param name="nIndx1">Ouput. The first index.</param> /// <param name="nIndx2">Ouput. The second index.</param> /// <param name="dDist">Ouput. The distance.</param> public void GetExtremePoints(ref int nIndx1, ref int nIndx2, ref double dDist) { // First take a guess at them. GetExtremePointsEst(ref nIndx1, ref nIndx2, ref dDist, 0); // Set up a circle to bound the 2 guesses. C2DVector Vec = new C2DVector(this[nIndx1], this[nIndx2]); Vec.Multiply(0.5); C2DCircle Circle = new C2DCircle(this[nIndx1] + new C2DPoint(Vec), dDist / 2); // Now, if the guess was wrong, there must be a point outside the circle which is part of // the right solution. Go through all these, check and reset the result each time. for (int i = 0; i < Count; i++) { if (i != nIndx1 && i != nIndx2) { if (!Circle.Contains(this[i])) { double dDistCheck = 0; int nCheck1 = GetFurthestPoint(i, ref dDistCheck); if (dDistCheck > dDist) { nIndx1 = i; nIndx2 = nCheck1; dDist = dDistCheck; } } } } }
/// <summary> /// Distance between this and the test point. /// </summary> /// <param name="TestPoint">The test point.</param> /// <param name="ptOnThis">The closest point on this to the given point as a returned value.</param> public override double Distance(C2DPoint TestPoint, C2DPoint ptOnThis) { C2DPoint ptCen = new C2DPoint(GetCircleCentre()); C2DCircle Circle = new C2DCircle(ptCen, Radius); C2DPoint ptOnCircle = new C2DPoint(); double dCircleDist = Circle.Distance(TestPoint, ptOnCircle); if (ArcOnRight ^ Line.IsOnRight(ptOnCircle)) { // The closest point on the circle isn't on the curve double d1 = TestPoint.Distance(Line.point); double d2 = TestPoint.Distance(Line.GetPointTo()); if (d1 < d2) { ptOnThis.Set(Line.point); return(d1); } else { ptOnThis.Set(Line.GetPointTo()); return(d2); } } else { // The closest point on the circle IS on the curve ptOnThis.Set(ptOnCircle); return(Math.Abs(dCircleDist)); } }
/// <summary> /// Draws a circle filled. /// </summary> public void DrawFilled(C2DCircle Circle, Graphics graphics, Brush brush) { C2DRect Rect = new C2DRect(); Circle.GetBoundingRect(Rect); this.ScaleAndOffSet(Rect.BottomRight); this.ScaleAndOffSet(Rect.TopLeft); graphics.FillEllipse(brush, (int)Rect.TopLeft.x, (int)Rect.BottomRight.y, (int)Rect.Width(), (int)Rect.Height()); }
/// <summary> /// Draws a circle /// </summary> public void Draw(C2DCircle Circle, Graphics graphics, Pen pen) { C2DRect Rect = new C2DRect(); Circle.GetBoundingRect(Rect); this.ScaleAndOffSet(Rect.BottomRight); this.ScaleAndOffSet(Rect.TopLeft); graphics.DrawEllipse(pen, (int)Rect.TopLeft.x, (int)Rect.BottomRight.y, (int)Rect.Width(), (int)Rect.Height()); }
/// <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> /// Assignment given a straight line defining the end points and a point on the arc. /// </summary> /// <param name="ArcLine">The line defining the start and end point of the arc.</param> /// <param name="ptOnArc">A point on the arc.</param> public void Set(C2DLine ArcLine, C2DPoint ptOnArc) { Line.Set(ArcLine); C2DPoint ptTo = new C2DPoint(Line.GetPointTo()); C2DCircle Circle = new C2DCircle(); Circle.SetCircumscribed(Line.point, ptTo, ptOnArc); Radius = Line.point.Distance(Circle.Centre); ArcOnRight = Line.IsOnRight(ptOnArc); CentreOnRight = Line.IsOnRight(Circle.Centre); }
/// <summary> /// True if this crosses the other and returns the intersectin points. /// </summary> /// <param name="Other">The other circle.</param> /// <param name="IntersectionPts">The point set to recieve the result.</param> public bool Crosses(C2DCircle Other, List <C2DPoint> IntersectionPts) { double x1 = _Centre.x; double y1 = _Centre.y; double R1 = Radius; double x2 = Other.Centre.x; double y2 = Other.Centre.y; double R2 = Other.Radius; double D = Other.Centre.Distance(_Centre); if (D == 0) { return(false); } if (D == (R1 + R2)) { C2DVector V = new C2DVector(_Centre, Other.Centre); V.SetLength(R1); C2DPoint P = new C2DPoint(_Centre.GetPointTo(V)); IntersectionPts.Add(P); return(true); } if (D > (R1 + R2) || D < Math.Abs(R1 - R2)) { return(false); } double A = (D + R1 + R2) * (D + R1 - R2) * (D - R1 + R2) * (-D + R1 + R2); A = Math.Sqrt(A) / 4; double XE1 = (x1 + x2) / 2 - (x1 - x2) * (R1 * R1 - R2 * R2) / (2 * D * D); double XE2 = 2 * (y1 - y2) * A / (D * D); double YE1 = (y1 + y2) / 2 - (y1 - y2) * (R1 * R1 - R2 * R2) / (2 * D * D); double YE2 = 2 * (x1 - x2) * A / (D * D); C2DPoint pt1 = new C2DPoint(XE1 + XE2, YE1 - YE2); C2DPoint pt2 = new C2DPoint(XE1 - XE2, YE1 + YE2); IntersectionPts.Add(pt1); IntersectionPts.Add(pt2); return(true); }
/// <summary> /// True if this crosses a curved line. /// </summary> /// <param name="Other">The other arc.</param> /// <param name="IntersectionPts">The interection point list to recieve the result.</param> public bool Crosses(C2DArc Other, List <C2DPoint> IntersectionPts) { C2DCircle TestCircleThis = new C2DCircle(GetCircleCentre(), Radius); C2DCircle TestCircleOther = new C2DCircle(Other.GetCircleCentre(), Other.Radius); List <C2DPoint> IntPtsTemp = new List <C2DPoint>(); if (TestCircleThis.Crosses(TestCircleOther, IntPtsTemp)) { for (int i = IntPtsTemp.Count - 1; i >= 0; i--) { if ((Line.IsOnRight(IntPtsTemp[i]) ^ ArcOnRight) || Other.Line.IsOnRight(IntPtsTemp[i]) ^ Other.ArcOnRight || IntPtsTemp[i].PointEqualTo(Line.point) || IntPtsTemp[i].PointEqualTo(Line.GetPointTo()) || IntPtsTemp[i].PointEqualTo(Other.GetPointFrom()) || IntPtsTemp[i].PointEqualTo(Other.GetPointTo())) { IntPtsTemp.RemoveAt(i); } } if (IntPtsTemp.Count == 0) { return(false); } else { IntersectionPts.InsertRange(0, IntPtsTemp); // IntPtsTemp.CopyTo( IntersectionPts ); // (*IntersectionPts) << IntPtsTemp; return(true); } } else { return(false); } }
/// <summary> /// Gets the minimum bounding circle. /// </summary> /// <param name="Circle">Ouput. The Circle.</param> public void GetBoundingCircle(C2DCircle Circle) { if (this.Count < 3) { if (this.Count == 2) { Circle.SetMinimum(this[0], this[1]); } else if (this.Count == 1) { Circle.Set(this[0], 0); } else { Debug.Assert(false, "Point set with no points. Cannot calculate bounding circle."); } return; } int nIndx1 = 0; int nIndx2 = 0;; int nIndx3 = 0;; double dDist = 0;; // First get the points that are furthest away from each other. GetExtremePoints(ref nIndx1, ref nIndx2, ref dDist); // Set the circle to bound these. Circle.SetMinimum(this[nIndx1], this[nIndx2]); // Set up a flag to show if we are circumscibed. (Once we are, we always will be). bool bCircum = false; // Cycle through and if any points aren't in the circle, then set the circle to be circumscribed. for (int i = 0; i < Count; i++) { if (i != nIndx1 && i != nIndx2) { if (!Circle.Contains(this[i])) { nIndx3 = i; Circle.SetCircumscribed(this[nIndx1], this[nIndx2], this[nIndx3]); bCircum = true; // Break out and try again. break; } } } // If we didn't succeed first time then go through again setting it to be circumscribed every time. if (bCircum) { for (int i = 0; i < Count; i++) { if (i != nIndx1 && i != nIndx2 && i != nIndx3) { if (!Circle.Contains(this[i])) { double Dist1 = this[i].Distance(this[nIndx1]); double Dist2 = this[i].Distance(this[nIndx2]); double Dist3 = this[i].Distance(this[nIndx3]); if (Dist1 < Dist2 && Dist1 < Dist3) { // Closest to point 1 so elimitate this nIndx1 = i; } else if (Dist2 < Dist3) { // Closest to point 2 so elimitate this nIndx2 = i; } else { // Closest to point 3 so elimitate this nIndx3 = i; } Circle.SetCircumscribed(this[nIndx1], this[nIndx2], this[nIndx3]); } } } } }
/// <summary> /// Assignment given a straight line defining the end points and a point on the arc. /// </summary> /// <param name="ArcLine">The line defining the start and end point of the arc.</param> /// <param name="ptOnArc">A point on the arc.</param> public void Set(C2DLine ArcLine, C2DPoint ptOnArc) { Line.Set(ArcLine); C2DPoint ptTo = new C2DPoint(Line.GetPointTo()); C2DCircle Circle = new C2DCircle(); Circle.SetCircumscribed( Line.point , ptTo, ptOnArc) ; Radius = Line.point.Distance( Circle.Centre ); ArcOnRight = Line.IsOnRight(ptOnArc); CentreOnRight = Line.IsOnRight(Circle.Centre); }
/// <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> /// Constructor. /// </summary> /// <param name="Other">The circle to assign this to.</param> public C2DCircle(C2DCircle Other) { _Centre.Set(Other.Centre); Radius = Other.Radius; }
/// <summary> /// Distance between this and the test point. /// </summary> /// <param name="TestPoint">The test point.</param> /// <param name="ptOnThis">The closest point on this to the given point as a returned value.</param> public override double Distance(C2DPoint TestPoint, C2DPoint ptOnThis) { C2DPoint ptCen = new C2DPoint( GetCircleCentre()); C2DCircle Circle = new C2DCircle(ptCen, Radius); C2DPoint ptOnCircle = new C2DPoint(); double dCircleDist = Circle.Distance(TestPoint, ptOnCircle); if (ArcOnRight ^ Line.IsOnRight(ptOnCircle)) { // The closest point on the circle isn't on the curve double d1 = TestPoint.Distance(Line.point); double d2 = TestPoint.Distance(Line.GetPointTo()); if (d1 < d2) { ptOnThis.Set(Line.point); return d1; } else { ptOnThis.Set(Line.GetPointTo()); return d2; } } else { // The closest point on the circle IS on the curve ptOnThis.Set(ptOnCircle); return Math.Abs(dCircleDist); } }
/// <summary> /// True if this crosses the other and returns the intersectin points. /// </summary> /// <param name="Other">The other circle.</param> /// <param name="IntersectionPts">The point set to recieve the result.</param> public bool Crosses(C2DCircle Other, List<C2DPoint> IntersectionPts) { double x1 = _Centre.x; double y1 = _Centre.y; double R1 = Radius; double x2 = Other.Centre.x; double y2 = Other.Centre.y; double R2 = Other.Radius; double D = Other.Centre.Distance(_Centre); if (D == 0) return false; if (D == (R1 + R2) ) { C2DVector V = new C2DVector(_Centre, Other.Centre); V.SetLength(R1); C2DPoint P = new C2DPoint(_Centre.GetPointTo( V )); IntersectionPts.Add(P); return true; } if ( D > (R1 + R2) || D < Math.Abs(R1 - R2)) return false; double A = (D + R1 + R2) * (D + R1 - R2) * (D - R1 + R2) * (-D + R1 + R2); A = Math.Sqrt(A) / 4; double XE1 = (x1 + x2) / 2 - (x1 - x2) * (R1 * R1 - R2 * R2) / (2 * D * D); double XE2 = 2 * (y1 - y2) * A / (D * D); double YE1 = (y1 + y2) / 2 - (y1 - y2) * (R1 * R1 - R2 * R2) / (2 * D * D); double YE2 = 2 * (x1 - x2) * A / (D * D); C2DPoint pt1 = new C2DPoint( XE1 + XE2, YE1 - YE2); C2DPoint pt2 = new C2DPoint( XE1 - XE2, YE1 + YE2); IntersectionPts.Add(pt1); IntersectionPts.Add(pt2); return true; }
/// <summary> /// Sets this to another. /// </summary> /// <param name="Other">The other circle.</param> public void Set(C2DCircle Other) { _Centre.Set(Other.Centre); Radius = Other.Radius; }
/// <summary> /// True if this crosses the straight line. /// </summary> /// <param name="TestLine">The other line.</param> /// <param name="IntersectionPts">The interection point list to recieve the result.</param> public bool Crosses(C2DLine TestLine, List<C2DPoint> IntersectionPts) { List<C2DPoint> IntPtsTemp = new List<C2DPoint>(); C2DCircle TestCircle = new C2DCircle(GetCircleCentre(), Radius); if (TestCircle.Crosses(TestLine, IntPtsTemp)) { for (int i = IntPtsTemp.Count - 1 ; i >= 0 ; i--) { if (Line.IsOnRight(IntPtsTemp[i]) ^ ArcOnRight || IntPtsTemp[i].PointEqualTo( Line.point) || IntPtsTemp[i].PointEqualTo( Line.GetPointTo())) { IntPtsTemp.RemoveAt(i); } } if (IntPtsTemp.Count == 0) return false; else { IntersectionPts.InsertRange(0, IntPtsTemp); // .( IntersectionPts ); // IntersectionPts << IntPtsTemp; return true; } } else { return false; } }
/// <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> /// The distance between this and another arc. /// </summary> /// <param name="Other">The test point.</param> /// <param name="ptOnThis">The closest point on this to the other as a returned value.</param> /// <param name="ptOnOther">The closest point on the other to this as a returned value.</param> public double Distance(C2DArc Other, C2DPoint ptOnThis, C2DPoint ptOnOther) { List<C2DPoint> IntPts1 = new List<C2DPoint>(); List<C2DPoint> IntPts2 = new List<C2DPoint>(); C2DPoint ptThisCen = new C2DPoint( GetCircleCentre() ); C2DPoint ptOtherCen = new C2DPoint(Other.GetCircleCentre()); C2DCircle CircleThis = new C2DCircle( ptThisCen, Radius); C2DCircle CircleOther = new C2DCircle( ptOtherCen, Other.Radius ); if (CircleThis.Crosses( CircleOther , IntPts1 ) ) { for (int i = 0; i < IntPts1.Count; i++) { if ( (Line.IsOnRight( IntPts1[i] ) == ArcOnRight ) && (Other.Line.IsOnRight( IntPts1[i] ) == Other.ArcOnRight ) ) { ptOnThis.Set(IntPts1[i]); ptOnOther.Set(IntPts1[i]); return 0; } } IntPts1.Clear(); } C2DLine LineCenToOther = new C2DLine(); LineCenToOther.point = new C2DPoint(ptThisCen); LineCenToOther.vector = new C2DVector(ptThisCen, ptOtherCen); LineCenToOther.GrowFromCentre( Math.Max(Radius, Other.Radius) * 10); double dMinDist = 1.7E308; double dDist = 0; if ( Crosses(LineCenToOther, IntPts1) && Other.Crosses(LineCenToOther, IntPts2)) { for (int i = 0 ; i < IntPts1.Count; i++) { for (int j = 0 ; j < IntPts2.Count; j++) { dDist = IntPts1[i].Distance(IntPts2[j]); if (dDist < dMinDist) { ptOnThis.Set( IntPts1[i]); ptOnOther.Set( IntPts2[j]); dMinDist = dDist; } } } } C2DPoint ptOnThisTemp = new C2DPoint(); dDist = Distance(Other.GetPointFrom(), ptOnThisTemp); if (dDist < dMinDist) { ptOnThis.Set(ptOnThisTemp); ptOnOther.Set(Other.GetPointFrom()); dMinDist = dDist; } dDist = Distance(Other.GetPointTo(), ptOnThisTemp); if (dDist < dMinDist) { ptOnThis.Set(ptOnThisTemp); ptOnOther.Set(Other.GetPointTo()); dMinDist = dDist; } C2DPoint ptOnOtherTemp = new C2DPoint(); dDist = Other.Distance(GetPointFrom(), ptOnOtherTemp); if (dDist < dMinDist) { ptOnThis.Set( GetPointFrom()); ptOnOther.Set( ptOnOtherTemp); dMinDist = dDist; } dDist = Other.Distance(GetPointTo(), ptOnOtherTemp); if (dDist < dMinDist) { ptOnThis.Set( GetPointTo()); ptOnOther.Set( ptOnOtherTemp); dMinDist = dDist; } return dMinDist; }
/// <summary> /// The distance between this and another arc. /// </summary> /// <param name="Other">The test point.</param> /// <param name="ptOnThis">The closest point on this to the other as a returned value.</param> /// <param name="ptOnOther">The closest point on the other to this as a returned value.</param> public double Distance(C2DArc Other, C2DPoint ptOnThis, C2DPoint ptOnOther) { List <C2DPoint> IntPts1 = new List <C2DPoint>(); List <C2DPoint> IntPts2 = new List <C2DPoint>(); C2DPoint ptThisCen = new C2DPoint(GetCircleCentre()); C2DPoint ptOtherCen = new C2DPoint(Other.GetCircleCentre()); C2DCircle CircleThis = new C2DCircle(ptThisCen, Radius); C2DCircle CircleOther = new C2DCircle(ptOtherCen, Other.Radius); if (CircleThis.Crosses(CircleOther, IntPts1)) { for (int i = 0; i < IntPts1.Count; i++) { if ((Line.IsOnRight(IntPts1[i]) == ArcOnRight) && (Other.Line.IsOnRight(IntPts1[i]) == Other.ArcOnRight)) { ptOnThis.Set(IntPts1[i]); ptOnOther.Set(IntPts1[i]); return(0); } } IntPts1.Clear(); } C2DLine LineCenToOther = new C2DLine(); LineCenToOther.point = new C2DPoint(ptThisCen); LineCenToOther.vector = new C2DVector(ptThisCen, ptOtherCen); LineCenToOther.GrowFromCentre(Math.Max(Radius, Other.Radius) * 10); double dMinDist = 1.7E308; double dDist = 0; if (Crosses(LineCenToOther, IntPts1) && Other.Crosses(LineCenToOther, IntPts2)) { for (int i = 0; i < IntPts1.Count; i++) { for (int j = 0; j < IntPts2.Count; j++) { dDist = IntPts1[i].Distance(IntPts2[j]); if (dDist < dMinDist) { ptOnThis.Set(IntPts1[i]); ptOnOther.Set(IntPts2[j]); dMinDist = dDist; } } } } C2DPoint ptOnThisTemp = new C2DPoint(); dDist = Distance(Other.GetPointFrom(), ptOnThisTemp); if (dDist < dMinDist) { ptOnThis.Set(ptOnThisTemp); ptOnOther.Set(Other.GetPointFrom()); dMinDist = dDist; } dDist = Distance(Other.GetPointTo(), ptOnThisTemp); if (dDist < dMinDist) { ptOnThis.Set(ptOnThisTemp); ptOnOther.Set(Other.GetPointTo()); dMinDist = dDist; } C2DPoint ptOnOtherTemp = new C2DPoint(); dDist = Other.Distance(GetPointFrom(), ptOnOtherTemp); if (dDist < dMinDist) { ptOnThis.Set(GetPointFrom()); ptOnOther.Set(ptOnOtherTemp); dMinDist = dDist; } dDist = Other.Distance(GetPointTo(), ptOnOtherTemp); if (dDist < dMinDist) { ptOnThis.Set(GetPointTo()); ptOnOther.Set(ptOnOtherTemp); dMinDist = dDist; } return(dMinDist); }
/// <summary> /// Distance to a 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 crosses a curved line. /// </summary> /// <param name="Other">The other arc.</param> /// <param name="IntersectionPts">The interection point list to recieve the result.</param> public bool Crosses(C2DArc Other, List<C2DPoint> IntersectionPts) { C2DCircle TestCircleThis = new C2DCircle (GetCircleCentre(), Radius); C2DCircle TestCircleOther= new C2DCircle (Other.GetCircleCentre(), Other.Radius); List<C2DPoint> IntPtsTemp = new List<C2DPoint>(); if (TestCircleThis.Crosses(TestCircleOther, IntPtsTemp)) { for (int i = IntPtsTemp.Count - 1; i >= 0 ; i--) { if ((Line.IsOnRight(IntPtsTemp[i]) ^ ArcOnRight) || Other.Line.IsOnRight(IntPtsTemp[i]) ^ Other.ArcOnRight || IntPtsTemp[i].PointEqualTo( Line.point) || IntPtsTemp[i].PointEqualTo( Line.GetPointTo()) || IntPtsTemp[i].PointEqualTo( Other.GetPointFrom()) || IntPtsTemp[i].PointEqualTo( Other.GetPointTo())) { IntPtsTemp.RemoveAt(i); } } if (IntPtsTemp.Count == 0) return false; else { IntersectionPts.InsertRange(0, IntPtsTemp); // IntPtsTemp.CopyTo( IntersectionPts ); // (*IntersectionPts) << IntPtsTemp; return true; } } else { return false; } }