]> git.openstreetmap.org Git - nominatim.git/commitdiff
Reverse geocode include geometry
authorMarc Tobias Metten <mtmail@gmx.net>
Fri, 4 Mar 2016 19:29:09 +0000 (20:29 +0100)
committerMarc Tobias Metten <mtmail@gmx.net>
Fri, 4 Mar 2016 19:29:09 +0000 (20:29 +0100)
16 files changed:
lib/Geocode.php
lib/PlaceLookup.php
lib/ReverseGeocode.php
lib/lib.php
lib/template/address-json.php
lib/template/address-jsonv2.php
lib/template/address-xml.php
lib/template/search-json.php
lib/template/search-jsonv2.php
lib/template/search-xml.php
tests-php/Nominatim/NominatimTest.php
tests/features/api/reverse.feature
tests/features/api/reverse_simple.feature
tests/features/api/search_params.feature
tests/steps/api_result.py
website/reverse.php

index a6ff279ca973d17c0488eef7eb5b5c0ddd0451d9..cf7dfbe6183e05916eefb4aff62b50ef20b7b1b5 100644 (file)
@@ -1,4 +1,6 @@
 <?php
+       require_once(CONST_BasePath.'/lib/PlaceLookup.php');
+
        class Geocode
        {
                protected $oDB;
                        foreach($aSearchResults as $iResNum => $aResult)
                        {
                                // Default
-                               $fDiameter = 0.0001;
-
-                               if (isset($aClassType[$aResult['class'].':'.$aResult['type'].':'.$aResult['admin_level']]['defdiameter'])
-                                               && $aClassType[$aResult['class'].':'.$aResult['type'].':'.$aResult['admin_level']]['defdiameter'])
-                               {
-                                       $fDiameter = $aClassType[$aResult['class'].':'.$aResult['type'].':'.$aResult['admin_level']]['defdiameter'];
-                               }
-                               elseif (isset($aClassType[$aResult['class'].':'.$aResult['type']]['defdiameter'])
-                                               && $aClassType[$aResult['class'].':'.$aResult['type']]['defdiameter'])
+                               $fDiameter = getResultDiameter($aResult);
+
+                               $oPlaceLookup = new PlaceLookup($this->oDB);
+                               $oPlaceLookup->setIncludePolygonAsPoints($this->bIncludePolygonAsPoints);
+                               $oPlaceLookup->setIncludePolygonAsText($this->bIncludePolygonAsText);
+                               $oPlaceLookup->setIncludePolygonAsGeoJSON($this->bIncludePolygonAsGeoJSON);
+                               $oPlaceLookup->setIncludePolygonAsKML($this->bIncludePolygonAsKML);
+                               $oPlaceLookup->setIncludePolygonAsSVG($this->bIncludePolygonAsSVG);
+                               $oPlaceLookup->setPolygonSimplificationThreshold($this->fPolygonSimplificationThreshold);
+
+                               $aOutlineResult = $oPlaceLookup->getOutlines($aResult['place_id'], $aResult['lon'], $aResult['lat'], $fDiameter/2);
+                               foreach($aOutlineResult as $k => $v)
                                {
-                                       $fDiameter = $aClassType[$aResult['class'].':'.$aResult['type']]['defdiameter'];
-                               }
-                               $fRadius = $fDiameter / 2;
-
-                               if (CONST_Search_AreaPolygons)
-                               {
-                                       // Get the bounding box and outline polygon
-                                       $sSQL = "select place_id,0 as numfeatures,st_area(geometry) as area,";
-                                       $sSQL .= "ST_Y(centroid) as centrelat,ST_X(centroid) as centrelon,";
-                                       $sSQL .= "ST_YMin(geometry) as minlat,ST_YMax(geometry) as maxlat,";
-                                       $sSQL .= "ST_XMin(geometry) as minlon,ST_XMax(geometry) as maxlon";
-                                       if ($this->bIncludePolygonAsGeoJSON) $sSQL .= ",ST_AsGeoJSON(geometry) as asgeojson";
-                                       if ($this->bIncludePolygonAsKML) $sSQL .= ",ST_AsKML(geometry) as askml";
-                                       if ($this->bIncludePolygonAsSVG) $sSQL .= ",ST_AsSVG(geometry) as assvg";
-                                       if ($this->bIncludePolygonAsText || $this->bIncludePolygonAsPoints) $sSQL .= ",ST_AsText(geometry) as astext";
-                                       $sFrom = " from placex where place_id = ".$aResult['place_id'];
-                                       if ($this->fPolygonSimplificationThreshold > 0)
-                                       {
-                                               $sSQL .= " from (select place_id,centroid,ST_SimplifyPreserveTopology(geometry,".$this->fPolygonSimplificationThreshold.") as geometry".$sFrom.") as plx";
-                                       }
-                                       else
-                                       {
-                                               $sSQL .= $sFrom;
-                                       }
-
-                                       $aPointPolygon = $this->oDB->getRow($sSQL);
-                                       if (PEAR::IsError($aPointPolygon))
-                                       {
-                                               failInternalError("Could not get outline.", $sSQL, $aPointPolygon);
-                                       }
-
-                                       if ($aPointPolygon['place_id'])
-                                       {
-                                               if ($this->bIncludePolygonAsGeoJSON) $aResult['asgeojson'] = $aPointPolygon['asgeojson'];
-                                               if ($this->bIncludePolygonAsKML) $aResult['askml'] = $aPointPolygon['askml'];
-                                               if ($this->bIncludePolygonAsSVG) $aResult['assvg'] = $aPointPolygon['assvg'];
-                                               if ($this->bIncludePolygonAsText) $aResult['astext'] = $aPointPolygon['astext'];
-
-                                               if ($aPointPolygon['centrelon'] !== null && $aPointPolygon['centrelat'] !== null )
-                                               {
-                                                       $aResult['lat'] = $aPointPolygon['centrelat'];
-                                                       $aResult['lon'] = $aPointPolygon['centrelon'];
-                                               }
-
-                                               if ($this->bIncludePolygonAsPoints)
-                                               {
-                                                       $aPolyPoints[] = geometryText2Points($aPointPolygon['astext'],$fRadius);
-
-                                                       // Output data suitable for display (points and a bounding box)
-                                                       if (isset($aPolyPoints))
-                                                       {
-                                                               $aResult['aPolyPoints'] = array();
-                                                               foreach($aPolyPoints as $aPoint)
-                                                               {
-                                                                       $aResult['aPolyPoints'][] = array($aPoint[1], $aPoint[2]);
-                                                               }
-                                                       }
-                                               }
-
-                                               if (abs($aPointPolygon['minlat'] - $aPointPolygon['maxlat']) < 0.0000001)
-                                               {
-                                                       $aPointPolygon['minlat'] = $aPointPolygon['minlat'] - $fRadius;
-                                                       $aPointPolygon['maxlat'] = $aPointPolygon['maxlat'] + $fRadius;
-                                               }
-                                               if (abs($aPointPolygon['minlon'] - $aPointPolygon['maxlon']) < 0.0000001)
-                                               {
-                                                       $aPointPolygon['minlon'] = $aPointPolygon['minlon'] - $fRadius;
-                                                       $aPointPolygon['maxlon'] = $aPointPolygon['maxlon'] + $fRadius;
-                                               }
-                                               $aResult['aBoundingBox'] = array((string)$aPointPolygon['minlat'],(string)$aPointPolygon['maxlat'],(string)$aPointPolygon['minlon'],(string)$aPointPolygon['maxlon']);
-                                       }
+                                       $aResult[$k] = $v;
                                }
 
                                if ($aResult['extra_place'] == 'city')
                                        $aResult['rank_search'] = 16;
                                }
 
-                               if (!isset($aResult['aBoundingBox']))
-                               {
-                                       $iSteps = max(8,min(100,$fRadius * 3.14 * 100000));
-                                       $fStepSize = (2*pi())/$iSteps;
-                                       $aPointPolygon['minlat'] = $aResult['lat'] - $fRadius;
-                                       $aPointPolygon['maxlat'] = $aResult['lat'] + $fRadius;
-                                       $aPointPolygon['minlon'] = $aResult['lon'] - $fRadius;
-                                       $aPointPolygon['maxlon'] = $aResult['lon'] + $fRadius;
-
-                                       // Output data suitable for display (points and a bounding box)
-                                       if ($this->bIncludePolygonAsPoints)
-                                       {
-                                               $aPolyPoints = array();
-                                               for($f = 0; $f < 2*pi(); $f += $fStepSize)
-                                               {
-                                                       $aPolyPoints[] = array('',$aResult['lon']+($fRadius*sin($f)),$aResult['lat']+($fRadius*cos($f)));
-                                               }
-                                               $aResult['aPolyPoints'] = array();
-                                               foreach($aPolyPoints as $aPoint)
-                                               {
-                                                       $aResult['aPolyPoints'][] = array($aPoint[1], $aPoint[2]);
-                                               }
-                                       }
-                                       $aResult['aBoundingBox'] = array((string)$aPointPolygon['minlat'],(string)$aPointPolygon['maxlat'],(string)$aPointPolygon['minlon'],(string)$aPointPolygon['maxlon']);
-                               }
-
                                // Is there an icon set for this type of result?
                                if (isset($aClassType[$aResult['class'].':'.$aResult['type']]['icon'])
                                                && $aClassType[$aResult['class'].':'.$aResult['type']]['icon'])
index c5129fee31006d47a011251a82a08237458703a3..04e45d5aba704657c933614900fdef835fd9c403 100644 (file)
 
                protected $bNameDetails = false;
 
+               protected $bIncludePolygonAsPoints = false;
+               protected $bIncludePolygonAsText = false;
+               protected $bIncludePolygonAsGeoJSON = false;
+               protected $bIncludePolygonAsKML = false;
+               protected $bIncludePolygonAsSVG = false;
+               protected $fPolygonSimplificationThreshold = 0.0;
+
+
                function PlaceLookup(&$oDB)
                {
                        $this->oDB =& $oDB;
                        }
                }
 
