|
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