From 0094d0762157b07e2860d39191aed9ee0d7eb29e Mon Sep 17 00:00:00 2001 From: Al Date: Thu, 14 Jul 2016 16:36:58 -0400 Subject: [PATCH] [osm] Adding admin_center properties to admin boundary polygons --- scripts/geodata/osm/admin_boundaries.py | 25 ++++++++++++++++----- scripts/geodata/polygons/reverse_geocode.py | 7 +++++- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/scripts/geodata/osm/admin_boundaries.py b/scripts/geodata/osm/admin_boundaries.py index e7a5b34b..3b03e7ba 100644 --- a/scripts/geodata/osm/admin_boundaries.py +++ b/scripts/geodata/osm/admin_boundaries.py @@ -14,6 +14,7 @@ from collections import defaultdict, OrderedDict from itertools import izip, combinations from geodata.coordinates.conversion import latlon_to_decimal +from geodata.file_utils import ensure_dir from geodata.graph.scc import strongly_connected_components from geodata.math.floats import isclose from geodata.osm.extract import * @@ -49,6 +50,8 @@ class OSMPolygonReader(object): self.coords = array.array('d') + self.nodes = {} + self.way_deps = array.array('l') self.way_coords = array.array('d') self.way_indptr = array.array('i', [0]) @@ -203,6 +206,9 @@ class OSMPolygonReader(object): if isclose(lon, 180.0): lon = 179.999 + if 'name' in props: + self.nodes[node_id] = props + # Nodes are stored in a sorted array, coordinate indices are simply # [lon, lat, lon, lat ...] so the index can be calculated as 2 * i # Note that the pairs are lon, lat instead of lat, lon for geometry purposes @@ -233,7 +239,7 @@ class OSMPolygonReader(object): if deps[0] == deps[-1] and self.include_polygon(props): outer_polys = self.create_polygons([way_id]) inner_polys = [] - yield WAY_OFFSET + way_id, props, outer_polys, inner_polys + yield WAY_OFFSET + way_id, props, {}, outer_polys, inner_polys elif element_id.startswith('relation'): if self.node_ids is not None: @@ -248,16 +254,25 @@ class OSMPolygonReader(object): outer_ways = [] inner_ways = [] - for way_id, role in deps: + for elem_id, role in deps: if role == 'outer': - outer_ways.append(way_id) + outer_ways.append(elem_id) elif role == 'inner': - inner_ways.append(way_id) + inner_ways.append(elem_id) + elif role == 'admin_centre': + val = self.nodes.get(long(elem_id)) + val['id'] = long(elem_id) + if val is not None: + admin_centers.append(val) outer_polys = self.create_polygons(outer_ways) inner_polys = self.create_polygons(inner_ways) - yield RELATION_OFFSET + relation_id, props, outer_polys, inner_polys + admin_center = {} + if len(admin_centers) == 1: + admin_center = admin_centers[0] + + yield RELATION_OFFSET + relation_id, props, admin_center, outer_polys, inner_polys if i % 1000 == 0 and i > 0: self.logger.info('doing {}s, at {}'.format(element_id.split(':')[0], i)) i += 1 diff --git a/scripts/geodata/polygons/reverse_geocode.py b/scripts/geodata/polygons/reverse_geocode.py index 835cafa1..21d96c99 100644 --- a/scripts/geodata/polygons/reverse_geocode.py +++ b/scripts/geodata/polygons/reverse_geocode.py @@ -326,7 +326,7 @@ class OSMReverseGeocoder(RTreePolygonIndex): logger = logging.getLogger('osm.reverse_geocode') - for element_id, props, outer_polys, inner_polys in polygons: + for element_id, props, admin_center, outer_polys, inner_polys in polygons: props = {k: v for k, v in six.iteritems(props) if 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)} @@ -335,6 +335,11 @@ class OSMReverseGeocoder(RTreePolygonIndex): props['type'] = id_type props['id'] = element_id + if admin_center: + props['admin_center'] = {k: v for k, v in six.iteritems(admin_center) + if 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 inner_polys and not outer_polys: logger.warn('inner polygons with no outer') continue