+
+               function setIncludePolygonAsPoints($b = true)
+               {
+                       $this->bIncludePolygonAsPoints = $b;
+               }
+
+               function getIncludePolygonAsPoints()
+               {
+                       return $this->bIncludePolygonAsPoints;
+               }
+
+               function setIncludePolygonAsText($b = true)
+               {
+                       $this->bIncludePolygonAsText = $b;
+               }
+
+               function getIncludePolygonAsText()
+               {
+                       return $this->bIncludePolygonAsText;
+               }
+
+               function setIncludePolygonAsGeoJSON($b = true)
+               {
+                       $this->bIncludePolygonAsGeoJSON = $b;
+               }
+
+               function setIncludePolygonAsKML($b = true)
+               {
+                       $this->bIncludePolygonAsKML = $b;
+               }
+
+               function setIncludePolygonAsSVG($b = true)
+               {
+                       $this->bIncludePolygonAsSVG = $b;
+               }
+
+               function setPolygonSimplificationThreshold($f)
+               {
+                       $this->fPolygonSimplificationThreshold = $f;
+               }
+
+
                function setPlaceID($iPlaceID)
                {
                        $this->iPlaceID = $iPlaceID;
                        return $aAddress;
                }
 
+
+
+               // returns an array which will contain the keys
+               //   aBoundingBox
+               // and may also contain one or more of the keys
+               //   asgeojson
+               //   askml
+               //   assvg
+               //   astext
+               //   lat
+               //   lon
+               function getOutlines($iPlaceID, $fLon=null, $fLat=null, $fRadius=null)
+               {
+
+                       $aOutlineResult = array();
+                       if (!$iPlaceID) return $aOutlineResult;
+
+                       if (CONST_Search_AreaPolygons)
+                       {
+                               // Get the bounding box and outline polygon
+                               $sSQL  = "select place_id,0 as numfeatures,st_area(geometry) as area,";
+                               $sSQL .= "ST_Y(centroid) as centrelat,ST_X(centroid) as centrelon,";
+                               $sSQL .= "ST_YMin(geometry) as minlat,ST_YMax(geometry) as maxlat,";
+                               $sSQL .= "ST_XMin(geometry) as minlon,ST_XMax(geometry) as maxlon";
+                               if ($this->bIncludePolygonAsGeoJSON) $sSQL .= ",ST_AsGeoJSON(geometry) as asgeojson";
+                               if ($this->bIncludePolygonAsKML) $sSQL .= ",ST_AsKML(geometry) as askml";
+                               if ($this->bIncludePolygonAsSVG) $sSQL .= ",ST_AsSVG(geometry) as assvg";
+                               if ($this->bIncludePolygonAsText || $this->bIncludePolygonAsPoints) $sSQL .= ",ST_AsText(geometry) as astext";
+                               $sFrom = " from placex where place_id = ".$iPlaceID;
+                               if ($this->fPolygonSimplificationThreshold > 0)
+                               {
+                                       $sSQL .= " from (select place_id,centroid,ST_SimplifyPreserveTopology(geometry,".$this->fPolygonSimplificationThreshold.") as geometry".$sFrom.") as plx";
+                               }
+                               else
+                               {
+                                       $sSQL .= $sFrom;
+                               }
+
+                               $aPointPolygon = $this->oDB->getRow($sSQL);
+                               if (PEAR::IsError($aPointPolygon))
+                               {
+                                       echo var_dump($aPointPolygon);
+                                       failInternalError("Could not get outline.", $sSQL, $aPointPolygon);
+                               }
+
+                               if ($aPointPolygon['place_id'])
+                               {
+                                       if ($aPointPolygon['centrelon'] !== null && $aPointPolygon['centrelat'] !== null )
+                                       {
+                                               $aOutlineResult['lat'] = $aPointPolygon['centrelat'];
+                                               $aOutlineResult['lon'] = $aPointPolygon['centrelon'];
+                                       }
+
+                                       if ($this->bIncludePolygonAsGeoJSON) $aOutlineResult['asgeojson'] = $aPointPolygon['asgeojson'];
+                                       if ($this->bIncludePolygonAsKML) $aOutlineResult['askml'] = $aPointPolygon['askml'];
+                                       if ($this->bIncludePolygonAsSVG) $aOutlineResult['assvg'] = $aPointPolygon['assvg'];
+                                       if ($this->bIncludePolygonAsText) $aOutlineResult['astext'] = $aPointPolygon['astext'];
+                                       if ($this->bIncludePolygonAsPoints) $aOutlineResult['aPolyPoints'] = geometryText2Points($aPointPolygon['astext'], $fRadius);
+
+
+                                       if (abs($aPointPolygon['minlat'] - $aPointPolygon['maxlat']) < 0.0000001)
+                                       {
+                                               $aPointPolygon['minlat'] = $aPointPolygon['minlat'] - $fRadius;
+                                               $aPointPolygon['maxlat'] = $aPointPolygon['maxlat'] + $fRadius;
+                                       }
+                                       if (abs($aPointPolygon['minlon'] - $aPointPolygon['maxlon']) < 0.0000001)
+                                       {
+                                               $aPointPolygon['minlon'] = $aPointPolygon['minlon'] - $fRadius;
+                                               $aPointPolygon['maxlon'] = $aPointPolygon['maxlon'] + $fRadius;
+                                       }
+
+                                       $aOutlineResult['aBoundingBox'] = array(
+                                                                         (string)$aPointPolygon['minlat'],
+                                                                         (string)$aPointPolygon['maxlat'],
+                                                                         (string)$aPointPolygon['minlon'],
+                                                                         (string)$aPointPolygon['maxlon']
+                                                                        );
+                               }
+                       } // CONST_Search_AreaPolygons
+
+                       // as a fallback we generate a bounding box without knowing the size of the geometry
+                       if ( (!isset($aOutlineResult['aBoundingBox'])) && isset($fLon) )
+                       {
+
+                               if ($this->bIncludePolygonAsPoints)
+                               {
+                                       $sGeometryText = 'POINT('.$fLon.','.$fLat.')';
+                                       $aOutlineResult['aPolyPoints'] = geometryText2Points($sGeometryText, $fRadius);
+                               }
+
+                               $aBounds = array();
+                               $aBounds['minlat'] = $fLat - $fRadius;
+                               $aBounds['maxlat'] = $fLat + $fRadius;
+                               $aBounds['minlon'] = $fLon - $fRadius;
+                               $aBounds['maxlon'] = $fLon + $fRadius;
+
+                               $aOutlineResult['aBoundingBox'] = array(
+                                                                 (string)$aBounds['minlat'],
+                                                                 (string)$aBounds['maxlat'],
+                                                                 (string)$aBounds['minlon'],
+                                                                 (string)$aBounds['maxlon']
+                                                                );
+                       }
+                       return $aOutlineResult;
+               }
        }
 ?>
