]> git.openstreetmap.org Git - nominatim.git/commitdiff
Merge remote-tracking branch 'upstream/master'
authorSarah Hoffmann <lonvia@denofr.de>
Thu, 2 Apr 2020 20:03:16 +0000 (22:03 +0200)
committerSarah Hoffmann <lonvia@denofr.de>
Thu, 2 Apr 2020 20:03:16 +0000 (22:03 +0200)
docs/api/Output.md
docs/api/Search.md
lib/AddressDetails.php
lib/template/address-geocodejson.php
lib/template/search-geocodejson.php
test/bdd/api/reverse/geocodejson.feature [new file with mode: 0644]
test/bdd/api/search/geocodejson.feature [new file with mode: 0644]
test/bdd/steps/queries.py

index a0d85220f7877802cbd768a08bd3269e5322d487..2f9bdaebe98fa7b4958587f2f7f2871ac4db745c 100644 (file)
@@ -100,12 +100,9 @@ The following feature attributes are implemented:
  * `type` - value of the main tag of the object (e.g. residential, restaurant, ...)
  * `label` - full comma-separated address
  * `name` - localised name of the place
- * `housenumber`, `street`, `locality`, `postcode`, `city`,
-   `district`, `county`, `state`, `country` -
+ * `housenumber`, `street`, `locality`, `district`, `postcode`, `city`,
+   `county`, `state`, `country` -
    provided when it can be determined from the address
