[polygons] Adding methods for fixing polygons in base RTreePolygonIndex, moving the current polygon index to an instance variable and adding ability to import from a general GeoJSON-like structure instead of just shapefiles
This commit is contained in:
@@ -45,6 +45,8 @@ class RTreePolygonIndex(object):
|
|||||||
else:
|
else:
|
||||||
self.polygons = polygons
|
self.polygons = polygons
|
||||||
|
|
||||||
|
self.i = 0
|
||||||
|
|
||||||
def index_polygon(self, id, polygon):
|
def index_polygon(self, id, polygon):
|
||||||
self.index.insert(id, polygon.bounds)
|
self.index.insert(id, polygon.bounds)
|
||||||
|
|
||||||
@@ -74,25 +76,81 @@ class RTreePolygonIndex(object):
|
|||||||
|
|
||||||
f = fiona.open(input_file)
|
f = fiona.open(input_file)
|
||||||
|
|
||||||
i = 0
|
index.add_geojson_like_file(f)
|
||||||
|
|
||||||
for rec in f:
|
return index
|
||||||
if not rec or not rec.get('geometry') or 'type' not in rec['geometry']:
|
|
||||||
|
@classmethod
|
||||||
|
def fix_polygon(cls, poly):
|
||||||
|
'''
|
||||||
|
Coerce to valid polygon
|
||||||
|
'''
|
||||||
|
if not poly.is_valid:
|
||||||
|
poly = poly.buffer(0)
|
||||||
|
if not poly.is_valid:
|
||||||
|
return None
|
||||||
|
return poly
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def to_polygon(cls, coords):
|
||||||
|
'''
|
||||||
|
Create shapely polygon from list of coordinate tuples if valid
|
||||||
|
'''
|
||||||
|
if not coords or len(coords) < 3:
|
||||||
|
return None
|
||||||
|
poly = Polygon(coords)
|
||||||
|
return cls.fix_polygon(poly)
|
||||||
|
|
||||||
|
def add_geojson_like_record(self, rec, include_only_properties=None):
|
||||||
|
if not rec or not rec.get('geometry') or 'type' not in rec['geometry']:
|
||||||
|
return
|
||||||
|
poly_type = rec['geometry']['type']
|
||||||
|
if poly_type == 'Polygon':
|
||||||
|
coords = rec['geometry']['coordinates'][0]
|
||||||
|
poly = self.to_polygon(coords)
|
||||||
|
if poly is None or not poly.bounds or len(poly.bounds) != 4:
|
||||||
|
return
|
||||||
|
self.index_polygon(self.i, poly)
|
||||||
|
self.add_polygon(poly, rec['properties'], include_only_properties=include_only_properties)
|
||||||
|
elif poly_type == 'MultiPolygon':
|
||||||
|
polys = []
|
||||||
|
poly_coords = rec['geometry']['coordinates']
|
||||||
|
for coords in poly_coords:
|
||||||
|
poly = self.to_polygon(coords[0])
|
||||||
|
if poly is None or not poly.bounds or len(poly.bounds) != 4:
|
||||||
continue
|
continue
|
||||||
poly_type = rec['geometry']['type']
|
polys.append(poly)
|
||||||
if poly_type == 'Polygon':
|
self.index_polygon(self.i, poly)
|
||||||
poly = Polygon(rec['geometry']['coordinates'][0])
|
|
||||||
index.index_polygon(i, poly)
|
self.add_polygon(MultiPolygon(polys), rec['properties'], include_only_properties=include_only_properties)
|
||||||
index.add_polygon(poly, rec['properties'], include_only_properties=include_props)
|
else:
|
||||||
elif poly_type == 'MultiPolygon':
|
return
|
||||||
polys = []
|
self.i += 1
|
||||||
for coords in rec['geometry']['coordinates']:
|
|
||||||
poly = Polygon(coords[0])
|
def add_geojson_like_file(self, f, include_only_properties=None):
|
||||||
polys.append(poly)
|
'''
|
||||||
index.index_polygon(i, poly)
|
Add either GeoJSON or a shapefile record to the index
|
||||||
|
'''
|
||||||
|
|
||||||
|
for rec in f:
|
||||||
|
self.add_geojson_like_record(rec, include_only_properties=include_only_properties)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_from_geojson_files(cls, inputs, output_dir,
|
||||||
|
index_filename=DEFAULT_INDEX_FILENAME,
|
||||||
|
polys_filename=DEFAULT_POLYS_FILENAME,
|
||||||
|
include_only_properties=None):
|
||||||
|
index = cls(save_dir=output_dir, index_filename=index_filename)
|
||||||
|
for input_file in inputs:
|
||||||
|
if include_only_properties is not None:
|
||||||
|
include_props = include_only_properties.get(input_file, cls.include_only_properties)
|
||||||
|
else:
|
||||||
|
include_props = cls.include_only_properties
|
||||||
|
|
||||||
|
f = json.load(open(input_file))
|
||||||
|
|
||||||
|
index.add_geojson_like_file(f['features'], include_only_properties=include_props)
|
||||||
|
|
||||||
index.add_polygon(MultiPolygon(polys), rec['properties'], include_only_properties=include_props)
|
|
||||||
i += 1
|
|
||||||
return index
|
return index
|
||||||
|
|
||||||
def save_polygons(self, out_filename):
|
def save_polygons(self, out_filename):
|
||||||
|
|||||||
Reference in New Issue
Block a user