]> git.openstreetmap.org Git - nominatim.git/commitdiff
correctly handle single-point interpolations in reverse
authorSarah Hoffmann <lonvia@denofr.de>
Wed, 16 Mar 2022 10:19:09 +0000 (11:19 +0100)
committerSarah Hoffmann <lonvia@denofr.de>
Wed, 16 Mar 2022 10:19:09 +0000 (11:19 +0100)
Lookup in location_property_osmline needs to be special cased
for startnumber = endnumber. Also adds tests for the case.

Fixes #2680.

lib-php/ReverseGeocode.php
test/bdd/db/query/interpolation.feature [new file with mode: 0644]
test/bdd/steps/http_responses.py
test/bdd/steps/steps_api_queries.py

index 646c592b9f5d4b3dc5efba035406602f0b44d3bc..35103aeb3f78681e93fc5e3aa0c287fb498739df 100644 (file)
@@ -64,7 +64,9 @@ class ReverseGeocode
     {
         Debug::newFunction('lookupInterpolation');
         $sSQL = 'SELECT place_id, parent_place_id, 30 as rank_search,';
-        $sSQL .= '  (endnumber - startnumber) * ST_LineLocatePoint(linegeo,'.$sPointSQL.') as fhnr,';
+        $sSQL .= '  (CASE WHEN endnumber != startnumber';
+        $sSQL .= '        THEN (endnumber - startnumber) * ST_LineLocatePoint(linegeo,'.$sPointSQL.')';
+        $sSQL .= '        ELSE startnumber END) as fhnr,';
         $sSQL .= '  startnumber, endnumber, step,';
         $sSQL .= '  ST_Distance(linegeo,'.$sPointSQL.') as distance';
         $sSQL .= ' FROM location_property_osmline';
diff --git a/test/bdd/db/query/interpolation.feature b/test/bdd/db/query/interpolation.feature
new file mode 100644 (file)
index 0000000..602ac43
--- /dev/null
@@ -0,0 +1,58 @@
+@DB
+Feature: Query of address interpolations
+    Tests that interpolated addresses can be queried correctly
+
+    Background:
+        Given the grid
+          | 1  |  | 2  |  | 3  |
+          | 10 |  | 12 |  | 13 |
+          | 7  |  | 8  |  | 9  |
+
+    Scenario: Find interpolations with single number
+        Given the places
+          | osm | class   | type    | name    | geometry |
+          | W10 | highway | primary | Nickway | 10,12,13 |
+        And the places
+          | osm | class | type   | addr+interpolation | geometry |
+          | W1  | place | houses | odd                | 1,3      |
+        And the places
+          | osm | class | type  | housenr | geometry |
+          | N1  | place | house | 1       | 1        |
+          | N3  | place | house | 5       | 3        |
+        And the ways
+          | id | nodes |
+          | 1  | 1,3   |
+        When importing
+        When sending jsonv2 reverse point 2
+        Then results contain
+          | ID | display_name |
+          | 0  | 3, Nickway   |
+        When sending search query "Nickway 3"
+        Then results contain
+          | osm | display_name |
+          | W1  | 3, Nickway   |
+
+
+    Scenario: Find interpolations with multiple numbers
+        Given the places
+          | osm | class   | type    | name    | geometry |
+          | W10 | highway | primary | Nickway | 10,12,13 |
+        And the places
+          | osm | class | type   | addr+interpolation | geometry |
+          | W1  | place | houses | even               | 1,3      |
+        And the places
+          | osm | class | type  | housenr | geometry |
+          | N1  | place | house | 2       | 1        |
+          | N3  | place | house | 16      | 3        |
+        And the ways
+          | id | nodes |
+          | 1  | 1,3   |
+        When importing
+        When sending jsonv2 reverse point 2
+        Then results contain
+          | ID | display_name | centroid |
+          | 0  | 10, Nickway  | 2 |
+        When sending search query "Nickway 10"
+        Then results contain
+          | osm | display_name  | centroid |
+          | W1  | 10, Nickway   | 2 |
index fa6ab7fb3a051c46bcd9bd0a50b446b23f668a61..fa841d25be068147b298fa20124d06366d35c997 100644 (file)
@@ -62,6 +62,8 @@ class GenericResponse:
 
         if errorcode == 200 and fmt != 'debug':
             getattr(self, '_parse_' + fmt)()
+        else:
+            print("Bad response: ", page)
 
     def _parse_json(self):
         m = re.fullmatch(r'([\w$][^(]*)\((.*)\)', self.page)
@@ -128,7 +130,7 @@ class GenericResponse:
                    "\nBad value for row {} field '{}' in address. Expected: {}, got: {}.\nFull address: {}"""\
                        .format(idx, field, value, address[field], json.dumps(address, indent=4))
 
-    def match_row(self, row):
+    def match_row(self, row, context=None):
         """ Match the result fields against the given behave table row.
         """
         if 'ID' in row.headings:
@@ -151,7 +153,12 @@ class GenericResponse:
                     assert self.result[i]['osm_type'] in (OSM_TYPE[value[0]], value[0]), \
                            BadRowValueAssert(self, i, 'osm_type', value)
                 elif name == 'centroid':
-                    lon, lat = value.split(' ')
+                    if ' ' in value:
+                        lon, lat = value.split(' ')
+                    elif context is not None:
+                        lon, lat = context.osm.grid_node(int(value))
+                    else:
+                        raise RuntimeError("Context needed when using grid coordinates")
                     self.assert_field(i, 'lat', float(lat))
                     self.assert_field(i, 'lon', float(lon))
                 else:
index 0fda8f0866f1d53a5119fcb6aba63a8cfc466f6b..22517338bab04f664198222680f273ae358882a1 100644 (file)
@@ -153,6 +153,20 @@ def website_reverse_request(context, fmt, lat, lon):
 
     context.response = ReverseResponse(outp, fmt or 'xml', status)
 
+@when(u'sending (?P<fmt>\S+ )?reverse point (?P<nodeid>.+)')
+def website_reverse_request(context, fmt, nodeid):
+    params = {}
+    if fmt and fmt.strip() == 'debug':
+        params['debug'] = '1'
+    params['lon'], params['lat'] = (f'{c:f}' for c in context.osm.grid_node(int(nodeid)))
+
+
+    outp, status = send_api_query('reverse', params, fmt, context)
+
+    context.response = ReverseResponse(outp, fmt or 'xml', status)
+
+
+
 @when(u'sending (?P<fmt>\S+ )?details query for (?P<query>.*)')
 def website_details_request(context, fmt, query):
     params = {}
@@ -238,7 +252,7 @@ def step_impl(context):
     context.execute_steps("then at least 1 result is returned")
 
     for line in context.table:
-        context.response.match_row(line)
+        context.response.match_row(line, context=context)
 
 @then(u'result (?P<lid>\d+ )?has (?P<neg>not )?attributes (?P<attrs>.*)')
 def validate_attributes(context, lid, neg, attrs):