Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Closest point From a Ray (a line), to the spline
#1
Hello Smile

I Wonder if you have already a function who find the closest position from a Ray to your spline.

You have the curvySpline.GetNearestPointTF(worldPos, out closestPosition);

I could test every point on the Ray (or iterate randomly with more and more acuracy), but I a sure there is a better & opti way of doing it with Math.
How could I do with your plugin ?

Thanks Smile
Reply
#2
Hi,
Here is an implementation of the method you want. I need to work on it more before putting it in a release, but if this can save you some time, here it go:
In CurvySplineSegment.cs

Code:
public float GetNearestPointF(Ray ray, out Vector3 nearestPointOnRay)
        {

#if CURVY_SANITY_CHECKS
           Assert.IsTrue(CacheSize >= 0, "[Curvy] CurvySplineSegment has unintialized cache. Call Refresh() on the CurvySpline it belongs to.");
#endif
            int ui = CacheSize + 1;
            float nearestDistSqr = float.MaxValue;
            float distSqr;
            int nearestIndex = 0;
            // get the nearest index
            for (int i = 0; i < ui; i++)
            {
                distSqr = DistanceToLine(ray, Approximation[i]);
                if (distSqr <= nearestDistSqr)
                {
                    nearestDistSqr = distSqr;
                    nearestIndex = i;
                }
            }
            // collide p against the lines build by the index
            int leftIdx = (nearestIndex > 0) ? nearestIndex - 1 : -1;
            int rightIdx = (nearestIndex < CacheSize) ? nearestIndex + 1 : -1;

            nearestPointOnRay = NearestPointOnRay(ray, Approximation[nearestIndex]);
            float lfrag = 0;
            float rfrag = 0;
            float ldistSqr = float.MaxValue;
            float rdistSqr = float.MaxValue;
            if (leftIdx > -1)
                ldistSqr = DTMath.LinePointDistanceSqr(Approximation[leftIdx], Approximation[nearestIndex], nearestPointOnRay, out lfrag);
            if (rightIdx > -1)
                rdistSqr = DTMath.LinePointDistanceSqr(Approximation[nearestIndex], Approximation[rightIdx], nearestPointOnRay, out rfrag);

            float stepSize = 1f / CacheSize;

            // return the nearest collision
            if (ldistSqr < rdistSqr)
                return getApproximationLocalF(leftIdx) + lfrag * stepSize;
            else
                return getApproximationLocalF(nearestIndex) + rfrag * stepSize;
        }

       public static float DistanceToLine(Ray ray, Vector3 point)
       {
           return Vector3.Cross(ray.direction, point - ray.origin).magnitude;
       }

       public static Vector3 NearestPointOnRay(Ray ray, Vector3 point)
       {
           Vector3 delta = point - ray.origin;
           float distance = Mathf.Max(0, Vector3.Dot(delta, ray.direction));
           return ray.origin + ray.direction * distance;
       }

In CurvySpline.cs

Code:
       public float GetNearestPointTF(Ray ray, out Vector3 nearestPoint, [CanBeNull] out CurvySplineSegment nearestSegment, out float nearestSegmentF, int startSegmentIndex = 0, int stopSegmentIndex = -1)
       {
#if CURVY_SANITY_CHECKS
           DoSanityChecks();
#endif

           nearestPoint = Vector3.zero;
           if (Count == 0)
           {
               nearestSegment = null;
               nearestSegmentF = -1;
               return -1;
           }
           // for each segment, get the distance to it's approximation points
           float distSqr = float.MaxValue;
           float resF = 0;

           CurvySplineSegment resSeg = null;
           if (stopSegmentIndex == -1)
               stopSegmentIndex = Count - 1;
           startSegmentIndex = Mathf.Clamp(startSegmentIndex, 0, Count - 1);
           stopSegmentIndex = Mathf.Clamp(stopSegmentIndex + 1, startSegmentIndex + 1, Count);
           for (int i = startSegmentIndex; i < stopSegmentIndex; i++)
           {
               Vector3 nearestPointOnRay;
               float f = this[i].GetNearestPointF(ray, out nearestPointOnRay);
               Vector3 v = this[i].Interpolate(f);
               float magSqr = (v - nearestPointOnRay).sqrMagnitude;
               if (magSqr <= distSqr)
               {
                   resSeg = this[i];
                   resF = f;
                   nearestPoint = v;
                   distSqr = magSqr;
               }

               //DrawPoint(v, Color.cyan);
               //DrawPoint(nearestPointOnRay, Color.magenta);
           }

           nearestSegment = resSeg;
           nearestSegmentF = resF;
           // return the nearest
           return resSeg.LocalFToTF(resF);
       }

        public float GetNearestPointTF(Ray ray, out Vector3 nearest, int startSegmentIndex = 0, int stopSegmentIndex = -1)
        {
#if CURVY_SANITY_CHECKS
            DoSanityChecks();
#endif

            CurvySplineSegment segement;
            float f;
            return GetNearestPointTF(ray, out nearest, out segement, out f, startSegmentIndex, stopSegmentIndex);
        }

        public float GetNearestPointTF(Ray ray, int startSegmentIndex = 0, int stopSegmentIndex = -1)
        {
#if CURVY_SANITY_CHECKS
            DoSanityChecks();
#endif

            Vector3 v;
            return GetNearestPointTF(ray, out v, startSegmentIndex, stopSegmentIndex);
        }

        public float GetNearestPointTF(Ray ray, out Vector3 nearest)
        {
#if CURVY_SANITY_CHECKS
            DoSanityChecks();
#endif

            return GetNearestPointTF(ray, out nearest, 0, -1);
        }
Please consider leaving a review for Curvy, this helps immensely. Thank you.
Available for freelance work—feel free to reach out.
Reply
#3
Wow, honestly, that far from I excpected, you just give me the good method, without any compile error at the first implementation, in less than a day, and it work ! Wow you are amazing ! Sincerly !
Reply
#4
Thanks a lot, you are making me shy Big Grin
But to be honest, I had that method already implemented. I just didn't take the time yet to test the s*** out of it, optimize it and document it. Once this is done, it will be included in the next Curvy update.
Please consider leaving a review for Curvy, this helps immensely. Thank you.
Available for freelance work—feel free to reach out.
Reply
#5
you're welcome Smile

oh, you should add another out Vector3, if I want to have also the closest point in the line
Reply
#6
noted, thanks
Please consider leaving a review for Curvy, this helps immensely. Thank you.
Available for freelance work—feel free to reach out.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
Information Questions regarding spline colliders and collisions with rigidbodies Spyboticer 7 51 01-20-2025, 12:25 PM
Last Post: _Aka_
  Extrude mesh along spline. New and confused user GhostStalker 3 14 01-02-2025, 09:58 AM
Last Post: _Aka_
  Newly created spline is invisible quickytools 7 26 12-21-2024, 10:14 AM
Last Post: _Aka_
  How to generate gameobject on the control point Yang Yi 1 8 12-10-2024, 10:14 PM
Last Post: _Aka_

Forum Jump: