Since you mentioned you had access to docker, you can utilize this postgis image to clean/export your geometries in a single docker run
command:
docker run -it --rm -e POSTGRES_PASSWORD=mysecretpassword \
--mount type=bind,source=<host_shapefile_location>,target=/tmp/shapedir \
mdillon/postgis bash -c "
apt-get update && apt-get install gdal-bin && tee /docker-entrypoint-initdb.d/z.sh <<EOF
psql -c $'CREATE DATABASE ogr WITH TEMPLATE = 'template_postgis''
ogr2ogr -f 'PostgreSQL' -a_srs 'EPSG:<YOUR_SRID>' PG:'host=localhost user=postgres dbname=ogr password=mysecretpassword' /tmp/shapedir/myshp.shp -nlt MULTIPOLYGON -lco GEOMETRY_NAME=geom -nln myshp
ogr2ogr -overwrite -f 'ESRI Shapefile' /tmp/shapedir/output.shp PG:'host=localhost user=postgres dbname=ogr password=mysecretpassword' -sql 'SELECT myfield, st_collectionextract(st_makevalid(st_buffer(st_makevalid(geom),0)),3) FROM myshp'
EOF
/docker-entrypoint.sh postgres"
This command does the following:
- Bind mounts the host directory containing the shapefile to /tmp/shapedir in the container.
- Installs "vanilla" GDAL into the container.
- Creates a Postgis database suitable for processing the shapefile.
- Uses ogr2ogr to import the shapefile into the newly created database (and coerces the geometry to MULTIPOLYGON for the sake of simplicity and sanity)
- Cleans geometries using
st_makevalid(geom)
and st_buffer(geom,0)
and then applies st_collectionextract(geom,3)
to ensure that only multipolygons are returned.
- Exports the cleaned geometry to the specified host directory.
Once your cleaned shapefile has successfully exported, just ctrl +c
in your terminal to stop and remove the temporary container.
Note: Make sure to explicitly provide the correct EPSG code via a_srs
-OGR is not great at autodetecting it! You can look up the correct projection by pasting the contents of the .prj file here