mirror of
https://github.com/osm-search/Nominatim.git
synced 2026-02-16 15:47:58 +00:00
Merge pull request #605 from lonvia/fix-fraction-on-interpolations
Better search radius for interpolations when reverse geocoding
This commit is contained in:
@@ -42,6 +42,29 @@ class ReverseGeocode
|
|||||||
$this->iMaxRank = (isset($iZoom) && isset($aZoomRank[$iZoom]))?$aZoomRank[$iZoom]:28;
|
$this->iMaxRank = (isset($iZoom) && isset($aZoomRank[$iZoom]))?$aZoomRank[$iZoom]:28;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the closest interpolation with the given search diameter.
|
||||||
|
*
|
||||||
|
* @param string $sPointSQL Reverse geocoding point as SQL
|
||||||
|
* @param float $fSearchDiam Search diameter
|
||||||
|
*
|
||||||
|
* @return Record of the interpolation or null.
|
||||||
|
*/
|
||||||
|
protected function lookupInterpolation($sPointSQL, $fSearchDiam)
|
||||||
|
{
|
||||||
|
$sSQL = 'SELECT place_id, parent_place_id, 30 as rank_search,';
|
||||||
|
$sSQL .= ' ST_LineLocatePoint(linegeo,'.$sPointSQL.') as fraction';
|
||||||
|
$sSQL .= ' , ST_Distance(linegeo,'.$sPointSQL.') as distance';
|
||||||
|
$sSQL .= ' FROM location_property_osmline';
|
||||||
|
$sSQL .= ' WHERE ST_DWithin('.$sPointSQL.', linegeo, '.$fSearchDiam.')';
|
||||||
|
$sSQL .= ' and indexed_status = 0 ';
|
||||||
|
$sSQL .= ' ORDER BY ST_distance('.$sPointSQL.', linegeo) ASC limit 1';
|
||||||
|
|
||||||
|
return chksql(
|
||||||
|
$this->oDB->getRow($sSQL),
|
||||||
|
"Could not determine closest housenumber on an osm interpolation line."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/* lookup()
|
/* lookup()
|
||||||
* returns { place_id =>, type => '(osm|tiger)' }
|
* returns { place_id =>, type => '(osm|tiger)' }
|
||||||
@@ -57,7 +80,6 @@ class ReverseGeocode
|
|||||||
// Find the nearest point
|
// Find the nearest point
|
||||||
$fSearchDiam = 0.0004;
|
$fSearchDiam = 0.0004;
|
||||||
$iPlaceID = null;
|
$iPlaceID = null;
|
||||||
$aArea = false;
|
|
||||||
$fMaxAreaDistance = 1;
|
$fMaxAreaDistance = 1;
|
||||||
$bIsInUnitedStates = false;
|
$bIsInUnitedStates = false;
|
||||||
$bPlaceIsTiger = false;
|
$bPlaceIsTiger = false;
|
||||||
@@ -74,7 +96,27 @@ class ReverseGeocode
|
|||||||
if ($fSearchDiam > 0.2 && $iMaxRank > 17) $iMaxRank = 17;
|
if ($fSearchDiam > 0.2 && $iMaxRank > 17) $iMaxRank = 17;
|
||||||
if ($fSearchDiam > 0.1 && $iMaxRank > 18) $iMaxRank = 18;
|
if ($fSearchDiam > 0.1 && $iMaxRank > 18) $iMaxRank = 18;
|
||||||
if ($fSearchDiam > 0.008 && $iMaxRank > 22) $iMaxRank = 22;
|
if ($fSearchDiam > 0.008 && $iMaxRank > 22) $iMaxRank = 22;
|
||||||
if ($fSearchDiam > 0.001 && $iMaxRank > 26) $iMaxRank = 26;
|
if ($fSearchDiam > 0.001 && $iMaxRank > 26) {
|
||||||
|
// try with interpolations before continuing
|
||||||
|
if ($bDoInterpolation) {
|
||||||
|
// no house found, try with interpolations
|
||||||
|
$aPlaceLine = $this->lookupInterpolation($sPointSQL, $fSearchDiam/2);
|
||||||
|
|
||||||
|
if ($aPlaceLine) {
|
||||||
|
// interpolation is closer to point than placex house
|
||||||
|
$bPlaceIsLine = true;
|
||||||
|
$aPlace = $aPlaceLine;
|
||||||
|
$iPlaceID = $aPlaceLine['place_id'];
|
||||||
|
$iParentPlaceID = $aPlaceLine['parent_place_id']; // the street
|
||||||
|
$fFraction = $aPlaceLine['fraction'];
|
||||||
|
$iMaxRank = 30;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// no interpolation found, continue search
|
||||||
|
$iMaxRank = 26;
|
||||||
|
}
|
||||||
|
|
||||||
$sSQL = 'select place_id,parent_place_id,rank_search,calculated_country_code';
|
$sSQL = 'select place_id,parent_place_id,rank_search,calculated_country_code';
|
||||||
$sSQL .= ' FROM placex';
|
$sSQL .= ' FROM placex';
|
||||||
@@ -95,69 +137,32 @@ class ReverseGeocode
|
|||||||
$iParentPlaceID = $aPlace['parent_place_id'];
|
$iParentPlaceID = $aPlace['parent_place_id'];
|
||||||
$bIsInUnitedStates = ($aPlace['calculated_country_code'] == 'us');
|
$bIsInUnitedStates = ($aPlace['calculated_country_code'] == 'us');
|
||||||
}
|
}
|
||||||
// if a street or house was found, look in interpolation lines table
|
|
||||||
if ($bDoInterpolation && $this->iMaxRank >= 28 && $aPlace && $aPlace['rank_search'] >= 26) {
|
|
||||||
// if a house was found, search the interpolation line that is at least as close as the house
|
|
||||||
$sSQL = 'SELECT place_id, parent_place_id, 30 as rank_search, ST_LineLocatePoint(linegeo,'.$sPointSQL.') as fraction';
|
|
||||||
$sSQL .= ' FROM location_property_osmline';
|
|
||||||
$sSQL .= ' WHERE ST_DWithin('.$sPointSQL.', linegeo, '.$fSearchDiam.')';
|
|
||||||
$sSQL .= ' and indexed_status = 0 ';
|
|
||||||
$sSQL .= ' ORDER BY ST_distance('.$sPointSQL.', linegeo) ASC limit 1';
|
|
||||||
|
|
||||||
if (CONST_Debug) {
|
|
||||||
$sSQL = preg_replace('/limit 1/', 'limit 100', $sSQL);
|
|
||||||
var_dump($sSQL);
|
|
||||||
|
|
||||||
$aAllHouses = chksql($this->oDB->getAll($sSQL));
|
// If a house was found make sure there isn't an interpolation line
|
||||||
foreach ($aAllHouses as $i) {
|
// that is closer
|
||||||
echo $i['housenumber'] . ' | ' . $i['distance'] * 1000 . ' | ' . $i['lat'] . ' | ' . $i['lon']. ' | '. "<br>\n";
|
if ($bDoInterpolation && !$bPlaceIsLine && $aPlace && $aPlace['rank_search'] == 30) {
|
||||||
}
|
// get the distance of the house to the search point
|
||||||
}
|
$sSQL = 'SELECT ST_distance('.$sPointSQL.', house.geometry)';
|
||||||
$aPlaceLine = chksql(
|
$sSQL .= ' FROM placex as house WHERE house.place_id='.$iPlaceID;
|
||||||
$this->oDB->getRow($sSQL),
|
|
||||||
"Could not determine closest housenumber on an osm interpolation line."
|
$fDistancePlacex = chksql(
|
||||||
|
$this->oDB->getOne($sSQL),
|
||||||
|
"Could not determine distance between searched point and placex house."
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// look for an interpolation that is closer
|
||||||
|
$aPlaceLine = $this->lookupInterpolation($sPointSQL, $fDistancePlacex);
|
||||||
|
|
||||||
if ($aPlaceLine) {
|
if ($aPlaceLine) {
|
||||||
if (CONST_Debug) var_dump('found housenumber in interpolation lines table', $aPlaceLine);
|
// interpolation is closer to point than placex house
|
||||||
if ($aPlace['rank_search'] == 30) {
|
$bPlaceIsLine = true;
|
||||||
// if a house was already found in placex, we have to find out,
|
$aPlace = $aPlaceLine;
|
||||||
// if the placex house or the interpolated house are closer to the searched point
|
$iPlaceID = $aPlaceLine['place_id'];
|
||||||
// distance between point and placex house
|
$iParentPlaceID = $aPlaceLine['parent_place_id']; // the street
|
||||||
$sSQL = 'SELECT ST_distance('.$sPointSQL.', house.geometry) as distance FROM placex as house WHERE house.place_id='.$iPlaceID;
|
$fFraction = $aPlaceLine['fraction'];
|
||||||
$aDistancePlacex = chksql(
|
|
||||||
$this->oDB->getRow($sSQL),
|
|
||||||
"Could not determine distance between searched point and placex house."
|
|
||||||
);
|
|
||||||
$fDistancePlacex = $aDistancePlacex['distance'];
|
|
||||||
// distance between point and interpolated house (fraction on interpolation line)
|
|
||||||
$sSQL = 'SELECT ST_distance('.$sPointSQL.', ST_LineInterpolatePoint(linegeo, '.$aPlaceLine['fraction'].')) as distance';
|
|
||||||
$sSQL .= ' FROM location_property_osmline WHERE place_id = '.$aPlaceLine['place_id'];
|
|
||||||
$aDistanceInterpolation = chksql(
|
|
||||||
$this->oDB->getRow($sSQL),
|
|
||||||
"Could not determine distance between searched point and interpolated house."
|
|
||||||
);
|
|
||||||
$fDistanceInterpolation = $aDistanceInterpolation['distance'];
|
|
||||||
if ($fDistanceInterpolation < $fDistancePlacex) {
|
|
||||||
// interpolation is closer to point than placex house
|
|
||||||
$bPlaceIsLine = true;
|
|
||||||
$aPlace = $aPlaceLine;
|
|
||||||
$iPlaceID = $aPlaceLine['place_id'];
|
|
||||||
$iParentPlaceID = $aPlaceLine['parent_place_id']; // the street
|
|
||||||
$fFraction = $aPlaceLine['fraction'];
|
|
||||||
$iMaxRank = 30;
|
|
||||||
}
|
|
||||||
// else: nothing to do, take placex house from above
|
|
||||||
} else {
|
|
||||||
$bPlaceIsLine = true;
|
|
||||||
$aPlace = $aPlaceLine;
|
|
||||||
$iPlaceID = $aPlaceLine['place_id'];
|
|
||||||
$iParentPlaceID = $aPlaceLine['parent_place_id']; // the street
|
|
||||||
$fFraction = $aPlaceLine['fraction'];
|
|
||||||
$iMaxRank = 30;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only street found? If it's in the US we can check TIGER data for nearest housenumber
|
// Only street found? If it's in the US we can check TIGER data for nearest housenumber
|
||||||
if (CONST_Use_US_Tiger_Data && $bDoInterpolation && $bIsInUnitedStates && $this->iMaxRank >= 28 && $iPlaceID && ($aPlace['rank_search'] == 26 || $aPlace['rank_search'] == 27 )) {
|
if (CONST_Use_US_Tiger_Data && $bDoInterpolation && $bIsInUnitedStates && $this->iMaxRank >= 28 && $iPlaceID && ($aPlace['rank_search'] == 26 || $aPlace['rank_search'] == 27 )) {
|
||||||
$fSearchDiam = 0.001;
|
$fSearchDiam = 0.001;
|
||||||
|
|||||||
@@ -68,18 +68,18 @@ Feature: Search queries
|
|||||||
Scenario: Search with bounded viewbox in right area
|
Scenario: Search with bounded viewbox in right area
|
||||||
When sending json search query "restaurant" with address
|
When sending json search query "restaurant" with address
|
||||||
| bounded | viewbox |
|
| bounded | viewbox |
|
||||||
| 1 | 9.93027,53.61634,10.10073,53.54500 |
|
| 1 | -56.16786,-34.84061,-56.12525,-34.86526 |
|
||||||
Then result addresses contain
|
Then result addresses contain
|
||||||
| state |
|
| city |
|
||||||
| Hamburg |
|
| Montevideo |
|
||||||
|
|
||||||
Scenario: Search with bounded viewboxlbrt in right area
|
Scenario: Search with bounded viewboxlbrt in right area
|
||||||
When sending json search query "restaurant" with address
|
When sending json search query "restaurant" with address
|
||||||
| bounded | viewboxlbrt |
|
| bounded | viewboxlbrt |
|
||||||
| 1 | 9.93027,53.54500,10.10073,53.61634 |
|
| 1 | -56.16786,-34.86526,-56.12525,-34.84061 |
|
||||||
Then result addresses contain
|
Then result addresses contain
|
||||||
| state |
|
| city |
|
||||||
| Hamburg |
|
| Montevideo |
|
||||||
|
|
||||||
Scenario: No POI search with unbounded viewbox
|
Scenario: No POI search with unbounded viewbox
|
||||||
When sending json search query "restaurant"
|
When sending json search query "restaurant"
|
||||||
|
|||||||
Reference in New Issue
Block a user