index e40ce6cceaa23f2904be061914c46a3bdf73b718..d96527643fa67603c525de016d59319d432d9835 100644 (file)
@@ -9,6 +9,14 @@
 
                protected $aLangPrefOrder = array();
 
+               protected $bIncludePolygonAsPoints = false;
+               protected $bIncludePolygonAsText = false;
+               protected $bIncludePolygonAsGeoJSON = false;
+               protected $bIncludePolygonAsKML = false;
+               protected $bIncludePolygonAsSVG = false;
+               protected $fPolygonSimplificationThreshold = 0.0;
+
+
                function ReverseGeocode(&$oDB)
                {
                        $this->oDB =& $oDB;
                        $this->iMaxRank = (isset($iZoom) && isset($aZoomRank[$iZoom]))?$aZoomRank[$iZoom]:28;
                }
 
+                               function setIncludePolygonAsPoints($b = true)
+               {
+                       $this->bIncludePolygonAsPoints = $b;
+               }
+
+               function getIncludePolygonAsPoints()
+               {
+                       return $this->bIncludePolygonAsPoints;
+               }
+
+               function setIncludePolygonAsText($b = true)
+               {
+                       $this->bIncludePolygonAsText = $b;
+               }
+
+               function getIncludePolygonAsText()
+               {
+                       return $this->bIncludePolygonAsText;
+               }
+
+               function setIncludePolygonAsGeoJSON($b = true)
+               {
+                       $this->bIncludePolygonAsGeoJSON = $b;
+               }
+
+               function setIncludePolygonAsKML($b = true)
+               {
+                       $this->bIncludePolygonAsKML = $b;
+               }
+
+               function setIncludePolygonAsSVG($b = true)
+               {
+                       $this->bIncludePolygonAsSVG = $b;
+               }
+
+               function setPolygonSimplificationThreshold($f)
+               {
+                       $this->fPolygonSimplificationThreshold = $f;
+               }
+
+               // returns { place_id =>, type => '(osm|tiger)' }
+               // fails if no place was found
                function lookup()
                {
                        $sPointSQL = 'ST_SetSRID(ST_Point('.$this->fLon.','.$this->fLat.'),4326)';
                                if ($fSearchDiam > 0.008 && $iMaxRank > 22) $iMaxRank = 22;
                                if ($fSearchDiam > 0.001 && $iMaxRank > 26) $iMaxRank = 26;
 
-                               $sSQL = 'select place_id,parent_place_id,rank_search,calculated_country_code from placex';
+                               $sSQL = 'select place_id,parent_place_id,rank_search,calculated_country_code';
+                               $sSQL .= ' FROM placex';
                                $sSQL .= ' WHERE ST_DWithin('.$sPointSQL.', geometry, '.$fSearchDiam.')';
                                $sSQL .= ' and rank_search != 28 and rank_search >= '.$iMaxRank;
                                $sSQL .= ' and (name is not null or housenumber is not null)';
                                {
                                        $iPlaceID = $iParentPlaceID;
                                }
-                               $sSQL = "select address_place_id from place_addressline where place_id = $iPlaceID order by abs(cached_rank_address - $iMaxRank) asc,cached_rank_address desc,isaddress desc,distance desc limit 1";
+                               $sSQL  = 'select address_place_id';
+                               $sSQL .= ' FROM place_addressline';
+                               $sSQL .= " WHERE place_id = $iPlaceID";
+                               $sSQL .= " ORDER BY abs(cached_rank_address - $iMaxRank) asc,cached_rank_address desc,isaddress desc,distance desc";
+                               $sSQL .= ' LIMIT 1';
                                $iPlaceID = $this->oDB->getOne($sSQL);
                                if (PEAR::IsError($iPlaceID))
                                {
                        }
 
                        return array('place_id' => $iPlaceID,
-                                            'type' => $bPlaceIsTiger ? 'tiger' : 'osm');
+                                    'type' => $bPlaceIsTiger ? 'tiger' : 'osm');
                }
