add a WKB decoder for the Point class

This allows to return point geometries from the database and makes
the SQL a bit simpler.
This commit is contained in:
Sarah Hoffmann
2023-02-16 15:35:54 +01:00
parent b320f1c7e3
commit ee0c5e24bb
5 changed files with 39 additions and 22 deletions

View File

@@ -10,6 +10,7 @@ Complex datatypes used by the Nominatim API.
from typing import Optional, Union, NamedTuple
import dataclasses
import enum
from struct import unpack
@dataclasses.dataclass
class PlaceID:
@@ -55,6 +56,33 @@ class Point(NamedTuple):
return self.x
def to_geojson(self) -> str:
""" Return the point in GeoJSON format.
"""
return f'{{"type": "Point","coordinates": [{self.x}, {self.y}]}}'
@staticmethod
def from_wkb(wkb: bytes) -> 'Point':
""" Create a point from EWKB as returned from the database.
"""
if len(wkb) != 25:
raise ValueError("Point wkb has unexpected length")
if wkb[0] == 0:
gtype, srid, x, y = unpack('>iidd', wkb[1:])
elif wkb[0] == 1:
gtype, srid, x, y = unpack('<iidd', wkb[1:])
else:
raise ValueError("WKB has unknown endian value.")
if gtype != 0x20000001:
raise ValueError("WKB must be a point geometry.")
if srid != 4326:
raise ValueError("Only WGS84 WKB supported.")
return Point(x, y)
class GeometryFormat(enum.Flag):
""" Geometry output formats supported by Nominatim.
"""