示例#1
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
                });
            }
        }
示例#2
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
            });
        }