+               
        }
 ?>
index e81d85becc68ffe9aac16dcb73a56a030c0e9fe9..51bf7ebb13381e32507535ca394f7aad46545685 100644 (file)
                return $aOrders;
        }
 
+       function getResultDiameter($aResult)
+       {
+               $aClassType = getClassTypes();
+
+               $fDiameter = 0.0001;
+
+               if (isset($aResult['class'])
+                         && isset($aResult['type'])
+                         && isset($aResult['admin_level'])
+                         && isset($aClassType[$aResult['class'].':'.$aResult['type'].':'.$aResult['admin_level']]['defdiameter'])
+                               && $aClassType[$aResult['class'].':'.$aResult['type'].':'.$aResult['admin_level']]['defdiameter'])
+               {
+                       $fDiameter = $aClassType[$aResult['class'].':'.$aResult['type'].':'.$aResult['admin_level']]['defdiameter'];
+               }
+               elseif (isset($aResult['class'])
+                         && isset($aResult['type'])
+                         && isset($aClassType[$aResult['class'].':'.$aResult['type']]['defdiameter'])
+                               && $aClassType[$aResult['class'].':'.$aResult['type']]['defdiameter'])
+               {
+                       $fDiameter = $aClassType[$aResult['class'].':'.$aResult['type']]['defdiameter'];
+               }
+
+               return $fDiameter;
+       }
+
 
        function javascript_renderData($xVal, $iOptions = 0)
        {
        }
 
 