-   (see [this issue](https://github.com/openstreetmap/Nominatim/issues/1080) for
-   current limitations on the correctness of the address) and `addressdetails=1`
-   was given
  * `admin` - list of localised names of administrative boundaries (only with `addressdetails=1`)
 
 Use `polygon_geojson` to output the full geometry of the object instead
index ace6cc8de7df34571c334bd0d396f611703c17d3..688d7e0c522f04eb93210677be09c0b2b2c20047 100644 (file)
@@ -168,21 +168,27 @@ This overrides the specified machine readable format. (Default: 0)
 ## Examples
 
 
-##### XML with polygon points
+##### XML with kml polygon
 
-* [https://nominatim.openstreetmap.org/search?q=135+pilkington+avenue,+birmingham&format=xml&polygon=1&addressdetails=1](https://nominatim.openstreetmap.org/search?q=135+pilkington+avenue,+birmingham&format=xml&polygon=1&addressdetails=1)
-* [https://nominatim.openstreetmap.org/search/gb/birmingham/pilkington%20avenue/135?format=xml&polygon=1&addressdetails=1](https://nominatim.openstreetmap.org/search/gb/birmingham/pilkington%20avenue/135?format=xml&polygon=1&addressdetails=1)
-* [https://nominatim.openstreetmap.org/search/135%20pilkington%20avenue,%20birmingham?format=xml&polygon=1&addressdetails=1](https://nominatim.openstreetmap.org/search/135%20pilkington%20avenue,%20birmingham?format=xml&polygon=1&addressdetails=1)
+* [https://nominatim.openstreetmap.org/search?q=135+pilkington+avenue,+birmingham&format=xml&polygon_geojson=1&addressdetails=1](https://nominatim.openstreetmap.org/search?q=135+pilkington+avenue,+birmingham&format=xml&polygon_geojson=1&addressdetails=1)
 
 ```xml
   <searchresults timestamp="Sat, 07 Nov 09 14:42:10 +0000" querystring="135 pilkington, avenue birmingham" polygon="true">
     <place
       place_id="1620612" osm_type="node" osm_id="452010817"
       boundingbox="52.548641204834,52.5488433837891,-1.81612110137939,-1.81592094898224"
-      polygonpoints="[['-1.81592098644987','52.5487429714954'],['-1.81592290792183','52.5487234624632'],...]"
       lat="52.5487429714954" lon="-1.81602098644987"
       display_name="135, Pilkington Avenue, Wylde Green, City of Birmingham, West Midlands (county), B72, United Kingdom"
       class="place" type="house">
+      <geokml>
+        <Polygon>
+          <outerBoundaryIs>
+            <LinearRing>
+              <coordinates>-1.816513,52.548756599999997 -1.816434,52.548747300000002 -1.816429,52.5487629 -1.8163717,52.548756099999999 -1.8163464,52.548834599999999 -1.8164599,52.548848100000001 -1.8164685,52.5488213 -1.8164913,52.548824000000003 -1.816513,52.548756599999997</coordinates>
+            </LinearRing>
+          </outerBoundaryIs>
+        </Polygon>
+      </geokml>
       <house_number>135</house_number>
       <road>Pilkington Avenue</road>
       <village>Wylde Green</village>
index 61823b4ce9dc504010ed33e67aeb575df400d047..2aae0742e131cb6c314e691cb84273d31a2f7180 100644 (file)
@@ -101,6 +101,53 @@ class AddressDetails
         return $aAddress;
     }
 
+    /**
+     * Annotates the given json with geocodejson address information fields.
+     *
+     * @param array  $aJson  Json hash to add the fields to.
+     *
+     * Geocodejson has the following fields:
+     *  street, locality, postcode, city, district,
+     *  county, state, country
+     *
+     * Postcode and housenumber are added by type, district is not used.
+     * All other fields are set according to address rank.
+     */
+    public function addGeocodeJsonAddressParts(&$aJson)
+    {
+        foreach ($this->aAddressLines as $aLine) {
+            if (!$aLine['isaddress']) {
+                continue;
+            }
+
+            if (!isset($aLine['localname']) || $aLine['localname'] == '') {
+                continue;
+            }
+
+            $iRank = (int)$aLine['rank_address'];
+
+            if ($aLine['type'] == 'postcode' || $aLine['type'] == 'postal_code') {
+                $aJson['postcode'] = $aLine['localname'];
+            } else if ($aLine['type'] == 'house_number') {
+                $aJson['housenumber'] = $aLine['localname'];
+            } else if ($iRank > 25 && $iRank < 28) {
+                $aJson['street'] = $aLine['localname'];
+            } else if ($iRank >= 22 && $iRank <= 25) {
+                $aJson['locality'] = $aLine['localname'];
+            } else if ($iRank >= 17 && $iRank <= 21) {
+                $aJson['district'] = $aLine['localname'];
+            } else if ($iRank >= 13 && $iRank <= 16) {
+                $aJson['city'] = $aLine['localname'];
+            } else if ($iRank >= 10 && $iRank <= 12) {
+                $aJson['county'] = $aLine['localname'];
+            } else if ($iRank >= 5 && $iRank <= 9) {
+                $aJson['state'] = $aLine['localname'];
+            } else if ($iRank == 4) {
+                $aJson['country'] = $aLine['localname'];
+            }
+        }
+    }
+
     public function getAdminLevels()
     {
         $aAddress = array();
index 032dcf4347a1046eb684a517af6cebb980aef176..6ccbeb5786b0563737bf647662205107a2b476b5 100644 (file)
@@ -33,24 +33,9 @@ if (empty($aPlace)) {
     $aFilteredPlaces['properties']['geocoding']['name'] = $aPlace['placename'];
 
     if (isset($aPlace['address'])) {
-        $aFieldMappings = array(
-                           'house_number' => 'housenumber',
-                           'road' => 'street',
-                           'locality' => 'locality',
-                           'postcode' => 'postcode',
-                           'city' => 'city',
-                           'district' => 'district',
-                           'county' => 'county',
-                           'state' => 'state',
-                           'country' => 'country'
-                          );
-
-        $aAddressNames = $aPlace['address']->getAddressNames();
-        foreach ($aFieldMappings as $sFrom => $sTo) {
-            if (isset($aAddressNames[$sFrom])) {
-                $aFilteredPlaces['properties']['geocoding'][$sTo] = $aAddressNames[$sFrom];
-            }
-        }
+        $aPlace['address']->addGeocodeJsonAddressParts(
+          $aFilteredPlaces['properties']['geocoding']
+        );
 
         $aFilteredPlaces['properties']['geocoding']['admin']
             = $aPlace['address']->getAdminLevels();
index 29bfe0bf58d4fae3be47896c26d64b00e6bfcf03..c046b4affdde1db98be548913c2521bda6947f16 100644 (file)
@@ -23,24 +23,9 @@ foreach ($aSearchResults as $iResNum => $aPointDetails) {
     $aPlace['properties']['geocoding']['name'] = $aPointDetails['placename'];
 
     if (isset($aPointDetails['address'])) {
-        $aFieldMappings = array(
-                           'house_number' => 'housenumber',
-                           'road' => 'street',
-                           'locality' => 'locality',
-                           'postcode' => 'postcode',
-                           'city' => 'city',
-                           'district' => 'district',
-                           'county' => 'county',
-                           'state' => 'state',
-                           'country' => 'country'
-                          );
-
-        $aAddrNames = $aPointDetails['address']->getAddressNames();
-        foreach ($aFieldMappings as $sFrom => $sTo) {
-            if (isset($aAddrNames[$sFrom])) {
-                $aPlace['properties']['geocoding'][$sTo] = $aAddrNames[$sFrom];
-            }
-        }
+        $aPointDetails['address']->addGeocodeJsonAddressParts(
+          $aPlace['properties']['geocoding']
+        );
 
         $aPlace['properties']['geocoding']['admin']
             = $aPointDetails['address']->getAdminLevels();
diff --git a/test/bdd/api/reverse/geocodejson.feature b/test/bdd/api/reverse/geocodejson.feature
new file mode 100644 (file)
index 0000000..b32bf1c
--- /dev/null
@@ -0,0 +1,27 @@
+@APIDB
+Feature: Parameters for Reverse API
+    Testing correctness of geocodejson output.
+
+    Scenario: City housenumber-level address with street
+        When sending geocodejson reverse coordinates 53.556,9.9607
+        Then results contain
+          | housenumber | street           | postcode | city    | country |
+          | 10          | Brunnenhofstraße | 22767    | Hamburg | Deutschland | 
+
+    Scenario: Town street-level address with street
+        When sending geocodejson reverse coordinates 47.066,9.504
+        Then results contain
+          | street  | city    | postcode | country |
+          | Gnetsch | Balzers | 9496     | Liechtenstein |
+
+    Scenario: Town street-level address with footway
+        When sending geocodejson reverse coordinates 47.0653,9.5007
+        Then results contain
+          | street  | city    | postcode | country |
+          | Burgweg | Balzers | 9496     | Liechtenstein |
+
+    Scenario: City address with suburb
+        When sending geocodejson reverse coordinates 53.5822,10.0805
+        Then results contain
+          | housenumber | street                | district | city    | postcode | country |
+          | 64          | Hinschenfelder Straße | Wandsbek | Hamburg | 22047    | Deutschland |
diff --git a/test/bdd/api/search/geocodejson.feature b/test/bdd/api/search/geocodejson.feature
new file mode 100644 (file)
index 0000000..97cb220
--- /dev/null
@@ -0,0 +1,27 @@
+@APIDB
+Feature: Parameters for Search API
+    Testing correctness of geocodejson output.
+
+    Scenario: City housenumber-level address with street
+        When sending geocodejson search query "Brunnenhofstr 10, Hamburg" with address
+        Then results contain
+          | housenumber | street           | postcode | city    | country |
+          | 10          | Brunnenhofstraße | 22767    | Hamburg | Deutschland | 
+
+    Scenario: Town street-level address with street
+        When sending geocodejson search query "Gnetsch, Balzers" with address
+        Then results contain
+          | street  | city    | postcode | country |
+          | Gnetsch | Balzers | 9496     | Liechtenstein |
+
+    Scenario: Town street-level address with footway
+        When sending geocodejson search query "burg gutenberg 6000 jahre geschichte" with address
+        Then results contain
+          | street  | city    | postcode | country |
+          | Burgweg | Balzers | 9496     | Liechtenstein |
+
+    Scenario: City address with suburb
+        When sending geocodejson search query "hinschenfelder str 64, wandsbek" with address
+        Then results contain
+          | housenumber | street                | district | city    | postcode | country |
+          | 64          | Hinschenfelder Straße | Wandsbek | Hamburg | 22047    | Deutschland |
index 4e6ec1ff5ab02c6d3556cd17877ca48376c370d6..d3b1203b47ae7a0c0cf1897b3bc7ec34c09988a6 100644 (file)
@@ -115,7 +115,9 @@ class SearchResponse(GenericResponse):
         self.result = geojson_results_to_json_results(self.result)
 
     def parse_geocodejson(self):
-        return self.parse_geojson()
+        self.parse_geojson()
+        if self.result is not None:
+            self.result = [r['geocoding'] for r in self.result]
 
     def parse_html(self):
         content, errors = tidy_document(self.page,
@@ -203,7 +205,9 @@ class ReverseResponse(GenericResponse):
         self.result = geojson_results_to_json_results(self.result[0])
 
     def parse_geocodejson(self):
-        return self.parse_geojson()
+        self.parse_geojson()
+        if self.result is not None:
+            self.result = [r['geocoding'] for r in self.result]
 
     def parse_xml(self):
         et = ET.fromstring(self.page)