/// <summary> /// Calculates position of the closest point on the line to the passed point /// </summary> /// <param name="point">Passed point that will be snapped</param> /// <param name="snappedPointType">Precalculated snapping type (from the distance method)</param> /// <returns>Position of closest point</returns> /// <exception cref="ArgumentOutOfRangeException">Invalid snapped point type</exception> public Vector3 ClosestPoint(Vector3 point, SnappedPointType snappedPointType) { switch (snappedPointType) { case SnappedPointType.InBetween: var x = (b * (b * point.x - a * point.z) - a * c) / a2b2; var z = (a * (-b * point.x + a * point.z) - b * c) / a2b2; return(new Vector3(x, point.y, z)); case SnappedPointType.Start: return(new Vector3(start.x, point.y, start.z)); case SnappedPointType.End: return(new Vector3(end.x, point.y, end.z)); default: throw new ArgumentOutOfRangeException(nameof(snappedPointType), snappedPointType, null); } }
/// <summary> /// Calculates distance to the line, returns float.MaxValue is greater than passed max distance /// </summary> /// <param name="point">Point that will be snapped to line</param> /// <param name="maxDistance">Maximal distance that can be applied</param> /// <param name="snappedPointType">Returns type how point will be snapped to the line</param> /// <returns>Distance between the point and the line, returns float.MaxValue is greater than passed max distance</returns> public float Distance(Vector3 point, float maxDistance, out SnappedPointType snappedPointType) { var distanceToStraightLine = Mathf.Abs((a * point.x + b * point.z + c) / sqrta2b2); if (distanceToStraightLine > maxDistance) { snappedPointType = SnappedPointType.Invalid; return(float.MaxValue); } var pointStart = Distance(point, start); var pointEnd = Distance(point, end); var lengthPow = Mathf.Pow(length, 2); var pointStartPow = Mathf.Pow(pointStart, 2); var pointEndPow = Mathf.Pow(pointEnd, 2); //Check if point will be snapped to the start, end or in between //Point is snapped to point between start and end only when the formed triangle is obtuse if (pointStartPow > lengthPow + pointEndPow) { if (pointEnd > maxDistance) { snappedPointType = SnappedPointType.Invalid; return(float.MaxValue); } snappedPointType = SnappedPointType.End; return(pointEnd); } if (pointEndPow > lengthPow + pointStartPow) { if (pointStart > maxDistance) { snappedPointType = SnappedPointType.Invalid; return(float.MaxValue); } snappedPointType = SnappedPointType.Start; return(pointStart); } snappedPointType = SnappedPointType.InBetween; return(distanceToStraightLine); }