add python implementation of reverse

This adds an additional layer parameter and slightly changes the
queries to do more efficient lookups for large area features.
This commit is contained in:
Sarah Hoffmann
2023-03-22 00:07:17 +01:00
parent ebcf8c2b6b
commit 41da298b18
6 changed files with 650 additions and 7 deletions

View File

@@ -7,7 +7,7 @@
"""
Complex datatypes used by the Nominatim API.
"""
from typing import Optional, Union, NamedTuple
from typing import Optional, Union, Tuple, NamedTuple
import dataclasses
import enum
from struct import unpack
@@ -83,6 +83,74 @@ class Point(NamedTuple):
return Point(x, y)
AnyPoint = Union[Point, Tuple[float, float]]
class Bbox:
""" A bounding box in WSG84 projection.
The coordinates are available as an array in the 'coord'
property in the order (minx, miny, maxx, maxy).
"""
def __init__(self, minx: float, miny: float, maxx: float, maxy: float) -> None:
self.coords = (minx, miny, maxx, maxy)
@property
def minlat(self) -> float:
""" Southern-most latitude, corresponding to the minimum y coordinate.
"""
return self.coords[1]
@property
def maxlat(self) -> float:
""" Northern-most latitude, corresponding to the maximum y coordinate.
"""
return self.coords[3]
@property
def minlon(self) -> float:
""" Western-most longitude, corresponding to the minimum x coordinate.
"""
return self.coords[0]
@property
def maxlon(self) -> float:
""" Eastern-most longitude, corresponding to the maximum x coordinate.
"""
return self.coords[2]
@staticmethod
def from_wkb(wkb: Optional[bytes]) -> 'Optional[Bbox]':
""" Create a Bbox from a bounding box polygon as returned by
the database. Return s None if the input value is None.
"""
if wkb is None:
return None
if len(wkb) != 97:
raise ValueError("WKB must be a bounding box polygon")
if wkb.startswith(b'\x01\x03\x00\x00\x20\xE6\x10\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00'):
x1, y1, _, _, x2, y2 = unpack('<dddddd', wkb[17:65])
elif wkb.startswith(b'\x00\x20\x00\x00\x03\x00\x00\x10\xe6\x00\x00\x00\x01\x00\x00\x00\x05'):
x1, y1, _, _, x2, y2 = unpack('>dddddd', wkb[17:65])
else:
raise ValueError("WKB has wrong header")
return Bbox(min(x1, x2), min(y1, y2), max(x1, x2), max(y1, y2))
def from_point(pt: Point, buffer: float) -> 'Bbox':
""" Return a Bbox around the point with the buffer added to all sides.
"""
return Bbox(pt[0] - buffer, pt[1] - buffer,
pt[0] + buffer, pt[1] + buffer)
class GeometryFormat(enum.Flag):
""" Geometry output formats supported by Nominatim.
"""
@@ -117,3 +185,18 @@ class LookupDetails:
keywords: bool = False
""" Add information about the search terms used for this place.
"""
geometry_simplification: float = 0.0
""" Simplification factor for a geometry in degrees WGS. A factor of
0.0 means the original geometry is kept. The higher the value, the
more the geometry gets simplified.
"""
class DataLayer(enum.Flag):
""" Layer types that can be selected for reverse and forward search.
"""
POI = enum.auto()
ADDRESS = enum.auto()
RAILWAY = enum.auto()
MANMADE = enum.auto()
NATURAL = enum.auto()