Skip to content
This repository was archived by the owner on Jun 10, 2025. It is now read-only.

Replace homegrown converter with osm2geojson #140

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions Pipfile
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
[[source]]
url = "https://pypi.python.org/simple"
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
geojson = ">=1.3.1"
pytest = "6.0.0"
requests = ">=2.20.0"
shapely = ">=1.6.4"
osm2geojson = ">=0.1.30"
requests = ">=2.8.1"

[dev-packages]
geojson = ">=1.3.1"
pytest = "6.0.0"
requests-mock = "*"

[requires]
83 changes: 2 additions & 81 deletions overpass/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@
from math import ceil
from typing import Optional

import geojson
import requests
from shapely.geometry import Point, Polygon
from osm2geojson import json2geojson

from .errors import (
MultipleRequestsError,
Expand Down Expand Up @@ -136,7 +135,7 @@ def get(self, query, responseformat="geojson", verbosity="body", build=True, dat
return response

# construct geojson
return self._as_geojson(response["elements"])
return json2geojson(response)

@staticmethod
def _api_status() -> dict:
Expand Down Expand Up @@ -294,81 +293,3 @@ def _get_from_overpass(self, query):
else:
r.encoding = "utf-8"
return r

def _as_geojson(self, elements):
ids_already_seen = set()
features = []
geometry = None
for elem in elements:
try:
if elem["id"] in ids_already_seen:
continue
ids_already_seen.add(elem["id"])
except KeyError:
raise UnknownOverpassError("Received corrupt data from Overpass (no id).")
elem_type = elem.get("type")
elem_tags = elem.get("tags", {})
elem_nodes = elem.get("nodes", None)
elem_timestamp = elem.get("timestamp", None)
elem_user = elem.get("user", None)
elem_uid = elem.get("uid", None)
elem_version = elem.get("version", None)
if elem_nodes:
elem_tags["nodes"] = elem_nodes
if elem_user:
elem_tags["user"] = elem_user
if elem_uid:
elem_tags["uid"] = elem_uid
if elem_version:
elem_tags["version"] = elem_version
elem_geom = elem.get("geometry", [])
if elem_type == "node":
# Create Point geometry
geometry = geojson.Point((elem.get("lon"), elem.get("lat")))
elif elem_type == "way":
# Create LineString geometry
geometry = geojson.LineString([(coords["lon"], coords["lat"]) for coords in elem_geom])
elif elem_type == "relation":
# Initialize polygon list
polygons = []
# First obtain the outer polygons
for member in elem.get("members", []):
if member["role"] == "outer":
points = [(coords["lon"], coords["lat"]) for coords in member.get("geometry", [])]
# Check that the outer polygon is complete
if points and points[-1] == points[0]:
polygons.append([points])
else:
raise UnknownOverpassError("Received corrupt data from Overpass (incomplete polygon).")
# Then get the inner polygons
for member in elem.get("members", []):
if member["role"] == "inner":
points = [(coords["lon"], coords["lat"]) for coords in member.get("geometry", [])]
# Check that the inner polygon is complete
if not points or points[-1] != points[0]:
raise UnknownOverpassError("Received corrupt data from Overpass (incomplete polygon).")
# We need to check to which outer polygon the inner polygon belongs
point = Point(points[0])
for poly in polygons:
polygon = Polygon(poly[0])
if polygon.contains(point):
poly.append(points)
break
else:
raise UnknownOverpassError("Received corrupt data from Overpass (inner polygon cannot "
"be matched to outer polygon).")
# Finally create MultiPolygon geometry
if polygons:
geometry = geojson.MultiPolygon(polygons)
else:
raise UnknownOverpassError("Received corrupt data from Overpass (invalid element).")

if geometry:
feature = geojson.Feature(
id=elem["id"],
geometry=geometry,
properties=elem_tags
)
features.append(feature)

return geojson.FeatureCollection(features)
1 change: 1 addition & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pytest>=6.2.0
requests-mock[fixture]
tox>=3.20.1
geojson>=1.3.1
4 changes: 1 addition & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
geojson>=1.3.1
pytest
osm2geojson>=0.1.30
requests>=2.8.1
shapely>=1.6.4
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@
"Topic :: Scientific/Engineering :: GIS",
"Topic :: Utilities",
],
install_requires=["requests>=2.3.0", "geojson>=1.0.9", "shapely>=1.6.4"],
extras_require={"test": ["pytest", "requests-mock[fixture]"]},
install_requires=["requests>=2.3.0", "osm2geojson"],
extras_require={"test": ["pytest", "requests-mock[fixture]", "geojson>=1.0.9"]},
)
Loading