Inspired by comments I saw today on the internet, this is how you spatially clean features using Fiona and Shapely (for small values of dirty).
import logging import sys from shapely.geometry import mapping, shape from fiona import collection logging.basicConfig(stream=sys.stderr, level=logging.INFO) with collection("docs/data/test_uk.shp", "r") as input: schema = input.schema.copy() with collection( "with-shapely.shp", "w", "ESRI Shapefile", schema ) as output: for f in input: try: # Make a shapely object from the dict. geom = shape(f['geometry']) if not geom.is_valid: # Use the 0-buffer polygon cleaning trick clean = geom.buffer(0.0) assert clean.geom_type == 'Polygon' assert clean.is_valid geom = clean # Make a dict from the shapely object. f['geometry'] = mapping(geom) output.write(f) except Exception, e: # Writing uncleanable features to a different shapefile # is another option. logging.exception("Error cleaning feature %s:", f['id'])
Makes a neat example, I think. Shapely just happens to provide this handy zero buffer feature (via GEOS), it's not required at all. Fiona just reads and writes GeoJSON-like mappings (like Python's
dict), it doesn't care what you do in between or what you do it with.
Update (2011-12-25): The error I noted in the comments is fixed above.