예제 #1
0
        /// <summary>
        /// Gets the two line segments that start at the given point and terminate
        /// on the circle and are tangent to the circle.
        /// </summary>
        /// <param name="point">The point for the tangent segments to go through.</param>
        /// <remarks>
        /// Got strategy from Wikipedia's description involving Thale's theorem.
        /// http://en.wikipedia.org/wiki/Tangent_lines_to_circles
        /// </remarks>
        public         LineSeg2D[] TangentsThroughPoint(Point2D point)
        {
            Circle2D intersectingCircle = default(Circle2D);

            Point2D[] intersects = null;

            if (point.DistanceTo(this.Center) <= this.Radius)
            {
                return(null);
            }

            intersectingCircle = new Circle2D(this.Center, point);

            intersects = this.GetIntersect(intersectingCircle);
            if (intersects.Length != 2)
            {
                throw new Exception("Unexpected number of intersects when getting tangents through a point.");
            }

            return(new LineSeg2D[] {
                new LineSeg2D(point, intersects[0]),
                new LineSeg2D(point, intersects[1])
            });
        }
예제 #2
0
 /// <summary>
 /// Creates an arc based on another arc, but with a different radius.
 /// </summary>
 /// <param name="a">An arc from which to take the center and start/end angles.</param>
 /// <param name="radius">A radius for the new arc.</param>
 public Arc2D(Arc2D a, decimal radius)
 {
     Circle      = new Circle2D(a.Center, radius);
     _startAngle = a._startAngle;
     _endAngle   = a._endAngle;
 }
예제 #3
0
        /// <summary>
        /// Creates an arc on the given circle with the start angle projected through
        /// the start point and the end angle projected through the end point.
        /// </summary>
        /// <param name="c">Circle that the arc lies on.</param>
        /// <param name="startPoint">Point that start angle is projected through.</param>
        /// <param name="endPoint">Point that end angle is projected through.</param>

        public Arc2D(Circle2D c, Point2D startPoint, Point2D endPoint)
        {
            this.Circle = c;
            _startAngle = c.AngleThroughPoint(startPoint);
            _endAngle   = c.AngleThroughPoint(endPoint);
        }
예제 #4
0
 /// <summary>
 /// Creates an arc centered on the given point with the specified radius and start/end angle.
 /// </summary>
 /// <param name="center">Center of the arc.</param>
 /// <param name="radius">Radius of the arc.</param>
 /// <param name="startAngle">Start angle.</param>
 /// <param name="endAngle">End angle.</param>
 public Arc2D(Point2D center, decimal radius, decimal startAngle, decimal endAngle)
 {
     this.Circle = new Circle2D(center, radius);
     _startAngle = startAngle;
     _endAngle   = endAngle;
 }
예제 #5
0
 /// <summary>
 /// Creates an arc centered at (0,0) with the given radius and start/end angle.
 /// </summary>
 /// <param name="radius">Radius of the arc.</param>
 /// <param name="startAngle">Start angle.</param>
 /// <param name="endAngle">End angle.</param>
 public Arc2D(decimal radius, decimal startAngle, decimal endAngle)
 {
     this.Circle = new Circle2D(0, 0, radius);
     _startAngle = startAngle;
     _endAngle   = endAngle;
 }
예제 #6
0
 /// <summary>
 /// Creates and arc with the given circle and start/end angle.
 /// </summary>
 /// <param name="c">The circle that the arc lies on.</param>
 /// <param name="startAngle">Start angle.</param>
 /// <param name="endAngle">End angle.</param>
 public Arc2D(Circle2D c, decimal startAngle, decimal endAngle)
 {
     this.Circle = c;
     _startAngle = startAngle;
     _endAngle   = endAngle;
 }
예제 #7
0
 public decimal DistanceTo(Circle2D c)
 {
     return(c.DistanceTo(this));
 }
예제 #8
0
        public         Point2D[] GetIntersect(Circle2D c, int decimals = -1)
        {
            _CheckIsValid();

            return(c.GetIntersect(this, decimals));
        }
예제 #9
0
 /// <summary>
 /// Returns circles that are tangent to another circle and line.
 /// </summary>
 /// <param name="line">Line that returned circles should be tangent to.</param>
 /// <param name="circle">Circle that returned circles should be tangent to.</param>
 /// <param name="radius">Radius of new circles.</param>
 /// <returns>External tangent circles are listed first.</returns>
 public static  Circle2D[] FromTangentTangentRadius(LineSeg2D line, Circle2D circle, decimal radius)
 {
     return(FromTangentTangentRadius(circle, line, radius));
 }
예제 #10
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
            });
        }