예제 #1
0
        /// <summary>
        /// Create a circle from three points.
        /// </summary>
        /// <param name="pt1">A point.</param>
        /// <param name="pt2">A point.</param>
        /// <param name="pt3">A point.</param>

        public Circle2D(Point2D pt1, Point2D pt2, Point2D pt3)
            : this(pt1.X, pt1.Y, pt2.X, pt2.Y, pt3.X, pt3.Y)
        {
        }
예제 #2
0
 /// <summary>
 /// Creates a new instance with the center at the given point and a radius of r.
 /// </summary>
 /// <param name="center">The center of the circle.</param>
 /// <param name="radius">The radius of the circle.</param>
 public Circle2D(Point2D center, decimal radius)
 {
     _center     = center;
     _radius     = 0m; // to satisfy compiler
     this.Radius = radius;
 }
예제 #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>
        public Point2D[] GetIntersectFast(ref LineSeg2D l)
        {
            decimal[] x      = new decimal[2];
            decimal   m      = 0m;
            decimal   b      = 0m;
            decimal   aCoeff = 0m;
            decimal   bCoeff = 0m;
            decimal   cCoeff = 0m;
            decimal   lineX  = 0m;
            decimal   t      = 0m;
            decimal   p      = 0m;
            decimal   q      = 0m;

            Point2D[] pts = null;



            if (!l.IsVertical)
            {
                // Circle    (x - h) ^ 2 + (y - k) ^ 2 = r ^ 2
                //   Center: (h, k)
                //   Radius: r
                // Line      y = m * x + b

                // (x - h) ^ 2 + (m * x + b - k) ^ 2 = r ^ 2
                // (x - h) * (x - h) + (m * x + b - k) * (m * x + b - k) = r^2
                // (x^2 - 2 * h * x + h^2) + (m^2 * x^2 + 2 * (b - k) * m * x + (b - k)^2 = r^2
                // (m^2 + 1) * x^2 + (2 * (b - k) * m - 2 * h) * x + (h^2 + (b - k)^2 - r^2) = 0

                m = l.Slope;
                b = l.YIntersect;

                aCoeff = DecimalEx.Pow(m, 2) + 1;
                bCoeff = 2 * (b - _center.Y) * m - 2 * _center.X;
                cCoeff = DecimalEx.Pow(_center.X, 2) + DecimalEx.Pow(b - _center.Y, 2) - DecimalEx.Pow(_radius, 2);

                x = DecimalEx.SolveQuadratic(aCoeff, bCoeff, cCoeff);

                if (x.Length == 0)
                {
                    return new Point2D[] { }
                }
                ;

                pts = new Point2D[x.Length];

                for (var i = 0; i <= x.Length - 1; i++)
                {
                    pts[i] = new Point2D(x[i], m * x[i] + b);
                }
            }
            else
            {
                // Circle    (x - h) ^ 2 + (y - k) ^ 2 = r ^ 2
                //   Center: (h, k)
                //   Radius: r
                // Line      x = lineX

                // Got the following from
                //  http://www.sonoma.edu/users/w/wilsonst/Papers/Geometry/circles/T1--2/T1-3-2.html
                //  http://www.sonoma.edu/users/w/wilsonst/Papers/Geometry/circles/default.html

                lineX = l.Pt1.X;
                t     = _radius * _radius - (lineX - _center.X) * (lineX - _center.X);


                if (t < 0)
                {
                    return(new Point2D[] { });
                }
                else
                {
                    p = _center.Y + DecimalEx.Sqrt(t);
                    q = _center.Y - DecimalEx.Sqrt(t);

                    pts    = new Point2D[1];
                    pts[0] = new Point2D(lineX, p);

                    // NOTE that P=Q when t=0
                    if (p != q)
                    {
                        Array.Resize(ref pts, 2);
                        pts[1] = new Point2D(lineX, q);
                    }
                }
            }

            return(pts);
        }
예제 #4
0
 /// <summary>
 /// Returns distance to the given point from the circle. If the
 /// point is on the circle, distance is 0. If the point is inside
 /// the circle, the distance is expressed as a negative number
 /// whose absolute value is the distance from the outside of the circle.
 /// </summary>
 /// <param name="pt">The point to get distance to.</param>
 public decimal DistanceTo(Point2D pt)
 {
     return(Center.DistanceTo(pt) - Radius);
 }
예제 #5
0
 /// <summary>
 /// Creates a new instance with the center at (x, y) and a radius of r.
 /// </summary>
 /// <param name="x">The X component of the center.</param>
 /// <param name="y">The Y component of the center.</param>
 /// <param name="radius">The radius of the circle.</param>
 public Circle2D(decimal x, decimal y, decimal radius)
 {
     _center     = new Point2D(x, y);
     _radius     = 0m; // to satisfy compiler
     this.Radius = radius;
 }
예제 #6
0
 public static  Circle2D[] FromTwoPointsAndRadius(Point2D pt1, Point2D pt2, decimal radius)
 {
     return(FromTwoPointsAndRadius(pt1.X, pt1.Y, pt2.X, pt2.Y, radius));
 }
예제 #7
0
 /// <summary>
 /// Creates a new instance with the center at the origin with the provided radius.
 /// </summary>
 /// <param name="radius">The radius of the circle.</param>
 public Circle2D(decimal radius)
 {
     _center     = Point2D.Origin;
     _radius     = 0m; // to satisfy compiler
     this.Radius = radius;
 }
