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 will help a lot keeping Curvy relevant in the eyes of the Asset Store algorithm.
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 will help a lot keeping Curvy relevant in the eyes of the Asset Store algorithm.
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 will help a lot keeping Curvy relevant in the eyes of the Asset Store algorithm.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  How to get length starting from one spline to connected nth spline Dragon-3623 1 1 05-14-2024, 04:52 PM
Last Post: _Aka_
  Getting Distance from a World Point zorksox 3 5 04-16-2024, 07:30 PM
Last Post: _Aka_
  Curvy Line Renderer for UI Spline? gekido 3 6 04-04-2024, 12:56 PM
Last Post: _Aka_
  Get position of all control points for a spline gekido 1 6 03-28-2024, 10:08 PM
Last Post: _Aka_

Forum Jump: