|
8 | 8 | import csv |
9 | 9 | import geojson |
10 | 10 | import logging |
11 | | -import code |
| 11 | +from shapely.geometry import Polygon, Point |
12 | 12 | from io import StringIO |
13 | 13 | from .errors import ( |
14 | 14 | OverpassSyntaxError, |
@@ -193,117 +193,38 @@ def _as_geojson(self, elements): |
193 | 193 | for elem in elements: |
194 | 194 | elem_type = elem.get("type") |
195 | 195 | elem_tags = elem.get("tags") |
196 | | - if elem_type and elem_type == "node": |
| 196 | + elem_geom = elem.get("geometry", []) |
| 197 | + if elem_type == "node": |
| 198 | + # Create Point geometry |
197 | 199 | geometry = geojson.Point((elem.get("lon"), elem.get("lat"))) |
198 | | - elif elem_type and elem_type == "way": |
199 | | - points = [] |
200 | | - geom = elem.get("geometry") |
201 | | - if geom: |
202 | | - for coords in elem.get("geometry"): |
203 | | - points.append((coords["lon"], coords["lat"])) |
204 | | - geometry = geojson.LineString(points) |
205 | | - elif elem_type and elem_type == "relation": |
206 | | - # initialize result lists |
| 200 | + elif elem_type == "way": |
| 201 | + # Create LineString geometry |
| 202 | + geometry = geojson.LineString([(coords["lon"], coords["lat"]) for coords in elem_geom]) |
| 203 | + elif elem_type == "relation": |
| 204 | + # Initialize polygon list |
207 | 205 | polygons = [] |
208 | | - poly = [] |
209 | | - points = [] |
210 | | - # conditions |
211 | | - prev = "inner" |
212 | | - not_first = False |
213 | | - |
214 | | - for pos in range(len(elem["members"])): |
215 | | - mem = elem['members'][pos] |
216 | | - |
217 | | - # check whether the coordinates of the next member need to be reversed |
218 | | - # also sometimes the next member may not actually connect to the previous member, so if necessary, |
219 | | - # find a matching member |
220 | | - if points: |
221 | | - dist_start = (points[-1][0] - mem["geometry"][0]["lon"]) ** 2 + ( |
222 | | - points[-1][1] - mem["geometry"][0]["lat"]) ** 2 |
223 | | - dist_end = (points[-1][0] - mem["geometry"][-1]["lon"]) ** 2 + ( |
224 | | - points[-1][1] - mem["geometry"][-1]["lat"]) ** 2 |
225 | | - if dist_start == 0: |
226 | | - pass # don't need to do anything |
227 | | - elif dist_end == 0: |
228 | | - # flip the next member - it is entered in the wrong direction |
229 | | - mem["geometry"] = list(reversed(mem["geometry"])) |
230 | | - else: |
231 | | - # try flipping the previous member |
232 | | - dist_flipped_start = (points[0][0] - mem["geometry"][0]["lon"]) ** 2 + ( |
233 | | - points[0][1] - mem["geometry"][0]["lat"]) ** 2 |
234 | | - dist_flipped_end = (points[0][0] - mem["geometry"][-1]["lon"]) ** 2 + ( |
235 | | - points[0][1] - mem["geometry"][-1]["lat"]) ** 2 |
236 | | - if dist_flipped_start == 0: |
237 | | - # just flip the start |
238 | | - points = list(reversed(points)) |
239 | | - elif dist_flipped_end == 0: |
240 | | - # both need to be flipped |
241 | | - points = list(reversed(points)) |
242 | | - mem["geometry"] = list(reversed(mem["geometry"])) |
243 | | - else: |
244 | | - # no matches -- look for a new match |
245 | | - point_found = False |
246 | | - for i in range(pos + 1, len(elem['members'])): |
247 | | - if not point_found: |
248 | | - new_pt = elem['members'][i] |
249 | | - dist_start = (new_pt['geometry'][0]['lon'] - points[-1][0]) ** 2 + ( |
250 | | - new_pt['geometry'][0]['lat'] - points[-1][1]) ** 2 |
251 | | - dist_end = (new_pt['geometry'][-1]['lon'] - points[-1][0]) ** 2 + ( |
252 | | - new_pt['geometry'][-1]['lat'] - points[-1][1]) ** 2 |
253 | | - |
254 | | - if dist_start == 0 or dist_end == 0: |
255 | | - point_found = True |
256 | | - # swap the order of the members -- we have found the one we want |
257 | | - elem['members'][pos], elem['members'][i] = elem['members'][i], \ |
258 | | - elem['members'][pos] |
259 | | - # save this new point as mem |
260 | | - mem = elem['members'][pos] |
261 | | - |
262 | | - if dist_end == 0: |
263 | | - mem['geometry'] = list(reversed(mem['geometry'])) |
264 | | - |
265 | | - # address outer values |
266 | | - if mem['role'] == 'outer': |
267 | | - if prev == "inner": |
268 | | - # start new outer polygon |
269 | | - points = [] |
270 | | - |
271 | | - if points == [] and not_first: |
272 | | - # append the previous poly to the polygon list |
273 | | - polygons.append(poly) |
274 | | - poly = [] |
275 | | - |
276 | | - for coords in mem["geometry"]: |
277 | | - try: |
278 | | - points.append([coords["lon"], coords["lat"]]) |
279 | | - except: |
280 | | - code.interact(local=locals()) |
281 | | - |
282 | | - if points[-1] == points[0]: |
283 | | - # finish the outer polygon if it has met the start |
284 | | - poly.append(points) |
285 | | - points = [] |
286 | | - # update condition |
287 | | - prev = "outer" |
288 | | - |
289 | | - # address inner points |
290 | | - if mem['role'] == "inner": |
291 | | - for coords in mem["geometry"]: |
292 | | - points.append([coords["lon"], coords["lat"]]) |
293 | | - |
294 | | - # check if the inner is complete |
295 | | - if points[-1] == points[0]: |
296 | | - poly.append(points) |
297 | | - points = [] |
298 | | - # update condition |
299 | | - prev = "inner" |
300 | | - |
301 | | - not_first = True |
302 | | - |
303 | | - # add in the final poly |
304 | | - polygons.append(poly) |
305 | | - |
306 | | - if polygons != [[]]: |
| 206 | + # First obtain the outer polygons |
| 207 | + for member in elem.get("members", []): |
| 208 | + if member["role"] == "outer": |
| 209 | + points = [(coords["lon"], coords["lat"]) for coords in member.get('geometry', [])] |
| 210 | + # Check that the outer polygon is complete |
| 211 | + if points and points[-1] == points[0]: |
| 212 | + polygons.append([points]) |
| 213 | + # Then get the inner polygons |
| 214 | + for member in elem.get("members", []): |
| 215 | + if member["role"] == "inner": |
| 216 | + points = [(coords["lon"], coords["lat"]) for coords in member.get('geometry', [])] |
| 217 | + # Check that the inner polygon is complete |
| 218 | + if points and points[-1] == points[0]: |
| 219 | + # We need to check to which outer polygon the inner polygon belongs |
| 220 | + point = Point(points[0]) |
| 221 | + for poly in polygons: |
| 222 | + polygon = Polygon(poly[0]) |
| 223 | + if polygon.contains(point): |
| 224 | + poly.append(points) |
| 225 | + break |
| 226 | + # Finally create MultiPolygon geometry |
| 227 | + if polygons: |
307 | 228 | geometry = geojson.MultiPolygon(polygons) |
308 | 229 | else: |
309 | 230 | continue |
|
0 commit comments