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
  Deform mesh on the spline Nico_CL 3 88 10-09-2019, 04:10 PM
Last Post: _Aka_
  Best practice for mass-object instancing along 100km spline (railways) plus streaming bs@vectorvision.de 10 493 09-24-2019, 03:42 PM
Last Post: _Aka_
  Invert the spline points ? UsernameHed 1 90 09-21-2019, 03:22 PM
Last Post: _Aka_
  How to spawn GameObjects on corners of the liinear spline? Pixel Flipper 7 286 09-18-2019, 07:03 PM
Last Post: _Aka_

Forum Jump: