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
  Curvy Line Renderer for UI Spline? gekido 1 1 9 hours ago
Last Post: _Aka_
  Get position of all control points for a spline gekido 1 2 10 hours ago
Last Post: _Aka_
Bug Changing spline connection in inspector causes splines to revert to defaults lacota 3 6 03-18-2024, 07:55 PM
Last Post: _Aka_
  GO can't fit end of the spline GameDeveloperek4123 3 13 03-04-2024, 11:06 AM
Last Post: _Aka_

Forum Jump: