Announcement

Collapse
No announcement yet.

Get Distance at Location Along Spline.

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    [FEATURE REQUEST] Get Distance at Location Along Spline.

    On the face of it, it might just sound like the inverse of the Get Location at Distance Along Spline node, but it requires some pretty complex math (and from what i gather can only give an approximation). But this node is something that would be incredibly helpful when dealing with splines.
    Lee Devonald
    Character Technical Artist.
    Portfolio: http://crazyferretstudios.com

    #2
    You can get fairly accurate distance by dividing spline segments into lots of very small straight lines and therefore, the distance = number of lines * single line length.

    Comment


      #3
      lol - I was totally looking for this today as well!

      Upvote++
      https://www.casualdistractiongames.com

      Comment


        #4
        I agree that this would be very useful.

        Comment


          #5
          I believe I was able to write a function(a pure one even) in blueprint to achieve this. I have included a screenshot of my graph. I have tested this a few times and it seems to work. If anyone finds that this doesn't work please say so. Click image for larger version

Name:	CDCUUxR.png
Views:	1
Size:	209.2 KB
ID:	1122235

          Comment


            #6
            Hello! It seems to me so it will be easier.
            Click image for larger version

Name:	Screenshot_28.png
Views:	1
Size:	135.4 KB
ID:	1124622

            Comment


              #7
              Originally posted by path3tic View Post
              I believe I was able to write a function(a pure one even) in blueprint to achieve this. I have included a screenshot of my graph. I have tested this a few times and it seems to work. If anyone finds that this doesn't work please say so. [ATTACH=CONFIG]127193[/ATTACH]
              Thanks !! Exactly what I needed and it work great !

              Comment


                #8
                Oh seem like that function don't work at all as expected cause of this https://issues.unrealengine.com/issue/UE-27979
                Hevedy - Instance Tools: https://hevedy.itch.io/hevedyinstances
                Hevedy - Image Tools: https://hevedy.itch.io/imagetools

                Comment


                  #9
                  Originally posted by Hevedy View Post
                  Oh seem like that function don't work at all as expected cause of this https://issues.unrealengine.com/issue/UE-27979
                  According to the issue this has been only affecting 4.10 and 4.11. Also its closed now due to not being able to reproduce.

                  Comment


                    #10
                    Here's the same thing (more or less) in C++ with a consideration for having the location at the end point.

                    Code:
                    UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Spline")
                    static float UUtilities::FindDistanceAlongSplineClosestToLocation(const USplineComponent* Spline, const FVector& Location)
                    {
                        float InputKey = Spline->FindInputKeyClosestToWorldLocation(Location);
                        int32 SplinePoint = FMath::TruncToInt(InputKey);
                        float SplinePointDistance = Spline->GetDistanceAlongSplineAtSplinePoint(SplinePoint);
                        if (SplinePoint < Spline->GetNumberOfSplinePoints())
                        {
                            float NextPointDistance = Spline->GetDistanceAlongSplineAtSplinePoint(SplinePoint + 1);
                            return FMath::Lerp(SplinePointDistance, NextPointDistance,  InputKey - SplinePoint);
                        }
                        else
                        {
                            float PrevPointDistance = Spline->GetDistanceAlongSplineAtSplinePoint(SplinePoint - 1);
                            return FMath::Lerp(PrevPointDistance, SplinePointDistance, SplinePoint - InputKey);
                        }
                    }

                    Comment


                      #11
                      Originally posted by roushenzo View Post
                      Hello! It seems to me so it will be easier.
                      [ATTACH=CONFIG]132997[/ATTACH]
                      Originally posted by Aakrasia View Post
                      I believe I was able to write a function(a pure one even) in blueprint to achieve this. I have included a screenshot of my graph. I have tested this a few times and it seems to work. If anyone finds that this doesn't work please say so. [ATTACH=CONFIG]127193[/ATTACH]

                      Aakrasia solution is more accurate than roushenzo. Sadly still not perfect due to the tangents (distance is not linear), but it is a good approach. Maybe someone who knows mathematics could perfectionate it :-/. Are splines a bezier curve? Maybe I could investigate it. If I can make one perfect I will post it here.
                      Last edited by Cucharón; 06-01-2019, 03:56 PM.

                      Comment


                        #12
                        bump?.....

                        Comment


                          #13
                          I'm using this one:

                          Code:
                          float ASomething::GetDistanceAlongSplineAtWorldLocation(const USplineComponent* InSpline, const FVector InWorldLocation)
                          {
                              if (!InSpline)
                                  return 0.f;
                          
                              auto InputKeyFloat = InSpline->FindInputKeyClosestToWorldLocation(InWorldLocation);
                              auto InputKey = FMath::TruncToInt(InputKeyFloat);
                              auto A = InSpline->GetDistanceAlongSplineAtSplinePoint(InputKey);
                              auto B = InSpline->GetDistanceAlongSplineAtSplinePoint(InputKey + 1);
                          
                              return A + ((B - A) * (InputKeyFloat - InputKey));
                          }
                          Seems to work pretty well.

                          Comment


                            #14
                            All above answers assume spline segments are straight lines which can lead to meters of error on curved splines. I suggest a binary search instead where any precision can be achieved depending on the number of iterations.
                            Code:
                            float SplineUtils::GetApproxDistanceClosestToWorldLocation(FVector Pos_WS, const USplineComponent& Spline)
                            {
                                const auto TargetInputKey = Spline.FindInputKeyClosestToWorldLocation(Pos_WS);
                                const auto PointIdx       = static_cast<int32>(TargetInputKey);
                            
                                auto LowDistBound_cm       = Spline.GetDistanceAlongSplineAtSplinePoint(PointIdx);
                                auto HighDistBound_cm      = Spline.GetDistanceAlongSplineAtSplinePoint(PointIdx + 1);
                                auto MiddleDistEstimate_cm = (LowDistBound_cm + HighDistBound_cm) * 0.5f;
                            
                                const auto& DistanceToInputMapping = Spline.SplineCurves.ReparamTable;
                            
                                for (auto IterCount = 0; IterCount < 10; ++IterCount)
                                {
                                    const auto MiddleInputKey = DistanceToInputMapping.Eval(MiddleDistEstimate_cm);
                            
                                    if (TargetInputKey < MiddleInputKey) {
                                        HighDistBound_cm = MiddleDistEstimate_cm;
                                    } else {
                                        LowDistBound_cm = MiddleDistEstimate_cm;
                                    }
                            
                                    MiddleDistEstimate_cm = (LowDistBound_cm + HighDistBound_cm) * 0.5f;
                                }
                            
                                return MiddleDistEstimate_cm;
                            }

                            Comment


                              #15
                              I've created a pull request for this feature:

                              https://github.com/EpicGames/UnrealEngine/pull/6646

                              It adds a GetDistanceAtSplineInputKey GetDistanceAlongSplineAtSplineInputKey method to USplineComponent.

                              The change relies on the ReparamTable assuming a linear relationship between the distance and the input key between consecutive entries. Meaning if distance is 5 at input key 0.1, and distance is 25 at input key 0.2, then distance at input key 0.15 is 15.

                              So this should be as accurate as the inverse operation(s) (e.g. GetInputKeyAtDistanceAlongSpline, GetLocationAtDistanceAlongSpline), without the need to iterate.
                              Last edited by Seurabimn; 02-04-2020, 10:31 PM.

                              Comment

                              Working...
                              X