Skip to content

Commit 51c4ae9

Browse files
committed
added support for multipolygons
1 parent 4a61d9f commit 51c4ae9

File tree

1 file changed

+74
-19
lines changed

1 file changed

+74
-19
lines changed

overpass/api.py

Lines changed: 74 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
import json
33
import geojson
44
import logging
5+
import code
56

67
from .errors import (OverpassSyntaxError, TimeoutError, MultipleRequestsError,
7-
ServerLoadError, UnknownOverpassError, ServerRuntimeError)
8+
ServerLoadError, UnknownOverpassError, ServerRuntimeError)
89

910
class API(object):
1011
"""A simple Python wrapper for the OpenStreetMap Overpass API"""
@@ -135,6 +136,7 @@ def _GetFromOverpass(self, query):
135136
def _asGeoJSON(self, elements):
136137

137138
features = []
139+
no_match_count = 0
138140
for elem in elements:
139141
elem_type = elem["type"]
140142
if elem_type == "node":
@@ -164,7 +166,55 @@ def _asGeoJSON(self, elements):
164166
# conditions
165167
prev = "inner"
166168
not_first = False
167-
for mem in elem["members"]:
169+
170+
for pos in range(len(elem["members"])):
171+
mem = elem['members'][pos]
172+
173+
# check whether the coordinates of the next member need to be reversed
174+
# also sometimes the next member may not actually connect to the previous member, so if necessary, find a matching member
175+
if points != []:
176+
dist_start = (points[-1][0] - mem["geometry"][0]["lon"])**2 + (points[-1][1] - mem["geometry"][0]["lat"])**2
177+
dist_end = (points[-1][0] - mem["geometry"][-1]["lon"])**2 + (points[-1][1] - mem["geometry"][-1]["lat"])**2
178+
if dist_start == 0:
179+
pass # don't need to do anything
180+
elif dist_end == 0:
181+
# flip the next member - it is entered in the wrong direction
182+
mem["geometry"] = list(reversed(mem["geometry"]))
183+
else:
184+
# try flipping the previous member
185+
dist_flipped_start = (points[0][0] - mem["geometry"][0]["lon"])**2 + (points[0][1] - mem["geometry"][0]["lat"])**2
186+
dist_flipped_end = (points[0][0] - mem["geometry"][-1]["lon"])**2 + (points[0][1] - mem["geometry"][-1]["lat"])**2
187+
if dist_flipped_start == 0:
188+
# just flip the start
189+
points = list(reversed(points))
190+
elif dist_flipped_end == 0:
191+
# both need to be flipped
192+
points = list(reversed(points))
193+
mem["geometry"] = list(reversed(mem["geometry"]))
194+
else:
195+
# no matches -- look for a new match
196+
point_found = False
197+
for i in range(pos + 1, len(elem['members'])):
198+
if not point_found:
199+
new_pt = elem['members'][i]
200+
dist_start = (new_pt['geometry'][0]['lon'] - points[-1][0])**2 + (new_pt['geometry'][0]['lat'] - points[-1][1])**2
201+
dist_end = (new_pt['geometry'][-1]['lon'] - points[-1][0])**2 + (new_pt['geometry'][-1]['lat'] - points[-1][1])**2
202+
203+
if dist_start == 0 or dist_end == 0:
204+
point_found = True
205+
# swap the order of the members -- we have found the one we want
206+
elem['members'][pos], elem['members'][i] = elem['members'][i], elem['members'][pos]
207+
# save this new point as mem
208+
mem = elem['members'][pos]
209+
210+
if dist_end == 0:
211+
mem['geometry'] = list(reversed(mem['geometry']))
212+
213+
if not point_found:
214+
no_match_count += 1
215+
# don't work with this park
216+
continue
217+
168218
# address outer values
169219
if mem['role'] == 'outer':
170220
if prev == "inner":
@@ -175,13 +225,15 @@ def _asGeoJSON(self, elements):
175225
# append the previous poly to the polygon list
176226
polygons.append(poly)
177227
poly = []
178-
228+
179229
for coords in mem["geometry"]:
180-
points.append([coords["lon"], coords["lat"]])
230+
try:
231+
points.append([coords["lon"], coords["lat"]])
232+
except:
233+
code.interact(local=locals())
181234

182235
if points[-1] == points[0]:
183236
# finish the outer polygon if it has met the start
184-
is_complete = True
185237
poly.append(points)
186238
points = []
187239
# update condition
@@ -200,20 +252,23 @@ def _asGeoJSON(self, elements):
200252
prev = "inner"
201253

202254
not_first = True
203-
#
255+
256+
# add in the final poly
204257
polygons.append(poly)
205258

206259
if polygons != [[]]:
207-
# create MultiPolygon feature
208-
poly_props = elem.get("tags")
209-
poly_props.update({'id':elem['id']})
210-
multipoly = {"type": "Feature",
211-
"properties" : poly_props,
212-
"geometry": {
213-
"type": "MultiPolygon",
214-
"coordinates": polygons}}
215-
216-
# add to features
217-
features.append(multipoly)
218-
219-
return geojson.FeatureCollection(features)
260+
# create MultiPolygon feature - separate multipolygon for each outer
261+
for outer_poly in polygons:
262+
poly_props = elem.get("tags")
263+
poly_props.update({'id':elem['id']})
264+
multipoly = {"type": "Feature",
265+
"properties" : poly_props,
266+
"geometry": {
267+
"type": "MultiPolygon",
268+
"coordinates": [outer_poly]}}
269+
270+
# add to features
271+
features.append(multipoly)
272+
273+
print('number of unmatched parks: {}'.format(no_match_count))
274+
return geojson.FeatureCollection(features)

0 commit comments

Comments
 (0)