Compare commits

..

89 Commits

Author SHA1 Message Date
Sarah Hoffmann
07cbf1535b set software version defaults to something more recent 2015-04-19 23:49:40 +02:00
Sarah Hoffmann
5eb56c11ba prepare next release 2015-04-18 22:48:46 +02:00
Sarah Hoffmann
b82c8ceab9 ignore places without housenumber in interpolations
fixes trac ticket 5311
2015-04-18 17:47:49 +02:00
Brian Quinion
a5a0e1dd0b Various places where conversion from to ->aStructuredQuery had been missed 2015-04-07 14:04:08 +01:00
Sarah Hoffmann
ddcb95ca39 fix boundary test 2015-03-31 23:07:52 +02:00
Sarah Hoffmann
4a3dc3187c clean out dead sql code 2015-03-30 23:43:27 +02:00
Sarah Hoffmann
133dd2e974 make sure place exists before printing hierarchy 2015-03-29 19:03:51 +02:00
Sarah Hoffmann
eb1d8894b9 correctly handle comma-only exclude_place_ids 2015-03-29 18:17:52 +02:00
Sarah Hoffmann
59be7846e9 fix utf8 in tests for jsonp 2015-03-29 18:17:28 +02:00
Sarah Hoffmann
aaabf70a1c correctly quote regular expression 2015-03-29 17:23:06 +02:00
Sarah Hoffmann
987b6a70c9 use unescaped unicode in json where supported by PHP 2015-03-29 13:02:21 +02:00
Sarah Hoffmann
2bcd1aa194 avoid calling add_location for non-addressing features 2015-03-25 22:25:03 +01:00
Sarah Hoffmann
86b4df1e81 only address features can be linked with placex 2015-03-23 22:04:43 +01:00
Sarah Hoffmann
753227ae25 more strict parameter checking for reverse 2015-03-17 21:06:58 +01:00
Sarah Hoffmann
ef48ee5f80 update osm2pgsql (coastline typo) 2015-03-09 21:45:01 +01:00
Sarah Hoffmann
0930f6e728 state setup: get latest node from place, planet_osm_nodes may be empty 2015-03-09 21:33:02 +01:00
Sarah Hoffmann
6f98fa0fb3 interpolations: snap lines to points, not vice versa
Avoids the occasional rounding problem which might occur when splitting
a line anywhere but on a support point, see postgis doc for ST_Split.

Fixes #253
2015-03-08 18:25:51 +01:00
Sarah Hoffmann
555362eabe simplify bounding box computation
Makes highlighting of points reappear.
2015-03-06 20:58:09 +01:00
Sarah Hoffmann
9f4c7f4e6d update osm2pgsql (get rid of way-node index) 2015-03-05 23:09:00 +01:00
Sarah Hoffmann
1eb52879c6 replace final reference to way-node index with spatial lookup 2015-03-05 22:00:27 +01:00
Sarah Hoffmann
27ce2afbcf reorder parenting search for POI level
Push back the more expensive node-on-way parenting which is rather
rare anyways. Prefer assodicatedStreet relations and addr:* tags
instead.
2015-03-05 22:00:27 +01:00
Sarah Hoffmann
9d9745b378 add more tests for interpolations (mostly updating) 2015-03-05 22:00:27 +01:00
Sarah Hoffmann
30f087b168 switch interpolation node to using the interpolation osm id 2015-03-05 22:00:27 +01:00
Sarah Hoffmann
1ce3307b7a fix typos and make interpolation tests run 2015-03-05 22:00:26 +01:00
Sarah Hoffmann
a25810d317 write interpolated house numbers complete out and avoid reindexing 2015-03-05 22:00:26 +01:00
Sarah Hoffmann
394a00f521 computation of parent of interpolations 2015-03-05 22:00:26 +01:00
Sarah Hoffmann
9e3e7bf791 switch remaining GRANTs to configurable web user
fixes #252
2015-03-05 21:55:20 +01:00
Sarah Hoffmann
6dcdf34fda Merge pull request #250 from mtmail/patch-1
Update README.md
2015-03-03 19:55:33 +01:00
mtmail
f4d7337266 Update README.md
Added missing `shapely` library and instructions how to install `pip` on Ubuntu
2015-03-02 23:57:41 +01:00
Sarah Hoffmann
7ed580f1d5 enable NameOnlySearch per default 2015-02-27 19:55:31 +01:00
Sarah Hoffmann
c6d8e91b88 add script for recomputing word frequencies 2015-02-27 19:53:11 +01:00
Sarah Hoffmann
340b9793d6 update scene builder to compile with latest libosmium 2015-02-21 16:35:54 +01:00
Sarah Hoffmann
82e5a95f16 also drop interpolation index 2015-02-21 14:17:34 +01:00
Sarah Hoffmann
822ca14480 add makefile for test scene extractor 2015-02-21 14:11:05 +01:00
Sarah Hoffmann
b41a5c962c drop unnecessary index 2015-02-19 08:07:04 +01:00
Marc Tobias Metten
3c2c3ab674 check database results before using variable 2015-02-18 17:53:49 +01:00
Sarah Hoffmann
2b2b6ffadc drop special handling of short exact terms in address
There is a double check against exact terms, so that results with
a matching exact short term will float to the top.
2015-02-15 19:36:39 +01:00
Sarah Hoffmann
02cd91d251 update osm2pgsql (bug in relation update) 2015-02-11 22:31:30 +01:00
Sarah Hoffmann
5d87136969 reduce search area for secondary adresses when areas are involved 2015-02-09 19:35:15 +01:00
Sarah Hoffmann
0de6f37647 remove address lines with fully duplicated keywords
Mainly there to avoid having many duplicated postcode entries
in place_addressline from nodes which have tags where only
addr:postcode is recognized by Nominatim (e.g. fire hydrants).
2015-02-09 19:35:15 +01:00
Sarah Hoffmann
c9f3d7d08b disable housenumber-specific search when no address details are provided 2015-02-05 21:13:33 +01:00
Sarah Hoffmann
62ed8b9e0c add test for house number search 2015-02-04 20:39:20 +01:00
Sarah Hoffmann
cf5ced6618 order search results by existance of housenumbers
When searching for an address with housenumber, include the house
number lookup already when searching in search_name so that we do
not cut away relevant results in cases where there are too many
street pieces.
2015-02-04 20:31:30 +01:00
Sarah Hoffmann
0f84371748 actually write back the reversed final phrase when reversing the query 2015-02-04 20:29:38 +01:00
Sarah Hoffmann
43b925b258 slightly relax API tests 2015-02-03 23:17:51 +01:00
Sarah Hoffmann
b145dadd63 correctly quote display name in html search result 2015-02-03 23:12:21 +01:00
Sarah Hoffmann
7769b0a823 junctions should not appear as roads in addresses
fixes #228
2015-01-30 22:25:08 +01:00
Sarah Hoffmann
330f147b02 use _st_intersects when dealing with countries, it does not use index 2015-01-28 21:40:08 +01:00
Sarah Hoffmann
fbc5ba13f8 show class instead of yes in html search output 2015-01-27 22:22:26 +01:00
Sarah Hoffmann
c798577f70 remove hack for fixing adminitrative typo 2015-01-26 22:33:56 +01:00
Sarah Hoffmann
4c2fa68c55 details view: use class name if type is yes
fixes #209
2015-01-26 22:27:33 +01:00
Sarah Hoffmann
d1552b0904 don't use tokens from country parameter in address field of searches
fixes #218
2015-01-26 21:59:36 +01:00
Sarah Hoffmann
b121da0ca3 need phrase types in getGroupedSearches 2015-01-26 21:34:21 +01:00
Sarah Hoffmann
f6bfadaef6 Merge remote-tracking branch 'lonvia/inverse-query-II' 2015-01-23 16:46:50 +01:00
Sarah Hoffmann
b9355ac829 switch to enhanced osm2pgsql C++ version
This includes a major rewrite of the tag processing code. Much more
data is already rejected during osm2pgsql processing and names are
choosen more selectively depending on the class/type.
2015-01-23 08:13:11 +01:00
Sarah Hoffmann
f54ad3b86d adapt API tests to latest data 2015-01-22 00:06:44 +01:00
Sarah Hoffmann
e16fcf879d fully evaluate reverse order of queries
Factors out computation of search group and calls the code once
for forward evaluation and wants with reversed word order.
2015-01-21 21:40:38 +01:00
Sarah Hoffmann
021702f190 tablespace definition belongs before the where clause 2015-01-20 20:45:16 +01:00
Sarah Hoffmann
138b8a2ada remove unused functions 2015-01-16 21:36:35 +01:00
Sarah Hoffmann
352f0fdc27 finish osm2pgsql tag tests 2015-01-14 23:13:38 +01:00
Sarah Hoffmann
8c89b65082 more osm2pgsql tag tests 2015-01-13 22:16:00 +01:00
Sarah Hoffmann
f156da6b63 support tablespaces and www user config in tiger import 2015-01-11 13:44:39 +01:00
Sarah Hoffmann
759222eef2 tests for name import in osm2pgsql 2015-01-09 23:17:17 +01:00
Sarah Hoffmann
14d17a3ad4 properly close connection in test 2015-01-09 23:16:53 +01:00
Sarah Hoffmann
6d0ab44800 reuse template db for tests by default 2015-01-09 23:16:31 +01:00
Sarah Hoffmann
a855bfc6e5 be more restrictive with sql select when computing linked waterways 2014-12-30 22:55:24 +01:00
Sarah Hoffmann
3db64e7913 support tablespaces for special phrase table 2014-12-28 23:10:10 +01:00
Sarah Hoffmann
d6e7bbaad9 add underscore back to derelict canal
fixes #212 (again)
2014-12-20 14:55:08 +01:00
Sarah Hoffmann
1217083146 remove duplicate derelict canal
fixes #212
2014-12-20 00:02:26 +01:00
Sarah Hoffmann
635006b19b add hint about osm2pgsql submodule 2014-12-19 23:44:54 +01:00
Sarah Hoffmann
c391479c58 reorganise table creation
- remove unused tables
- make apache user configurable
- introduce configurable tablespaces
2014-12-02 00:05:21 +01:00
Sarah Hoffmann
04a20a2a0a remove debug output 2014-11-28 22:16:56 +01:00
Sarah Hoffmann
6382b1c111 more tolerant regexp for parsing replication state directories
Apache 2.4 has changed the date format, so that the current regexp
doesn't match anymore, so be more tolerant with the date format.
Also force less fancy output formatting without tables.
2014-11-27 22:23:04 +01:00
Sarah Hoffmann
59de7c5a9b fix address interpolation for self-intersecting ways 2014-11-03 22:42:34 +01:00
Sarah Hoffmann
4b8632d1e5 transliterate precomputed house numbers 2014-11-02 19:17:30 +01:00
Sarah Hoffmann
8f09b9378f only check for postgres major and minor version
fixes #192
2014-10-29 21:04:28 +01:00
Sarah Hoffmann
e1c88352ab use unique function name for test step 2014-10-29 20:37:56 +01:00
Marc Tobias Metten
084a110efb add regression test 2014-10-28 15:40:01 +01:00
Marc Tobias Metten
52265a33ba for PlaceLookup if we look for nodes then the centroid does not exist in the placex table 2014-10-28 14:27:40 +01:00
Sarah Hoffmann
475108b937 fix typo in osm test file generator 2014-10-20 00:02:29 +02:00
Sarah Hoffmann
02c219d40e PATH_INFO is delivered URL encoded on newer apache 2.4 2014-10-16 00:33:56 +02:00
Sarah Hoffmann
4cfeeb06ba adapt API tests to latest OSM data changes 2014-10-09 21:04:16 +02:00
Sarah Hoffmann
dd18e74079 remove all unidentified large areas from addresses 2014-10-08 23:33:46 +02:00
Sarah Hoffmann
e62ae5b090 respect bounded in country searches
fixes trac 5238
2014-10-08 23:31:33 +02:00
Sarah Hoffmann
8989776bfd remove most landuses from addresses 2014-10-08 20:47:32 +02:00
Sarah Hoffmann
d899b3b04c reintroduce index on gb_postcode 2014-10-08 20:43:19 +02:00
Sarah Hoffmann
2d6f00945a rewrite address interpolation so that planet_osm_node is not needed
This allows address interpolations to work correctly when flatnode storage
is used for node coordinates.

To fix interpolations in an existing database, follow these steps:

  * invalidate all interpolations (in psql):
    `UPDATE placex SET indexed_status=2 WHERE rank_search = 28`
  * disable updates:
    ./utils/setup.php --create-functions --create-partition-functions
  * reindex the whole lot:
    ./utils/update.php --index --index-instances <number of your cpus>
  * enable updates again:
    ./utils/setup.php --create-functions --enable-diff-updates --create-partition-functions
2014-10-05 22:16:02 +02:00
Sarah Hoffmann
6a22d71b3b officially drop support for postgres 8.4 2014-10-04 22:50:04 +02:00
Sarah Hoffmann
d794b74550 bump development version to 2.4 2014-10-04 22:20:40 +02:00
58 changed files with 3121 additions and 1737 deletions

1
.gitignore vendored
View File

@@ -16,6 +16,7 @@ autom4te.cache/
config.*
configure
Makefile
!tests/scenes/bin/Makefile
Makefile.in
stamp-h1
missing

View File

@@ -1,7 +1,45 @@
2.0.1
2.4
* delete outdated entries from location_area_country
* remove remaining uses of INTEGER, to allow node ids larger than 2^31
* drop support for postgres 8.4
* rewrite address interpolation
* switch to C++ version of osm2pgsql and rewrite tag filtering
* support for bridge:name and tunnel:name, man_made, junction
* drop way-node index (reduces database size by about 15%)
* add support for configuring tablespaces and webserver user
* better evaluation of search queries in right-to-left notation
* improve house number search for streets with many duplicate entries
* code cleanup (remove unused functions and tables)
2.3
* further improve ordering of results
* support for more lat/lon formats in search-as-reverse
* fix handling of GB postcodes
* new functional test suite
* support for waterway relations
* inherit postcodes from street to poi
* fix housenumber normalisation to find non-latin house numbers
* take viewbox into account for ordering of results
* pois may now inherit address tags from surrounding buildings
* improve what objects may participate in an address
* clean up handled class/type combinations to current OSM usage
* lots of bug fixes
2.2
* correct database rights for www-data
* add timestamps for update output
* load postgis via extension for postgis >= 2.0
* remove non-admin boundaries from addresses
* further improve ordering of results with same importance
* merge addr:postcode tags into object addresses
* include rank and importance in reverse geocode output
* replace ST_Line_Interpolate_Point with ST_LineInterpolatePoint
(for postgis >= 2.1)
* update osm2pgsql to latest version
* properly detect changes of admin_level
* remove landuses when name is removed
* smaller fixes
2.1
@@ -27,33 +65,7 @@
* refactoring of front-end PHP code
* lots of smaller bug fixes
2.2
2.0.1
* correct database rights for www-data
* add timestamps for update output
* load postgis via extension for postgis >= 2.0
* remove non-admin boundaries from addresses
* further improve ordering of results with same importance
* merge addr:postcode tags into object addresses
* include rank and importance in reverse geocode output
* replace ST_Line_Interpolate_Point with ST_LineInterpolatePoint
(for postgis >= 2.1)
* update osm2pgsql to latest version
* properly detect changes of admin_level
* remove landuses when name is removed
* smaller fixes
2.3
* further improve ordering of results
* support for more lat/lon formats in search-as-reverse
* fix handling of GB postcodes
* new functional test suite
* support for waterway relations
* inherit postcodes from street to poi
* fix housenumber normalisation to find non-latin house numbers
* take viewbox into account for ordering of results
* pois may now inherit address tags from surrounding buildings
* improve what objects may participate in an address
* clean up handled class/type combinations to current OSM usage
* lots of bug fixes
* delete outdated entries from location_area_country
* remove remaining uses of INTEGER, to allow node ids larger than 2^31

5
README
View File

@@ -24,6 +24,9 @@ how to set up your own instance of Nominatim can be found in the wiki:
http://wiki.openstreetmap.org/wiki/Nominatim/Installation
Note that this repository contains a submodule called osm2pgsql. Make sure it
is cloned as well by running `git submodule update --init`.
Installation steps:
0. If checking out from git run:
@@ -32,7 +35,7 @@ Installation steps:
1. Compile Nominatim:
./configure [--enable-64bit-ids]
./configure
make
2. Get OSM data and import:

View File

@@ -1,4 +1,4 @@
AC_INIT(Nominatim,2.2)
AC_INIT(Nominatim,2.4)
if git rev-parse HEAD 2>/dev/null >/dev/null; then
AC_SUBST([PACKAGE_VERSION], [$PACKAGE_VERSION-git-`git rev-parse --short HEAD`])
fi
@@ -40,7 +40,7 @@ fi
dnl Check for PostgresSQL client library
AX_LIB_POSTGRESQL(8.4)
AX_LIB_POSTGRESQL(9.0)
if test "x$POSTGRESQL_VERSION" = "x"
then
AC_MSG_ERROR([postgresql client library not found])

View File

