[polygons] adding optional test_point for complex polygons with an admin_center, and including admin_center lat/lon as part of the properties
This commit is contained in:
@@ -153,7 +153,7 @@ class PolygonIndex(object):
|
||||
return poly
|
||||
|
||||
@classmethod
|
||||
def to_polygon(cls, coords, holes=None):
|
||||
def to_polygon(cls, coords, holes=None, test_point=None):
|
||||
'''
|
||||
Create shapely polygon from list of coordinate tuples if valid
|
||||
'''
|
||||
@@ -176,10 +176,15 @@ class PolygonIndex(object):
|
||||
if invalid:
|
||||
try:
|
||||
poly_fix = cls.fix_polygon(poly)
|
||||
if poly_fix is not None and poly_fix.bounds and len(poly_fix.bounds) == 4 and poly_fix.is_valid and (poly_fix.contains(poly.centroid) or poly_fix.contains(poly_fix.representative_point())):
|
||||
poly = poly_fix
|
||||
|
||||
if poly_fix is not None and poly_fix.bounds and len(poly_fix.bounds) == 4 and poly_fix.is_valid and poly_fix.type == poly.type:
|
||||
if test_point is None:
|
||||
test_point = poly_fix.representative_point()
|
||||
|
||||
if poly_fix.contains(test_point):
|
||||
poly = poly_fix
|
||||
except Exception:
|
||||
poly = None
|
||||
pass
|
||||
|
||||
return poly
|
||||
|
||||
|
||||
@@ -340,10 +340,18 @@ class OSMReverseGeocoder(RTreePolygonIndex):
|
||||
|
||||
id_type, element_id = osm_type_and_id(element_id)
|
||||
|
||||
test_point = None
|
||||
|
||||
if admin_center:
|
||||
props['admin_center'] = {k: v for k, v in six.iteritems(admin_center)
|
||||
if k in ('id', 'type', 'lat', 'lon') or k in cls.include_property_patterns or (six.u(':') in k and
|
||||
six.u('{}:*').format(k.split(six.u(':'), 1)[0]) in cls.include_property_patterns)}
|
||||
admin_center_props = {k: v for k, v in six.iteritems(admin_center)
|
||||
if k in ('id', 'type', 'lat', 'lon') or k in cls.include_property_patterns or (six.u(':') in k and
|
||||
six.u('{}:*').format(k.split(six.u(':'), 1)[0]) in cls.include_property_patterns)}
|
||||
|
||||
if cls.fix_invalid_polygons:
|
||||
center_lat, center_lon = latlon_to_decimal(admin_center_props['lat'], admin_center_props['lon'])
|
||||
test_point = Point(center_lon, center_lat)
|
||||
|
||||
props['admin_center'] = admin_center_props
|
||||
|
||||
if inner_polys and not outer_polys:
|
||||
logger.warn('inner polygons with no outer')
|
||||
@@ -363,12 +371,8 @@ class OSMReverseGeocoder(RTreePolygonIndex):
|
||||
# Validate inner polygons (holes)
|
||||
for p in inner_polys:
|
||||
poly = cls.to_polygon(p)
|
||||
if poly is None or not poly.bounds or len(poly.bounds) != 4:
|
||||
if poly is None or not poly.bounds or len(poly.bounds) != 4 or not poly.is_valid:
|
||||
continue
|
||||
if not poly.is_valid:
|
||||
poly = cls.fix_polygon(poly)
|
||||
if poly is None or not poly.bounds or len(poly.bounds) != 4:
|
||||
continue
|
||||
|
||||
if poly.type != 'MultiPolygon':
|
||||
inner.append(poly)
|
||||
@@ -377,7 +381,7 @@ class OSMReverseGeocoder(RTreePolygonIndex):
|
||||
|
||||
# Validate outer polygons
|
||||
for p in outer_polys:
|
||||
poly = cls.to_polygon(p)
|
||||
poly = cls.to_polygon(p, test_point=admin_center_point)
|
||||
if poly is None or not poly.bounds or len(poly.bounds) != 4:
|
||||
continue
|
||||
|
||||
@@ -390,7 +394,7 @@ class OSMReverseGeocoder(RTreePolygonIndex):
|
||||
|
||||
if interior:
|
||||
# Polygon with holes constructor
|
||||
poly = cls.to_polygon(p, [zip(*p2.exterior.coords.xy) for p2 in interior])
|
||||
poly = cls.to_polygon(p, [zip(*p2.exterior.coords.xy) for p2 in interior], test_point=admin_center_point)
|
||||
if poly is None or not poly.bounds or len(poly.bounds) != 4:
|
||||
continue
|
||||
# R-tree only stores the bounding box, so add the whole polygon
|
||||
|
||||
Reference in New Issue
Block a user