/// <summary> /// Returns the distance from this to the point. /// </summary> /// <param name="TestPoint">The test pointt.</param> /// <param name="ptOnThis">Output. The closest point on this.</param> public override double Distance(C2DPoint TestPoint, C2DPoint ptOnThis) { var vP1ToPoint = new C2DVector(point, TestPoint); var dLength = GetLength(); var dProjLength = vP1ToPoint.Dot(vector); if (dProjLength < 0) { ptOnThis.Set(point); return(TestPoint.Distance(point)); } else { dProjLength = dProjLength / dLength; if (dProjLength < dLength) { // The projection is on the line var dFactorOnLine = dProjLength / dLength; var PtOnLine = new C2DPoint(point.x + vector.i * dFactorOnLine, point.y + vector.j * dFactorOnLine); ptOnThis.Set(PtOnLine); return(TestPoint.Distance(PtOnLine)); } else { ptOnThis.Set(GetPointTo()); return(TestPoint.Distance(GetPointTo())); } } }
/// <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> /// Returns the distance from this to the other rect. 0 if there is an overlap. /// </summary> /// <param name="Other">Other rectangle.</param> public double Distance(C2DRect Other) { if (this.Overlaps(Other)) { return(0); } if (Other.GetLeft() > this.BottomRight.x) { // Other is to the right if (Other.GetBottom() > this.TopLeft.y) { // Other is to the top right C2DPoint ptTopRight = new C2DPoint(BottomRight.x, TopLeft.y); return(ptTopRight.Distance(new C2DPoint(Other.GetLeft(), Other.GetBottom()))); } else if (Other.GetTop() < this.BottomRight.y) { // Other to the bottom right return(BottomRight.Distance(Other.TopLeft)); } else { // to the right return(Other.GetLeft() - this.BottomRight.x); } } else if (Other.GetRight() < this.TopLeft.x) { // Other to the left if (Other.GetBottom() > this.TopLeft.y) { // Other is to the top left return(TopLeft.Distance(Other.BottomRight)); } else if (Other.GetTop() < this.BottomRight.y) { // Other to the bottom left C2DPoint ptBottomLeft = new C2DPoint(TopLeft.x, BottomRight.y); return(ptBottomLeft.Distance(new C2DPoint(Other.GetRight(), Other.GetTop()))); } else { //Just to the left return(this.TopLeft.x - Other.GetRight()); } } else { // There is horizontal overlap; if (Other.GetBottom() > TopLeft.y) { return(Other.GetBottom() - TopLeft.y); } else { return(BottomRight.y - Other.GetTop()); } } }
/// <summary> /// Set to be the minimum bounding circle for the 3 points. /// </summary> /// <param name="Point1">The first point to include.</param> /// <param name="Point2">The second point to include.</param> /// <param name="Point3">The third point to include.</param> public void SetMinimum(C2DPoint Point1, C2DPoint Point2, C2DPoint Point3) { double dDist12 = Point1.Distance(Point2); double dDist23 = Point2.Distance(Point3); double dDist31 = Point3.Distance(Point1); if (dDist12 >= dDist23 && dDist12 >= dDist31) { SetMinimum(Point1, Point2); if (this.Contains(Point3)) { return; } } else if (dDist23 >= dDist31) { SetMinimum(Point2, Point3); if (this.Contains(Point1)) { return; } } else { SetMinimum(Point3, Point1); if (this.Contains(Point2)) { return; } } // If here, the simple minimum of any 2 doesn't incorporate the other 1 so the // minimum is the circumscribed circle. SetCircumscribed(Point1, Point2, Point3); }
/// <summary> /// Set to be the minimum bounding circle for the 3 points. /// </summary> /// <param name="Point1">The first point to include.</param> /// <param name="Point2">The second point to include.</param> /// <param name="Point3">The third point to include.</param> public void SetMinimum(C2DPoint Point1, C2DPoint Point2, C2DPoint Point3) { double dDist12 = Point1.Distance(Point2); double dDist23 = Point2.Distance(Point3); double dDist31 = Point3.Distance(Point1); if (dDist12 >= dDist23 && dDist12 >= dDist31) { SetMinimum(Point1, Point2); if (this.Contains(Point3)) return; } else if (dDist23 >= dDist31) { SetMinimum(Point2, Point3); if (this.Contains(Point1)) return; } else { SetMinimum(Point3, Point1); if (this.Contains(Point2)) return; } // If here, the simple minimum of any 2 doesn't incorporate the other 1 so the // minimum is the circumscribed circle. SetCircumscribed(Point1, Point2, Point3); }
/// <summary> /// Returns the corresponding circle's centre. /// </summary> public C2DPoint GetCircleCentre() { if (!IsValid()) { return(new C2DPoint(0, 0)); } C2DPoint MidPoint = new C2DPoint(Line.GetMidPoint()); double dMinToStart = MidPoint.Distance(Line.point); double dMidToCentre = Math.Sqrt(Radius * Radius - dMinToStart * dMinToStart); C2DVector MidToCentre = new C2DVector(Line.vector); if (CentreOnRight) { MidToCentre.TurnRight(); } else { MidToCentre.TurnLeft(); } MidToCentre.SetLength(dMidToCentre); return(MidPoint.GetPointTo(MidToCentre)); }
/// <summary> /// Returns the distance from this to the point. 0 if the point inside. /// </summary> /// <param name="TestPoint">Test Point.</param> public override double Distance(C2DPoint TestPoint) { if (TestPoint.x > BottomRight.x) // To the east half { if (TestPoint.y > TopLeft.y) // To the north east { return(TestPoint.Distance(new C2DPoint(BottomRight.x, TopLeft.y))); } else if (TestPoint.y < BottomRight.y) // To the south east { return(TestPoint.Distance(BottomRight)); } else { return(TestPoint.x - BottomRight.x); // To the east } } else if (TestPoint.x < TopLeft.x) // To the west half { if (TestPoint.y > TopLeft.y) // To the north west { return(TestPoint.Distance(TopLeft)); } else if (TestPoint.y < BottomRight.y) // To the south west { return(TestPoint.Distance(new C2DPoint(TopLeft.x, BottomRight.y))); } else { return(TopLeft.x - TestPoint.x); // To the west } } else { if (TestPoint.y > TopLeft.y) //To the north { return(TestPoint.y - TopLeft.y); } else if (TestPoint.y < BottomRight.y) // To the south { return(BottomRight.y - TestPoint.y); } } // assert(Contains(TestPoint)); return(0); // Inside }
/// <summary> /// Returns the distance from this to the point with this as a ray. /// </summary> /// <param name="TestPoint"></param> /// <param name="ptOnThis"></param> /// <returns></returns> public double DistanceAsRay(C2DPoint TestPoint, C2DPoint ptOnThis) { var vP1ToPoint = new C2DVector(point, TestPoint); // The projection is on the line var dFactorOnLine = vP1ToPoint.Dot(vector) / (vector.i * vector.i + vector.j * vector.j); ptOnThis.Set(point.x + vector.i * dFactorOnLine, point.y + vector.j * dFactorOnLine); return(TestPoint.Distance(ptOnThis)); }
/// <summary> /// Returns whether the point is in the shape. /// </summary> public bool Contains(C2DPoint TestPoint) { var ptCentre = new C2DPoint(GetCircleCentre()); if (TestPoint.Distance(ptCentre) > Arc.Radius) { return(false); } else { if (Arc.Line.IsOnRight(TestPoint)) { return(Arc.ArcOnRight); } else { return(!Arc.ArcOnRight); } } }
/// <summary> /// Sets the circle to be the maximum contained circle within the triangle. /// </summary> /// <param name="Triangle">The triangle to bound the circle.</param> public void SetInscribed(C2DTriangle Triangle) { C2DPoint InCen = Triangle.GetInCentre(); C2DLine Line = new C2DLine(Triangle.P1, Triangle.P2); C2DVector vec = new C2DVector(Line.point, InCen); double dProj = vec.Dot(Line.vector); double dLength = Line.vector.GetLength(); dProj /= dLength; double dFactor = dProj / dLength; C2DVector vProj = new C2DVector(Line.vector); vProj.Multiply(dFactor); C2DPoint ptOnLine = new C2DPoint(Line.point.x + vProj.i, Line.point.y + vProj.j); Set(InCen, InCen.Distance(ptOnLine)); }
/// <summary> /// Distance to a point. /// </summary> /// <param name="ptTest">The test point.</param> /// <param name="ptOnThis">Output. The closest point on the triangle.</param> public double Distance(C2DPoint ptTest, C2DPoint ptOnThis) { var dArea = GetAreaSigned(); var BTemp = true; // Construct the lines. var Line12 = new C2DLine(P1, P2); var Line23 = new C2DLine(P2, P3); var Line31 = new C2DLine(P3, P1); if (dArea == 0) { // Colinear so find the biggest line and return the distance from that var d1 = Line12.GetLength(); var d2 = Line23.GetLength(); var d3 = Line31.GetLength(); if (d1 > d2 && d1 > d3) { return(Line12.Distance(ptTest, ptOnThis)); } else if (d2 > d3) { return(Line23.Distance(ptTest, ptOnThis)); } else { return(Line31.Distance(ptTest, ptOnThis)); } } // Find out it the triangle is clockwise or not. var bClockwise = dArea < 0; // Set up some pointers to record the lines that the point is "above", "above" meaning that the // point is on the opposite side of the line to the rest of the triangle C2DLine LineAbove1 = null; C2DLine LineAbove2 = null; // Find out which Lines have the point above. if (Line12.IsOnRight(ptTest) ^ bClockwise) // if the pt is on the opposite side to the triangle { LineAbove1 = Line12; } if (Line23.IsOnRight(ptTest) ^ bClockwise) { if (LineAbove1 != null) { LineAbove2 = Line23; } else { LineAbove1 = Line23; } } if (Line31.IsOnRight(ptTest) ^ bClockwise) { if (LineAbove1 != null) { // We can't have all the lines with the point above. Debug.Assert(LineAbove2 != null); LineAbove2 = Line31; } else { LineAbove1 = Line31; } } // Check for containment (if there isn't a single line that its above then it must be inside) if (LineAbove1 == null) { // Pt inside so project onto all the lines and find the closest projection (there must be one). // Set up a record of the point projection on the lines. var ptOnLine = new C2DPoint(); var bSet = false; double dMinDist = 0; if (ptTest.ProjectsOnLine(Line12, ptOnLine, ref BTemp)) { dMinDist = ptTest.Distance(ptOnLine); ptOnThis.Set(ptOnLine); bSet = true; } if (ptTest.ProjectsOnLine(Line23, ptOnLine, ref BTemp)) { var dDist = ptTest.Distance(ptOnLine); if (!bSet || dDist < dMinDist) { dMinDist = dDist; ptOnThis.Set(ptOnLine); bSet = true; } } if (ptTest.ProjectsOnLine(Line31, ptOnLine, ref BTemp)) { var dDist = ptTest.Distance(ptOnLine); if (!bSet || dDist < dMinDist) { dMinDist = dDist; ptOnThis.Set(ptOnLine); bSet = true; } } Debug.Assert(bSet); return(-dMinDist); //-ve if inside } else if (LineAbove2 == null) { // it is only above 1 of the lines so simply return the distance to that line return(LineAbove1.Distance(ptTest, ptOnThis)); } else { // It's above 2 lines so first check them both for projection. Can only be projected on 1. // If the point can be projected onto the line then that's the closest point. var ptOnLine = new C2DPoint(); if (ptTest.ProjectsOnLine(LineAbove1, ptOnLine, ref BTemp)) { ptOnThis = ptOnLine; return(ptOnLine.Distance(ptTest)); } else if (ptTest.ProjectsOnLine(LineAbove2, ptOnLine, ref BTemp)) { ptOnThis = ptOnLine; return(ptOnLine.Distance(ptTest)); } else { // The point doesn't project onto either line so find the closest point if (LineAbove1 == Line12) { if (LineAbove2 == Line23) { ptOnThis = P2; return(ptTest.Distance(P2)); } else { ptOnThis = P1; return(ptTest.Distance(P1)); } } else { ptOnThis = P3; return(ptTest.Distance(P3)); } } } }
/// <summary> /// Distance to a point. /// </summary> /// <param name="ptTest">The test point.</param> /// <param name="ptOnThis">Output. The closest point on the triangle.</param> public double Distance(C2DPoint ptTest, C2DPoint ptOnThis) { double dArea = GetAreaSigned(); bool BTemp = true; // Construct the lines. C2DLine Line12 = new C2DLine(P1, P2); C2DLine Line23 = new C2DLine(P2, P3); C2DLine Line31 = new C2DLine(P3, P1); if (dArea == 0) { // Colinear so find the biggest line and return the distance from that double d1 = Line12.GetLength(); double d2 = Line23.GetLength(); double d3 = Line31.GetLength(); if (d1 > d2 && d1 > d3) return Line12.Distance(ptTest, ptOnThis); else if (d2 > d3) return Line23.Distance(ptTest, ptOnThis); else return Line31.Distance(ptTest, ptOnThis); } // Find out it the triangle is clockwise or not. bool bClockwise = dArea < 0; // Set up some pointers to record the lines that the point is "above", "above" meaning that the // point is on the opposite side of the line to the rest of the triangle C2DLine LineAbove1 = null; C2DLine LineAbove2 = null; // Find out which Lines have the point above. if ( Line12.IsOnRight( ptTest ) ^ bClockwise ) // if the pt is on the opposite side to the triangle LineAbove1 = Line12; if ( Line23.IsOnRight( ptTest ) ^ bClockwise) { if (LineAbove1 != null) LineAbove2 = Line23; else LineAbove1 = Line23; } if ( Line31.IsOnRight( ptTest ) ^ bClockwise) { if (LineAbove1 != null) { // We can't have all the lines with the point above. Debug.Assert(LineAbove2 != null); LineAbove2 = Line31; } else LineAbove1 = Line31; } // Check for containment (if there isn't a single line that its above then it must be inside) if (LineAbove1 == null) { // Pt inside so project onto all the lines and find the closest projection (there must be one). // Set up a record of the point projection on the lines. C2DPoint ptOnLine = new C2DPoint(); bool bSet = false; double dMinDist = 0; if (ptTest.ProjectsOnLine(Line12, ptOnLine, ref BTemp)) { dMinDist = ptTest.Distance(ptOnLine); ptOnThis.Set(ptOnLine); bSet = true; } if (ptTest.ProjectsOnLine(Line23, ptOnLine, ref BTemp)) { double dDist = ptTest.Distance(ptOnLine); if (!bSet || dDist < dMinDist) { dMinDist = dDist; ptOnThis.Set(ptOnLine); bSet = true; } } if (ptTest.ProjectsOnLine(Line31, ptOnLine, ref BTemp)) { double dDist = ptTest.Distance(ptOnLine); if (!bSet || dDist < dMinDist) { dMinDist = dDist; ptOnThis.Set(ptOnLine); bSet = true; } } Debug.Assert(bSet); return -dMinDist; //-ve if inside } else if (LineAbove2 == null) { // it is only above 1 of the lines so simply return the distance to that line return LineAbove1.Distance(ptTest, ptOnThis); } else { // It's above 2 lines so first check them both for projection. Can only be projected on 1. // If the point can be projected onto the line then that's the closest point. C2DPoint ptOnLine = new C2DPoint(); if (ptTest.ProjectsOnLine(LineAbove1, ptOnLine, ref BTemp)) { ptOnThis = ptOnLine; return ptOnLine.Distance(ptTest); } else if (ptTest.ProjectsOnLine(LineAbove2, ptOnLine, ref BTemp)) { ptOnThis = ptOnLine; return ptOnLine.Distance(ptTest); } else { // The point doesn't project onto either line so find the closest point if (LineAbove1 == Line12) { if (LineAbove2 == Line23) { ptOnThis = P2; return ptTest.Distance(P2); } else { ptOnThis = P1; return ptTest.Distance(P1); } } else { ptOnThis = P3; return ptTest.Distance(P3); } } } }
/// <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 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 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> /// Returns the distance from this to the point. /// </summary> /// <param name="TestPoint">The test pointt.</param> /// <param name="ptOnThis">Output. The closest point on this.</param> public override double Distance(C2DPoint TestPoint, C2DPoint ptOnThis) { C2DVector vP1ToPoint = new C2DVector(point, TestPoint); double dLength = GetLength(); double dProjLength = vP1ToPoint.Dot(vector); if (dProjLength < 0) { ptOnThis.Set(point); return TestPoint.Distance(point); } else { dProjLength = dProjLength / dLength; if (dProjLength < dLength) { // The projection is on the line double dFactorOnLine = dProjLength / dLength; C2DPoint PtOnLine = new C2DPoint(point.x + vector.i * dFactorOnLine, point.y + vector.j * dFactorOnLine); ptOnThis.Set(PtOnLine); return TestPoint.Distance(PtOnLine); } else { ptOnThis .Set(GetPointTo()); return TestPoint.Distance( GetPointTo() ); } } }
/// <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> /// Returns the distance from this to the other rect. 0 if there is an overlap. /// </summary> /// <param name="Other">Other rectangle.</param> public double Distance(C2DRect Other) { if (this.Overlaps(Other)) return 0; if (Other.GetLeft() > this.BottomRight.x) { // Other is to the right if (Other.GetBottom() > this.TopLeft.y) { // Other is to the top right C2DPoint ptTopRight = new C2DPoint(BottomRight.x, TopLeft.y); return ptTopRight.Distance(new C2DPoint(Other.GetLeft(), Other.GetBottom())); } else if (Other.GetTop() < this.BottomRight.y) { // Other to the bottom right return BottomRight.Distance( Other.TopLeft ); } else { // to the right return Other.GetLeft() - this.BottomRight.x; } } else if ( Other.GetRight() < this.TopLeft.x) { // Other to the left if (Other.GetBottom() > this.TopLeft.y) { // Other is to the top left return TopLeft.Distance(Other.BottomRight); } else if (Other.GetTop() < this.BottomRight.y) { // Other to the bottom left C2DPoint ptBottomLeft = new C2DPoint(TopLeft.x, BottomRight.y); return ptBottomLeft.Distance ( new C2DPoint( Other.GetRight(), Other.GetTop())); } else { //Just to the left return (this.TopLeft.x - Other.GetRight()); } } else { // There is horizontal overlap; if (Other.GetBottom() > TopLeft.y) return Other.GetBottom() - TopLeft.y; else return BottomRight.y - Other.GetTop(); } }
/// <summary> /// Returns the distance from this to the point. 0 if the point inside. /// </summary> /// <param name="TestPoint">Test Point.</param> public override double Distance(C2DPoint TestPoint) { if (TestPoint.x > BottomRight.x) // To the east half { if (TestPoint.y > TopLeft.y) // To the north east return TestPoint.Distance(new C2DPoint(BottomRight.x, TopLeft.y)); else if (TestPoint.y < BottomRight.y) // To the south east return TestPoint.Distance(BottomRight); else return (TestPoint.x - BottomRight.x); // To the east } else if (TestPoint.x < TopLeft.x) // To the west half { if (TestPoint.y > TopLeft.y) // To the north west return TestPoint.Distance(TopLeft); else if (TestPoint.y < BottomRight.y) // To the south west return TestPoint.Distance(new C2DPoint(TopLeft.x, BottomRight.y)); else return (TopLeft.x - TestPoint.x); // To the west } else { if (TestPoint.y > TopLeft.y) //To the north return (TestPoint.y - TopLeft.y); else if (TestPoint.y < BottomRight.y) // To the south return (BottomRight.y - TestPoint.y); } // assert(Contains(TestPoint)); return 0; // Inside }
/// <summary> /// Returns the distance from this to the point with this as a ray. /// </summary> /// <param name="TestPoint"></param> /// <param name="ptOnThis"></param> /// <returns></returns> public double DistanceAsRay(C2DPoint TestPoint, C2DPoint ptOnThis) { C2DVector vP1ToPoint = new C2DVector(point, TestPoint); // The projection is on the line double dFactorOnLine = vP1ToPoint.Dot(vector) / (vector.i * vector.i + vector.j * vector.j); ptOnThis.Set(point.x + vector.i * dFactorOnLine, point.y + vector.j * dFactorOnLine); return TestPoint.Distance(ptOnThis); }
/// <summary> /// Returns whether the point is in the shape. /// </summary> public bool Contains( C2DPoint TestPoint) { C2DPoint ptCentre = new C2DPoint(GetCircleCentre()); if (TestPoint.Distance(ptCentre) > Arc.Radius) return false; else { if (Arc.Line.IsOnRight(TestPoint)) { return Arc.ArcOnRight; } else { return !Arc.ArcOnRight; } } }
/// <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 corresponding circle's centre. /// </summary> public C2DPoint GetCircleCentre() { if (!IsValid() ) return new C2DPoint(0, 0); C2DPoint MidPoint = new C2DPoint(Line.GetMidPoint()); double dMinToStart = MidPoint.Distance( Line.point); double dMidToCentre = Math.Sqrt( Radius * Radius - dMinToStart * dMinToStart); C2DVector MidToCentre = new C2DVector(Line.vector); if ( CentreOnRight) MidToCentre.TurnRight(); else MidToCentre.TurnLeft(); MidToCentre.SetLength(dMidToCentre); return (MidPoint.GetPointTo(MidToCentre)); }