@@ -295,7 +295,6 @@ CREATE INDEX idx_country_name_country_code ON country_name USING btree (country_
--
REVOKE ALL ON TABLE country_name FROM PUBLIC;
GRANT SELECT ON TABLE country_name TO "www-data";
--

View File

@@ -24,4 +24,3 @@ CREATE TABLE gb_postcode (
CONSTRAINT enforce_srid_geometry CHECK ((st_srid(geometry) = 4326))
);
GRANT SELECT ON TABLE gb_postcode TO "www-data";

View File

@@ -49637,7 +49637,7 @@ kein 100
select count(make_keywords(v)) from (select distinct svals(name) as v from place) as w where v is not null;
select count(make_keywords(v)) from (select distinct postcode as v from place) as w where v is not null;
select count(getorcreate_housenumber_id(v)) from (select distinct housenumber as v from place where housenumber is not null) as w;
select count(getorcreate_housenumber_id(make_standard_name(v))) from (select distinct housenumber as v from place where housenumber is not null) as w;
-- copy the word frequencies
update word set search_name_count = count from word_frequencies wf where wf.word_token = word.word_token;

View File

@@ -222,9 +222,12 @@
foreach(explode(',',$aParams['exclude_place_ids']) as $iExcludedPlaceID)
{
$iExcludedPlaceID = (int)$iExcludedPlaceID;
if ($iExcludedPlaceID) $aExcludePlaceIDs[$iExcludedPlaceID] = $iExcludedPlaceID;
if ($iExcludedPlaceID)
$aExcludePlaceIDs[$iExcludedPlaceID] = $iExcludedPlaceID;
}
$this->aExcludePlaceIDs = $aExcludePlaceIDs;
if (isset($aExcludePlaceIDs))
$this->aExcludePlaceIDs = $aExcludePlaceIDs;
}
// Only certain ranks of feature
@@ -441,6 +444,295 @@
return $aSearchResults;
}
function getGroupedSearches($aSearches, $aPhraseTypes, $aPhrases, $aValidTokens, $aWordFrequencyScores, $bStructuredPhrases)
{
/*
Calculate all searches using aValidTokens i.e.
'Wodsworth Road, Sheffield' =>
Phrase Wordset
0 0 (wodsworth road)
0 1 (wodsworth)(road)
1 0 (sheffield)
Score how good the search is so they can be ordered
*/
foreach($aPhrases as $iPhrase => $sPhrase)
{
$aNewPhraseSearches = array();
if ($bStructuredPhrases) $sPhraseType = $aPhraseTypes[$iPhrase];
else $sPhraseType = '';
foreach($aPhrases[$iPhrase]['wordsets'] as $iWordSet => $aWordset)
{
// Too many permutations - too expensive
if ($iWordSet > 120) break;
$aWordsetSearches = $aSearches;
// Add all words from this wordset
foreach($aWordset as $iToken => $sToken)
{
//echo "<br><b>$sToken</b>";
$aNewWordsetSearches = array();
foreach($aWordsetSearches as $aCurrentSearch)
{
//echo "<i>";
//var_dump($aCurrentSearch);
//echo "</i>";
// If the token is valid
if (isset($aValidTokens[' '.$sToken]))
{
foreach($aValidTokens[' '.$sToken] as $aSearchTerm)
{
$aSearch = $aCurrentSearch;
$aSearch['iSearchRank']++;
if (($sPhraseType == '' || $sPhraseType == 'country') && !empty($aSearchTerm['country_code']) && $aSearchTerm['country_code'] != '0')
{
if ($aSearch['sCountryCode'] === false)
{
$aSearch['sCountryCode'] = strtolower($aSearchTerm['country_code']);
// Country is almost always at the end of the string - increase score for finding it anywhere else (optimisation)
if (($iToken+1 != sizeof($aWordset) || $iPhrase+1 != sizeof($aPhrases)))
{
$aSearch['iSearchRank'] += 5;
}
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
elseif (isset($aSearchTerm['lat']) && $aSearchTerm['lat'] !== '' && $aSearchTerm['lat'] !== null)
{
if ($aSearch['fLat'] === '')
{
$aSearch['fLat'] = $aSearchTerm['lat'];
$aSearch['fLon'] = $aSearchTerm['lon'];
$aSearch['fRadius'] = $aSearchTerm['radius'];
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
elseif ($sPhraseType == 'postalcode')
{
// We need to try the case where the postal code is the primary element (i.e. no way to tell if it is (postalcode, city) OR (city, postalcode) so try both
if (isset($aSearchTerm['word_id']) && $aSearchTerm['word_id'])
{
// If we already have a name try putting the postcode first
if (sizeof($aSearch['aName']))
{
$aNewSearch = $aSearch;
$aNewSearch['aAddress'] = array_merge($aNewSearch['aAddress'], $aNewSearch['aName']);
$aNewSearch['aName'] = array();
$aNewSearch['aName'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aNewSearch;
}
if (sizeof($aSearch['aName']))
{
if ((!$bStructuredPhrases || $iPhrase > 0) && $sPhraseType != 'country' && (!isset($aValidTokens[$sToken]) || strpos($sToken, ' ') !== false))
{
$aSearch['aAddress'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
}
else
{
$aCurrentSearch['aFullNameAddress'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
$aSearch['iSearchRank'] += 1000; // skip;
}
}
else
{
$aSearch['aName'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
//$aSearch['iNamePhrase'] = $iPhrase;
}
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
elseif (($sPhraseType == '' || $sPhraseType == 'street') && $aSearchTerm['class'] == 'place' && $aSearchTerm['type'] == 'house')
{
if ($aSearch['sHouseNumber'] === '')
{
$aSearch['sHouseNumber'] = $sToken;
// sanity check: if the housenumber is not mainly made
// up of numbers, add a penalty
if (preg_match_all("/[^0-9]/", $sToken, $aMatches) > 2) $aSearch['iSearchRank']++;
// also housenumbers should appear in the first or second phrase
if ($iPhrase > 1) $aSearch['iSearchRank'] += 1;
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
/*
// Fall back to not searching for this item (better than nothing)
$aSearch = $aCurrentSearch;
$aSearch['iSearchRank'] += 1;
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
*/
}
}
elseif ($sPhraseType == '' && $aSearchTerm['class'] !== '' && $aSearchTerm['class'] !== null)
{
if ($aSearch['sClass'] === '')
{
$aSearch['sOperator'] = $aSearchTerm['operator'];
$aSearch['sClass'] = $aSearchTerm['class'];
$aSearch['sType'] = $aSearchTerm['type'];
if (sizeof($aSearch['aName'])) $aSearch['sOperator'] = 'name';
else $aSearch['sOperator'] = 'near'; // near = in for the moment
if (strlen($aSearchTerm['operator']) == 0) $aSearch['iSearchRank'] += 1;
// Do we have a shortcut id?
if ($aSearch['sOperator'] == 'name')
{
$sSQL = "select get_tagpair('".$aSearch['sClass']."', '".$aSearch['sType']."')";
if ($iAmenityID = $this->oDB->getOne($sSQL))
{
$aValidTokens[$aSearch['sClass'].':'.$aSearch['sType']] = array('word_id' => $iAmenityID);
$aSearch['aName'][$iAmenityID] = $iAmenityID;
$aSearch['sClass'] = '';
$aSearch['sType'] = '';
}
}
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
elseif (isset($aSearchTerm['word_id']) && $aSearchTerm['word_id'])
{
if (sizeof($aSearch['aName']))
{
if ((!$bStructuredPhrases || $iPhrase > 0) && $sPhraseType != 'country' && (!isset($aValidTokens[$sToken]) || strpos($sToken, ' ') !== false))
{
$aSearch['aAddress'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
}
else
{
$aCurrentSearch['aFullNameAddress'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
$aSearch['iSearchRank'] += 1000; // skip;
}
}
else
{
$aSearch['aName'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
//$aSearch['iNamePhrase'] = $iPhrase;
}
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
}
// Look for partial matches.
// Note that there is no point in adding country terms here
// because country are omitted in the address.
if (isset($aValidTokens[$sToken]) && $sPhraseType != 'country')
{
// Allow searching for a word - but at extra cost
foreach($aValidTokens[$sToken] as $aSearchTerm)
{
if (isset($aSearchTerm['word_id']) && $aSearchTerm['word_id'])
{
if ((!$bStructuredPhrases || $iPhrase > 0) && sizeof($aCurrentSearch['aName']) && strpos($sToken, ' ') === false)
{
$aSearch = $aCurrentSearch;
$aSearch['iSearchRank'] += 1;
if ($aWordFrequencyScores[$aSearchTerm['word_id']] < CONST_Max_Word_Frequency)
{
$aSearch['aAddress'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
elseif (isset($aValidTokens[' '.$sToken])) // revert to the token version?
{
$aSearch['aAddressNonSearch'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
$aSearch['iSearchRank'] += 1;
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
foreach($aValidTokens[' '.$sToken] as $aSearchTermToken)
{
if (empty($aSearchTermToken['country_code'])
&& empty($aSearchTermToken['lat'])
&& empty($aSearchTermToken['class']))
{
$aSearch = $aCurrentSearch;
$aSearch['iSearchRank'] += 1;
$aSearch['aAddress'][$aSearchTermToken['word_id']] = $aSearchTermToken['word_id'];
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
}
else
{
$aSearch['aAddressNonSearch'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
if (preg_match('#^[0-9]+$#', $sToken)) $aSearch['iSearchRank'] += 2;
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
if (!sizeof($aCurrentSearch['aName']) || $aCurrentSearch['iNamePhrase'] == $iPhrase)
{
$aSearch = $aCurrentSearch;
$aSearch['iSearchRank'] += 1;
if (!sizeof($aCurrentSearch['aName'])) $aSearch['iSearchRank'] += 1;
if (preg_match('#^[0-9]+$#', $sToken)) $aSearch['iSearchRank'] += 2;
if ($aWordFrequencyScores[$aSearchTerm['word_id']] < CONST_Max_Word_Frequency)
$aSearch['aName'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
else
$aSearch['aNameNonSearch'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
$aSearch['iNamePhrase'] = $iPhrase;
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
}
}
else
{
// Allow skipping a word - but at EXTREAM cost
//$aSearch = $aCurrentSearch;
//$aSearch['iSearchRank']+=100;
//$aNewWordsetSearches[] = $aSearch;
}
}
// Sort and cut
usort($aNewWordsetSearches, 'bySearchRank');
$aWordsetSearches = array_slice($aNewWordsetSearches, 0, 50);
}
//var_Dump('<hr>',sizeof($aWordsetSearches)); exit;
$aNewPhraseSearches = array_merge($aNewPhraseSearches, $aNewWordsetSearches);
usort($aNewPhraseSearches, 'bySearchRank');
$aSearchHash = array();
foreach($aNewPhraseSearches as $iSearch => $aSearch)
{
$sHash = serialize($aSearch);
if (isset($aSearchHash[$sHash])) unset($aNewPhraseSearches[$iSearch]);
else $aSearchHash[$sHash] = 1;
}
$aNewPhraseSearches = array_slice($aNewPhraseSearches, 0, 50);
}
// Re-group the searches by their score, junk anything over 20 as just not worth trying
$aGroupedSearches = array();
foreach($aNewPhraseSearches as $aSearch)
{
if ($aSearch['iSearchRank'] < $this->iMaxRank)
{
if (!isset($aGroupedSearches[$aSearch['iSearchRank']])) $aGroupedSearches[$aSearch['iSearchRank']] = array();
$aGroupedSearches[$aSearch['iSearchRank']][] = $aSearch;
}
}
ksort($aGroupedSearches);
$iSearchCount = 0;
$aSearches = array();
foreach($aGroupedSearches as $iScore => $aNewSearches)
{
$iSearchCount += sizeof($aNewSearches);
$aSearches = array_merge($aSearches, $aNewSearches);
if ($iSearchCount > 50) break;
}
//if (CONST_Debug) _debugDumpGroupedSearches($aGroupedSearches, $aValidTokens);
}
return $aGroupedSearches;
}
/* Perform the actual query lookup.
Returns an ordered list of results, each with the following fields:
@@ -579,10 +871,10 @@
preg_match_all('/\\[([\\w ]*)\\]/u', $sQuery, $aSpecialTermsRaw, PREG_SET_ORDER);
$aSpecialTerms = array();
if (isset($aStructuredQuery['amenity']) && $aStructuredQuery['amenity'])
if (isset($this->aStructuredQuery['amenity']) && $this->aStructuredQuery['amenity'])
{
$aSpecialTermsRaw[] = array('['.$aStructuredQuery['amenity'].']', $aStructuredQuery['amenity']);
unset($aStructuredQuery['amenity']);
$aSpecialTermsRaw[] = array('['.$this->aStructuredQuery['amenity'].']', $this->aStructuredQuery['amenity']);
unset($this->aStructuredQuery['amenity']);
}
foreach($aSpecialTermsRaw as $aSpecialTerm)
{
@@ -680,8 +972,8 @@
foreach($aDatabaseWords as $aToken)
{
// Very special case - require 2 letter country param to match the country code found
if ($bStructuredPhrases && $aToken['country_code'] && !empty($aStructuredQuery['country'])
&& strlen($aStructuredQuery['country']) == 2 && strtolower($aStructuredQuery['country']) != $aToken['country_code'])
if ($bStructuredPhrases && $aToken['country_code'] && !empty($this->aStructuredQuery['country'])
&& strlen($this->aStructuredQuery['country']) == 2 && strtolower($this->aStructuredQuery['country']) != $aToken['country_code'])
{
continue;
}
@@ -755,287 +1047,38 @@
// Start the search process
$aResultPlaceIDs = array();
/*
Calculate all searches using aValidTokens i.e.
'Wodsworth Road, Sheffield' =>
$aGroupedSearches = $this->getGroupedSearches($aSearches, $aPhraseTypes, $aPhrases, $aValidTokens, $aWordFrequencyScores, $bStructuredPhrases);
Phrase Wordset
0 0 (wodsworth road)
0 1 (wodsworth)(road)
1 0 (sheffield)
Score how good the search is so they can be ordered
*/
foreach($aPhrases as $iPhrase => $sPhrase)
if ($this->bReverseInPlan)
{
$aNewPhraseSearches = array();
if ($bStructuredPhrases) $sPhraseType = $aPhraseTypes[$iPhrase];
else $sPhraseType = '';
foreach($aPhrases[$iPhrase]['wordsets'] as $iWordSet => $aWordset)
// Reverse phrase array and also reverse the order of the wordsets in
// the first and final phrase. Don't bother about phrases in the middle
// because order in the address doesn't matter.
$aPhrases = array_reverse($aPhrases);
$aPhrases[0]['wordsets'] = getInverseWordSets($aPhrases[0]['words'], 0);
if (sizeof($aPhrases) > 1)
{
// Too many permutations - too expensive
if ($iWordSet > 120) break;
$aFinalPhrase = end($aPhrases);
$aPhrases[sizeof($aPhrases)-1]['wordsets'] = getInverseWordSets($aFinalPhrase['words'], 0);
}
$aReverseGroupedSearches = $this->getGroupedSearches($aSearches, null, $aPhrases, $aValidTokens, $aWordFrequencyScores, false);
$aWordsetSearches = $aSearches;
// Add all words from this wordset
foreach($aWordset as $iToken => $sToken)
foreach($aGroupedSearches as $aSearches)
{
foreach($aSearches as $aSearch)
{
//echo "<br><b>$sToken</b>";
$aNewWordsetSearches = array();
foreach($aWordsetSearches as $aCurrentSearch)
if ($aSearch['iSearchRank'] < $this->iMaxRank)
{
//echo "<i>";
//var_dump($aCurrentSearch);
//echo "</i>";
// If the token is valid
if (isset($aValidTokens[' '.$sToken]))
{
foreach($aValidTokens[' '.$sToken] as $aSearchTerm)
{
$aSearch = $aCurrentSearch;
$aSearch['iSearchRank']++;
if (($sPhraseType == '' || $sPhraseType == 'country') && !empty($aSearchTerm['country_code']) && $aSearchTerm['country_code'] != '0')
{
if ($aSearch['sCountryCode'] === false)
{
$aSearch['sCountryCode'] = strtolower($aSearchTerm['country_code']);
// Country is almost always at the end of the string - increase score for finding it anywhere else (optimisation)
// If reverse order is enabled, it may appear at the beginning as well.
if (($iToken+1 != sizeof($aWordset) || $iPhrase+1 != sizeof($aPhrases)) &&
(!$this->bReverseInPlan || $iToken > 0 || $iPhrase > 0))
{
$aSearch['iSearchRank'] += 5;
}
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
elseif (isset($aSearchTerm['lat']) && $aSearchTerm['lat'] !== '' && $aSearchTerm['lat'] !== null)
{
if ($aSearch['fLat'] === '')
{
$aSearch['fLat'] = $aSearchTerm['lat'];
$aSearch['fLon'] = $aSearchTerm['lon'];
$aSearch['fRadius'] = $aSearchTerm['radius'];
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
elseif ($sPhraseType == 'postalcode')
{
// We need to try the case where the postal code is the primary element (i.e. no way to tell if it is (postalcode, city) OR (city, postalcode) so try both
if (isset($aSearchTerm['word_id']) && $aSearchTerm['word_id'])
{
// If we already have a name try putting the postcode first
if (sizeof($aSearch['aName']))
{
$aNewSearch = $aSearch;
$aNewSearch['aAddress'] = array_merge($aNewSearch['aAddress'], $aNewSearch['aName']);
$aNewSearch['aName'] = array();
$aNewSearch['aName'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aNewSearch;
}
if (sizeof($aSearch['aName']))
{
if ((!$bStructuredPhrases || $iPhrase > 0) && $sPhraseType != 'country' && (!isset($aValidTokens[$sToken]) || strlen($sToken) < 4 || strpos($sToken, ' ') !== false))
{
$aSearch['aAddress'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
}
else
{
$aCurrentSearch['aFullNameAddress'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
$aSearch['iSearchRank'] += 1000; // skip;
}
}
else
{
$aSearch['aName'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
//$aSearch['iNamePhrase'] = $iPhrase;
}
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
elseif (($sPhraseType == '' || $sPhraseType == 'street') && $aSearchTerm['class'] == 'place' && $aSearchTerm['type'] == 'house')
{
if ($aSearch['sHouseNumber'] === '')
{
$aSearch['sHouseNumber'] = $sToken;
// sanity check: if the housenumber is not mainly made
// up of numbers, add a penalty
if (preg_match_all("/[^0-9]/", $sToken, $aMatches) > 2) $aSearch['iSearchRank']++;
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
/*
// Fall back to not searching for this item (better than nothing)
$aSearch = $aCurrentSearch;
$aSearch['iSearchRank'] += 1;
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
*/
}
}
elseif ($sPhraseType == '' && $aSearchTerm['class'] !== '' && $aSearchTerm['class'] !== null)
{
if ($aSearch['sClass'] === '')
{
$aSearch['sOperator'] = $aSearchTerm['operator'];
$aSearch['sClass'] = $aSearchTerm['class'];
$aSearch['sType'] = $aSearchTerm['type'];
if (sizeof($aSearch['aName'])) $aSearch['sOperator'] = 'name';
else $aSearch['sOperator'] = 'near'; // near = in for the moment
if (strlen($aSearchTerm['operator']) == 0) $aSearch['iSearchRank'] += 1;
// Do we have a shortcut id?
if ($aSearch['sOperator'] == 'name')
{
$sSQL = "select get_tagpair('".$aSearch['sClass']."', '".$aSearch['sType']."')";
if ($iAmenityID = $this->oDB->getOne($sSQL))
{
$aValidTokens[$aSearch['sClass'].':'.$aSearch['sType']] = array('word_id' => $iAmenityID);
$aSearch['aName'][$iAmenityID] = $iAmenityID;
$aSearch['sClass'] = '';
$aSearch['sType'] = '';
}
}
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
elseif (isset($aSearchTerm['word_id']) && $aSearchTerm['word_id'])
{
if (sizeof($aSearch['aName']))
{
if ((!$bStructuredPhrases || $iPhrase > 0) && $sPhraseType != 'country' && (!isset($aValidTokens[$sToken]) || strlen($sToken) < 4 || strpos($sToken, ' ') !== false))
{
$aSearch['aAddress'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
}
else
{
$aCurrentSearch['aFullNameAddress'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
$aSearch['iSearchRank'] += 1000; // skip;
}
}
else
{
$aSearch['aName'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
//$aSearch['iNamePhrase'] = $iPhrase;
}
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
}
if (isset($aValidTokens[$sToken]))
{
// Allow searching for a word - but at extra cost
foreach($aValidTokens[$sToken] as $aSearchTerm)
{
if (isset($aSearchTerm['word_id']) && $aSearchTerm['word_id'])
{
if ((!$bStructuredPhrases || $iPhrase > 0) && sizeof($aCurrentSearch['aName']) && strpos($sToken, ' ') === false)
{
$aSearch = $aCurrentSearch;
$aSearch['iSearchRank'] += 1;
if ($aWordFrequencyScores[$aSearchTerm['word_id']] < CONST_Max_Word_Frequency)
{
$aSearch['aAddress'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
elseif (isset($aValidTokens[' '.$sToken]) && strlen($sToken) >= 4) // revert to the token version?
{
$aSearch['aAddressNonSearch'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
$aSearch['iSearchRank'] += 1;
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
foreach($aValidTokens[' '.$sToken] as $aSearchTermToken)
{
if (empty($aSearchTermToken['country_code'])
&& empty($aSearchTermToken['lat'])
&& empty($aSearchTermToken['class']))
{
$aSearch = $aCurrentSearch;
$aSearch['iSearchRank'] += 1;
$aSearch['aAddress'][$aSearchTermToken['word_id']] = $aSearchTermToken['word_id'];
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
}
else
{
$aSearch['aAddressNonSearch'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
if (preg_match('#^[0-9]+$#', $sToken)) $aSearch['iSearchRank'] += 2;
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
if (!sizeof($aCurrentSearch['aName']) || $aCurrentSearch['iNamePhrase'] == $iPhrase)
{
$aSearch = $aCurrentSearch;
$aSearch['iSearchRank'] += 1;
if (!sizeof($aCurrentSearch['aName'])) $aSearch['iSearchRank'] += 1;
if (preg_match('#^[0-9]+$#', $sToken)) $aSearch['iSearchRank'] += 2;
if ($aWordFrequencyScores[$aSearchTerm['word_id']] < CONST_Max_Word_Frequency)
$aSearch['aName'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
else
$aSearch['aNameNonSearch'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
$aSearch['iNamePhrase'] = $iPhrase;
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
}
}
else
{
// Allow skipping a word - but at EXTREAM cost
//$aSearch = $aCurrentSearch;
//$aSearch['iSearchRank']+=100;
//$aNewWordsetSearches[] = $aSearch;
}
if (!isset($aReverseGroupedSearches[$aSearch['iSearchRank']])) $aReverseGroupedSearches[$aSearch['iSearchRank']] = array();
$aReverseGroupedSearches[$aSearch['iSearchRank']][] = $aSearch;
}
// Sort and cut
usort($aNewWordsetSearches, 'bySearchRank');
$aWordsetSearches = array_slice($aNewWordsetSearches, 0, 50);
}
//var_Dump('<hr>',sizeof($aWordsetSearches)); exit;
$aNewPhraseSearches = array_merge($aNewPhraseSearches, $aNewWordsetSearches);
usort($aNewPhraseSearches, 'bySearchRank');
$aSearchHash = array();
foreach($aNewPhraseSearches as $iSearch => $aSearch)
{
$sHash = serialize($aSearch);
if (isset($aSearchHash[$sHash])) unset($aNewPhraseSearches[$iSearch]);
else $aSearchHash[$sHash] = 1;
}
$aNewPhraseSearches = array_slice($aNewPhraseSearches, 0, 50);
}
// Re-group the searches by their score, junk anything over 20 as just not worth trying
$aGroupedSearches = array();
foreach($aNewPhraseSearches as $aSearch)
{
if ($aSearch['iSearchRank'] < $this->iMaxRank)
{
if (!isset($aGroupedSearches[$aSearch['iSearchRank']])) $aGroupedSearches[$aSearch['iSearchRank']] = array();
$aGroupedSearches[$aSearch['iSearchRank']][] = $aSearch;
}
}
$aGroupedSearches = $aReverseGroupedSearches;
ksort($aGroupedSearches);
$iSearchCount = 0;
$aSearches = array();
foreach($aGroupedSearches as $iScore => $aNewSearches)
{
$iSearchCount += sizeof($aNewSearches);
$aSearches = array_merge($aSearches, $aNewSearches);
if ($iSearchCount > 50) break;
}
//if (CONST_Debug) _debugDumpGroupedSearches($aGroupedSearches, $aValidTokens);
}
}
else
{
@@ -1054,30 +1097,7 @@
if (CONST_Debug) var_Dump($aGroupedSearches);
if ($this->bReverseInPlan)
{
$aCopyGroupedSearches = $aGroupedSearches;
foreach($aCopyGroupedSearches as $iGroup => $aSearches)
{
foreach($aSearches as $iSearch => $aSearch)
{
if (sizeof($aSearch['aAddress']))
{
$iReverseItem = array_pop($aSearch['aAddress']);
if (isset($aPossibleMainWordIDs[$iReverseItem]))
{
$aSearch['aAddress'] = array_merge($aSearch['aAddress'], $aSearch['aName']);
$aSearch['aName'] = array($iReverseItem);
$aGroupedSearches[$iGroup][] = $aSearch;
}
//$aReverseSearch['aName'][$iReverseItem] = $iReverseItem;
//$aGroupedSearches[$iGroup][] = $aReverseSearch;
}
}
}
}
if (CONST_Search_TryDroppedAddressTerms && sizeof($aStructuredQuery) > 0)
if (CONST_Search_TryDroppedAddressTerms && sizeof($this->aStructuredQuery) > 0)
{
$aCopyGroupedSearches = $aGroupedSearches;
foreach($aCopyGroupedSearches as $iGroup => $aSearches)
@@ -1156,6 +1176,8 @@
{
$sSQL = "select place_id from placex where calculated_country_code='".$aSearch['sCountryCode']."' and rank_search = 4";
if ($sCountryCodesSQL) $sSQL .= " and calculated_country_code in ($sCountryCodesSQL)";
if ($bBoundingBoxSearch)
$sSQL .= " and _st_intersects($this->sViewboxSmallSQL, geometry)";
$sSQL .= " order by st_area(geometry) desc limit 1";
if (CONST_Debug) var_dump($sSQL);
$aPlaceIDs = $this->oDB->getCol($sSQL);
@@ -1221,6 +1243,12 @@
$aTerms = array();
$aOrder = array();
if ($aSearch['sHouseNumber'] && sizeof($aSearch['aAddress']))
{
$sHouseNumberRegex = '\\\\m'.$aSearch['sHouseNumber'].'\\\\M';
$aOrder[] = "exists(select place_id from placex where parent_place_id = search_name.place_id and transliteration(housenumber) ~* E'".$sHouseNumberRegex."' limit 1) desc";
}
// TODO: filter out the pointless search terms (2 letter name tokens and less)
// they might be right - but they are just too darned expensive to run
if (sizeof($aSearch['aName'])) $aTerms[] = "name_vector @> ARRAY[".join($aSearch['aName'],",")."]";
@@ -1301,7 +1329,7 @@
$sSQL .= " where ".join(' and ',$aTerms);
$sSQL .= " order by ".join(', ',$aOrder);
if ($aSearch['sHouseNumber'] || $aSearch['sClass'])
$sSQL .= " limit 50";
$sSQL .= " limit 20";
elseif (!sizeof($aSearch['aName']) && !sizeof($aSearch['aAddress']) && $aSearch['sClass'])
$sSQL .= " limit 1";
else
@@ -1566,9 +1594,11 @@
$aRecheckWords = preg_split('/\b[\s,\\-]*/u',$sQuery);
foreach($aRecheckWords as $i => $sWord)
{
if (!$sWord) unset($aRecheckWords[$i]);
if (!preg_match('/\pL/', $sWord)) unset($aRecheckWords[$i]);
}
if (CONST_Debug) { echo '<i>Recheck words:<\i>'; var_dump($aRecheckWords); }
foreach($aSearchResults as $iResNum => $aResult)
{
if (CONST_Search_AreaPolygons)
@@ -1576,13 +1606,13 @@
// Get the bounding box and outline polygon
$sSQL = "select place_id,0 as numfeatures,st_area(geometry) as area,";
$sSQL .= "ST_Y(centroid) as centrelat,ST_X(centroid) as centrelon,";
$sSQL .= "ST_Y(ST_PointN(ST_ExteriorRing(Box2D(geometry)),4)) as minlat,ST_Y(ST_PointN(ST_ExteriorRing(Box2D(geometry)),2)) as maxlat,";
$sSQL .= "ST_X(ST_PointN(ST_ExteriorRing(Box2D(geometry)),1)) as minlon,ST_X(ST_PointN(ST_ExteriorRing(Box2D(geometry)),3)) as maxlon";
$sSQL .= "ST_YMin(geometry) as minlat,ST_YMax(geometry) as maxlat,";
$sSQL .= "ST_XMin(geometry) as minlon,ST_XMax(geometry) as maxlon";
if ($this->bIncludePolygonAsGeoJSON) $sSQL .= ",ST_AsGeoJSON(geometry) as asgeojson";
if ($this->bIncludePolygonAsKML) $sSQL .= ",ST_AsKML(geometry) as askml";
if ($this->bIncludePolygonAsSVG) $sSQL .= ",ST_AsSVG(geometry) as assvg";
if ($this->bIncludePolygonAsText || $this->bIncludePolygonAsPoints) $sSQL .= ",ST_AsText(geometry) as astext";
$sSQL .= " from placex where place_id = ".$aResult['place_id'].' and st_geometrytype(Box2D(geometry)) = \'ST_Polygon\'';
$sSQL .= " from placex where place_id = ".$aResult['place_id'];
$aPointPolygon = $this->oDB->getRow($sSQL);
if (PEAR::IsError($aPointPolygon))
{
@@ -1604,7 +1634,7 @@
if ($this->bIncludePolygonAsPoints)
{
// Translate geometary string to point array
// Translate geometry string to point array
if (preg_match('#POLYGON\\(\\(([- 0-9.,]+)#',$aPointPolygon['astext'],$aMatch))
{
preg_match_all('/(-?[0-9.]+) (-?[0-9.]+)/',$aMatch[1],$aPolyPoints,PREG_SET_ORDER);
@@ -1727,7 +1757,7 @@
if (stripos($sAddress, $sWord)!==false)
{
$iCountWords++;
if (preg_match("/(^|,)\s*$sWord\s*(,|$)/", $sAddress)) $iCountWords += 0.1;
if (preg_match("/(^|,)\s*".preg_quote($sWord, '/')."\s*(,|$)/", $sAddress)) $iCountWords += 0.1;
}
}
@@ -1764,7 +1794,6 @@
$bFirst = true;
foreach($aToFilter as $iResNum => $aResult)
{
if ($aResult['type'] == 'adminitrative') $aResult['type'] = 'administrative';
$this->aExcludePlaceIDs[$aResult['place_id']] = $aResult['place_id'];
if ($bFirst)
{

View File

@@ -46,10 +46,15 @@
$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 .= " st_y(centroid) as lat, st_x(centroid) as lon";
$sSQL .= " (case when centroid is null then st_y(st_centroid(geometry)) else st_y(centroid) end) as lat,";
$sSQL .= " (case when centroid is null then st_x(st_centroid(geometry)) else st_x(centroid) end) as lon";
$sSQL .= " from placex where place_id = ".(int)$this->iPlaceID;
$aPlace = $this->oDB->getRow($sSQL);
if (PEAR::IsError($aPlace))
{
failInternalError("Could not lookup place.", $sSQL, $aPlace);
}
if (!$aPlace['place_id']) return null;
if ($this->bAddressDetails)

View File

@@ -193,6 +193,26 @@
return $aResult;
}
function getInverseWordSets($aWords, $iDepth)
{
$aResult = array(array(join(' ',$aWords)));
$sFirstToken = '';
if ($iDepth < 8)
{
while(sizeof($aWords) > 1)
{
$sWord = array_pop($aWords);
$sFirstToken = $sWord.($sFirstToken?' ':'').$sFirstToken;
$aRest = getInverseWordSets($aWords, $iDepth+1);
foreach($aRest as $aSet)
{
$aResult[] = array_merge(array($sFirstToken),$aSet);
}
}
}
return $aResult;
}
function getTokensFromSets($aSets)
{
@@ -358,7 +378,7 @@
'landuse:farm' => array('label'=>'Farm','frequency'=>1201,'icon'=>'', 'defdiameter' => 0.02,),
'place:farm' => array('label'=>'Farm','frequency'=>1162,'icon'=>'', 'defdiameter' => 0.02,),
'highway:motorway_junction' => array('label'=>'Motorway Junction','frequency'=>1126,'icon'=>'','simplelabel'=>'Road',),
'highway:motorway_junction' => array('label'=>'Motorway Junction','frequency'=>1126,'icon'=>'','simplelabel'=>'Junction',),
'highway:motorway' => array('label'=>'Motorway','frequency'=>4627,'icon'=>'','simplelabel'=>'Road',),
'highway:trunk' => array('label'=>'Trunk','frequency'=>23084,'icon'=>'','simplelabel'=>'Road',),
'highway:primary' => array('label'=>'Primary','frequency'=>32138,'icon'=>'','simplelabel'=>'Road',),
@@ -460,7 +480,7 @@
'shop:electronics' => array('label'=>'Electronics','frequency'=>96,'icon'=>'',),
'shop:department_store' => array('label'=>'Department Store','frequency'=>86,'icon'=>'',),
'shop:books' => array('label'=>'Books','frequency'=>85,'icon'=>'',),
'shop:yes' => array('label'=>'Yes','frequency'=>68,'icon'=>'',),
'shop:yes' => array('label'=>'Shop','frequency'=>68,'icon'=>'',),
'shop:outdoor' => array('label'=>'Outdoor','frequency'=>67,'icon'=>'',),
'shop:mall' => array('label'=>'Mall','frequency'=>63,'icon'=>'',),
'shop:florist' => array('label'=>'Florist','frequency'=>61,'icon'=>'',),
@@ -540,7 +560,6 @@
'natural:beach' => array('label'=>'Beach','frequency'=>121,'icon'=>'tourist_beach',),
'place:moor' => array('label'=>'Moor','frequency'=>118,'icon'=>'',),
'amenity:grave_yard' => array('label'=>'Grave Yard','frequency'=>110,'icon'=>'',),
'waterway:derelict_canal' => array('label'=>'Derelict Canal','frequency'=>109,'icon'=>'',),
'waterway:drain' => array('label'=>'Drain','frequency'=>108,'icon'=>'',),
'landuse:grass' => array('label'=>'Grass','frequency'=>106,'icon'=>'',),
'landuse:village_green' => array('label'=>'Village Green','frequency'=>106,'icon'=>'',),
@@ -606,7 +625,7 @@
'historic:roman_road' => array('label'=>'Roman Road','frequency'=>27,'icon'=>'',),
'historic:fort' => array('label'=>'Fort','frequency'=>26,'icon'=>'',),
'railway:subway_entrance' => array('label'=>'Subway Entrance','frequency'=>26,'icon'=>'',),
'historic:yes' => array('label'=>'Yes','frequency'=>25,'icon'=>'',),
'historic:yes' => array('label'=>'Historic','frequency'=>25,'icon'=>'',),
'highway:gate' => array('label'=>'Gate','frequency'=>25,'icon'=>'',),
'leisure:fishing' => array('label'=>'Fishing','frequency'=>24,'icon'=>'',),
'historic:museum' => array('label'=>'Museum','frequency'=>24,'icon'=>'',),
@@ -628,7 +647,7 @@
'place:houses' => array('label'=>'Houses','frequency'=>85,'icon'=>'',),
'railway:preserved' => array('label'=>'Preserved','frequency'=>227,'icon'=>'',),
'waterway:derelict canal' => array('label'=>'Derelict Canal','frequency'=>21,'icon'=>'',),
'waterway:derelict_canal' => array('label'=>'Derelict Canal','frequency'=>21,'icon'=>'',),
'amenity:dead_pub' => array('label'=>'Dead Pub','frequency'=>20,'icon'=>'',),
'railway:disused_station' => array('label'=>'Disused Station','frequency'=>114,'icon'=>'',),
'railway:abandoned' => array('label'=>'Abandoned','frequency'=>641,'icon'=>'',),
@@ -652,7 +671,10 @@
function javascript_renderData($xVal)
{
header("Access-Control-Allow-Origin: *");
$jsonout = json_encode($xVal);
$iOptions = 0;
if (defined('PHP_VERSION_ID') && PHP_VERSION_ID > 50400)
$iOptions = JSON_UNESCAPED_UNICODE;
$jsonout = json_encode($xVal, $iOptions);
if( ! isset($_GET['json_callback']))
{
@@ -994,4 +1016,4 @@
$sQuery = trim(str_replace($sFound, ' ', $sQuery));
return array('lat' => $fQueryLat, 'lon' => $fQueryLon, 'query' => $sQuery);
}
}

View File

@@ -189,8 +189,12 @@
$aGroupedAddressLines = array();
foreach($aParentOfLines as $aAddressLine)
{
if (!isset($aGroupedAddressLines[$aAddressLine['type']])) $aGroupedAddressLines[$aAddressLine['type']] = array();
$aGroupedAddressLines[$aAddressLine['type']][] = $aAddressLine;
if ($aAddressLine['type'] == 'yes') $sType = $aAddressLine['class'];
else $sType = $aAddressLine['type'];
if (!isset($aGroupedAddressLines[$sType]))
$aGroupedAddressLines[$sType] = array();
$aGroupedAddressLines[$sType][] = $aAddressLine;
}
foreach($aGroupedAddressLines as $sGroupHeading => $aParentOfLines)
{

View File

@@ -199,11 +199,13 @@ target="_blank">FAQ</a></td>
}
echo (isset($aResult['icon'])?'<img alt="icon" src="'.$aResult['icon'].'"/>':'');
echo ' <span class="name">'.$aResult['name'].'</span>';
echo ' <span class="name">'.htmlspecialchars($aResult['name']).'</span>';
echo ' <span class="latlon">'.round($aResult['lat'],3).','.round($aResult['lon'],3).'</span>';
echo ' <span class="place_id">'.$aResult['place_id'].'</span>';
if (isset($aResult['label']))
echo ' <span class="type">('.$aResult['label'].')</span>';
else if ($aResult['type'] == 'yes')
echo ' <span class="type">('.ucwords(str_replace('_',' ',$aResult['class'])).')</span>';
else
echo ' <span class="type">('.ucwords(str_replace('_',' ',$aResult['type'])).')</span>';
echo ' <span class="details">(<a href="details.php?place_id='.$aResult['place_id'].'">details</a>)</span>';

View File

@@ -5,12 +5,13 @@
// General settings
@define('CONST_Debug', false);
@define('CONST_Database_DSN', 'pgsql://@/nominatim'); // <driver>://<username>:<password>@<host>:<port>/<database>
@define('CONST_Database_Web_User', 'www-data');
@define('CONST_Max_Word_Frequency', '50000');
@define('CONST_Limit_Reindexing', true);
// Software versions
@define('CONST_Postgresql_Version', '9.1'); // values: 8.3, 8.4, 9.0, 9.1, 9.2
@define('CONST_Postgis_Version', '1.5'); // values: 1.5, 2.0
@define('CONST_Postgresql_Version', '9.3'); // values: 9.0, ... , 9.4
@define('CONST_Postgis_Version', '2.1'); // values: 1.5, 2.0, 2.1
// Paths
@define('CONST_Path_Postgresql_Contrib', '/usr/share/postgresql/'.CONST_Postgresql_Version.'/contrib');
@@ -21,6 +22,23 @@
// osm2pgsql settings
@define('CONST_Osm2pgsql_Flatnode_File', null);
// tablespace settings
// osm2pgsql caching tables (aka slim mode tables) - update only
@define('CONST_Tablespace_Osm2pgsql_Data', false);
@define('CONST_Tablespace_Osm2pgsql_Index', false);
// osm2pgsql output tables (aka main table) - update only
@define('CONST_Tablespace_Place_Data', false);
@define('CONST_Tablespace_Place_Index', false);
// address computation tables - update only
@define('CONST_Tablespace_Address_Data', false);
@define('CONST_Tablespace_Address_Index', false);
// search tables - needed for lookups
@define('CONST_Tablespace_Search_Data', false);
@define('CONST_Tablespace_Search_Index', false);
// additional data, e.g. TIGER data, type searches - needed for lookups
@define('CONST_Tablespace_Aux_Data', false);
@define('CONST_Tablespace_Aux_Index', false);
// Replication settings
@define('CONST_Replication_Url', 'http://planet.openstreetmap.org/replication/minute');
@define('CONST_Replication_MaxInterval', '3600');
@@ -72,7 +90,7 @@
@define('CONST_Search_BatchMode', false);
@define('CONST_Search_TryDroppedAddressTerms', false);
@define('CONST_Search_NameOnlySearchFrequencyThreshold', false);
@define('CONST_Search_NameOnlySearchFrequencyThreshold', 500);
// Set to zero to disable polygon output
@define('CONST_PolygonOutput_MaximumTypes', 1);

File diff suppressed because it is too large Load Diff

View File

@@ -1,30 +1,30 @@
-- Indices used only during search and update.
-- These indices are created only after the indexing process is done.
CREATE INDEX idx_word_word_id on word USING BTREE (word_id);
CREATE INDEX idx_word_word_id on word USING BTREE (word_id) {ts:search-index};
CREATE INDEX idx_search_name_nameaddress_vector ON search_name USING GIN (nameaddress_vector) WITH (fastupdate = off);
CREATE INDEX idx_search_name_name_vector ON search_name USING GIN (name_vector) WITH (fastupdate = off);
CREATE INDEX idx_search_name_centroid ON search_name USING GIST (centroid);
CREATE INDEX idx_search_name_nameaddress_vector ON search_name USING GIN (nameaddress_vector) WITH (fastupdate = off) {ts:search-index};
CREATE INDEX idx_search_name_name_vector ON search_name USING GIN (name_vector) WITH (fastupdate = off) {ts:search-index};
CREATE INDEX idx_search_name_centroid ON search_name USING GIST (centroid) {ts:search-index};
CREATE INDEX idx_place_addressline_address_place_id on place_addressline USING BTREE (address_place_id);
CREATE INDEX idx_place_boundingbox_place_id on place_boundingbox USING BTREE (place_id);
CREATE INDEX idx_place_boundingbox_outline ON place_boundingbox USING GIST (outline);
CREATE INDEX idx_place_addressline_address_place_id on place_addressline USING BTREE (address_place_id) {ts:search-index};
DROP INDEX IF EXISTS idx_placex_rank_search;
CREATE INDEX idx_placex_rank_search ON placex USING BTREE (rank_search);
CREATE INDEX idx_placex_rank_address ON placex USING BTREE (rank_address);
CREATE INDEX idx_placex_pendingsector ON placex USING BTREE (rank_search,geometry_sector) where indexed_status > 0;
CREATE INDEX idx_placex_parent_place_id ON placex USING BTREE (parent_place_id) where parent_place_id IS NOT NULL;
CREATE INDEX idx_placex_interpolation ON placex USING BTREE (geometry_sector) where indexed_status > 0 and class='place' and type='houses';
CREATE INDEX idx_placex_reverse_geometry ON placex USING gist (geometry) where rank_search != 28 and (name is not null or housenumber is not null) and class not in ('waterway','railway','tunnel','bridge');
CREATE INDEX idx_location_area_country_place_id ON location_area_country USING BTREE (place_id);
CREATE INDEX idx_placex_rank_search ON placex USING BTREE (rank_search) {ts:search-index};
CREATE INDEX idx_placex_rank_address ON placex USING BTREE (rank_address) {ts:search-index};
CREATE INDEX idx_placex_pendingsector ON placex USING BTREE (rank_search,geometry_sector) {ts:address-index} where indexed_status > 0;
CREATE INDEX idx_placex_parent_place_id ON placex USING BTREE (parent_place_id) {ts:search-index} where parent_place_id IS NOT NULL;
CREATE INDEX idx_placex_reverse_geometry ON placex USING gist (geometry) {ts:search-index} where rank_search != 28 and (name is not null or housenumber is not null) and class not in ('waterway','railway','tunnel','bridge');
CREATE INDEX idx_location_area_country_place_id ON location_area_country USING BTREE (place_id) {ts:address-index};
CREATE INDEX idx_search_name_country_centroid ON search_name_country USING GIST (centroid);
CREATE INDEX idx_search_name_country_centroid ON search_name_country USING GIST (centroid) {ts:address-index};
-- start
CREATE INDEX idx_location_property_-partition-_centroid ON location_property_-partition- USING GIST (centroid);
CREATE INDEX idx_location_property_-partition-_centroid ON location_property_-partition- USING GIST (centroid) {ts:address-index};
-- end
CREATE UNIQUE INDEX idx_place_osm_unique on place using btree(osm_id,osm_type,class,type);
DROP INDEX IF EXISTS place_id_idx;
CREATE UNIQUE INDEX idx_place_osm_unique on place using btree(osm_id,osm_type,class,type) {ts:address-index};
CREATE INDEX idx_gb_postcode_postcode ON gb_postcode USING BTREE (postcode) {ts:search-index};

View File

@@ -34,35 +34,35 @@ CREATE TABLE search_name_blank (
SELECT AddGeometryColumn('search_name_blank', 'centroid', 4326, 'GEOMETRY', 2);
CREATE TABLE location_area_country () INHERITS (location_area_large);
CREATE INDEX idx_location_area_country_geometry ON location_area_country USING GIST (geometry);
CREATE TABLE location_area_country () INHERITS (location_area_large) {ts:address-data};
CREATE INDEX idx_location_area_country_geometry ON location_area_country USING GIST (geometry) {ts:address-index};
CREATE TABLE search_name_country () INHERITS (search_name_blank);
CREATE INDEX idx_search_name_country_place_id ON search_name_country USING BTREE (place_id);
CREATE INDEX idx_search_name_country_name_vector ON search_name_country USING GIN (name_vector) WITH (fastupdate = off);
CREATE TABLE search_name_country () INHERITS (search_name_blank) {ts:address-data};
CREATE INDEX idx_search_name_country_place_id ON search_name_country USING BTREE (place_id) {ts:address-index};
CREATE INDEX idx_search_name_country_name_vector ON search_name_country USING GIN (name_vector) WITH (fastupdate = off) {ts:address-index};
-- start
CREATE TABLE location_area_large_-partition- () INHERITS (location_area_large);
CREATE INDEX idx_location_area_large_-partition-_place_id ON location_area_large_-partition- USING BTREE (place_id);
CREATE INDEX idx_location_area_large_-partition-_geometry ON location_area_large_-partition- USING GIST (geometry);
CREATE TABLE location_area_large_-partition- () INHERITS (location_area_large) {ts:address-data};
CREATE INDEX idx_location_area_large_-partition-_place_id ON location_area_large_-partition- USING BTREE (place_id) {ts:address-index};
CREATE INDEX idx_location_area_large_-partition-_geometry ON location_area_large_-partition- USING GIST (geometry) {ts:address-index};
CREATE TABLE search_name_-partition- () INHERITS (search_name_blank);
CREATE INDEX idx_search_name_-partition-_place_id ON search_name_-partition- USING BTREE (place_id);
CREATE INDEX idx_search_name_-partition-_centroid ON search_name_-partition- USING GIST (centroid);
CREATE INDEX idx_search_name_-partition-_name_vector ON search_name_-partition- USING GIN (name_vector) WITH (fastupdate = off);
CREATE TABLE search_name_-partition- () INHERITS (search_name_blank) {ts:address-data};
CREATE INDEX idx_search_name_-partition-_place_id ON search_name_-partition- USING BTREE (place_id) {ts:address-index};
CREATE INDEX idx_search_name_-partition-_centroid ON search_name_-partition- USING GIST (centroid) {ts:address-index};
CREATE INDEX idx_search_name_-partition-_name_vector ON search_name_-partition- USING GIN (name_vector) WITH (fastupdate = off) {ts:address-index};
CREATE TABLE location_property_-partition- () INHERITS (location_property);
CREATE INDEX idx_location_property_-partition-_place_id ON location_property_-partition- USING BTREE (place_id);
CREATE INDEX idx_location_property_-partition-_parent_place_id ON location_property_-partition- USING BTREE (parent_place_id);
CREATE INDEX idx_location_property_-partition-_housenumber_parent_place_id ON location_property_-partition- USING BTREE (parent_place_id, housenumber);
CREATE TABLE location_property_-partition- () INHERITS (location_property) {ts:aux-data};
CREATE INDEX idx_location_property_-partition-_place_id ON location_property_-partition- USING BTREE (place_id) {ts:aux-index};
CREATE INDEX idx_location_property_-partition-_parent_place_id ON location_property_-partition- USING BTREE (parent_place_id) {ts:aux-index};
CREATE INDEX idx_location_property_-partition-_housenumber_parent_place_id ON location_property_-partition- USING BTREE (parent_place_id, housenumber) {ts:aux-index};
CREATE TABLE location_road_-partition- (
partition integer,
place_id BIGINT,
country_code VARCHAR(2)
);
) {ts:address-data};
SELECT AddGeometryColumn('location_road_-partition-', 'geometry', 4326, 'GEOMETRY', 2);
CREATE INDEX idx_location_road_-partition-_geometry ON location_road_-partition- USING GIST (geometry);
CREATE INDEX idx_location_road_-partition-_place_id ON location_road_-partition- USING BTREE (place_id);
CREATE INDEX idx_location_road_-partition-_geometry ON location_road_-partition- USING GIST (geometry) {ts:address-index};
CREATE INDEX idx_location_road_-partition-_place_id ON location_road_-partition- USING BTREE (place_id) {ts:address-index};
-- end

14
sql/postgis_15_aux.sql Normal file
View File

@@ -0,0 +1,14 @@
-- Splits the line at the given point and returns the two parts
-- in a multilinestring.
CREATE OR REPLACE FUNCTION split_line_on_node(line GEOMETRY, point GEOMETRY)
RETURNS GEOMETRY
AS $$
DECLARE
frac FLOAT;
BEGIN
frac := ST_Line_Locate_Point(line, point);
RETURN ST_Collect(ST_Line_Substring(line, 0, frac),
ST_Line_Substring(line, frac, 1));
END
$$
LANGUAGE plpgsql;

10
sql/postgis_20_aux.sql Normal file
View File

@@ -0,0 +1,10 @@
-- Splits the line at the given point and returns the two parts
-- in a multilinestring.
CREATE OR REPLACE FUNCTION split_line_on_node(line GEOMETRY, point GEOMETRY)
RETURNS GEOMETRY
AS $$
BEGIN
RETURN ST_Split(ST_Snap(line, point, 0.0005), point);
END;
$$
LANGUAGE plpgsql;

View File

@@ -1,10 +1,10 @@
drop table import_status;
drop table if exists import_status;
CREATE TABLE import_status (
lastimportdate timestamp NOT NULL
);
GRANT SELECT ON import_status TO "www-data" ;
GRANT SELECT ON import_status TO "{www-user}" ;
drop table import_osmosis_log;
drop table if exists import_osmosis_log;
CREATE TABLE import_osmosis_log (
batchend timestamp,
batchsize integer,
@@ -13,7 +13,7 @@ CREATE TABLE import_osmosis_log (
event text
);
drop table import_npi_log;
drop table if exists import_npi_log;
CREATE TABLE import_npi_log (
npiid integer,
batchend timestamp,
@@ -32,9 +32,9 @@ CREATE TABLE query_log (
results integer
);
CREATE INDEX idx_query_log ON query_log USING BTREE (starttime);
GRANT SELECT ON query_log TO "www-data" ;
GRANT INSERT ON query_log TO "www-data" ;
GRANT UPDATE ON query_log TO "www-data" ;
GRANT SELECT ON query_log TO "{www-user}" ;
GRANT INSERT ON query_log TO "{www-user}" ;
GRANT UPDATE ON query_log TO "{www-user}" ;
CREATE TABLE new_query_log (
type text,
@@ -49,23 +49,16 @@ CREATE TABLE new_query_log (
secret text
);
CREATE INDEX idx_new_query_log_starttime ON new_query_log USING BTREE (starttime);
GRANT INSERT ON new_query_log TO "www-data" ;
GRANT UPDATE ON new_query_log TO "www-data" ;
GRANT SELECT ON new_query_log TO "www-data" ;
GRANT INSERT ON new_query_log TO "{www-user}" ;
GRANT UPDATE ON new_query_log TO "{www-user}" ;
GRANT SELECT ON new_query_log TO "{www-user}" ;
GRANT SELECT ON TABLE country_name TO "{www-user}";
GRANT SELECT ON TABLE gb_postcode TO "{www-user}";
create view vw_search_query_log as SELECT substr(query, 1, 50) AS query, starttime, endtime - starttime AS duration, substr(useragent, 1, 20) as
useragent, language, results, ipaddress FROM new_query_log WHERE type = 'search' ORDER BY starttime DESC;
--drop table IF EXISTS report_log;
CREATE TABLE report_log (
starttime timestamp,
ipaddress text,
query text,
description text,
email text
);
GRANT INSERT ON report_log TO "www-data" ;
drop table IF EXISTS word;
CREATE TABLE word (
word_id INTEGER,
@@ -76,17 +69,17 @@ CREATE TABLE word (
country_code varchar(2),
search_name_count INTEGER,
operator TEXT
);
CREATE INDEX idx_word_word_token on word USING BTREE (word_token);
GRANT SELECT ON word TO "www-data" ;
DROP SEQUENCE seq_word;
) {ts:search-data};
CREATE INDEX idx_word_word_token on word USING BTREE (word_token) {ts:search-index};
GRANT SELECT ON word TO "{www-user}" ;
DROP SEQUENCE IF EXISTS seq_word;
CREATE SEQUENCE seq_word start 1;
drop table IF EXISTS location_area CASCADE;
CREATE TABLE location_area (
partition integer,
place_id BIGINT,
country_code VARCHAR(2),
country_code VARCHAR(2),
keywords INTEGER[],
rank_search INTEGER NOT NULL,
rank_address INTEGER NOT NULL,
@@ -96,8 +89,6 @@ SELECT AddGeometryColumn('location_area', 'centroid', 4326, 'POINT', 2);
SELECT AddGeometryColumn('location_area', 'geometry', 4326, 'GEOMETRY', 2);
CREATE TABLE location_area_large () INHERITS (location_area);
CREATE TABLE location_area_roadnear () INHERITS (location_area);
CREATE TABLE location_area_roadfar () INHERITS (location_area);
drop table IF EXISTS location_property CASCADE;
CREATE TABLE location_property (
@@ -113,13 +104,13 @@ CREATE TABLE location_property_aux () INHERITS (location_property);
CREATE INDEX idx_location_property_aux_place_id ON location_property_aux USING BTREE (place_id);
CREATE INDEX idx_location_property_aux_parent_place_id ON location_property_aux USING BTREE (parent_place_id);
CREATE INDEX idx_location_property_aux_housenumber_parent_place_id ON location_property_aux USING BTREE (parent_place_id, housenumber);
GRANT SELECT ON location_property_aux TO "www-data";
GRANT SELECT ON location_property_aux TO "{www-user}";
CREATE TABLE location_property_tiger () INHERITS (location_property);
CREATE INDEX idx_location_property_tiger_place_id ON location_property_tiger USING BTREE (place_id);
CREATE INDEX idx_location_property_tiger_parent_place_id ON location_property_tiger USING BTREE (parent_place_id);
CREATE INDEX idx_location_property_tiger_housenumber_parent_place_id ON location_property_tiger USING BTREE (parent_place_id, housenumber);
GRANT SELECT ON location_property_tiger TO "www-data";
CREATE TABLE location_property_tiger () INHERITS (location_property) {ts:aux-data};
CREATE INDEX idx_location_property_tiger_place_id ON location_property_tiger USING BTREE (place_id) {ts:aux-index};
CREATE INDEX idx_location_property_tiger_parent_place_id ON location_property_tiger USING BTREE (parent_place_id) {ts:aux-index};
CREATE INDEX idx_location_property_tiger_housenumber_parent_place_id ON location_property_tiger USING BTREE (parent_place_id, housenumber) {ts:aux-index};
GRANT SELECT ON location_property_tiger TO "{www-user}";
drop table IF EXISTS search_name;
CREATE TABLE search_name (
@@ -130,9 +121,9 @@ CREATE TABLE search_name (
country_code varchar(2),
name_vector integer[],
nameaddress_vector integer[]
);
) {ts:search-data};
SELECT AddGeometryColumn('search_name', 'centroid', 4326, 'GEOMETRY', 2);
CREATE INDEX idx_search_name_place_id ON search_name USING BTREE (place_id);
CREATE INDEX idx_search_name_place_id ON search_name USING BTREE (place_id) {ts:search-index};
drop table IF EXISTS place_addressline;
CREATE TABLE place_addressline (
@@ -142,46 +133,10 @@ CREATE TABLE place_addressline (
isaddress boolean,
distance float,
cached_rank_address integer
);
CREATE INDEX idx_place_addressline_place_id on place_addressline USING BTREE (place_id);
) {ts:search-data};
CREATE INDEX idx_place_addressline_place_id on place_addressline USING BTREE (place_id) {ts:search-index};
drop table IF EXISTS place_boundingbox CASCADE;
CREATE TABLE place_boundingbox (
place_id BIGINT,
minlat float,
maxlat float,
minlon float,
maxlon float,
numfeatures integer,
area float
);
SELECT AddGeometryColumn('place_boundingbox', 'outline', 4326, 'GEOMETRY', 2);
GRANT SELECT on place_boundingbox to "www-data" ;
GRANT INSERT on place_boundingbox to "www-data" ;
drop table IF EXISTS reverse_cache;
CREATE TABLE reverse_cache (
latlonzoomid integer,
country_code varchar(2),
place_id BIGINT
);
GRANT SELECT on reverse_cache to "www-data" ;
GRANT INSERT on reverse_cache to "www-data" ;
CREATE INDEX idx_reverse_cache_latlonzoomid ON reverse_cache USING BTREE (latlonzoomid);
drop table country;
CREATE TABLE country (
country_code varchar(2),
country_name hstore,
country_default_language_code varchar(2)
);
SELECT AddGeometryColumn('country', 'geometry', 4326, 'POLYGON', 2);
insert into country select iso3166::varchar(2), 'name:en'->cntry_name, null,
ST_Transform(geometryn(the_geom, generate_series(1, numgeometries(the_geom))), 4326) from worldboundaries;
CREATE INDEX idx_country_country_code ON country USING BTREE (country_code);
CREATE INDEX idx_country_geometry ON country USING GIST (geometry);
drop table placex;
drop table if exists placex;
CREATE TABLE placex (
place_id BIGINT NOT NULL,
partition integer,
@@ -196,29 +151,24 @@ CREATE TABLE placex (
wikipedia TEXT, -- calculated wikipedia article name (language:title)
geometry_sector INTEGER,
calculated_country_code varchar(2)
);
) {ts:search-data};
SELECT AddGeometryColumn('placex', 'centroid', 4326, 'GEOMETRY', 2);
CREATE UNIQUE INDEX idx_place_id ON placex USING BTREE (place_id);
CREATE INDEX idx_placex_osmid ON placex USING BTREE (osm_type, osm_id);
CREATE INDEX idx_placex_linked_place_id ON placex USING BTREE (linked_place_id);
CREATE INDEX idx_placex_rank_search ON placex USING BTREE (rank_search, geometry_sector);
CREATE INDEX idx_placex_geometry ON placex USING GIST (geometry);
CREATE INDEX idx_placex_adminname on placex USING BTREE (make_standard_name(name->'name'),rank_search) WHERE osm_type='N' and rank_search < 26;
CREATE UNIQUE INDEX idx_place_id ON placex USING BTREE (place_id) {ts:search-index};
CREATE INDEX idx_placex_osmid ON placex USING BTREE (osm_type, osm_id) {ts:search-index};
CREATE INDEX idx_placex_linked_place_id ON placex USING BTREE (linked_place_id) {ts:address-index};
CREATE INDEX idx_placex_rank_search ON placex USING BTREE (rank_search, geometry_sector) {ts:address-index};
CREATE INDEX idx_placex_geometry ON placex USING GIST (geometry) {ts:search-index};
CREATE INDEX idx_placex_adminname on placex USING BTREE (make_standard_name(name->'name'),rank_search) {ts:address-index} WHERE osm_type='N' and rank_search < 26;
--CREATE INDEX idx_placex_indexed ON placex USING BTREE (indexed);
--CREATE INDEX idx_placex_pendingbylatlon ON placex USING BTREE (geometry_index(geometry_sector,indexed,name),rank_search) where geometry_index(geometry_sector,indexed,name) IS NOT NULL;
DROP SEQUENCE seq_place;
DROP SEQUENCE IF EXISTS seq_place;
CREATE SEQUENCE seq_place start 1;
GRANT SELECT on placex to "www-data" ;
GRANT SELECT ON search_name to "www-data" ;
GRANT SELECT on place_addressline to "www-data" ;
GRANT SELECT ON seq_word to "www-data" ;
GRANT SELECT ON planet_osm_ways to "www-data" ;
GRANT SELECT ON planet_osm_rels to "www-data" ;
GRANT SELECT on location_area to "www-data" ;
GRANT SELECT on country to "www-data" ;
GRANT SELECT on placex to "{www-user}" ;
GRANT SELECT ON search_name to "{www-user}" ;
GRANT SELECT on place_addressline to "{www-user}" ;
GRANT SELECT ON seq_word to "{www-user}" ;
GRANT SELECT ON planet_osm_ways to "{www-user}" ;
GRANT SELECT ON planet_osm_rels to "{www-user}" ;
GRANT SELECT on location_area to "{www-user}" ;
-- insert creates the location tagbles, creates location indexes if indexed == true
CREATE TRIGGER placex_before_insert BEFORE INSERT ON placex
@@ -237,7 +187,7 @@ CREATE TRIGGER place_before_insert BEFORE INSERT ON place
FOR EACH ROW EXECUTE PROCEDURE place_insert();
drop index idx_placex_sector;
CREATE INDEX idx_placex_sector ON placex USING BTREE (geometry_sector,rank_address,osm_type,osm_id);
CREATE INDEX idx_placex_sector ON placex USING BTREE (geometry_sector,rank_address,osm_type,osm_id) {ts:address-index};
DROP SEQUENCE seq_postcodes;
CREATE SEQUENCE seq_postcodes start 1;
@@ -256,7 +206,7 @@ CREATE TABLE import_polygon_error (
SELECT AddGeometryColumn('import_polygon_error', 'prevgeometry', 4326, 'GEOMETRY', 2);
SELECT AddGeometryColumn('import_polygon_error', 'newgeometry', 4326, 'GEOMETRY', 2);
CREATE INDEX idx_import_polygon_error_osmid ON import_polygon_error USING BTREE (osm_type, osm_id);
GRANT SELECT ON import_polygon_error TO "www-data";
GRANT SELECT ON import_polygon_error TO "{www-user}";
drop table import_polygon_delete;
CREATE TABLE import_polygon_delete (
@@ -266,7 +216,7 @@ CREATE TABLE import_polygon_delete (
type TEXT NOT NULL
);
CREATE INDEX idx_import_polygon_delete_osmid ON import_polygon_delete USING BTREE (osm_type, osm_id);
GRANT SELECT ON import_polygon_delete TO "www-data";
GRANT SELECT ON import_polygon_delete TO "{www-user}";
drop sequence file;
CREATE SEQUENCE file start 1;

View File

@@ -1,9 +1,9 @@
CREATE INDEX idx_location_property_tiger_housenumber_parent_place_id_imp ON location_property_tiger_import (parent_place_id, housenumber);
CREATE UNIQUE INDEX idx_location_property_tiger_place_id_imp ON location_property_tiger_import (place_id);
CREATE INDEX idx_location_property_tiger_housenumber_parent_place_id_imp ON location_property_tiger_import (parent_place_id, housenumber) {ts:aux-index};
CREATE UNIQUE INDEX idx_location_property_tiger_place_id_imp ON location_property_tiger_import (place_id) {ts:aux-index};
GRANT SELECT ON location_property_tiger_import TO "www-data";
GRANT SELECT ON location_property_tiger_import TO "{www-user}";
DROP TABLE location_property_tiger;
DROP TABLE IF EXISTS location_property_tiger;
ALTER TABLE location_property_tiger_import RENAME TO location_property_tiger;
ALTER INDEX idx_location_property_tiger_housenumber_parent_place_id_imp RENAME TO idx_location_property_tiger_housenumber_parent_place_id;

View File

@@ -1,5 +1,5 @@
DROP TABLE IF EXISTS location_property_tiger_import;
CREATE TABLE location_property_tiger_import () INHERITS (location_property);
CREATE TABLE location_property_tiger_import () INHERITS (location_property) {ts:aux-data};
CREATE OR REPLACE FUNCTION tigger_create_interpolation(linegeo GEOMETRY, in_startnumber INTEGER,
in_endnumber INTEGER, interpolationtype TEXT,

14
sql/words.sql Normal file
View File

@@ -0,0 +1,14 @@
CREATE TABLE word_frequencies AS
(SELECT unnest(make_keywords(v)) as id, sum(count) as count
FROM (select svals(name) as v, count(*)from place group by v) cnt
WHERE v is not null
GROUP BY id);
select count(make_keywords(v)) from (select distinct postcode as v from place) as w where v is not null;
select count(getorcreate_housenumber_id(make_standard_name(v))) from (select distinct housenumber as v from place where housenumber is not null) as w;
-- copy the word frequencies
update word set search_name_count = count from word_frequencies wf where wf.id = word.word_id;
-- and drop the temporary frequency table again
drop table word_frequencies;

View File

@@ -15,13 +15,17 @@ Prerequisites
* nose (https://nose.readthedocs.org)
* pytidylib (http://countergram.com/open-source/pytidylib)
* haversine (https://github.com/mapado/haversine)
* shapely (https://github.com/Toblerity/Shapely)
Usage
=====
* get prerequisites
# on a fresh Ubuntu LTS 14.04 you'll also need these system-wide packages
[sudo] apt-get install python-dev python-pip python-Levenshtein tidy
[sudo] pip install lettuce nose pytidylib haversine psycopg2
[sudo] pip install lettuce nose pytidylib haversine psycopg2 shapely
* run the tests

View File

@@ -1,19 +1,6 @@
Feature: API regression tests
Tests error cases reported in tickets.
@poldi-only
Scenario Outline: github #36
When sending json search query "<query>" with address
Then result addresses contain
| ID | road | city
| 0 | Seegasse | Gemeinde Wieselburg-Land
Examples:
| query
| Seegasse, Gemeinde Wieselburg-Land
| Seegasse, Wieselburg-Land
| Seegasse, Wieselburg
Scenario: trac #2430
When sending json search query "89 River Avenue, Hoddesdon, Hertfordshire, EN11 0JT"
Then at least 1 result is returned
@@ -177,3 +164,55 @@ Feature: API regression tests
Then results contain
| ID | class | latlon
| 0 | highway | 51.8324206,1.2447352 +-100m
Scenario Outline: trac #5025
When sending json search query "Kriegsstr <house_nr>, Karlsruhe" with address
Then result addresses contain
| house_number | road
| <house_nr> | Kriegsstraße
Examples:
| house_nr
| 5c
| 25
| 78
| 80
| 99
| 130
| 153
| 196
| 256
| 294
Scenario: trac #5238
Given the request parameters
| bounded | viewbox
| 1 | 0,0,-1,-1
When sending json search query "sy"
Then exactly 0 results are returned
Scenario: trac #5274
When sending json search query "Goedestraat 41-BS, Utrecht" with address
Then result addresses contain
| house_number | road | city
| 41-BS | Goedestraat | Utrecht
@poldi-only
Scenario Outline: github #36
When sending json search query "<query>" with address
Then result addresses contain
| ID | road | city
| 0 | Seegasse | Wieselburg-Land
Examples:
| query
| Seegasse, Gemeinde Wieselburg-Land
| Seegasse, Wieselburg-Land
| Seegasse, Wieselburg
Scenario: github #190
When looking up place N257363453
Then the results contain
| osm_type | osm_id | latlon
| node | 257363453 | 35.8404121,128.5586643 +-100m

View File

@@ -50,3 +50,48 @@ Feature: Simple Reverse Tests
Then the result is valid json
When looking up jsonv2 coordinates 36.791966,127.171726
Then the result is valid json
Scenario: Missing lon parameter
Given the request parameters
| lat
| 51.51
When sending an API call reverse
Then exactly 0 results are returned
Scenario: Missing lat parameter
Given the request parameters
| lon
| -79.39114
When sending an API call reverse
Then exactly 0 results are returned
Scenario: Missing osm_id parameter
Given the request parameters
| osm_type
| N
When sending an API call reverse
Then exactly 0 results are returned
Scenario: Missing osm_type parameter
Given the request parameters
| osm_id
| 3498564
When sending an API call reverse
Then exactly 0 results are returned
Scenario Outline: Bad format for lat or lon
Given the request parameters
| lat | lon |
| <lat> | <lon> |
When sending an API call reverse
Then exactly 0 results are returned
Examples:
| lat | lon
| 48.9660 | 8,4482
| 48,9660 | 8.4482
| 48,9660 | 8,4482
| 48.966.0 | 8.4482
| 48.966 | 8.448.2
| Nan | 8.448
| 48.966 | Nan

View File

@@ -16,17 +16,17 @@ Feature: Search queries
Scenario: House number search for non-street address
Given the request parameters
| accept-language
| en
When sending json search query "4 Pomocnia, Poland" with address
Then address of result 0 is
| en
When sending json search query "4 Pomocnia, Pokrzywnica, Poland" with address
Then address of result 0 contains
| type | value
| house_number | 4
| suburb | Pomocnia
| county | gmina Pokrzywnica
| state | Masovian Voivodeship
| postcode | 06-121
| country | Poland
| country_code | pl
Then address of result 0 does not contain road
Scenario: House number interpolation even
Given the request parameters
@@ -56,10 +56,12 @@ Feature: Search queries
| country | Canada
| country_code | ca
@Tiger
Scenario: TIGER house number
When sending json search query "3 West Victory Way, Craig"
Then result 0 has not attributes osm_id,osm_type
@Tiger
Scenario: TIGER house number (road fallback)
When sending json search query "3030 West Victory Way, Craig"
Then result 0 has attributes osm_id,osm_type

View File

@@ -2,6 +2,9 @@ Feature: Result order for Geocoding
Testing that importance ordering returns sensible results
Scenario Outline: city order in street search
Given the request parameters
| limit
| 100
When sending json search query "<street>, <city>" with address
Then address of result 0 contains
| type | value

View File

@@ -27,9 +27,9 @@ Feature: Search queries
Scenario: XML search with addressdetails
When sending xml search query "Inuvik" with address
Then address of result 0 is
Then address of result 0 contains
| type | value
| town | Inuvik
| city | Inuvik
| state | Northwest Territories
| country | Canada
| country_code | ca
@@ -41,7 +41,7 @@ Feature: Search queries
| 0 | leisure | hackerspace
And result addresses contain
| ID | address29
| 0 | foobar
| 0 | Chaospott
And address of result 0 does not contain leisure,hackerspace
Scenario: Disabling deduplication

View File

@@ -166,6 +166,13 @@ Feature: Simple Tests
| attr | value
| exclude_place_ids | 123,76,342565
Scenario: Empty XML search with bad exluded place ids
Given the request parameters
| exclude_place_ids
| ,
When sending xml search query "jghrleoxsbwjer"
Then result header has no attribute exclude_place_ids
Scenario Outline: Wrapping of legal jsonp search requests
Given the request parameters
| json_callback

View File

@@ -0,0 +1,441 @@
@DB
Feature: Import of address interpolations
Tests that interpolated addresses are added correctly
Scenario: Simple even two point interpolation
Given the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | 1 1
| 2 | place | house | 6 | 1 1.001
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | houses | even | 1 1, 1 1.001
And the ways
| id | nodes
| 1 | 1,2
When importing
Then way 1 expands to housenumbers
| housenumber | centroid
| 4 | 1,1.0005
Scenario: Simple even two point interpolation with zero beginning
Given the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 0 | 1 1
| 2 | place | house | 8 | 1 1.001
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | houses | even | 1 1, 1 1.001
And the ways
| id | nodes
| 1 | 1,2
When importing
Then way 1 expands to housenumbers
| housenumber | centroid
| 2 | 1,1.00025
| 4 | 1,1.0005
| 6 | 1,1.00075
Scenario: Backwards even two point interpolation
Given the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | 1 1
| 2 | place | house | 6 | 1 1.001
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | houses | even | 1 1.001, 1 1
And the ways
| id | nodes
| 1 | 2,1
When importing
Then way 1 expands to housenumbers
| housenumber | centroid
| 4 | 1,1.0005
Scenario: Even two point interpolation with odd beginning
Given the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 11 | 1 1
| 2 | place | house | 16 | 1 1.001
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | houses | even | 1 1, 1 1.001
And the ways
| id | nodes
| 1 | 1,2
When importing
Then way 1 expands to housenumbers
| housenumber | centroid
| 12 | 1,1.0002
| 14 | 1,1.0006
Scenario: Even two point interpolation with odd end
Given the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 10 | 1 1
| 2 | place | house | 15 | 1 1.001
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | houses | even | 1 1, 1 1.001
And the ways
| id | nodes
| 1 | 1,2
When importing
Then way 1 expands to housenumbers
| housenumber | centroid
| 12 | 1,1.0004
| 14 | 1,1.0008
Scenario: Reverse even two point interpolation with odd beginning
Given the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 11 | 1 1
| 2 | place | house | 16 | 1 1.001
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | houses | even | 1 1.001, 1 1
And the ways
| id | nodes
| 1 | 2,1
When importing
Then way 1 expands to housenumbers
| housenumber | centroid
| 12 | 1,1.0002
| 14 | 1,1.0006
Scenario: Reverse even two point interpolation with odd end
Given the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 10 | 1 1
| 2 | place | house | 15 | 1 1.001
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | houses | even | 1 1.001, 1 1
And the ways
| id | nodes
| 1 | 2,1
When importing
Then way 1 expands to housenumbers
| housenumber | centroid
| 12 | 1,1.0004
| 14 | 1,1.0008
Scenario: Simple odd two point interpolation
Given the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 1 | 1 1
| 2 | place | house | 11 | 1 1.001
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | houses | odd | 1 1, 1 1.001
And the ways
| id | nodes
| 1 | 1,2
When importing
Then way 1 expands to housenumbers
| housenumber | centroid
| 3 | 1,1.0002
| 5 | 1,1.0004
| 7 | 1,1.0006
| 9 | 1,1.0008
Scenario: Odd two point interpolation with even beginning
Given the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | 1 1
| 2 | place | house | 7 | 1 1.001
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | houses | odd | 1 1, 1 1.001
And the ways
| id | nodes
| 1 | 1,2
When importing
Then way 1 expands to housenumbers
| housenumber | centroid
| 3 | 1,1.0002
| 5 | 1,1.0006
Scenario: Simple all two point interpolation
Given the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 1 | 1 1
| 2 | place | house | 3 | 1 1.001
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | houses | all | 1 1, 1 1.001
And the ways
| id | nodes
| 1 | 1,2
When importing
Then way 1 expands to housenumbers
| housenumber | centroid
| 2 | 1,1.0005
Scenario: Simple numbered two point interpolation
Given the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 3 | 1 1
| 2 | place | house | 9 | 1 1.001
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | houses | 3 | 1 1, 1 1.001
And the ways
| id | nodes
| 1 | 1,2
When importing
Then way 1 expands to housenumbers
| housenumber | centroid
| 6 | 1,1.0005
Scenario: Even two point interpolation with intermediate empty node
Given the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | 1 1
| 2 | place | house | 10 | 1.001 1.001
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | houses | even | 1 1, 1 1.001, 1.001 1.001
And the ways
| id | nodes
| 1 | 1,3,2
When importing
Then way 1 expands to housenumbers
| housenumber | centroid
| 4 | 1,1.0005
| 6 | 1,1.001
| 8 | 1.0005,1.001
Scenario: Even two point interpolation with intermediate duplicated empty node
Given the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | 1 1
| 2 | place | house | 10 | 1.001 1.001
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | houses | even | 1 1, 1 1.001, 1.001 1.001
And the ways
| id | nodes
| 1 | 1,3,3,2
When importing
Then way 1 expands to housenumbers
| housenumber | centroid
| 4 | 1,1.0005
| 6 | 1,1.001
| 8 | 1.0005,1.001
Scenario: Simple even three point interpolation
Given the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | 1 1
| 2 | place | house | 14 | 1.001 1.001
| 3 | place | house | 10 | 1 1.001
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | houses | even | 1 1, 1 1.001, 1.001 1.001
And the ways
| id | nodes
| 1 | 1,3,2
When importing
Then way 1 expands to housenumbers
| housenumber | centroid
| 4 | 1,1.00025
| 6 | 1,1.0005
| 8 | 1,1.00075
| 12 | 1.0005,1.001
Scenario: Simple even four point interpolation
Given the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | 1 1
| 2 | place | house | 14 | 1.001 1.001
| 3 | place | house | 10 | 1 1.001
| 4 | place | house | 18 | 1.001 1.002
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | houses | even | 1 1, 1 1.001, 1.001 1.001, 1.001 1.002
And the ways
| id | nodes
| 1 | 1,3,2,4
When importing
Then way 1 expands to housenumbers
| housenumber | centroid
| 4 | 1,1.00025
| 6 | 1,1.0005
| 8 | 1,1.00075
| 12 | 1.0005,1.001
| 16 | 1.001,1.0015
Scenario: Reverse simple even three point interpolation
Given the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | 1 1
| 2 | place | house | 14 | 1.001 1.001
| 3 | place | house | 10 | 1 1.001
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | houses | even | 1.001 1.001, 1 1.001, 1 1
And the ways
| id | nodes
| 1 | 2,3,1
When importing
Then way 1 expands to housenumbers
| housenumber | centroid
| 4 | 1,1.00025
| 6 | 1,1.0005
| 8 | 1,1.00075
| 12 | 1.0005,1.001
Scenario: Even three point interpolation with odd center point
Given the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | 1 1
| 2 | place | house | 8 | 1.001 1.001
| 3 | place | house | 7 | 1 1.001
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | houses | even | 1 1, 1 1.001, 1.001 1.001
And the ways
| id | nodes
| 1 | 1,3,2
When importing
Then way 1 expands to housenumbers
| housenumber | centroid
| 4 | 1,1.0004
| 6 | 1,1.0008
Scenario: Interpolation on self-intersecting way
Given the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | 0 0
| 2 | place | house | 6 | 0 0.001
| 3 | place | house | 10 | 0 0.002
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | houses | even | 0 0, 0 0.001, 0 0.002, 0 0.001
And the ways
| id | nodes
| 1 | 1,2,3,2
When importing
Then way 1 expands to housenumbers
| housenumber | centroid
| 4 | 0,0.0005
| 8 | 0,0.0015
Scenario: Interpolation on self-intersecting way II
Given the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | 0 0
| 2 | place | house | 6 | 0 0.001
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | houses | even | 0 0, 0 0.001, 0 0.002, 0 0.001
And the ways
| id | nodes
| 1 | 1,2,3,2
When importing
Then way 1 expands to housenumbers
| housenumber | centroid
| 4 | 0,0.0005
Scenario: addr:street on interpolation way
Given the scene parallel-road
And the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | :n-middle-w
| 2 | place | house | 6 | :n-middle-e
| 3 | place | house | 12 | :n-middle-w
| 4 | place | house | 16 | :n-middle-e
And the place ways
| osm_id | class | type | housenumber | street | geometry
| 10 | place | houses | even | | :w-middle
| 11 | place | houses | even | Cloud Street | :w-middle
And the place ways
| osm_id | class | type | name | geometry
| 2 | highway | tertiary | 'name' : 'Sun Way' | :w-north
| 3 | highway | tertiary | 'name' : 'Cloud Street' | :w-south
And the ways
| id | nodes
| 10 | 1,100,101,102,2
| 11 | 3,200,201,202,4
When importing
Then table placex contains
| object | parent_place_id
| N1 | W2
| N2 | W2
| N3 | W3
| N4 | W3
| W10 | W2
| W11 | W3
And way 10 expands exactly to housenumbers 4
And way 11 expands exactly to housenumbers 14
Scenario: addr:street on housenumber way
Given the scene parallel-road
And the place nodes
| osm_id | class | type | housenumber | street | geometry
| 1 | place | house | 2 | | :n-middle-w
| 2 | place | house | 6 | | :n-middle-e
| 3 | place | house | 12 | Cloud Street | :n-middle-w
| 4 | place | house | 16 | Cloud Street | :n-middle-e
And the place ways
| osm_id | class | type | housenumber | geometry
| 10 | place | houses | even | :w-middle
| 11 | place | houses | even | :w-middle
And the place ways
| osm_id | class | type | name | geometry
| 2 | highway | tertiary | 'name' : 'Sun Way' | :w-north
| 3 | highway | tertiary | 'name' : 'Cloud Street' | :w-south
And the ways
| id | nodes
| 10 | 1,100,101,102,2
| 11 | 3,200,201,202,4
When importing
Then table placex contains
| object | parent_place_id
| N1 | W2
| N2 | W2
| N3 | W3
| N4 | W3
| W10 | W2
| W11 | W3
And way 10 expands exactly to housenumbers 4
And way 11 expands exactly to housenumbers 14
Scenario: Geometry of points and way don't match (github #253)
Given the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 10 | 144.9632341 -37.76163
| 2 | place | house | 6 | 144.9630541 -37.7628174
| 3 | shop | supermarket | 2 | 144.9629794 -37.7630755
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | houses | even | 144.9632341 -37.76163,144.9630541 -37.7628172,144.9629794 -37.7630755
And the ways
| id | nodes
| 1 | 1,2,3
When importing
Then way 1 expands to housenumbers
| housenumber | centroid
| 4 | 144.963016723312,-37.7629464422819+-0.000005
| 8 | 144.9631440856,-37.762223694978+-0.000005
Scenario: Place with missing address information
Given the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 23 | 0.0001 0.0001
| 2 | amenity | school | | 0.0001 0.0002
| 3 | place | house | 29 | 0.0001 0.0004
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | houses | odd | 0.0001 0.0001,0.0001 0.0002,0.0001 0.0004
And the ways
| id | nodes
| 1 | 1,2,3
When importing
Then way 1 expands to housenumbers
| housenumber | centroid
| 25 | 0.0001,0.0002
| 27 | 0.0001,0.0003

View File

@@ -2,6 +2,20 @@
Feature: Linking of places
Tests for correctly determining linked places
Scenario: Only address-describing places can be linked
Given the scene way-area-with-center
And the place areas
| osm_type | osm_id | class | type | name | geometry
| R | 13 | landuse | forest | Garbo | :area
And the place nodes
| osm_id | class | type | name | geometry
| 256 | natural | peak | Garbo | :inner-C
When importing
Then table placex contains
| object | linked_place_id
| R13 | None
| N256 | None
Scenario: Waterways are linked when in waterway relations
Given the scene split-road
And the place ways

View File

@@ -167,15 +167,6 @@ Feature: Import and search of names
| name:fi | finnish
| name:de | local
Scenario: Landuse without name are ignored
Given the place areas
| osm_type | osm_id | class | type | geometry
| R | 1 | natural | meadow | (0 0, 1 0, 1 1, 0 1, 0 0)
| R | 2 | landuse | industrial | (0 0, -1 0, -1 -1, 0 -1, 0 0)
When importing
Then table placex has no entry for R1
And table placex has no entry for R2
Scenario: Landuse with name are found
Given the place areas
| osm_type | osm_id | class | type | name | geometry

View File

@@ -389,7 +389,7 @@ Feature: Parenting of objects
| N3 | W2 | None | nowhere | None
### Scenario 20
Scenario: POIs parent a road if and only if they are attached to it
Scenario: POIs parent a road if they are attached to it
Given the scene points-on-roads
And the named place nodes
| osm_id | class | type | street | geometry
@@ -408,8 +408,8 @@ Feature: Parenting of objects
When importing
Then table placex contains
| object | parent_place_id
| N1 | W2
| N2 | W1
| N1 | W1
| N2 | W2
| N3 | W1
| N4 | W2

View File

@@ -242,37 +242,6 @@ Feature: Import into placex
| R22 | 12 | 0
| R23 | 20 | 0
Scenario Outline: minor highways droped without name, included with
Given the scene roads-with-pois
And a wiped database
And the place ways
| osm_id | class | type | geometry
| 1 | highway | <type> | :w-south
And the named place ways
| osm_id | class | type | geometry
| 2 | highway | <type> | :w-north
When importing
Then table placex has no entry for W1
And table placex contains
| object | rank_search | rank_address
| W2 | <rank> | <rank>
Examples:
| type | rank
| service | 27
| cycleway | 27
| path | 27
| footway | 27
| steps | 27
| bridleway | 27
| track | 26
| byway | 26
| motorway_link | 27
| primary_link | 27
| trunk_link | 27
| secondary_link| 27
| tertiary_link | 27
Scenario: search and address ranks for highways correctly assigned
Given the scene roads-with-pois
And the place nodes
@@ -298,77 +267,43 @@ Feature: Import into placex
| W6 | 26 | 26
Scenario: rank and inclusion of landuses
Given the place nodes
| osm_id | class | type
| 1 | landuse | residential
And the named place nodes
| osm_id | class | type
| osm_id | class | type
| 2 | landuse | residential
And the place ways
| osm_id | class | type | geometry
| 1 | landuse | residential | 0 0, 0 1
And the named place ways
| osm_id | class | type | geometry
| 2 | landuse | residential | 1 1, 1 1.1
And the place areas
| osm_type | osm_id | class | type | geometry
| W | 3 | landuse | residential | poly-area:0.1
| R | 1 | landuse | residential | poly-area:0.01
| R | 10 | landuse | residential | poly-area:0.5
And the named place areas
| osm_type | osm_id | class | type | geometry
| W | 4 | landuse | residential | poly-area:0.1
| R | 2 | landuse | residential | poly-area:0.05
| R | 3 | landuse | forrest | poly-area:0.5
When importing
Then table placex has no entry for N1
And table placex has no entry for W1
And table placex has no entry for W3
And table placex has no entry for R1
And table placex has no entry for R10
And table placex contains
| object | rank_search | rank_address
| N2 | 30 | 30
| W2 | 30 | 30
| W4 | 22 | 22
| R2 | 22 | 22
| R3 | 22 | 0
Scenario: rank and inclusion of naturals
Given the place nodes
| osm_id | class | type
| 1 | natural | peak
| 3 | natural | volcano
And the named place nodes
| osm_id | class | type
| 2 | natural | peak
| 4 | natural | volcano
| 5 | natural | foobar
And the place ways
| osm_id | class | type | geometry
| 1 | natural | mountain_range | 10 10,11 11
And the named place ways
| osm_id | class | type | geometry
| 2 | natural | mountain_range | 12 12,11 11
| 3 | natural | foobar | 13 13,13.1 13
| 4 | natural | coastline | 14 14,14.1 14
And the place areas
| osm_type | osm_id | class | type | geometry
| R | 1 | natural | volcano | poly-area:0.1
| R | 2 | natural | volcano | poly-area:1.0
And the named place areas
| osm_type | osm_id | class | type | geometry
| R | 3 | natural | volcano | poly-area:0.1
| R | 4 | natural | foobar | poly-area:0.5
| R | 5 | natural | sea | poly-area:5.0
| R | 6 | natural | sea | poly-area:0.01
| R | 7 | natural | coastline | poly-area:1.0
When importing
Then table placex has no entry for N1
And table placex has no entry for N3
And table placex has no entry for W1
And table placex has no entry for R1
And table placex has no entry for R2
And table placex has no entry for R7
And table placex has no entry for W4
And table placex contains
| object | rank_search | rank_address
| N2 | 18 | 0
@@ -376,7 +311,7 @@ Feature: Import into placex
| N5 | 30 | 30
| W2 | 18 | 0
| R3 | 18 | 0
| R4 | 22 | 22
| R4 | 22 | 0
| R5 | 4 | 4
| R6 | 4 | 4
| W3 | 30 | 30

View File

@@ -0,0 +1,167 @@
@DB
Feature: Update of address interpolations
Test the interpolated address are updated correctly
Scenario: addr:street added to interpolation
Given the scene parallel-road
And the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | :n-middle-w
| 2 | place | house | 6 | :n-middle-e
And the place ways
| osm_id | class | type | housenumber | geometry
| 10 | place | houses | even | :w-middle
And the place ways
| osm_id | class | type | name | geometry
| 2 | highway | unclassified | 'name' : 'Sun Way' | :w-north
| 3 | highway | unclassified | 'name' : 'Cloud Street' | :w-south
And the ways
| id | nodes
| 10 | 1,100,101,102,2
When importing
Then table placex contains
| object | parent_place_id
| N1 | W2
| N2 | W2
| W10 | W2
And way 10 expands exactly to housenumbers 4
When updating place ways
| osm_id | class | type | housenumber | street | geometry
| 10 | place | houses | even | Cloud Street | :w-middle
Then way 10 expands exactly to housenumbers 4
And table placex contains
| object | parent_place_id
| N1 | W3
| N2 | W3
| W10 | W3
@Fail
Scenario: addr:street added to housenumbers
Given the scene parallel-road
And the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | :n-middle-w
| 2 | place | house | 6 | :n-middle-e
And the place ways
| osm_id | class | type | housenumber | geometry
| 10 | place | houses | even | :w-middle
And the place ways
| osm_id | class | type | name | geometry
| 2 | highway | unclassified | 'name' : 'Sun Way' | :w-north
| 3 | highway | unclassified | 'name' : 'Cloud Street' | :w-south
And the ways
| id | nodes
| 10 | 1,100,101,102,2
When importing
Then table placex contains
| object | parent_place_id
| N1 | W2
| N2 | W2
| W10 | W2
And way 10 expands exactly to housenumbers 4
When updating place nodes
| osm_id | class | type | street | housenumber | geometry
| 1 | place | house | Cloud Street| 2 | :n-middle-w
| 2 | place | house | Cloud Street| 6 | :n-middle-e
Then way 10 expands exactly to housenumbers 4
And table placex contains
| object | parent_place_id
| N1 | W3
| N2 | W3
| W10 | W3
Scenario: interpolation tag removed
Given the scene parallel-road
And the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | :n-middle-w
| 2 | place | house | 6 | :n-middle-e
And the place ways
| osm_id | class | type | housenumber | geometry
| 10 | place | houses | even | :w-middle
And the place ways
| osm_id | class | type | name | geometry
| 2 | highway | unclassified | 'name' : 'Sun Way' | :w-north
| 3 | highway | unclassified | 'name' : 'Cloud Street' | :w-south
And the ways
| id | nodes
| 10 | 1,100,101,102,2
When importing
Then table placex contains
| object | parent_place_id
| N1 | W2
| N2 | W2
| W10 | W2
And way 10 expands exactly to housenumbers 4
When marking for delete W10
Then way 10 expands to no housenumbers
And table placex contains
| object | parent_place_id
| N1 | W2
| N2 | W2
Scenario: referenced road added
Given the scene parallel-road
And the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | :n-middle-w
| 2 | place | house | 6 | :n-middle-e
And the place ways
| osm_id | class | type | housenumber | street | geometry
| 10 | place | houses | even | Cloud Street| :w-middle
And the place ways
| osm_id | class | type | name | geometry
| 2 | highway | unclassified | 'name' : 'Sun Way' | :w-north
And the ways
| id | nodes
| 10 | 1,100,101,102,2
When importing
Then table placex contains
| object | parent_place_id
| N1 | W2
| N2 | W2
| W10 | W2
And way 10 expands exactly to housenumbers 4
When updating place ways
| osm_id | class | type | name | geometry
| 3 | highway | unclassified | 'name' : 'Cloud Street' | :w-south
Then way 10 expands exactly to housenumbers 4
And table placex contains
| object | parent_place_id
| N1 | W3
| N2 | W3
| W10 | W3
Scenario: referenced road deleted
Given the scene parallel-road
And the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | :n-middle-w
| 2 | place | house | 6 | :n-middle-e
And the place ways
| osm_id | class | type | housenumber | street | geometry
| 10 | place | houses | even | Cloud Street| :w-middle
And the place ways
| osm_id | class | type | name | geometry
| 2 | highway | unclassified | 'name' : 'Sun Way' | :w-north
| 3 | highway | unclassified | 'name' : 'Cloud Street' | :w-south
And the ways
| id | nodes
| 10 | 1,100,101,102,2
When importing
Then table placex contains
| object | parent_place_id
| N1 | W3
| N2 | W3
| W10 | W3
And way 10 expands exactly to housenumbers 4
When marking for delete W3
Then way 10 expands exactly to housenumbers 4
And table placex contains
| object | parent_place_id
| N1 | W2
| N2 | W2
| W10 | W2

View File

@@ -2,20 +2,6 @@
Feature: Update of simple objects
Testing simple stuff
Scenario: Remove name from a landuse object
Given the place nodes
| osm_id | class | type | name
| 1 | landuse | wood | 'name' : 'Foo'
When importing
Then table placex contains
| object | class | type | name
| N1 | landuse| wood | 'name' : 'Foo'
When updating place nodes
| osm_id | class | type
| 1 | landuse | wood
Then table placex has no entry for N1
Scenario: Do delete small boundary features
Given the place areas
| osm_type | osm_id | class | type | admin_level | geometry

View File

@@ -0,0 +1,37 @@
@DB
Feature: Import of objects with broken geometries by osm2pgsql
@Fail
Scenario: Import way with double nodes
Given the osm nodes:
| id | geometry
| 100 | 0 0
| 101 | 0 0.1
| 102 | 0.1 0.2
And the osm ways:
| id | tags | nodes
| 1 | 'highway' : 'primary' | 100 101 101 102
When loading osm data
Then table place contains
| object | class | type | geometry
| W1 | highway | primary | (0 0, 0 0.1, 0.1 0.2)
Scenario: Import of ballon areas
Given the osm nodes:
| id | geometry
| 1 | 0 0
| 2 | 0 0.0001
| 3 | 0.00001 0.0001
| 4 | 0.00001 0
| 5 | -0.00001 0
And the osm ways:
| id | tags | nodes
| 1 | 'highway' : 'unclassified' | 1 2 3 4 1 5
| 2 | 'highway' : 'unclassified' | 1 2 3 4 1
| 3 | 'highway' : 'unclassified' | 1 2 3 4 3
When loading osm data
Then table place contains
| object | geometrytype
| W1 | ST_LineString
| W2 | ST_Polygon
| W3 | ST_LineString

View File

@@ -0,0 +1,537 @@
@DB
Feature: Tag evaluation
Tests if tags are correctly imported into the place table
Scenario Outline: Name tags
Given the osm nodes:
| id | tags
| 1 | 'highway' : 'yes', '<nametag>' : 'Foo'
When loading osm data
Then table place contains
| object | name
| N1 | '<nametag>' : 'Foo'
Examples:
| nametag
| ref
| int_ref
| nat_ref
| reg_ref
| loc_ref
| old_ref
| iata
| icao
| pcode:1
| pcode:2
| pcode:3
| name
| name:de
| name:bt-BR
| int_name
| int_name:xxx
| nat_name
| nat_name:fr
| reg_name
| reg_name:1
| loc_name
| loc_name:DE
| old_name
| old_name:v1
| alt_name
| alt_name:dfe
| alt_name_1
| official_name
| short_name
| short_name:CH
| addr:housename
| brand
Scenario Outline: operator only for shops and amenities
Given the osm nodes:
| id | tags
| 1 | 'highway' : 'yes', 'operator' : 'Foo', 'name' : 'null'
| 2 | 'shop' : 'grocery', 'operator' : 'Foo'
| 3 | 'amenity' : 'hospital', 'operator' : 'Foo'
| 4 | 'tourism' : 'hotel', 'operator' : 'Foo'
When loading osm data
Then table place contains
| object | name
| N1 | 'name' : 'null'
| N2 | 'operator' : 'Foo'
| N3 | 'operator' : 'Foo'
| N4 | 'operator' : 'Foo'
Scenario Outline: Ignored name tags
Given the osm nodes:
| id | tags
| 1 | 'highway' : 'yes', '<nametag>' : 'Foo', 'name' : 'real'
When loading osm data
Then table place contains
| object | name
| N1 | 'name' : 'real'
Examples:
| nametag
| name_de
| Name
| ref:de
| ref_de
| my:ref
| br:name
| name:prefix
Scenario: Special character in name tag
Given the osm nodes:
| id | tags
| 1 | 'highway' : 'yes', 'name: de' : 'Foo', 'name' : 'real'
| 2 | 'highway' : 'yes', 'name:\nde' : 'Foo', 'name' : 'real'
| 3 | 'highway' : 'yes', 'name:\tde' : 'Foo', 'name:\\' : 'real'
When loading osm data
Then table place contains
| object | name
| N1 | 'name:_de' : 'Foo', 'name' : 'real'
| N2 | 'name:_de' : 'Foo', 'name' : 'real'
| N3 | 'name:_de' : 'Foo', 'name:\\\\' : 'real'
Scenario Outline: Included places
Given the osm nodes:
| id | tags
| 1 | '<key>' : '<value>', 'name' : 'real'
When loading osm data
Then table place contains
| object | name
| N1 | 'name' : 'real'
Examples:
| key | value
| emergency | phone
| tourism | information
| historic | castle
| military | barracks
| natural | water
| highway | residential
| aerialway | station
| aeroway | way
| boundary | administrative
| craft | butcher
| leisure | playground
| office | bookmaker
| railway | rail
| shop | bookshop
| waterway | stream
| landuse | cemetry
| man_made | tower
| mountain_pass | yes
Scenario Outline: Bridges and Tunnels take special name tags
Given the osm nodes:
| id | tags
| 1 | 'highway' : 'road', '<key>' : 'yes', 'name' : 'Rd', '<key>:name' : 'My'
| 2 | 'highway' : 'road', '<key>' : 'yes', 'name' : 'Rd'
When loading osm data
Then table place contains
| object | class | type | name
| N1:highway | highway | road | 'name' : 'Rd'
| N1:<key> | <key> | yes | 'name' : 'My'
| N2:highway | highway | road | 'name' : 'Rd'
And table place has no entry for N2:<key>
Examples:
| key
| bridge
| tunnel
Scenario Outline: Excluded places
Given the osm nodes:
| id | tags
| 1 | '<key>' : '<value>', 'name' : 'real'
| 2 | 'highway' : 'motorway', 'name' : 'To Hell'
When loading osm data
Then table place has no entry for N1
Examples:
| key | value
| emergency | yes
| emergency | no
| tourism | yes
| tourism | no
| historic | yes
| historic | no
| military | yes
| military | no
| natural | yes
| natural | no
| highway | no
| highway | turning_circle
| highway | mini_roundabout
| highway | noexit
| highway | crossing
| aerialway | no
| aerialway | pylon
| man_made | survey_point
| man_made | cutline
| aeroway | no
| amenity | no
| bridge | no
| craft | no
| leisure | no
| office | no
| railway | no
| railway | level_crossing
| shop | no
| tunnel | no
| waterway | riverbank
Scenario: Some tags only are included when named
Given the osm nodes:
| id | tags
| 1 | '<key>' : '<value>'
| 2 | '<key>' : '<value>', 'name' : 'To Hell'
| 3 | '<key>' : '<value>', 'ref' : '123'
When loading osm data
Then table place has no entry for N1
And table place has no entry for N3
And table place contains
| object | class | type
| N2 | <key> | <value>
Examples:
| key | value
| landuse | residential
| natural | meadow
| highway | traffic_signals
| highway | service
| highway | cycleway
| highway | path
| highway | footway
| highway | steps
| highway | bridleway
| highway | track
| highway | byway
| highway | motorway_link
| highway | primary_link
| highway | trunk_link
| highway | secondary_link
| highway | tertiary_link
| railway | rail
| boundary | administrative
| waterway | stream
Scenario: named junctions are included if there is no other tag
Given the osm nodes:
| id | tags
| 1 | 'junction' : 'yes'
| 2 | 'highway' : 'secondary', 'junction' : 'roundabout', 'name' : 'To Hell'
| 3 | 'junction' : 'yes', 'name' : 'Le Croix'
When loading osm data
Then table place has no entry for N1
And table place has no entry for N2:junction
And table place contains
| object | class | type
| N3 | junction | yes
Scenario: Boundary with place tag
Given the osm nodes:
| id | geometry
| 200 | 0 0
| 201 | 0 1
| 202 | 1 1
| 203 | 1 0
And the osm ways:
| id | tags | nodes
| 2 | 'boundary' : 'administrative', 'place' : 'city', 'name' : 'Foo' | 200 201 202 203 200
| 4 | 'boundary' : 'administrative', 'place' : 'island','name' : 'Foo' | 200 201 202 203 200
| 20 | 'place' : 'city', 'name' : 'ngng' | 200 201 202 203 200
| 40 | 'place' : 'city', 'boundary' : 'statistical', 'name' : 'BB' | 200 201 202 203 200
When loading osm data
Then table place contains
| object | class | extratags | type
| W2 | boundary | 'place' : 'city' | administrative
| W4:boundary | boundary | None | administrative
| W4:place | place | None | island
| W20 | place | None | city
| W40:boundary | boundary | None | statistical
| W40:place | place | None | city
And table place has no entry for W2:place
Scenario Outline: Tags that describe a house
Given the osm nodes:
| id | tags
| 100 | '<key>' : '<value>'
| 999 | 'amenity' : 'prison', '<key>' : '<value>'
When loading osm data
Then table place contains
| object | class | type
| N100 | place | house
| N999 | amenity | prison
And table place has no entry for N100:<key>
And table place has no entry for N999:<key>
And table place has no entry for N999:place
Examples:
| key | value
| addr:housename | My Mansion
| addr:housenumber | 456
| addr:conscriptionnumber | 4
| addr:streetnumber | 4568765
Scenario: Only named with no other interesting tag
Given the osm nodes:
| id | tags
| 1 | 'landuse' : 'meadow'
| 2 | 'landuse' : 'residential', 'name' : 'important'
| 3 | 'landuse' : 'residential', 'name' : 'important', 'place' : 'hamlet'
When loading osm data
Then table place contains
| object | class | type
| N2 | landuse | residential
| N3 | place | hamlet
And table place has no entry for N1
And table place has no entry for N3:landuse
Scenario Outline: Import of postal codes
Given the osm nodes:
| id | tags
| 10 | 'highway' : 'secondary', '<key>' : '<value>'
| 11 | '<key>' : '<value>'
When loading osm data
Then table place contains
| object | class | type | postcode
| N10 | highway | secondary | <value>
| N11 | place | postcode | <value>
And table place has no entry for N10:place
Examples:
| key | value
| postal_code | 45736
| postcode | xxx
| addr:postcode | 564
| tiger:zip_left | 00011
| tiger:zip_right | 09123
Scenario: Import of street and place
Given the osm nodes:
| id | tags
| 10 | 'amenity' : 'hospital', 'addr:street' : 'Foo St'
| 20 | 'amenity' : 'hospital', 'addr:place' : 'Foo Town'
When loading osm data
Then table place contains
| object | class | type | street | addr_place
| N10 | amenity | hospital | Foo St | None
| N20 | amenity | hospital | None | Foo Town
Scenario Outline: Import of country
Given the osm nodes:
| id | tags
| 10 | 'place' : 'village', '<key>' : '<value>'
When loading osm data
Then table place contains
| object | class | type | country_code
| N10 | place | village | <value>
Examples:
| key | value
| country_code | us
| ISO3166-1 | XX
| is_in:country_code | __
| addr:country | ..
| addr:country_code | cv
Scenario Outline: Ignore country codes with wrong length
Given the osm nodes:
| id | tags
| 10 | 'place' : 'village', 'country_code' : '<value>'
When loading osm data
Then table place contains
| object | class | type | country_code
| N10 | place | village | None
Examples:
| value
| X
| x
| ger
| dkeufr
| d e
Scenario: Import of house numbers
Given the osm nodes:
| id | tags
| 10 | 'building' : 'yes', 'addr:housenumber' : '4b'
| 11 | 'building' : 'yes', 'addr:conscriptionnumber' : '003'
| 12 | 'building' : 'yes', 'addr:streetnumber' : '2345'
| 13 | 'building' : 'yes', 'addr:conscriptionnumber' : '3', 'addr:streetnumber' : '111'
When loading osm data
Then table place contains
| object | class | type | housenumber
| N10 | building | yes | 4b
| N11 | building | yes | 003
| N12 | building | yes | 2345
| N13 | building | yes | 3/111
Scenario: Import of address interpolations
Given the osm nodes:
| id | tags
| 10 | 'addr:interpolation' : 'odd'
| 11 | 'addr:housenumber' : '10', 'addr:interpolation' : 'odd'
| 12 | 'addr:interpolation' : 'odd', 'addr:housenumber' : '23'
When loading osm data
Then table place contains
| object | class | type | housenumber
| N10 | place | houses | odd
| N11 | place | houses | odd
| N12 | place | houses | odd
Scenario: Shorten tiger:county tags
Given the osm nodes:
| id | tags
| 10 | 'place' : 'village', 'tiger:county' : 'Feebourgh, AL'
| 11 | 'place' : 'village', 'addr:state' : 'Alabama', 'tiger:county' : 'Feebourgh, AL'
| 12 | 'place' : 'village', 'tiger:county' : 'Feebourgh'
When loading osm data
Then table place contains
| object | class | type | isin
| N10 | place | village | Feebourgh county
| N11 | place | village | Alabama,Feebourgh county
| N12 | place | village | Feebourgh county
Scenario Outline: Import of address tags
Given the osm nodes:
| id | tags
| 10 | 'place' : 'village', '<key>' : '<value>'
When loading osm data
Then table place contains
| object | class | type | isin
| N10 | place | village | <value>
Examples:
| key | value
| is_in | Stockholm, Sweden
| is_in:country | Xanadu
| addr:suburb | hinein
| addr:county | le havre
| addr:city | Sydney
| addr:state | Jura
Scenario: Import of admin level
Given the osm nodes:
| id | tags
| 10 | 'amenity' : 'hospital', 'admin_level' : '3'
| 11 | 'amenity' : 'hospital', 'admin_level' : 'b'
| 12 | 'amenity' : 'hospital'
| 13 | 'amenity' : 'hospital', 'admin_level' : '3.0'
When loading osm data
Then table place contains
| object | class | type | admin_level
| N10 | amenity | hospital | 3
| N11 | amenity | hospital | 100
| N12 | amenity | hospital | 100
| N13 | amenity | hospital | 3
Scenario: Import of extra tags
Given the osm nodes:
| id | tags
| 10 | 'tourism' : 'hotel', '<key>' : 'foo'
When loading osm data
Then table place contains
| object | class | type | extratags
| N10 | tourism | hotel | '<key>' : 'foo'
Examples:
| key
| tracktype
| traffic_calming
| service
| cuisine
| capital
| dispensing
| religion
| denomination
| sport
| internet_access
| lanes
| surface
| smoothness
| width
| est_width
| incline
| opening_hours
| collection_times
| service_times
| disused
| wheelchair
| sac_scale
| trail_visibility
| mtb:scale
| mtb:description
| wood
| drive_in
| access
| vehicle
| bicyle
| foot
| goods
| hgv
| motor_vehicle
| motor_car
| access:foot
| contact:phone
| drink:mate
| oneway
| date_on
| date_off
| day_on
| day_off
| hour_on
| hour_off
| maxweight
| maxheight
| maxspeed
| disused
| toll
| charge
| population
| description
| image
| attribution
| fax
| email
| url
| website
| phone
| real_ale
| smoking
| food
| camera
| brewery
| locality
| wikipedia
| wikipedia:de
Scenario: buildings
Given the osm nodes:
| id | tags
| 10 | 'tourism' : 'hotel', 'building' : 'yes'
| 11 | 'building' : 'house'
| 12 | 'building' : 'shed', 'addr:housenumber' : '1'
| 13 | 'building' : 'yes', 'name' : 'Das Haus'
| 14 | 'building' : 'yes', 'addr:postcode' : '12345'
When loading osm data
Then table place contains
| object | class | type
| N10 | tourism | hotel
| N12 | building| yes
| N13 | building| yes
| N14 | building| yes
And table place has no entry for N10:building
And table place has no entry for N11
Scenario: complete node entry
Given the osm nodes:
| id | tags
| 290393920 | 'addr:city':'Perpignan','addr:country':'FR','addr:housenumber':'43\\','addr:postcode':'66000','addr:street':'Rue Pierre Constant d`Ivry','source':'cadastre-dgi-fr source : Direction Générale des Impôts - Cadastre ; mise à jour :2008'
When loading osm data
Then table place contains
| object | class | type | housenumber
| N290393920 | place | house| 43\

View File

@@ -28,3 +28,125 @@ Scenario: Remove all members of a relation
When updating osm data
Then table place has no entry for R1
Scenario: Change type of a relation
Given the osm nodes:
| id | geometry
| 200 | 0 0
| 201 | 0 0.0001
| 202 | 0.0001 0.0001
| 203 | 0.0001 0
Given the osm ways:
| id | tags | nodes
| 2 | 'ref' : '45' | 200 201 202 203 200
Given the osm relations:
| id | tags | members
| 1 | 'type' : 'multipolygon', 'tourism' : 'hotel', 'name' : 'XZ' | W2
When loading osm data
Then table place contains
| object | class | type | name
| R1 | tourism | hotel | 'name' : 'XZ'
Given the osm relations:
| action | id | tags | members
| M | 1 | 'type' : 'multipolygon', 'amenity' : 'prison', 'name' : 'XZ' | W2
When updating osm data
Then table place has no entry for R1:tourism
And table place contains
| object | class | type | name
| R1 | amenity | prison | 'name' : 'XZ'
Scenario: Change name of a relation
Given the osm nodes:
| id | geometry
| 200 | 0 0
| 201 | 0 0.0001
| 202 | 0.0001 0.0001
| 203 | 0.0001 0
Given the osm ways:
| id | tags | nodes
| 2 | 'ref' : '45' | 200 201 202 203 200
Given the osm relations:
| id | tags | members
| 1 | 'type' : 'multipolygon', 'tourism' : 'hotel', 'name' : 'AB' | W2
When loading osm data
Then table place contains
| object | class | type | name
| R1 | tourism | hotel | 'name' : 'AB'
Given the osm relations:
| action | id | tags | members
| M | 1 | 'type' : 'multipolygon', 'tourism' : 'hotel', 'name' : 'XZ' | W2
When updating osm data
Then table place contains
| object | class | type | name
| R1 | tourism | hotel | 'name' : 'XZ'
Scenario: Change type of a relation into something unknown
Given the osm nodes:
| id | geometry
| 200 | 0 0
| 201 | 0 0.0001
| 202 | 0.0001 0.0001
| 203 | 0.0001 0
Given the osm ways:
| id | tags | nodes
| 2 | 'ref' : '45' | 200 201 202 203 200
Given the osm relations:
| id | tags | members
| 1 | 'type' : 'multipolygon', 'tourism' : 'hotel', 'name' : 'XZ' | W2
When loading osm data
Then table place contains
| object | class | type | name
| R1 | tourism | hotel | 'name' : 'XZ'
Given the osm relations:
| action | id | tags | members
| M | 1 | 'type' : 'multipolygon', 'amenities' : 'prison', 'name' : 'XZ' | W2
When updating osm data
Then table place has no entry for R1
Scenario: Type tag is removed
Given the osm nodes:
| id | geometry
| 200 | 0 0
| 201 | 0 0.0001
| 202 | 0.0001 0.0001
| 203 | 0.0001 0
Given the osm ways:
| id | tags | nodes
| 2 | 'ref' : '45' | 200 201 202 203 200
Given the osm relations:
| id | tags | members
| 1 | 'type' : 'multipolygon', 'tourism' : 'hotel', 'name' : 'XZ' | W2
When loading osm data
Then table place contains
| object | class | type | name
| R1 | tourism | hotel | 'name' : 'XZ'
Given the osm relations:
| action | id | tags | members
| M | 1 | 'tourism' : 'hotel', 'name' : 'XZ' | W2
When updating osm data
Then table place has no entry for R1
Scenario: Type tag is renamed to something unknown
Given the osm nodes:
| id | geometry
| 200 | 0 0
| 201 | 0 0.0001
| 202 | 0.0001 0.0001
| 203 | 0.0001 0
Given the osm ways:
| id | tags | nodes
| 2 | 'ref' : '45' | 200 201 202 203 200
Given the osm relations:
| id | tags | members
| 1 | 'type' : 'multipolygon', 'tourism' : 'hotel', 'name' : 'XZ' | W2
When loading osm data
Then table place contains
| object | class | type | name
| R1 | tourism | hotel | 'name' : 'XZ'
Given the osm relations:
| action | id | tags | members
| M | 1 | 'type' : 'multipolygonn', 'tourism' : 'hotel', 'name' : 'XZ' | W2
When updating osm data
Then table place has no entry for R1

26
tests/scenes/bin/Makefile Normal file
View File

@@ -0,0 +1,26 @@
CXXFLAGS += -O3
#CXXFLAGS += -g
CXXFLAGS += -std=c++11 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
CXXFLAGS += -I../../../../libosmium/include
OS:=$(shell uname -s)
ifeq ($(OS),Darwin)
CXXFLAGS += -stdlib=libc++
LDFLAGS += -stdlib=libc++
endif
CXXFLAGS_WARNINGS := -Wall -Wextra -pedantic -Wredundant-decls -Wdisabled-optimization -Wctor-dtor-privacy -Wnon-virtual-dtor -Woverloaded-virtual -Wsign-promo -Wold-style-cast
LIB_EXPAT := -lexpat
LIB_PBF := -pthread -lz -lprotobuf-lite -losmpbf
LIB_GZIP := -lz
LIB_BZIP2 := -lbz2
LIB_IO := $(LIB_EXPAT) $(LIB_PBF) $(LIB_GZIP) $(LIB_BZIP2)
all:
osm2wkt: osm2wkt.cc
$(CXX) $(CXXFLAGS) $(CXXFLAGS_WARNINGS) -o $@ $< $(LDFLAGS) $(LIB_IO)
scenarios: osm2wkt

View File

@@ -5,7 +5,7 @@
datadir="$( cd "$( dirname "$0" )" && cd ../data && pwd )"
if [! -d "$datadir" ]; then
if [ ! -d "$datadir" ]; then
echo "Cannot find data dir.";
exit -1;
fi

View File

@@ -7,23 +7,23 @@
#include <unordered_map>
#include <osmium/area/assembler.hpp>
#include <osmium/area/collector.hpp>
#include <osmium/area/multipolygon_collector.hpp>
#include <osmium/area/problem_reporter_exception.hpp>
#include <osmium/geom/wkt.hpp>
#include <osmium/handler.hpp>
#include <osmium/handler/node_locations_for_ways.hpp>
#include <osmium/io/any_input.hpp>
#include <osmium/visitor.hpp>
#include <osmium/index/map/stl_map.hpp>
#include <osmium/index/map/sparse_mem_array.hpp>
typedef osmium::index::map::StlMap<osmium::unsigned_object_id_type, osmium::Location> index_type;
typedef osmium::index::map::SparseMemArray<osmium::unsigned_object_id_type, osmium::Location> index_type;
typedef osmium::handler::NodeLocationsForWays<index_type, index_type> location_handler_type;
class ExportToWKTHandler : public osmium::handler::Handler {
osmium::geom::WKTFactory m_factory;
osmium::geom::WKTFactory<> m_factory;
std::unordered_map<std::string, std::ofstream> m_files;
public:
@@ -70,13 +70,12 @@ int main(int argc, char* argv[]) {
std::string input_filename {argv[1]};
typedef osmium::area::Assembler area_assembler_type;
osmium::area::ProblemReporterException problem_reporter;
area_assembler_type assembler(&problem_reporter);
osmium::area::Collector<area_assembler_type> collector(assembler);
osmium::area::Assembler::config_type assembler_config(&problem_reporter);
osmium::area::MultipolygonCollector<osmium::area::Assembler> collector(assembler_config);
std::cerr << "Pass 1...\n";
osmium::io::Reader reader1(input_filename);
osmium::io::Reader reader1(input_filename, osmium::osm_entity_bits::relation);
collector.read_relations(reader1);
std::cerr << "Pass 1 done\n";
@@ -87,9 +86,10 @@ int main(int argc, char* argv[]) {
std::cerr << "Pass 2...\n";
ExportToWKTHandler export_handler;
osmium::io::Reader reader2(input_filename);
osmium::apply(reader2, location_handler, export_handler, collector.handler());
osmium::apply(reader2, location_handler, export_handler, collector.handler([&export_handler](osmium::memory::Buffer&& buffer) {
osmium::apply(buffer, export_handler);
}));
reader2.close();
osmium::apply(collector, export_handler);
export_handler.close();
std::cerr << "Pass 2 done\n";

View File

@@ -0,0 +1,5 @@
n-middle-w | POINT(1.0065316 2.0003381)
n-middle-e | POINT(1.007236 2.0003408)
w-south | LINESTRING(1.0065324 2.0001892,1.006676 2.0002786,1.0068195 2.0002786,1.0069171 2.0002515,1.0070417 2.0001892,1.0072422 2.000173)
w-middle | LINESTRING(1.0065316 2.0003381,1.006686 2.0004248,1.0069 2.0004167,1.007236 2.0003408)
w-north | LINESTRING(1.0065397 2.000418,1.0066833 2.0005074,1.0068269 2.0005074,1.0069244 2.0004803,1.007049 2.000418,1.0072495 2.0004018)

View File

@@ -1,168 +1,221 @@
<?xml version='1.0' encoding='UTF-8'?>
<osm version='0.6'>
<node id="100" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.0" lon="0.0" />
<node id="101" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.1" lon="0.0" />
<node id="102" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.1" lon="0.001" />
<node id="103" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.0" lon="0.001" />
<way id="100" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1">
<nd ref="100" />
<nd ref="101" />
<nd ref="102" />
<nd ref="103" />
<nd ref="100" />
<tag k="test:section" v="poly-area"/>
<tag k="test:id" v="0.0001"/>
<tag k="area" v="yes"/>
</way>
<node id="200" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.0" lon="0.0" />
<node id="201" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.1" lon="0.0" />
<node id="202" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.1" lon="0.005" />
<node id="203" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.0" lon="0.005" />
<way id="200" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1">
<nd ref="200" />
<nd ref="201" />
<nd ref="202" />
<nd ref="203" />
<nd ref="200" />
<tag k="test:section" v="poly-area"/>
<tag k="test:id" v="0.0005"/>
<tag k="area" v="yes"/>
</way>
<node id="300" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.0" lon="0.0" />
<node id="301" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.1" lon="0.0" />
<node id="302" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.1" lon="0.01" />
<node id="303" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.0" lon="0.01" />
<way id="300" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1">
<nd ref="300" />
<nd ref="301" />
<nd ref="302" />
<nd ref="303" />
<nd ref="300" />
<tag k="test:section" v="poly-area"/>
<tag k="test:id" v="0.001"/>
<tag k="area" v="yes"/>
</way>
<node id="400" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.0" lon="0.0" />
<node id="401" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.1" lon="0.0" />
<node id="402" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.1" lon="0.05" />
<node id="403" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.0" lon="0.05" />
<way id="400" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1">
<nd ref="400" />
<nd ref="401" />
<nd ref="402" />
<nd ref="403" />
<nd ref="400" />
<tag k="test:section" v="poly-area"/>
<tag k="test:id" v="0.005"/>
<tag k="area" v="yes"/>
</way>
<node id="500" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.0" lon="0.0" />
<node id="501" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.1" lon="0.0" />
<node id="502" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.1" lon="0.1" />
<node id="503" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.0" lon="0.1" />
<way id="500" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1">
<nd ref="500" />
<nd ref="501" />
<nd ref="502" />
<nd ref="503" />
<nd ref="500" />
<tag k="test:section" v="poly-area"/>
<tag k="test:id" v="0.01"/>
<tag k="area" v="yes"/>
</way>
<node id="600" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.0" lon="0.0" />
<node id="601" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.1" lon="0.0" />
<node id="602" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.1" lon="0.5" />
<node id="603" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.0" lon="0.5" />
<way id="600" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1">
<nd ref="600" />
<nd ref="601" />
<nd ref="602" />
<nd ref="603" />
<nd ref="600" />
<tag k="test:section" v="poly-area"/>
<tag k="test:id" v="0.05"/>
<tag k="area" v="yes"/>
</way>
<node id="700" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.0" lon="0.0" />
<node id="701" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="1.0" lon="0.0" />
<node id="702" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="1.0" lon="0.1" />
<node id="703" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.0" lon="0.1" />
<way id="700" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1">
<nd ref="700" />
<nd ref="701" />
<nd ref="702" />
<nd ref="703" />
<nd ref="700" />
<tag k="test:section" v="poly-area"/>
<tag k="test:id" v="0.1"/>
<tag k="area" v="yes"/>
</way>
<node id="800" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.0" lon="0.0" />
<node id="801" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="1.0" lon="0.0" />
<node id="802" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="1.0" lon="0.5" />
<node id="803" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.0" lon="0.5" />
<way id="800" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1">
<nd ref="800" />
<nd ref="801" />
<nd ref="802" />
<nd ref="803" />
<nd ref="800" />
<tag k="test:section" v="poly-area"/>
<tag k="test:id" v="0.5"/>
<tag k="area" v="yes"/>
</way>
<node id="900" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.0" lon="0.0" />
<node id="901" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="1.0" lon="0.0" />
<node id="902" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="1.0" lon="1.0" />
<node id="903" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.0" lon="1.0" />
<way id="900" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1">
<nd ref="900" />
<nd ref="901" />
<nd ref="902" />
<nd ref="903" />
<nd ref="900" />
<tag k="test:section" v="poly-area"/>
<tag k="test:id" v="1.0"/>
<tag k="area" v="yes"/>
</way>
<node id="1000" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.0" lon="0.0" />
<node id="1001" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="1.0" lon="0.0" />
<node id="1002" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="1.0" lon="2.0" />
<node id="1003" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.0" lon="2.0" />
<way id="1000" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1">
<nd ref="1000" />
<nd ref="1001" />
<nd ref="1002" />
<nd ref="1003" />
<nd ref="1000" />
<tag k="test:section" v="poly-area"/>
<tag k="test:id" v="2.0"/>
<tag k="area" v="yes"/>
</way>
<node id="1100" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.0" lon="0.0" />
<node id="1101" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="1.0" lon="0.0" />
<node id="1102" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="1.0" lon="5.0" />
<node id="1103" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lat="0.0" lon="5.0" />
<way id="1100" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1">
<nd ref="1100" />
<nd ref="1101" />
<nd ref="1102" />
<nd ref="1103" />
<nd ref="1100" />
<tag k="test:section" v="poly-area"/>
<tag k="test:id" v="5.0"/>
<tag k="area" v="yes"/>
</way>
<osm version='0.6' upload='true' generator='JOSM'>
<node id='-238' action='modify' visible='true' lat='-0.00661880152' lon='0.00356249245'>
<tag k='test:id' v='inner-C' />
<tag k='test:section' v='way-area-with-center' />
</node>
<node id='-231' action='modify' visible='true' lat='-0.00600066098' lon='0.0041244384'>
<tag k='test:id' v='outer-C' />
<tag k='test:section' v='way-area-with-center' />
</node>
<node id='-225' action='modify' visible='true' lat='-0.00236518426' lon='0.00188464186'>
<tag k='test:id' v='inner-N' />
<tag k='test:section' v='way-area-with-center' />
</node>
<node id='-166' action='modify' visible='true' lat='-0.00951758843' lon='0.00485156509'>
<tag k='test:id' v='inner-S' />
<tag k='test:section' v='way-area-with-center' />
</node>
<node id='-137' action='modify' visible='true' lat='-0.00215326117' lon='0.00501050741' />
<node id='-135' action='modify' visible='true' lat='-0.00257710735' lon='0.00644098825' />
<node id='-133' action='modify' visible='true' lat='-0.00400758819' lon='0.00750060369' />
<node id='-131' action='modify' visible='true' lat='-0.00591489597' lon='0.00336810348' />
<node id='-129' action='modify' visible='true' lat='-0.00766326144' lon='0.00516944972' />
<node id='-127' action='modify' visible='true' lat='-0.00649768446' lon='0.00612310362' />
<node id='-125' action='modify' visible='true' lat='-0.00496124208' lon='0.00686483443' />
<node id='-123' action='modify' visible='true' lat='-0.00665662678' lon='0.00771252678' />
<node id='-121' action='modify' visible='true' lat='-0.0099414346' lon='0.0065469498' />
<node id='-119' action='modify' visible='true' lat='-0.01094806925' lon='0.0038979112' />
<node id='-117' action='modify' visible='true' lat='-0.01057720386' lon='0.00267935344' />
<node id='-115' action='modify' visible='true' lat='-0.00999441537' lon='0.00220252649' />
<node id='-113' action='modify' visible='true' lat='-0.00919970381' lon='0.00262637267' />
<node id='-111' action='modify' visible='true' lat='-0.00803412684' lon='0.00262637267' />
<node id='-109' action='modify' visible='true' lat='-0.00655066523' lon='0.00193762263' />
<node id='-107' action='modify' visible='true' lat='-0.00729239604' lon='0.00103694951' />
<node id='-105' action='modify' visible='true' lat='-0.00607383829' lon='0.00050714179' />
<node id='-103' action='modify' visible='true' lat='-0.00564999211' lon='0.00177868032' />
<node id='-101' action='modify' visible='true' lat='-0.00421951128' lon='0.00050714179' />
<node id='-99' action='modify' visible='true' lat='-0.00257710735' lon='0.00056012256' />
<node id='-98' action='modify' visible='true' lat='-0.00151749191' lon='0.00130185337' />
<node id='100' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.0' lon='0.0' />
<node id='101' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.1' lon='0.0' />
<node id='102' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.1' lon='0.001' />
<node id='103' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.0' lon='0.001' />
<node id='200' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.0' lon='0.0' />
<node id='201' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.1' lon='0.0' />
<node id='202' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.1' lon='0.005' />
<node id='203' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.0' lon='0.005' />
<node id='300' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.0' lon='0.0' />
<node id='301' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.1' lon='0.0' />
<node id='302' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.1' lon='0.01' />
<node id='303' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.0' lon='0.01' />
<node id='400' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.0' lon='0.0' />
<node id='401' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.1' lon='0.0' />
<node id='402' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.1' lon='0.05' />
<node id='403' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.0' lon='0.05' />
<node id='500' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.0' lon='0.0' />
<node id='501' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.1' lon='0.0' />
<node id='502' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.1' lon='0.1' />
<node id='503' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.0' lon='0.1' />
<node id='600' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.0' lon='0.0' />
<node id='601' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.1' lon='0.0' />
<node id='602' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.1' lon='0.5' />
<node id='603' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.0' lon='0.5' />
<node id='700' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.0' lon='0.0' />
<node id='701' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='1.0' lon='0.0' />
<node id='702' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='1.0' lon='0.1' />
<node id='703' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.0' lon='0.1' />
<node id='800' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.0' lon='0.0' />
<node id='801' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='1.0' lon='0.0' />
<node id='802' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='1.0' lon='0.5' />
<node id='803' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.0' lon='0.5' />
<node id='900' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.0' lon='0.0' />
<node id='901' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='1.0' lon='0.0' />
<node id='902' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='1.0' lon='1.0' />
<node id='903' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.0' lon='1.0' />
<node id='1000' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.0' lon='0.0' />
<node id='1001' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='1.0' lon='0.0' />
<node id='1002' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='1.0' lon='2.0' />
<node id='1003' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.0' lon='2.0' />
<node id='1100' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.0' lon='0.0' />
<node id='1101' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='1.0' lon='0.0' />
<node id='1102' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='1.0' lon='5.0' />
<node id='1103' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='0.0' lon='5.0' />
<way id='-100' action='modify' visible='true'>
<nd ref='-98' />
<nd ref='-99' />
<nd ref='-101' />
<nd ref='-103' />
<nd ref='-105' />
<nd ref='-107' />
<nd ref='-109' />
<nd ref='-111' />
<nd ref='-113' />
<nd ref='-115' />
<nd ref='-117' />
<nd ref='-119' />
<nd ref='-121' />
<nd ref='-123' />
<nd ref='-125' />
<nd ref='-127' />
<nd ref='-129' />
<nd ref='-131' />
<nd ref='-133' />
<nd ref='-135' />
<nd ref='-137' />
<nd ref='-98' />
<tag k='area' v='yes' />
<tag k='test:id' v='area' />
<tag k='test:section' v='way-area-with-center' />
</way>
<way id='100' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1'>
<nd ref='100' />
<nd ref='101' />
<nd ref='102' />
<nd ref='103' />
<nd ref='100' />
<tag k='area' v='yes' />
<tag k='test:id' v='0.0001' />
<tag k='test:section' v='poly-area' />
</way>
<way id='200' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1'>
<nd ref='200' />
<nd ref='201' />
<nd ref='202' />
<nd ref='203' />
<nd ref='200' />
<tag k='area' v='yes' />
<tag k='test:id' v='0.0005' />
<tag k='test:section' v='poly-area' />
</way>
<way id='300' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1'>
<nd ref='300' />
<nd ref='301' />
<nd ref='302' />
<nd ref='303' />
<nd ref='300' />
<tag k='area' v='yes' />
<tag k='test:id' v='0.001' />
<tag k='test:section' v='poly-area' />
</way>
<way id='400' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1'>
<nd ref='400' />
<nd ref='401' />
<nd ref='402' />
<nd ref='403' />
<nd ref='400' />
<tag k='area' v='yes' />
<tag k='test:id' v='0.005' />
<tag k='test:section' v='poly-area' />
</way>
<way id='500' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1'>
<nd ref='500' />
<nd ref='501' />
<nd ref='502' />
<nd ref='503' />
<nd ref='500' />
<tag k='area' v='yes' />
<tag k='test:id' v='0.01' />
<tag k='test:section' v='poly-area' />
</way>
<way id='600' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1'>
<nd ref='600' />
<nd ref='601' />
<nd ref='602' />
<nd ref='603' />
<nd ref='600' />
<tag k='area' v='yes' />
<tag k='test:id' v='0.05' />
<tag k='test:section' v='poly-area' />
</way>
<way id='700' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1'>
<nd ref='700' />
<nd ref='701' />
<nd ref='702' />
<nd ref='703' />
<nd ref='700' />
<tag k='area' v='yes' />
<tag k='test:id' v='0.1' />
<tag k='test:section' v='poly-area' />
</way>
<way id='800' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1'>
<nd ref='800' />
<nd ref='801' />
<nd ref='802' />
<nd ref='803' />
<nd ref='800' />
<tag k='area' v='yes' />
<tag k='test:id' v='0.5' />
<tag k='test:section' v='poly-area' />
</way>
<way id='900' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1'>
<nd ref='900' />
<nd ref='901' />
<nd ref='902' />
<nd ref='903' />
<nd ref='900' />
<tag k='area' v='yes' />
<tag k='test:id' v='1.0' />
<tag k='test:section' v='poly-area' />
</way>
<way id='1000' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1'>
<nd ref='1000' />
<nd ref='1001' />
<nd ref='1002' />
<nd ref='1003' />
<nd ref='1000' />
<tag k='area' v='yes' />
<tag k='test:id' v='2.0' />
<tag k='test:section' v='poly-area' />
</way>
<way id='1100' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1'>
<nd ref='1100' />
<nd ref='1101' />
<nd ref='1102' />
<nd ref='1103' />
<nd ref='1100' />
<tag k='area' v='yes' />
<tag k='test:id' v='5.0' />
<tag k='test:section' v='poly-area' />
</way>
</osm>

View File

@@ -1,294 +1,347 @@
<?xml version='1.0' encoding='UTF-8'?>
<osm version='0.6' upload='false' generator='JOSM'>
<node id='-204' action='modify' visible='true' lat='2.000651586300547' lon='1.005746444902722'>
<node id='-197' action='modify' visible='true' lat='2.0006515863' lon='1.0057464449'>
<tag k='name' v='split-road' />
</node>
<node id='-189' action='modify' visible='true' lat='2.0005350827634585' lon='1.0057490943252971' />
<node id='-187' action='modify' visible='true' lat='2.0005430261867043' lon='1.0058974619895207' />
<node id='-185' action='modify' visible='true' lat='2.0005430261867043' lon='1.0060511284988949' />
<node id='-183' action='modify' visible='true' lat='2.0005324349557014' lon='1.0061306111761574' />
<node id='-174' action='modify' visible='true' lat='2.0005244915324045' lon='1.00551064629351' />
<node id='-172' action='modify' visible='true' lat='2.0005668564562127' lon='1.0056086749288005' />
<node id='-170' action='modify' visible='true' lat='2.000561560840796' lon='1.0056855081834875' />
<node id='-168' action='modify' visible='true' lat='2.0005006612622807' lon='1.0057358472124205' />
<node id='-166' action='modify' visible='true' lat='2.000505956877894' lon='1.0059107091023978' />
<node id='-164' action='modify' visible='true' lat='2.0005112524934896' lon='1.0060537779214704' />
<node id='-162' action='modify' visible='true' lat='2.0004953656466506' lon='1.006135910021308' />
<node id='-160' action='modify' visible='true' lat='2.000513900301281' lon='1.0062842776855314' />
<node id='-158' action='modify' visible='true' lat='2.000471535376104' lon='1.0063717086305204' />
<node id='-156' action='modify' visible='true' lat='2.000296780048186' lon='1.0063584615176433' />
<node id='-154' action='modify' visible='true' lat='2.000262358542008' lon='1.006281628262956' />
<node id='-152' action='modify' visible='true' lat='2.000339144977876' lon='1.0061994961631182' />
<node id='-150' action='modify' visible='true' lat='2.0003576796342712' lon='1.0061041169504032' />
<node id='-148' action='modify' visible='true' lat='2.0003497362101275' lon='1.0060034388925374' />
<node id='-146' action='modify' visible='true' lat='2.000325905937466' lon='1.0058868642992191' />
<node id='-144' action='modify' visible='true' lat='2.000280893199271' lon='1.0057941345090795' />
<node id='-142' action='modify' visible='true' lat='2.0002782453911037' lon='1.0056351691545544' />
<node id='-141' action='modify' visible='true' lat='2.0003603274423103' lon='1.005470904954879' />
<node id='-139' action='modify' visible='true' lat='2.0007265421773432' lon='1.0047054313390744'>
<node id='-195' action='modify' visible='true' lat='2.00053508276' lon='1.00574909433' />
<node id='-193' action='modify' visible='true' lat='2.00054302619' lon='1.00589746199' />
<node id='-191' action='modify' visible='true' lat='2.00054302619' lon='1.0060511285' />
<node id='-189' action='modify' visible='true' lat='2.00053243496' lon='1.00613061118' />
<node id='-187' action='modify' visible='true' lat='2.00052449153' lon='1.00551064629' />
<node id='-185' action='modify' visible='true' lat='2.00056685646' lon='1.00560867493' />
<node id='-183' action='modify' visible='true' lat='2.00056156084' lon='1.00568550818' />
<node id='-181' action='modify' visible='true' lat='2.00050066126' lon='1.00573584721' />
<node id='-179' action='modify' visible='true' lat='2.00050595688' lon='1.0059107091' />
<node id='-177' action='modify' visible='true' lat='2.00051125249' lon='1.00605377792' />
<node id='-175' action='modify' visible='true' lat='2.00049536565' lon='1.00613591002' />
<node id='-173' action='modify' visible='true' lat='2.0005139003' lon='1.00628427769' />
<node id='-171' action='modify' visible='true' lat='2.00047153538' lon='1.00637170863' />
<node id='-169' action='modify' visible='true' lat='2.00029678005' lon='1.00635846152' />
<node id='-167' action='modify' visible='true' lat='2.00026235854' lon='1.00628162826' />
<node id='-165' action='modify' visible='true' lat='2.00033914498' lon='1.00619949616' />
<node id='-163' action='modify' visible='true' lat='2.00035767963' lon='1.00610411695' />
<node id='-161' action='modify' visible='true' lat='2.00034973621' lon='1.00600343889' />
<node id='-159' action='modify' visible='true' lat='2.00032590594' lon='1.0058868643' />
<node id='-157' action='modify' visible='true' lat='2.0002808932' lon='1.00579413451' />
<node id='-155' action='modify' visible='true' lat='2.00027824539' lon='1.00563516915' />
<node id='-153' action='modify' visible='true' lat='2.00036032744' lon='1.00547090495' />
<node id='-151' action='modify' visible='true' lat='2.00072654218' lon='1.00470543134'>
<tag k='name' v='points-on-road' />
</node>
<node id='-112' action='modify' visible='true' lat='2.0005155253763816' lon='1.0049220138358423' />
<node id='-110' action='modify' visible='true' lat='2.0005155253763816' lon='1.0049220138358423'>
<node id='-149' action='modify' visible='true' lat='2.00051552538' lon='1.00492201384' />
<node id='-147' action='modify' visible='true' lat='2.00051552538' lon='1.00492201384'>
<tag k='test:id' v='n-N-unglued' />
<tag k='test:section' v='points-on-roads' />
</node>
<node id='-108' action='modify' visible='true' lat='2.0002948553437463' lon='1.0046258759080025'>
<node id='-145' action='modify' visible='true' lat='2.00029485534' lon='1.00462587591'>
<tag k='test:id' v='n-S-unglued' />
<tag k='test:section' v='points-on-roads' />
</node>
<node id='-106' action='modify' visible='true' lat='2.0002948553437463' lon='1.0046258759080025' />
<node id='-104' action='modify' visible='true' lat='2.0006117740392657' lon='1.0050661381425037'>
<node id='-143' action='modify' visible='true' lat='2.00029485534' lon='1.00462587591' />
<node id='-141' action='modify' visible='true' lat='2.00061177404' lon='1.00506613814'>
<tag k='test:id' v='n-NE' />
<tag k='test:section' v='points-on-roads' />
</node>
<node id='-102' action='modify' visible='true' lat='2.000334854794143' lon='1.0051338707939657'>
<node id='-139' action='modify' visible='true' lat='2.00033485479' lon='1.00513387079'>
<tag k='test:id' v='n-SE' />
<tag k='test:section' v='points-on-roads' />
</node>
<node id='-100' action='modify' visible='true' lat='2.0006240815601832' lon='1.0053155174501582' />
<node id='-98' action='modify' visible='true' lat='2.0004086999307416' lon='1.0047582624540412'>
<node id='-137' action='modify' visible='true' lat='2.00062408156' lon='1.00531551745' />
<node id='-135' action='modify' visible='true' lat='2.00040869993' lon='1.00475826245'>
<tag k='test:id' v='n-NW' />
<tag k='test:section' v='points-on-roads' />
</node>
<node id='-96' action='modify' visible='true' lat='2.0003840848855767' lon='1.0046258759080025' />
<node id='-94' action='modify' visible='true' lat='2.0004302380949586' lon='1.004499646875733' />
<node id='-92' action='modify' visible='true' lat='2.0003687004821606' lon='1.0053278324776966' />
<node id='-90' action='modify' visible='true' lat='2.0002640865351053' lon='1.0049368303533495' />
<node id='-88' action='modify' visible='true' lat='2.000291778462916' lon='1.004825995105503' />
<node id='-86' action='modify' visible='true' lat='2.0003563929593238' lon='1.004727474885195'>
<node id='-133' action='modify' visible='true' lat='2.00038408489' lon='1.00462587591' />
<node id='-131' action='modify' visible='true' lat='2.00043023809' lon='1.00449964688' />
<node id='-129' action='modify' visible='true' lat='2.00036870048' lon='1.00532783248' />
<node id='-127' action='modify' visible='true' lat='2.00026408654' lon='1.00493683035' />
<node id='-125' action='modify' visible='true' lat='2.00029177846' lon='1.00482599511' />
<node id='-123' action='modify' visible='true' lat='2.00035639296' lon='1.00472747489'>
<tag k='test:id' v='n-SW' />
<tag k='test:section' v='points-on-roads' />
</node>
<node id='-84' action='modify' visible='true' lat='2.0002240870829975' lon='1.00452427693081' />
<node id='-82' action='modify' visible='true' lat='2.000715618411992' lon='1.0018322734314236'>
<node id='-121' action='modify' visible='true' lat='2.00022408708' lon='1.00452427693' />
<node id='-119' action='modify' visible='true' lat='2.00071561841' lon='1.00183227343'>
<tag k='name' v='road-with-alley' />
</node>
<node id='-80' action='modify' visible='true' lat='2.0007286441385155' lon='1.0004669962874884'>
<node id='-117' action='modify' visible='true' lat='2.00072864414' lon='1.00046699629'>
<tag k='name' v='roads-with-pois' />
</node>
<node id='-78' action='modify' visible='true' lat='2.000354154459697' lon='1.002448114434296'>
<node id='-115' action='modify' visible='true' lat='2.00035415446' lon='1.00244811443'>
<tag k='test:id' v='n-main-east' />
<tag k='test:section' v='road-with-alley' />
</node>
<node id='-76' action='modify' visible='true' lat='2.000266230783582' lon='1.0015520494830263'>
<node id='-113' action='modify' visible='true' lat='2.00026623078' lon='1.00155204948'>
<tag k='test:id' v='n-main-west' />
<tag k='test:section' v='road-with-alley' />
</node>
<node id='-74' action='modify' visible='true' lat='2.000546283957771' lon='1.0019235091355527'>
<node id='-111' action='modify' visible='true' lat='2.00054628396' lon='1.00192350914'>
<tag k='test:id' v='n-alley' />
<tag k='test:section' v='road-with-alley' />
</node>
<node id='-72' action='modify' visible='true' lat='2.000354154459697' lon='1.0019235091355527'>
<node id='-109' action='modify' visible='true' lat='2.00035415446' lon='1.00192350914'>
<tag k='test:id' v='n-corner' />
<tag k='test:section' v='road-with-alley' />
</node>
<node id='-70' action='modify' visible='true' lat='2.0005755918453296' lon='1.0019593517336036' />
<node id='-68' action='modify' visible='true' lat='2.000298795108618' lon='1.0026077769165225' />
<node id='-66' action='modify' visible='true' lat='2.000311820838452' lon='1.0023699124021854' />
<node id='-64' action='modify' visible='true' lat='2.0003150772708946' lon='1.0021255310518389' />
<node id='-62' action='modify' visible='true' lat='2.0003085644060037' lon='1.0019593517336036' />
<node id='-60' action='modify' visible='true' lat='2.000305307973548' lon='1.0016758693672019' />
<node id='-58' action='modify' visible='true' lat='2.000311820838452' lon='1.0013435107307307' />
<node id='-56' action='modify' visible='true' lat='2.0004054696330322' lon='1.0001173628501097'>
<node id='-107' action='modify' visible='true' lat='2.00057559185' lon='1.00195935173' />
<node id='-105' action='modify' visible='true' lat='2.00029879511' lon='1.00260777692' />
<node id='-103' action='modify' visible='true' lat='2.00031182084' lon='1.0023699124' />
<node id='-101' action='modify' visible='true' lat='2.00031507727' lon='1.00212553105' />
<node id='-99' action='modify' visible='true' lat='2.00030856441' lon='1.00195935173' />
<node id='-97' action='modify' visible='true' lat='2.00030530797' lon='1.00167586937' />
<node id='-95' action='modify' visible='true' lat='2.00031182084' lon='1.00134351073' />
<node id='-93' action='modify' visible='true' lat='2.00040546963' lon='1.00011736285'>
<tag k='test:section' v='roads-with-pois' />
</node>
<node id='-54' action='modify' visible='true' lat='2.000397598928471' lon='1.0004297578433892'>
<node id='-91' action='modify' visible='true' lat='2.00039759893' lon='1.00042975784'>
<tag k='test:section' v='roads-with-pois' />
</node>
<node id='-52' action='modify' visible='true' lat='2.0004579409958114' lon='1.0006607726283354'>
<node id='-89' action='modify' visible='true' lat='2.000457941' lon='1.00066077263'>
<tag k='test:section' v='roads-with-pois' />
</node>
<node id='-50' action='modify' visible='true' lat='2.0005418951727663' lon='1.0010624233339804'>
<node id='-87' action='modify' visible='true' lat='2.00054189517' lon='1.00106242333'>
<tag k='test:section' v='roads-with-pois' />
</node>
<node id='-48' action='modify' visible='true' lat='2.000190337028091' lon='1.0001383641941959'>
<node id='-85' action='modify' visible='true' lat='2.00019033703' lon='1.00013836419'>
<tag k='test:section' v='roads-with-pois' />
</node>
<node id='-46' action='modify' visible='true' lat='2.000198207733647' lon='1.000721151492583'>
<node id='-83' action='modify' visible='true' lat='2.00019820773' lon='1.00072115149'>
<tag k='test:section' v='roads-with-pois' />
</node>
<node id='-44' action='modify' visible='true' lat='2.000219196281612' lon='1.0010676736700022'>
<node id='-81' action='modify' visible='true' lat='2.00021919628' lon='1.00106767367'>
<tag k='test:section' v='roads-with-pois' />
</node>
<node id='-42' action='modify' visible='true' lat='2.000339880427198' lon='1.000390380323228'>
<node id='-79' action='modify' visible='true' lat='2.00033988043' lon='1.00039038032'>
<tag k='test:id' v='p-N2' />
<tag k='test:section' v='roads-with-pois' />
</node>
<node id='-40' action='modify' visible='true' lat='2.000292656197374' lon='1.0008104072049482'>
<node id='-77' action='modify' visible='true' lat='2.0002926562' lon='1.0008104072'>
<tag k='test:id' v='p-S1' />
<tag k='test:section' v='roads-with-pois' />
</node>
<node id='-38' action='modify' visible='true' lat='2.0005287773329004' lon='1.0005321393958087'>
<node id='-75' action='modify' visible='true' lat='2.00052877733' lon='1.0005321394'>
<tag k='test:id' v='p-N1' />
<tag k='test:section' v='roads-with-pois' />
</node>
<node id='-36' action='modify' visible='true' lat='2.000106382833144' lon='1.0006397712842492'>
<node id='-73' action='modify' visible='true' lat='2.00010638283' lon='1.00063977128'>
<tag k='test:id' v='p-S2' />
<tag k='test:section' v='roads-with-pois' />
</node>
<node id='-34' action='modify' visible='true' lat='2.0007211692424525' lon='1.0035828658185688'>
<node id='-71' action='modify' visible='true' lat='2.00072116924' lon='1.00358286582'>
<tag k='name' v='building-on-street-corner' />
</node>
<node id='-32' action='modify' visible='true' lat='2.000231635335803' lon='1.0031759205058477' />
<node id='-30' action='modify' visible='true' lat='2.000221087674047' lon='1.0040360790429201' />
<node id='-28' action='modify' visible='true' lat='2.0002263615049336' lon='1.0042735461237067' />
<node id='-26' action='modify' visible='true' lat='2.000105063390253' lon='1.0040413560891597' />
<node id='-24' action='modify' visible='true' lat='2.0006377202618473' lon='1.0040363991494512' />
<node id='-22' action='modify' visible='true' lat='2.0004388569487612' lon='1.0039042871025967' />
<node id='-20' action='modify' visible='true' lat='2.0004385547672516' lon='1.0040022536164286' />
<node id='-18' action='modify' visible='true' lat='2.0002343878022306' lon='1.0040016230872442' />
<node id='-16' action='modify' visible='true' lat='2.000234689983778' lon='1.0039036565734125' />
<node id='-14' action='modify' visible='true' lat='2.0003240388594246' lon='1.0040018999567464'>
<node id='-69' action='modify' visible='true' lat='2.00023163534' lon='1.00317592051' />
<node id='-67' action='modify' visible='true' lat='2.00022108767' lon='1.00403607904' />
<node id='-65' action='modify' visible='true' lat='2.0002263615' lon='1.00427354612' />
<node id='-63' action='modify' visible='true' lat='2.00010506339' lon='1.00404135609' />
<node id='-61' action='modify' visible='true' lat='2.00063772026' lon='1.00403639915' />
<node id='-59' action='modify' visible='true' lat='2.00043885695' lon='1.0039042871' />
<node id='-57' action='modify' visible='true' lat='2.00043855477' lon='1.00400225362' />
<node id='-55' action='modify' visible='true' lat='2.0002343878' lon='1.00400162309' />
<node id='-53' action='modify' visible='true' lat='2.00023468998' lon='1.00390365657' />
<node id='-51' action='modify' visible='true' lat='2.00032403886' lon='1.00400189996'>
<tag k='test:id' v='n-edge-NS' />
<tag k='test:section' v='building-on-street-corner' />
</node>
<node id='-12' action='modify' visible='true' lat='2.000354798021768' lon='1.0039384858598128'>
<node id='-49' action='modify' visible='true' lat='2.00035479802' lon='1.00393848586'>
<tag k='test:id' v='n-inner' />
<tag k='test:section' v='building-on-street-corner' />
</node>
<node id='-10' action='modify' visible='true' lat='2.0004676051467527' lon='1.0039478144477645'>
<node id='-47' action='modify' visible='true' lat='2.00046760515' lon='1.00394781445'>
<tag k='test:id' v='n-outer' />
<tag k='test:section' v='building-on-street-corner' />
</node>
<node id='-8' action='modify' visible='true' lat='2.000234516370527' lon='1.0039599415620857'>
<node id='-45' action='modify' visible='true' lat='2.00023451637' lon='1.00395994156'>
<tag k='test:id' v='n-edge-WE' />
<tag k='test:section' v='building-on-street-corner' />
</node>
<node id='-43' action='modify' visible='true' lat='2.0001892102' lon='1.00653236169' />
<node id='-41' action='modify' visible='true' lat='2.00027856164' lon='1.00667595302' />
<node id='-39' action='modify' visible='true' lat='2.00027856164' lon='1.00681954435' />
<node id='-37' action='modify' visible='true' lat='2.00025148545' lon='1.00691707809' />
<node id='-35' action='modify' visible='true' lat='2.0001892102' lon='1.00704170453' />
<node id='-33' action='modify' visible='true' lat='2.00017296448' lon='1.00724219054' />
<node id='-31' action='modify' visible='true' lat='2.00062243814' lon='1.00685396461'>
<tag k='name' v='parallel-road' />
</node>
<node id='-29' action='modify' visible='true' lat='2.00033813812' lon='1.00653156143'>
<tag k='test:id' v='n-middle-w' />
<tag k='test:section' v='parallel-road' />
</node>
<node id='-27' action='modify' visible='true' lat='2.00042478194' lon='1.00668598984' />
<node id='-25' action='modify' visible='true' lat='2.00041665908' lon='1.00690002221' />
<node id='-23' action='modify' visible='true' lat='2.00034084574' lon='1.00723597174'>
<tag k='test:id' v='n-middle-e' />
<tag k='test:section' v='parallel-road' />
</node>
<node id='-21' action='modify' visible='true' lat='2.00041801289' lon='1.00653968924' />
<node id='-19' action='modify' visible='true' lat='2.00050736432' lon='1.00668328057' />
<node id='-17' action='modify' visible='true' lat='2.00050736432' lon='1.00682687191' />
<node id='-15' action='modify' visible='true' lat='2.00048028813' lon='1.00692440564' />
<node id='-13' action='modify' visible='true' lat='2.00041801289' lon='1.00704903208' />
<node id='-11' action='modify' visible='true' lat='2.00040176717' lon='1.00724951809' />
<node id='100000' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='2.0' lon='1.0' />
<node id='100001' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='3.0' lon='1.0' />
<node id='100002' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='3.0' lon='2.0' />
<node id='100003' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='2.0' lon='2.0' />
<way id='-195' action='modify' visible='true'>
<nd ref='-170' />
<nd ref='-172' />
<nd ref='-174' />
<tag k='test:id' v='w-5' />
<tag k='test:section' v='split-road' />
</way>
<way id='-194' action='modify' visible='true'>
<nd ref='-160' />
<nd ref='-162' />
<nd ref='-164' />
<nd ref='-166' />
<nd ref='-168' />
<nd ref='-170' />
<tag k='test:id' v='w-4a' />
<tag k='test:section' v='split-road' />
</way>
<way id='-193' action='modify' visible='true'>
<nd ref='-152' />
<nd ref='-154' />
<nd ref='-156' />
<nd ref='-158' />
<nd ref='-160' />
<tag k='test:id' v='w-3' />
<tag k='test:section' v='split-road' />
</way>
<way id='-192' action='modify' visible='true'>
<nd ref='-144' />
<nd ref='-146' />
<nd ref='-148' />
<nd ref='-150' />
<nd ref='-152' />
<tag k='test:id' v='w-2' />
<tag k='test:section' v='split-road' />
</way>
<way id='-184' action='modify' visible='true'>
<nd ref='-160' />
<way id='-237' action='modify' visible='true'>
<nd ref='-183' />
<nd ref='-185' />
<nd ref='-187' />
<tag k='test:id' v='w-5' />
<tag k='test:section' v='split-road' />
</way>
<way id='-235' action='modify' visible='true'>
<nd ref='-173' />
<nd ref='-175' />
<nd ref='-177' />
<nd ref='-179' />
<nd ref='-181' />
<nd ref='-183' />
<tag k='test:id' v='w-4a' />
<tag k='test:section' v='split-road' />
</way>
<way id='-233' action='modify' visible='true'>
<nd ref='-165' />
<nd ref='-167' />
<nd ref='-169' />
<nd ref='-171' />
<nd ref='-173' />
<tag k='test:id' v='w-3' />
<tag k='test:section' v='split-road' />
</way>
<way id='-231' action='modify' visible='true'>
<nd ref='-157' />
<nd ref='-159' />
<nd ref='-161' />
<nd ref='-163' />
<nd ref='-165' />
<tag k='test:id' v='w-2' />
<tag k='test:section' v='split-road' />
</way>
<way id='-229' action='modify' visible='true'>
<nd ref='-173' />
<nd ref='-189' />
<nd ref='-170' />
<nd ref='-191' />
<nd ref='-193' />
<nd ref='-195' />
<nd ref='-183' />
<tag k='test:id' v='w-4b' />
<tag k='test:section' v='split-road' />
</way>
<way id='-143' action='modify' visible='true'>
<nd ref='-141' />
<nd ref='-142' />
<nd ref='-144' />
<way id='-227' action='modify' visible='true'>
<nd ref='-153' />
<nd ref='-155' />
<nd ref='-157' />
<tag k='test:id' v='w-1' />
<tag k='test:section' v='split-road' />
</way>
<way id='-134' action='modify' visible='true'>
<nd ref='-94' />
<nd ref='-96' />
<nd ref='-98' />
<nd ref='-112' />
<nd ref='-104' />
<nd ref='-100' />
<way id='-225' action='modify' visible='true'>
<nd ref='-131' />
<nd ref='-133' />
<nd ref='-135' />
<nd ref='-149' />
<nd ref='-141' />
<nd ref='-137' />
<tag k='test:id' v='w-north' />
<tag k='test:section' v='points-on-roads' />
</way>
<way id='-132' action='modify' visible='true'>
<nd ref='-84' />
<nd ref='-106' />
<nd ref='-86' />
<nd ref='-88' />
<nd ref='-90' />
<nd ref='-102' />
<nd ref='-92' />
<way id='-223' action='modify' visible='true'>
<nd ref='-121' />
<nd ref='-143' />
<nd ref='-123' />
<nd ref='-125' />
<nd ref='-127' />
<nd ref='-139' />
<nd ref='-129' />
<tag k='test:id' v='w-south' />
<tag k='test:section' v='points-on-roads' />
</way>
<way id='-130' action='modify' visible='true'>
<nd ref='-62' />
<nd ref='-70' />
<way id='-221' action='modify' visible='true'>
<nd ref='-99' />
<nd ref='-107' />
<tag k='test:id' v='w-alley' />
<tag k='test:section' v='road-with-alley' />
</way>
<way id='-128' action='modify' visible='true'>
<nd ref='-58' />
<nd ref='-60' />
<nd ref='-62' />
<nd ref='-64' />
<nd ref='-66' />
<nd ref='-68' />
<way id='-219' action='modify' visible='true'>
<nd ref='-95' />
<nd ref='-97' />
<nd ref='-99' />
<nd ref='-101' />
<nd ref='-103' />
<nd ref='-105' />
<tag k='test:id' v='w-main' />
<tag k='test:section' v='road-with-alley' />
</way>
<way id='-126' action='modify' visible='true'>
<nd ref='-56' />
<nd ref='-54' />
<nd ref='-52' />
<nd ref='-50' />
<way id='-217' action='modify' visible='true'>
<nd ref='-93' />
<nd ref='-91' />
<nd ref='-89' />
<nd ref='-87' />
<tag k='test:id' v='w-north' />
<tag k='test:section' v='roads-with-pois' />
</way>
<way id='-124' action='modify' visible='true'>
<nd ref='-48' />
<nd ref='-46' />
<nd ref='-44' />
<way id='-215' action='modify' visible='true'>
<nd ref='-85' />
<nd ref='-83' />
<nd ref='-81' />
<tag k='test:id' v='w-south' />
<tag k='test:section' v='roads-with-pois' />
</way>
<way id='-122' action='modify' visible='true'>
<nd ref='-32' />
<nd ref='-30' />
<nd ref='-28' />
<way id='-213' action='modify' visible='true'>
<nd ref='-69' />
<nd ref='-67' />
<nd ref='-65' />
<tag k='test:id' v='w-WE' />
<tag k='test:section' v='building-on-street-corner' />
</way>
<way id='-120' action='modify' visible='true'>
<nd ref='-26' />
<nd ref='-30' />
<nd ref='-24' />
<way id='-211' action='modify' visible='true'>
<nd ref='-63' />
<nd ref='-67' />
<nd ref='-61' />
<tag k='test:id' v='w-NS' />
<tag k='test:section' v='building-on-street-corner' />
</way>
<way id='-118' action='modify' visible='true'>
<nd ref='-22' />
<nd ref='-20' />
<nd ref='-14' />
<nd ref='-18' />
<nd ref='-8' />
<nd ref='-16' />
<nd ref='-22' />
<way id='-209' action='modify' visible='true'>
<nd ref='-59' />
<nd ref='-57' />
<nd ref='-51' />
<nd ref='-55' />
<nd ref='-45' />
<nd ref='-53' />
<nd ref='-59' />
<tag k='area' v='yes' />
<tag k='test:id' v='w-building' />
<tag k='test:section' v='building-on-street-corner' />
</way>
<way id='-207' action='modify' visible='true'>
<nd ref='-43' />
<nd ref='-41' />
<nd ref='-39' />
<nd ref='-37' />
<nd ref='-35' />
<nd ref='-33' />
<tag k='test:id' v='w-south' />
<tag k='test:section' v='parallel-road' />
</way>
<way id='-205' action='modify' visible='true'>
<nd ref='-29' />
<nd ref='-27' />
<nd ref='-25' />
<nd ref='-23' />
<tag k='test:id' v='w-middle' />
<tag k='test:section' v='parallel-road' />
</way>
<way id='-203' action='modify' visible='true'>
<nd ref='-21' />
<nd ref='-19' />
<nd ref='-17' />
<nd ref='-15' />
<nd ref='-13' />
<nd ref='-11' />
<tag k='test:id' v='w-north' />
<tag k='test:section' v='parallel-road' />
</way>
<way id='100000' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1'>
<nd ref='100000' />
<nd ref='100001' />

View File

@@ -0,0 +1,5 @@
inner-C | POINT(0.0035625 -0.0066188)
outer-C | POINT(0.0041244 -0.0060007)
inner-N | POINT(0.0018846 -0.0023652)
inner-S | POINT(0.0048516 -0.0095176)
area | MULTIPOLYGON(((0.0077125 -0.0066566,0.0065469 -0.0099414,0.0038979 -0.0109481,0.0026794 -0.0105772,0.0022025 -0.0099944,0.0026264 -0.0091997,0.0026264 -0.0080341,0.0019376 -0.0065507,0.0010369 -0.0072924,0.0005071 -0.0060738,0.0017787 -0.00565,0.0005071 -0.0042195,0.0005601 -0.0025771,0.0013019 -0.0015175,0.0050105 -0.0021533,0.006441 -0.0025771,0.0075006 -0.0040076,0.0033681 -0.0059149,0.0051694 -0.0076633,0.0061231 -0.0064977,0.0068648 -0.0049612,0.0077125 -0.0066566)))

View File

@@ -143,6 +143,11 @@ def api_result_header_contains(step):
assert_in(line['attr'], world.result_header)
m = re.match("%s$" % (line['value'],), world.result_header[line['attr']])
@step(u'result header has no attribute (.*)')
def api_result_header_contains_not(step, attr):
step.given('the result is valid')
assert_not_in(attr, world.result_header)
@step(u'results contain$')
def api_result_contains(step):
step.given('at least 1 result is returned')

View File

@@ -36,7 +36,7 @@ def api_call(requesttype):
world.response_format = fmt
elif fmt in ('json', 'jsonv2'):
if 'json_callback' in world.params:
world.json_callback = world.params['json_callback']
world.json_callback = world.params['json_callback'].encode('utf8')
assert world.page.startswith(world.json_callback + '(')
assert world.page.endswith(')')
world.page = world.page[(len(world.json_callback)+1):-1]
@@ -103,6 +103,16 @@ def api_setup_reverse(step, fmt, lat, lon):
world.params['format'] = fmt.strip()
api_call('reverse')
@step(u'looking up place ([NRW]?\d+)')
def api_setup_details_reverse(step, obj):
if obj[0] in ('N', 'R', 'W'):
# an osm id
world.params['osm_type'] = obj[0]
world.params['osm_id'] = obj[1:]
else:
world.params['place_id'] = obj
api_call('reverse')
@step(u'looking up details for ([NRW]?\d+)')
def api_setup_details(step, obj):
if obj[0] in ('N', 'R', 'W'):
@@ -112,3 +122,7 @@ def api_setup_details(step, obj):
else:
world.params['place_id'] = obj
api_call('details')
@step(u'sending an API call (\w+)')
def api_general_call(step, call):
api_call(call)

View File

@@ -22,7 +22,7 @@ logger = logging.getLogger(__name__)
@step(u'table placex contains as names for (N|R|W)(\d+)')
def check_placex_names(step, osmtyp, osmid):
""" Check for the exact content of the name hstaore in placex.
""" Check for the exact content of the name hstore in placex.
"""
cur = world.conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
cur.execute('SELECT name FROM placex where osm_type = %s and osm_id =%s', (osmtyp, int(osmid)))
@@ -43,46 +43,55 @@ def check_placex_content(step, tablename):
given columns are tested. If there is more than one
line for an OSM object, they must match in these columns.
"""
cur = world.conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
for line in step.hashes:
osmtype, osmid, cls = world.split_id(line['object'])
q = 'SELECT *'
if tablename == 'placex':
q = q + ", ST_X(centroid) as clat, ST_Y(centroid) as clon"
q = q + ' FROM %s where osm_type = %%s and osm_id = %%s' % (tablename,)
if cls is None:
params = (osmtype, osmid)
else:
q = q + ' and class = %s'
params = (osmtype, osmid, cls)
cur.execute(q, params)
assert(cur.rowcount > 0)
for res in cur:
for k,v in line.iteritems():
if not k == 'object':
assert_in(k, res)
if type(res[k]) is dict:
val = world.make_hash(v)
assert_equals(res[k], val)
elif k in ('parent_place_id', 'linked_place_id'):
pid = world.get_placeid(v)
assert_equals(pid, res[k], "Results for '%s'/'%s' differ: '%s' != '%s'" % (line['object'], k, pid, res[k]))
elif k == 'centroid':
world.match_geometry((res['clat'], res['clon']), v)
else:
assert_equals(str(res[k]), v, "Results for '%s'/'%s' differ: '%s' != '%s'" % (line['object'], k, str(res[k]), v))
try:
cur = world.conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
for line in step.hashes:
osmtype, osmid, cls = world.split_id(line['object'])
q = 'SELECT *'
if tablename == 'placex':
q = q + ", ST_X(centroid) as clat, ST_Y(centroid) as clon"
q = q + ", ST_GeometryType(geometry) as geometrytype"
q = q + ' FROM %s where osm_type = %%s and osm_id = %%s' % (tablename,)
if cls is None:
params = (osmtype, osmid)
else:
q = q + ' and class = %s'
params = (osmtype, osmid, cls)
cur.execute(q, params)
assert(cur.rowcount > 0)
for res in cur:
for k,v in line.iteritems():
if not k == 'object':
assert_in(k, res)
if type(res[k]) is dict:
val = world.make_hash(v)
assert_equals(res[k], val)
elif k in ('parent_place_id', 'linked_place_id'):
pid = world.get_placeid(v)
assert_equals(pid, res[k], "Results for '%s'/'%s' differ: '%s' != '%s'" % (line['object'], k, pid, res[k]))
elif k == 'centroid':
world.match_geometry((res['clat'], res['clon']), v)
else:
assert_equals(str(res[k]), v, "Results for '%s'/'%s' differ: '%s' != '%s'" % (line['object'], k, str(res[k]), v))
finally:
cur.close()
world.conn.commit()
@step(u'table (placex?) has no entry for (N|R|W)(\d+)(:\w+)?')
def check_placex_missing(step, tablename, osmtyp, osmid, placeclass):
cur = world.conn.cursor()
q = 'SELECT count(*) FROM %s where osm_type = %%s and osm_id = %%s' % (tablename, )
args = [osmtyp, int(osmid)]
if placeclass is not None:
q = q + ' and class = %s'
args.append(placeclass[1:])
cur.execute(q, args)
numres = cur.fetchone()[0]
assert_equals (numres, 0)
try:
q = 'SELECT count(*) FROM %s where osm_type = %%s and osm_id = %%s' % (tablename, )
args = [osmtyp, int(osmid)]
if placeclass is not None:
q = q + ' and class = %s'
args.append(placeclass[1:])
cur.execute(q, args)
numres = cur.fetchone()[0]
assert_equals (numres, 0)
finally:
cur.close()
world.conn.commit()
@step(u'search_name table contains$')
def check_search_name_content(step):
@@ -110,6 +119,54 @@ def check_search_name_content(step):
else:
raise Exception("Cannot handle field %s in search_name table" % (k, ))
@step(u'way (\d+) expands to housenumbers')
def check_interpolated_housenumbers(step, nodeid):
"""Check that the exact set of housenumbers has been entered in
placex for the given source node. Expected are two columns:
housenumber and centroid
"""
numbers = {}
for line in step.hashes:
assert line["housenumber"] not in numbers
numbers[line["housenumber"]] = line["centroid"]
cur = world.conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
cur.execute("""SELECT DISTINCT housenumber,
ST_X(centroid) as clat, ST_Y(centroid) as clon
FROM placex WHERE osm_type = 'W' and osm_id = %s
and class = 'place' and type = 'address'""",
(int(nodeid),))
assert_equals(len(numbers), cur.rowcount)
for r in cur:
assert_in(r["housenumber"], numbers)
world.match_geometry((r['clat'], r['clon']), numbers[r["housenumber"]])
del numbers[r["housenumber"]]
@step(u'way (\d+) expands exactly to housenumbers ([0-9,]*)')
def check_interpolated_housenumber_list(step, nodeid, numberlist):
""" Checks that the interpolated house numbers corresponds
to the given list.
"""
expected = numberlist.split(',');
cur = world.conn.cursor()
cur.execute("""SELECT housenumber FROM placex
WHERE osm_type = 'W' and osm_id = %s
and class = 'place' and type = 'address'""", (int(nodeid),))
for r in cur:
assert_in(r[0], expected, "Unexpected house number %s for node %s." % (r[0], nodeid))
expected.remove(r[0])
assert_equals(0, len(expected), "Missing house numbers for way %s: %s" % (nodeid, expected))
@step(u'way (\d+) expands to no housenumbers')
def check_no_interpolated_housenumber_list(step, nodeid):
""" Checks that the interpolated house numbers corresponds
to the given list.
"""
cur = world.conn.cursor()
cur.execute("""SELECT housenumber FROM placex
WHERE osm_type = 'W' and osm_id = %s
and class = 'place' and type = 'address'""", (int(nodeid),))
res = [r[0] for r in cur]
assert_equals(0, len(res), "Unexpected house numbers for way %s: %s" % (nodeid, res))
@step(u'table search_name has no entry for (.*)')
def check_placex_missing(step, osmid):

View File

@@ -95,6 +95,9 @@ def _format_placex_cols(cols, geomtype, force_name):
else:
coords = "'%s'::geometry" % coords.wkt
cols['geometry'] = coords
for k in cols:
if not cols[k]:
cols[k] = None
def _insert_place_table_nodes(places, force_name):
@@ -213,8 +216,8 @@ def import_database(step):
world.run_nominatim_script('setup', 'create-functions', 'create-partition-functions')
cur = world.conn.cursor()
cur.execute("""insert into placex (osm_type, osm_id, class, type, name, admin_level,
housenumber, street, addr_place, isin, postcode, country_code, extratags,
geometry) select * from place""")
housenumber, street, addr_place, isin, postcode, country_code, extratags,
geometry) select * from place""")
world.conn.commit()
world.run_nominatim_script('setup', 'index', 'index-noanalyse')
#world.db_dump_table('placex')

View File

@@ -108,7 +108,7 @@ def _sort_xml_entries(x, y):
def write_osm_obj(fd, obj):
if obj['type'] == 'N':
fd.write('<node id="%(id)d" lat="%(lat).8f" lon="%(lon).8f" version="%(version)s" timestamp="%(timestamp)%" changeset="%(changeset)s" uid="%(uid)s" user="%(user)s"'% obj)
fd.write('<node id="%(id)d" lat="%(lat).8f" lon="%(lon).8f" version="%(version)s" timestamp="%(timestamp)s" changeset="%(changeset)s" uid="%(uid)s" user="%(user)s"'% obj)
if obj['tags'] is None:
fd.write('/>\n')
else:
@@ -154,7 +154,7 @@ def osm2pgsql_load_place(step):
logger.debug( "Filename: %s" % fname)
cmd = [os.path.join(world.config.source_dir, 'utils', 'setup.php')]
cmd.extend(['--osm-file', fname, '--import-data'])
cmd.extend(['--osm-file', fname, '--import-data','--osm2pgsql-cache', '300'])
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(outp, outerr) = proc.communicate()
assert (proc.returncode == 0), "OSM data import failed:\n%s\n%s\n" % (outp, outerr)

View File

@@ -27,7 +27,7 @@ class NominatimConfig:
self.template_db = os.environ.get('TEMPLATE_DB', 'test_template_nominatim')
self.test_db = os.environ.get('TEST_DB', 'test_nominatim')
self.local_settings_file = os.environ.get('NOMINATIM_SETTINGS', '/tmp/nominatim_settings.php')
self.reuse_template = 'NOMINATIM_REUSE_TEMPLATE' in os.environ
self.reuse_template = 'NOMINATIM_REMOVE_TEMPLATE' not in os.environ
self.keep_scenario_db = 'NOMINATIM_KEEP_SCENARIO_DB' in os.environ
os.environ['NOMINATIM_SETTINGS'] = '/tmp/nominatim_settings.php'
@@ -94,7 +94,7 @@ def get_placeid(oid):
q = 'SELECT place_id FROM placex where osm_type = %s and osm_id = %s and class = %s'
params = (osmtype, osmid, cls)
cur.execute(q, params)
assert_equals (cur.rowcount, 1)
assert_equals(cur.rowcount, 1, "%d rows found for place %s" % (cur.rowcount, oid))
return cur.fetchone()[0]

View File

@@ -89,6 +89,8 @@
$aDSNInfo = DB::parseDSN(CONST_Database_DSN);
if (!isset($aDSNInfo['port']) || !$aDSNInfo['port']) $aDSNInfo['port'] = 5432;
$fPostgisVersion = (float) CONST_Postgis_Version;
if ($aCMDResult['create-db'] || $aCMDResult['all'])
{
echo "Create DB\n";
@@ -110,7 +112,7 @@
$oDB =& getDB();
$sVersionString = $oDB->getOne('select version()');
preg_match('#PostgreSQL ([0-9]+)[.]([0-9]+)[.]([0-9]+) #', $sVersionString, $aMatches);
preg_match('#PostgreSQL ([0-9]+)[.]([0-9]+)[^0-9]#', $sVersionString, $aMatches);
if (CONST_Postgresql_Version != $aMatches[1].'.'.$aMatches[2])
{
echo "ERROR: PostgreSQL version is not correct. Expected ".CONST_Postgresql_Version." found ".$aMatches[1].'.'.$aMatches[2]."\n";
@@ -126,7 +128,6 @@
pgsqlRunScript('CREATE EXTENSION hstore');
}
$fPostgisVersion = (float) CONST_Postgis_Version;
if ($fPostgisVersion < 2.0) {
pgsqlRunScriptFile(CONST_Path_Postgresql_Postgis.'/postgis.sql');
pgsqlRunScriptFile(CONST_Path_Postgresql_Postgis.'/spatial_ref_sys.sql');
@@ -190,6 +191,14 @@
{
$osm2pgsql .= ' --flat-nodes '.CONST_Osm2pgsql_Flatnode_File;
}
if (CONST_Tablespace_Osm2pgsql_Data)
$osm2pgsql .= ' --tablespace-slim-data '.CONST_Tablespace_Osm2pgsql_Data;
if (CONST_Tablespace_Osm2pgsql_Index)
$osm2pgsql .= ' --tablespace-slim-index '.CONST_Tablespace_Osm2pgsql_Index;
if (CONST_Tablespace_Place_Data)
$osm2pgsql .= ' --tablespace-main-data '.CONST_Tablespace_Place_Data;
if (CONST_Tablespace_Place_Index)
$osm2pgsql .= ' --tablespace-main-index '.CONST_Tablespace_Place_Index;
$osm2pgsql .= ' -lsc -O gazetteer --hstore';
$osm2pgsql .= ' -C '.$iCacheMemory;
$osm2pgsql .= ' -P '.$aDSNInfo['port'];
@@ -215,6 +224,15 @@
if ($aCMDResult['enable-debug-statements']) $sTemplate = str_replace('--DEBUG:', '', $sTemplate);
if (CONST_Limit_Reindexing) $sTemplate = str_replace('--LIMIT INDEXING:', '', $sTemplate);
pgsqlRunScript($sTemplate);
if ($fPostgisVersion < 2.0) {
echo "Helper functions for postgis < 2.0\n";
$sTemplate = file_get_contents(CONST_BasePath.'/sql/postgis_15_aux.sql');
} else {
echo "Helper functions for postgis >= 2.0\n";
$sTemplate = file_get_contents(CONST_BasePath.'/sql/postgis_20_aux.sql');
}
pgsqlRunScript($sTemplate);
}
if ($aCMDResult['create-minimal-tables'])
@@ -249,13 +267,30 @@
if ($aCMDResult['create-tables'] || $aCMDResult['all'])
{
echo "Tables\n";
$bDidSomething = true;
pgsqlRunScriptFile(CONST_BasePath.'/sql/tables.sql');
echo "Tables\n";
$sTemplate = file_get_contents(CONST_BasePath.'/sql/tables.sql');
$sTemplate = str_replace('{www-user}', CONST_Database_Web_User, $sTemplate);
$sTemplate = replace_tablespace('{ts:address-data}',
CONST_Tablespace_Address_Data, $sTemplate);
$sTemplate = replace_tablespace('{ts:address-index}',
CONST_Tablespace_Address_Index, $sTemplate);
$sTemplate = replace_tablespace('{ts:search-data}',
CONST_Tablespace_Search_Data, $sTemplate);
$sTemplate = replace_tablespace('{ts:search-index}',
CONST_Tablespace_Search_Index, $sTemplate);
$sTemplate = replace_tablespace('{ts:aux-data}',
CONST_Tablespace_Aux_Data, $sTemplate);
$sTemplate = replace_tablespace('{ts:aux-index}',
CONST_Tablespace_Aux_Index, $sTemplate);
pgsqlRunScript($sTemplate, false);
// re-run the functions
echo "Functions\n";
$sTemplate = file_get_contents(CONST_BasePath.'/sql/functions.sql');
$sTemplate = str_replace('{modulepath}',CONST_BasePath.'/module', $sTemplate);
$sTemplate = str_replace('{modulepath}',
CONST_BasePath.'/module', $sTemplate);
pgsqlRunScript($sTemplate);
}
@@ -273,6 +308,18 @@
if (!$aCMDResult['no-partitions']) $aPartitions[] = 0;
$sTemplate = file_get_contents(CONST_BasePath.'/sql/partition-tables.src.sql');
$sTemplate = replace_tablespace('{ts:address-data}',
CONST_Tablespace_Address_Data, $sTemplate);
$sTemplate = replace_tablespace('{ts:address-index}',
CONST_Tablespace_Address_Index, $sTemplate);
$sTemplate = replace_tablespace('{ts:search-data}',
CONST_Tablespace_Search_Data, $sTemplate);
$sTemplate = replace_tablespace('{ts:search-index}',
CONST_Tablespace_Search_Index, $sTemplate);
$sTemplate = replace_tablespace('{ts:aux-data}',
CONST_Tablespace_Aux_Data, $sTemplate);
$sTemplate = replace_tablespace('{ts:aux-index}',
CONST_Tablespace_Aux_Index, $sTemplate);
preg_match_all('#^-- start(.*?)^-- end#ms', $sTemplate, $aMatches, PREG_SET_ORDER);
foreach($aMatches as $aMatch)
{
@@ -453,7 +500,13 @@
{
$bDidSomething = true;
pgsqlRunScriptFile(CONST_BasePath.'/sql/tiger_import_start.sql');
$sTemplate = file_get_contents(CONST_BasePath.'/sql/tiger_import_start.sql');
$sTemplate = str_replace('{www-user}', CONST_Database_Web_User, $sTemplate);
$sTemplate = replace_tablespace('{ts:aux-data}',
CONST_Tablespace_Aux_Data, $sTemplate);
$sTemplate = replace_tablespace('{ts:aux-index}',
CONST_Tablespace_Aux_Index, $sTemplate);
pgsqlRunScript($sTemplate, false);
$aDBInstances = array();
for($i = 0; $i < $iInstances; $i++)
@@ -505,7 +558,13 @@
}
echo "Creating indexes\n";
pgsqlRunScriptFile(CONST_BasePath.'/sql/tiger_import_finish.sql');
$sTemplate = file_get_contents(CONST_BasePath.'/sql/tiger_import_finish.sql');
$sTemplate = str_replace('{www-user}', CONST_Database_Web_User, $sTemplate);
$sTemplate = replace_tablespace('{ts:aux-data}',
CONST_Tablespace_Aux_Data, $sTemplate);
$sTemplate = replace_tablespace('{ts:aux-index}',
CONST_Tablespace_Aux_Index, $sTemplate);
pgsqlRunScript($sTemplate, false);
}
if ($aCMDResult['calculate-postcodes'] || $aCMDResult['all'])
@@ -554,7 +613,7 @@
}
// Find the last node in the DB
$iLastOSMID = $oDB->getOne("select max(id) from planet_osm_nodes");
$iLastOSMID = $oDB->getOne("select max(osm_id) from place where osm_type = 'N'");
// Lookup the timestamp that node was created (less 3 hours for margin for changsets to be closed)
$sLastNodeURL = 'http://www.openstreetmap.org/api/0.6/node/'.$iLastOSMID."/1";
@@ -564,49 +623,59 @@
// Search for the correct state file - uses file timestamps so need to sort by date descending
$sRepURL = CONST_Replication_Url."/";
$sRep = file_get_contents($sRepURL."?C=M;O=D");
$sRep = file_get_contents($sRepURL."?C=M;O=D;F=1");
// download.geofabrik.de: <a href="000/">000/</a></td><td align="right">26-Feb-2013 11:53 </td>
// planet.openstreetmap.org: <a href="273/">273/</a> 22-Mar-2013 07:41 -
preg_match_all('#<a href="[0-9]{3}/">([0-9]{3}/)</a>.*(([0-9]{2})-([A-z]{3})-([0-9]{4}) ([0-9]{2}):([0-9]{2}))#', $sRep, $aRepMatches, PREG_SET_ORDER);
$aPrevRepMatch = false;
foreach($aRepMatches as $aRepMatch)
// planet.openstreetmap.org: <a href="273/">273/</a> 2013-03-11 07:41 -
preg_match_all('#<a href="[0-9]{3}/">([0-9]{3}/)</a>\s*([-0-9a-zA-Z]+ [0-9]{2}:[0-9]{2})#', $sRep, $aRepMatches, PREG_SET_ORDER);
if ($aRepMatches)
{
if (strtotime($aRepMatch[2]) < $iLastNodeTimestamp) break;
$aPrevRepMatch = $aRepMatch;
}
if ($aPrevRepMatch) $aRepMatch = $aPrevRepMatch;
$aPrevRepMatch = false;
foreach($aRepMatches as $aRepMatch)
{
if (strtotime($aRepMatch[2]) < $iLastNodeTimestamp) break;
$aPrevRepMatch = $aRepMatch;
}
if ($aPrevRepMatch) $aRepMatch = $aPrevRepMatch;
$sRepURL .= $aRepMatch[1];
$sRep = file_get_contents($sRepURL."?C=M;O=D");
preg_match_all('#<a href="[0-9]{3}/">([0-9]{3}/)</a>.*(([0-9]{2})-([A-z]{3})-([0-9]{4}) ([0-9]{2}):([0-9]{2}))#', $sRep, $aRepMatches, PREG_SET_ORDER);
$aPrevRepMatch = false;
foreach($aRepMatches as $aRepMatch)
$sRepURL .= $aRepMatch[1];
$sRep = file_get_contents($sRepURL."?C=M;O=D;F=1");
preg_match_all('#<a href="[0-9]{3}/">([0-9]{3}/)</a>\s*([-0-9a-zA-Z]+ [0-9]{2}:[0-9]{2})#', $sRep, $aRepMatches, PREG_SET_ORDER);
$aPrevRepMatch = false;
foreach($aRepMatches as $aRepMatch)
{
if (strtotime($aRepMatch[2]) < $iLastNodeTimestamp) break;
$aPrevRepMatch = $aRepMatch;
}
if ($aPrevRepMatch) $aRepMatch = $aPrevRepMatch;
$sRepURL .= $aRepMatch[1];
$sRep = file_get_contents($sRepURL."?C=M;O=D;F=1");
preg_match_all('#<a href="[0-9]{3}.state.txt">([0-9]{3}).state.txt</a>\s*([-0-9a-zA-Z]+ [0-9]{2}:[0-9]{2})#', $sRep, $aRepMatches, PREG_SET_ORDER);
$aPrevRepMatch = false;
foreach($aRepMatches as $aRepMatch)
{
if (strtotime($aRepMatch[2]) < $iLastNodeTimestamp) break;
$aPrevRepMatch = $aRepMatch;
}
if ($aPrevRepMatch) $aRepMatch = $aPrevRepMatch;
$sRepURL .= $aRepMatch[1].'.state.txt';
echo "Getting state file: $sRepURL\n";
$sStateFile = file_get_contents($sRepURL);
if (!$sStateFile || strlen($sStateFile) > 1000) fail("unable to obtain state file");
file_put_contents(CONST_BasePath.'/settings/state.txt', $sStateFile);
echo "Updating DB status\n";
pg_query($oDB->connection, 'TRUNCATE import_status');
$sSQL = "INSERT INTO import_status VALUES('".$aRepMatch[2]."')";
pg_query($oDB->connection, $sSQL);
}
else
{
if (strtotime($aRepMatch[2]) < $iLastNodeTimestamp) break;
$aPrevRepMatch = $aRepMatch;
if (!$aCMDResult['all'])
{
fail("Cannot read state file directory.");
}
}
if ($aPrevRepMatch) $aRepMatch = $aPrevRepMatch;
$sRepURL .= $aRepMatch[1];
$sRep = file_get_contents($sRepURL."?C=M;O=D");
preg_match_all('#<a href="[0-9]{3}.state.txt">([0-9]{3}).state.txt</a>.*(([0-9]{2})-([A-z]{3})-([0-9]{4}) ([0-9]{2}):([0-9]{2}))#', $sRep, $aRepMatches, PREG_SET_ORDER);
$aPrevRepMatch = false;
foreach($aRepMatches as $aRepMatch)
{
if (strtotime($aRepMatch[2]) < $iLastNodeTimestamp) break;
$aPrevRepMatch = $aRepMatch;
}
if ($aPrevRepMatch) $aRepMatch = $aPrevRepMatch;
$sRepURL .= $aRepMatch[1].'.state.txt';
echo "Getting state file: $sRepURL\n";
$sStateFile = file_get_contents($sRepURL);
if (!$sStateFile || strlen($sStateFile) > 1000) fail("unable to obtain state file");
file_put_contents(CONST_BasePath.'/settings/state.txt', $sStateFile);
echo "Updating DB status\n";
pg_query($oDB->connection, 'TRUNCATE import_status');
$sSQL = "INSERT INTO import_status VALUES('".$aRepMatch[2]."')";
pg_query($oDB->connection, $sSQL);
}
}
@@ -637,6 +706,12 @@
if (!$aCMDResult['no-partitions']) $aPartitions[] = 0;
$sTemplate = file_get_contents(CONST_BasePath.'/sql/indices.src.sql');
$sTemplate = replace_tablespace('{ts:address-index}',
CONST_Tablespace_Address_Index, $sTemplate);
$sTemplate = replace_tablespace('{ts:search-index}',
CONST_Tablespace_Search_Index, $sTemplate);
$sTemplate = replace_tablespace('{ts:aux-index}',
CONST_Tablespace_Aux_Index, $sTemplate);
preg_match_all('#^-- start(.*?)^-- end#ms', $sTemplate, $aMatches, PREG_SET_ORDER);
foreach($aMatches as $aMatch)
{
@@ -748,14 +823,14 @@
}
function pgsqlRunScript($sScript)
function pgsqlRunScript($sScript, $bfatal = true)
{
global $aCMDResult;
// Convert database DSN to psql parameters
$aDSNInfo = DB::parseDSN(CONST_Database_DSN);
if (!isset($aDSNInfo['port']) || !$aDSNInfo['port']) $aDSNInfo['port'] = 5432;
$sCMD = 'psql -p '.$aDSNInfo['port'].' -d '.$aDSNInfo['database'];
if (!$aCMDResult['ignore-errors'])
if ($bfatal && !$aCMDResult['ignore-errors'])
$sCMD .= ' -v ON_ERROR_STOP=1';
$aDescriptors = array(
0 => array('pipe', 'r'),
@@ -774,7 +849,7 @@
}
fclose($ahPipes[0]);
$iReturn = proc_close($hProcess);
if ($iReturn > 0)
if ($bfatal && $iReturn > 0)
{
fail("pgsql returned with error code ($iReturn)");
}
@@ -842,3 +917,15 @@
passthru($cmd, $result);
if ($result != 0) fail('Error executing external command: '.$cmd);
}
function replace_tablespace($sTemplate, $sTablespace, $sSql)
{
if ($sTablespace)
$sSql = str_replace($sTemplate, 'TABLESPACE "'.$sTablespace.'"',
$sSql);
else
$sSql = str_replace($sTemplate, '', $sSql);
return $sSql;
}

View File

@@ -86,17 +86,26 @@
foreach($aPairs as $aPair)
{
echo "create table place_classtype_".pg_escape_string($aPair[0])."_".pg_escape_string($aPair[1])." as ";
echo "select place_id as place_id,st_centroid(geometry) as centroid from placex where ";
echo "class = '".pg_escape_string($aPair[0])."' and type = '".pg_escape_string($aPair[1])."';\n";
echo "create table place_classtype_".pg_escape_string($aPair[0])."_".pg_escape_string($aPair[1]);
if (CONST_Tablespace_Aux_Data)
echo " tablespace ".CONST_Tablespace_Aux_Data;
echo " as select place_id as place_id,st_centroid(geometry) as centroid from placex where ";
echo "class = '".pg_escape_string($aPair[0])."' and type = '".pg_escape_string($aPair[1])."'";
echo ";\n";
echo "CREATE INDEX idx_place_classtype_".pg_escape_string($aPair[0])."_".pg_escape_string($aPair[1])."_centroid ";
echo "ON place_classtype_".pg_escape_string($aPair[0])."_".pg_escape_string($aPair[1])." USING GIST (centroid);\n";
echo "ON place_classtype_".pg_escape_string($aPair[0])."_".pg_escape_string($aPair[1])." USING GIST (centroid)";
if (CONST_Tablespace_Aux_Index)
echo " tablespace ".CONST_Tablespace_Aux_Index;
echo ";\n";
echo "CREATE INDEX idx_place_classtype_".pg_escape_string($aPair[0])."_".pg_escape_string($aPair[1])."_place_id ";
echo "ON place_classtype_".pg_escape_string($aPair[0])."_".pg_escape_string($aPair[1])." USING btree(place_id);\n";
echo "ON place_classtype_".pg_escape_string($aPair[0])."_".pg_escape_string($aPair[1])." USING btree(place_id)";
if (CONST_Tablespace_Aux_Index)
echo " tablespace ".CONST_Tablespace_Aux_Index;
echo ";\n";
echo "GRANT SELECT ON place_classtype_".pg_escape_string($aPair[0])."_".pg_escape_string($aPair[1])." TO \"www-data\";";
echo "GRANT SELECT ON place_classtype_".pg_escape_string($aPair[0])."_".pg_escape_string($aPair[1]).' TO "'.CONST_Database_Web_User."\";\n";
}

View File

@@ -64,6 +64,13 @@
$oPlaceLookup->setPlaceId($iPlaceID);
$aPlaceAddress = array_reverse($oPlaceLookup->getAddressDetails());
if (!sizeof($aPlaceAddress))
{
echo "Unknown place id.";
exit;
}
$aBreadcrums = array();
foreach($aPlaceAddress as $i => $aPlace)
{

View File

@@ -45,10 +45,8 @@
$oPlaceLookup->setOSMID($_GET['osm_type'], $_GET['osm_id']);
$aPlace = $oPlaceLookup->lookup();
//if (!$iPlaceID) $sError = 'OSM ID Not Found';
}
else
else if (isset($_GET['lat']) && isset($_GET['lon']) && preg_match('/^[+-]?[0-9]*\.?[0-9]+$/', $_GET['lat']) && preg_match('/^[+-]?[0-9]*\.?[0-9]+$/', $_GET['lon']))
{
$oReverseGeocode = new ReverseGeocode($oDB);
$oReverseGeocode->setLanguagePreference($aLangPrefOrder);
@@ -59,6 +57,10 @@
$aPlace = $oReverseGeocode->lookup();
}
else
{
$aPlace = null;
}
if (CONST_Debug) exit;

View File

@@ -87,7 +87,7 @@
} else {
if (!(isset($_GET['q']) && $_GET['q']) && isset($_SERVER['PATH_INFO']) && $_SERVER['PATH_INFO'][0] == '/')
{
$sQuery = substr($_SERVER['PATH_INFO'], 1);
$sQuery = substr(rawurldecode($_SERVER['PATH_INFO']), 1);
// reverse order of '/' separated string
$aPhrases = explode('/', $sQuery);