22import json
33import geojson
44import logging
5+ import code
56
67from .errors import (OverpassSyntaxError , TimeoutError , MultipleRequestsError ,
7- ServerLoadError , UnknownOverpassError , ServerRuntimeError )
8+ ServerLoadError , UnknownOverpassError , ServerRuntimeError )
89
910class 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