/// <summary> /// Calculates the distance from the path. /// </summary> /// <param name="point">The point.</param> /// <returns>Returns the distance from the path</returns> public PointInfo DistanceFromPath(PointF point) { PointInfoInternal internalInfo = default; internalInfo.DistanceSquared = float.MaxValue; // Set it to max so that CalculateShorterDistance can reduce it back down int polyCorners = this.points.Length; if (!this.closedPath) { polyCorners -= 1; } int closestPoint = 0; for (int i = 0; i < polyCorners; i++) { int next = i + 1; if (this.closedPath && next == polyCorners) { next = 0; } if (this.CalculateShorterDistance(this.points[i].Point, this.points[next].Point, point, ref internalInfo)) { closestPoint = i; } } return new PointInfo { DistanceAlongPath = this.points[closestPoint].TotalLength + Vector2.Distance(this.points[closestPoint].Point, internalInfo.PointOnLine), DistanceFromPath = MathF.Sqrt(internalInfo.DistanceSquared), SearchPoint = point, ClosestPointOnPath = internalInfo.PointOnLine }; }
/// <summary> /// Calculates the distance from the path. /// </summary> /// <param name="point">The point.</param> /// <returns>Returns the distance from the path</returns> public PointInfo DistanceFromPath(PointF point) { if (IsDisposed) { throw new ObjectDisposedException(nameof(InternalPath)); } PointInfoInternal internalInfo = default; internalInfo.DistanceSquared = float.MaxValue; // Set it to max so that CalculateShorterDistance can reduce it back down int polyCorners = _points.Count; if (!closedPath) { polyCorners -= 1; } int closestPoint = 0; for (int i = 0; i < polyCorners; i++) { int next = i + 1; if (closedPath && next == polyCorners) { next = 0; } if (CalculateShorterDistance(_points[i].Point, _points[next].Point, point, ref internalInfo)) { closestPoint = i; } } return(new PointInfo { DistanceAlongPath = _points[closestPoint].TotalLength + Vector2.Distance(_points[closestPoint].Point, internalInfo.PointOnLine), DistanceFromPath = (float)Math.Sqrt(internalInfo.DistanceSquared), SearchPoint = point, ClosestPointOnPath = internalInfo.PointOnLine }); }
/// <summary> /// Calculate any shorter distances along the path. /// </summary> /// <param name="start">The start position.</param> /// <param name="end">The end position.</param> /// <param name="point">The current point.</param> /// <param name="info">The info.</param> /// <returns> /// The <see cref="bool"/>. /// </returns> private bool CalculateShorterDistance(Vector2 start, Vector2 end, Vector2 point, ref PointInfoInternal info) { Vector2 diffEnds = end - start; float lengthSquared = diffEnds.LengthSquared(); Vector2 diff = point - start; Vector2 multiplied = diff * diffEnds; float u = (multiplied.X + multiplied.Y) / lengthSquared; if (u > 1) { u = 1; } else if (u < 0) { u = 0; } Vector2 multipliedByU = diffEnds * u; Vector2 pointOnLine = start + multipliedByU; Vector2 d = pointOnLine - point; float dist = d.LengthSquared(); if (info.DistanceSquared > dist) { info.DistanceSquared = dist; info.PointOnLine = pointOnLine; return(true); } return(false); }