-
-       function geometryText2Points($geometry_as_text,$fRadius)
+       function geometryText2Points($geometry_as_text, $fRadius)
        {
                $aPolyPoints = NULL;
-               if (preg_match('#POLYGON\\(\\(([- 0-9.,]+)#',$geometry_as_text,$aMatch))
+               if (preg_match('#POLYGON\\(\\(([- 0-9.,]+)#', $geometry_as_text, $aMatch))
                {
-                       preg_match_all('/(-?[0-9.]+) (-?[0-9.]+)/',$aMatch[1],$aPolyPoints,PREG_SET_ORDER);
+                       preg_match_all('/(-?[0-9.]+) (-?[0-9.]+)/', $aMatch[1], $aPolyPoints, PREG_SET_ORDER);
                }
-               elseif (preg_match('#MULTIPOLYGON\\(\\(\\(([- 0-9.,]+)#',$geometry_as_text,$aMatch))
+               elseif (preg_match('#LINESTRING\\(([- 0-9.,]+)#', $geometry_as_text, $aMatch))
                {
-                       preg_match_all('/(-?[0-9.]+) (-?[0-9.]+)/',$aMatch[1],$aPolyPoints,PREG_SET_ORDER);
+                       preg_match_all('/(-?[0-9.]+) (-?[0-9.]+)/', $aMatch[1], $aPolyPoints, PREG_SET_ORDER);
                }
-               elseif (preg_match('#POINT\\((-?[0-9.]+) (-?[0-9.]+)\\)#',$geometry_as_text,$aMatch))
+               elseif (preg_match('#MULTIPOLYGON\\(\\(\\(([- 0-9.,]+)#', $geometry_as_text, $aMatch))
                {
+                       preg_match_all('/(-?[0-9.]+) (-?[0-9.]+)/', $aMatch[1], $aPolyPoints, PREG_SET_ORDER);
+               }
+               elseif (preg_match('#POINT\\((-?[0-9.]+) (-?[0-9.]+)\\)#', $geometry_as_text, $aMatch))
+               {
+                       $aPolyPoints = createPointsAroundCenter($aMatch[1], $aMatch[2], $fRadius);
+               }
+
+               if (isset($aPolyPoints))
+               {
+                       $aResultPoints = array();
+                       foreach($aPolyPoints as $aPoint)
+                       {
+                               $aResultPoints[] = array($aPoint[1], $aPoint[2]);
+                       }
+                       return $aResultPoints;
+               }
+
+               return;
+       }
+
+       function createPointsAroundCenter($fLon, $fLat, $fRadius)
+       {
                        $iSteps = max(8, min(100, ($fRadius * 40000)^2));
                        $fStepSize = (2*pi())/$iSteps;
                        $aPolyPoints = array();
                        for($f = 0; $f < 2*pi(); $f += $fStepSize)
                        {
-                               $aPolyPoints[] = array('',$aMatch[1]+($fRadius*sin($f)),$aMatch[2]+($fRadius*cos($f)));
+                               $aPolyPoints[] = array('', $fLon+($fRadius*sin($f)), $fLat+($fRadius*cos($f)) );
                        }
-               }
-               return $aPolyPoints;
+                       return $aPolyPoints;
        }
index d1edaf0d14cb60c68f8afb70a0161351ef673505..6fd101bbaac0f97c511c7250b99e62554c52e654 100644 (file)
                if (isset($aPlace['aAddress'])) $aFilteredPlaces['address'] = $aPlace['aAddress'];
                if (isset($aPlace['sExtraTags'])) $aFilteredPlaces['extratags'] = $aPlace['sExtraTags'];
                if (isset($aPlace['sNameDetails'])) $aFilteredPlaces['namedetails'] = $aPlace['sNameDetails'];
+
+               if (isset($aPlace['aBoundingBox']))
+               {
+                       $aFilteredPlaces['boundingbox'] = $aPlace['aBoundingBox'];
+
+                       if (isset($aPlace['aPolyPoints']) && $bAsPoints)
+                       {
+                               $aFilteredPlaces['polygonpoints'] = $aPlace['aPolyPoints'];
+                       }
+               }
+
+               if (isset($aPlace['asgeojson']))
+               {
+                       $aFilteredPlaces['geojson'] = json_decode($aPlace['asgeojson']);
+               }
+
+               if (isset($aPlace['assvg']))
+               {
+                       $aFilteredPlaces['svg'] = $aPlace['assvg'];
+               }
+
+               if (isset($aPlace['astext']))
+               {
+                       $aFilteredPlaces['geotext'] = $aPlace['astext'];
+               }
+
+               if (isset($aPlace['askml']))
+               {
+                       $aFilteredPlaces['geokml'] = $aPlace['askml'];
+               }
+
+
        }
 
        javascript_renderData($aFilteredPlaces);
index 40c5c56d974ecd05b2403396106e89947f9f2d88..894038758411117edf6ed9a9a6350a3b3b3c0ec3 100644 (file)
                if (isset($aPlace['aAddress'])) $aFilteredPlaces['address'] = $aPlace['aAddress'];
                if (isset($aPlace['sExtraTags'])) $aFilteredPlaces['extratags'] = $aPlace['sExtraTags'];
                if (isset($aPlace['sNameDetails'])) $aFilteredPlaces['namedetails'] = $aPlace['sNameDetails'];
+
+               if (isset($aPlace['aBoundingBox']))
+               {
+                       $aFilteredPlaces['boundingbox'] = $aPlace['aBoundingBox'];
+
+                       if (isset($aPlace['aPolyPoints']) && $bAsPoints)
+                       {
+                               $aFilteredPlaces['polygonpoints'] = $aPlace['aPolyPoints'];
+                       }
+               }
+
+               if (isset($aPlace['asgeojson']))
+               {
+                       $aFilteredPlaces['geojson'] = json_decode($aPlace['asgeojson']);
+               }
+
+               if (isset($aPlace['assvg']))
+               {
+                       $aFilteredPlaces['svg'] = $aPlace['assvg'];
+               }
+
+               if (isset($aPlace['astext']))
+               {
+                       $aFilteredPlaces['geotext'] = $aPlace['astext'];
+               }
+
+               if (isset($aPlace['askml']))
+               {
+                       $aFilteredPlaces['geokml'] = $aPlace['askml'];
+               }
+
        }
 
        javascript_renderData($aFilteredPlaces);
