Пример #1
0
        /// <summary>
        /// Creates an arc with the given center, start, and end points. Performs a check
        /// at the given precision to make sure that both the start and end points are
        /// the same distance from the center, throwing an exception if they're not. Note
        /// that because radius is generated from start point, the resultant arc's start
        /// point will be more accurate than the end point.
        /// </summary>
        /// <param name="center">Center of the arc.</param>
        /// <param name="startPoint">Start point of the arc.</param>
        /// <param name="endPoint">Point that end angle is projected through.</param>
        /// <param name="decimals">Precision at which to check the distance of the endpoints to the center.
        /// A negative value will perform an exact check.</param>

        public Arc2D(Point2D center, Point2D startPoint, Point2D endPoint, int decimals = 15)
            : this(center, center.DistanceTo(startPoint), 0, 0)
        {
            if ((decimals < 0 && center.DistanceTo(endPoint) != Radius) || (decimals >= 0 && center.DistanceTo(endPoint).RoundFromZero(decimals) != Radius.RoundFromZero(decimals)))
            {
                throw new Exception("Can't create arc from center and endpoints because endpoints have different distances from the center!");
            }

            _startAngle = Circle.AngleThroughPoint(startPoint);
            _endAngle   = Circle.AngleThroughPoint(endPoint);
        }
Пример #2
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])
            });
        }
Пример #3
0
        /// <summary>
        /// Returns the point on the line segment closest to the given point. Can also
        /// return the closest point on the line through the line segment.
        /// </summary>
        /// <param name="pt">A 2D point.</param>
        /// <param name="treatLineSegmentAsLine">If True, will return closest point on
        /// the line through the line segment even if it doesn't lie on the segment
        /// itself. If False, will find the closest point on the segment itself.</param>
        public Point2D ClosestPointTo(Point2D pt, bool treatLineSegmentAsLine = false)
        {
            _CheckIsValid();

            LineSeg2D l   = default(LineSeg2D);
            Point2D   ret = default(Point2D);

            if (this.IsHorizontal)
            {
                ret = new Point2D(pt.X, this.Pt1.Y);
            }
            else
            {
                l   = FromPointSlope(pt, this.PerpendicularSlope);
                ret = this.GetIntersect(l, true).Value;
            }

            if (!treatLineSegmentAsLine && !this.IsInBounds(ret))
            {
                if (pt.DistanceTo(Pt1) < pt.DistanceTo(Pt2))
                {
                    ret = Pt1;
                }
                else
                {
                    ret = Pt2;
                }
            }

            return(ret);

            //' Alt method using vector project
            //'   http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html
            //Dim v As Vector2D
            //Dim r As Vector2D
            //Dim proj As Vector2D
            //Dim ret As XYPoint

            //v = New Vector2D(Pt2.Y - Pt1.Y, -(Pt2.X - Pt1.X))
            //r = New Vector2D(Pt1.X - pt.X, Pt1.Y - pt.Y)
            //proj = r.ProjectOnto(v)
            //ret = pt + proj
            //' End alt method

            //' Alt method using vectors
            //'   http://www.gamedev.net/community/forums/topic.asp?topic_id=198199&whichpage=1&#1250842
            //' Not used because of round off problems that affect precision.
            //Dim d As Decimal
            //Dim t As Decimal
            //Dim aToB As Vector2D
            //Dim aToPt As Vector2D

            //aToB = (New Vector2D(Pt1, Pt2)).Normalize
            //aToPt = New Vector2D(Pt1, pt)
            //d = Me.Length
            //t = aToB.Dot(aToPt)

            //If Not treatLineSegmentAsLine Then
            //    If t < 0 Then
            //        ret = Pt1
            //    ElseIf t > d Then
            //        ret = Pt2
            //    Else
            //        ret = Pt1 + aToB * t
            //    End If
            //Else
            //    If Not (Pt1 + aToB * t).Equals(ret, 23) Then Stop
            //    ret = Pt1 + aToB * t
            //End If
            //' End alt method
        }
Пример #4
0
 /// <summary>
 /// Finds the closest distance between a point and this line segment or
 /// the line through this line segment.
 /// </summary>
 /// <param name="pt">A 2D point.</param>
 /// <param name="treatLineSegmentAsLine">If True, will return distance to closest
 /// point on the line through the line segment. If False, will return distance to the
 /// closest point on the segment itself.</param>
 public decimal DistanceTo(Point2D pt, bool treatLineSegmentAsLine = false)
 {
     return(pt.DistanceTo(this.ClosestPointTo(pt, treatLineSegmentAsLine)));
 }