Skip to content

Commit 5fabd38

Browse files
author
Lukas Müller
committed
Bugfixed and cleaned up _as_geojson method
1 parent f0c4560 commit 5fabd38

File tree

4 files changed

+34
-111
lines changed

4 files changed

+34
-111
lines changed

Diff for: Pipfile

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ name = "pypi"
77
geojson = ">=1.3.1"
88
requests = ">=2.20.0"
99
nose = ">=1.3.7"
10+
shapely = ">=1.6.4"
1011

1112
[dev-packages]
1213

Diff for: overpass/api.py

+31-110
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import csv
99
import geojson
1010
import logging
11-
import code
11+
from shapely.geometry import Polygon, Point
1212
from io import StringIO
1313
from .errors import (
1414
OverpassSyntaxError,
@@ -193,117 +193,38 @@ def _as_geojson(self, elements):
193193
for elem in elements:
194194
elem_type = elem.get("type")
195195
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
197199
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
207205
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:
307228
geometry = geojson.MultiPolygon(polygons)
308229
else:
309230
continue

Diff for: requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
geojson>=1.3.1
22
requests>=2.8.1
33
nose>=1.3.7
4+
shapely>=1.6.4

Diff for: setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@
2222
"Topic :: Scientific/Engineering :: GIS",
2323
"Topic :: Utilities",
2424
],
25-
install_requires=["requests>=2.3.0", "geojson>=1.0.9"],
25+
install_requires=["requests>=2.3.0", "geojson>=1.0.9", "shapely>=1.6.4"],
2626
extras_require={"test": ["pytest"]},
2727
)

0 commit comments

Comments
 (0)