mirror of
https://github.com/osm-search/Nominatim.git
synced 2026-02-14 18:37:58 +00:00
make NearPoint its own class
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Nominatim;
|
||||
|
||||
require_once(CONST_BasePath.'/lib/NearPoint.php');
|
||||
require_once(CONST_BasePath.'/lib/PlaceLookup.php');
|
||||
require_once(CONST_BasePath.'/lib/ReverseGeocode.php');
|
||||
|
||||
@@ -32,7 +33,6 @@ class Geocode
|
||||
protected $bFallback = false;
|
||||
|
||||
protected $aCountryCodes = false;
|
||||
protected $aNearPoint = false;
|
||||
|
||||
protected $bBoundedSearch = false;
|
||||
protected $aViewBox = false;
|
||||
@@ -221,11 +221,6 @@ class Geocode
|
||||
);
|
||||
}
|
||||
|
||||
public function setNearPoint($aNearPoint, $fRadiusDeg = 0.1)
|
||||
{
|
||||
$this->aNearPoint = array((float)$aNearPoint[0], (float)$aNearPoint[1], (float)$fRadiusDeg);
|
||||
}
|
||||
|
||||
public function setQuery($sQueryString)
|
||||
{
|
||||
$this->sQuery = $sQueryString;
|
||||
@@ -942,8 +937,9 @@ class Geocode
|
||||
}
|
||||
|
||||
// Do we have anything that looks like a lat/lon pair?
|
||||
if ($aLooksLike = looksLikeLatLonPair($sQuery)) {
|
||||
$this->setNearPoint(array($aLooksLike['lat'], $aLooksLike['lon']));
|
||||
$oNearPoint = false;
|
||||
if ($aLooksLike = NearPoint::extractFromQuery($sQuery)) {
|
||||
$oNearPoint = $aLooksLike['pt'];
|
||||
$sQuery = $aLooksLike['query'];
|
||||
}
|
||||
|
||||
@@ -972,12 +968,10 @@ class Geocode
|
||||
);
|
||||
|
||||
// Do we have a radius search?
|
||||
$sNearPointSQL = false;
|
||||
if ($this->aNearPoint) {
|
||||
$sNearPointSQL = "ST_SetSRID(ST_Point(".(float)$this->aNearPoint[1].",".(float)$this->aNearPoint[0]."),4326)";
|
||||
$aSearches[0]['fLat'] = (float)$this->aNearPoint[0];
|
||||
$aSearches[0]['fLon'] = (float)$this->aNearPoint[1];
|
||||
$aSearches[0]['fRadius'] = (float)$this->aNearPoint[2];
|
||||
if ($oNearPoint) {
|
||||
$aSearches[0]['fLat'] = $oNearPoint->lat();
|
||||
$aSearches[0]['fLon'] = $oNearPoint->lon();
|
||||
$aSearches[0]['fRadius'] = $oNearPoint->radius();
|
||||
}
|
||||
|
||||
// Any 'special' terms in the search?
|
||||
@@ -1382,7 +1376,9 @@ class Geocode
|
||||
}
|
||||
|
||||
if ($bBoundingBoxSearch) $aTerms[] = "centroid && $this->sViewboxSmallSQL";
|
||||
if ($sNearPointSQL) $aOrder[] = "ST_Distance($sNearPointSQL, centroid) ASC";
|
||||
if ($oNearPoint) {
|
||||
$aOrder[] = $oNearPoint->distanceSQL('centroid');
|
||||
}
|
||||
|
||||
if ($aSearch['sHouseNumber']) {
|
||||
$sImportanceSQL = '- abs(26 - address_rank) + 3';
|
||||
@@ -1590,9 +1586,13 @@ class Geocode
|
||||
$fRange = 0.05;
|
||||
|
||||
$sOrderBySQL = '';
|
||||
if ($sNearPointSQL) $sOrderBySQL = "ST_Distance($sNearPointSQL, l.centroid)";
|
||||
elseif ($sPlaceIDs) $sOrderBySQL = "ST_Distance(l.centroid, f.geometry)";
|
||||
elseif ($sPlaceGeom) $sOrderBysSQL = "ST_Distance(st_centroid('".$sPlaceGeom."'), l.centroid)";
|
||||
if ($oNearPoint) {
|
||||
$sOrderBySQL = $oNearPoint->distanceSQL('l.centroid');
|
||||
} elseif ($sPlaceIDs) {
|
||||
$sOrderBySQL = "ST_Distance(l.centroid, f.geometry)";
|
||||
} elseif ($sPlaceGeom) {
|
||||
$sOrderBysSQL = "ST_Distance(st_centroid('".$sPlaceGeom."'), l.centroid)";
|
||||
}
|
||||
|
||||
$sSQL = "select distinct l.place_id".($sOrderBySQL?','.$sOrderBySQL:'')." from place_classtype_".$aSearch['sClass']."_".$aSearch['sType']." as l";
|
||||
if ($sCountryCodesSQL) $sSQL .= " join placex as lp using (place_id)";
|
||||
@@ -1617,8 +1617,11 @@ class Geocode
|
||||
if (isset($aSearch['fRadius']) && $aSearch['fRadius']) $fRange = $aSearch['fRadius'];
|
||||
|
||||
$sOrderBySQL = '';
|
||||
if ($sNearPointSQL) $sOrderBySQL = "ST_Distance($sNearPointSQL, l.geometry)";
|
||||
else $sOrderBySQL = "ST_Distance(l.geometry, f.geometry)";
|
||||
if ($oNearPoint) {
|
||||
$sOrderBySQL = $oNearPoint->distanceSQL('l.geometry');
|
||||
} else {
|
||||
$sOrderBySQL = "ST_Distance(l.geometry, f.geometry)";
|
||||
}
|
||||
|
||||
$sSQL = "SELECT distinct l.place_id".($sOrderBysSQL?','.$sOrderBysSQL:'');
|
||||
$sSQL .= " FROM placex as l, placex as f ";
|
||||
@@ -1708,8 +1711,8 @@ class Geocode
|
||||
$oReverse->setZoom(18);
|
||||
|
||||
$aLookup = $oReverse->lookup(
|
||||
(float)$this->aNearPoint[0],
|
||||
(float)$this->aNearPoint[1],
|
||||
$oNearPoint->lat(),
|
||||
$oNearPoint->lon(),
|
||||
false
|
||||
);
|
||||
|
||||
|
||||
135
lib/NearPoint.php
Normal file
135
lib/NearPoint.php
Normal file
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
namespace Nominatim;
|
||||
|
||||
/**
|
||||
* A geographic point with a search radius.
|
||||
*/
|
||||
class NearPoint
|
||||
{
|
||||
private $fLat;
|
||||
private $fLon;
|
||||
private $fRadius;
|
||||
|
||||
private $sSQL;
|
||||
|
||||
public function __construct($lat, $lon, $radius = 0.1)
|
||||
{
|
||||
$this->fLat = (float)$lat;
|
||||
$this->fLon = (float)$lon;
|
||||
$this->fRadius = (float)$radius;
|
||||
$this->sSQL = 'ST_SetSRID(ST_Point('.$this->fLon.','.$this->fLat.'),4326)';
|
||||
}
|
||||
|
||||
public function lat() { return $this->fLat; }
|
||||
|
||||
public function lon() { return $this->fLon; }
|
||||
|
||||
public function radius() { return $this->fRadius; }
|
||||
|
||||
public function distanceSQL($sObj)
|
||||
{
|
||||
return 'ST_Distance('.$this->sSQL.", $sObj)";
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the coordinates are valid WSG84 coordinates.
|
||||
*/
|
||||
public function isValid()
|
||||
{
|
||||
return ($this->fLat <= 90.1
|
||||
&& $this->fLat >= -90.1
|
||||
&& $this->fLon <= 180.1
|
||||
&& $this->fLon >= -180.1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a coordinate point from a query string.
|
||||
*
|
||||
* If a coordinate is found an array of a new NearPoint and the
|
||||
* remaining query is returned or false otherwise.
|
||||
*/
|
||||
public static function extractFromQuery($sQuery)
|
||||
{
|
||||
// Do we have anything that looks like a lat/lon pair?
|
||||
// returns array(lat,lon,query_with_lat_lon_removed)
|
||||
// or null
|
||||
$sFound = null;
|
||||
$fQueryLat = null;
|
||||
$fQueryLon = null;
|
||||
|
||||
if (preg_match('/\\b([NS])[ ]+([0-9]+[0-9.]*)[° ]+([0-9.]+)?[′\']*[, ]+([EW])[ ]+([0-9]+)[° ]+([0-9]+[0-9.]*)[′\']*?\\b/', $sQuery, $aData)) {
|
||||
/* 1 2 3 4 5 6
|
||||
* degrees decimal minutes
|
||||
* N 40 26.767, W 79 58.933
|
||||
* N 40°26.767′, W 79°58.933′
|
||||
*/
|
||||
$sFound = $aData[0];
|
||||
$fQueryLat = ($aData[1]=='N'?1:-1) * ($aData[2] + $aData[3]/60);
|
||||
$fQueryLon = ($aData[4]=='E'?1:-1) * ($aData[5] + $aData[6]/60);
|
||||
} elseif (preg_match('/\\b([0-9]+)[° ]+([0-9]+[0-9.]*)?[′\']*[ ]+([NS])[, ]+([0-9]+)[° ]+([0-9]+[0-9.]*)?[′\' ]+([EW])\\b/', $sQuery, $aData)) {
|
||||
/* 1 2 3 4 5 6
|
||||
* degrees decimal minutes
|
||||
* 40 26.767 N, 79 58.933 W
|
||||
* 40° 26.767′ N 79° 58.933′ W
|
||||
*/
|
||||
$sFound = $aData[0];
|
||||
$fQueryLat = ($aData[3]=='N'?1:-1) * ($aData[1] + $aData[2]/60);
|
||||
$fQueryLon = ($aData[6]=='E'?1:-1) * ($aData[4] + $aData[5]/60);
|
||||
} elseif (preg_match('/\\b([NS])[ ]([0-9]+)[° ]+([0-9]+)[′\' ]+([0-9]+)[″"]*[, ]+([EW])[ ]([0-9]+)[° ]+([0-9]+)[′\' ]+([0-9]+)[″"]*\\b/', $sQuery, $aData)) {
|
||||
/* 1 2 3 4 5 6 7 8
|
||||
* degrees decimal seconds
|
||||
* N 40 26 46 W 79 58 56
|
||||
* N 40° 26′ 46″, W 79° 58′ 56″
|
||||
*/
|
||||
$sFound = $aData[0];
|
||||
$fQueryLat = ($aData[1]=='N'?1:-1) * ($aData[2] + $aData[3]/60 + $aData[4]/3600);
|
||||
$fQueryLon = ($aData[5]=='E'?1:-1) * ($aData[6] + $aData[7]/60 + $aData[8]/3600);
|
||||
} elseif (preg_match('/\\b([0-9]+)[° ]+([0-9]+)[′\' ]+([0-9]+)[″" ]+([NS])[, ]+([0-9]+)[° ]+([0-9]+)[′\' ]+([0-9]+)[″" ]+([EW])\\b/', $sQuery, $aData)) {
|
||||
/* 1 2 3 4 5 6 7 8
|
||||
* degrees decimal seconds
|
||||
* 40 26 46 N 79 58 56 W
|
||||
* 40° 26′ 46″ N, 79° 58′ 56″ W
|
||||
*/
|
||||
$sFound = $aData[0];
|
||||
$fQueryLat = ($aData[4]=='N'?1:-1) * ($aData[1] + $aData[2]/60 + $aData[3]/3600);
|
||||
$fQueryLon = ($aData[8]=='E'?1:-1) * ($aData[5] + $aData[6]/60 + $aData[7]/3600);
|
||||
} elseif (preg_match('/\\b([NS])[ ]([0-9]+[0-9]*\\.[0-9]+)[°]*[, ]+([EW])[ ]([0-9]+[0-9]*\\.[0-9]+)[°]*\\b/', $sQuery, $aData)) {
|
||||
/* 1 2 3 4
|
||||
* degrees decimal
|
||||
* N 40.446° W 79.982°
|
||||
*/
|
||||
$sFound = $aData[0];
|
||||
$fQueryLat = ($aData[1]=='N'?1:-1) * ($aData[2]);
|
||||
$fQueryLon = ($aData[3]=='E'?1:-1) * ($aData[4]);
|
||||
} elseif (preg_match('/\\b([0-9]+[0-9]*\\.[0-9]+)[° ]+([NS])[, ]+([0-9]+[0-9]*\\.[0-9]+)[° ]+([EW])\\b/', $sQuery, $aData)) {
|
||||
/* 1 2 3 4
|
||||
* degrees decimal
|
||||
* 40.446° N 79.982° W
|
||||
*/
|
||||
$sFound = $aData[0];
|
||||
$fQueryLat = ($aData[2]=='N'?1:-1) * ($aData[1]);
|
||||
$fQueryLon = ($aData[4]=='E'?1:-1) * ($aData[3]);
|
||||
} elseif (preg_match('/(\\[|^|\\b)(-?[0-9]+[0-9]*\\.[0-9]+)[, ]+(-?[0-9]+[0-9]*\\.[0-9]+)(\\]|$|\\b)/', $sQuery, $aData)) {
|
||||
/* 1 2 3 4
|
||||
* degrees decimal
|
||||
* 12.34, 56.78
|
||||
* [12.456,-78.90]
|
||||
*/
|
||||
$sFound = $aData[0];
|
||||
$fQueryLat = $aData[2];
|
||||
$fQueryLon = $aData[3];
|
||||
} else {
|
||||
return False;
|
||||
}
|
||||
|
||||
$oPt = new NearPoint($fQueryLat, $fQueryLon);
|
||||
|
||||
if (!$oPt->isValid()) return False;
|
||||
|
||||
$sQuery = trim(str_replace($sFound, ' ', $sQuery));
|
||||
|
||||
return array('pt' => $oPt, 'query' => $sQuery);
|
||||
}
|
||||
|
||||
}
|
||||
83
lib/lib.php
83
lib/lib.php
@@ -599,89 +599,6 @@ function addQuotes($s)
|
||||
return "'".$s."'";
|
||||
}
|
||||
|
||||
function validLatLon($fLat, $fLon)
|
||||
{
|
||||
return ($fLat <= 90.1 && $fLat >= -90.1 && $fLon <= 180.1 && $fLon >= -180.1);
|
||||
}
|
||||
|
||||
function looksLikeLatLonPair($sQuery)
|
||||
{
|
||||
// Do we have anything that looks like a lat/lon pair?
|
||||
// returns array(lat,lon,query_with_lat_lon_removed)
|
||||
// or null
|
||||
$sFound = null;
|
||||
$fQueryLat = null;
|
||||
$fQueryLon = null;
|
||||
|
||||
if (preg_match('/\\b([NS])[ ]+([0-9]+[0-9.]*)[° ]+([0-9.]+)?[′\']*[, ]+([EW])[ ]+([0-9]+)[° ]+([0-9]+[0-9.]*)[′\']*?\\b/', $sQuery, $aData)) {
|
||||
/* 1 2 3 4 5 6
|
||||
* degrees decimal minutes
|
||||
* N 40 26.767, W 79 58.933
|
||||
* N 40°26.767′, W 79°58.933′
|
||||
*/
|
||||
$sFound = $aData[0];
|
||||
$fQueryLat = ($aData[1]=='N'?1:-1) * ($aData[2] + $aData[3]/60);
|
||||
$fQueryLon = ($aData[4]=='E'?1:-1) * ($aData[5] + $aData[6]/60);
|
||||
} elseif (preg_match('/\\b([0-9]+)[° ]+([0-9]+[0-9.]*)?[′\']*[ ]+([NS])[, ]+([0-9]+)[° ]+([0-9]+[0-9.]*)?[′\' ]+([EW])\\b/', $sQuery, $aData)) {
|
||||
/* 1 2 3 4 5 6
|
||||
* degrees decimal minutes
|
||||
* 40 26.767 N, 79 58.933 W
|
||||
* 40° 26.767′ N 79° 58.933′ W
|
||||
*/
|
||||
$sFound = $aData[0];
|
||||
$fQueryLat = ($aData[3]=='N'?1:-1) * ($aData[1] + $aData[2]/60);
|
||||
$fQueryLon = ($aData[6]=='E'?1:-1) * ($aData[4] + $aData[5]/60);
|
||||
} elseif (preg_match('/\\b([NS])[ ]([0-9]+)[° ]+([0-9]+)[′\' ]+([0-9]+)[″"]*[, ]+([EW])[ ]([0-9]+)[° ]+([0-9]+)[′\' ]+([0-9]+)[″"]*\\b/', $sQuery, $aData)) {
|
||||
/* 1 2 3 4 5 6 7 8
|
||||
* degrees decimal seconds
|
||||
* N 40 26 46 W 79 58 56
|
||||
* N 40° 26′ 46″, W 79° 58′ 56″
|
||||
*/
|
||||
$sFound = $aData[0];
|
||||
$fQueryLat = ($aData[1]=='N'?1:-1) * ($aData[2] + $aData[3]/60 + $aData[4]/3600);
|
||||
$fQueryLon = ($aData[5]=='E'?1:-1) * ($aData[6] + $aData[7]/60 + $aData[8]/3600);
|
||||
} elseif (preg_match('/\\b([0-9]+)[° ]+([0-9]+)[′\' ]+([0-9]+)[″" ]+([NS])[, ]+([0-9]+)[° ]+([0-9]+)[′\' ]+([0-9]+)[″" ]+([EW])\\b/', $sQuery, $aData)) {
|
||||
/* 1 2 3 4 5 6 7 8
|
||||
* degrees decimal seconds
|
||||
* 40 26 46 N 79 58 56 W
|
||||
* 40° 26′ 46″ N, 79° 58′ 56″ W
|
||||
*/
|
||||
$sFound = $aData[0];
|
||||
$fQueryLat = ($aData[4]=='N'?1:-1) * ($aData[1] + $aData[2]/60 + $aData[3]/3600);
|
||||
$fQueryLon = ($aData[8]=='E'?1:-1) * ($aData[5] + $aData[6]/60 + $aData[7]/3600);
|
||||
} elseif (preg_match('/\\b([NS])[ ]([0-9]+[0-9]*\\.[0-9]+)[°]*[, ]+([EW])[ ]([0-9]+[0-9]*\\.[0-9]+)[°]*\\b/', $sQuery, $aData)) {
|
||||
/* 1 2 3 4
|
||||
* degrees decimal
|
||||
* N 40.446° W 79.982°
|
||||
*/
|
||||
$sFound = $aData[0];
|
||||
$fQueryLat = ($aData[1]=='N'?1:-1) * ($aData[2]);
|
||||
$fQueryLon = ($aData[3]=='E'?1:-1) * ($aData[4]);
|
||||
} elseif (preg_match('/\\b([0-9]+[0-9]*\\.[0-9]+)[° ]+([NS])[, ]+([0-9]+[0-9]*\\.[0-9]+)[° ]+([EW])\\b/', $sQuery, $aData)) {
|
||||
/* 1 2 3 4
|
||||
* degrees decimal
|
||||
* 40.446° N 79.982° W
|
||||
*/
|
||||
$sFound = $aData[0];
|
||||
$fQueryLat = ($aData[2]=='N'?1:-1) * ($aData[1]);
|
||||
$fQueryLon = ($aData[4]=='E'?1:-1) * ($aData[3]);
|
||||
} elseif (preg_match('/(\\[|^|\\b)(-?[0-9]+[0-9]*\\.[0-9]+)[, ]+(-?[0-9]+[0-9]*\\.[0-9]+)(\\]|$|\\b)/', $sQuery, $aData)) {
|
||||
/* 1 2 3 4
|
||||
* degrees decimal
|
||||
* 12.34, 56.78
|
||||
* [12.456,-78.90]
|
||||
*/
|
||||
$sFound = $aData[0];
|
||||
$fQueryLat = $aData[2];
|
||||
$fQueryLon = $aData[3];
|
||||
}
|
||||
|
||||
if (!validLatLon($fQueryLat, $fQueryLon)) return;
|
||||
$sQuery = trim(str_replace($sFound, ' ', $sQuery));
|
||||
|
||||
return array('lat' => $fQueryLat, 'lon' => $fQueryLon, 'query' => $sQuery);
|
||||
}
|
||||
|
||||
|
||||
function geometryText2Points($geometry_as_text, $fRadius)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user