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);


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

       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
  Accessing generator's input spline in script, changing it at runtime smackledorf 3 105 06-17-2021, 01:59 PM
Last Post: _Aka_
  Questions about Generator: mesh/objects within spline, snap to control point dartboard 5 197 06-09-2021, 12:42 PM
Last Post: _Aka_
  get world vector3 from absolute position on spline hawken 2 94 06-08-2021, 12:28 PM
Last Post: hawken
Shocked Change spline path at runtime burn0815 7 391 05-27-2021, 08:27 PM
Last Post: _Aka_

Forum Jump: