X-Git-Url: https://git.openstreetmap.org./nominatim.git/blobdiff_plain/1b33999f105a0d2499b880f77fefae29346bab2d..5464dec0570c2451d8607bc739c6f2b6f298bb75:/lib/Geocode.php diff --git a/lib/Geocode.php b/lib/Geocode.php index ce77862b..b102c4b2 100644 --- a/lib/Geocode.php +++ b/lib/Geocode.php @@ -33,9 +33,9 @@ protected $bBoundedSearch = false; protected $aViewBox = false; + protected $sViewboxCentreSQL = false; protected $sViewboxSmallSQL = false; protected $sViewboxLargeSQL = false; - protected $aRoutePoints = false; protected $iMaxRank = 20; protected $iMinAddressRank = 0; @@ -63,11 +63,6 @@ $this->aLangPrefOrder = $aLangPref; } - function setIncludeAddressDetails($bAddressDetails = true) - { - $this->bIncludeAddressDetails = (bool)$bAddressDetails; - } - function getIncludeAddressDetails() { return $this->bIncludeAddressDetails; @@ -88,21 +83,11 @@ $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; @@ -123,34 +108,13 @@ $this->fPolygonSimplificationThreshold = $f; } - function setDeDupe($bDeDupe = true) - { - $this->bDeDupe = (bool)$bDeDupe; - } - function setLimit($iLimit = 10) { if ($iLimit > 50) $iLimit = 50; if ($iLimit < 1) $iLimit = 1; $this->iFinalLimit = $iLimit; - $this->iLimit = $this->iFinalLimit + min($this->iFinalLimit, 10); - } - - function setOffset($iOffset = 0) - { - $this->iOffset = $iOffset; - } - - function setFallback($bFallback = true) - { - $this->bFallback = (bool)$bFallback; - } - - function setExcludedPlaceIDs($a) - { - // TODO: force to int - $this->aExcludePlaceIDs = $a; + $this->iLimit = $iLimit + min($iLimit, 10); } function getExcludedPlaceIDs() @@ -158,27 +122,12 @@ return $this->aExcludePlaceIDs; } - function setBounded($bBoundedSearch = true) - { - $this->bBoundedSearch = (bool)$bBoundedSearch; - } - - function setViewBox($fLeft, $fBottom, $fRight, $fTop) - { - $this->aViewBox = array($fLeft, $fBottom, $fRight, $fTop); - } - function getViewBoxString() { if (!$this->aViewBox) return null; return $this->aViewBox[0].','.$this->aViewBox[3].','.$this->aViewBox[2].','.$this->aViewBox[1]; } - function setRoute($aRoutePoints) - { - $this->aRoutePoints = $aRoutePoints; - } - function setFeatureType($sFeatureType) { switch($sFeatureType) @@ -200,18 +149,50 @@ function setRankRange($iMin, $iMax) { - $this->iMinAddressRank = (int)$iMin; - $this->iMaxAddressRank = (int)$iMax; + $this->iMinAddressRank = $iMin; + $this->iMaxAddressRank = $iMax; } - function setNearPoint($aNearPoint, $fRadiusDeg = 0.1) + function setRoute($aRoutePoints, $fRouteWidth) { - $this->aNearPoint = array((float)$aNearPoint[0], (float)$aNearPoint[1], (float)$fRadiusDeg); + $this->aViewBox = false; + + $this->sViewboxCentreSQL = "ST_SetSRID('LINESTRING("; + $sSep = ''; + foreach($this->aRoutePoints as $aPoint) + { + $fPoint = (float)$aPoint; + $this->sViewboxCentreSQL .= $sSep.$fPoint; + $sSep = ($sSep == ' ') ? ',' : ' '; + } + $this->sViewboxCentreSQL .= ")'::geometry,4326)"; + + $this->sViewboxSmallSQL = 'st_buffer('.$this->sViewboxCentreSQL; + $this->sViewboxSmallSQL .= ','.($fRouteWidth/69).')'; + + $this->sViewboxLargeSQL = 'st_buffer('.$this->sViewboxCentreSQL; + $this->sViewboxLargeSQL .= ','.($fRouteWidth/30).')'; } - function setCountryCodesList($aCountryCodes) + function setViewbox($aViewbox) { - $this->aCountryCodes = $aCountryCodes; + $this->aViewBox = array_map('floatval', $aViewbox); + + $fHeight = $this->aViewBox[0] - $this->aViewBox[2]; + $fWidth = $this->aViewBox[1] - $this->aViewBox[3]; + $aBigViewBox[0] = $this->aViewBox[0] + $fHeight; + $aBigViewBox[2] = $this->aViewBox[2] - $fHeight; + $aBigViewBox[1] = $this->aViewBox[1] + $fWidth; + $aBigViewBox[3] = $this->aViewBox[3] - $fWidth; + + $this->sViewboxCentreSQL = false; + $this->sViewboxSmallSQL = "ST_SetSRID(ST_MakeBox2D(ST_Point(".$this->aViewBox[0].",".$this->aViewBox[1]."),ST_Point(".$this->aViewBox[2].",".$this->aViewBox[3].")),4326)"; + $this->sViewboxLargeSQL = "ST_SetSRID(ST_MakeBox2D(ST_Point(".$aBigViewBox[0].",".$aBigViewBox[1]."),ST_Point(".$aBigViewBox[2].",".$aBigViewBox[3].")),4326)"; + } + + function setNearPoint($aNearPoint, $fRadiusDeg = 0.1) + { + $this->aNearPoint = array((float)$aNearPoint[0], (float)$aNearPoint[1], (float)$fRadiusDeg); } function setQuery($sQueryString) @@ -226,24 +207,28 @@ } - function loadParamArray($aParams) + function loadParamArray($oParams) { - if (isset($aParams['addressdetails'])) $this->bIncludeAddressDetails = (bool)$aParams['addressdetails']; - if (isset($aParams['extratags'])) $this->bIncludeExtraTags = (bool)$aParams['extratags']; - if (isset($aParams['namedetails'])) $this->bIncludeNameDetails = (bool)$aParams['namedetails']; + $this->bIncludeAddressDetails = $oParams->getBool('addressdetails', + $this->bIncludeAddressDetails); + $this->bIncludeExtraTags = $oParams->getBool('extratags', + $this->bIncludeExtraTags); + $this->bIncludeNameDetails = $oParams->getBool('namedetails', + $this->bIncludeNameDetails); - if (isset($aParams['bounded'])) $this->bBoundedSearch = (bool)$aParams['bounded']; - if (isset($aParams['dedupe'])) $this->bDeDupe = (bool)$aParams['dedupe']; + $this->bBoundedSearch = $oParams->getBool('bounded', $this->bBoundedSearch); + $this->bDeDupe = $oParams->getBool('dedupe', $this->bDeDupe); - if (isset($aParams['limit'])) $this->setLimit((int)$aParams['limit']); - if (isset($aParams['offset'])) $this->iOffset = (int)$aParams['offset']; + $this->setLimit($oParams->getInt('limit', $this->iFinalLimit)); + $this->iOffset = $oParams->getInt('offset', $this->iOffset); - if (isset($aParams['fallback'])) $this->bFallback = (bool)$aParams['fallback']; + $this->bFallback = $oParams->getBool('fallback', $this->bFallback); // List of excluded Place IDs - used for more acurate pageing - if (isset($aParams['exclude_place_ids']) && $aParams['exclude_place_ids']) + $sExcluded = $oParams->getStringList('exclude_place_ids'); + if ($sExcluded) { - foreach(explode(',',$aParams['exclude_place_ids']) as $iExcludedPlaceID) + foreach($sExcluded as $iExcludedPlaceID) { $iExcludedPlaceID = (int)$iExcludedPlaceID; if ($iExcludedPlaceID) @@ -255,66 +240,63 @@ } // Only certain ranks of feature - if (isset($aParams['featureType'])) $this->setFeatureType($aParams['featureType']); - if (isset($aParams['featuretype'])) $this->setFeatureType($aParams['featuretype']); + $sFeatureType = $oParams->getString('featureType'); + if (!$sFeatureType) $sFeatureType = $oParams->getString('featuretype'); + if ($sFeatureType) $this->setFeatureType($sFeatureType); // Country code list - if (isset($aParams['countrycodes'])) + $sCountries = $oParams->getStringList('countrycodes'); + if ($sCountries) { - $aCountryCodes = array(); - foreach(explode(',',$aParams['countrycodes']) as $sCountryCode) + foreach($sCountries as $sCountryCode) { if (preg_match('/^[a-zA-Z][a-zA-Z]$/', $sCountryCode)) { - $aCountryCodes[] = strtolower($sCountryCode); + $aCountries[] = strtolower($sCountryCode); } } - $this->aCountryCodes = $aCountryCodes; + if (isset($aCountryCodes)) + $this->aCountryCodes = $aCountries; } - if (isset($aParams['viewboxlbrt']) && $aParams['viewboxlbrt']) - { - $aCoOrdinatesLBRT = explode(',',$aParams['viewboxlbrt']); - $this->setViewBox($aCoOrdinatesLBRT[0], $aCoOrdinatesLBRT[1], $aCoOrdinatesLBRT[2], $aCoOrdinatesLBRT[3]); - } - else if (isset($aParams['viewbox']) && $aParams['viewbox']) + $aViewbox = $oParams->getStringList('viewboxlbrt'); + if ($aViewbox) { - $aCoOrdinatesLTRB = explode(',',$aParams['viewbox']); - $this->setViewBox($aCoOrdinatesLTRB[0], $aCoOrdinatesLTRB[3], $aCoOrdinatesLTRB[2], $aCoOrdinatesLTRB[1]); + $this->setViewbox($aViewbox); } - - if (isset($aParams['route']) && $aParams['route'] && isset($aParams['routewidth']) && $aParams['routewidth']) + else { - $aPoints = explode(',',$aParams['route']); - if (sizeof($aPoints) % 2 != 0) + $aViewbox = $oParams->getStringList('viewbox'); + if ($aViewbox) { - userError("Uneven number of points"); - exit; + $this->setViewBox(array($aViewbox[0], $aViewbox[3], + $aViewbox[2], $aViewbox[1])); } - $fPrevCoord = false; - $aRoute = array(); - foreach($aPoints as $i => $fPoint) + else { - if ($i%2) + $aRoute = $oParams->getStringList('route'); + $fRouteWidth = $oParams->getFloat('routewidth'); + if ($aRoute && $fRouteWidth) { - $aRoute[] = array((float)$fPoint, $fPrevCoord); - } - else - { - $fPrevCoord = (float)$fPoint; + $this->setRoute($aRoute, $fRouteWidth); } } - $this->aRoutePoints = $aRoute; } } - function setQueryFromParams($aParams) + function setQueryFromParams($oParams) { // Search query - $sQuery = (isset($aParams['q'])?trim($aParams['q']):''); + $sQuery = $oParams->getString('q'); if (!$sQuery) { - $this->setStructuredQuery(@$aParams['amenity'], @$aParams['street'], @$aParams['city'], @$aParams['county'], @$aParams['state'], @$aParams['country'], @$aParams['postalcode']); + $this->setStructuredQuery($oParams->getString('amenity'), + $oParams->getString('street'), + $oParams->getString('city'), + $oParams->getString('county'), + $oParams->getString('state'), + $oParams->getString('country'), + $oParams->getString('postalcode')); $this->setReverseInPlan(false); } else @@ -834,7 +816,7 @@ $sLanguagePrefArraySQL = "ARRAY[".join(',',array_map("getDBQuoted",$this->aLangPrefOrder))."]"; $sCountryCodesSQL = false; - if ($this->aCountryCodes && sizeof($this->aCountryCodes)) + if ($this->aCountryCodes) { $sCountryCodesSQL = join(',', array_map('addQuotes', $this->aCountryCodes)); } @@ -849,46 +831,17 @@ $sQuery = preg_replace('/(^|,)\s*la\s*(,|$)/','\1louisiana\2', $sQuery); } - // View Box SQL - $sViewboxCentreSQL = false; - $bBoundingBoxSearch = false; - if ($this->aViewBox) - { - $fHeight = $this->aViewBox[0]-$this->aViewBox[2]; - $fWidth = $this->aViewBox[1]-$this->aViewBox[3]; - $aBigViewBox[0] = $this->aViewBox[0] + $fHeight; - $aBigViewBox[2] = $this->aViewBox[2] - $fHeight; - $aBigViewBox[1] = $this->aViewBox[1] + $fWidth; - $aBigViewBox[3] = $this->aViewBox[3] - $fWidth; - - $this->sViewboxSmallSQL = "ST_SetSRID(ST_MakeBox2D(ST_Point(".(float)$this->aViewBox[0].",".(float)$this->aViewBox[1]."),ST_Point(".(float)$this->aViewBox[2].",".(float)$this->aViewBox[3].")),4326)"; - $this->sViewboxLargeSQL = "ST_SetSRID(ST_MakeBox2D(ST_Point(".(float)$aBigViewBox[0].",".(float)$aBigViewBox[1]."),ST_Point(".(float)$aBigViewBox[2].",".(float)$aBigViewBox[3].")),4326)"; - $bBoundingBoxSearch = $this->bBoundedSearch; - } - - // Route SQL - if ($this->aRoutePoints) + $bBoundingBoxSearch = $this->bBoundedSearch && $this->sViewboxSmallSQL; + if ($this->sViewboxCentreSQL) { - $sViewboxCentreSQL = "ST_SetSRID('LINESTRING("; - $bFirst = true; - foreach($this->aRoutePoints as $aPoint) - { - if (!$bFirst) $sViewboxCentreSQL .= ","; - $sViewboxCentreSQL .= $aPoint[0].' '.$aPoint[1]; - $bFirst = false; - } - $sViewboxCentreSQL .= ")'::geometry,4326)"; - - $sSQL = "select st_buffer(".$sViewboxCentreSQL.",".(float)($_GET['routewidth']/69).")"; - $this->sViewboxSmallSQL = chksql($this->oDB->getOne($sSQL), - "Could not get small viewbox."); - $this->sViewboxSmallSQL = "'".$this->sViewboxSmallSQL."'::geometry"; - - $sSQL = "select st_buffer(".$sViewboxCentreSQL.",".(float)($_GET['routewidth']/30).")"; - $this->sViewboxLargeSQL = chksql($this->oDB->getOne($sSQL), - "Could not get large viewbox."); - $this->sViewboxLargeSQL = "'".$this->sViewboxLargeSQL."'::geometry"; - $bBoundingBoxSearch = $this->bBoundedSearch; + // For complex viewboxes (routes) precompute the bounding geometry + $sGeom = chksql($this->oDB->getOne("select ".$this->sViewboxSmallSQL), + "Could not get small viewbox"); + $this->sViewboxSmallSQL = "'".$sGeom."'::geometry"; + + $sGeom = chksql($this->oDB->getOne("select ".$this->sViewboxLargeSQL), + "Could not get large viewbox"); + $this->sViewboxLargeSQL = "'".$sGeom."'::geometry"; } // Do we have anything that looks like a lat/lon pair? @@ -1275,7 +1228,7 @@ { $sSQL .= " and place_id not in (".join(',',$this->aExcludePlaceIDs).")"; } - if ($sViewboxCentreSQL) $sSQL .= " order by st_distance($sViewboxCentreSQL, ct.centroid) asc"; + if ($this->sViewboxCentreSQL) $sSQL .= " order by st_distance($this->sViewboxCentreSQL, ct.centroid) asc"; $sSQL .= " limit $this->iLimit"; if (CONST_Debug) var_dump($sSQL); $aPlaceIDs = chksql($this->oDB->getCol($sSQL)); @@ -1290,7 +1243,7 @@ if ($sCountryCodesSQL) $sSQL .= " join placex using (place_id)"; $sSQL .= " where st_contains($this->sViewboxLargeSQL, ct.centroid)"; if ($sCountryCodesSQL) $sSQL .= " and calculated_country_code in ($sCountryCodesSQL)"; - if ($sViewboxCentreSQL) $sSQL .= " order by st_distance($sViewboxCentreSQL, ct.centroid) asc"; + if ($this->sViewboxCentreSQL) $sSQL .= " order by st_distance($this->sViewboxCentreSQL, ct.centroid) asc"; $sSQL .= " limit $this->iLimit"; if (CONST_Debug) var_dump($sSQL); $aPlaceIDs = chksql($this->oDB->getCol($sSQL)); @@ -1301,7 +1254,7 @@ $sSQL = "select place_id from placex where class='".$aSearch['sClass']."' and type='".$aSearch['sType']."'"; $sSQL .= " and st_contains($this->sViewboxSmallSQL, geometry) and linked_place_id is null"; if ($sCountryCodesSQL) $sSQL .= " and calculated_country_code in ($sCountryCodesSQL)"; - if ($sViewboxCentreSQL) $sSQL .= " order by st_distance($sViewboxCentreSQL, centroid) asc"; + if ($this->sViewboxCentreSQL) $sSQL .= " order by st_distance($this->sViewboxCentreSQL, centroid) asc"; $sSQL .= " limit $this->iLimit"; if (CONST_Debug) var_dump($sSQL); $aPlaceIDs = chksql($this->oDB->getCol($sSQL)); @@ -1735,19 +1688,19 @@ if (CONST_Debug) { echo 'Recheck words:<\i>'; var_dump($aRecheckWords); } + $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); + foreach($aSearchResults as $iResNum => $aResult) { // Default $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); if ($aOutlineResult) {