1

ST_MinimumBoundingCircle returns the smallest circle polygon that can fully contain a geometry, but if you execute this function iteratively on a geometry, it increases more and more, whereas the same geometry should be maintained. Here is an example where a circle is created using ST_buffer with quad_segs by default. Then apply ST_MinimumBoundingCircle on it and then reapply on the same geometry.

As you can see, the area of the geometry starts to increase every time ST_MinimumBoundingCircle is applied.

with gen_circle as(
SELECT ST_Buffer(
ST_GeomFromText('POINT(100 90)'),50) as circle)
select postgis_liblwgeom_version(), 
st_area(ST_MinimumBoundingCircle(circle)),
st_area(ST_MinimumBoundingCircle(ST_MinimumBoundingCircle(circle))),
st_area(ST_MinimumBoundingCircle(ST_MinimumBoundingCircle(ST_MinimumBoundingCircle(circle)))) from gen_circle

enter image description here

I'm using the last postgis version

1
  • well, inconsistencies are to be expected. there is a note on the doc page concerning the accuracy of the polygonal approximation, that, naturally, decreases with each 'iteration' (approx. of an approx. of ...). equally, a buffer circle can never be a perfect circle, as for the dependency of segmentation.
    – geozelot
    Commented Aug 30, 2018 at 7:16

1 Answer 1

2

As ThingamuBob said, this is due to the parameter for number of segments per quarter circle in the ST_MinimumBoundingCircle function. As an illustration, you can see the same behaviour with ST_Buffer and how close the area of a circle with radius 1 approaches PI, as you increase the segments.

WITH segs(x) AS (VALUES(1), (10), (100), (1000), (10000))                                          
SELECT 
    x, 
    ST_Area(ST_Buffer(ST_MakePoint(0,0), 1, x))/PI() 
 FROM segs;

which returns:

    1 | 0.636619772367581
   10 | 0.995892735243561
  100 | 0.999958877155665
 1000 | 0.999999588766537
10000 | 0.999999995887669

Returning to your example:

WTIH gen_circle as(
  SELECT ST_Buffer(
           ST_GeomFromText('POINT(100 90)'),50) as circle)
SELECT        
    ST_Area(ST_MinimumBoundingCircle(circle, 1000)),
    ST_Area(ST_MinimumBoundingCircle(ST_MinimumBoundingCircle(circle, 1000), 1000)),
    ST_Area(ST_MinimumBoundingCircle(ST_MinimumBoundingCircle(
           ST_MinimumBoundingCircle(circle, 1000), 1000), 1000)) 
FROM gen_circle;

now returns:

7853.98324888513 | 7853.98809361888 | 7853.99293835557

which is a lot closer to the same answer -- of course, 4000 segments is still only an approximation of a circle, albeit a very close one.

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.