/// <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> /// 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> /// 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> /// Static version of Fermat point function. /// </summary> public static C2DPoint GetFermatPoint(C2DPoint pt1, C2DPoint pt2, C2DPoint pt3) { C2DLine Line12 = new C2DLine(pt1, pt2); C2DLine Line23 = new C2DLine(pt2, pt3); C2DLine Line31 = new C2DLine(pt3, pt1); double dAng2 = Constants.conPI - Line12.vector.AngleBetween(Line23.vector); if (dAng2 >= Constants.conTWOTHIRDPI) // greater than 120 degrees { return new C2DPoint(pt2); } else if (dAng2 < Constants.conTHIRDPI) // if less than 60 then 1 of the other 2 could be greater than 120 { double dAng3 = Constants.conPI - Line23.vector.AngleBetween(Line31.vector); if (dAng3 >= Constants.conTWOTHIRDPI) // greater than 120 degrees { return new C2DPoint(pt3); } else if ((Constants.conPI - dAng2 - dAng3) >= Constants.conTWOTHIRDPI) // if least angle is greater than 120 { return new C2DPoint(pt1); } } bool bClockwise = Line12.IsOnRight(pt3); if (bClockwise) { Line12.vector.TurnLeft(Constants.conTHIRDPI); // 60 degrees Line23.vector.TurnLeft(Constants.conTHIRDPI); // 60 degrees } else { Line12.vector.TurnRight(Constants.conTHIRDPI); // 60 degrees Line23.vector.TurnRight(Constants.conTHIRDPI); // 60 degrees } Line12.SetPointFrom(pt3); Line23.SetPointFrom(pt1); List<C2DPoint> IntPt = new List<C2DPoint>(); bool B1 = true, B2 = true; if (Line12.Crosses(Line23, IntPt, ref B1, ref B2, false)) { return IntPt[0]; } else { Debug.Assert(false); } return new C2DPoint(0, 0); }
/// <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> /// 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(); }