private MinDistanceAtTPair GetClosestTParameter(BezierTParameterRequest _request, MinDistanceAtTPair _compareWith) { float mid = (_request.startingT + _request.endT) / 2.0f; // Base case for recursion. if ((_request.endT - _request.startingT) < _request.thresholdT) { _compareWith.tParameter = mid; return(_compareWith); } // The two halves have param range [start, mid] and [mid, end]. We decide which one to use by using a midpoint param calculation for each section. float paramA = (_request.startingT + mid) / 2.0f; float paramB = (mid + _request.endT) / 2.0f; Vector3 posA = Spline.GetPoint(paramA); Vector3 posB = Spline.GetPoint(paramB); float distASq = (posA - _request.pointToCheck).sqrMagnitude; float distBSq = (posB - _request.pointToCheck).sqrMagnitude; if (distASq < distBSq) { _request.endT = mid; _compareWith.minSqrDistance = distASq; } else { _request.startingT = mid; _compareWith.minSqrDistance = distBSq; } // The (tail) recursive call. return(GetClosestTParameter(_request, _compareWith)); }
public float GetTParameter(Vector3 _pointToCheck) { MinDistanceAtTPair result = new MinDistanceAtTPair(float.NaN, float.NaN); for (int i = 0; i < Spline.ControlPointCount - 1; i += 3) { BezierTParameterRequest request = new BezierTParameterRequest(_pointToCheck); result = GetClosestTParameter(request, result); } return(result.tParameter); }