/// <summary> /// Returns the closest point on the polyline to the given point. /// </summary> /// <param name="p">a point</param> /// <returns>A point which is the closest to the given point but still on the line.</returns> public Point2D ClosestPointTo(Point2D p) { var minError = double.MaxValue; var closest = default(Point2D); for (var i = 0; i < this.VertexCount - 1; i++) { var segment = new LineSegment2D(this.points[i], this.points[i + 1]); var projected = segment.ClosestPointTo(p); var error = p.DistanceTo(projected); if (error < minError) { minError = error; closest = projected; } } return(closest); }
/// <summary> /// Creates a <see cref="Circle2D"/> circle from three points which lie along its circumference. /// Points may not be collinear /// </summary> /// <param name="pointA">The first point on the circle.</param> /// <param name="pointB">The second point on the circle.</param> /// <param name="pointC">The third point on the circle.</param> /// <returns>A Circle which is defined by the three specified points</returns> /// <exception cref="ArgumentException">An exception is thrown if no possible circle can be formed from the points</exception> public static Circle2D FromPoints(Point2D pointA, Point2D pointB, Point2D pointC) { // ReSharper disable InconsistentNaming var midpointAB = Point2D.MidPoint(pointA, pointB); var midpointBC = Point2D.MidPoint(pointB, pointC); var gradientAB = (pointB.Y - pointA.Y) / (pointB.X - pointA.X); var gradientBC = (pointC.Y - pointB.Y) / (pointC.X - pointB.X); var gradientl1 = -1 / gradientAB; var gradientl2 = -1 / gradientBC; // ReSharper restore InconsistentNaming var denominator = gradientl2 - gradientl1; var nominator = midpointAB.Y - (gradientl1 * midpointAB.X) + (gradientl2 * midpointBC.X) - midpointBC.Y; var centerX = nominator / denominator; var centerY = (gradientl1 * (centerX - midpointAB.X)) + midpointAB.Y; var center = new Point2D(centerX, centerY); if (double.IsNaN(center.X) || double.IsNaN(center.Y) || double.IsInfinity(center.X) || double.IsInfinity(center.Y)) { throw new ArgumentException("Points cannot form a circle, are they collinear?"); } return(new Circle2D(center, center.DistanceTo(pointA))); }