1
SELECT ST_GeomFromGeoJSON('{"type":"LineString","coordinates":[[-3.01055556,56.46583333],[-71.20583333,46.825]]}')

gives me a line from Dundee to Quebec.

I try to surround it with a 999 nautical mile buffer

SELECT ST_Buffer(
ST_GeomFromGeoJSON('{"type":"LineString","coordinates":[[-3.01055556,56.46583333],[-71.20583333,46.825]]}')::geography,
999 * 1852,
'quad_segs=30 endcap=round join=round'
)

(1852 = number of metres in a nautical mile)

A 999NM radius around Dundee ought to intersect Coimbra, Portugal. But the buffer only extends as far as half-way through France. The buffer appears correct for shorter distances e.g. 10NM.

Why is the buffer smaller than expected?

1
  • The documentation postgis.net/docs/ST_Buffer.html seems to warn about this: For geography, this is a wrapper around the geometry implementation. It determines a planar spatial reference system that best fits the bounding box of the geography object (trying UTM, Lambert Azimuthal Equal Area (LAEA) North/South pole, and finally Mercator ). The buffer is computed in the planar space, and then transformed back to WGS84. This may not produce the desired behavior if the input object is much larger than a UTM zone or crosses the dateline.
    – user30184
    Commented Mar 11, 2022 at 14:35

2 Answers 2

2

It's probably linked to the projection the buffer will use. By default, it will do that:

It determines a planar spatial reference system that best fits the bounding box of the geography object (trying UTM, Lambert Azimuthal Equal Area (LAEA) North/South pole, and finally Mercator). The buffer is computed in the planar space, and then transformed back to WGS84. This may not produce the desired behavior if the input object is much larger than a UTM zone or crosses the dateline

Your geometry is definitly bigger than an UTM zone, and if you make your buffer in 3857 (mercator) directly you get the same result:

SELECT
ST_Buffer(
  st_transform(
    st_setsrid(
      ST_GeomFromtext(
        'linestring(-3.01055556 56.46583333, -71.20583333 46.825)'
      ),
      4326
    ),
    3857
  ),
  999 * 1852,
  'quad_segs=30 endcap=round join=round'
)

So it mean the ST_buffer fall back to 3857 for your geom. If you want a more correct result for your case, you have to choose a better fitting projection, in your case one that respects the distances instead of the form. For example, there is the Bonne projection (srid 54024) (there is probably better suited projection for your case, but it's a classic). Replace the 3857 in the request above by 54024, and I think the result (in red) is closer to what you expect than the 3857 projection (in green):

Differences between the projections

EDIT: the North Pole Azimuthal Equidistant (102016) is also a good candidate in the north hemisphere I think

2

Buffers on geography are not reliable over large areas.

The st_buffer code reveals that the operation is transformed to

SELECT geography(ST_Transform(ST_Buffer(ST_Transform(geometry($1), _ST_BestSRID($1)), $2, $3), 4326))

and the code for _ST_BestSRID, after trying UTM and a few other projections, returns the world mercator projection, with a comment that should be a big warning instead: Running out of options... fall-back to Mercator and hope for the best.

This is confirmed if we measure the returned buffer distance in 3857:

black circle: buffer around the point only (fine)
horizontal lines: buffer as you have created it
vertical lines: buffer + segmentize before casting back to geometry, so we can visualize the great circle arcs.

enter image description here

The issue here is not the radius size but rather the original geometry extent. Using a smaller radius only reduce the distance distortion induced by the use of 3857.

To get a better buffer, you could create the line geography, segmentize it in 1000 segments, split the output at each vertex, buffer each individual segment, merge the buffers

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.