forked from hans/Nominatim
handle pure lat,lon search by passing to reverse geocoding and returning first match as a search result
This commit is contained in:
99
lib/lib.php
99
lib/lib.php
@@ -816,3 +816,102 @@
|
||||
$aSimilar = $oDB->getAll($sSQL);
|
||||
return $aSimilar;
|
||||
}
|
||||
|
||||
function geocodeReverse($fLat, $fLon, $iZoom=18)
|
||||
{
|
||||
$oDB =& getDB();
|
||||
|
||||
$sPointSQL = "ST_SetSRID(ST_Point($fLon,$fLat),4326)";
|
||||
|
||||
// Zoom to rank, this could probably be calculated but a lookup gives fine control
|
||||
$aZoomRank = array(
|
||||
0 => 2, // Continent / Sea
|
||||
1 => 2,
|
||||
2 => 2,
|
||||
3 => 4, // Country
|
||||
4 => 4,
|
||||
5 => 8, // State
|
||||
6 => 10, // Region
|
||||
7 => 10,
|
||||
8 => 12, // County
|
||||
9 => 12,
|
||||
10 => 17, // City
|
||||
11 => 17,
|
||||
12 => 18, // Town / Village
|
||||
13 => 18,
|
||||
14 => 22, // Suburb
|
||||
15 => 22,
|
||||
16 => 26, // Street, TODO: major street?
|
||||
17 => 26,
|
||||
18 => 30, // or >, Building
|
||||
19 => 30, // or >, Building
|
||||
);
|
||||
$iMaxRank = isset($aZoomRank[$iZoom])?$aZoomRank[$iZoom]:28;
|
||||
|
||||
// Find the nearest point
|
||||
$fSearchDiam = 0.0001;
|
||||
$iPlaceID = null;
|
||||
$aArea = false;
|
||||
$fMaxAreaDistance = 1;
|
||||
while(!$iPlaceID && $fSearchDiam < $fMaxAreaDistance)
|
||||
{
|
||||
$fSearchDiam = $fSearchDiam * 2;
|
||||
|
||||
// If we have to expand the search area by a large amount then we need a larger feature
|
||||
// then there is a limit to how small the feature should be
|
||||
if ($fSearchDiam > 2 && $iMaxRank > 4) $iMaxRank = 4;
|
||||
if ($fSearchDiam > 1 && $iMaxRank > 9) $iMaxRank = 8;
|
||||
if ($fSearchDiam > 0.8 && $iMaxRank > 10) $iMaxRank = 10;
|
||||
if ($fSearchDiam > 0.6 && $iMaxRank > 12) $iMaxRank = 12;
|
||||
if ($fSearchDiam > 0.2 && $iMaxRank > 17) $iMaxRank = 17;
|
||||
if ($fSearchDiam > 0.1 && $iMaxRank > 18) $iMaxRank = 18;
|
||||
if ($fSearchDiam > 0.008 && $iMaxRank > 22) $iMaxRank = 22;
|
||||
if ($fSearchDiam > 0.001 && $iMaxRank > 26) $iMaxRank = 26;
|
||||
|
||||
$sSQL = 'select place_id,parent_place_id 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)';
|
||||
$sSQL .= ' and class not in (\'waterway\')';
|
||||
$sSQL .= ' and (ST_GeometryType(geometry) not in (\'ST_Polygon\',\'ST_MultiPolygon\') ';
|
||||
$sSQL .= ' OR ST_DWithin('.$sPointSQL.', ST_Centroid(geometry), '.$fSearchDiam.'))';
|
||||
$sSQL .= ' ORDER BY ST_distance('.$sPointSQL.', geometry) ASC limit 1';
|
||||
//var_dump($sSQL);
|
||||
$aPlace = $oDB->getRow($sSQL);
|
||||
$iPlaceID = $aPlace['place_id'];
|
||||
if (PEAR::IsError($iPlaceID))
|
||||
{
|
||||
var_Dump($sSQL, $iPlaceID);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// The point we found might be too small - use the address to find what it is a child of
|
||||
if ($iPlaceID)
|
||||
{
|
||||
$sSQL = "select address_place_id from place_addressline where cached_rank_address <= $iMaxRank and place_id = $iPlaceID order by cached_rank_address desc,isaddress desc,distance desc limit 1";
|
||||
$iPlaceID = $oDB->getOne($sSQL);
|
||||
if (PEAR::IsError($iPlaceID))
|
||||
{
|
||||
var_Dump($sSQL, $iPlaceID);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($iPlaceID && $aPlace['place_id'] && $iMaxRank < 28)
|
||||
{
|
||||
$sSQL = "select address_place_id from place_addressline where cached_rank_address <= $iMaxRank and place_id = ".$aPlace['place_id']." order by cached_rank_address desc,isaddress desc,distance desc";
|
||||
$iPlaceID = $oDB->getOne($sSQL);
|
||||
if (PEAR::IsError($iPlaceID))
|
||||
{
|
||||
var_Dump($sSQL, $iPlaceID);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
if (!$iPlaceID)
|
||||
{
|
||||
$iPlaceID = $aPlace['place_id'];
|
||||
}
|
||||
}
|
||||
|
||||
return $iPlaceID;
|
||||
}
|
||||
|
||||
@@ -183,7 +183,7 @@
|
||||
$_GET['nearlon'] = ($aData[6]=='E'?1:-1) * ($aData[4] + $aData[5]/60);
|
||||
$sQuery = trim(str_replace($aData[0], ' ', $sQuery));
|
||||
}
|
||||
elseif (preg_match('/(\\[|\\b)(-?[0-9]+[0-9.]*)[, ]+(-?[0-9]+[0-9.]*)(\\]|\\b])/', $sQuery, $aData))
|
||||
elseif (preg_match('/(\\[|\\b)(-?[0-9]+[0-9.]*)[, ]+(-?[0-9]+[0-9.]*)(\\]|\\b)/', $sQuery, $aData))
|
||||
{
|
||||
$_GET['nearlat'] = $aData[2];
|
||||
$_GET['nearlon'] = $aData[3];
|
||||
@@ -192,7 +192,6 @@
|
||||
|
||||
if ($sQuery)
|
||||
{
|
||||
|
||||
// Start with a blank search
|
||||
$aSearches = array(
|
||||
array('iSearchRank' => 0, 'iNamePhrase' => -1, 'sCountryCode' => false, 'aName'=>array(), 'aAddress'=>array(),
|
||||
@@ -983,6 +982,75 @@
|
||||
$aSearchResults = $oDB->getAll($sSQL);
|
||||
//var_dump($sSQL,$aSearchResults);exit;
|
||||
|
||||
if (PEAR::IsError($aSearchResults))
|
||||
{
|
||||
var_dump($sSQL, $aSearchResults);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
} // end if ($sQuery)
|
||||
else
|
||||
{
|
||||
if (isset($_GET['nearlat']) && trim($_GET['nearlat'])!=='' && isset($_GET['nearlon']) && trim($_GET['nearlon']) !== '')
|
||||
{
|
||||
$iPlaceID = geocodeReverse($_GET['nearlat'], $_GET['nearlon']);
|
||||
$aResultPlaceIDs = array($iPlaceID);
|
||||
|
||||
// TODO: this needs refactoring!
|
||||
|
||||
// Get the details for display (is this a redundant extra step?)
|
||||
$sPlaceIDs = join(',',$aResultPlaceIDs);
|
||||
$sOrderSQL = 'CASE ';
|
||||
foreach(array_keys($aResultPlaceIDs) as $iOrder => $iPlaceID)
|
||||
{
|
||||
$sOrderSQL .= 'when min(place_id) = '.$iPlaceID.' then '.$iOrder.' ';
|
||||
}
|
||||
$sOrderSQL .= ' ELSE 10000000 END';
|
||||
$sSQL = "select osm_type,osm_id,class,type,admin_level,rank_search,rank_address,min(place_id) as place_id,country_code,";
|
||||
$sSQL .= "get_address_by_language(place_id, $sLanguagePrefArraySQL) as langaddress,";
|
||||
$sSQL .= "get_name_by_language(name, $sLanguagePrefArraySQL) as placename,";
|
||||
$sSQL .= "get_name_by_language(name, ARRAY['ref']) as ref,";
|
||||
$sSQL .= "avg(ST_X(ST_Centroid(geometry))) as lon,avg(ST_Y(ST_Centroid(geometry))) as lat, ";
|
||||
// $sSQL .= $sOrderSQL." as porder, ";
|
||||
$sSQL .= "coalesce(importance,0.9-(rank_search::float/30)) as importance ";
|
||||
$sSQL .= "from placex where place_id in ($sPlaceIDs) ";
|
||||
$sSQL .= "and placex.rank_address between $iMinAddressRank and $iMaxAddressRank ";
|
||||
$sSQL .= "group by osm_type,osm_id,class,type,admin_level,rank_search,rank_address,country_code,importance";
|
||||
if (!$bDeDupe) $sSQL .= ",place_id";
|
||||
$sSQL .= ",get_address_by_language(place_id, $sLanguagePrefArraySQL) ";
|
||||
$sSQL .= ",get_name_by_language(name, $sLanguagePrefArraySQL) ";
|
||||
$sSQL .= ",get_name_by_language(name, ARRAY['ref']) ";
|
||||
$sSQL .= " union ";
|
||||
$sSQL .= "select 'T' as osm_type,place_id as osm_id,'place' as class,'house' as type,null as admin_level,30 as rank_search,30 as rank_address,min(place_id) as place_id,'us' as country_code,";
|
||||
$sSQL .= "get_address_by_language(place_id, $sLanguagePrefArraySQL) as langaddress,";
|
||||
$sSQL .= "null as placename,";
|
||||
$sSQL .= "null as ref,";
|
||||
$sSQL .= "avg(ST_X(centroid)) as lon,avg(ST_Y(centroid)) as lat, ";
|
||||
// $sSQL .= $sOrderSQL." as porder, ";
|
||||
$sSQL .= "-0.15 as importance ";
|
||||
$sSQL .= "from location_property_tiger where place_id in ($sPlaceIDs) ";
|
||||
$sSQL .= "and 30 between $iMinAddressRank and $iMaxAddressRank ";
|
||||
$sSQL .= "group by place_id";
|
||||
if (!$bDeDupe) $sSQL .= ",place_id";
|
||||
$sSQL .= " union ";
|
||||
$sSQL .= "select 'L' as osm_type,place_id as osm_id,'place' as class,'house' as type,null as admin_level,30 as rank_search,30 as rank_address,min(place_id) as place_id,'us' as country_code,";
|
||||
$sSQL .= "get_address_by_language(place_id, $sLanguagePrefArraySQL) as langaddress,";
|
||||
$sSQL .= "null as placename,";
|
||||
$sSQL .= "null as ref,";
|
||||
$sSQL .= "avg(ST_X(centroid)) as lon,avg(ST_Y(centroid)) as lat, ";
|
||||
// $sSQL .= $sOrderSQL." as porder, ";
|
||||
$sSQL .= "-0.10 as importance ";
|
||||
$sSQL .= "from location_property_aux where place_id in ($sPlaceIDs) ";
|
||||
$sSQL .= "and 30 between $iMinAddressRank and $iMaxAddressRank ";
|
||||
$sSQL .= "group by place_id";
|
||||
if (!$bDeDupe) $sSQL .= ",place_id";
|
||||
$sSQL .= ",get_address_by_language(place_id, $sLanguagePrefArraySQL) ";
|
||||
$sSQL .= "order by importance desc";
|
||||
// $sSQL .= "order by rank_search,rank_address,porder asc";
|
||||
if (CONST_Debug) var_dump('<hr>',$sSQL);
|
||||
$aSearchResults = $oDB->getAll($sSQL);
|
||||
//var_dump($sSQL,$aSearchResults);exit;
|
||||
|
||||
if (PEAR::IsError($aSearchResults))
|
||||
{
|
||||
var_dump($sSQL, $aSearchResults);
|
||||
@@ -995,6 +1063,8 @@
|
||||
$sSearchResult = '';
|
||||
if (!sizeof($aSearchResults) && isset($_GET['q']) && $_GET['q'])
|
||||
{
|
||||
echo "here";
|
||||
exit;
|
||||
$sSearchResult = 'No Results Found';
|
||||
}
|
||||
//var_Dump($aSearchResults);
|
||||
|
||||
Reference in New Issue
Block a user