1

We have a situation where we get a single lat/long point and a value for "acreage", and we need to draw a polygon circle that is roughly the size that the acreage value implies. What we have is a query that comes extremely close, but the total area is still off, for some reason.

create TEMP TABLE g (geom geometry, acres float);
 insert into g VALUES (ST_SETSRID(ST_POINT(-74,34.00), 4326), 100);
 insert into g VALUES (ST_SETSRID(ST_POINT(-74,34.00), 4326), 10000);
 insert into g VALUES (ST_SETSRID(ST_POINT(-74,34.00), 4326), 100000);
create temp table gg  AS select 
    ST_TRANSFORM(
        ST_BUFFER(
        -- Build a buffer, calculating radius as sqrt(area/pi)
            geom::geography, 
            SQRT(
                 (acres/.00024711)/3.1415
             )
        )::geometry
    , 4326)::geography as b,
    acres,
    acres/.00024711 as area_in_meters
FROM g;

SELECT 
    b,
    st_area(b, TRUE), -- This and area_in_meters are not _quite_ equal
    acres,
    area_in_meters
FROM gg;

I believe its one of a few factors, but I am having a hard time deriving the right test.

acres/.00024711 as area_in_meters - is this an accurate way of converting acres to sq meters?

ST_TRANSFORM(buffer_geom, 4326) Will this always yield an accurate geometry for the buffer we want? are we loosing data jumping around between geography and geometry?

st_area(b, TRUE) b is a geography, so this is in meters right? its what the docs say, but perhaps ::geography as b isn't fully performing the cast I think it is?

1
  • 1
    The conclusion btw. is that, as long as geometries are described with vertex meshes, and vizualized via rasterization of these meshes, technically you cannot have circular entities. Mathematically however, you can happily assume a circle to have the exact area resulting by defining a radius around a point. Thus, if you need a value to present, don't rely on vector entities and their limits inherited from digital representation, use PI*r*r (or the more complex speroidal surface sector area calculation) instead.
    – geozelot
    Commented Jan 30, 2021 at 10:27

2 Answers 2

2

The polygon generated by using ST_Buffer on a point is only an approximation to a circle. By default it is a 32-sided regular polygon. The number of sides can be increased by specifying the number of segments in a quarter-circle as the third parameter. But it will still have an area which is slightly less than a circle of the same diameter.

If you need the area to be exact, you should be able to work out the (small) factor by which to increase the nominal radius.

2

One cause of the observed difference is that the ST_Buffer function does not actually compute a geographic buffer. It instead converts it to a 'best srid' that it determines itself (usually a UTM zone), performs the buffer in 2D, and converts it back to geography. You can easily observe the effect of this by changing the longitude of the point slightly. You'll notice that the results are not always the same, they can be slightly higher or lower depending on the location of the point within the 'best srid/projection' used.

If you know the best projection for your area of interest, you can force it to use that one by passing a geometry (previously converted to your preferred srid) in the ST_Buffer instead of a geography. For example in your case, maybe an equal-area projection centered on your points could be an option.

Another source of difference is the approximation of the circle. When buffering something, by default, PostGIS creates 8 vertices per quarter circle, yielding a 32-sided polygon, which isn't quite a circle. You can increase the number of vertices to get it closer, but it will never be exactly a circle.

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.