예제 #8
0
        /// <summary>
        /// Gets the points of intersection between this circle and another circle.
        /// </summary>
        /// <param name="other">The other circle.</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>
        /// <param name="impreciseResult">Which value to return for an imprecise result,
        /// i.e. tangency determined by rounding. If positive, returns the point on the larger circle. If
        /// negative, returns the point on the smaller circle. If 0, returns the midpoint between these
        /// two points.</param>
        public Point2D[] GetIntersect(Circle2D other, int decimals = -1, int impreciseResult = 0)
        {
            Vector2D meToOtherVector = default(Vector2D);

            meToOtherVector = this.Center.GetVectorTo(other.Center);


            if (decimals >= 0)
            {
                // The only intersection decision that can be made to a given precision is whether
                // the two circles are tangent to each other, either internally or externally.


                if (this.IsTangentTo(other, decimals))
                {
                    // If the smaller circle is inside the other, then the smaller is
                    // considered internally tangent to the larger.

                    if ((this.Radius < other.Radius && this.IsInside(other, decimals)) || (other.Radius < this.Radius && other.IsInside(this, decimals)))
                    {
                        // Internal tangent

                        Point2D pointOnLargeCircle = default(Point2D);
                        Point2D pointOnSmallCircle = default(Point2D);

                        // Vectors to the two tangent points are both pointing in the same
                        // direction--from the center of the larger circle towards the
                        // center of the smaller circle. Their magnitude is the same as the
                        // radius of the circle whose center they start from.


                        if (this.Radius > other.Radius)
                        {
                            // Go from center of larger circle, Me, to smaller circle, other.
                            pointOnLargeCircle = this.Center + new Vector2D(meToOtherVector, this.Radius);
                            pointOnSmallCircle = other.Center + new Vector2D(meToOtherVector, other.Radius);
                        }
                        else
                        {
                            // Go from center of larger circle, other, to smaller circle, Me.
                            pointOnLargeCircle = other.Center - new Vector2D(meToOtherVector, other.Radius);
                            pointOnSmallCircle = this.Center - new Vector2D(meToOtherVector, this.Radius);
                        }


                        if (impreciseResult > 0)
                        {
                            // Point on larger
                            return(new Point2D[] { pointOnLargeCircle });
                        }
                        else if (impreciseResult < 0)
                        {
                            // Point on smaller
                            return(new Point2D[] { pointOnSmallCircle });
                        }
                        else
                        {
                            // Split difference
                            LineSeg2D l = new LineSeg2D(pointOnLargeCircle, pointOnSmallCircle);
                            return(new Point2D[] { l.MidPoint });
                        }
                    }
                    else
                    {
                        // External tangent

                        Point2D pointOnMe    = default(Point2D);
                        Point2D pointOnOther = default(Point2D);

                        // Vectors to the two tangent points are simply pointing at the other
                        // circle's center with a magnitude of the radius of the circle whose
                        // center it originates in.
                        pointOnMe    = this.Center + new Vector2D(meToOtherVector, this.Radius);
                        pointOnOther = other.Center - new Vector2D(meToOtherVector, other.Radius);


                        if (impreciseResult > 0)
                        {
                            // Point on larger
                            return(new Point2D[] { (this.Radius > other.Radius ? pointOnMe : pointOnOther) });
                        }
                        else if (impreciseResult < 0)
                        {
                            // Point on smaller
                            return(new Point2D[] { (this.Radius < other.Radius ? pointOnMe : pointOnOther) });
                        }
                        else
                        {
                            if (pointOnMe == pointOnOther)
                            {
                                return(new Point2D[] { pointOnMe });
                            }
                            else
                            {
                                // Split difference
                                return(new Point2D[] { new LineSeg2D(pointOnMe, pointOnOther).MidPoint });
                            }
                        }
                    }
                }
            }

            // Detect situations where two points touch
            decimal  a                 = 0m;
            decimal  h                 = 0m;
            decimal  r2mina2           = 0m;
            Vector2D vToIntersectMidPt = default(Vector2D);
            Vector2D vToIntersect1     = default(Vector2D);

            // The following two equations are from:
            //   http://paulbourke.net/geometry/2circle/
            a = (DecimalEx.Pow(meToOtherVector.Magnitude, 2) - DecimalEx.Pow(other.Radius, 2) + DecimalEx.Pow(this.Radius, 2)) / (2 * meToOtherVector.Magnitude);

            r2mina2 = DecimalEx.Pow(this.Radius, 2) - DecimalEx.Pow(a, 2);

            // No intersection points -- one circle is inside or outside the other
            if (r2mina2 < 0)
            {
                return new Point2D[] { }
            }
            ;

            vToIntersectMidPt           = new Vector2D(this.Center, other.Center);
            vToIntersectMidPt.Magnitude = a;


            if (r2mina2 == 0)
            {
                // Only one intersection point
                return(new Point2D[] { this.Center + vToIntersectMidPt });
            }

            h                       = DecimalEx.Sqrt(r2mina2);
            vToIntersect1           = vToIntersectMidPt.GetPerpendicular();
            vToIntersect1.Magnitude = h;

            return(new Point2D[] {
                this.Center + vToIntersectMidPt + vToIntersect1,
                this.Center + vToIntersectMidPt - vToIntersect1
            });
        }