예제 #1
0
        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);
        }
예제 #2
0
        /// <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);
        }
예제 #3
0
        /// <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
                });
            }
        }