Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 572861
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 13, 20262026-05-13T13:39:47+00:00 2026-05-13T13:39:47+00:00

I have a geography field stored in my database, holding a linestring path. I

  • 0

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();
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-13T13:39:47+00:00Added an answer on May 13, 2026 at 1:39 pm

    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:

    CREATE FUNCTION [dbo].[func_MoveTowardsPoint](@start_point geography,
                                                  @end_point   geography,  
                                                  @distance    int)  /* Meters */   
    RETURNS geography
    AS
    BEGIN
        DECLARE @ang_dist float = @distance / 6371000.0;  /* Earth's radius */
        DECLARE @bearing  decimal(18,15);
        DECLARE @lat_1    decimal(18,15) = Radians(@start_point.Lat);
        DECLARE @lon_1    decimal(18,15) = Radians(@start_point.Long);
        DECLARE @lat_2    decimal(18,15) = Radians(@end_point.Lat);
        DECLARE @lon_diff decimal(18,15) = Radians(@end_point.Long - @start_point.Long);
        DECLARE @new_lat  decimal(18,15);
        DECLARE @new_lon  decimal(18,15);
        DECLARE @result   geography;
    
        /* First calculate the bearing */
    
        SET @bearing = ATN2(sin(@lon_diff) * cos(@lat_2),
                            (cos(@lat_1) * sin(@lat_2)) - 
                            (sin(@lat_1) * cos(@lat_2) * 
                            cos(@lon_diff)));
    
        /* Then use the bearing and the start point to find the destination */
    
        SET @new_lat = asin(sin(@lat_1) * cos(@ang_dist) + 
                            cos(@lat_1) * sin(@ang_dist) * cos(@bearing));
    
        SET @new_lon = @lon_1 + atn2( sin(@bearing) * sin(@ang_dist) * cos(@lat_1), 
                                      cos(@ang_dist) - sin(@lat_1) * sin(@lat_2));
    
        /* Convert from Radians to Decimal */
    
        SET @new_lat = Degrees(@new_lat);
        SET @new_lon = Degrees(@new_lon);
    
        /* Return the geography result */
    
        SET @result = 
            geography::STPointFromText('POINT(' + CONVERT(varchar(64), @new_lon) + ' ' + 
                                                  CONVERT(varchar(64), @new_lat) + ')', 
                                       4326);
    
        RETURN @result;
    END
    

    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:

    1. Iterate through each point of your linestring with STPointN(), from x=1 to x=STNumPoints().
    2. Find the distance with STDistance() between the current point in the iteration to the next point: @linestring.STPointN(x).STDistance(@linestring.STPointN(x+1))
    3. If the above distance > your input distance ‘n’:

      …then the destination point is between this point and the next. Simply apply func_MoveTowardsPoint passing 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:

    CREATE FUNCTION [dbo].[func_MoveAlongPath](@path geography, 
                                               @distance int, 
                                               @index int = 1)   
    RETURNS geography
    AS
    BEGIN
        DECLARE @result       geography = null;
        DECLARE @num_points   int = @path.STNumPoints();
        DECLARE @dist_to_next float;
    
        IF @index < @num_points
        BEGIN
            /* There is still at least one point further from the point @index
               in the linestring. Find the distance to the next point. */
    
            SET @dist_to_next = @path.STPointN(@index).STDistance(@path.STPointN(@index + 1));
    
            IF @distance <= @dist_to_next 
            BEGIN
                /* @dist_to_next is within this point and the next. Return
                  the destination point with func_MoveTowardsPoint(). */
    
                SET @result = [dbo].[func_MoveTowardsPoint](@path.STPointN(@index),
                                                            @path.STPointN(@index + 1),
                                                            @distance);
            END
            ELSE
            BEGIN
                /* The destination is further from the next point. Subtract
                   @dist_to_next from @distance and continue recursively. */
    
                SET @result = [dbo].[func_MoveAlongPath](@path, 
                                                         @distance - @dist_to_next,
                                                         @index + 1);
            END
        END
        ELSE
        BEGIN
            /* There is no further point. Our distance exceeds the length 
               of the linestring. Return the last point of the linestring.
               You may prefer to return NULL instead. */
    
            SET @result = @path.STPointN(@index);
        END
    
        RETURN @result;
    END
    

    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:

    DECLARE @g geography;
    SET @g = geography::STGeomFromText('LINESTRING(-122.360 47.656, 
                                                   -122.343 47.656, 
                                                   -122.310 47.690)', 4326);
    
    SELECT [dbo].[func_MoveAlongPath](@g, 350, DEFAULT).ToString();
    SELECT [dbo].[func_MoveAlongPath](@g, 3500, DEFAULT).ToString();
    SELECT [dbo].[func_MoveAlongPath](@g, 7000, DEFAULT).ToString();
    

    Our test returns the following results:

    POINT (-122.3553270591861 47.6560002502638)
    POINT (-122.32676470116748 47.672728464582583)
    POINT (-122.31 47.69)
    

    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.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a column in my database of data type Geography which I want
I have an SQL Server 2008 database with a column of type geography storing
I have a number of database tables below. I want to display each user
I have a local database with some data of type geography in it. I
I have users stored in a database that has latitude and longitude set on
I have a SQL Server 2008 database that contains DateTimeOffset objects. As per this
We have developers working in different geographic locations and we want to set up
I have created Twitter bots for many geographic locations. I want to allow users
have written this little class, which generates a UUID every time an object of
I have geographic data that was loaded into the geography datatype. For very specific

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.