I have a SQL Server 2008 GEOGRAPHY data type in my database containing a LINESTRING. The LINESTRING describes a potentially curvy road.
I have another table that contains a start point and end point, both GEOGRAPHY POINT‘s, on the road. I need to know if a third point falls between those two points on the road (LINESTRING).
Currently, I’m testing that:
- the third point is on the line
- the distance between the new point to the start point and the distance between the new point and the end point are both less than the distance between the start point and end point
This works, but it seems really inelegant doesn’t work at all if the road u-turns on itself! Is there a way that works?
As you have noted, your method will fail in the following case, where S is the start point, E is the end point, and X is the point you are testing:
Determine if a POINT is between two other POINTs on a LINESTRING http://img10.imageshack.us/img10/4937/gmap.png
Using that method, point X will falsely result as being between point S and point E, because it passes both test 1 and test 2 of your algorithm: ie. Point X is on the linestring, and the distances from X to S and from X to E are both smaller than the distance from S to E.
One Possible Solution
You can “explode” your linestring path into separate line segmenets with just two points each, so that:
would get broken down into:
Then you would be able to iterate through each of the above line segments and test if the point lies on one of these segments using
STIntersects. When a point passes this test, you would be able to determine if this was within the start point and the end point.If possible, I would suggest storing your start/end points as an index to a point on your linestring path, instead of a raw geography point. First of all, this will make it easier to solve this problem, but apart from that, you would eliminate the duplication of data, which also comes with a guarantee where you cannot have a start/end point that is not part of a linestring. The disadvantage of this is that you will not able to have start/end points in the middle of a line segment, but they have to be on one of the corners of the path. Now you have to determine if this limitation is acceptable in your application.
If you opt for the above representation, we could solve this problem with the following recursive function, where
@pathis the linestring representing the road,@start_pointand@end_endrepresent the indexes of two points on the@path(first index is 1), and@test_pointis the geography point that will be tested. The test point can lie anywhere on the lie.To test the above function, I am defining the 6-point linestring which is shown in the map above. Then we’ll define two test points:
@test_point_a, which lies exactly between the third and the fourth point, and@test_point_b, which lies out of the path.