index 39d9a14792171a0c0d0cd0efc60ff8fa73c7257b..109e66a17ef41d2e3426f6b4061c535817be6435 100644 (file)
                if ($aPlace['ref']) echo ' ref="'.htmlspecialchars($aPlace['ref']).'"';
                if (isset($aPlace['lat'])) echo ' lat="'.htmlspecialchars($aPlace['lat']).'"';
                if (isset($aPlace['lon'])) echo ' lon="'.htmlspecialchars($aPlace['lon']).'"';
+               if (isset($aPlace['aBoundingBox']))
+               {
+                       echo ' boundingbox="';
+                       echo join(',', $aPlace['aBoundingBox']);
+                       echo '"';
+
+                       if ($bAsPoints && isset($aPlace['aPolyPoints']))
+                       {
+                               echo ' polygonpoints=\'';
+                               echo json_encode($aPlace['aPolyPoints']);
+                               echo '\'';
+                       }
+               }
+
+               if (isset($aPlace['asgeojson']))
+               {
+                       echo ' geojson=\'';
+                       echo $aPlace['asgeojson'];
+                       echo '\'';
+               }
+
+               if (isset($aPlace['assvg']))
+               {
+                       echo ' geosvg=\'';
+                       echo $aPlace['assvg'];
+                       echo '\'';
+               }
+
+               if (isset($aPlace['astext']))
+               {
+                       echo ' geotext=\'';
+                       echo $aPlace['astext'];
+                       echo '\'';
+               }
                echo ">".htmlspecialchars($aPlace['langaddress'])."</result>";
 
                if (isset($aPlace['aAddress']))
                        }
                        echo "</namedetails>";
                }
+
+               if (isset($aPlace['askml']))
+               {
+                       echo "\n<geokml>";
+                       echo $aPlace['askml'];
+                       echo "</geokml>";
+               }
+
        }
 
        echo "</reversegeocode>";
