2

I have a line made up of two points. I am creating a buffer around that line of 18520m (10 Nautical Miles) using ST_Buffer.

I have a third point and I want to test if that is within the buffer or not.

When I test the distance from the original line to the third point (using ST_Distance), I get a distance of 18630m. Clearly, outside of the buffer of 18520m.

When I test the distance from the buffer to the third point (using ST_Distance), I get a distance of 0m - implying that the point is inside the buffer of 18520.

When I test whether the third point is within the buffer (using ST_Intersects), I get a value of 'true' - implying that the point is inside the buffer of 18520.

However, the distance from the line to the third point being 18630m AND the third point being within the buffer of 18520m cannot both be true. So where am I going wrong?

Have a look at the following script to replicate my results:

WITH myconstants (bufferGeography, myLat, myLon) as (
   values (
       ST_Buffer(
            ST_GeogFromText('SRID=4326;LINESTRING(-4.275000095367432 60.314998626708984, -32.579489389701344 59.51950893947703)'
            )
        , 18520)
       ,59.6793
       ,-32.6768
   )    
)

SELECT 
    ST_Distance(ST_GeogFromText('SRID=4326;LINESTRING(-4.275000095367432 60.314998626708984, -32.579489389701344 59.51950893947703)'),ST_Point(myLon, myLat)::geography) AS DistanceFromLine
    ,ST_Distance(bufferGeography,ST_Point(myLon, myLat)::geography) AS DistanceFromBuffer
    ,ST_Intersects(bufferGeography, ST_Point(myLon, myLat)::geography) AS WithinBuffer
FROM myconstants;

This gives the following output:

"distancefromline"  "distancefrombuffer"    "withinbuffer"
18630.52586952  0   true

What is wrong?

2
  • I suspect that this is to do with the number of segments in the buffer as you are off to the left of the line (just)
    – Ian Turton
    Commented Jan 12, 2023 at 15:42
  • Even with a high amount of segments, I get the same result than you. A buffer on the western most point gives the expected result, but the buffer based on the line has a weird skewed shape. You can use ST_DWithin, faster and it works consistently (18520 is out, 18630 is out, 18631 is in)
    – Kasper
    Commented Jan 12, 2023 at 15:56

3 Answers 3

6

Buffers are a bad idea in 99% of times you are thinking of them. The reasons are plentiful, but here specifically it is the fact that their shapes are

  • limited due to segmentation
  • only approximated by a best fitting projection of the AOI internally

Especially compared to spherical/spheroidal surface distances, buffers are inaccurate to a degree of utter uselessness.


As mentioned in comments, whenever you are thinking about spatial proximity - directly or hidden somewhere in a problem definition - ST_DWithin is the first tool you should be consulting. It has GEOGRAPHY support and is index boosted.

5

One should be very cautious when using geography function over large distances, as some of them are just a wrapper over the gometry function, using the "best" possible projection, which is UTM for short distances and bad ones for longer distances (it degrades down to world mercator).

ST_Buffer is one them, and we can see its code contains:

SELECT @[email protected](
 @[email protected]_Transform(
  @[email protected]_Buffer(
   @[email protected]_Transform(
    @[email protected]($1), 
    @extschema@._ST_BestSRID($1)), $2), 4326))

The original query was automatically transformed to build a buffer in a poor projection and it happens that the point falls in it. On the other hand, you are computing the true geographical distance, using the original geography line, and you are getting the true distance, which happen to be longer than the buffer "size".

So the answer here is not to use a buffer for distance analysis.

0

Some great responses here. Thanks all who contributed.

It seems that the short of it is that ST_Buffer is just not reliable as far as accuracy is concerned. This is a bit of a blow because we were not only hoping to use it for our calculations, but to show that buffer on a map as well. Knowing that the buffer is inaccurate means that we've had to change our thinking here.

If anyone's interested then in the back-end we're using ST_DWithin and for the front-end we're using turf.js which does appear to be accurate.

1
  • Hi @Thomas you should write this as a comment instead of an Answer
    – Kasper
    Commented Jan 13, 2023 at 13:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.