]> git.openstreetmap.org Git - nominatim.git/commitdiff
python reverse: add support for point geometries in interpolations
authorSarah Hoffmann <lonvia@denofr.de>
Wed, 29 Mar 2023 15:21:33 +0000 (17:21 +0200)
committerSarah Hoffmann <lonvia@denofr.de>
Wed, 29 Mar 2023 15:21:33 +0000 (17:21 +0200)
nominatim/api/reverse.py
test/python/api/test_api_reverse.py

index f454a83777073a3ee90f516a5d7d9902e842ded4..1c9cd4c1708bf435c2dbd5348fb9ddba1f87204e 100644 (file)
@@ -66,6 +66,14 @@ def _interpolated_position(table: SaFromClause) -> SaLabel:
               else_=table.c.linegeo.ST_LineInterpolatePoint(rounded_pos)).label('centroid')
 
 
+def _locate_interpolation(table: SaFromClause, wkt: WKTElement) -> SaLabel:
+    """ Given a position, locate the closest point on the line.
+    """
+    return sa.case((table.c.linegeo.ST_GeometryType() == 'ST_LineString',
+                    sa.func.ST_LineLocatePoint(table.c.linegeo, wkt)),
+                   else_=0).label('position')
+
+
 def _is_address_point(table: SaFromClause) -> SaColumn:
     return sa.and_(table.c.rank_address == 30,
                    sa.or_(table.c.housenumber != None,
@@ -207,7 +215,7 @@ class ReverseGeocoder:
 
         sql = sa.select(t,
                         t.c.linegeo.ST_Distance(wkt).label('distance'),
-                        t.c.linegeo.ST_LineLocatePoint(wkt).label('position'))\
+                        _locate_interpolation(t, wkt))\
                 .where(t.c.linegeo.ST_DWithin(wkt, distance))\
                 .where(t.c.startnumber != None)\
                 .order_by('distance')\
@@ -239,7 +247,7 @@ class ReverseGeocoder:
 
         inner = sa.select(t,
                           t.c.linegeo.ST_Distance(wkt).label('distance'),
-                          sa.func.ST_LineLocatePoint(t.c.linegeo, wkt).label('position'))\
+                          _locate_interpolation(t, wkt))\
                   .where(t.c.linegeo.ST_DWithin(wkt, 0.001))\
                   .where(t.c.parent_place_id == parent_place_id)\
                   .order_by('distance')\
index e78dc0711165298ca101663dbdb11157fb4639e3..d1d47f8454e10f3fa91c237d23b4e378393a0115 100644 (file)
@@ -135,6 +135,23 @@ def test_reverse_housenumber_interpolation(apiobj):
     assert apiobj.api.reverse((10.0, 10.0)).place_id == 992
 
 
+def test_reverse_housenumber_point_interpolation(apiobj):
+    apiobj.add_placex(place_id=990, class_='highway', type='service',
+                      rank_search=27, rank_address=27,
+                      name = {'name': 'My Street'},
+                      centroid=(10.0, 10.0),
+                      geometry='LINESTRING(9.995 10, 10.005 10)')
+    apiobj.add_osmline(place_id=992,
+                       parent_place_id=990,
+                       startnumber=42, endnumber=42, step=1,
+                       centroid=(10.0, 10.00001),
+                       geometry='POINT(10.0 10.00001)')
+
+    res = apiobj.api.reverse((10.0, 10.0))
+    assert res.place_id == 992
+    assert res.housenumber == '42'
+
+
 def test_reverse_tiger_number(apiobj):
     apiobj.add_placex(place_id=990, class_='highway', type='service',
                       rank_search=27, rank_address=27,
@@ -152,6 +169,24 @@ def test_reverse_tiger_number(apiobj):
     assert apiobj.api.reverse((10.0, 10.00001)).place_id == 992
 
 
+def test_reverse_point_tiger(apiobj):
+    apiobj.add_placex(place_id=990, class_='highway', type='service',
+                      rank_search=27, rank_address=27,
+                      name = {'name': 'My Street'},
+                      centroid=(10.0, 10.0),
+                      country_code='us',
+                      geometry='LINESTRING(9.995 10, 10.005 10)')
+    apiobj.add_tiger(place_id=992,
+                     parent_place_id=990,
+                     startnumber=1, endnumber=1, step=1,
+                     centroid=(10.0, 10.00001),
+                     geometry='POINT(10.0 10.00001)')
+
+    res = apiobj.api.reverse((10.0, 10.0))
+    assert res.place_id == 992
+    assert res.housenumber == '1'
+
+
 def test_reverse_low_zoom_address(apiobj):
     apiobj.add_placex(place_id=1001, class_='place', type='house',
                       housenumber='1',