+
+ 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']);
+ }
+ }
+
+ // still nothing, then return the country object
+ $sSQL = 'SELECT place_id, ST_distance('.$sPointSQL.', centroid) as distance';
+ $sSQL .= ' FROM placex';
+ $sSQL .= ' WHERE country_code = \''.$sCountryCode.'\'';
+ $sSQL .= ' AND rank_search = 4 AND rank_address = 4';
+ $sSQL .= ' AND class in (\'boundary\', \'place\')';
+ $sSQL .= ' ORDER BY distance ASC';
+
+ 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']);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Search for areas or nodes for areas or nodes between state and suburb level.
+ *
+ * @param string $sPointSQL Search point as SQL string.
+ * @param int $iMaxRank Maximum address rank of the feature.
+ *
+ * @return Record of the found feature or null.
+ *
+ * Searches first for polygon that contains the search point.
+ * If such a polygon is found, place nodes with a higher rank are
+ * searched inside the polygon.
+ */
+ protected function lookupPolygon($sPointSQL, $iMaxRank)
+ {
+ // polygon search begins at suburb-level
+ if ($iMaxRank > 25) $iMaxRank = 25;
+ // no polygon search over country-level
+ if ($iMaxRank < 5) $iMaxRank = 5;
+ // search for polygon
+ $sSQL = 'SELECT place_id, parent_place_id, rank_address, rank_search FROM';
+ $sSQL .= '(select place_id, parent_place_id, rank_address, rank_search, country_code, geometry';