/// <summary> /// Computes the centre of the circumcircle of this vertex and two others. /// </summary> /// <param name="b" /> /// <param name="c" /> /// <returns>the Coordinate which is the circumcircle of the 3 points.</returns> public Vertex CircleCenter(Vertex b, Vertex c) { var a = new Vertex(X, Y); // compute the perpendicular bisector of cord ab var cab = Bisector(a, b); // compute the perpendicular bisector of cord bc var cbc = Bisector(b, c); // compute the intersection of the bisectors (circle radii) var hcc = new HCoordinate(cab, cbc); Vertex cc = null; try { cc = new Vertex(hcc.GetX(), hcc.GetY()); } catch (NotRepresentableException nre) { #if !PCL Debug.WriteLine("a: " + a + " b: " + b + " c: " + c); Debug.WriteLine(nre); #endif //throw; } return(cc); }
/// <summary> /// Computes the (approximate) intersection point between two line segments /// using homogeneous coordinates. /// Note that this algorithm is /// not numerically stable; i.e. it can produce intersection points which /// lie outside the envelope of the line segments themselves. In order /// to increase the precision of the calculation input points should be normalized /// before passing them to this routine. /// </summary> /// <param name="p1"></param> /// <param name="p2"></param> /// <param name="q1"></param> /// <param name="q2"></param> /// <returns></returns> public static ICoordinate Intersection(ICoordinate p1, ICoordinate p2, ICoordinate q1, ICoordinate q2) { HCoordinate l1 = new HCoordinate(new HCoordinate(p1), new HCoordinate(p2)); HCoordinate l2 = new HCoordinate(new HCoordinate(q1), new HCoordinate(q2)); HCoordinate intHCoord = new HCoordinate(l1, l2); ICoordinate intPt = intHCoord.Coordinate; return intPt; }
///<summary> /// Computes the line which is the perpendicular bisector of the ///</summary> /// <param name="a">A point</param> /// <param name="b">Another point</param> /// <returns>The perpendicular bisector, as an HCoordinate line segment a-b.</returns> public static HCoordinate PerpendicularBisector(Coordinate a, Coordinate b) { // returns the perpendicular bisector of the line segment ab double dx = b.X - a.X; double dy = b.Y - a.Y; HCoordinate l1 = new HCoordinate(a.X + dx / 2.0, a.Y + dy / 2.0, 1.0); HCoordinate l2 = new HCoordinate(a.X - dy + dx / 2.0, a.Y + dx + dy / 2.0, 1.0); return new HCoordinate(l1, l2); }
///<summary> /// Computes the line which is the perpendicular bisector of the ///</summary> /// <param name="a">A point</param> /// <param name="b">Another point</param> /// <returns>The perpendicular bisector, as an HCoordinate line segment a-b.</returns> public static HCoordinate PerpendicularBisector(Coordinate a, Coordinate b) { // returns the perpendicular bisector of the line segment ab double dx = b.X - a.X; double dy = b.Y - a.Y; HCoordinate l1 = new HCoordinate(a.X + dx / 2.0, a.Y + dy / 2.0, 1.0); HCoordinate l2 = new HCoordinate(a.X - dy + dx / 2.0, a.Y + dx + dy / 2.0, 1.0); return(new HCoordinate(l1, l2)); }
/// <summary> /// Computes the intersection point of the lines defined by two segments, if there is one. /// </summary> /// <remarks> /// There may be 0, 1 or an infinite number of intersection points between two lines. /// If there is a unique intersection point, it is returned. /// Otherwise, <c>null</c> is returned. /// If more information is required about the details of the intersection, /// the <see cref="RobustLineIntersector"/> class should be used. /// </remarks> /// <param name="line">A line segment defining a straight line</param> /// <returns>An intersection point, or <c>null</c> if there is none or an infinite number</returns> /// <seealso cref="RobustLineIntersector"/> public Coordinate LineIntersection(LineSegment line) { try { var intPt = HCoordinate.Intersection(_p0, _p1, line._p0, line._p1); return(intPt); } catch (NotRepresentableException ex) { // eat this exception, and return null; } return(null); }
/// <summary> /// Adds a mitre join connecting the two reflex offset segments. /// The mitre will be beveled if it exceeds the mitre ratio limit. /// </summary> /// <param name="p"></param> /// <param name="offset0">The first offset segment</param> /// <param name="offset1">The second offset segment</param> /// <param name="distance">The offset distance</param> private void AddMitreJoin(Coordinate p, LineSegment offset0, LineSegment offset1, double distance) { bool isMitreWithinLimit = true; Coordinate intPt; /** * This computation is unstable if the offset segments are nearly collinear. * However, this situation should have been eliminated earlier by the check for * whether the offset segment endpoints are almost coincident */ try { intPt = HCoordinate.Intersection(offset0.P0, offset0.P1, offset1.P0, offset1.P1); double mitreRatio = distance <= 0.0 ? 1.0 : intPt.Distance(p) / Math.Abs(distance); if (mitreRatio > _bufParams.MitreLimit) { isMitreWithinLimit = false; } } catch (NotRepresentableException ex) { intPt = new Coordinate(0, 0); isMitreWithinLimit = false; } if (isMitreWithinLimit) { _segList.AddPt(intPt); } else { AddLimitedMitreJoin(offset0, offset1, distance, _bufParams.MitreLimit); // addBevelJoin(offset0, offset1); } }
/// <summary> /// Calculate the intermediate coordinate /// </summary> private void CalculateIntermediate() { double angle = Base.Angle + MathSE.HalfPI; try { // Interaction calculation using cross products var a = Base.Start; var b = Base.End; var c = Coordinate.NewAtDistanceAngleFrom(End, 50, angle); var d = Coordinate.NewAtDistanceAngleFrom(End, 50, angle + Math.PI); var l1 = new HCoordinate(a).HCross(new HCoordinate(b)); var l2 = new HCoordinate(c).HCross(new HCoordinate(d)); Intermediate = new Coordinate(l1.HCross(l2)); } catch { // Backstop in case of not being able to calculate the intersection point Intermediate = Start; } }
///<summary>Computes the circumcentre of a triangle.</summary> /// <remarks> /// The circumcentre is the centre of the circumcircle, /// the smallest circle which encloses the triangle. /// It is also the common intersection point of the /// perpendicular bisectors of the sides of the triangle, /// and is the only point which has equal distance to all three /// vertices of the triangle. /// </remarks> /// <param name="a">A vertex of the triangle</param> /// <param name="b">A vertex of the triangle</param> /// <param name="c">A vertex of the triangle</param> /// <returns>The circumcentre of the triangle</returns> public static Coordinate Circumcentre(Coordinate a, Coordinate b, Coordinate c) { // compute the perpendicular bisector of chord ab HCoordinate cab = PerpendicularBisector(a, b); // compute the perpendicular bisector of chord bc HCoordinate cbc = PerpendicularBisector(b, c); // compute the intersection of the bisectors (circle radii) HCoordinate hcc = new HCoordinate(cab, cbc); Coordinate cc; try { cc = new Coordinate(hcc.GetX(), hcc.GetY()); } catch (NotRepresentableException ex) { // MD - not sure what we can do to prevent this (robustness problem) // Idea - can we condition which edges we choose? throw new InvalidOperationException(ex.Message); } return(cc); }
/// <summary> /// Computes the centre of the circumcircle of this vertex and two others. /// </summary> /// <param name="b" /> /// <param name="c" /> /// <returns>the Coordinate which is the circumcircle of the 3 points.</returns> public Vertex CircleCenter(Vertex b, Vertex c) { Vertex a = new Vertex(this.X, this.Y); // compute the perpendicular bisector of cord ab HCoordinate cab = Bisector(a, b); // compute the perpendicular bisector of cord bc HCoordinate cbc = Bisector(b, c); // compute the intersection of the bisectors (circle radii) HCoordinate hcc = new HCoordinate(cab, cbc); Vertex cc = null; try { cc = new Vertex(hcc.GetX(), hcc.GetY()); } catch (NotRepresentableException nre) { System.Console.WriteLine("a: " + a + " b: " + b + " c: " + c); System.Console.WriteLine(nre); } return(cc); }
/// <summary> /// /// </summary> /// <param name="p1"></param> /// <param name="p2"></param> public HCoordinate(HCoordinate p1, HCoordinate p2) { x = p1.y * p2.w - p2.y * p1.w; y = p2.x * p1.w - p1.x * p2.w; w = p1.x * p2.y - p2.x * p1.y; }
/// <summary> /// /// </summary> /// <param name="p1"></param> /// <param name="p2"></param> public HCoordinate(HCoordinate p1, HCoordinate p2) { _x = p1._y * p2._w - p2._y * p1._w; _y = p2._x * p1._w - p1._x * p2._w; _w = p1._x * p2._y - p2._x * p1._y; }
///<summary>Computes the circumcentre of a triangle.</summary> /// <remarks> /// The circumcentre is the centre of the circumcircle, /// the smallest circle which encloses the triangle. /// It is also the common intersection point of the /// perpendicular bisectors of the sides of the triangle, /// and is the only point which has equal distance to all three /// vertices of the triangle. /// </remarks> /// <param name="a">A vertex of the triangle</param> /// <param name="b">A vertex of the triangle</param> /// <param name="c">A vertex of the triangle</param> /// <returns>The circumcentre of the triangle</returns> public static Coordinate Circumcentre(Coordinate a, Coordinate b, Coordinate c) { // compute the perpendicular bisector of chord ab HCoordinate cab = PerpendicularBisector(a, b); // compute the perpendicular bisector of chord bc HCoordinate cbc = PerpendicularBisector(b, c); // compute the intersection of the bisectors (circle radii) HCoordinate hcc = new HCoordinate(cab, cbc); Coordinate cc; try { cc = new Coordinate(hcc.GetX(), hcc.GetY()); } catch (NotRepresentableException ex) { // MD - not sure what we can do to prevent this (robustness problem) // Idea - can we condition which edges we choose? throw new InvalidOperationException(ex.Message); } return cc; }