public static bool PointsAreColinear(decimal x1, decimal y1, decimal x2, decimal y2, decimal x3, decimal y3) { var l1 = new LineSeg2D(x1, y1, x2, y2); var l2 = new LineSeg2D(x2, y2, x3, y3); var intersect = l1.GetIntersect(l2, true); // Points won't have an intersection if they are parallel. If they // are parallel and share a point, then they are colinear. return(!intersect.HasValue); }
/// <summary> /// Creates a circle from three points. /// </summary> /// <param name="x1">A number.</param> /// <param name="y1">A number.</param> /// <param name="x2">A number.</param> /// <param name="y2">A number.</param> /// <param name="x3">A number.</param> /// <param name="y3">A number.</param> /// <remarks>See http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=geometry2#circle</remarks> public Circle2D(decimal x1, decimal y1, decimal x2, decimal y2, decimal x3, decimal y3) { _radius = 0m; // to satisfy compiler _center = default(Point2D); // to satisfy compiler if (Point2D.PointsAreColinear(x1, y1, x2, y2, x3, y3)) { throw new Exception("Can't create circle! Points are colinear."); } LineSeg2D l1 = new LineSeg2D(x1, y1, x2, y2).PerpendicularBisector(); LineSeg2D l2 = new LineSeg2D(x2, y2, x3, y3).PerpendicularBisector(); Point2D? intersect = l1.GetIntersect(l2, true); if (intersect == null) { // Should never get null here because lines won't be parallel so // long as they aren't colinear which we checked for above. throw new Exception("Something bad happened. Should have found an intersect so long as points are not colinear."); } Center = intersect.Value; Radius = intersect.Value.DistanceTo(x1, y1); }
/// <summary> /// Gets the points of intersection between this circle and the line which /// contains the given line segment. /// </summary> /// <param name="l">Line segment used to determine line equation.</param> /// <param name="decimals">Determines rounding that should be performed when determining /// if line intersection happens on zero, one, or two points. Default is -1 for /// no rounding.</param> public Point2D[] GetIntersect(LineSeg2D l, int decimals = -1) { LineSeg2D centToLine = default(LineSeg2D); decimal centToLineLength = 0m; decimal centToLineLengthForComp = 0m; decimal radiusForComp = 0m; if (l.IsHorizontal) { // The center to any horizontal line is a vertical line through // the center of the circle. centToLine = new LineSeg2D(this.Center, this.Center + new Vector2D(0, 1)); } else { centToLine = LineSeg2D.FromPointSlope(this.Center, l.PerpendicularSlope); } centToLine.Pt2 = l.GetIntersect(centToLine, true).Value; centToLineLength = centToLine.Length; // Get numbers for comparison, rounding if necessary centToLineLengthForComp = centToLineLength; radiusForComp = _radius; if (decimals >= 0) { centToLineLengthForComp = centToLineLengthForComp.RoundFromZero(decimals); radiusForComp = radiusForComp.RoundFromZero(decimals); } // See if line is outside of circle if (centToLineLengthForComp > radiusForComp) { return(new Point2D[] { }); } // See if line is tangent to circle if (centToLineLengthForComp == radiusForComp) { return(new Point2D[] { centToLine.Pt2 }); } // Line must intersect in two places Vector2D vCentToChord = default(Vector2D); decimal halfChord = 0m; // Get a vector from the center to the intersecting chord vCentToChord = centToLine.GetVectorP1toP2(); if (vCentToChord.Magnitude == 0) { Vector2D offsetVector = default(Vector2D); // Line goes through circle center if (l.IsVertical) { // Slope undefined so just go up the length of the radius offsetVector = new Vector2D(0, _radius); } else { offsetVector = new Vector2D(_radius * DecimalEx.Cos(DecimalEx.ATan(l.Slope)), _radius * DecimalEx.Sin(DecimalEx.ATan(l.Slope))); } return(new Point2D[] { this.Center + offsetVector, this.Center - offsetVector }); } else { Vector2D vChord = default(Vector2D); // Get a vector along the chord vChord = vCentToChord.GetPerpendicular(); // Determine the length of half the chord halfChord = RightTriangle.GetSideFromSideHyp(centToLineLength, _radius); // Set the magnitude of the vector along the chord // to be half the chord length vChord.Magnitude = halfChord; // The two intersecting points are points translated // from the center of the circle to the chord (+vCentToChord) // and then translated to the ends of the chord (+-vChord) return(new Point2D[] { this.Center + vCentToChord + vChord, this.Center + vCentToChord - vChord }); } }