index 5f29fdfb22c3087ef3fb013c01a3c0859e83ad26..068599191b0d01e4a5e5a25842bda2a6783aa731 100644 (file)
 
                if (isset($aPointDetails['aBoundingBox']))
                {
-                       $aPlace['boundingbox'] = array(
-                               $aPointDetails['aBoundingBox'][0],
-                               $aPointDetails['aBoundingBox'][1],
-                               $aPointDetails['aBoundingBox'][2],
-                               $aPointDetails['aBoundingBox'][3]);
+                       $aPlace['boundingbox'] = $aPointDetails['aBoundingBox'][0];
 
                        if (isset($aPointDetails['aPolyPoints']) && $bShowPolygons)
                        {
index 66098d303e69272826030bee08a0f6b30a47156d..773cfd96679dd7b27d88f368930a599753485033 100644 (file)
 
                if (isset($aPointDetails['aBoundingBox']))
                {
-                       $aPlace['boundingbox'] = array(
-                               $aPointDetails['aBoundingBox'][0],
-                               $aPointDetails['aBoundingBox'][1],
-                               $aPointDetails['aBoundingBox'][2],
-                               $aPointDetails['aBoundingBox'][3]);
+                       $aPlace['boundingbox'] = $aPointDetails['aBoundingBox'];
 
                        if (isset($aPointDetails['aPolyPoints']) && $bShowPolygons)
                        {
index b61ff22f55fe2eed589466c682a8f650ac14b52b..6a382ebf7bcb4bde0c83783e05211f9ba8241ccb 100644 (file)
                if (isset($aResult['aBoundingBox']))
                {
                        echo ' boundingbox="';
-                       echo $aResult['aBoundingBox'][0];
-                       echo ','.$aResult['aBoundingBox'][1];
-                       echo ','.$aResult['aBoundingBox'][2];
-                       echo ','.$aResult['aBoundingBox'][3];
+                       echo join(',',$aResult['aBoundingBox']);
                        echo '"';
 
                        if ($bShowPolygons && isset($aResult['aPolyPoints']))
index 129fa01201f9a5c96a205b3652daf5063afa4852..d50a8da4a4a0f487ca1686cdfc450da36fd86415 100644 (file)
@@ -12,6 +12,51 @@ class NominatimTest extends \PHPUnit_Framework_TestCase
        }
 
 
+       public function test_getClassTypesWithImportance()
+       {
+               $aClasses = getClassTypesWithImportance();
+
+               $this->assertGreaterThan(
+                       200,
+                       count($aClasses)
+               );
+
+               $this->assertEquals(
+                       array(
+                               'label' => "Country",
+                               'frequency' => 0,
+                               'icon' => "poi_boundary_administrative",
+                               'defzoom' => 6,
+                               'defdiameter' => 15,
+                               'importance' => 3
+                       ),
+                       $aClasses['place:country']
+               );
+       }
+
+
+       public function test_getResultDiameter()
+       {
+               $aResult = array();
+               $this->assertEquals(
+                       0.0001,
+                       getResultDiameter($aResult)
+               );
+
+               $aResult = array('class' => 'place', 'type' => 'country');
+               $this->assertEquals(
+                       15,
+                       getResultDiameter($aResult)
+               );
+
+               $aResult = array('class' => 'boundary', 'type' => 'administrative', 'admin_level' => 6);
+               $this->assertEquals(
+                       0.32,
+                       getResultDiameter($aResult)
+               );
+       }
+
+
        public function test_addQuotes()
        {
                // FIXME: not quoting existing quote signs is probably a bug
@@ -142,36 +187,48 @@ class NominatimTest extends \PHPUnit_Framework_TestCase
                        65536,
                        count( getWordSets(array_fill( 0, 18, 'a'),0) )
                );
-
        }
 
 
+       // you might say we're creating a circle
+       public function test_createPointsAroundCenter()
+       {
+               $aPoints = createPointsAroundCenter(0, 0, 2);
 
+               $this->assertEquals(
+                       101,
+                       count($aPoints)
+               );
+               $this->assertEquals(
+                       array(
+                               ['', 0, 2],
+                               ['', 0.12558103905863, 1.9960534568565],
+                               ['', 0.25066646712861, 1.984229402629]
+                       ),
+                       array_splice($aPoints, 0, 3)
+               );
+       }
 
        public function test_geometryText2Points()
        {
                $fRadius = 1;
-
                // invalid value
                $this->assertEquals(
                        NULL,
                        geometryText2Points('', $fRadius)
                );
 
-
                // POINT
                $aPoints = geometryText2Points('POINT(10 20)', $fRadius);
                $this->assertEquals(
                        101,
                        count($aPoints)
                );
-
                $this->assertEquals(
-
-               array(
-                       ['', 10, 21],
-                       ['', 10.062790519529, 20.998026728428],
-                               ['', 10.125333233564, 20.992114701314]
+                       array(
+                               [10, 21],
+                               [10.062790519529, 20.998026728428],
+                               [10.125333233564, 20.992114701314]
                        ),
                        array_splice($aPoints, 0,3)
                );
@@ -179,35 +236,25 @@ class NominatimTest extends \PHPUnit_Framework_TestCase
                // POLYGON
                $this->assertEquals(
                        array(
-                               ['30 10', '30', '10'],
-                               ['40 40', '40', '40'],
-                               ['20 40', '20', '40'],
-                               ['10 20', '10', '20'],
-                               ['30 10', '30', '10']
+                               ['30', '10'],
+                               ['40', '40'],
+                               ['20', '40'],
+                               ['10', '20'],
+                               ['30', '10']
                        ),
                        geometryText2Points('POLYGON((30 10, 40 40, 20 40, 10 20, 30 10))', $fRadius)
                );
 
                // MULTIPOLYGON
-               // only the first polygon is used
                $this->assertEquals(
                        array(
-                               ['30 20', '30', '20'],
-                               ['45 40', '45', '40'],
-                               ['10 40', '10', '40'],
-                               ['30 20', '30', '20'],
-
-                               // ['15 5' , '15', '5' ],
-                               // ['45 10', '45', '10'],
-                               // ['10 20', '10', '20'],
-                               // ['5 10' , '5' , '10'],
-                               // ['15 5' , '15', '5' ]
+                               ['30', '20'], // first polygon only
+                               ['45', '40'],
+                               ['10', '40'],
+                               ['30', '20'],
                        ),
                        geometryText2Points('MULTIPOLYGON(((30 20, 45 40, 10 40, 30 20)),((15 5, 40 10, 10 20, 5 10, 15 5)))', $fRadius)
                );
-
-
        }
 
-
 }
index fa636acf548b773f9b5df287f9f7ef6ab812512e..4d0c554992e410667521a9a6de3387d676156905 100644 (file)
@@ -61,3 +61,75 @@ Feature: Reverse geocoding
         | xml
         | json
         | jsonv2
+
+
+   Scenario Outline: Reverse Geocoding contains TEXT geometry
+        Given the request parameters
+          | polygon_text
+          | 1
+        When looking up <format> coordinates 48.86093,2.2978
+        Then result 0 has attributes <response_attribute>
+
+   Examples:
+        | format   | response_attribute
+        | xml      | geotext
+        | json     | geotext
+        | jsonv2   | geotext
+
+   Scenario Outline: Reverse Geocoding contains polygon-as-points geometry
+        Given the request parameters
+          | polygon
+          | 1
+        When looking up <format> coordinates 48.86093,2.2978
+        Then result 0 has not attributes <response_attribute>
+
+   Examples:
+        | format   | response_attribute
+        | xml      | polygonpoints
+        | json     | polygonpoints
+        | jsonv2   | polygonpoints
+
+
+
+   Scenario Outline: Reverse Geocoding contains SVG geometry
+        Given the request parameters
+          | polygon_svg
+          | 1
+        When looking up <format> coordinates 48.86093,2.2978
+        Then result 0 has attributes <response_attribute>
+
+   Examples:
+        | format   | response_attribute
+        | xml      | geosvg
+        | json     | svg
+        | jsonv2   | svg
+
+
+   Scenario Outline: Reverse Geocoding contains KML geometry
+        Given the request parameters
+          | polygon_kml
+          | 1
+        When looking up <format> coordinates 48.86093,2.2978
+        Then result 0 has attributes <response_attribute>
+
+   Examples:
+        | format   | response_attribute
+        | xml      | geokml
+        | json     | geokml
+        | jsonv2   | geokml
+
+
+   Scenario Outline: Reverse Geocoding contains GEOJSON geometry
+        Given the request parameters
+          | polygon_geojson
+          | 1
+        When looking up <format> coordinates 48.86093,2.2978
+        Then result 0 has attributes <response_attribute>
+
+   Examples:
+        | format   | response_attribute
+        | xml      | geojson
+        | json     | geojson
+        | jsonv2   | geojson
+
+
index 8621ec655903d80006909b7ecf9fff097287cf48..5d79fd4b8af1e22bb61343fe2d7af3d5ba620171 100644 (file)
@@ -17,6 +17,49 @@ Feature: Simple Reverse Tests
      | -79.34   | 23.5
      | 0.23     | -178.555
 
+    Scenario Outline: Testing different parameters
+        Given the request parameters
+          | <parameter>
+          | <value>
+        When sending search query "Manchester"
+        Then the result is valid html
+        Given the request parameters
+          | <parameter>
+          | <value>
+        When sending html search query "Manchester"
+        Then the result is valid html
+        Given the request parameters
+          | <parameter>
+          | <value>
+        When sending xml search query "Manchester"
+        Then the result is valid xml
+        Given the request parameters
+          | <parameter>
+          | <value>
+        When sending json search query "Manchester"
+        Then the result is valid json
+        Given the request parameters
+          | <parameter>
+          | <value>
+        When sending jsonv2 search query "Manchester"
+        Then the result is valid json
+
+    Examples:
+     | parameter        | value
+     | polygon          | 1
+     | polygon          | 0
+     | polygon_text     | 1
+     | polygon_text     | 0
+     | polygon_kml      | 1
+     | polygon_kml      | 0
+     | polygon_geojson  | 1
+     | polygon_geojson  | 0
+     | polygon_svg      | 1
+     | polygon_svg      | 0
+
+
+
+
     Scenario Outline: Wrapping of legal jsonp requests
         Given the request parameters
         | json_callback
index 7099c72fe4d9f0e4c7fa4b75253f8529093aa441..fa0e63b7afe2a70e8dfc25c2628348002ec4af5e 100644 (file)
@@ -230,3 +230,73 @@ Feature: Search queries
         | xml
         | json
         | jsonv2
+
+
+   Scenario Outline: Search result with contains TEXT geometry
+        Given the request parameters
+          | polygon_text
+          | 1
+        When sending <format> search query "switzerland"
+        Then result 0 has attributes <response_attribute>
+
+   Examples:
+        | format   | response_attribute
+        | xml      | geotext
+        | json     | geotext
+        | jsonv2   | geotext
+
+   Scenario Outline: Search result contains polygon-as-points geometry
+        Given the request parameters
+          | polygon
+          | 1
+        When sending <format> search query "switzerland"
+        Then result 0 has attributes <response_attribute>
+
+   Examples:
+        | format   | response_attribute
+        | xml      | polygonpoints
+        | json     | polygonpoints
+        | jsonv2   | polygonpoints
+
+
+
+   Scenario Outline: Search result contains SVG geometry
+        Given the request parameters
+          | polygon_svg
+          | 1
+        When sending <format> search query "switzerland"
+        Then result 0 has attributes <response_attribute>
+
+   Examples:
+        | format   | response_attribute
+        | xml      | geosvg
+        | json     | svg
+        | jsonv2   | svg
+
+
+   Scenario Outline: Search result contains KML geometry
+        Given the request parameters
+          | polygon_kml
+          | 1
+        When sending <format> search query "switzerland"
+        Then result 0 has attributes <response_attribute>
+
+   Examples:
+        | format   | response_attribute
+        | xml      | geokml
+        | json     | geokml
+        | jsonv2   | geokml
+
+
+   Scenario Outline: Search result contains GEOJSON geometry
+        Given the request parameters
+          | polygon_geojson
+          | 1
+        When sending <format> search query "switzerland"
+        Then result 0 has attributes <response_attribute>
+
+   Examples:
+        | format   | response_attribute
+        | xml      | geojson
+        | json     | geojson
+        | jsonv2   | geojson
index 4910c157649d17bc7f818abeca610f366eb75c18..5e1bcc90e09ee0b8ae82e101939f8a3fcc4c4917 100644 (file)
@@ -98,6 +98,8 @@ def _parse_xml():
                     attrs = dict(tag.attributes.items())
                     assert_in('desc', attrs)
                     world.results[0]['namedetails'][attrs['desc']] = tag.firstChild.nodeValue.strip()
+            elif node.nodeName == "geokml":
+                world.results[0]['geokml'] = node
             elif node.nodeName == "#text":
                 pass
             else:
index f760dc09043e588e920bc8538efefdaca0c1cb8b..ca823d3cdf60d1be6d1da3cfa4ae4e2dc1e06dfa 100755 (executable)
                }
        }
 
+
+       $bAsPoints = false;
+       $bAsGeoJSON = (boolean)isset($_GET['polygon_geojson']) && $_GET['polygon_geojson'];
+       $bAsKML = (boolean)isset($_GET['polygon_kml']) && $_GET['polygon_kml'];
+       $bAsSVG = (boolean)isset($_GET['polygon_svg']) && $_GET['polygon_svg'];
+       $bAsText = (boolean)isset($_GET['polygon_text']) && $_GET['polygon_text'];
+       if ( ( ($bAsGeoJSON?1:0)
+                        + ($bAsKML?1:0)
+                        + ($bAsSVG?1:0)
+                        + ($bAsText?1:0)
+                        + ($bAsPoints?1:0)
+                        ) > CONST_PolygonOutput_MaximumTypes)
+       {
+               if (CONST_PolygonOutput_MaximumTypes)
+               {
+                       userError("Select only ".CONST_PolygonOutput_MaximumTypes." polgyon output option");
+               }
+               else
+               {
+                       userError("Polygon output is disabled");
+               }
+               exit;
+       }
+
+
+       // Polygon simplification threshold (optional)
+       $fThreshold = 0.0;
+       if (isset($_GET['polygon_threshold'])) $fThreshold = (float)$_GET['polygon_threshold'];
+
+
        $oDB =& getDB();
        ini_set('memory_limit', '200M');
 
                $oPlaceLookup->setIncludeNameDetails(getParamBool('namedetails', false));
 
                $aPlace = $oPlaceLookup->lookupPlace($aLookup);
+
+               $oPlaceLookup->setIncludePolygonAsPoints($bAsPoints);
+               $oPlaceLookup->setIncludePolygonAsText($bAsText);
+               $oPlaceLookup->setIncludePolygonAsGeoJSON($bAsGeoJSON);
+               $oPlaceLookup->setIncludePolygonAsKML($bAsKML);
+               $oPlaceLookup->setIncludePolygonAsSVG($bAsSVG);
+               $oPlaceLookup->setPolygonSimplificationThreshold($fThreshold);
+
+               $fRadius = $fDiameter = getResultDiameter($aPlace);
+               $aOutlineResult = $oPlaceLookup->getOutlines($aPlace['place_id'],$aPlace['lon'],$aPlace['lat'],$fRadius);
+
+               foreach($aOutlineResult as $k => $v)
+               {
+                       $aPlace[$k] = $v;
+               }
+
        }
        else
        {