[GIS] Get exterior ring of a multipolygon using GEOSGeometry or PostGIS

boundariesgeodjangogeospostgis

I am trying to get the exterior ring of the multipolygon in the image below using GEOSGeometry (through GeoDjango) or Postgis, but I have not found an easy solution.

enter image description here

This is an example of a dynamically generated polygon in my django code, so the shapes can be different in other cases. The final goal is to get the length of the red line (sorry about the poor GIMP job!).

I did not find a solution using Django GEOGeometry.

As for Postgis, the best I could do was removing the holes, making a polygon from my shape, buffering a bit, and using the boundary of the final shape to calculate the length. Here's the query for this process:

SELECT st_asgeojson(
           ST_Boundary(
               ST_Buffer(
                   ST_Collect(
                       ST_MakePolygon(geom)
                     ),
                   0.0001
                 )
             )::geography
         ) As geom
FROM (
       SELECT ST_ExteriorRing(
                  (ST_Dump(
                      ST_SetSRID(
                          ST_GeomFromGeojson(
                              '{ "type": "MultiPolygon", "coordinates": [...]}'
                            ),
                          4326
                        )
                    )).geom
                ) AS geom
     ) AS foo

And here is the geojson object for the example in the screenshot:
https://gist.github.com/ka7eh/427d071c7077340cdc128f3624b30777

So my questions are:

  • Is there any way to do this directly in Python?
  • If not, is there a more straight-forward way of handling this in Postgis?
  • Are there any downfalls to my solution? I mean whether there might be situations that my query returns unexpected results? The only tricky part I can think of right now is the buffer value and how it might mess up my geometry.

Best Answer

If not, is there a more straight-forward way of handling this in Postgis?

I do not have your data, and if I understand you correctly, then this script will do your work, I have translation difficulties,

SELECT ST_Boundary(st_buffer( (st_dump( st_union( st_buffer(geom, 1.0)))).geom, 0.5)) FROM source_table;

play the buffer zones so that you get the required value :-), OS... `