+ /**
+ * 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 .= ' startnumber, endnumber, interpolationtype,';
+ $sSQL .= ' ST_Distance(linegeo,'.$sPointSQL.') as distance';
+ $sSQL .= ' FROM location_property_osmline';
+ $sSQL .= ' WHERE ST_DWithin('.$sPointSQL.', linegeo, '.$fSearchDiam.')';
+ $sSQL .= ' and indexed_status = 0 and startnumber is not NULL ';
+ $sSQL .= ' ORDER BY distance ASC limit 1';
+
+ return chksql(
+ $this->oDB->getRow($sSQL),
+ 'Could not determine closest housenumber on an osm interpolation line.'
+ );
+ }
+
+ protected function lookupLargeArea($sPointSQL, $iMaxRank)
+ {
+ $oResult = null;
+
+ if ($iMaxRank > 4) {
+ $aPlace = $this->lookupPolygon($sPointSQL, $iMaxRank);
+ if ($aPlace) {
+ return new Result($aPlace['place_id']);
+ }
+ }
+
+ // If no polygon which contains the searchpoint is found,
+ // searches in the country_osm_grid table for a polygon.
+ return $this->lookupInCountry($sPointSQL, $iMaxRank);
+ }
+
+ protected function lookupInCountry($sPointSQL, $iMaxRank)
+ {
+ // searches for polygon in table country_osm_grid which contains the searchpoint
+ // and searches for the nearest place node to the searchpoint in this polygon
+ $sSQL = 'SELECT country_code FROM country_osm_grid';
+ $sSQL .= ' WHERE ST_CONTAINS(geometry, '.$sPointSQL.') LIMIT 1';
+
+ $sCountryCode = chksql(
+ $this->oDB->getOne($sSQL),
+ 'Could not determine country polygon containing the point.'
+ );
+ if ($sCountryCode) {
+ if ($iMaxRank > 4) {
+ // look for place nodes with the given country code
+ $sSQL = 'SELECT place_id FROM';
+ $sSQL .= ' (SELECT place_id, rank_search,';
+ $sSQL .= ' ST_distance('.$sPointSQL.', geometry) as distance';
+ $sSQL .= ' FROM placex';
+ $sSQL .= ' WHERE osm_type = \'N\'';
+ $sSQL .= ' AND country_code = \''.$sCountryCode.'\'';
+ $sSQL .= ' AND rank_search between 5 and ' .min(25, $iMaxRank);
+ $sSQL .= ' AND class = \'place\' AND type != \'postcode\'';
+ $sSQL .= ' AND name IS NOT NULL ';
+ $sSQL .= ' and indexed_status = 0 and linked_place_id is null';
+ $sSQL .= ' AND ST_DWithin('.$sPointSQL.', geometry, 1.8)) p ';
+ $sSQL .= 'WHERE distance <= reverse_place_diameter(rank_search)';
+ $sSQL .= ' ORDER BY rank_search DESC, distance ASC';
+ $sSQL .= ' LIMIT 1';
+
+ if (CONST_Debug) var_dump($sSQL);
+ $aPlace = chksql(
+ $this->oDB->getRow($sSQL),
+ 'Could not determine place node.'
+ );
+ if ($aPlace) {
+ return new Result($aPlace['place_id']);
+ }
+ }