I have a geography field stored in my database, holding a linestring path.
I want to move a point n meters along this linestring, and return the destination.
For example, I want the destination point 500 meters along the linestring starting from its beginning.
Here’s an example — what is the YourFunctionHere? Or, is there another way?
DECLARE @g geography;
SET @g = geography::STGeomFromText('LINESTRING(-122.360 47.656, -122.343 47.656, -122.310 47.690)', 4326);
SELECT @g.YourFunctionHere(100).ToString();
This is a little bit tricky, but it is certainly possible.
Let’s start by calculating the bearing from one point to another. Given a starting point, a bearing, and a distance, the following function will return the destination point:
I understand that you require a function that takes a linestring as input, not just start and end points. The point has to move along a path of concatenated line segments, and must continue moving around the “corners” of the path. This might seem complicated at first, but I think it can be tackled as follows:
STPointN(), from x=1 to x=STNumPoints().STDistance()between the current point in the iteration to the next point:@linestring.STPointN(x).STDistance(@linestring.STPointN(x+1))If the above distance > your input distance ‘n’:
…then the destination point is between this point and the next. Simply apply
func_MoveTowardsPointpassing point x as start point, point x+1 as end point, and distance n. Return the result and break the iteration.Else:
…the destination point is further in the path from the next point in the iteration. Subtract the distance between point x and point x+1 from your distance ‘n’. Continue through the iteration with the modified distance.
You may have noticed that we can easily implement the above recursively, instead of iteratively.
Let’s do it:
With that in place, it’s time to do some tests. Let’s use the original linestring that was provided in the question, and we’ll request the destination points at 350m, at 3500m and at 7000m:
Our test returns the following results:
Note that the last distance we requested (7000m) exceeded the length of the linestring, so we were returned the last point. In this case, you can easily modify the function to return NULL, if you prefer.