Compare commits

..

287 Commits

Author SHA1 Message Date
Sarah Hoffmann
567d81d10d remove more JSON_PRETTY_PRINT parameters 2016-10-17 23:03:21 +02:00
Sarah Hoffmann
6d77c08269 remove JSON_PRETTY_PRINT (requires php >= 5.4) 2016-10-17 21:49:12 +02:00
Sarah Hoffmann
f42ae6b2f6 replace more new-style array constructs 2016-10-17 21:37:13 +02:00
marc tobias
83ce6e12e7 query the last updated timestamp only if output format is HTML 2016-08-02 21:56:30 +02:00
Sarah Hoffmann
5b4c7b7f7e replace [] notation with old-style array() 2016-07-21 22:15:33 +02:00
Sarah Hoffmann
70997a9554 remove reference assignment where unnecessary
Avoids a number of warnings on PHP7.
2016-07-21 22:10:53 +02:00
Sarah Hoffmann
805f16b0cd bump version for 2.5.1 release 2016-04-26 22:05:46 +02:00
Marc Tobias Metten
083c55b230 update.php was checking for static file which is no longer part of the project 2016-04-26 22:02:16 +02:00
marc tobias
a24991b430 corrected layout of keywords on HTML details page 2016-04-26 22:02:04 +02:00
Marc Tobias Metten
3b44edf4a5 corrected layout of keywords on HTML details page 2016-04-26 22:01:51 +02:00
Sarah Hoffmann
8b75e1f4c4 prepare next release 2016-02-08 23:54:06 +01:00
Sarah Hoffmann
a2994fc55c ubuntu-vagrant: install Nominatim as vagrant user 2016-02-08 23:44:27 +01:00
Sarah Hoffmann
ebdd250fa0 also show line geometries on search page 2016-02-08 23:06:27 +01:00
Sarah Hoffmann
676c565905 update vagrant readme 2016-02-08 23:05:19 +01:00
Sarah Hoffmann
4d15bdaacc add vagrant script for CentOS 2016-02-08 22:58:59 +01:00
Sarah Hoffmann
f9ee4e3bd3 update dependencies in vagrant provision file
also automatically checkout if Nominatim directory does not exist
2016-02-06 18:49:12 +01:00
Sarah Hoffmann
c2112fc6ff add xml2 configure script now missing in osm2pgsql 2016-02-06 18:22:41 +01:00
Sarah Hoffmann
8b491e8544 Merge pull request #361 from mtmail/detail-page-big-table2
UI: columns nicer aligned in details table(s)
2016-02-06 12:51:47 +01:00
Sarah Hoffmann
40588482a2 Merge pull request #362 from mtmail/fix-timeout-on-detail-pages
fix timeout on detail pages related to distance calculation
2016-02-06 12:50:38 +01:00
marc tobias
c2b68c337b remove commented-out lines 2016-02-06 12:49:59 +01:00
marc tobias
a73135aebe fix timeout on detail pages related to distance calculation 2016-02-06 12:43:12 +01:00
marc tobias
634d04068d UI: columns nicer aligned in details table(s) 2016-02-06 12:39:51 +01:00
Sarah Hoffmann
a5883337f5 Merge pull request #354 from mtmail/configurable-tile-url
make map tile layer configurable
2016-01-29 21:11:32 +01:00
Marc Tobias Metten
21385f5e51 make map tile layer configurable 2016-01-27 19:42:49 +01:00
Sarah Hoffmann
4cade95b24 more detailed introduction
fixes #261
2016-01-24 09:22:49 +01:00
Sarah Hoffmann
a9b370fcb2 reverse webpage: don't choose zoom level 0 when none is given 2016-01-22 23:11:47 +01:00
Sarah Hoffmann
355d1efe21 add a short introduction text for the web interface 2016-01-22 23:01:03 +01:00
Sarah Hoffmann
620100a5ac Merge remote-tracking branch 'mtmail/mobile-responsive' 2016-01-22 22:55:34 +01:00
marc tobias
cd37227a3c user interface: zoom dropdown for debugging on reverse search page 2016-01-22 11:54:26 +00:00
marc tobias
690d7014f8 accidentially checked in a local configuration file 2016-01-22 11:53:31 +00:00
marc tobias
ef1a7d9073 user interface: reverse search remembers zoom level after map click 2016-01-21 15:26:18 +00:00
marc tobias
8f0199008d user interface: enable scrollwheel zoom. Disable on touch devices 2016-01-21 14:47:55 +00:00
marc tobias
9f1d3ac272 user interface: less spacing in table, pushing more content above the fold 2016-01-21 13:47:00 +00:00
marc tobias
513efecc34 user interface: less whitespace in header 2016-01-21 12:03:19 +00:00
mtmail
6822e50fe5 Merge pull request #1 from lonvia/mobile-responsive-compact-header
make headers more compact
2016-01-21 11:53:52 +00:00
Sarah Hoffmann
248588fbf3 make headers more compact 2016-01-20 21:14:30 +01:00
Marc Tobias Metten
f01828ae02 accidentally checked in two data files 2016-01-20 01:25:52 +01:00
Marc Tobias Metten
47a7887d86 tests: skip tidylib, it cannot handle HTML5 2016-01-20 01:14:20 +01:00
Marc Tobias Metten
016815eda2 new reverse HTML page incl leaflet map 2016-01-19 16:15:32 +01:00
Marc Tobias Metten
f2a2c29815 responsive details-error page. Shared header and footer 2016-01-19 12:29:07 +01:00
Marc Tobias Metten
97c572b92f Merge branch 'mobile-responsive' of https://github.com/mtmail/Nominatim into mobile-responsive 2016-01-15 17:11:41 +01:00
Marc Tobias Metten
851af3db7f details.php now also responsive 2016-01-15 17:11:12 +01:00
marc tobias
fc961c14fa status after hackweekend London 2016-01-15 17:11:12 +01:00
marc tobias
91f3405713 status after hackweekend London 2016-01-15 17:11:12 +01:00
Sarah Hoffmann
645182f2c0 Merge pull request #345 from netsgnut/updated-tiger-mips
Updated FIPS map in utils/tigerAddressImport.py
2016-01-04 21:03:01 +01:00
Kelvin Wong
e0e812d09b Reverted change on FIPS 35013 to remain ASCII 2016-01-04 23:10:01 +08:00
Kelvin Wong
7e8e952b66 Additional changes to FIPS code
See http://www2.census.gov/geo/docs/reference/codes/files/national_county.txt
2016-01-04 16:18:33 +08:00
Kelvin Wong
32c8dabefe Updated FIPS map in utils/tigerAddressImport.py
See https://www.census.gov/geo/reference/county-changes.html
2016-01-04 15:34:00 +08:00
Sarah Hoffmann
b079b4713f fix versions of pip-installed python modules for vagrant 2015-12-22 22:59:19 +01:00
Sarah Hoffmann
baefb4062f fix dependences in vagrant provision script
Add missing ones and replace manually installed stuff with
distro packages where possible.
2015-12-22 22:57:38 +01:00
Sarah Hoffmann
af150bc63e Merge pull request #340 from calimeroteknik/update-with-exit-errorcodes
utils/update.php: make the process exit with an non-zero error code if the update fails
2015-12-07 20:24:03 +01:00
calimeroteknik
fb7d65b8c3 utils/update.php: use fail() whenever possible for errors 2015-12-07 14:08:02 +01:00
calimeroteknik
dbb1f5c0e2 utils/update.php: make the process exit with an non-zero error code if the update fails 2015-12-07 13:54:05 +01:00
Sarah Hoffmann
2e1281b9a0 Merge pull request #313 from mtmail/more-tests-for-libphp
more tests for lib/lib.php
2015-11-29 10:13:01 +01:00
Marc Tobias Metten
2338d04e9f more tests for libphp - incorporate lonvias feedback 2015-10-15 02:30:51 +02:00
Marc Tobias Metten
111444cd99 more tests for libphp - incorporate lonvias feedback 2015-10-15 02:28:16 +02:00
Marc Tobias Metten
10a965c3ab more tests for lib/lib.php 2015-10-15 02:03:53 +02:00
Brian Quinion
fc9e75a5e6 Revert accidental change of osm2pgsql version 2015-10-07 15:52:56 +01:00
Brian Quinion
347f8e57c7 Allow for postgis being in the default template - not an error if it already is installed 2015-10-07 14:44:59 +01:00
Sarah Hoffmann
f24b904f9a don't use isset for bool options in setup.php 2015-09-27 11:09:55 +02:00
Sarah Hoffmann
0df8a4e24f add more tables and an experimental warning to new --drop function 2015-09-27 11:00:45 +02:00
Sarah Hoffmann
ccca38f22d Merge branch 'drop' of https://github.com/woodpeck/Nominatim 2015-09-27 10:36:31 +02:00
Sarah Hoffmann
b2cca7cea1 Merge pull request #315 from PhiRub/patch-1
Fixed Lat/Long Example
2015-09-26 10:43:20 +02:00
Frederik Ramm
b5c9845448 Add --drop option to setup.php 2015-09-26 01:41:19 +02:00
Sarah Hoffmann
9fb2bf36be streamline get_name_by_language()
patch by mdeweerd
2015-09-24 23:52:03 +02:00
PhiRub
5cc1946dfc Fixed Lat/Long Example 2015-09-03 15:59:40 -05:00
Sarah Hoffmann
fe3eb40e3a disable multithreading in osm2pgsql
not really useful for gazetteer plugin and producing too much overhead
2015-08-29 13:14:11 +02:00
Sarah Hoffmann
7822b1bc25 adapt to new configure variables for postgres 2015-08-29 12:15:19 +02:00
Sarah Hoffmann
5b1eca4c48 add configure script for pgsql server libs
This used to be in osm2pgsql but now has magically disappeared.
2015-08-29 12:04:46 +02:00
Sarah Hoffmann
8375392f39 force sensible file prefixes for generated test files
libosmium needs them to detect the file type
2015-08-29 11:29:09 +02:00
Sarah Hoffmann
71ab123fbb update osm2pgsql (libosmium; source, sidewalk, wikidata tags) 2015-08-29 11:26:12 +02:00
Marc Tobias Metten
c7eea2e419 details.php now also responsive 2015-08-23 07:15:04 +02:00
marc tobias
b0d9c0598e status after hackweekend London 2015-08-23 00:08:40 +02:00
Marc Tobias Metten
1e4c22a037 more tests for lib/lib.php 2015-08-22 23:56:14 +02:00
marc tobias
ce49d3c632 status after hackweekend London 2015-08-22 23:41:25 +02:00
Sarah Hoffmann
6479768932 gazetteer: exclude sidewalks 2015-08-17 22:41:40 +02:00
Sarah Hoffmann
5c187182a3 fix json output of empty arrays 2015-08-15 09:52:48 +02:00
Sarah Hoffmann
c242386ddb use url with php prefix in more url
User may not want to set up URL rewriting for suffixes.

Fixes #241
2015-08-11 23:09:50 +02:00
Sarah Hoffmann
c9d7015f69 make search with reverse plan default
The old behaviour with reverse planning for only selected languages
can be reinstated by setting CONST_Search_ReversePlanForAll to
false.

Fixes #293
2015-08-11 22:30:07 +02:00
Sarah Hoffmann
e90087a063 Merge pull request #305 from lonvia/api-extratags
Add new parameters to export name and extratags information
2015-08-11 22:19:36 +02:00
Sarah Hoffmann
058f597186 add basic tests for namedetails and extratags parameters 2015-08-10 23:18:19 +02:00
Sarah Hoffmann
95a681f128 make sure names/extratags is enabled for postgres > 9.2 only
Support for hstore_to_json() needed.
2015-08-10 21:53:13 +02:00
Sarah Hoffmann
ddb2b3cafb add namedetails and extratags to lookup call 2015-08-10 21:45:22 +02:00
Sarah Hoffmann
a1f3bfb35a implement namedetails and extratags parameter for search 2015-08-10 21:42:40 +02:00
Sarah Hoffmann
86ca377b1a add extratags and name details to PlaceLookup (reverse) 2015-08-09 15:14:59 +02:00
Sarah Hoffmann
5581bb67f8 respect --osm2pgsql-cache setting
fixes #260
2015-08-08 18:15:14 +02:00
Sarah Hoffmann
9e5c9ca81d fix HTTP return on status when database is down 2015-08-08 17:50:29 +02:00
Sarah Hoffmann
134553b184 ignore man_made objects in reverse search
fixes https://trac.openstreetmap.org/ticket/5339
2015-08-04 21:44:19 +02:00
Sarah Hoffmann
dbabfcd0cf tests for update of search_name table 2015-07-12 17:13:01 +02:00
Sarah Hoffmann
b328bcf518 Merge pull request #290 from mtmail/vagrant
first version of Vagrant installation instructions
2015-07-10 20:56:09 +02:00
marc tobias
3fe49072fe Vagrant: use 2GB by default, dont overwrite local.php which would be unexpected 2015-07-09 03:45:31 +02:00
marc tobias
9b7d8db038 assume PHP test suite is run from the tests-php directory. Matches documentation in VAGRANT.md 2015-07-09 03:43:59 +02:00
Marc Tobias Metten
df7d3b7478 correct documentation on how to start PHP tests 2015-07-04 19:16:09 +02:00
Marc Tobias Metten
d7c3f04e04 Vagrant: remove nonworking Digitalocean configuration 2015-06-28 23:54:48 +02:00
Marc Tobias Metten
23a53661e0 first version of Vagrant installation instructions 2015-06-25 04:21:32 +02:00
Marc Tobias Metten
86e946d369 method /lookup.php: incorporate better PHP variable naming and other feedback in pull request 2015-06-25 04:12:44 +02:00
Marc Tobias Metten
8c656fb667 remove tag in test suite used during debugging 2015-06-16 21:13:12 +02:00
Marc Tobias Metten
7c8c206818 new method /lookup.php - Reverse search by multiple osm ids 2015-06-16 21:11:21 +02:00
Sarah Hoffmann
1fcb712f00 also return bbox ccordinates as string for nodes
fixes https://trac.openstreetmap.org/ticket/5132 again
2015-06-12 23:26:38 +02:00
Sarah Hoffmann
80df4d3b56 fix parameter name
Fixes trac ticket 5319.
2015-05-28 21:25:55 +02:00
Sarah Hoffmann
b4f9252c63 update API tests 2015-05-22 21:49:31 +02:00
Sarah Hoffmann
3e871d6ee0 Merge branch 'http_proxy' of https://github.com/simonlopez/Nominatim 2015-05-22 21:20:51 +02:00
Sarah Hoffmann
dd97528726 get rid of sector index, no longer used 2015-05-21 23:35:04 +02:00
Sarah Hoffmann
c51ca976ed bring back area bboxes for nodes 2015-05-21 22:47:37 +02:00
Simon Lopez
c1f65ba7cf allow usage behind an HTTP Proxy. Fixes twain47/Nominatim#33 2015-05-21 19:51:04 +02:00
Sarah Hoffmann
bf77c72195 amke Tiger import script work with python3 2015-05-08 20:04:22 +02:00
Sarah Hoffmann
3257c04d94 make Tiger data path configurable 2015-05-08 19:48:27 +02:00
Sarah Hoffmann
ddb2e4aa12 Merge branch 'tiger2014' of https://github.com/mtmail/Nominatim 2015-05-08 19:37:40 +02:00
Sarah Hoffmann
2f8a29ba39 merge addr:postcode from houses into search index of attached road
Makes house number searchable by postcode when the postcode is
only available in addr:postcode.
2015-05-08 19:34:33 +02:00
Sarah Hoffmann
4ba93dcb50 remove debug output 2015-05-06 21:51:35 +02:00
Sarah Hoffmann
68596436b1 set SQL statement timeout to php execution timeout 2015-05-06 21:27:12 +02:00
Sarah Hoffmann
79f1107391 increase relevance of class/type importance
fixes #273
2015-05-04 21:14:34 +02:00
Marc Tobias Metten
3b809c40f1 update Tiger import script to use 2014 data 2015-05-04 01:13:20 +02:00
Marc Tobias Metten
3134fb8b40 update Tiger import script to use 2014 data 2015-05-04 01:07:54 +02:00
Sarah Hoffmann
48e0b318f2 remove create-road function, no longer used
The road tables are filled during indexing. Fixes #21.
2015-05-03 19:56:08 +02:00
Sarah Hoffmann
6727c36298 places marked as linked should use the address of the link origin
fixes #269
2015-05-03 17:31:14 +02:00
Sarah Hoffmann
a97808afec add test for TIGER reverse with lower zoom 2015-04-30 22:17:00 +02:00
Sarah Hoffmann
cf36e8d2fb Merge branch 'reverse-lookup-including-tiger-lookup' of https://github.com/mtmail/Nominatim 2015-04-30 21:48:25 +02:00
Sarah Hoffmann
cc40706188 add tests for new polygon_threshold feature 2015-04-30 21:39:41 +02:00
Sarah Hoffmann
a7e1b3b1ee Merge branch 'feature/polygon-simplification' of https://github.com/a1exsh/Nominatim 2015-04-30 21:26:11 +02:00
Oleksandr Shulgin
46e64bd933 Check for positive polygon simplification threshold
Don't run the simplification function if no threshold was given
(or in case of a negative one).  Also process the query string
parameter in case of html out format.
2015-04-29 16:13:39 +02:00
Marc Tobias Metten
2e1590ed89 apply Sarah's pull request feedback 2015-04-29 01:34:32 +02:00
Sarah Hoffmann
27753fb8db remove check for class/type shortcuts which were never implemented
fixes #266
2015-04-28 21:37:51 +02:00
Marc Tobias Metten
2a3672c19b postgres coalesce() looks for null values, not 0. Result remains in this case 0 2015-04-28 21:14:36 +02:00
Marc Tobias Metten
9746629fd3 during reverse geocode lookup we also check the (optional) Tiger data for house numbers 2015-04-28 21:07:34 +02:00
Sarah Hoffmann
b7fd7ef169 set new development version 2015-04-28 20:46:57 +02:00
Oleksandr Shulgin
ab47773604 Add polygon simplification
New query string parameter polygon_threshold=<0.0..1> is introduced.
The float value of this parameter (defaults to 0) is passed to
ST_SimplifyPreserveTopology() on geometry we're about to output in
one (or many) requested formats such as GeoJSON, KML, etc.

This is useful when getting border polygons for whole countries, but
rendering them at large scale, when most of the high resolution details
cannot be seen anyway.  For example, the unsimplified polygon data for
Germany in GeoJSON format currently makes for about 3 MB response body.
With use of this new parameter, the application can greatly reduce the
amount of downloaded data and server response time while providing its
users with the same picture.  On a typical laptop screen resolution,
zooming out to fit the whole country borders on screen, only 1/100 amount
of details could be well enough.
2015-04-27 15:16:38 +02:00
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
Sarah Hoffmann
59ea8d0830 prepare next release 2014-10-03 22:48:39 +02:00
Sarah Hoffmann
a1a136778d add finished message to setup.php 2014-09-29 19:31:37 +02:00
Sarah Hoffmann
4d6da459da experimental tweaking of ranks of searches
- completely removes partial words with spaces from addresses
- ensure that frequent partial search terms appear in NonAddress
- higher penalty for partial words consisting of numbers
2014-09-29 19:11:59 +02:00
Sarah Hoffmann
fd6db5a13f update osm2pgsql (protobuf lib)
fixes #175
2014-09-24 23:19:20 +02:00
Marc Tobias Metten
d6f298f033 move looksLikeLatLonPair into lib.php, basic PHP test suite using phpunit 2014-09-23 22:53:20 +02:00
Sarah Hoffmann
aae90ea5cb fix adding of spaces in GB postcode
Based on https://github.com/twain47/Nominatim/pull/180 by arunkmp.
2014-09-21 22:44:06 +02:00
Sarah Hoffmann
b6fd7b1857 lower significance of postcodes in Singapure
Postcodes with 6 digits designate delivery points, i.e. houses.
2014-09-11 19:42:52 +02:00
Sarah Hoffmann
4498c84d48 update osm2pgsql (nameless landuses) and add tests for it 2014-09-10 20:55:17 +02:00
Sarah Hoffmann
75cb02a497 fix running of DB tests via Makefile
Selecting tags for tests to run does not work when the tags are
on the features instead of the scenarios.
2014-09-10 20:52:37 +02:00
Sarah Hoffmann
a7d3146967 remove special casing of houses and postcodes in place import 2014-09-08 22:27:24 +02:00
Sarah Hoffmann
f94ee6ad57 change default nominatim path for tests to obvious '..' 2014-09-07 20:11:21 +02:00
Sarah Hoffmann
031f20c3e6 add simplified geometry index for reverse queries 2014-09-07 17:17:49 +02:00
Sarah Hoffmann
8c7f8165bd update osm2pgsql (empty waterways)
fixes #153
2014-09-07 17:13:25 +02:00
Sarah Hoffmann
86d90bc460 add functional tests
These are the tests that were formerly located at
https://github.com/lonvia/test-nominatim
2014-09-07 17:02:10 +02:00
Sarah Hoffmann
e7ee9c2d84 fix coordinate order for route parameter
fixes #174
2014-09-03 21:08:26 +02:00
Sarah Hoffmann
5f79cca558 apply rank restrictions already when scanning search_name table
fixes #176
2014-09-03 21:00:37 +02:00
Sarah Hoffmann
0b545ba093 experimental ordering of searches within same rank
giving preference to those without operator and housenumber
2014-09-03 20:46:41 +02:00
Sarah Hoffmann
a27bf64a55 disable unused function get_coonected_ways()
interferes with testing because of a reverse dependency on planet_osm_ways
2014-08-29 22:13:57 +02:00
Brian Quinion
fcc731dcd4 Add aeroway as alias for airport 2014-08-22 14:11:01 +01:00
Sarah Hoffmann
6b0ecb0e2f support colon in wikipedia article names
fixes #172
2014-08-17 22:31:18 +02:00
Sarah Hoffmann
8a4bd7fa4c consider side_streams as part of waterways if they have the same name
fixes #155
2014-07-21 23:11:28 +02:00
Sarah Hoffmann
2643225b72 fix member lookup in empty waterway relations 2014-07-06 23:15:53 +02:00
Sarah Hoffmann
c3dcb6535a go through entire member list when checking waterway relations 2014-07-06 21:23:11 +02:00
Brian Quinion
1d248ac86d Make deduplicate work again. Only currently support 9.3 due to new postgresql functions added. 2014-06-30 17:49:24 +01:00
Brian Quinion
7c54c81b77 update tiger import for changes to functions.sql 2014-06-26 17:12:39 +01:00
Sarah Hoffmann
3aab35e4b6 revert accidental osm2pgsql version downgrade 2014-06-05 22:37:58 +02:00
Sarah Hoffmann
6a5b5b3c36 revert error checking on pgsql restore
wikipedia dumps create expected errors on restore, fixes #142
2014-06-05 22:31:59 +02:00
Sarah Hoffmann
0ab547793d inherit postcode from street to poi 2014-05-26 22:42:03 +02:00
Sarah Hoffmann
be1d7f38ca return with non-zero exit code on error 2014-05-18 22:58:58 +02:00
Sarah Hoffmann
a178a62877 update osm2pgsql (waterway multiline geometries) 2014-05-18 21:51:26 +02:00
Sarah Hoffmann
665446e1a6 omit places with zero address rank from address lookup tables 2014-05-18 21:45:29 +02:00
Sarah Hoffmann
ea48e50c60 Merge branch 'place-in-addressdetails' of https://github.com/lonvia/Nominatim 2014-05-16 11:23:05 +02:00
Sarah Hoffmann
71883fc341 add setup option to ignore SQL errors
needed when restoring partial backups
2014-05-13 23:23:31 +02:00
Sarah Hoffmann
08b6fffc36 break out of write loop when psql fails
fixes hanging in --create-functions
2014-05-13 23:17:05 +02:00
Sarah Hoffmann
defb809b83 normalize house numbers in placex when searching 2014-05-10 19:41:11 +02:00
Sarah Hoffmann
052d219205 link waterway relations against contained ways 2014-05-07 22:47:36 +02:00
Sarah Hoffmann
bbd08742ce update osm2pgsql (waterways) 2014-05-05 21:40:07 +02:00
Sarah Hoffmann
70deb7883e fix PHP warnings about undefined variables 2014-05-01 15:38:31 +02:00
Sarah Hoffmann
7b24f72870 give slight preference to full-word matches when reranking
fixes https://trac.openstreetmap.org/ticket/5094
2014-05-01 15:19:24 +02:00
Sarah Hoffmann
11153633ff remove some dead code 2014-05-01 14:21:57 +02:00
Sarah Hoffmann
3eb21a7694 don't enlarge viewbox when bounded is requested 2014-05-01 14:20:23 +02:00
Sarah Hoffmann
9ac57c92ee fix formatting 2014-05-01 09:25:06 +02:00
Sarah Hoffmann
ac70726591 sanity check of house number format
Add a penalty for house number search terms when they contain
too many non-numeric characters in an attempt to filter tokens
that ended up as house numbers in the word table as a result
of mapping errors.
2014-05-01 09:18:10 +02:00
Sarah Hoffmann
34adfd5041 add penalty for special term searches
abbreviations for some of the terms are too easily matched against
common address terms like 'street'
2014-05-01 09:16:03 +02:00
Sarah Hoffmann
bafd92093b prefer place tag for address details 2014-04-30 23:31:28 +02:00
Sarah Hoffmann
2cc0fa341b remove New York hack
Seems to work okay with current boundaries.
2014-04-30 21:11:23 +02:00
Sarah Hoffmann
21adb3740e take viewbox into account for final result ranking
fixes #12
2014-04-30 21:04:46 +02:00
Sarah Hoffmann
ffe24a8a64 address inheritance from buildings to pois
POI nodes inherit the address tags from surrounding buildings
if they do not have an address of their own.
2014-04-30 20:05:59 +02:00
Sarah Hoffmann
00768d321e fix addr:place lookup 2014-04-28 21:52:24 +02:00
Sarah Hoffmann
6a1e599f31 avoid unnamed streets in associated street relations
fixes https://trac.openstreetmap.org/ticket/4877
2014-04-28 20:27:09 +02:00
Sarah Hoffmann
5882a15bac handle duplicate word entries correctly when looking for nearest street 2014-04-28 20:01:44 +02:00
Sarah Hoffmann
e3f90f8dcf assign rank of sea and coastline before area catchall 2014-04-28 16:45:55 +02:00
Sarah Hoffmann
76a83b91d7 fix copying of extratags from linked places
Didn't work correctly when the extratags of the parent relation
was null.
2014-04-23 21:29:55 +02:00
Sarah Hoffmann
b4a8bc1fea invalidate object itself in place_force_update() 2014-04-21 21:41:17 +02:00
Sarah Hoffmann
7f95590a77 correct start time computation
fixes #125
2014-04-21 21:12:14 +02:00
Sarah Hoffmann
090e9e7fb6 make errors from psql in setup fatal 2014-04-13 16:09:27 +02:00
Sarah Hoffmann
369a0974bd make HTML validator happy with details page 2014-04-12 20:12:23 +02:00
Sarah Hoffmann
488cd726ed suppress recursive updates for places that cannot appear in addresses 2014-04-11 22:57:00 +02:00
Sarah Hoffmann
496e1b0616 give waterways an address but remove them from being part of an address 2014-04-11 22:27:17 +02:00
Sarah Hoffmann
1bb47a6523 allow deletion of large areas of high rank 2014-04-11 22:28:07 +02:00
Sarah Hoffmann
589bad809e force countries into partitions as determined by country code
Avoids to a certain extent propagation of misassignment of
partitions when a country is expanded so far into another
that the centroid ends up in this other country.
2014-04-10 22:55:49 +02:00
Sarah Hoffmann
346da9bc0d handle multiple results from gb_postcode table 2014-04-10 21:50:44 +02:00
Sarah Hoffmann
49fa768f67 remove special handling for place tag values that have fallen out of use 2014-03-29 01:16:08 +01:00
Sarah Hoffmann
f6c7c4fcef truely ignore country codes provided via tags 2014-03-25 23:52:07 +01:00
Sarah Hoffmann
c2417dd1c4 update ref for postcode boundaries
Fixes https://trac.openstreetmap.org/ticket/5140
2014-03-24 13:01:20 +01:00
Sarah Hoffmann
0b9618e349 prefer street results when doing house number search
This is an experimental fix for #119.
2014-03-13 20:40:02 +01:00
Sarah Hoffmann
a92907186b allow US state name abbreviations at beginning of search term
fixes https://trac.openstreetmap.org/ticket/5136
2014-03-11 00:32:54 +01:00
Sarah Hoffmann
e42ff1935f forgot the actual query script 2014-03-03 21:48:17 +01:00
Sarah Hoffmann
ff35dbd4db ignore more autoconf files 2014-03-03 20:02:24 +01:00
Sarah Hoffmann
bc27cb2bd8 introduce util function to query db from command line 2014-03-03 20:02:24 +01:00
Sarah Hoffmann
236750eba4 always return bbox ccordinates as string
fixes https://trac.openstreetmap.org/ticket/5132
2014-03-02 17:52:09 +01:00
163 changed files with 11821 additions and 7917 deletions

12
.gitignore vendored
View File

@@ -1,9 +1,11 @@
*.log
*.pyc
nominatim/*.d
nominatim/*.o
nominatim/nominatim
module/nominatim.so
module/nominatim.o
settings/configuration.txt
settings/download.lock
settings/state.txt
@@ -14,8 +16,18 @@ autom4te.cache/
config.*
configure
Makefile
!tests/scenes/bin/Makefile
Makefile.in
stamp-h1
missing
INSTALL
aclocal.m4
depcomp
install-sh
compile
data/wiki_import.sql
data/wiki_specialphrases.sql
data/osmosischange.osc
.vagrant

View File

@@ -14,3 +14,6 @@ Nominatim was written by:
Spin0us
Kurt Roeckx
Rodolphe Quiédeville
Marc Tobias Metten
Reverse geocoding using Tiger data feature made possible with support from Guru Labs

View File

@@ -1,7 +1,60 @@
2.0.1
2.5.1
* delete outdated entries from location_area_country
* remove remaining uses of INTEGER, to allow node ids larger than 2^31
* fix layout error in details page when keywords are displayed
* fix website check during setup
2.5
* reverse geocoding includes looking up housenumbers from Tiger data
* added parameter to return simplified geometries
* new lookup call for getting address information for OSM objects
* new namedetails and extratags parameters that expose the name and extratags
fields of the placex table
* mobile website
* reverse web view
2.4
* 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,18 +80,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
* delete outdated entries from location_area_country
* remove remaining uses of INTEGER, to allow node ids larger than 2^31

View File

@@ -1,6 +1,27 @@
ACLOCAL_AMFLAGS = -I osm2pgsql/m4
AUTOMAKE_OPTIONS = -Wno-portability
SUBDIRS = osm2pgsql module nominatim
NOMINATIM_SERVER ?= $(shell echo a | php -F lib/init.php -E 'echo CONST_Website_BaseURL."\n";')
NOMINATIM_DATABASE ?= $(shell echo a | php -F lib/init.php -E 'echo DB::parseDSN(CONST_Database_DSN)["database"];')
install:
@echo Nominatim needs to be executed directly from this directory. No install necessary.
test:
cd tests; NOMINATIM_SERVER=${NOMINATIM_SERVER} lettuce -t -Fail -t -poldi-only
test-fast:
cd tests; NOMINATIM_SERVER=${NOMINATIM_SERVER} NOMINATIM_REUSE_TEMPLATE=1 lettuce -t -Fail -t -poldi-only
test-db:
cd tests; NOMINATIM_SERVER=${NOMINATIM_SERVER} lettuce -t -Fail -t -poldi-only features/db
test-db-fast:
cd tests; NOMINATIM_SERVER=${NOMINATIM_SERVER} NOMINATIM_REUSE_TEMPLATE=1 lettuce -t -Fail -t -poldi-only features/db
test-api:
cd tests; NOMINATIM_SERVER=${NOMINATIM_SERVER} lettuce -t -Fail -t -poldi-only features/api
.PHONY: test test-fast test-db test-db-fast test-api

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:

172
VAGRANT.md Normal file
View File

@@ -0,0 +1,172 @@
# Install Nominatim in a virtual machine for development and testing
This document describes how you can install Nominatim inside a Ubuntu 14
virtual machine on your desktop/laptop (host machine). The goal is to give
you a development environment to easily edit code and run the test suite
without affecting the rest of your system.
The installation can run largely unsupervised. You should expect 1-2h from
start to finish depending on how fast your computer and download speed
is.
## Prerequisites
1. [Virtualbox](https://www.virtualbox.org/wiki/Downloads)
2. [Vagrant](https://www.vagrantup.com/downloads.html)
3. Nominatim
git clone --recursive https://github.com/twain47/Nominatim.git
If you haven't used `--recursive`, then you can load the submodules using
git submodule init
git submodule update
## Installation
1. Start the virtual machine
vagrant up ubuntu
2. Log into the virtual machine
vagrant ssh ubuntu
3. Import a small country (Monaco)
You need to give the virtual machine more memory (2GB) for an import,
see `Vagrantfile`. Otherwise 1GB is enough.
See the FAQ how to skip this step and point Nominatim to an existing database.
```
# inside the virtual machine:
cd Nominatim
wget --no-verbose --output-document=data/monaco.osm.pbf http://download.geofabrik.de/europe/monaco-latest.osm.pbf
./utils/setup.php --osm-file data/monaco.osm.pbf --osm2pgsql-cache 1000 --all 2>&1 | tee monaco.$$.log
./utils/specialphrases.php --countries > data/specialphrases_countries.sql
psql -d nominatim -f data/specialphrases_countries.sql
```
To repeat an import you'd need to delete the database first
dropdb -if-exists nominatim
## Development
Vagrant maps the virtual machine's port 8089 to your host machine. Thus you can
see Nominatim in action on [locahost:8089](http://localhost:8089/nominatim/).
You edit code on your host machine in any editor you like. There is no need to
restart any software: just refresh your browser window.
PHP errors are written to `/var/log/apache2/error.log`.
With `echo` and `var_dump()` you write into the output (HTML/XML/JSON) when
you either add `&debug=1` to the URL (preferred) or set
`@define('CONST_Debug', true);` in `settings/local.php`.
## Running functional tests
Tests in `/features/db` and `/features/osm2pgsql` have to pass 100%. Other
tests might require full planet-wide data. Sadly even if you have your own
planet-wide data there will be enough differences to the openstreetmap.org
installation to cause false positives in the other tests (see FAQ).
To run the full test suite
cd ~/Nominatim/tests
NOMINATIM_SERVER=http://localhost:8089/nominatim lettuce features
To run a single file
NOMINATIM_SERVER=http://localhost:8089/nominatim lettuce features/api/reverse.feature
To run specific tests you can add tags just before the `Scenario line`, e.g.
@bug-34
Scenario: address lookup for non-existing or invalid node, way, relation
and then
NOMINATIM_SERVER=http://localhost:8089/nominatim lettuce -t bug-34
## Running unit tests
cd ~/Nominatim/tests-php
phpunit ./
## FAQ
##### Will it run on Windows?
Yes, Vagrant and Virtualbox can be installed on MS Windows just fine. You need a 64bit
version of Windows.
##### Why Monaco, can I use another country?
Of course! The Monaco import takes less than 30 minutes and works with 2GB RAM.
##### Will the results be the same as those from nominatim.openstreetmap.org?
No. Long running Nominatim installations will differ once new import features (or
bug fixes) get added since those usually only get applied to new/changed data.
Also this document skips the optional Wikipedia data import which affects ranking
of search results. See [Nominatim installation](http://wiki.openstreetmap.org/wiki/Nominatim/Installation) for details.
##### Why Ubuntu and CentOS, can I test CentOS/CoreOS/FreeBSD?
There is a Vagrant script for CentOS available. Simply start your box
with `vagrant up centos` and then log in with `vagrant ssh centos`.
In general Nominatim will also run in the other environments. The installation steps
are slightly different, e.g. the name of the package manager, Apache2 package
name, location of files. We chose Ubuntu because that is closest to the
nominatim.openstreetmap.org production environment.
You can configure/download other Vagrant boxes from [vagrantbox.es](http://www.vagrantbox.es/).
##### How can I connect to an existing database?
Let's say you have a Postgres database named `nominatim_it` on server `your-server.com` and port `5432`. The Postgres username is `postgres`. You can edit `settings/local.php` and point Nominatim to it.
pgsql://postgres@your-server.com:5432/nominatim_it
No data import necessary, no restarting necessary.
If the Postgres installation is behind a firewall, you can try
ssh -L 9999:localhost:5432 your-username@your-server.com
inside the virtual machine. It will map the port to `localhost:9999` and then
you edit `settings/local.php` with
pgsql://postgres@localhost:9999/nominatim_it
To access postgres directly remember to specify the hostname, e.g. `psql --host localhost --port 9999 nominatim_it`
##### My computer is slow and the import takes too long. Can I start the virtual machine "in the cloud"?
Yes. It's possible to start the virtual machine on [Amazon AWS (plugin)](https://github.com/mitchellh/vagrant-aws) or [DigitalOcean (plugin)](https://github.com/smdahlen/vagrant-digitalocean).

47
Vagrantfile vendored Normal file
View File

@@ -0,0 +1,47 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
# Apache webserver
config.vm.network "forwarded_port", guest: 8089, host: 8089
# If true, then any SSH connections made will enable agent forwarding.
config.ssh.forward_agent = true
config.vm.synced_folder ".", "/home/vagrant/Nominatim"
config.vm.define "ubuntu" do |sub|
sub.vm.box = "ubuntu/trusty64"
sub.vm.provision :shell, :path => "vagrant/ubuntu-trusty-provision.sh"
end
config.vm.define "centos" do |sub|
sub.vm.box = "bento/centos-7.2"
sub.vm.provision :shell, :path => "vagrant/centos-7-provision.sh"
end
# configure shared package cache if possible
#if Vagrant.has_plugin?("vagrant-cachier")
# config.cache.enable :apt
# config.cache.scope = :box
#end
config.vm.provider "virtualbox" do |vb|
vb.gui = false
vb.customize ["modifyvm", :id, "--memory", "2048"]
end
# config.vm.provider :digital_ocean do |provider, override|
# override.ssh.private_key_path = '~/.ssh/id_rsa'
# override.vm.box = 'digital_ocean'
# override.vm.box_url = "https://github.com/smdahlen/vagrant-digitalocean/raw/master/box/digital_ocean.box"
# provider.token = ''
# # provider.token = 'YOUR TOKEN'
# provider.image = 'ubuntu-14-04-x64'
# provider.region = 'nyc2'
# provider.size = '512mb'
# end
end

View File

@@ -1,4 +1,4 @@
AC_INIT(Nominatim,2.2)
AC_INIT(Nominatim,2.5.1)
if git rev-parse HEAD 2>/dev/null >/dev/null; then
AC_SUBST([PACKAGE_VERSION], [$PACKAGE_VERSION-git-`git rev-parse --short HEAD`])
fi
@@ -9,6 +9,7 @@ AC_PREREQ(2.61)
AM_INIT_AUTOMAKE([1.9.6 dist-bzip2 std-options check-news])
dnl Additional macro definitions are in here
m4_include([m4/ax_lib_postgresql_svr.m4])
AC_CONFIG_MACRO_DIR([osm2pgsql/m4])
dnl Generate configuration header file
@@ -40,11 +41,12 @@ 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])
fi
AX_LIB_POSTGRESQL_SVR(9.0)
if test ! -f "$POSTGRESQL_PGXS"
then
AC_MSG_ERROR([postgresql server development 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;

File diff suppressed because it is too large Load Diff

View File

@@ -5,10 +5,16 @@
protected $iPlaceID;
protected $sType = false;
protected $aLangPrefOrder = array();
protected $bAddressDetails = false;
protected $bExtraTags = false;
protected $bNameDetails = false;
function PlaceLookup(&$oDB)
{
$this->oDB =& $oDB;
@@ -24,6 +30,22 @@
$this->bAddressDetails = $bAddressDetails;
}
function setIncludeExtraTags($bExtraTags = false)
{
if ((float) CONST_Postgresql_Version > 9.2)
{
$this->bExtraTags = $bExtraTags;
}
}
function setIncludeNameDetails($bNameDetails = false)
{
if ((float) CONST_Postgresql_Version > 9.2)
{
$this->bNameDetails = $bNameDetails;
}
}
function setPlaceID($iPlaceID)
{
$this->iPlaceID = $iPlaceID;
@@ -35,21 +57,60 @@
$this->iPlaceID = $this->oDB->getOne($sSQL);
}
function lookupPlace($details)
{
if (isset($details['place_id'])) $this->iPlaceID = $details['place_id'];
if (isset($details['type'])) $this->sType = $details['type'];
if (isset($details['osm_type']) && isset($details['osm_id']))
{
$this->setOSMID($details['osm_type'], $details['osm_id']);
}
return $this->lookup();
}
function lookup()
{
if (!$this->iPlaceID) return null;
$sLanguagePrefArraySQL = "ARRAY[".join(',',array_map("getDBQuoted", $this->aLangPrefOrder))."]";
$sSQL = "select placex.place_id, partition, osm_type, osm_id, class, type, admin_level, housenumber, street, isin, postcode, country_code, extratags, parent_place_id, linked_place_id, rank_address, rank_search, ";
$sSQL .= " coalesce(importance,0.75-(rank_search::float/40)) as importance, indexed_status, indexed_date, wikipedia, calculated_country_code, ";
$sSQL .= " get_address_by_language(place_id, $sLanguagePrefArraySQL) as langaddress,";
$sSQL .= " get_name_by_language(name, $sLanguagePrefArraySQL) as placename,";
$sSQL .= " get_name_by_language(name, ARRAY['ref']) as ref,";
$sSQL .= " st_y(centroid) as lat, st_x(centroid) as lon";
$sSQL .= " from placex where place_id = ".(int)$this->iPlaceID;
if ($this->sType == 'tiger')
{
$sSQL = "select place_id,partition, 'T' as osm_type, place_id as osm_id, 'place' as class, 'house' as type, null as admin_level, housenumber, null as street, null as isin, postcode,";
$sSQL .= " 'us' as country_code, parent_place_id, null as linked_place_id, 30 as rank_address, 30 as rank_search,";
$sSQL .= " coalesce(null,0.75-(30::float/40)) as importance, null as indexed_status, null as indexed_date, null as wikipedia, 'us' as calculated_country_code, ";
$sSQL .= " get_address_by_language(place_id, $sLanguagePrefArraySQL) as langaddress,";
$sSQL .= " null as placename,";
$sSQL .= " null as ref,";
if ($this->bExtraTags) $sSQL .= " null as extra,";
if ($this->bNameDetails) $sSQL .= " null as names,";
$sSQL .= " st_y(centroid) as lat,";
$sSQL .= " st_x(centroid) as lon";
$sSQL .= " from location_property_tiger where place_id = ".(int)$this->iPlaceID;
}
else
{
$sSQL = "select placex.place_id, partition, osm_type, osm_id, class, type, admin_level, housenumber, street, isin, postcode, country_code, parent_place_id, linked_place_id, rank_address, rank_search, ";
$sSQL .= " coalesce(importance,0.75-(rank_search::float/40)) as importance, indexed_status, indexed_date, wikipedia, calculated_country_code, ";
$sSQL .= " get_address_by_language(place_id, $sLanguagePrefArraySQL) as langaddress,";
$sSQL .= " get_name_by_language(name, $sLanguagePrefArraySQL) as placename,";
$sSQL .= " get_name_by_language(name, ARRAY['ref']) as ref,";
if ($this->bExtraTags) $sSQL .= " hstore_to_json(extratags) as extra,";
if ($this->bNameDetails) $sSQL .= " hstore_to_json(name) as names,";
$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)
@@ -58,6 +119,30 @@
$aPlace['aAddress'] = $aAddress;
}
if ($this->bExtraTags)
{
if ($aPlace['extra'])
{
$aPlace['sExtraTags'] = json_decode($aPlace['extra']);
}
else
{
$aPlace['sExtraTags'] = (object) array();
}
}
if ($this->bNameDetails)
{
if ($aPlace['names'])
{
$aPlace['sNameDetails'] = json_decode($aPlace['names']);
}
else
{
$aPlace['sNameDetails'] = (object) array();
}
}
$aClassType = getClassTypes();
$sAddressType = '';
$sClassType = $aPlace['class'].':'.$aPlace['type'].':'.$aPlace['admin_level'];
@@ -99,7 +184,7 @@
function getAddressNames()
{
$aAddressLines = $this->getAddressDetails(false);;
$aAddressLines = $this->getAddressDetails(false);
$aAddress = array();
$aFallback = array();
@@ -124,7 +209,7 @@
{
$sTypeLabel = strtolower(isset($aTypeLabel['simplelabel'])?$aTypeLabel['simplelabel']:$aTypeLabel['label']);
$sTypeLabel = str_replace(' ','_',$sTypeLabel);
if (!isset($aAddress[$sTypeLabel]) || (isset($aFallback[$sTypeLabel]) && $aFallback[$sTypeLabel]))
if (!isset($aAddress[$sTypeLabel]) || (isset($aFallback[$sTypeLabel]) && $aFallback[$sTypeLabel]) || $aLine['class'] == 'place')
{
$aAddress[$sTypeLabel] = $aLine['localname']?$aLine['localname']:$aLine['housenumber'];
}

View File

@@ -9,8 +9,6 @@
protected $aLangPrefOrder = array();
protected $bShowAddressDetails = true;
function ReverseGeocode(&$oDB)
{
$this->oDB =& $oDB;
@@ -21,11 +19,6 @@
$this->aLangPrefOrder = $aLangPref;
}
function setIncludeAddressDetails($bAddressDetails = true)
{
$this->bAddressDetails = $bAddressDetails;
}
function setLatLon($fLat, $fLon)
{
$this->fLat = (float)$fLat;
@@ -69,12 +62,15 @@
{
$sPointSQL = 'ST_SetSRID(ST_Point('.$this->fLon.','.$this->fLat.'),4326)';
$iMaxRank = $this->iMaxRank;
$iMaxRank_orig = $this->iMaxRank;
// Find the nearest point
$fSearchDiam = 0.0004;
$iPlaceID = null;
$aArea = false;
$fMaxAreaDistance = 1;
$bIsInUnitedStates = false;
$bPlaceIsTiger = false;
while(!$iPlaceID && $fSearchDiam < $fMaxAreaDistance)
{
$fSearchDiam = $fSearchDiam * 2;
@@ -90,11 +86,11 @@
if ($fSearchDiam > 0.008 && $iMaxRank > 22) $iMaxRank = 22;
if ($fSearchDiam > 0.001 && $iMaxRank > 26) $iMaxRank = 26;
$sSQL = 'select place_id,parent_place_id,rank_search from placex';
$sSQL = 'select place_id,parent_place_id,rank_search,calculated_country_code from placex';
$sSQL .= ' WHERE ST_DWithin('.$sPointSQL.', geometry, '.$fSearchDiam.')';
$sSQL .= ' and rank_search != 28 and rank_search >= '.$iMaxRank;
$sSQL .= ' and (name is not null or housenumber is not null)';
$sSQL .= ' and class not in (\'waterway\',\'railway\',\'tunnel\',\'bridge\')';
$sSQL .= ' and class not in (\'waterway\',\'railway\',\'tunnel\',\'bridge\',\'man_made\')';
$sSQL .= ' and indexed_status = 0 ';
$sSQL .= ' and (ST_GeometryType(geometry) not in (\'ST_Polygon\',\'ST_MultiPolygon\') ';
$sSQL .= ' OR ST_DWithin('.$sPointSQL.', centroid, '.$fSearchDiam.'))';
@@ -107,12 +103,52 @@
}
$iPlaceID = $aPlace['place_id'];
$iParentPlaceID = $aPlace['parent_place_id'];
$bIsInUnitedStates = ($aPlace['calculated_country_code'] == 'us');
}
// Only street found? If it's in the US we can check TIGER data for nearest housenumber
if ($bIsInUnitedStates && $iMaxRank_orig >= 28 && $iPlaceID && ($aPlace['rank_search'] == 26 || $aPlace['rank_search'] == 27 ))
{
$fSearchDiam = 0.001;
$sSQL = 'SELECT place_id,parent_place_id,30 as rank_search ';
if (CONST_Debug) { $sSQL .= ', housenumber, ST_distance('.$sPointSQL.', centroid) as distance, st_y(centroid) as lat, st_x(centroid) as lon'; }
$sSQL .= ' FROM location_property_tiger WHERE parent_place_id = '.$iPlaceID;
$sSQL .= ' AND ST_DWithin('.$sPointSQL.', centroid, '.$fSearchDiam.')';
$sSQL .= ' ORDER BY ST_distance('.$sPointSQL.', centroid) ASC limit 1';
// print all house numbers in the parent (street)
if (CONST_Debug)
{
$sSQL = preg_replace('/limit 1/', 'limit 100', $sSQL);
var_dump($sSQL);
$aAllHouses = $this->oDB->getAll($sSQL);
foreach($aAllHouses as $i)
{
echo $i['housenumber'] . ' | ' . $i['distance'] * 1000 . ' | ' . $i['lat'] . ' | ' . $i['lon']. ' | '. "<br>\n";
}
}
$aPlaceTiger = $this->oDB->getRow($sSQL);
if (PEAR::IsError($aPlace))
{
failInternalError("Could not determine closest Tiger place.", $sSQL, $aPlaceTiger);
}
if ($aPlaceTiger)
{
if (CONST_Debug) var_dump('found Tiger place', $aPlaceTiger);
$bPlaceIsTiger = true;
$aPlace = $aPlaceTiger;
$iPlaceID = $aPlaceTiger['place_id'];
$iParentPlaceID = $aPlaceTiger['parent_place_id']; // the street
}
}
// The point we found might be too small - use the address to find what it is a child of
if ($iPlaceID && $iMaxRank < 28)
{
if ($aPlace['rank_search'] > 28 && $iParentPlaceID)
if ($aPlace['rank_search'] > 28 && $iParentPlaceID && !$bPlaceIsTiger)
{
$iPlaceID = $iParentPlaceID;
}
@@ -128,12 +164,8 @@
}
}
$oPlaceLookup = new PlaceLookup($this->oDB);
$oPlaceLookup->setLanguagePreference($this->aLangPrefOrder);
$oPlaceLookup->setIncludeAddressDetails($this->bAddressDetails);
$oPlaceLookup->setPlaceId($iPlaceID);
return $oPlaceLookup->lookup();
return array('place_id' => $iPlaceID,
'type' => $bPlaceIsTiger ? 'tiger' : 'osm');
}
}
?>

View File

@@ -4,7 +4,7 @@
function &getDB($bNew = false, $bPersistent = false)
{
// Get the database object
$oDB =& DB::connect(CONST_Database_DSN.($bNew?'?new_link=true':''), $bPersistent);
$oDB = DB::connect(CONST_Database_DSN.($bNew?'?new_link=true':''), $bPersistent);
if (PEAR::IsError($oDB))
{
var_dump(CONST_Database_DSN);
@@ -14,6 +14,8 @@
$oDB->setFetchMode(DB_FETCHMODE_ASSOC);
$oDB->query("SET DateStyle TO 'sql,european'");
$oDB->query("SET client_encoding TO 'utf-8'");
$iMaxExecution = ini_get('max_execution_time') * 1000;
if ($iMaxExecution > 0) $oDB->query("SET statement_timeout TO $iMaxExecution");
return $oDB;
}

View File

@@ -1,9 +1,31 @@
<?php
if (file_exists(getenv('NOMINATIM_SETTINGS')))
{
echo 'Using local config: '.getenv('NOMINATIM_SETTINGS');
require_once(getenv('NOMINATIM_SETTINGS'));
}
require_once('init.php');
require_once('cmd.php');
// handle http proxy when using file_get_contents
if (CONST_HTTP_Proxy) {
$proxy = 'tcp://' . CONST_HTTP_Proxy_Host . ':' . CONST_HTTP_Proxy_Port;
$aHeaders = array();
if(CONST_HTTP_Proxy_Login != null && CONST_HTTP_Proxy_Login != '' && CONST_HTTP_Proxy_Password != null && CONST_HTTP_Proxy_Password != '') {
$auth = base64_encode(CONST_HTTP_Proxy_Login . ':' . CONST_HTTP_Proxy_Password);
$aHeaders = array("Proxy-Authorization: Basic $auth");
}
$aContext = array(
'http' => array(
'proxy' => $proxy,
'request_fulluri' => true,
'header' => $aHeaders
),
'https' => array(
'proxy' => $proxy,
'request_fulluri' => true,
'header' => $aHeaders
)
);
stream_context_set_default($aContext);
}

View File

@@ -39,13 +39,19 @@
exit;
}
function getParamBool($name, $default=false)
{
if (!isset($_GET[$name])) return $default;
return (bool) $_GET[$name];
}
function fail($sError, $sUserError = false)
{
if (!$sUserError) $sUserError = $sError;
error_log('ERROR: '.$sError);
echo $sUserError."\n";
exit;
exit(-1);
}
@@ -94,7 +100,8 @@
function bySearchRank($a, $b)
{
if ($a['iSearchRank'] == $b['iSearchRank']) return 0;
if ($a['iSearchRank'] == $b['iSearchRank'])
return strlen($a['sOperator']) + strlen($a['sHouseNumber']) - strlen($b['sOperator']) - strlen($b['sHouseNumber']);
return ($a['iSearchRank'] < $b['iSearchRank']?-1:1);
}
@@ -117,18 +124,26 @@
}
function getPreferredLanguages()
function getPreferredLanguages($sLangString=false)
{
// If we have been provided the value in $_GET it overrides browser value
if (isset($_GET['accept-language']) && $_GET['accept-language'])
if (!$sLangString)
{
$_SERVER["HTTP_ACCEPT_LANGUAGE"] = $_GET['accept-language'];
// If we have been provided the value in $_GET it overrides browser value
if (isset($_GET['accept-language']) && $_GET['accept-language'])
{
$_SERVER["HTTP_ACCEPT_LANGUAGE"] = $_GET['accept-language'];
$sLangString = $_GET['accept-language'];
}
else if (isset($_SERVER["HTTP_ACCEPT_LANGUAGE"]))
{
$sLangString = $_SERVER["HTTP_ACCEPT_LANGUAGE"];
}
}
$aLanguages = array();
if (isset($_SERVER["HTTP_ACCEPT_LANGUAGE"]))
if ($sLangString)
{
if (preg_match_all('/(([a-z]{1,8})(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $aLanguagesParse, PREG_SET_ORDER))
if (preg_match_all('/(([a-z]{1,8})(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $sLangString, $aLanguagesParse, PREG_SET_ORDER))
{
foreach($aLanguagesParse as $iLang => $aLanguage)
{
@@ -184,6 +199,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)
{
@@ -246,7 +281,13 @@
if (sizeof($aNearPostcodes))
{
return array(array('lat' => $aNearPostcodes[0]['lat'], 'lon' => $aNearPostcodes[0]['lon'], 'radius' => 0.005));
$aPostcodes = array();
foreach($aNearPostcodes as $aPostcode)
{
$aPostcodes[] = array('lat' => $aPostcode['lat'], 'lon' => $aPostcode['lon'], 'radius' => 0.005);
}
return $aPostcodes;
}
return false;
@@ -343,7 +384,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',),
@@ -371,6 +412,8 @@
'landuse:commercial' => array('label'=>'Commercial','frequency'=>657,'icon'=>'',),
'place:airport' => array('label'=>'Airport','frequency'=>36,'icon'=>'transport_airport2', 'defdiameter' => 0.03,),
'aeroway:aerodrome' => array('label'=>'Aerodrome','frequency'=>36,'icon'=>'transport_airport2', 'defdiameter' => 0.03,),
'aeroway' => array('label'=>'Aeroway','frequency'=>36,'icon'=>'transport_airport2', 'defdiameter' => 0.03,),
'railway:station' => array('label'=>'Station','frequency'=>3431,'icon'=>'transport_train_station2', 'defdiameter' => 0.01,),
'amenity:place_of_worship' => array('label'=>'Place Of Worship','frequency'=>9049,'icon'=>'place_of_worship_unknown3',),
'amenity:pub' => array('label'=>'Pub','frequency'=>18969,'icon'=>'food_pub',),
@@ -401,7 +444,6 @@
'tourism:hotel' => array('label'=>'Hotel','frequency'=>2150,'icon'=>'accommodation_hotel2',),
'tourism:motel' => array('label'=>'Motel','frequency'=>43,'icon'=>'',),
'amenity:cinema' => array('label'=>'Cinema','frequency'=>277,'icon'=>'tourist_cinema',),
'tourism:information' => array('label'=>'Information','frequency'=>224,'icon'=>'amenity_information',),
'tourism:artwork' => array('label'=>'Artwork','frequency'=>171,'icon'=>'tourist_art_gallery2',),
'historic:archaeological_site' => array('label'=>'Archaeological Site','frequency'=>407,'icon'=>'tourist_archaeological2',),
'amenity:doctors' => array('label'=>'Doctors','frequency'=>581,'icon'=>'health_doctors',),
@@ -443,7 +485,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'=>'',),
@@ -475,6 +517,7 @@
'shop:travel_agency' => array('label'=>'Travel Agency','frequency'=>21,'icon'=>'',),
'shop:hifi' => array('label'=>'Hifi','frequency'=>21,'icon'=>'',),
'amenity:shop' => array('label'=>'Shop','frequency'=>61,'icon'=>'',),
'tourism:information' => array('label'=>'Information','frequency'=>224,'icon'=>'amenity_information',),
'place:house' => array('label'=>'House','frequency'=>2086,'icon'=>'','defzoom'=>18,),
'place:house_name' => array('label'=>'House','frequency'=>2086,'icon'=>'','defzoom'=>18,),
@@ -523,7 +566,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'=>'',),
@@ -589,7 +631,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'=>'',),
@@ -611,7 +653,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'=>'',),
@@ -632,10 +674,12 @@
}
function javascript_renderData($xVal)
function javascript_renderData($xVal, $iOptions = 0)
{
header("Access-Control-Allow-Origin: *");
$jsonout = json_encode($xVal);
if (defined('PHP_VERSION_ID') && PHP_VERSION_ID > 50400)
$iOptions |= JSON_UNESCAPED_UNICODE;
$jsonout = json_encode($xVal, $iOptions);
if( ! isset($_GET['json_callback']))
{
@@ -774,7 +818,7 @@
{
$sTypeLabel = strtolower(isset($aTypeLabel['simplelabel'])?$aTypeLabel['simplelabel']:$aTypeLabel['label']);
$sTypeLabel = str_replace(' ','_',$sTypeLabel);
if (!isset($aAddress[$sTypeLabel]) || (isset($aFallback[$sTypeLabel]) && $aFallback[$sTypeLabel]))
if (!isset($aAddress[$sTypeLabel]) || (isset($aFallback[$sTypeLabel]) && $aFallback[$sTypeLabel]) || $aLine['class'] == 'place')
{
$aAddress[$sTypeLabel] = $aLine['localname']?$aLine['localname']:$aLine['housenumber'];
}
@@ -888,3 +932,93 @@
{
return "'".$s."'";
}
// returns boolean
function validLatLon($fLat,$fLon)
{
return ($fLat <= 90.1 && $fLat >= -90.1 && $fLon <= 180.1 && $fLon >= -180.1);
}
// Do we have anything that looks like a lat/lon pair?
// returns array(lat,lon,query_with_lat_lon_removed)
// or null
function looksLikeLatLonPair($sQuery)
{
$sFound = null;
$fQueryLat = null;
$fQueryLon = null;
// degrees decimal minutes
// N 40 26.767, W 79 58.933
// N 40°26.767, W 79°58.933
// 1 2 3 4 5 6
if (preg_match('/\\b([NS])[ ]+([0-9]+[0-9.]*)[° ]+([0-9.]+)?[\']*[, ]+([EW])[ ]+([0-9]+)[° ]+([0-9]+[0-9.]*)[\']*?\\b/', $sQuery, $aData))
{
$sFound = $aData[0];
$fQueryLat = ($aData[1]=='N'?1:-1) * ($aData[2] + $aData[3]/60);
$fQueryLon = ($aData[4]=='E'?1:-1) * ($aData[5] + $aData[6]/60);
}
// degrees decimal minutes
// 40 26.767 N, 79 58.933 W
// 40° 26.767 N 79° 58.933 W
// 1 2 3 4 5 6
elseif (preg_match('/\\b([0-9]+)[° ]+([0-9]+[0-9.]*)?[\']*[ ]+([NS])[, ]+([0-9]+)[° ]+([0-9]+[0-9.]*)?[\' ]+([EW])\\b/', $sQuery, $aData))
{
$sFound = $aData[0];
$fQueryLat = ($aData[3]=='N'?1:-1) * ($aData[1] + $aData[2]/60);
$fQueryLon = ($aData[6]=='E'?1:-1) * ($aData[4] + $aData[5]/60);
}
// degrees decimal seconds
// N 40 26 46 W 79 58 56
// N 40° 26 46″, W 79° 58 56″
// 1 2 3 4 5 6 7 8
elseif (preg_match('/\\b([NS])[ ]([0-9]+)[° ]+([0-9]+)[\' ]+([0-9]+)[″"]*[, ]+([EW])[ ]([0-9]+)[° ]+([0-9]+)[\' ]+([0-9]+)[″"]*\\b/', $sQuery, $aData))
{
$sFound = $aData[0];
$fQueryLat = ($aData[1]=='N'?1:-1) * ($aData[2] + $aData[3]/60 + $aData[4]/3600);
$fQueryLon = ($aData[5]=='E'?1:-1) * ($aData[6] + $aData[7]/60 + $aData[8]/3600);
}
// degrees decimal seconds
// 40 26 46 N 79 58 56 W
// 40° 26 46″ N, 79° 58 56″ W
// 1 2 3 4 5 6 7 8
elseif (preg_match('/\\b([0-9]+)[° ]+([0-9]+)[\' ]+([0-9]+)[″" ]+([NS])[, ]+([0-9]+)[° ]+([0-9]+)[\' ]+([0-9]+)[″" ]+([EW])\\b/', $sQuery, $aData))
{
$sFound = $aData[0];
$fQueryLat = ($aData[4]=='N'?1:-1) * ($aData[1] + $aData[2]/60 + $aData[3]/3600);
$fQueryLon = ($aData[8]=='E'?1:-1) * ($aData[5] + $aData[6]/60 + $aData[7]/3600);
}
// degrees decimal
// N 40.446° W 79.982°
// 1 2 3 4
elseif (preg_match('/\\b([NS])[ ]([0-9]+[0-9]*\\.[0-9]+)[°]*[, ]+([EW])[ ]([0-9]+[0-9]*\\.[0-9]+)[°]*\\b/', $sQuery, $aData))
{
$sFound = $aData[0];
$fQueryLat = ($aData[1]=='N'?1:-1) * ($aData[2]);
$fQueryLon = ($aData[3]=='E'?1:-1) * ($aData[4]);
}
// degrees decimal
// 40.446° N 79.982° W
// 1 2 3 4
elseif (preg_match('/\\b([0-9]+[0-9]*\\.[0-9]+)[° ]+([NS])[, ]+([0-9]+[0-9]*\\.[0-9]+)[° ]+([EW])\\b/', $sQuery, $aData))
{
$sFound = $aData[0];
$fQueryLat = ($aData[2]=='N'?1:-1) * ($aData[1]);
$fQueryLon = ($aData[4]=='E'?1:-1) * ($aData[3]);
}
// degrees decimal
// 12.34, 56.78
// [12.456,-78.90]
// 1 2 3 4
elseif (preg_match('/(\\[|^|\\b)(-?[0-9]+[0-9]*\\.[0-9]+)[, ]+(-?[0-9]+[0-9]*\\.[0-9]+)(\\]|$|\\b)/', $sQuery, $aData))
{
$sFound = $aData[0];
$fQueryLat = $aData[2];
$fQueryLon = $aData[3];
}
if (!validLatLon($fQueryLat, $fQueryLon)) return;
$sQuery = trim(str_replace($sFound, ' ', $sQuery));
return array('lat' => $fQueryLat, 'lon' => $fQueryLon, 'query' => $sQuery);
}

View File

@@ -3,7 +3,7 @@
function logStart(&$oDB, $sType = '', $sQuery = '', $aLanguageList = array())
{
$aStartTime = explode('.',microtime(true));
if (!$aStartTime[1]) $aStartTime[1] = '0';
if (!isset($aStartTime[1])) $aStartTime[1] = '0';
$sOutputFormat = '';
if (isset($_GET['format'])) $sOutputFormat = $_GET['format'];

View File

@@ -0,0 +1,129 @@
<?php
header("content-type: text/html; charset=UTF-8");
?>
<?php include(CONST_BasePath.'/lib/template/includes/html-header.php'); ?>
<link href="css/common.css" rel="stylesheet" type="text/css" />
<link href="css/search.css" rel="stylesheet" type="text/css" />
</head>
<body id="reverse-page">
<?php include(CONST_BasePath.'/lib/template/includes/html-top-navigation.php'); ?>
<form class="form-inline" role="search" accept-charset="UTF-8" action="<?php echo CONST_Website_BaseURL; ?>reverse.php">
<div class="form-group">
<input name="format" type="hidden" value="html">
<input name="lat" type="text" class="form-control input-sm" placeholder="latitude" value="<?php echo htmlspecialchars($_GET['lat']); ?>" >
<input name="lon" type="text" class="form-control input-sm" placeholder="longitude" value="<?php echo htmlspecialchars($_GET['lon']); ?>" >
max zoom
<select name="zoom" class="form-control input-sm" value="<?php echo htmlspecialchars($_GET['zoom']); ?>">
<option value="" <?php echo $_GET['zoom']==''?'selected':'' ?> >--</option>
<?php
$aZoomLevels = array(
0 => "Continent / Sea",
1 => "",
2 => "",
3 => "Country",
4 => "",
5 => "State",
6 => "Region",
7 => "",
8 => "County",
9 => "",
10 => "City",
11 => "",
12 => "Town / Village",
13 => "",
14 => "Suburb",
15 => "",
16 => "Street",
17 => "",
18 => "Building",
19 => "",
20 => "",
21 => "",
);
foreach($aZoomLevels as $iZoomLevel => $sLabel)
{
$bSel = isset($_GET['zoom']) && ($_GET['zoom'] == (string)$iZoomLevel);
echo '<option value="'.$iZoomLevel.'"'.($bSel?'selected':'').'>'.$iZoomLevel.' '.$sLabel.'</option>'."\n";
}
?>
</select>
</div>
<div class="form-group search-button-group">
<button type="submit" class="btn btn-primary btn-sm">Search</button>
</div>
<div class="search-type-link">
<a href="<?php echo CONST_Website_BaseURL; ?>search.php">forward search</a>
</div>
</form>
<div id="content">
<?php if ($aPlace) { ?>
<div id="searchresults" class="sidebar">
<?php
$aResult = $aPlace;
echo '<div class="result" data-position="0">';
echo (isset($aResult['icon'])?'<img alt="icon" src="'.$aResult['icon'].'"/>':'');
echo ' <span class="name">'.htmlspecialchars($aResult['langaddress']).'</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 '<p>'.$aResult['lat'].','.$aResult['lon'].'</p>';
echo ' <a class="btn btn-default btn-xs details" href="details.php?place_id='.$aResult['place_id'].'">details</a>';
echo '</div>';
?>
</div>
<?php } else { ?>
<div id="intro" class="sidebar">
Search for coordinates or click anywhere on the map.
</div>
<?php } ?>
<div id="map-wrapper">
<div id="map-position"></div>
<div id="map"></div>
</div>
</div> <!-- /content -->
<script type="text/javascript">
<?php
$aNominatimMapInit = array(
'zoom' => isset($_GET['zoom']) ? htmlspecialchars($_GET['zoom']) : CONST_Default_Zoom,
'lat' => isset($_GET['lat'] ) ? htmlspecialchars($_GET['lat'] ) : CONST_Default_Lat,
'lon' => isset($_GET['lon'] ) ? htmlspecialchars($_GET['lon'] ) : CONST_Default_Lon,
'tile_url' => $sTileURL,
'tile_attribution' => $sTileAttribution
);
echo 'var nominatim_map_init = ' . json_encode($aNominatimMapInit) . ';';
echo 'var nominatim_results = ' . json_encode([$aPlace]) . ';';
?>
</script>
<?php include(CONST_BasePath.'/lib/template/includes/html-footer.php'); ?>
</body>
</html>

View File

@@ -10,7 +10,7 @@
}
else
{
if ($aPlace['place_id']) $aFilteredPlaces['place_id'] = $aPlace['place_id'];
if (isset($aPlace['place_id'])) $aFilteredPlaces['place_id'] = $aPlace['place_id'];
$aFilteredPlaces['licence'] = "Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright";
$sOSMType = ($aPlace['osm_type'] == 'N'?'node':($aPlace['osm_type'] == 'W'?'way':($aPlace['osm_type'] == 'R'?'relation':'')));
if ($sOSMType)
@@ -21,7 +21,9 @@
if (isset($aPlace['lat'])) $aFilteredPlaces['lat'] = $aPlace['lat'];
if (isset($aPlace['lon'])) $aFilteredPlaces['lon'] = $aPlace['lon'];
$aFilteredPlaces['display_name'] = $aPlace['langaddress'];
if ($bShowAddressDetails) $aFilteredPlaces['address'] = $aPlace['aAddress'];
if (isset($aPlace['aAddress'])) $aFilteredPlaces['address'] = $aPlace['aAddress'];
if (isset($aPlace['sExtraTags'])) $aFilteredPlaces['extratags'] = $aPlace['sExtraTags'];
if (isset($aPlace['sNameDetails'])) $aFilteredPlaces['namedetails'] = $aPlace['sNameDetails'];
}
javascript_renderData($aFilteredPlaces);

View File

@@ -23,16 +23,19 @@
$aFilteredPlaces['place_rank'] = $aPlace['rank_search'];
$aFilteredPlaces['category'] = $aPlace['class'];
$aFilteredPlaces['type'] = $aPlace['type'];
$aFilteredPlaces['category'] = $aPlace['class'];
$aFilteredPlaces['type'] = $aPlace['type'];
$aFilteredPlaces['importance'] = $aPlace['importance'];
$aFilteredPlaces['addresstype'] = strtolower($aPlace['addresstype']);
$aFilteredPlaces['addresstype'] = strtolower($aPlace['addresstype']);
$aFilteredPlaces['display_name'] = $aPlace['langaddress'];
$aFilteredPlaces['name'] = $aPlace['placename'];
if ($bShowAddressDetails && $aPlace['aAddress'] && sizeof($aPlace['aAddress'])) $aFilteredPlaces['address'] = $aPlace['aAddress'];
$aFilteredPlaces['name'] = $aPlace['placename'];
if (isset($aPlace['aAddress'])) $aFilteredPlaces['address'] = $aPlace['aAddress'];
if (isset($aPlace['sExtraTags'])) $aFilteredPlaces['extratags'] = $aPlace['sExtraTags'];
if (isset($aPlace['sNameDetails'])) $aFilteredPlaces['namedetails'] = $aPlace['sNameDetails'];
}
javascript_renderData($aFilteredPlaces);

View File

@@ -29,7 +29,8 @@
if (isset($aPlace['lon'])) echo ' lon="'.htmlspecialchars($aPlace['lon']).'"';
echo ">".htmlspecialchars($aPlace['langaddress'])."</result>";
if ($bShowAddressDetails) {
if (isset($aPlace['aAddress']))
{
echo "<addressparts>";
foreach($aPlace['aAddress'] as $sKey => $sValue)
{
@@ -40,6 +41,28 @@
}
echo "</addressparts>";
}
if (isset($aPlace['sExtraTags']))
{
echo "<extratags>";
foreach ($aPlace['sExtraTags'] as $sKey => $sValue)
{
echo '<tag key="'.htmlspecialchars($sKey).'" value="'.htmlspecialchars($sValue).'"/>';
}
echo "</extratags>";
}
if (isset($aPlace['sNameDetails']))
{
echo "<namedetails>";
foreach ($aPlace['sNameDetails'] as $sKey => $sValue)
{
echo '<name desc="'.htmlspecialchars($sKey).'">';
echo htmlspecialchars($sValue);
echo "</name>";
}
echo "</namedetails>";
}
}
echo "</reversegeocode>";

View File

@@ -1,180 +1,133 @@
<?php
header("content-type: text/html; charset=UTF-8");
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>OpenStreetMap Nominatim: <?php echo $aPointDetails['localname'];?></title>
<style>
body {
margin:0px;
padding:16px;
background:#ffffff;
height: 100%;
font: normal 12px/15px arial,sans-serif;
}
.line{
margin-left:20px;
}
.name{
font-weight: bold;
}
.notused{
color:#ddd;
}
.noname{
color:#800;
}
#map {
width:500px;
height:500px;
border: 2px solid #666;
float: right;
}
</style>
<script src="js/OpenLayers.js"></script>
<script src="js/tiles.js"></script>
<script type="text/javascript">
var map;
function init() {
map = new OpenLayers.Map ("map", {
controls:[
new OpenLayers.Control.Permalink(),
new OpenLayers.Control.Navigation(),
new OpenLayers.Control.PanZoomBar(),
new OpenLayers.Control.MouseDefaults(),
new OpenLayers.Control.MousePosition(),
new OpenLayers.Control.Attribution()],
maxExtent: new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34),
maxResolution: 156543.0399,
numZoomLevels: 19,
units: 'm',
projection: new OpenLayers.Projection("EPSG:900913"),
displayProjection: new OpenLayers.Projection("EPSG:4326")
} );
map.addLayer(new OpenLayers.Layer.OSM.<?php echo CONST_Tile_Default;?>("Default"));
var layer_style = OpenLayers.Util.extend({}, OpenLayers.Feature.Vector.style['default']);
layer_style.fillOpacity = 0.2;
layer_style.graphicOpacity = 0.2;
vectorLayer = new OpenLayers.Layer.Vector("Points", {style: layer_style});
map.addLayer(vectorLayer);
var proj_EPSG4326 = new OpenLayers.Projection("EPSG:4326");
var proj_map = map.getProjectionObject();
freader = new OpenLayers.Format.WKT({
'internalProjection': proj_map,
'externalProjection': proj_EPSG4326
});
var bounds;
<?php if ($aPointDetails['prevgeom']) { ?>
var feature = freader.read('<?php echo $aPointDetails['prevgeom'];?>');
if (feature) {
bounds = feature.geometry.getBounds();
}
feature.style = {
strokeColor: "#777777",
fillColor: "#F0F0F0",
strokeWidth: 2,
strokeOpacity: 0.75,
fillOpacity: 0.75,
strokeDashstyle: "longdash"
};
vectorLayer.addFeatures([feature]);
<?php } ?>
<?php if ($aPointDetails['newgeom']) { ?>
feature = freader.read('<?php echo $aPointDetails['newgeom'];?>');
if (feature) {
if (!bounds) {
bounds = feature.geometry.getBounds();
}
else
{
bounds.extend(feature.geometry.getBounds());
}
}
feature.style = {
strokeColor: "#75ADFF",
fillColor: "#FFF7F0",
strokeWidth: 2,
strokeOpacity: 0.75,
fillOpacity: 0.75
};
vectorLayer.addFeatures([feature]);
<?php } ?>
<?php if (isset($aPointDetails['error_x'])) { ?>
var pt = new OpenLayers.Geometry.Point(<?php echo $aPointDetails['error_x'].','.$aPointDetails['error_y'];?>);
pt = pt.transform(proj_EPSG4326, proj_map);
feature = new OpenLayers.Feature.Vector(pt, null,
{
graphicName : "x",
fillColor: "#FF0000",
graphic : true,
pointRadius: 6
});
vectorLayer.addFeatures([feature]);
<?php } ?>
<?php include(CONST_BasePath.'/lib/template/includes/html-header.php'); ?>
<link href="css/common.css" rel="stylesheet" type="text/css" />
<link href="css/details.css" rel="stylesheet" type="text/css" />
</head>
map.zoomToExtent(bounds);
}
</script>
</head>
<body onload="init();">
<div id="map"></div>
<h1><?php echo $aPointDetails['localname'] ?></h1>
<div class="locationdetails">
<div>Type: <span class="type"><?php echo $aPointDetails['class'].':'.$aPointDetails['type'];?></span></div>
<?php
$sOSMType = ($aPointDetails['osm_type'] == 'N'?'node':($aPointDetails['osm_type'] == 'W'?'way': ($aPointDetails['osm_type'] == 'R'?'relation':'')));
if ($sOSMType) echo ' <div>OSM: <span class="osm"><span class="label"></span>'.$sOSMType.' <a href="http://www.openstreetmap.org/browse/'.$sOSMType.'/'.$aPointDetails['osm_id'].'">'. $aPointDetails['osm_id'].'</a></span></div>';
function osm_link($aFeature)
{
$sOSMType = ($aFeature['osm_type'] == 'N'?'node':($aFeature['osm_type'] == 'W'?'way':($aFeature['osm_type'] == 'R'?'relation':'')));
if ($sOSMType) {
return '<a href="http://www.openstreetmap.org/browse/'.$sOSMType.'/'.$aFeature['osm_id'].'">'.$sOSMType.' '.$aFeature['osm_id'].'</a>';
}
return '';
}
function osm_map_url($aFeature)
{
$sLon = $aFeature['error_x'];
$sLat = $aFeature['error_y'];
if (isset($sLat))
{
$sOSMType = ($aFeature['osm_type'] == 'N'?'node':($aFeature['osm_type'] == 'W'?'way':($aFeature['osm_type'] == 'R'?'relation':'')));
if ($sOSMType)
{
return "http://www.openstreetmap.org/?lat=".$sLat."&lon=".$sLon."&zoom=18&layers=M&".$sOSMType."=".$aFeature['osm_id'];
}
}
return '';
}
function josm_edit_url($aFeature)
{
$fWidth = 0.0002;
$sLon = $aFeature['error_x'];
$sLat = $aFeature['error_y'];
if (isset($sLat))
{
return "http://localhost:8111/load_and_zoom?left=".($sLon-$fWidth)."&right=".($sLon+$fWidth)."&top=".($sLat+$fWidth)."&bottom=".($sLat-$fWidth);
}
$sOSMType = ($aFeature['osm_type'] == 'N'?'node':($aFeature['osm_type'] == 'W'?'way':($aFeature['osm_type'] == 'R'?'relation':'')));
if ($sOSMType)
{
return 'http://localhost:8111/import?url=http://www.openstreetmap.org/api/0.6/'.$sOSMType.'/'.$aFeature['osm_id'].'/full';
// Should be better to load by object id - but this doesn't seem to zoom correctly
// return " <a href=\"http://localhost:8111/load_object?new_layer=true&objects=".strtolower($aFeature['osm_type']).$sOSMID."\" target=\"josm\">Remote Control (JOSM / Merkaartor)</a>";
}
return '';
}
function potlach_edit_url($aFeature)
{
$fWidth = 0.0002;
$sLat = $aFeature['error_y'];
$sLon = $aFeature['error_x'];
if (isset($sLat))
{
return "http://www.openstreetmap.org/edit?editor=potlatch2&bbox=".($sLon-$fWidth).",".($sLat-$fWidth).",".($sLon+$fWidth).",".($sLat+$fWidth);
}
return '';
}
?>
<p>This object has an invalid geometry.</p>
<p><b>Details:</b> <?php
<body id="details-page">
<div class="container">
<div class="row">
<div class="col-md-6">
$sVal = $aPointDetails['errormessage']?$aPointDetails['errormessage']:'&nbsp;';
$sOSMType = ($aPointDetails['osm_type'] == 'N'?'node':($aPointDetails['osm_type'] == 'W'?'way':($aPointDetails['osm_type'] == 'R'?'relation':'')));
$sOSMID = $aPointDetails['osm_id'];
if (isset($aPointDetails['error_x']))
{
$sLat = $aPointDetails['error_y'];
$sLon = $aPointDetails['error_x'];
echo "<a href=\"http://www.openstreetmap.org/?lat=".$sLat."&lon=".$sLon."&zoom=18&layers=M&".$sOSMType."=".$sOSMID."\">".$sVal."</a>";
}
else
{
echo $sVal;
}
?>
<p><b>Edit:</b> in <?php
if (isset($aPointDetails['error_x']))
{
$fWidth = 0.0002;
echo " <a href=\"http://localhost:8111/load_and_zoom?left=".($sLon-$fWidth)."&right=".($sLon+$fWidth)."&top=".($sLat+$fWidth)."&bottom=".($sLat-$fWidth)."\" target=\"josm\">Remote Control (JOSM / Merkaartor)</a>";
echo " | <a href=\"http://www.openstreetmap.org/edit?editor=potlatch2&bbox=".($sLon-$fWidth).",".($sLat-$fWidth).",".($sLon+$fWidth).",".($sLat+$fWidth)."\" target=\"potlatch2\">Potlatch 2</a>";
}
else
{
echo " <a href=\"http://localhost:8111/import?url=http://www.openstreetmap.org/api/0.6/".$sOSMType.'/'.$sOSMID."/full\" target=\"josm\">Remote Control (JOSM / Merkaartor)</a>";
// Should be better to load by object id - but this doesn't seem to zoom correctly
//echo " <a href=\"http://localhost:8111/load_object?new_layer=true&objects=".strtolower($aPointDetails['osm_type']).$sOSMID."\" target=\"josm\">Remote Control (JOSM / Merkaartor)</a>";
}
<h1><?php echo $aPointDetails['localname'] ?></h1>
<div class="locationdetails">
<h2 class="bg-danger">This object has an invalid geometry.</h2>
?></p>
<div>
Type: <span class="type"><?php echo $aPointDetails['class'].':'.$aPointDetails['type'];?></span>
</div>
</body>
</html>
<div>
OSM: <span class="label"><?php echo osm_link($aPointDetails); ?><span>
</div>
<h4>Error</h4>
<p>
<?php echo $aPointDetails['errormessage']?$aPointDetails['errormessage']:'unknown'; ?>
</p>
<?php if (osm_map_url($aPointDetails)) { ?>
<a href="<?php echo osm_map_url($aPointDetails); ?>">view on osm.org</a>
<?php } ?>
<h4>Edit</h4>
<ul>
<?php if (josm_edit_url($aPointDetails)) { ?>
<li><a href="<?php echo josm_edit_url($aPointDetails); ?>" target="josm">Remote Control (JOSM / Merkaartor)</a></li>
<?php } ?>
<?php if (potlach_edit_url($aPointDetails)) { ?>
<li><a href="<?php echo potlach_edit_url($aPointDetails); ?>" target="potlatch2">Potlatch 2</a></li>
<?php } ?>
</ul>
</div>
</div>
<div class="col-md-6">
<div id="map"></div>
</div>
</div>
<script type="text/javascript">
var nominatim_result = {
outlinestring: '<?php echo $aPointDetails['outlinestring'];?>',
lon: <?php echo isset($aPointDetails['error_x']) ? $aPointDetails['error_x'] : 0; ?>,
lat: <?php echo isset($aPointDetails['error_y']) ? $aPointDetails['error_y'] : 0; ?>
};
</script>
<?php include(CONST_BasePath.'/lib/template/includes/html-footer.php'); ?>
</body>
</html>

View File

@@ -1,229 +1,301 @@
<?php
header("content-type: text/html; charset=UTF-8");
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>OpenStreetMap Nominatim: <?php echo $aPointDetails['localname'];?></title>
<link href="css/details.css" rel="stylesheet" type="text/css" />
<script src="js/OpenLayers.js" type="text/javascript"></script>
<script src="js/tiles.js" type="text/javascript"></script>
<script type="text/javascript">
<?php include(CONST_BasePath.'/lib/template/includes/html-header.php'); ?>
<link href="css/common.css" rel="stylesheet" type="text/css" />
<link href="css/details.css" rel="stylesheet" type="text/css" />
</head>
var map;
function init() {
map = new OpenLayers.Map ("map", {
controls:[
new OpenLayers.Control.Permalink(),
new OpenLayers.Control.Navigation(),
new OpenLayers.Control.PanZoomBar(),
new OpenLayers.Control.MousePosition(),
new OpenLayers.Control.Attribution()],
maxExtent: new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34),
maxResolution: 156543.0399,
numZoomLevels: 19,
units: 'm',
projection: new OpenLayers.Projection("EPSG:900913"),
displayProjection: new OpenLayers.Projection("EPSG:4326")
} );
map.addLayer(new OpenLayers.Layer.OSM.<?php echo CONST_Tile_Default;?>("Default"));
var layer_style = OpenLayers.Util.extend({}, OpenLayers.Feature.Vector.style['default']);
layer_style.fillOpacity = 0.2;
layer_style.graphicOpacity = 0.2;
vectorLayer = new OpenLayers.Layer.Vector("Points", {style: layer_style});
map.addLayer(vectorLayer);
var proj_EPSG4326 = new OpenLayers.Projection("EPSG:4326");
var proj_map = map.getProjectionObject();
freader = new OpenLayers.Format.WKT({
'internalProjection': proj_map,
'externalProjection': proj_EPSG4326
});
var feature = freader.read('<?php echo $aPointDetails['outlinestring'];?>');
var featureCentre = freader.read('POINT(<?php echo $aPointDetails['lon'];?> <?php echo $aPointDetails['lat'];?>)');
if (feature) {
map.zoomToExtent(feature.geometry.getBounds());
feature.style = {
strokeColor: "#75ADFF",
fillColor: "#F0F7FF",
strokeWidth: <?php echo ($aPointDetails['isarea']=='t'?'2':'5');?>,
strokeOpacity: 0.75,
fillOpacity: 0.75,
pointRadius: 50
};
<?php if ($aPointDetails['isarea']=='t') {?>
featureCentre.style = {
strokeColor: "#008800",
fillColor: "#338833",
strokeWidth: <?php echo ($aPointDetails['isarea']=='t'?'2':'5');?>,
strokeOpacity: 0.75,
fillOpacity: 0.75,
pointRadius: 8
};
vectorLayer.addFeatures([feature,featureCentre]);
<?php } else { ?>
vectorLayer.addFeatures([feature]);
<?php } ?>
}
}
</script>
</head>
<body onload="init();">
<div id="map"></div>
<?php
echo '<h1>';
if ($aPointDetails['icon'])
{
echo '<img style="float:right;margin-right:40px;" src="'.CONST_Website_BaseURL.'images/mapicons/'.$aPointDetails['icon'].'.n.32.png'.'" alt="'.$aPointDetails['icon'].'" />';
}
echo $aPointDetails['localname'].'</h1>';
echo '<div class="locationdetails">';
echo ' <div>Name: ';
foreach($aPointDetails['aNames'] as $sKey => $sValue)
{
echo ' <div class="line"><span class="name">'.$sValue.'</span> ('.$sKey.')</div>';
}
echo ' </div>';
echo ' <div>Type: <span class="type">'.$aPointDetails['class'].':'.$aPointDetails['type'].'</span></div>';
echo ' <div>Last Updated: <span class="type">'.$aPointDetails['indexed_date'].'</span></div>';
echo ' <div>Admin Level: <span class="adminlevel">'.$aPointDetails['admin_level'].'</span></div>';
echo ' <div>Rank: <span class="rankaddress">'.$aPointDetails['rank_search_label'].'</span></div>';
if ($aPointDetails['calculated_importance']) echo ' <div>Importance: <span class="rankaddress">'.$aPointDetails['calculated_importance'].($aPointDetails['importance']?'':' (estimated)').'</span></div>';
echo ' <div>Coverage: <span class="area">'.($aPointDetails['isarea']=='t'?'Polygon':'Point').'</span></div>';
echo ' <div>Centre Point: <span class="area">'.$aPointDetails['lat'].','.$aPointDetails['lon'].'</span></div>';
$sOSMType = ($aPointDetails['osm_type'] == 'N'?'node':($aPointDetails['osm_type'] == 'W'?'way':($aPointDetails['osm_type'] == 'R'?'relation':'')));
if ($sOSMType) echo ' <div>OSM: <span class="osm">'.$sOSMType.' <a href="http://www.openstreetmap.org/browse/'.$sOSMType.'/'.$aPointDetails['osm_id'].'">'.$aPointDetails['osm_id'].'</a></span></div>';
if ($aPointDetails['wikipedia'])
{
list($sWikipediaLanguage,$sWikipediaArticle) = explode(':',$aPointDetails['wikipedia']);
echo ' <div>Wikipedia Calculated: <span class="wikipedia"><a href="http://'.$sWikipediaLanguage.'.wikipedia.org/wiki/'.urlencode($sWikipediaArticle).'">'.$aPointDetails['wikipedia'].'</a></span></div>';
}
echo ' <div>Extra Tags: ';
foreach($aPointDetails['aExtraTags'] as $sKey => $sValue)
{
echo ' <div class="line"><span class="name">'.$sValue.'</span> ('.$sKey.')</div>';
}
echo ' </div>';
echo '</div>';
echo '<h2>Address</h2>';
echo '<div class="address">';
$iPrevRank = 1000000;
$sPrevLocalName = '';
foreach($aAddressLines as $aAddressLine)
{
$sOSMType = ($aAddressLine['osm_type'] == 'N'?'node':($aAddressLine['osm_type'] == 'W'?'way':($aAddressLine['osm_type'] == 'R'?'relation':'')));
function headline($sTitle)
{
echo "<tr class='all-columns'><td colspan='6'><h2>".$sTitle."</h2></td></tr>\n";
}
echo '<div class="line'.($aAddressLine['isaddress']=='f'?' notused':'').'">';
if (!($iPrevRank<=$aAddressLine['rank_address'] || $sPrevLocalName == $aAddressLine['localname']))
function headline3($sTitle)
{
echo "<tr class='all-columns'><td colspan='6'><h3>".$sTitle."</h3></td></tr>\n";
}
function osm_link($aFeature)
{
$sOSMType = ($aFeature['osm_type'] == 'N'?'node':($aFeature['osm_type'] == 'W'?'way':($aFeature['osm_type'] == 'R'?'relation':'')));
if ($sOSMType)
{
$iPrevRank = $aAddressLine['rank_address'];
$sPrevLocalName = $aAddressLine['localname'];
return '<a href="http://www.openstreetmap.org/browse/'.$sOSMType.'/'.$aFeature['osm_id'].'">'.$sOSMType.' '.$aFeature['osm_id'].'</a>';
}
echo '<span class="name">'.(trim($aAddressLine['localname'])?$aAddressLine['localname']:'<span class="noname">No Name</span>').'</span>';
echo ' (';
echo '<span class="type"><span class="label">Type: </span>'.$aAddressLine['class'].':'.$aAddressLine['type'].'</span>';
if ($sOSMType) echo ', <span class="osm">'.$sOSMType.' <a href="http://www.openstreetmap.org/browse/'.$sOSMType.'/'.$aAddressLine['osm_id'].'">'.$aAddressLine['osm_id'].'</a></span>';
if (isset($aAddressLine['admin_level'])) echo ', <span class="adminlevel">'.$aAddressLine['admin_level'].'</span>';
if (isset($aAddressLine['rank_search_label'])) echo ', <span class="rankaddress">'.$aAddressLine['rank_search_label'].'</span>';
// echo ', <span class="area">'.($aAddressLine['fromarea']=='t'?'Polygon':'Point').'</span>';
echo ', <span class="distance">'.$aAddressLine['distance'].'</span>';
echo ' <a href="details.php?place_id='.$aAddressLine['place_id'].'">GOTO</a>';
echo ')';
echo '</div>';
return '';
}
echo '</div>';
function wikipedia_link($aFeature)
{
if ($aFeature['wikipedia'])
{
list($sWikipediaLanguage,$sWikipediaArticle) = explode(':',$aFeature['wikipedia']);
return '<a href="https://'.$sWikipediaLanguage.'.wikipedia.org/wiki/'.urlencode($sWikipediaArticle).'" target="_blank">'.$aFeature['wikipedia'].'</a>';
}
return '';
}
function nominatim_link($aFeature, $sTitle)
{
return '<a href="details.php?place_id='.$aFeature['place_id'].'">'.$sTitle.'</a>';
}
function format_distance($fDistance)
{
// $fDistance is in meters
if ($fDistance < 1)
{
return '0';
}
elseif ($fDistance < 1000)
{
return'<abbr class="distance" title="'.$fDistance.'">~'.(round($fDistance,0)).' m</abbr>';
}
else
{
return'<abbr class="distance" title="'.$fDistance.'">~'.(round($fDistance/1000,1)).' km</abbr>';
}
}
function kv($sKey,$sValue)
{
echo ' <tr><td>' . $sKey . '</td><td>'.$sValue.'</td></tr>'. "\n";
}
function hash_to_subtable($aAssociatedList)
{
$sHTML = '';
foreach($aAssociatedList as $sKey => $sValue)
{
$sHTML = $sHTML.' <div class="line"><span class="name">'.$sValue.'</span> ('.$sKey.')</div>'."\n";
}
return $sHTML;
}
// function hash_to_subtable($aAssociatedList)
// {
// $sHTML = '<table class="table">';
// foreach($aAssociatedList as $sKey => $sValue)
// {
// $sHTML = $sHTML . '<tr><td>'.$sKey.'</td><td class="name">'.$sValue.'</td></tr>'."\n";
// }
// $sHTML = $sHTML . '</table>';
// return $sHTML;
// }
function map_icon($sIcon)
{
if ($sIcon){
echo '<img id="mapicon" src="'.CONST_Website_BaseURL.'images/mapicons/'.$sIcon.'.n.32.png'.'" alt="'.$sIcon.'" />';
}
}
function _one_row($aAddressLine){
$bNotUsed = (isset($aAddressLine['isaddress']) && $aAddressLine['isaddress'] == 'f');
echo '<tr class="' . ($bNotUsed?'notused':'') . '">'."\n";
echo ' <td class="name">'.(trim($aAddressLine['localname'])?$aAddressLine['localname']:'<span class="noname">No Name</span>')."</td>\n";
echo ' <td>' . $aAddressLine['class'].':'.$aAddressLine['type'] . "</td>\n";
echo ' <td>' . osm_link($aAddressLine) . "</td>\n";
echo ' <td>' . (isset($aAddressLine['admin_level']) ? $aAddressLine['admin_level'] : '') . "</td>\n";
// echo '<td>' . (isset($aAddressLine['rank_search_label']) ? $aAddressLine['rank_search_label'] : '') ."</td>\n";
// echo ', <span class="area">'.($aAddressLine['fromarea']=='t'?'Polygon':'Point').'</span>';
echo ' <td>' . format_distance($aAddressLine['distance'])."</td>\n";
echo ' <td>' . nominatim_link($aAddressLine,'details &gt;') . "</td>\n";
echo "</tr>\n";
}
function _one_keyword_row($keyword_token,$word_id){
echo "<tr>\n";
echo '<td>';
// mark partial tokens (those starting with a space) with a star for readability
echo ($keyword_token[0]==' '?'*':'');
echo $keyword_token;
if (isset($word_id))
{
echo '</td><td>word id: '.$word_id;
}
echo "</td></tr>\n";
}
?>
<body id="details-page">
<?php include(CONST_BasePath.'/lib/template/includes/html-top-navigation.php'); ?>
<div class="container">
<div class="row">
<div class="col-sm-10">
<h1><?php echo $aPointDetails['localname'] ?></h1>
</div>
<div class="col-sm-2 text-right">
<?php map_icon($aPointDetails['icon']) ?>
</div>
</div>
<div class="row">
<div class="col-md-6">
<table id="locationdetails" class="table table-striped">
<?php
kv('Name' , hash_to_subtable($aPointDetails['aNames']) );
kv('Type' , $aPointDetails['class'].':'.$aPointDetails['type'] );
kv('Last Updated' , $aPointDetails['indexed_date'] );
kv('Admin Level' , $aPointDetails['admin_level'] );
kv('Rank' , $aPointDetails['rank_search_label'] );
if ($aPointDetails['calculated_importance']) {
kv('Importance' , $aPointDetails['calculated_importance'].($aPointDetails['importance']?'':' (estimated)') );
}
kv('Coverage' , ($aPointDetails['isarea']=='t'?'Polygon':'Point') );
kv('Centre Point' , $aPointDetails['lat'].','.$aPointDetails['lon'] );
kv('OSM' , osm_link($aPointDetails) );
if ($aPointDetails['wikipedia'])
{
kv('Wikipedia Calculated' , wikipedia_link($aPointDetails) );
}
kv('Extra Tags' , hash_to_subtable($aPointDetails['aExtraTags']) );
?>
</table>
</div>
<div class="col-md-6">
<div id="map"></div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<h2>Address</h2>
<table id="address" class="table table-striped table-responsive">
<thead>
<tr>
<td>Local name</td>
<td>Type</td>
<td>OSM</td>
<td>Admin level</td>
<!-- <td>Search rank</td> -->
<td>Distance</td>
<td></td>
</tr>
</thead>
<tbody>
<?php
foreach($aAddressLines as $aAddressLine)
{
_one_row($aAddressLine);
}
?>
<?php
if ($aLinkedLines)
{
echo '<h2>Linked Places</h2>';
echo '<div class=\"linked\">';
headline('Linked Places');
foreach($aLinkedLines as $aAddressLine)
{
$sOSMType = ($aAddressLine['osm_type'] == 'N'?'node':($aAddressLine['osm_type'] == 'W'?'way':($aAddressLine['osm_type'] == 'R'?'relation':'')));
echo '<div class="line">';
echo '<span class="name">'.(trim($aAddressLine['localname'])?$aAddressLine['localname']:'<span class="noname">No Name</span>').'</span>';
echo ' (';
echo '<span class="type"><span class="label">Type: </span>'.$aAddressLine['class'].':'.$aAddressLine['type'].'</span>';
if ($sOSMType) echo ', <span class="osm"><span class="label"></span>'.$sOSMType.' <a href="http://www.openstreetmap.org/browse/'.$sOSMType.'/'.$aAddressLine['osm_id'].'">'.$aAddressLine['osm_id'].'</a></span>';
echo ', <span class="adminlevel">'.$aAddressLine['admin_level'].'</span>';
echo ', <span class="rankaddress">'.$aAddressLine['rank_search_label'].'</span>';
// echo ', <span class="area">'.($aAddressLine['fromarea']=='t'?'Polygon':'Point').'</span>';
echo ', <span class="distance">'.$aAddressLine['distance'].'</span>';
echo ' <a href="details.php?place_id='.$aAddressLine['place_id'].'">GOTO</a>';
echo ')';
echo '</div>';
_one_row($aAddressLine);
}
echo '</div>';
}
if ($aPlaceSearchNameKeywords)
{
echo '<h2>Name Keywords</h2>';
headline('Name Keywords');
foreach($aPlaceSearchNameKeywords as $aRow)
{
echo '<div>'.$aRow['word_token'].'</div>';
_one_keyword_row($aRow['word_token'], $aRow['word_id']);
}
}
if ($aPlaceSearchAddressKeywords)
{
echo '<h2>Address Keywords</h2>';
headline('Address Keywords');
foreach($aPlaceSearchAddressKeywords as $aRow)
{
echo '<div>'.($aRow['word_token'][0]==' '?'*':'').$aRow['word_token'].'('.$aRow['word_id'].')'.'</div>';
_one_keyword_row($aRow['word_token'], $aRow['word_id']);
}
}
if (sizeof($aParentOfLines))
{
echo '<h2>Parent Of:</h2>';
headline('Parent Of');
$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)
{
$sGroupHeading = ucwords($sGroupHeading);
echo "<h3>$sGroupHeading</h3>";
foreach($aParentOfLines as $aAddressLine)
{
$aAddressLine['localname'] = $aAddressLine['localname']?$aAddressLine['localname']:$aAddressLine['housenumber'];
$sOSMType = ($aAddressLine['osm_type'] == 'N'?'node':($aAddressLine['osm_type'] == 'W'?'way':($aAddressLine['osm_type'] == 'R'?'relation':'')));
echo '<div class="line">';
echo '<span class="name">'.(trim($aAddressLine['localname'])?$aAddressLine['localname']:'<span class="noname">No Name</span>').'</span>';
echo ' (';
// echo '<span class="type"><span class="label">Type: </span>'.$aAddressLine['class'].':'.$aAddressLine['type'].'</span>';
// echo ', <span class="adminlevel">'.$aAddressLine['admin_level'].'</span>';
// echo ', <span class="rankaddress">'.$aAddressLine['rank_address'].'</span>';
echo '<span class="area">'.($aAddressLine['isarea']=='t'?'Polygon':'Point').'</span>';
echo ', <span class="distance">~'.(round($aAddressLine['distance']*69,1)).'&nbsp;miles</span>';
if ($sOSMType) echo ', <span class="osm"><span class="label"></span>'.$sOSMType.' <a href="http://www.openstreetmap.org/browse/'.$sOSMType.'/'.$aAddressLine['osm_id'].'">'.$aAddressLine['osm_id'].'</a></span>';
echo ', <a href="details.php?place_id='.$aAddressLine['place_id'].'">GOTO</a>';
echo ')';
echo '</div>';
}
headline3($sGroupHeading);
foreach($aParentOfLines as $aAddressLine)
{
_one_row($aAddressLine);
}
}
if (sizeof($aParentOfLines) >= 500) {
echo '<p>There are more child objects which are not shown.</p>';
}
echo '</div>';
}
// echo '<h2>Other Parts:</h2>';
// echo '<h2>Linked To:</h2>';
// headline('Other Parts');
// headline('Linked To');
echo "</table>\n";
?>
</body>
</div>
</div>
</div>
<script type="text/javascript">
<?php
$aNominatimMapInit = array(
'tile_url' => $sTileURL,
'tile_attribution' => $sTileAttribution
);
echo 'var nominatim_map_init = ' . json_encode($aNominatimMapInit) . ';';
$aPlace = array(
'outlinestring' => $aPointDetails['outlinestring'],
'lon' => $aPointDetails['lon'],
'lat' => $aPointDetails['lat'],
);
echo 'var nominatim_result = ' . json_encode($aPlace) . ';';
?>
</script>
<?php include(CONST_BasePath.'/lib/template/includes/html-footer.php'); ?>
</body>
</html>

View File

@@ -0,0 +1,14 @@
<footer>
<p class="disclaimer">
Addresses and postcodes are approximate
</p>
<p class="copyright">
&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors
</p>
</footer>
<script src="js/jquery.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="js/leaflet.min.js"></script>
<script src="js/leaflet-omnivore.min.js"></script>
<script src="js/nominatim-ui.js"></script>

View File

@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>OpenStreetMap Nominatim: Search</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<base href="<?php echo CONST_Website_BaseURL;?>" />
<link href="nominatim.xml" rel="search" title="Nominatim Search" type="application/opensearchdescription+xml" />
<link href="css/leaflet.css" rel="stylesheet" />
<link href="css/bootstrap-theme.min.css" rel="stylesheet" />
<link href="css/bootstrap.min.css" rel="stylesheet" />

View File

@@ -0,0 +1,49 @@
<header class="container-fluid">
<div class="row">
<div class="col-xs-4">
<div class="brand">
<a href="<?php echo CONST_Website_BaseURL;?>">
<img alt="logo" src="images/osm_logo.120px.png" width="30" height="30"/>
<h1>Nominatim</h1>
</a>
</div>
</div>
<div id="last-updated" class="col-xs-4 text-center">
<?php if (isset($sDataDate)){ ?>
Data last updated:
<br>
<?php echo $sDataDate; ?>
<?php } ?>
</div>
<div class="col-xs-4 text-right">
<div class="btn-group">
<button class="dropdown-toggle btn btn-sm btn-default" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
About &amp; Help <span class="caret"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li><a href="http://wiki.openstreetmap.org/wiki/Nominatim" target="_blank">Documentation</a></li>
<li><a href="http://wiki.openstreetmap.org/wiki/Nominatim/FAQ" target="_blank">FAQ</a></li>
<li role="separator" class="divider"></li>
<li><a href="#" class="" data-toggle="modal" data-target="#report-modal">Report problem with results</a></li>
</ul>
</div>
</div>
</div>
</header>
<div class="modal fade" id="report-modal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Report a problem</h4>
</div>
<div class="modal-body">
<?php include(CONST_BasePath.'/lib/template/includes/report-errors.php'); ?>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">OK</button>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,9 @@
<h2>Welcome to Nominatim</h2>
<p>Nominatim is a search engine for <a href="http://www.openstreetmap.org">OpenStreetMap</a>
data. This is the debugging interface. You may search for a name or address(forward search) or
look up data by its geographic coordinate(reverse search). Each result comes with a
link to a details page where you can inspect what data about the object is saved in
the database and investigate how the address of the object has been computed.</p>
For more information visit the <a href="http://wiki.openstreetmap.org/wiki/Nominatim">Nominatim wiki page</a>.

View File

@@ -0,0 +1,24 @@
<p>
Before reporting problems please read the <a target="_blank" href="http://wiki.openstreetmap.org/wiki/Nominatim">user documentation</a>
and
<a target="_blank" href="http://wiki.openstreetmap.org/wiki/Nominatim/FAQ">FAQ</a>.
If your problem relates to the address of a particular search result please use the 'details' link
to check how the address was generated before reporting a problem.
</p>
<p>
Use <a target="_blank" href="https://github.com/twain47/nominatim/issues">Nominatim issues on github</a>
to report problems.
<!-- You can search for existing bug reports
<a href="http://trac.openstreetmap.org/query?status=new&amp;status=assigned&amp;status=reopened&amp;component=nominatim&amp;order=priority">here</a>.</p>
-->
</p>
<p>
Please ensure that you include a full description of the problem, including the search
query that you used, the problem with the result and, if the problem relates to missing data,
the osm type (node, way, relation) and id of the item that is missing.
</p>
<p>
Problems that contain enough detail are likely to get looked at before ones that require
significant research.
</p>

View File

@@ -1,298 +1,114 @@
<?php
header("content-type: text/html; charset=UTF-8");
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>OpenStreetMap Nominatim: Search</title>
<base href="<?php echo CONST_Website_BaseURL;?>" />
<link href="nominatim.xml" rel="search" title="Nominatim Search" type="application/opensearchdescription+xml" />
<?php include(CONST_BasePath.'/lib/template/includes/html-header.php'); ?>
<link href="css/common.css" rel="stylesheet" type="text/css" />
<link href="css/search.css" rel="stylesheet" type="text/css" />
<script src="js/OpenLayers.js" type="text/javascript"></script>
<script src="js/tiles.js" type="text/javascript"></script>
<script src="js/prototype-1.6.0.3.js" type="text/javascript"></script>
<script type="text/javascript">
var map;
function handleResize()
{
if ($('searchresults'))
{
var viewwidth = ((document.documentElement.clientWidth > 0?document.documentElement.clientWidth:document.documentElement.offsetWidth) - 200) + 'px';
$('map').style.width = viewwidth;
$('report').style.width = viewwidth;
}
else
{
$('map').style.width = ((document.documentElement.clientWidth > 0?document.documentElement.clientWidth:document.documentElement.offsetWidth) - 0) + 'px';
$('map').style.left = '0px';
}
if ($('map')) $('map').style.height = ((document.documentElement.clientHeight > 0?document.documentElement.clientHeight:document.documentElement.offsetHeight) - 38) + 'px';
if ($('searchresults')) $('searchresults').style.height = ((document.documentElement.clientHeight > 0?document.documentElement.clientHeight:document.documentElement.offsetHeight) - 38) + 'px';
if ($('report')) $('report').style.height = ((document.documentElement.clientHeight > 0?document.documentElement.clientHeight:document.documentElement.offsetHeight) - 38) + 'px';
}
window.onresize = handleResize;
function panToLatLon(lat,lon) {
var lonLat = new OpenLayers.LonLat(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
map.panTo(lonLat, <?php echo $iZoom ?>);
}
function panToLatLonZoom(lat, lon, zoom) {
var lonLat = new OpenLayers.LonLat(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
if (zoom != map.getZoom())
map.setCenter(lonLat, zoom);
else
map.panTo(lonLat, 10);
}
function panToLatLonBoundingBox(lat,lon,minlat,maxlat,minlon,maxlon,wkt) {
vectorLayer.destroyFeatures();
var proj_EPSG4326 = new OpenLayers.Projection("EPSG:4326");
var proj_map = map.getProjectionObject();
map.zoomToExtent(new OpenLayers.Bounds(minlon,minlat,maxlon,maxlat).transform(proj_EPSG4326, proj_map));
var lonLat = new OpenLayers.LonLat(lon, lat).transform(proj_EPSG4326, proj_map);
map.panTo(lonLat, <?php echo $iZoom ?>);
if (wkt)
{
var freader = new OpenLayers.Format.WKT({
'internalProjection': proj_map,
'externalProjection': proj_EPSG4326
});
var feature = freader.read(wkt);
if (feature)
{
feature.style = {
strokeColor: "#75ADFF",
fillColor: "#F0F7FF",
strokeWidth: 2,
strokeOpacity: 0.75,
fillOpacity: 0.75,
pointRadius: 100
};
vectorLayer.addFeatures([feature]);
}
}
}
function round(v,n)
{
n = Math.pow(10,n);
return Math.round(v*n)/n;
}
function floor(v,n)
{
n = Math.pow(10,n);
return Math.floor(v*n)/n;
}
function ceil(v,n)
{
n = Math.pow(10,n);
return Math.ceil(v*n)/n;
}
function mapEventMove() {
var proj = new OpenLayers.Projection("EPSG:4326");
var bounds = map.getExtent();
bounds = bounds.transform(map.getProjectionObject(), proj);
$('viewbox').value = floor(bounds.left,2)+','+ceil(bounds.top,2)+','+ceil(bounds.right,2)+','+floor(bounds.bottom,2);
}
function init() {
handleResize();
map = new OpenLayers.Map ("map", {
controls:[
new OpenLayers.Control.Navigation(),
new OpenLayers.Control.PanZoomBar(),
new OpenLayers.Control.MousePosition(),
new OpenLayers.Control.Attribution()],
maxExtent: new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34),
maxResolution: 156543.0399,
numZoomLevels: 19,
units: 'm',
projection: new OpenLayers.Projection("EPSG:900913"),
displayProjection: new OpenLayers.Projection("EPSG:4326"),
eventListeners: {
"moveend": mapEventMove
}
} );
map.addLayer(new OpenLayers.Layer.OSM.<?php echo CONST_Tile_Default;?>("Default"));
var layer_style = OpenLayers.Util.extend({}, OpenLayers.Feature.Vector.style['default']);
layer_style.fillOpacity = 0.2;
layer_style.graphicOpacity = 1;
vectorLayer = new OpenLayers.Layer.Vector("Points", {style: layer_style});
map.addLayer(vectorLayer);
// var lonLat = new OpenLayers.LonLat(<?php echo $fLon ?>, <?php echo $fLat ?>).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
// map.setCenter (lonLat, <?php echo $iZoom ?>);
}
function setfocus(field_id) {
$(field_id).focus()
}
</script>
</head>
<body onload="setfocus('q');">
<body id="search-page">
<div id="seachheaderfade1"></div><div id="seachheaderfade2"></div><div id="seachheaderfade3"></div><div id="seachheaderfade4"></div>
<?php include(CONST_BasePath.'/lib/template/includes/html-top-navigation.php'); ?>
<div id="seachheader">
<form accept-charset="UTF-8" action="<?php echo CONST_Website_BaseURL; ?>search.php" method="get">
<table border="0" width="100%" summary="header">
<tr>
<td valign="middle" style="width:30px;"><img alt="logo" src="images/logo.gif" /></td>
<td valign="middle" style="width:400px;"><input id="q" name="q" value="<?php echo htmlspecialchars($sQuery);
?>" style="width:270px;" /><input type="text" id="viewbox" style="width:120px;" name="viewbox" /></td>
<td style="width:80px;"><input type="submit" value="Search"/></td>
<?php if (CONST_Search_AreaPolygons) { ?> <td style="width:100px;"><input type="checkbox" value="1" name="polygon" <?php if ($bAsText) echo "checked='checked'"; ?>/> Highlight</td>
<td style="text-align:right;">Data: <?php echo $sDataDate; ?></td>
<td style="text-align:right;">
<a href="http://wiki.openstreetmap.org/wiki/Nominatim" target="_blank">Documentation</a> | <a href="http://wiki.openstreetmap.org/wiki/Nominatim/FAQ"
target="_blank">FAQ</a></td>
<?php } ?> <td style="text-align:right;"><?php if ($sQuery) { ?><input type="button" value="Report Problem With Results" onclick="$('report').style.visibility=($('report').style.visibility=='hidden'?'visible':'hidden')"/><?php } ?></td>
</tr>
</table>
</form>
</div>
<?php
if ($sQuery)
{
?>
<div id="searchresultsfade1"></div><div id="searchresultsfade2"></div><div id="searchresultsfade3"></div><div id="searchresultsfade4"></div>
<div id="searchresults">
<?php
if ($sSuggestionURL)
{
echo '<div class="more"><b>Suggest: </b><a href="'.$sSuggestionURL.'"><b>'.$sSuggestion.'</b></a></div>';
}
foreach($aSearchResults as $iResNum => $aResult)
{
if ($aResult['aBoundingBox'])
{
echo '<div class="result" onClick=\'panToLatLonBoundingBox('.$aResult['lat'].', '.$aResult['lon'];
echo ', '.$aResult['aBoundingBox'][0];
echo ', '.$aResult['aBoundingBox'][1];
echo ', '.$aResult['aBoundingBox'][2];
echo ', '.$aResult['aBoundingBox'][3];
if (isset($aResult['astext'])) echo ', "'.$aResult['astext'].'"';
echo ");'>\n";
}
elseif (isset($aResult['zoom']))
{
echo '<div class="result" onClick="panToLatLonZoom('.$aResult['lat'].', '.$aResult['lon'].', '.$aResult['zoom'].');">';
}
else
{
echo '<div class="result" onClick="panToLatLon('.$aResult['lat'].', '.$aResult['lon'].');">';
}
echo (isset($aResult['icon'])?'<img alt="icon" src="'.$aResult['icon'].'"/>':'');
echo ' <span class="name">'.$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
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>';
echo '</div>';
}
if (sizeof($aSearchResults))
{
if ($sMoreURL)
{
echo '<div class="more"><a href="'.htmlentities($sMoreURL).'">Search for more results</a></div>';
}
}
else
{
echo '<div class="noresults">No search results found</div>';
}
?>
<div class="disclaimer">Addresses and postcodes are approximate
<input type="button" value="Report Problem" onclick="$('report').style.visibility=($('report').style.visibility=='hidden'?'visible':'hidden')"/>
<form class="form-inline" role="search" accept-charset="UTF-8" action="<?php echo CONST_Website_BaseURL; ?>search.php">
<div class="form-group">
<input id="q" name="q" type="text" class="form-control input-sm" placeholder="Search" value="<?php echo htmlspecialchars($sQuery); ?>" >
</div>
</div>
<?php
}
?>
<div class="form-group search-button-group">
<button type="submit" class="btn btn-primary btn-sm">Search</button>
<?php if (CONST_Search_AreaPolygons) { ?>
<!-- <input type="checkbox" value="1" name="polygon" <?php if ($bAsText) echo "checked='checked'"; ?>/> Highlight -->
<input type="hidden" value="1" name="polygon" />
<?php } ?>
<input type="hidden" name="viewbox" value="<?php echo $sViewBox; ?>" />
<div class="checkbox-inline">
<label>
<input type="checkbox" id="use_viewbox" <?php if ($sViewBox) echo "checked='checked'"; ?>>
apply viewbox
</label>
</div>
</div>
<div class="search-type-link">
<a href="<?php echo CONST_Website_BaseURL; ?>reverse.php?format=html">reverse search</a>
</div>
</form>
<div id="map"></div>
<div id="report" style="visibility:hidden;"><div style="width:600px;margin:auto;margin-top:60px;">
<h2>Report a problem</h2>
<p>Before reporting problems please read the <a href="http://wiki.openstreetmap.org/wiki/Nominatim">user documentation</a> and <a
href="http://wiki.openstreetmap.org/wiki/Nominatim/FAQ">FAQ</a>. If your problem relates to the address of a particular search result please use the 'details' link
to check how the address was generated before reporting a problem.</p>
<p>Please use <a href="http://trac.openstreetmap.org/newticket?component=nominatim">trac.openstreetmap.org</a> to report problems
making sure to set
the component to 'nominatim'. You can search for existing bug reports <a href="http://trac.openstreetmap.org/query?status=new&amp;status=assigned&amp;status=reopened&amp;component=nominatim&amp;order=priority">here</a>.</p>
<p>Please ensure that you include a full description of the problem, including the search query that you used, the problem with the result and, if
the problem relates to missing data, the osm id of the item that is missing. Problems that contain enough detail are likely to get looked at before ones that
require significant research!</p>
<div id="content">
<?php if ($sQuery) { ?>
<div id="searchresults" class="sidebar">
<?php
$i = 0;
foreach($aSearchResults as $iResNum => $aResult)
{
echo '<div class="result" data-position=' . $i . '>';
echo (isset($aResult['icon'])?'<img alt="icon" src="'.$aResult['icon'].'"/>':'');
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 ' <a class="btn btn-default btn-xs details" href="details.php?place_id='.$aResult['place_id'].'">details</a>';
echo '</div>';
$i = $i+1;
}
if (sizeof($aSearchResults) && $sMoreURL)
{
echo '<div class="more"><a class="btn btn-primary" href="'.htmlentities($sMoreURL).'">Search for more results</a></div>';
}
else
{
echo '<div class="noresults">No search results found</div>';
}
?>
</div>
<!--
<p>Please use this form to report problems with the search results. Of particular interest are items missing, but please also use this form to
report any other problems.</p>
<p>If your problem relates to the address of a particular search result please use the 'details' link to check how the address was generated before
reporting a problem.</p>
<p>If you are reporting a missing result please (if possible) include the OSM ID of the item you where expecting (i.e. node 422162)</p>
<form method="post">
<table>
<tr><th>Your Query:</th><td><input type="hidden" name="report:query" value="<?php echo htmlspecialchars($sQuery); ?>" style="width:500px;"><?php echo htmlspecialchars($sQuery); ?></td></tr>
<tr><th>Your Email Address(opt):</th><td><input type="text" name="report:email" value="" style="width:500px;"></td></tr>
<tr><th>Description of Problem:</th><td><textarea name="report:description" style="width:500px;height:200px;"></textarea></td></tr>
<tr><td colspan="2" class="button"><input type="button" value="Cancel" onclick="$('report').style.visibility='hidden'"><input type="submit" value="Report"></td></tr>
</table>
</form>
<h2>Known Problems</h2>
<ul>
<li>Countries where missed out of the index</li>
<li>Area Polygons relate to the search area - not the address area which would make more sense</li>
</ul>
-->
</div>
<?php } else { ?>
<div id="intro" class="sidebar">
<?php include(CONST_BasePath.'/lib/template/includes/introduction.php'); ?>
</div>
<?php } ?>
<div id="map-wrapper">
<div id="map-position"></div>
<div id="map"></div>
</div>
</div> <!-- /content -->
<script type="text/javascript">
init();
<?php
foreach($aSearchResults as $iResNum => $aResult)
{
if ($aResult['aBoundingBox'])
{
echo 'panToLatLonBoundingBox('.$aResult['lat'].', '.$aResult['lon'];
echo ', '.$aResult['aBoundingBox'][0];
echo ', '.$aResult['aBoundingBox'][1];
echo ', '.$aResult['aBoundingBox'][2];
echo ', '.$aResult['aBoundingBox'][3];
if (isset($aResult['astext'])) echo ", '".$aResult['astext']."'";
echo ');'."\n";
}
else
{
echo 'panToLatLonZoom('.$fLat.', '.$fLon.', '.$iZoom.');'."\n";
}
break;
}
if (!sizeof($aSearchResults))
{
echo 'panToLatLonZoom('.$fLat.', '.$fLon.', '.$iZoom.');'."\n";
}
?>
</script>
</body>
<?php
$aNominatimMapInit = array(
'zoom' => $iZoom,
'lat' => $fLat,
'lon' => $fLon,
'tile_url' => $sTileURL,
'tile_attribution' => $sTileAttribution
);
echo 'var nominatim_map_init = ' . json_encode($aNominatimMapInit) . ';';
echo 'var nominatim_results = ' . json_encode($aSearchResults) . ';';
?>
</script>
<?php include(CONST_BasePath.'/lib/template/includes/html-footer.php'); ?>
</body>
</html>

View File

@@ -74,6 +74,9 @@
$aPlace['geokml'] = $aPointDetails['askml'];
}
if (isset($aPointDetails['sExtraTags'])) $aPlace['extratags'] = $aPointDetails['sExtraTags'];
if (isset($aPointDetails['sNameDetails'])) $aPlace['namedetails'] = $aPointDetails['sNameDetails'];
$aFilteredPlaces[] = $aPlace;
}

View File

@@ -73,7 +73,10 @@
$aPlace['geokml'] = $aPointDetails['askml'];
}
if (isset($aPointDetails['sExtraTags'])) $aPlace['extratags'] = $aPointDetails['sExtraTags'];
if (isset($aPointDetails['sNameDetails'])) $aPlace['namedetails'] = $aPointDetails['sNameDetails'];
$aFilteredPlaces[] = $aPlace;
}
javascript_renderData($aFilteredPlaces, array('geojson'));
javascript_renderData($aFilteredPlaces);

View File

@@ -5,7 +5,8 @@
echo "?xml version=\"1.0\" encoding=\"UTF-8\" ?";
echo ">\n";
echo "<searchresults";
echo "<";
echo (isset($sXmlRootTag)?$sXmlRootTag:'searchresults');
echo " timestamp='".date(DATE_RFC822)."'";
echo " attribution='Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright'";
echo " querystring='".htmlspecialchars($sQuery, ENT_QUOTES)."'";
@@ -87,20 +88,59 @@
echo " icon='".htmlspecialchars($aResult['icon'], ENT_QUOTES)."'";
}
if (isset($aResult['address']) || isset($aResult['askml']))
{
echo ">";
}
$bHasDelim = false;
if (isset($aResult['askml']))
{
if (!$bHasDelim)
{
$bHasDelim = true;
echo ">";
}
echo "\n<geokml>";
echo $aResult['askml'];
echo "</geokml>";
}
if (isset($aResult['sExtraTags']))
{
if (!$bHasDelim)
{
$bHasDelim = true;
echo ">";
}
echo "\n<extratags>";
foreach ($aResult['sExtraTags'] as $sKey => $sValue)
{
echo '<tag key="'.htmlspecialchars($sKey).'" value="'.htmlspecialchars($sValue).'"/>';
}
echo "</extratags>";
}
if (isset($aResult['sNameDetails']))
{
if (!$bHasDelim)
{
$bHasDelim = true;
echo ">";
}
echo "\n<namedetails>";
foreach ($aResult['sNameDetails'] as $sKey => $sValue)
{
echo '<name desc="'.htmlspecialchars($sKey).'">';
echo htmlspecialchars($sValue);
echo "</name>";
}
echo "</namedetails>";
}
if (isset($aResult['address']))
{
if (!$bHasDelim)
{
$bHasDelim = true;
echo ">";
}
echo "\n";
foreach($aResult['address'] as $sKey => $sValue)
{
@@ -111,7 +151,7 @@
}
}
if (isset($aResult['address']) || isset($aResult['askml']))
if ($bHasDelim)
{
echo "</place>";
}
@@ -121,4 +161,4 @@
}
}
echo "</searchresults>";
echo "</" . (isset($sXmlRootTag)?$sXmlRootTag:'searchresults') . ">";

125
m4/ax_lib_postgresql_svr.m4 Normal file
View File

@@ -0,0 +1,125 @@
# SYNOPSIS
#
# AX_LIB_POSTGRESQL_SVR([MINIMUM-VERSION])
#
# DESCRIPTION
#
# This macro provides tests of availability of PostgreSQL server library
#
# This macro calls:
#
# AC_SUBST(POSTGRESQL_PGXS)
# AC_SUBST(POSTGRESQL_SERVER_CFLAGS)
#
# LICENSE
#
# Copyright (c) 2008 Mateusz Loskot <mateusz@loskot.net>
# Copyright (c) 2015 Sarah Hoffmann <lonia@denofr.de>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved.
AC_DEFUN([AX_LIB_POSTGRESQL_SVR],
[
AC_ARG_WITH([postgresql],
AC_HELP_STRING([--with-postgresql-svr=@<:@ARG@:>@],
[use PostgreSQL server library @<:@default=yes@:>@, optionally specify path to pg_config]
),
[
if test "$withval" = "no"; then
want_postgresql="no"
elif test "$withval" = "yes"; then
want_postgresql="yes"
else
want_postgresql="yes"
PG_CONFIG="$withval"
fi
],
[want_postgresql="yes"]
)
dnl
dnl Check PostgreSQL server libraries
dnl
if test "$want_postgresql" = "yes"; then
if test -z "$PG_CONFIG" -o test; then
AC_PATH_PROG([PG_CONFIG], [pg_config], [])
fi
if test ! -x "$PG_CONFIG"; then
AC_MSG_ERROR([$PG_CONFIG does not exist or it is not an exectuable file])
PG_CONFIG="no"
found_postgresql="no"
fi
if test "$PG_CONFIG" != "no"; then
AC_MSG_CHECKING([for PostgreSQL server libraries])
POSTGRESQL_SERVER_CFLAGS="-I`$PG_CONFIG --includedir-server`"
POSTGRESQL_VERSION=`$PG_CONFIG --version | sed -e 's#PostgreSQL ##'`
POSTGRESQL_PGXS=`$PG_CONFIG --pgxs`
if test -f "$POSTGRESQL_PGXS"
then
found_postgresql="yes"
AC_MSG_RESULT([yes])
fi
else
found_postgresql="no"
AC_MSG_RESULT([no])
fi
fi
dnl
dnl Check if required version of PostgreSQL is available
dnl
postgresql_version_req=ifelse([$1], [], [], [$1])
if test "$found_postgresql" = "yes" -a -n "$postgresql_version_req"; then
AC_MSG_CHECKING([if PostgreSQL version is >= $postgresql_version_req])
dnl Decompose required version string of PostgreSQL
dnl and calculate its number representation
postgresql_version_req_major=`expr $postgresql_version_req : '\([[0-9]]*\)'`
postgresql_version_req_minor=`expr $postgresql_version_req : '[[0-9]]*\.\([[0-9]]*\)'`
postgresql_version_req_micro=`expr $postgresql_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'`
if test "x$postgresql_version_req_micro" = "x"; then
postgresql_version_req_micro="0"
fi
postgresql_version_req_number=`expr $postgresql_version_req_major \* 1000000 \
\+ $postgresql_version_req_minor \* 1000 \
\+ $postgresql_version_req_micro`
dnl Decompose version string of installed PostgreSQL
dnl and calculate its number representation
postgresql_version_major=`expr $POSTGRESQL_VERSION : '\([[0-9]]*\)'`
postgresql_version_minor=`expr $POSTGRESQL_VERSION : '[[0-9]]*\.\([[0-9]]*\)'`
postgresql_version_micro=`expr $POSTGRESQL_VERSION : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'`
if test "x$postgresql_version_micro" = "x"; then
postgresql_version_micro="0"
fi
postgresql_version_number=`expr $postgresql_version_major \* 1000000 \
\+ $postgresql_version_minor \* 1000 \
\+ $postgresql_version_micro`
postgresql_version_check=`expr $postgresql_version_number \>\= $postgresql_version_req_number`
if test "$postgresql_version_check" = "1"; then
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
fi
fi
AC_SUBST([POSTGRESQL_PGXS])
AC_SUBST([POSTGRESQL_SERVER_CFLAGS])
])

150
m4/ax_lib_xml2.m4 Normal file
View File

@@ -0,0 +1,150 @@
# SYNOPSIS
#
# AX_LIB_XML2([MINIMUM-VERSION])
#
# DESCRIPTION
#
# This macro provides tests of availability of xml2 'libxml2' library
# of particular version or newer.
#
# AX_LIB_LIBXML2 macro takes only one argument which is optional. If
# there is no required version passed, then macro does not run version
# test.
#
# The --with-libxml2 option takes one of three possible values:
#
# no - do not check for xml2 library
#
# yes - do check for xml2 library in standard locations (xml2-config
# should be in the PATH)
#
# path - complete path to xml2-config utility, use this option if xml2-config
# can't be found in the PATH
#
# This macro calls:
#
# AC_SUBST(XML2_CFLAGS)
# AC_SUBST(XML2_LDFLAGS)
# AC_SUBST(XML2_VERSION)
#
# And sets:
#
# HAVE_XML2
#
# LICENSE
#
# Copyright (c) 2009 Hartmut Holzgraefe <hartmut@php.net>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved.
AC_DEFUN([AX_LIB_XML2],
[
AC_ARG_WITH([libxml2],
AC_HELP_STRING([--with-libxml2=@<:@ARG@:>@],
[use libxml2 library @<:@default=yes@:>@, optionally specify path to xml2-config]
),
[
if test "$withval" = "no"; then
want_libxml2="no"
elif test "$withval" = "yes"; then
want_libxml2="yes"
else
want_libxml2="yes"
XML2_CONFIG="$withval"
fi
],
[want_libxml2="yes"]
)
XML2_CFLAGS=""
XML2_LDFLAGS=""
XML2_VERSION=""
dnl
dnl Check xml2 libraries (libxml2)
dnl
if test "$want_libxml2" = "yes"; then
if test -z "$XML2_CONFIG" -o test; then
AC_PATH_PROG([XML2_CONFIG], [xml2-config], [])
fi
if test ! -x "$XML2_CONFIG"; then
AC_MSG_ERROR([$XML2_CONFIG does not exist or it is not an exectuable file])
XML2_CONFIG="no"
found_libxml2="no"
fi
if test "$XML2_CONFIG" != "no"; then
AC_MSG_CHECKING([for xml2 libraries])
XML2_CFLAGS="`$XML2_CONFIG --cflags`"
XML2_LDFLAGS="`$XML2_CONFIG --libs`"
XML2_VERSION=`$XML2_CONFIG --version`
AC_DEFINE([HAVE_XML2], [1],
[Define to 1 if xml2 libraries are available])
found_libxml2="yes"
AC_MSG_RESULT([yes])
else
found_libxml2="no"
AC_MSG_RESULT([no])
fi
fi
dnl
dnl Check if required version of xml2 is available
dnl
libxml2_version_req=ifelse([$1], [], [], [$1])
if test "$found_libxml2" = "yes" -a -n "$libxml2_version_req"; then
AC_MSG_CHECKING([if libxml2 version is >= $libxml2_version_req])
dnl Decompose required version string of libxml2
dnl and calculate its number representation
libxml2_version_req_major=`expr $libxml2_version_req : '\([[0-9]]*\)'`
libxml2_version_req_minor=`expr $libxml2_version_req : '[[0-9]]*\.\([[0-9]]*\)'`
libxml2_version_req_micro=`expr $libxml2_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'`
if test "x$libxml2_version_req_micro" = "x"; then
libxml2_version_req_micro="0"
fi
libxml2_version_req_number=`expr $libxml2_version_req_major \* 1000000 \
\+ $libxml2_version_req_minor \* 1000 \
\+ $libxml2_version_req_micro`
dnl Decompose version string of installed PostgreSQL
dnl and calculate its number representation
libxml2_version_major=`expr $XML2_VERSION : '\([[0-9]]*\)'`
libxml2_version_minor=`expr $XML2_VERSION : '[[0-9]]*\.\([[0-9]]*\)'`
libxml2_version_micro=`expr $XML2_VERSION : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'`
if test "x$libxml2_version_micro" = "x"; then
libxml2_version_micro="0"
fi
libxml2_version_number=`expr $libxml2_version_major \* 1000000 \
\+ $libxml2_version_minor \* 1000 \
\+ $libxml2_version_micro`
libxml2_version_check=`expr $libxml2_version_number \>\= $libxml2_version_req_number`
if test "$libxml2_version_check" = "1"; then
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
fi
fi
AC_SUBST([XML2_VERSION])
AC_SUBST([XML2_CFLAGS])
AC_SUBST([XML2_LDFLAGS])
])

View File

@@ -2,8 +2,8 @@ bin_PROGRAMS = nominatim
nominatim_SOURCES = export.c geometry.cpp import.c index.c input.c nominatim.c postgresql.c sprompt.c
AM_CFLAGS = @PTHREAD_CFLAGS@ @POSTGRESQL_CFLAGS@ @XML_CPPFLAGS@ @BZIP2_CFLAGS@ @GEOS_CFLAGS@ @PROJ_CFLAGS@ -DVERSION='"@PACKAGE_VERSION@"'
AM_CPPFLAGS = @PTHREAD_CFLAGS@ @POSTGRESQL_CFLAGS@ @XML_CPPFLAGS@ @BZIP2_CFLAGS@ @GEOS_CFLAGS@ @PROJ_CFLAGS@
AM_CFLAGS = @PTHREAD_CFLAGS@ @POSTGRESQL_CPPFLAGS@ @XML_CPPFLAGS@ @BZIP2_CFLAGS@ @GEOS_CFLAGS@ @PROJ_CFLAGS@ -DVERSION='"@PACKAGE_VERSION@"'
AM_CPPFLAGS = @PTHREAD_CFLAGS@ @POSTGRESQL_CPPFLAGS@ @XML_CPPFLAGS@ @BZIP2_CFLAGS@ @GEOS_CFLAGS@ @PROJ_CFLAGS@
nominatim_LDADD = @PTHREAD_CFLAGS@ @POSTGRESQL_LDFLAGS@ @POSTGRESQL_LIBS@ @XML_LIBS@ @BZIP2_LDFLAGS@ @BZIP2_LIBS@ @GEOS_LDFLAGS@ @GEOS_LIBS@ @PROJ_LDFLAGS@ @PROJ_LIBS@ -lz

26
phpunit.xml Normal file
View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="true"
bootstrap="tests-php/bootstrap.php"
>
<php>
</php>
<testsuites>
<testsuite name="Nominatim PHP Test Suite">
<directory>./tests-php/Nominatim</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./lib/</directory>
</whitelist>
</filter>
</phpunit>

View File

@@ -5,22 +5,48 @@
// 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);
// Proxy settings
@define('CONST_HTTP_Proxy', false);
@define('CONST_HTTP_Proxy_Host', 'proxy.mydomain.com');
@define('CONST_HTTP_Proxy_Port', '3128');
@define('CONST_HTTP_Proxy_Login', '');
@define('CONST_HTTP_Proxy_Password', '');
// 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');
@define('CONST_Path_Postgresql_Postgis', CONST_Path_Postgresql_Contrib.'/postgis-'.CONST_Postgis_Version);
@define('CONST_Osm2pgsql_Binary', CONST_BasePath.'/osm2pgsql/osm2pgsql');
@define('CONST_Osmosis_Binary', '/usr/bin/osmosis');
@define('CONST_Tiger_Data_Path', CONST_BasePath.'/data/tiger');
// 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');
@@ -65,6 +91,8 @@
@define('CONST_Default_Lat', 20.0);
@define('CONST_Default_Lon', 0.0);
@define('CONST_Default_Zoom', 2);
@define('CONST_Map_Tile_URL', 'http://{s}.tile.osm.org/{z}/{x}/{y}.png');
@define('CONST_Map_Tile_Attribution', ''); // Set if tile source isn't osm.org
@define('CONST_Search_AreaPolygons_Enabled', true);
@define('CONST_Search_AreaPolygons', true);
@@ -72,7 +100,12 @@
@define('CONST_Search_BatchMode', false);
@define('CONST_Search_TryDroppedAddressTerms', false);
@define('CONST_Search_NameOnlySearchFrequencyThreshold', false);
@define('CONST_Search_NameOnlySearchFrequencyThreshold', 500);
// If set to true, then reverse order of queries will be tried by default.
// When set to false only selected languages alloow reverse search.
@define('CONST_Search_ReversePlanForAll', true);
@define('CONST_Places_Max_ID_count', 50);
// Set to zero to disable polygon output
@define('CONST_PolygonOutput_MaximumTypes', 1);
@@ -83,3 +116,5 @@
@define('CONST_Log_File_Format', 'TODO'); // Currently hard coded
@define('CONST_Log_File_SearchLog', '');
@define('CONST_Log_File_ReverseLog', '');

File diff suppressed because it is too large Load Diff

View File

@@ -1,29 +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_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','man_made');
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

@@ -60,6 +60,9 @@ create or replace function insertLocationAreaLarge(
in_centroid GEOMETRY, in_geometry GEOMETRY) RETURNS BOOLEAN AS $$
DECLARE
BEGIN
IF in_rank_address = 0 THEN
RETURN TRUE;
END IF;
IF in_rank_search <= 4 THEN
INSERT INTO location_area_country values (in_partition, in_place_id, in_country_code, in_keywords, in_rank_search, in_rank_address, in_estimate, in_centroid, in_geometry);
@@ -111,7 +114,7 @@ END
$$
LANGUAGE plpgsql;
create or replace function getNearestNamedRoadFeature(in_partition INTEGER, point GEOMETRY, isin_token INTEGER)
create or replace function getNearestNamedRoadFeature(in_partition INTEGER, point GEOMETRY, isin_token INTEGER[])
RETURNS setof nearfeature AS $$
DECLARE
r nearfeature%rowtype;
@@ -123,7 +126,7 @@ BEGIN
SELECT place_id, name_vector, address_rank, search_rank,
ST_Distance(centroid, point) as distance, null as isguess
FROM search_name_-partition-
WHERE name_vector @> ARRAY[isin_token]
WHERE name_vector @> isin_token
AND ST_DWithin(centroid, point, 0.01)
AND search_rank between 26 and 27
ORDER BY distance ASC limit 1
@@ -139,7 +142,7 @@ END
$$
LANGUAGE plpgsql;
create or replace function getNearestNamedPlaceFeature(in_partition INTEGER, point GEOMETRY, isin_token INTEGER)
create or replace function getNearestNamedPlaceFeature(in_partition INTEGER, point GEOMETRY, isin_token INTEGER[])
RETURNS setof nearfeature AS $$
DECLARE
r nearfeature%rowtype;
@@ -151,7 +154,7 @@ BEGIN
SELECT place_id, name_vector, address_rank, search_rank,
ST_Distance(centroid, point) as distance, null as isguess
FROM search_name_-partition-
WHERE name_vector @> ARRAY[isin_token]
WHERE name_vector @> isin_token
AND ST_DWithin(centroid, point, 0.03)
AND search_rank between 16 and 22
ORDER BY distance ASC limit 1
@@ -205,16 +208,20 @@ BEGIN
IF in_rank_search <= 4 THEN
DELETE FROM search_name_country WHERE place_id = in_place_id;
INSERT INTO search_name_country values (in_place_id, in_rank_search, in_rank_address,
in_name_vector, in_geometry);
IF in_rank_address > 0 THEN
INSERT INTO search_name_country values (in_place_id, in_rank_search, in_rank_address,
in_name_vector, in_geometry);
END IF;
RETURN TRUE;
END IF;
-- start
IF in_partition = -partition- THEN
DELETE FROM search_name_-partition- values WHERE place_id = in_place_id;
INSERT INTO search_name_-partition- values (in_place_id, in_rank_search, in_rank_address,
in_name_vector, in_geometry);
IF in_rank_address > 0 THEN
INSERT INTO search_name_-partition- values (in_place_id, in_rank_search, in_rank_address,
in_name_vector, in_geometry);
END IF;
RETURN TRUE;
END IF;
-- end

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
@@ -236,9 +186,6 @@ CREATE TRIGGER place_before_delete BEFORE DELETE ON place
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);
DROP SEQUENCE seq_postcodes;
CREATE SEQUENCE seq_postcodes start 1;
@@ -256,7 +203,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 +213,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,
@@ -53,12 +53,12 @@ BEGIN
END IF;
place_centroid := ST_Centroid(linegeo);
out_partition := get_partition(place_centroid, 'us');
out_partition := get_partition('us');
out_parent_place_id := null;
address_street_word_id := get_name_id(make_standard_name(in_street));
IF address_street_word_id IS NOT NULL THEN
FOR location IN SELECT * from getNearestNamedRoadFeature(out_partition, place_centroid, address_street_word_id) LOOP
FOR location IN SELECT * from getNearestNamedRoadFeature(out_partition, place_centroid, ARRAY[address_street_word_id]) LOOP
out_parent_place_id := location.place_id;
END LOOP;
END IF;

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

@@ -0,0 +1,151 @@
<?php
namespace Nominatim;
require '../lib/lib.php';
class NominatimTest extends \PHPUnit_Framework_TestCase
{
protected function setUp()
{
}
public function test_addQuotes()
{
// FIXME: not quoting existing quote signs is probably a bug
$this->assertSame("'St. John's'", addQuotes("St. John's"));
$this->assertSame("''", addQuotes(''));
}
public function test_looksLikeLatLonPair()
{
// no coordinates expected
$this->assertNull(looksLikeLatLonPair(''));
$this->assertNull(looksLikeLatLonPair('abc'));
$this->assertNull(looksLikeLatLonPair('12 34'));
$this->assertNull(looksLikeLatLonPair('200.1 89.9')); // because latitude > 180
// coordinates expected
$this->assertNotNull(looksLikeLatLonPair('0.0 -0.0'));
$this->assertEquals(
array( 'lat' => 12.456, 'lon' => -78.90, 'query' => 'abc def'),
looksLikeLatLonPair(' abc 12.456 -78.90 def ')
);
$this->assertEquals(
array( 'lat' => 12.456, 'lon' => -78.90, 'query' => ''),
looksLikeLatLonPair(' [12.456,-78.90] ')
);
// http://en.wikipedia.org/wiki/Geographic_coordinate_conversion
// these all represent the same location
$aQueries = array(
'40 26.767 N 79 58.933 W',
'40° 26.767 N 79° 58.933 W',
"40° 26.767' N 79° 58.933' W",
'N 40 26.767, W 79 58.933',
'N 40°26.767, W 79°58.933',
"N 40°26.767', W 79°58.933'",
'40 26 46 N 79 58 56 W',
'40° 26 46″ N 79° 58 56″ W',
'N 40 26 46 W 79 58 56',
'N 40° 26 46″, W 79° 58 56″',
'N 40° 26\' 46", W 79° 58\' 56"',
'40.446 -79.982',
'40.446,-79.982',
'40.446° N 79.982° W',
'N 40.446° W 79.982°',
'[40.446 -79.982]',
' 40.446 , -79.982 ',
);
foreach($aQueries as $sQuery){
$aRes = looksLikeLatLonPair($sQuery);
$this->assertEquals( 40.446, $aRes['lat'], 'degrees decimal ' . $sQuery, 0.01);
$this->assertEquals(-79.982, $aRes['lon'], 'degrees decimal ' . $sQuery, 0.01);
}
}
public function test_getWordSets()
{
// given an array of arrays like
// array( array('a','b'), array('c','d') )
// returns a summary as string: '(a|b),(c|d)'
function serialize_sets($aSets)
{
$aParts = array();
foreach($aSets as $aSet){
$aParts[] = '(' . join('|', $aSet) . ')';
}
return join(',', $aParts);
}
$this->assertEquals(
array(array('')),
getWordSets(array(),0)
);
$this->assertEquals(
'(a)',
serialize_sets( getWordSets(array("a"),0) )
);
$this->assertEquals(
'(a b),(a|b)',
serialize_sets( getWordSets(array('a','b'),0) )
);
$this->assertEquals(
'(a b c),(a|b c),(a|b|c),(a b|c)',
serialize_sets( getWordSets(array('a','b','c'),0) )
);
$this->assertEquals(
'(a b c d),(a|b c d),(a|b|c d),(a|b|c|d),(a|b c|d),(a b|c d),(a b|c|d),(a b c|d)',
serialize_sets( getWordSets(array('a','b','c','d'),0) )
);
// Inverse
$this->assertEquals(
'(a b c),(c|a b),(c|b|a),(b c|a)',
serialize_sets( getInverseWordSets(array('a','b','c'),0) )
);
// make sure we don't create too many sets
// 4 words => 8 sets
// 10 words => 511 sets
// 15 words => 12911 sets
// 18 words => 65536 sets
// 20 words => 169766 sets
// 22 words => 401930 sets
// 28 words => 3505699 sets (needs more than 4GB via 'phpunit -d memory_limit=' to run)
$this->assertEquals(
8,
count( getWordSets(array_fill( 0, 4, 'a'),0) )
);
$this->assertEquals(
65536,
count( getWordSets(array_fill( 0, 18, 'a'),0) )
);
}
}

14
tests-php/README.txt Normal file
View File

@@ -0,0 +1,14 @@
Basic unit tests of PHP code. Very low coverage. Doesn't cover interaction
with the webserver/HTTP or database (yet).
You need to have
https://phpunit.de/manual/4.2/en/
installed.
To execute the test suite run
$ cd tests-php
$ phpunit ./
It will read phpunit.xml which points to the library, test path, bootstrap
strip and set other parameters.

2
tests-php/bootstrap.php Normal file
View File

@@ -0,0 +1,2 @@
<?php

102
tests/README.md Normal file
View File

@@ -0,0 +1,102 @@
This directory contains functional tests for the Nominatim API,
for the import/update from osm files and for indexing.
The tests use the lettuce framework (http://lettuce.it/) and
nose (https://nose.readthedocs.org). API tests are meant to be run
against a Nominatim installation with a complete planet-wide
setup based on a fairly recent planet. If you only have an
excerpt, some of the API tests may fail. Database tests can be
run without having a database installed.
Prerequisites
=============
* lettuce framework (http://lettuce.it/)
* 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 shapely
* run the tests
NOMINATIM_SERVER=http://your.nominatim.instance/ lettuce features
The tests can be configured with a set of environment variables:
* `NOMINATIM_SERVER` - URL of the nominatim instance (API tests)
* `NOMINATIM_DIR` - source directory of Nominatim (import tests)
* `TEMPLATE_DB` - name of template database used as a skeleton for
the test databases (db tests)
* `TEST_DB` - name of test database (db tests)
* `NOMINATIM_SETTINGS` - file to write temporary Nominatim settings to (db tests)
* `NOMINATIM_REUSE_TEMPLATE` - if defined, the template database will not be
deleted after the test runs and reused during
the next run. This speeds up tests considerably
but might lead to outdated errors for some
changes in the database layout.
* `NOMINATIM_KEEP_SCENARIO_DB` - if defined, the test database will not be
dropped after a test is finished. Should
only be used if one single scenario is run,
otherwise the result is undefined.
* `LOGLEVEL` - set to 'debug' to get more verbose output (only works properly
when output to a logfile is configured)
* `LOGFILE` - sends debug output to the given file
Writing Tests
=============
The following explanation assume that the reader is familiar with the lettuce
notations of features, scenarios and steps.
All possible steps can be found in the `steps` directory and should ideally
be documented.
API Tests (`features/api`)
--------------------------
These tests are meant to test the different API calls and their parameters.
There are two kind of steps defined for these tests:
request setup steps (see `steps/api_setup.py`)
and steps for checking results (see `steps/api_result.py`).
Each scenario follows this simple sequence of steps:
1. One or more steps to define parameters and HTTP headers of the request.
These are cumulative, so you can use multiple steps.
2. A single step to call the API. This sends a HTTP request to the configured
server and collects the answer. The cached parameters will be deleted,
to ensure that the setup works properly with scenario outlines.
3. As many result checks as necessary. The result remains cached, so that
multiple tests can be added here.
Indexing Tests (`features/db`)
---------------------------------------------------
These tests check the import and update of the Nominatim database. They do not
test the correctness of osm2pgsql. Each test will write some data into the `place`
table (and optionally `the planet_osm_*` tables if required) and then run
Nominatim's processing functions on that.
These tests need to create their own test databases. By default they will be
called `test_template_nominatim` and `test_nominatim`. Names can be changed with
the environment variables `TEMPLATE_DB` and `TEST_DB`. The user running the tests
needs superuser rights for postgres.
Import Tests (`features/osm2pgsql`)
-----------------------------------
These tests check that data is imported correctly into the place table. They
use the same template database as the Indexing tests, so the same remarks apply.

View File

@@ -0,0 +1,14 @@
Feature: Object details
Check details page for correctness
Scenario Outline: Details via OSM id
When looking up details for <object>
Then the result is valid
Examples:
| object
| 1758375
| N158845944
| W72493656
| R62422

View File

@@ -0,0 +1,100 @@
Feature: Localization of search results
Scenario: Search - default language
When sending json search query "Germany"
Then results contain
| ID | display_name
| 0 | Deutschland.*
Scenario: Search - accept-language first
Given the request parameters
| accept-language
| en,de
When sending json search query "Deutschland"
Then results contain
| ID | display_name
| 0 | Germany.*
Scenario: Search - accept-language missing
Given the request parameters
| accept-language
| xx,fr,en,de
When sending json search query "Deutschland"
Then results contain
| ID | display_name
| 0 | Allemagne.*
Scenario: Search - http accept language header first
Given the HTTP header
| accept-language
| fr-ca,fr;q=0.8,en-ca;q=0.5,en;q=0.3
When sending json search query "Deutschland"
Then results contain
| ID | display_name
| 0 | Allemagne.*
Scenario: Search - http accept language header and accept-language
Given the request parameters
| accept-language
| de,en
Given the HTTP header
| accept-language
| fr-ca,fr;q=0.8,en-ca;q=0.5,en;q=0.3
When sending json search query "Deutschland"
Then results contain
| ID | display_name
| 0 | Deutschland.*
Scenario: Search - http accept language header fallback
Given the HTTP header
| accept-language
| fr-ca,en-ca;q=0.5
When sending json search query "Deutschland"
Then results contain
| ID | display_name
| 0 | Allemagne.*
Scenario: Search - http accept language header fallback (upper case)
Given the HTTP header
| accept-language
| fr-FR;q=0.8,en-ca;q=0.5
When sending json search query "Deutschland"
Then results contain
| ID | display_name
| 0 | Allemagne.*
Scenario: Reverse - default language
When looking up coordinates 48.13921,11.57328
Then result addresses contain
| ID | city
| 0 | München
Scenario: Reverse - accept-language parameter
Given the request parameters
| accept-language
| en,fr
When looking up coordinates 48.13921,11.57328
Then result addresses contain
| ID | city
| 0 | Munich
Scenario: Reverse - HTTP accept language header
Given the HTTP header
| accept-language
| fr-ca,fr;q=0.8,en-ca;q=0.5,en;q=0.3
When looking up coordinates 48.13921,11.57328
Then result addresses contain
| ID | city
| 0 | Munich
Scenario: Reverse - accept-language parameter and HTTP header
Given the request parameters
| accept-language
| it
Given the HTTP header
| accept-language
| fr-ca,fr;q=0.8,en-ca;q=0.5,en;q=0.3
When looking up coordinates 48.13921,11.57328
Then result addresses contain
| ID | city
| 0 | Monaco di Baviera

View File

@@ -0,0 +1,15 @@
Feature: Places by osm_type and osm_id Tests
Simple tests for internal server errors and response format.
Scenario: address lookup for existing node, way, relation
When looking up xml places N158845944,W72493656,,R62422,X99,N0
Then the result is valid xml
exactly 3 results are returned
When looking up json places N158845944,W72493656,,R62422,X99,N0
Then the result is valid json
exactly 3 results are returned
Scenario: address lookup for non-existing or invalid node, way, relation
When looking up xml places X99,,N0,nN158845944,ABC,,W9
Then the result is valid xml
exactly 0 results are returned

View File

@@ -0,0 +1,218 @@
Feature: API regression tests
Tests error cases reported in tickets.
Scenario: trac #2430
When sending json search query "89 River Avenue, Hoddesdon, Hertfordshire, EN11 0JT"
Then at least 1 result is returned
Scenario: trac #2440
When sending json search query "East Harvard Avenue, Denver"
Then more than 2 results are returned
Scenario: trac #2456
When sending xml search query "Borlänge Kommun"
Then results contain
| ID | place_rank
| 0 | 19
Scenario: trac #2530
When sending json search query "Lange Straße, Bamberg" with address
Then result addresses contain
| ID | town
| 0 | Bamberg
Scenario: trac #2541
When sending json search query "pad, germany"
Then results contain
| ID | class | display_name
| 0 | aeroway | Paderborn/Lippstadt,.*
Scenario: trac #2579
When sending json search query "Johnsons Close, hackbridge" with address
Then result addresses contain
| ID | postcode
| 0 | SM5 2LU
@Fail
Scenario Outline: trac #2586
When sending json search query "<query>" with address
Then result addresses contain
| ID | country_code
| 0 | uk
Examples:
| query
| DL7 0SN
| DL70SN
Scenario: trac #2628 (1)
When sending json search query "Adam Kraft Str" with address
Then result addresses contain
| ID | road
| 0 | Adam-Kraft-Straße
Scenario: trac #2628 (2)
When sending json search query "Maxfeldstr. 5, Nürnberg" with address
Then result addresses contain
| ID | house_number | road | city
| 0 | 5 | Maxfeldstraße | Nürnberg
Scenario: trac #2638
When sending json search query "Nöthnitzer Str. 40, 01187 Dresden" with address
Then result addresses contain
| ID | house_number | road | city
| 0 | 40 | Nöthnitzer Straße | Dresden
Scenario Outline: trac #2667
When sending json search query "<query>" with address
Then result addresses contain
| ID | house_number
| 0 | <number>
Examples:
| number | query
| 16 | 16 Woodpecker Way, Cambourne
| 14906 | 14906, 114 Street Northwest, Edmonton, Alberta, Canada
| 14904 | 14904, 114 Street Northwest, Edmonton, Alberta, Canada
| 15022 | 15022, 114 Street Northwest, Edmonton, Alberta, Canada
| 15024 | 15024, 114 Street Northwest, Edmonton, Alberta, Canada
Scenario: trac #2681
When sending json search query "kirchstraße troisdorf Germany"
Then results contain
| ID | display_name
| 0 | .*, Troisdorf, .*
Scenario: trac #2758
When sending json search query "6а, полуботка, чернигов" with address
Then result addresses contain
| ID | house_number
| 0 | 6а
Scenario: trac #2790
When looking up coordinates 49.0942079697809,8.27565898861822
Then result addresses contain
| ID | road | village | country
| 0 | Daimlerstraße | Jockgrim | Deutschland
Scenario: trac #2794
When sending json search query "4008"
Then results contain
| ID | class | type
| 0 | place | postcode
Scenario: trac #2797
When sending json search query "Philippstr.4, 52349 Düren" with address
Then result addresses contain
| ID | road | town
| 0 | Philippstraße | Düren
Scenario: trac #2830
When sending json search query "528, Merkley Drive, K4A 1N5,CA" with address
Then result addresses contain
| ID | house_number | road | postcode | country
| 0 | 528 | Merkley Drive | K4A 1N5 | Canada
Scenario: trac #2830
When sending json search query "K4A 1N5,CA"
Then results contain
| ID | class | type | display_name
| 0 | place | postcode | .*, Canada
Scenario: trac #2845
When sending json search query "Leliestraat 31, Zwolle" with address
Then result addresses contain
| ID | city
| 0 | Zwolle
Scenario: trac #2852
When sending json search query "berlinerstrasse, leipzig" with address
Then result addresses contain
| ID | road
| 0 | Berliner Straße
Scenario: trac #2871
When looking up coordinates -33.906895553,150.99609375
Then result addresses contain
| ID | city | postcode | country
| 0 | [^0-9]* | 2197 | Australia
Scenario: trac #2974
When sending json search query "Azadi Square, Faruj" with address
Then result addresses contain
| ID | road | city
| 0 | ميدان آزادي | فاروج
And results contain
| ID | latlon
| 0 | 37.2323,58.2193 +-1km
Scenario: trac #2981
When sending json search query "Ohmstraße 7, Berlin" with address
Then at least 2 results are returned
And result addresses contain
| house_number | road | state
| 7 | Ohmstraße | Berlin
Scenario: trac #3049
When sending json search query "Soccer City"
Then results contain
| ID | class | type | latlon
| 0 | leisure | stadium | -26.2347261,27.982645 +-50m
Scenario: trac #3130
When sending json search query "Old Way, Frinton"
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

@@ -0,0 +1,63 @@
Feature: Reverse geocoding
Testing the reverse function
# Make sure country is not overwritten by the postcode
Scenario: Country is returned
Given the request parameters
| accept-language
| de
When looking up coordinates 53.9788769,13.0830313
Then result addresses contain
| ID | country
| 0 | Deutschland
@Tiger
Scenario: TIGER house number
Given the request parameters
| addressdetails
| 1
When looking up coordinates 40.6863624710666,-112.060005720023
And exactly 1 result is returned
And result addresses contain
| ID | house_number | road | postcode | country_code
| 0 | 7094 | Kings Estate Drive | 84128 | us
And result 0 has not attributes osm_id,osm_type
@Tiger
Scenario: No TIGER house number for zoom < 18
Given the request parameters
| addressdetails | zoom
| 1 | 17
When looking up coordinates 40.6863624710666,-112.060005720023
And exactly 1 result is returned
And result addresses contain
| ID | road | postcode | country_code
| 0 | Kings Estate Drive | 84128 | us
And result 0 has attributes osm_id,osm_type
Scenario Outline: Reverse Geocoding with extratags
Given the request parameters
| extratags
| 1
When looking up <format> coordinates 48.86093,2.2978
Then result 0 has attributes extratags
Examples:
| format
| xml
| json
| jsonv2
Scenario Outline: Reverse Geocoding with namedetails
Given the request parameters
| namedetails
| 1
When looking up <format> coordinates 48.86093,2.2978
Then result 0 has attributes namedetails
Examples:
| format
| xml
| json
| jsonv2

View File

@@ -0,0 +1,13 @@
Feature: Reverse lookup by ID
Testing reverse geocoding via OSM ID
# see github issue #269
Scenario: Get address of linked places
Given the request parameters
| osm_type | osm_id
| N | 151421301
When sending an API call reverse
Then exactly 1 result is returned
And result addresses contain
| county | state
| Pratt County | Kansas

View File

@@ -0,0 +1,97 @@
Feature: Simple Reverse Tests
Simple tests for internal server errors and response format.
These tests should pass on any Nominatim installation.
Scenario Outline: Simple reverse-geocoding
When looking up xml coordinates <lat>,<lon>
Then the result is valid xml
When looking up json coordinates <lat>,<lon>
Then the result is valid json
When looking up jsonv2 coordinates <lat>,<lon>
Then the result is valid json
Examples:
| lat | lon
| 0.0 | 0.0
| 45.3 | 3.5
| -79.34 | 23.5
| 0.23 | -178.555
Scenario Outline: Wrapping of legal jsonp requests
Given the request parameters
| json_callback
| foo
When looking up <format> coordinates 67.3245,0.456
Then the result is valid json
Examples:
| format
| json
| jsonv2
Scenario: Reverse-geocoding without address
Given the request parameters
| addressdetails
| 0
When looking up xml coordinates 36.791966,127.171726
Then the result is valid xml
When looking up json coordinates 36.791966,127.171726
Then the result is valid json
When looking up jsonv2 coordinates 36.791966,127.171726
Then the result is valid json
Scenario: Reverse-geocoding with zoom
Given the request parameters
| zoom
| 10
When looking up xml coordinates 36.791966,127.171726
Then the result is valid xml
When looking up json coordinates 36.791966,127.171726
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

@@ -0,0 +1,82 @@
Feature: Search queries
Testing correctness of results
Scenario: UK House number search
When sending json search query "27 Thoresby Road, Broxtowe" with address
Then address of result 0 contains
| type | value
| house_number | 27
| road | Thoresby Road
| city | Broxtowe
| state | England
| country | United Kingdom
| country_code | gb
Scenario: House number search for non-street address
Given the request parameters
| accept-language
| en
When sending json search query "4 Pomocnia, Pokrzywnica, Poland" with address
Then address of result 0 contains
| type | value
| house_number | 4
| 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
| accept-language
| en
When sending json search query "140 rue Don Bosco, Saguenay" with address
Then address of result 0 contains
| type | value
| house_number | 140
| road | [Rr]ue Don Bosco
| city | Saguenay
| state | Quebec
| country | Canada
| country_code | ca
Scenario: House number interpolation odd
Given the request parameters
| accept-language
| en
When sending json search query "141 rue Don Bosco, Saguenay" with address
Then address of result 0 contains
| type | value
| house_number | 141
| road | [rR]ue Don Bosco
| city | Saguenay
| state | Quebec
| 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
Scenario: Expansion of Illinois
Given the request parameters
| accept-language
| en
When sending json search query "il, us"
Then results contain
| ID | display_name
| 0 | Illinois.*
Scenario: Search with class-type feature
When sending jsonv2 search query "Hotel California"
Then results contain
| place_rank
| 30

View File

@@ -0,0 +1,36 @@
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
| <type> | <city>
Examples:
| type | city | street
| city | Zürich | Rigistr
| city | Karlsruhe | Sophienstr
| city | München | Karlstr
| city | Praha | Dlouhá
Scenario Outline: use more important city in street search
When sending json search query "<street>, <city>" with address
Then result addresses contain
| ID | country_code
| 0 | <country>
Examples:
| country | city | street
| gb | London | Main St
| gb | Manchester | Central Street
# https://trac.openstreetmap.org/ticket/5094
Scenario: housenumbers are ordered by complete match first
When sending json search query "4 Докукина Москва" with address
Then result addresses contain
| ID | house_number
| 0 | 4

View File

@@ -0,0 +1,232 @@
Feature: Search queries
Testing different queries and parameters
Scenario: Simple XML search
When sending xml search query "Schaan"
Then result 0 has attributes place_id,osm_type,osm_id
And result 0 has attributes place_rank,boundingbox
And result 0 has attributes lat,lon,display_name
And result 0 has attributes class,type,importance,icon
And result 0 has not attributes address
Scenario: Simple JSON search
When sending json search query "Vaduz"
And result 0 has attributes place_id,licence,icon,class,type
And result 0 has attributes osm_type,osm_id,boundingbox
And result 0 has attributes lat,lon,display_name,importance
And result 0 has not attributes address
Scenario: JSON search with addressdetails
When sending json search query "Montevideo" with address
Then address of result 0 is
| type | value
| city | Montevideo
| state | Montevideo
| country | Uruguay
| country_code | uy
Scenario: XML search with addressdetails
When sending xml search query "Inuvik" with address
Then address of result 0 contains
| type | value
| city | Inuvik
| state | Northwest Territories
| country | Canada
| country_code | ca
Scenario: Address details with unknown class types
When sending json search query "foobar, Essen" with address
Then results contain
| ID | class | type
| 0 | leisure | hackerspace
And result addresses contain
| ID | address29
| 0 | Chaospott
And address of result 0 does not contain leisure,hackerspace
Scenario: Disabling deduplication
When sending json search query "Oxford Street, London"
Then there are no duplicates
Given the request parameters
| dedupe
| 0
When sending json search query "Oxford Street, London"
Then there are duplicates
Scenario: Search with bounded viewbox in right area
Given the request parameters
| bounded | viewbox
| 1 | -87.7,41.9,-87.57,41.85
When sending json search query "restaurant" with address
Then result addresses contain
| ID | city
| 0 | Chicago
Scenario: Search with bounded viewboxlbrt in right area
Given the request parameters
| bounded | viewboxlbrt
| 1 | -87.7,41.85,-87.57,41.9
When sending json search query "restaurant" with address
Then result addresses contain
| ID | city
| 0 | Chicago
Scenario: No POI search with unbounded viewbox
Given the request parameters
| viewbox
| -87.7,41.9,-87.57,41.85
When sending json search query "restaurant"
Then results contain
| display_name
| [^,]*(?i)restaurant.*
Scenario: bounded search remains within viewbox, even with no results
Given the request parameters
| bounded | viewbox
| 1 | 43.54285,-5.662003,43.5403125,-5.6563282
When sending json search query "restaurant"
Then less than 1 result is returned
Scenario: bounded search remains within viewbox with results
Given the request parameters
| bounded | viewbox
| 1 | -5.662003,43.55,-5.6563282,43.5403125
When sending json search query "restaurant"
| lon | lat
| >= -5.662003 | >= 43.5403125
| <= -5.6563282| <= 43.55
Scenario: Prefer results within viewbox
Given the request parameters
| accept-language
| en
When sending json search query "royan" with address
Then result addresses contain
| ID | country
| 0 | France
Given the request parameters
| accept-language | viewbox
| en | 51.94,36.59,51.99,36.56
When sending json search query "royan" with address
Then result addresses contain
| ID | country
| 0 | Iran
Scenario: Overly large limit number for search results
Given the request parameters
| limit
| 1000
When sending json search query "Neustadt"
Then at most 50 results are returned
Scenario: Limit number of search results
Given the request parameters
| limit
| 4
When sending json search query "Neustadt"
Then exactly 4 results are returned
Scenario: Restrict to feature type country
Given the request parameters
| featureType
| country
When sending xml search query "Monaco"
Then results contain
| place_rank
| 4
Scenario: Restrict to feature type state
When sending xml search query "Berlin"
Then results contain
| ID | place_rank
| 0 | 1[56]
Given the request parameters
| featureType
| state
When sending xml search query "Berlin"
Then results contain
| place_rank
| [78]
Scenario: Restrict to feature type city
Given the request parameters
| featureType
| city
When sending xml search query "Monaco"
Then results contain
| place_rank
| 1[56789]
Scenario: Restrict to feature type settlement
When sending json search query "Everest"
Then results contain
| ID | display_name
| 0 | Mount Everest.*
Given the request parameters
| featureType
| settlement
When sending json search query "Everest"
Then results contain
| ID | display_name
| 0 | Everest.*
Scenario Outline: Search with polygon threshold (json)
Given the request parameters
| polygon_geojson | polygon_threshold
| 1 | <th>
When sending json search query "switzerland"
Then at least 1 result is returned
And result 0 has attributes geojson
Examples:
| th
| -1
| 0.0
| 0.5
| 999
| nan
Scenario Outline: Search with polygon threshold (xml)
Given the request parameters
| polygon_geojson | polygon_threshold
| 1 | <th>
When sending xml search query "switzerland"
Then at least 1 result is returned
And result 0 has attributes geojson
Examples:
| th
| -1
| 0.0
| 0.5
| 999
| nan
Scenario Outline: Search with extratags
Given the request parameters
| extratags
| 1
When sending <format> search query "Hauptstr"
Then result 0 has attributes extratags
And result 1 has attributes extratags
Examples:
| format
| xml
| json
| jsonv2
Scenario Outline: Search with namedetails
Given the request parameters
| namedetails
| 1
When sending <format> search query "Hauptstr"
Then result 0 has attributes namedetails
And result 1 has attributes namedetails
Examples:
| format
| xml
| json
| jsonv2

View File

@@ -0,0 +1,238 @@
Feature: Simple Tests
Simple tests for internal server errors and response format.
These tests should pass on any Nominatim installation.
Scenario Outline: Testing different parameters
Given the request parameters
| <parameter>
| <value>
When sending search query "Manchester"
Then the result is valid html
Given the request parameters
| <parameter>
| <value>
When sending html search query "Manchester"
Then the result is valid html
Given the request parameters
| <parameter>
| <value>
When sending xml search query "Manchester"
Then the result is valid xml
Given the request parameters
| <parameter>
| <value>
When sending json search query "Manchester"
Then the result is valid json
Given the request parameters
| <parameter>
| <value>
When sending jsonv2 search query "Manchester"
Then the result is valid json
Examples:
| parameter | value
| addressdetails | 1
| addressdetails | 0
| polygon | 1
| polygon | 0
| polygon_text | 1
| polygon_text | 0
| polygon_kml | 1
| polygon_kml | 0
| polygon_geojson | 1
| polygon_geojson | 0
| polygon_svg | 1
| polygon_svg | 0
| accept-language | de,en
| countrycodes | uk,ir
| bounded | 1
| bounded | 0
| exclude_place_ids| 385252,1234515
| limit | 1000
| dedupe | 1
| dedupe | 0
| extratags | 1
| extratags | 0
| namedetails | 1
| namedetails | 0
Scenario: Search with invalid output format
Given the request parameters
| format
| fd$#
When sending search query "Berlin"
Then the result is valid html
Scenario Outline: Simple Searches
When sending search query "<query>"
Then the result is valid html
When sending html search query "<query>"
Then the result is valid html
When sending xml search query "<query>"
Then the result is valid xml
When sending json search query "<query>"
Then the result is valid json
When sending jsonv2 search query "<query>"
Then the result is valid json
Examples:
| query
| New York, New York
| France
| 12, Main Street, Houston
| München
|
| hotels in nantes
| xywxkrf
| gh; foo()
| %#$@*&l;der#$!
| 234
| 47.4,8.3
Scenario: Empty XML search
When sending xml search query "xnznxvcx"
Then result header contains
| attr | value
| querystring | xnznxvcx
| polygon | false
| more_url | .*format=xml.*q=xnznxvcx.*
Scenario: Empty XML search with special XML characters
When sending xml search query "xfdghn&zxn"xvbyx<vxx>cssdex"
Then result header contains
| attr | value
| querystring | xfdghn&zxn"xvbyx<vxx>cssdex
| polygon | false
| more_url | .*format=xml.*q=xfdghn&zxn"xvbyx<vxx>cssdex.*
Scenario: Empty XML search with viewbox
Given the request parameters
| viewbox
| 12,45.13,77,33
When sending xml search query "xnznxvcx"
Then result header contains
| attr | value
| querystring | xnznxvcx
| polygon | false
| viewbox | 12,45.13,77,33
Scenario: Empty XML search with viewboxlbrt
Given the request parameters
| viewboxlbrt
| 12,34.13,77,45
When sending xml search query "xnznxvcx"
Then result header contains
| attr | value
| querystring | xnznxvcx
| polygon | false
| viewbox | 12,45.13,77,33
Scenario: Empty XML search with viewboxlbrt and viewbox
Given the request parameters
| viewbox | viewboxblrt
| 12,45.13,77,33 | 1,2,3,4
When sending xml search query "pub"
Then result header contains
| attr | value
| querystring | pub
| polygon | false
| viewbox | 12,45.13,77,33
Scenario Outline: Empty XML search with polygon values
Given the request parameters
| polygon
| <polyval>
When sending xml search query "xnznxvcx"
Then result header contains
| attr | value
| polygon | <result>
Examples:
| result | polyval
| false | 0
| true | 1
| true | True
| true | true
| true | false
| true | FALSE
| true | yes
| true | no
| true | '; delete from foobar; select '
Scenario: Empty XML search with exluded place ids
Given the request parameters
| exclude_place_ids
| 123,76,342565
When sending xml search query "jghrleoxsbwjer"
Then result header contains
| 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
| <data>
When sending json search query "Tokyo"
Then there is a json wrapper "<data>"
Examples:
| data
| foo
| FOO
| __world
| $me
| m1[4]
| d_r[$d]
Scenario Outline: Wrapping of illegal jsonp search requests
Given the request parameters
| json_callback
| <data>
When sending json search query "Tokyo"
Then a HTTP 400 is returned
Examples:
| data
| 1asd
| bar(foo)
| XXX['bad']
| foo; evil
Scenario Outline: Ignore jsonp parameter for anything but json
Given the request parameters
| json_callback
| 234
When sending json search query "Malibu"
Then a HTTP 400 is returned
Given the request parameters
| json_callback
| 234
When sending xml search query "Malibu"
Then the result is valid xml
Given the request parameters
| json_callback
| 234
When sending html search query "Malibu"
Then the result is valid html
Scenario: Empty JSON search
When sending json search query "YHlERzzx"
Then exactly 0 results are returned
Scenario: Empty JSONv2 search
When sending jsonv2 search query "Flubb XdfESSaZx"
Then exactly 0 results are returned
Scenario: Search for non-existing coordinates
When sending json search query "-21.0,-33.0"
Then exactly 0 results are returned

View File

@@ -0,0 +1,41 @@
Feature: Structured search queries
Testing correctness of results with
structured queries
Scenario: Country only
When sending json structured query with address
| country
| Canada
Then address of result 0 is
| type | value
| country | Canada
| country_code | ca
Scenario: Postcode only
When sending json structured query with address
| postalcode
| 22547
Then at least 1 result is returned
And results contain
| type
| post(al_)?code
And result addresses contain
| postcode
| 22547
Scenario: Street, postcode and country
When sending xml structured query with address
| street | postalcode | country
| Old Palace Road | GU2 7UP | United Kingdom
Then at least 1 result is returned
Then result header contains
| attr | value
| querystring | Old Palace Road, GU2 7UP, United Kingdom
Scenario: gihub #176
When sending json structured query with address
| city
| Washington
Then at least 1 result is returned

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

@@ -0,0 +1,112 @@
@DB
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
| osm_type | osm_id | class | type | name | geometry
| W | 1 | waterway | river | Rhein | :w-2
| W | 2 | waterway | river | Rhein | :w-3
| R | 13 | waterway | river | Rhein | :w-1 + :w-2 + :w-3
| R | 23 | waterway | river | Limmat| :w-4a
And the relations
| id | members | tags
| 13 | R23:tributary,W1,W2:main_stream | 'type' : 'waterway'
When importing
Then table placex contains
| object | linked_place_id
| W1 | R13
| W2 | R13
| R13 | None
| R23 | None
When sending query "rhein"
Then results contain
| osm_type
| R
Scenario: Relations are not linked when in waterway relations
Given the scene split-road
And the place ways
| osm_type | osm_id | class | type | name | geometry
| W | 1 | waterway | river | Rhein | :w-2
| W | 2 | waterway | river | Rhein | :w-3
| R | 1 | waterway | river | Rhein | :w-1 + :w-2 + :w-3
| R | 2 | waterway | river | Limmat| :w-4a
And the relations
| id | members | tags
| 1 | R2 | 'type' : 'waterway'
When importing
Then table placex contains
| object | linked_place_id
| W1 | None
| W2 | None
| R1 | None
| R2 | None
Scenario: Empty waterway relations are handled correctly
Given the scene split-road
And the place ways
| osm_type | osm_id | class | type | name | geometry
| R | 1 | waterway | river | Rhein | :w-1 + :w-2 + :w-3
And the relations
| id | members | tags
| 1 | | 'type' : 'waterway'
When importing
Then table placex contains
| object | linked_place_id
| R1 | None
Scenario: Waterways are not linked when waterway types don't match
Given the scene split-road
And the place ways
| osm_type | osm_id | class | type | name | geometry
| W | 1 | waterway | drain | Rhein | :w-2
| R | 1 | waterway | river | Rhein | :w-1 + :w-2 + :w-3
And the relations
| id | members | tags
| 1 | N23,N34,W1,R45 | 'type' : 'multipolygon'
When importing
Then table placex contains
| object | linked_place_id
| W1 | None
| R1 | None
When sending query "rhein"
Then results contain
| ID | osm_type
| 0 | R
| 1 | W
Scenario: Side streams are linked only when they have the same name
Given the scene split-road
And the place ways
| osm_type | osm_id | class | type | name | geometry
| W | 1 | waterway | river | Rhein2 | :w-2
| W | 2 | waterway | river | Rhein | :w-3
| R | 1 | waterway | river | Rhein | :w-1 + :w-2 + :w-3
And the relations
| id | members | tags
| 1 | W1:side_stream,W2:side_stream | 'type' : 'waterway'
When importing
Then table placex contains
| object | linked_place_id
| W1 | None
| W2 | R1
When sending query "rhein2"
Then results contain
| osm_type
| W

View File

@@ -0,0 +1,193 @@
@DB
Feature: Import and search of names
Tests all naming related issues: normalisation,
abbreviations, internationalisation, etc.
Scenario: Case-insensitivity of search
Given the place nodes
| osm_id | class | type | name
| 1 | place | locality | 'name' : 'FooBar'
When importing
Then table placex contains
| object | class | type | name
| N1 | place | locality | 'name' : 'FooBar'
When sending query "FooBar"
Then results contain
| ID | osm_type | osm_id
| 0 | N | 1
When sending query "foobar"
Then results contain
| ID | osm_type | osm_id
| 0 | N | 1
When sending query "fOObar"
Then results contain
| ID | osm_type | osm_id
| 0 | N | 1
When sending query "FOOBAR"
Then results contain
| ID | osm_type | osm_id
| 0 | N | 1
Scenario: Multiple spaces in name
Given the place nodes
| osm_id | class | type | name
| 1 | place | locality | 'name' : 'one two three'
When importing
When sending query "one two three"
Then results contain
| ID | osm_type | osm_id
| 0 | N | 1
When sending query "one two three"
Then results contain
| ID | osm_type | osm_id
| 0 | N | 1
When sending query "one two three"
Then results contain
| ID | osm_type | osm_id
| 0 | N | 1
When sending query " one two three"
Then results contain
| ID | osm_type | osm_id
| 0 | N | 1
Scenario: Special characters in name
Given the place nodes
| osm_id | class | type | name
| 1 | place | locality | 'name' : 'Jim-Knopf-Str'
| 2 | place | locality | 'name' : 'Smith/Weston'
| 3 | place | locality | 'name' : 'space mountain'
| 4 | place | locality | 'name' : 'space'
| 5 | place | locality | 'name' : 'mountain'
When importing
When sending query "Jim-Knopf-Str"
Then results contain
| ID | osm_type | osm_id
| 0 | N | 1
When sending query "Jim Knopf-Str"
Then results contain
| ID | osm_type | osm_id
| 0 | N | 1
When sending query "Jim Knopf Str"
Then results contain
| ID | osm_type | osm_id
| 0 | N | 1
When sending query "Jim/Knopf-Str"
Then results contain
| ID | osm_type | osm_id
| 0 | N | 1
When sending query "Jim-Knopfstr"
Then results contain
| ID | osm_type | osm_id
| 0 | N | 1
When sending query "Smith/Weston"
Then results contain
| ID | osm_type | osm_id
| 0 | N | 2
When sending query "Smith Weston"
Then results contain
| ID | osm_type | osm_id
| 0 | N | 2
When sending query "Smith-Weston"
Then results contain
| ID | osm_type | osm_id
| 0 | N | 2
When sending query "space mountain"
Then results contain
| ID | osm_type | osm_id
| 0 | N | 3
When sending query "space-mountain"
Then results contain
| ID | osm_type | osm_id
| 0 | N | 3
When sending query "space/mountain"
Then results contain
| ID | osm_type | osm_id
| 0 | N | 3
When sending query "space\mountain"
Then results contain
| ID | osm_type | osm_id
| 0 | N | 3
When sending query "space(mountain)"
Then results contain
| ID | osm_type | osm_id
| 0 | N | 3
Scenario: No copying name tag if only one name
Given the place nodes
| osm_id | class | type | name | geometry
| 1 | place | locality | 'name' : 'german' | country:de
When importing
Then table placex contains
| object | calculated_country_code |
| N1 | de
And table placex contains as names for N1
| object | k | v
| N1 | name | german
Scenario: Copying name tag to default language if it does not exist
Given the place nodes
| osm_id | class | type | name | geometry
| 1 | place | locality | 'name' : 'german', 'name:fi' : 'finnish' | country:de
When importing
Then table placex contains
| object | calculated_country_code |
| N1 | de
And table placex contains as names for N1
| k | v
| name | german
| name:fi | finnish
| name:de | german
Scenario: Copying default language name tag to name if it does not exist
Given the place nodes
| osm_id | class | type | name | geometry
| 1 | place | locality | 'name:de' : 'german', 'name:fi' : 'finnish' | country:de
When importing
Then table placex contains
| object | calculated_country_code |
| N1 | de
And table placex contains as names for N1
| k | v
| name | german
| name:fi | finnish
| name:de | german
Scenario: Do not overwrite default language with name tag
Given the place nodes
| osm_id | class | type | name | geometry
| 1 | place | locality | 'name' : 'german', 'name:fi' : 'finnish', 'name:de' : 'local' | country:de
When importing
Then table placex contains
| object | calculated_country_code |
| N1 | de
And table placex contains as names for N1
| k | v
| name | german
| name:fi | finnish
| name:de | local
Scenario: Landuse with name are found
Given the place areas
| osm_type | osm_id | class | type | name | geometry
| R | 1 | natural | meadow | 'name' : 'landuse1' | (0 0, 1 0, 1 1, 0 1, 0 0)
| R | 2 | landuse | industrial | 'name' : 'landuse2' | (0 0, -1 0, -1 -1, 0 -1, 0 0)
When importing
When sending query "landuse1"
Then results contain
| ID | osm_type | osm_id
| 0 | R | 1
When sending query "landuse2"
Then results contain
| ID | osm_type | osm_id
| 0 | R | 2
Scenario: Postcode boundaries without ref
Given the place areas
| osm_type | osm_id | class | type | postcode | geometry
| R | 1 | boundary | postal_code | 12345 | (0 0, 1 0, 1 1, 0 1, 0 0)
When importing
When sending query "12345"
Then results contain
| ID | osm_type | osm_id
| 0 | R | 1

View File

@@ -0,0 +1,458 @@
@DB
Feature: Parenting of objects
Tests that the correct parent is choosen
Scenario: Address inherits postcode from its street unless it has a postcode
Given the scene roads-with-pois
And the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 4 | :p-N1
And the place nodes
| osm_id | class | type | housenumber | postcode | geometry
| 2 | place | house | 5 | 99999 | :p-N1
And the place ways
| osm_id | class | type | name | postcode | geometry
| 1 | highway | residential | galoo | 12345 | :w-north
When importing
Then table placex contains
| object | parent_place_id
| N1 | W1
| N2 | W1
When sending query "4 galoo"
Then results contain
| ID | osm_type | osm_id | langaddress
| 0 | N | 1 | 4, galoo, 12345
When sending query "5 galoo"
Then results contain
| ID | osm_type | osm_id | langaddress
| 0 | N | 2 | 5, galoo, 99999
Scenario: Address without tags, closest street
Given the scene roads-with-pois
And the place nodes
| osm_id | class | type | geometry
| 1 | place | house | :p-N1
| 2 | place | house | :p-N2
| 3 | place | house | :p-S1
| 4 | place | house | :p-S2
And the named place ways
| osm_id | class | type | geometry
| 1 | highway | residential | :w-north
| 2 | highway | residential | :w-south
When importing
Then table placex contains
| object | parent_place_id
| N1 | W1
| N2 | W1
| N3 | W2
| N4 | W2
Scenario: Address without tags avoids unnamed streets
Given the scene roads-with-pois
And the place nodes
| osm_id | class | type | geometry
| 1 | place | house | :p-N1
| 2 | place | house | :p-N2
| 3 | place | house | :p-S1
| 4 | place | house | :p-S2
And the place ways
| osm_id | class | type | geometry
| 1 | highway | residential | :w-north
And the named place ways
| osm_id | class | type | geometry
| 2 | highway | residential | :w-south
When importing
Then table placex contains
| object | parent_place_id
| N1 | W2
| N2 | W2
| N3 | W2
| N4 | W2
Scenario: addr:street tag parents to appropriately named street
Given the scene roads-with-pois
And the place nodes
| osm_id | class | type | street| geometry
| 1 | place | house | south | :p-N1
| 2 | place | house | north | :p-N2
| 3 | place | house | south | :p-S1
| 4 | place | house | north | :p-S2
And the place ways
| osm_id | class | type | name | geometry
| 1 | highway | residential | north | :w-north
| 2 | highway | residential | south | :w-south
When importing
Then table placex contains
| object | parent_place_id
| N1 | W2
| N2 | W1
| N3 | W2
| N4 | W1
Scenario: addr:street tag parents to next named street
Given the scene roads-with-pois
And the place nodes
| osm_id | class | type | street | geometry
| 1 | place | house | abcdef | :p-N1
| 2 | place | house | abcdef | :p-N2
| 3 | place | house | abcdef | :p-S1
| 4 | place | house | abcdef | :p-S2
And the place ways
| osm_id | class | type | name | geometry
| 1 | highway | residential | abcdef | :w-north
| 2 | highway | residential | abcdef | :w-south
When importing
Then table placex contains
| object | parent_place_id
| N1 | W1
| N2 | W1
| N3 | W2
| N4 | W2
Scenario: addr:street tag without appropriately named street
Given the scene roads-with-pois
And the place nodes
| osm_id | class | type | street | geometry
| 1 | place | house | abcdef | :p-N1
| 2 | place | house | abcdef | :p-N2
| 3 | place | house | abcdef | :p-S1
| 4 | place | house | abcdef | :p-S2
And the place ways
| osm_id | class | type | name | geometry
| 1 | highway | residential | abcde | :w-north
| 2 | highway | residential | abcde | :w-south
When importing
Then table placex contains
| object | parent_place_id
| N1 | W1
| N2 | W1
| N3 | W2
| N4 | W2
Scenario: addr:place address
Given the scene road-with-alley
And the place nodes
| osm_id | class | type | addr_place | geometry
| 1 | place | house | myhamlet | :n-alley
And the place nodes
| osm_id | class | type | name | geometry
| 2 | place | hamlet | myhamlet | :n-main-west
And the place ways
| osm_id | class | type | name | geometry
| 1 | highway | residential | myhamlet | :w-main
When importing
Then table placex contains
| object | parent_place_id
| N1 | N2
Scenario: addr:street is preferred over addr:place
Given the scene road-with-alley
And the place nodes
| osm_id | class | type | addr_place | street | geometry
| 1 | place | house | myhamlet | mystreet| :n-alley
And the place nodes
| osm_id | class | type | name | geometry
| 2 | place | hamlet | myhamlet | :n-main-west
And the place ways
| osm_id | class | type | name | geometry
| 1 | highway | residential | mystreet | :w-main
When importing
Then table placex contains
| object | parent_place_id
| N1 | W1
Scenario: Untagged address in simple associated street relation
Given the scene road-with-alley
And the place nodes
| osm_id | class | type | geometry
| 1 | place | house | :n-alley
| 2 | place | house | :n-corner
| 3 | place | house | :n-main-west
And the place ways
| osm_id | class | type | name | geometry
| 1 | highway | residential | foo | :w-main
| 2 | highway | service | bar | :w-alley
And the relations
| id | members | tags
| 1 | W1:street,N1,N2,N3 | 'type' : 'associatedStreet'
When importing
Then table placex contains
| object | parent_place_id
| N1 | W1
| N2 | W1
| N3 | W1
Scenario: Avoid unnamed streets in simple associated street relation
Given the scene road-with-alley
And the place nodes
| osm_id | class | type | geometry
| 1 | place | house | :n-alley
| 2 | place | house | :n-corner
| 3 | place | house | :n-main-west
And the named place ways
| osm_id | class | type | geometry
| 1 | highway | residential | :w-main
And the place ways
| osm_id | class | type | geometry
| 2 | highway | residential | :w-alley
And the relations
| id | members | tags
| 1 | N1,N2,N3,W2:street,W1:street | 'type' : 'associatedStreet'
When importing
Then table placex contains
| object | parent_place_id
| N1 | W1
| N2 | W1
| N3 | W1
### Scenario 10
Scenario: Associated street relation overrides addr:street
Given the scene road-with-alley
And the place nodes
| osm_id | class | type | street | geometry
| 1 | place | house | bar | :n-alley
And the place ways
| osm_id | class | type | name | geometry
| 1 | highway | residential | foo | :w-main
| 2 | highway | residential | bar | :w-alley
And the relations
| id | members | tags
| 1 | W1:street,N1,N2,N3 | 'type' : 'associatedStreet'
When importing
Then table placex contains
| object | parent_place_id
| N1 | W1
Scenario: Building without tags, closest street from center point
Given the scene building-on-street-corner
And the named place ways
| osm_id | class | type | geometry
| 1 | building | yes | :w-building
| 2 | highway | primary | :w-WE
| 3 | highway | residential | :w-NS
When importing
Then table placex contains
| object | parent_place_id
| W1 | W3
Scenario: Building with addr:street tags
Given the scene building-on-street-corner
And the named place ways
| osm_id | class | type | street | geometry
| 1 | building | yes | bar | :w-building
And the place ways
| osm_id | class | type | name | geometry
| 2 | highway | primary | bar | :w-WE
| 3 | highway | residential | foo | :w-NS
When importing
Then table placex contains
| object | parent_place_id
| W1 | W2
Scenario: Building with addr:place tags
Given the scene building-on-street-corner
And the place nodes
| osm_id | class | type | name | geometry
| 1 | place | village | bar | :n-outer
And the named place ways
| osm_id | class | type | addr_place | geometry
| 1 | building | yes | bar | :w-building
And the place ways
| osm_id | class | type | name | geometry
| 2 | highway | primary | bar | :w-WE
| 3 | highway | residential | foo | :w-NS
When importing
Then table placex contains
| object | parent_place_id
| W1 | N1
Scenario: Building in associated street relation
Given the scene building-on-street-corner
And the named place ways
| osm_id | class | type | geometry
| 1 | building | yes | :w-building
And the place ways
| osm_id | class | type | name | geometry
| 2 | highway | primary | bar | :w-WE
| 3 | highway | residential | foo | :w-NS
And the relations
| id | members | tags
| 1 | W1:house,W2:street | 'type' : 'associatedStreet'
When importing
Then table placex contains
| object | parent_place_id
| W1 | W2
Scenario: Building in associated street relation overrides addr:street
Given the scene building-on-street-corner
And the named place ways
| osm_id | class | type | street | geometry
| 1 | building | yes | foo | :w-building
And the place ways
| osm_id | class | type | name | geometry
| 2 | highway | primary | bar | :w-WE
| 3 | highway | residential | foo | :w-NS
And the relations
| id | members | tags
| 1 | W1:house,W2:street | 'type' : 'associatedStreet'
When importing
Then table placex contains
| object | parent_place_id
| W1 | W2
Scenario: Wrong member in associated street relation is ignored
Given the scene building-on-street-corner
And the named place nodes
| osm_id | class | type | geometry
| 1 | place | house | :n-outer
And the named place ways
| osm_id | class | type | street | geometry
| 1 | building | yes | foo | :w-building
And the place ways
| osm_id | class | type | name | geometry
| 2 | highway | primary | bar | :w-WE
| 3 | highway | residential | foo | :w-NS
And the relations
| id | members | tags
| 1 | N1:house,W1:street,W3:street | 'type' : 'associatedStreet'
When importing
Then table placex contains
| object | parent_place_id
| N1 | W3
Scenario: POIs in building inherit address
Given the scene building-on-street-corner
And the named place nodes
| osm_id | class | type | geometry
| 1 | amenity | bank | :n-inner
| 2 | shop | bakery | :n-edge-NS
| 3 | shop | supermarket| :n-edge-WE
And the place ways
| osm_id | class | type | street | addr_place | housenumber | geometry
| 1 | building | yes | foo | nowhere | 3 | :w-building
And the place ways
| osm_id | class | type | name | geometry
| 2 | highway | primary | bar | :w-WE
| 3 | highway | residential | foo | :w-NS
When importing
Then table placex contains
| object | parent_place_id | street | addr_place | housenumber
| W1 | W3 | foo | nowhere | 3
| N1 | W3 | foo | nowhere | 3
| N2 | W3 | foo | nowhere | 3
| N3 | W3 | foo | nowhere | 3
Scenario: POIs don't inherit from streets
Given the scene building-on-street-corner
And the named place nodes
| osm_id | class | type | geometry
| 1 | amenity | bank | :n-inner
And the place ways
| osm_id | class | type | street | addr_place | housenumber | geometry
| 1 | highway | path | foo | nowhere | 3 | :w-building
And the place ways
| osm_id | class | type | name | geometry
| 3 | highway | residential | foo | :w-NS
When importing
Then table placex contains
| object | parent_place_id | street | addr_place | housenumber
| N1 | W3 | None | None | None
Scenario: POIs with own address do not inherit building address
Given the scene building-on-street-corner
And the named place nodes
| osm_id | class | type | street | geometry
| 1 | amenity | bank | bar | :n-inner
And the named place nodes
| osm_id | class | type | housenumber | geometry
| 2 | shop | bakery | 4 | :n-edge-NS
And the named place nodes
| osm_id | class | type | addr_place | geometry
| 3 | shop | supermarket| nowhere | :n-edge-WE
And the place nodes
| osm_id | class | type | name | geometry
| 4 | place | isolated_dwelling | theplace | :n-outer
And the place ways
| osm_id | class | type | addr_place | housenumber | geometry
| 1 | building | yes | theplace | 3 | :w-building
And the place ways
| osm_id | class | type | name | geometry
| 2 | highway | primary | bar | :w-WE
| 3 | highway | residential | foo | :w-NS
When importing
Then table placex contains
| object | parent_place_id | street | addr_place | housenumber
| W1 | N4 | None | theplace | 3
| N1 | W2 | bar | None | None
| N2 | W3 | None | None | 4
| N3 | W2 | None | nowhere | None
### Scenario 20
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
| 1 | highway | bus_stop | North St | :n-SE
| 2 | highway | bus_stop | South St | :n-NW
| 3 | highway | bus_stop | North St | :n-S-unglued
| 4 | highway | bus_stop | South St | :n-N-unglued
And the place ways
| osm_id | class | type | name | geometry
| 1 | highway | secondary | North St | :w-north
| 2 | highway | unclassified | South St | :w-south
And the ways
| id | nodes
| 1 | 100,101,2,103,104
| 2 | 200,201,1,202,203
When importing
Then table placex contains
| object | parent_place_id
| N1 | W1
| N2 | W2
| N3 | W1
| N4 | W2
Scenario: POIs do not parent non-roads they are attached to
Given the scene points-on-roads
And the named place nodes
| osm_id | class | type | street | geometry
| 1 | highway | bus_stop | North St | :n-SE
| 2 | highway | bus_stop | South St | :n-NW
And the place ways
| osm_id | class | type | name | geometry
| 1 | landuse | residential | North St | :w-north
| 2 | waterway| river | South St | :w-south
And the ways
| id | nodes
| 1 | 100,101,2,103,104
| 2 | 200,201,1,202,203
When importing
Then table placex contains
| object | parent_place_id
| N1 | 0
| N2 | 0
Scenario: POIs on building outlines inherit associated street relation
Given the scene building-on-street-corner
And the named place nodes
| osm_id | class | type | geometry
| 1 | place | house | :n-edge-NS
And the named place ways
| osm_id | class | type | geometry
| 1 | building | yes | :w-building
And the place ways
| osm_id | class | type | name | geometry
| 2 | highway | primary | bar | :w-WE
| 3 | highway | residential | foo | :w-NS
And the relations
| id | members | tags
| 1 | W1:house,W2:street | 'type' : 'associatedStreet'
And the ways
| id | nodes
| 1 | 100,1,101,102,100
When importing
Then table placex contains
| object | parent_place_id
| N1 | W2

View File

@@ -0,0 +1,318 @@
@DB
Feature: Import into placex
Tests that data in placex is completed correctly.
Scenario: No country code tag is available
Given the place nodes
| osm_id | class | type | name | geometry
| 1 | highway | primary | 'name' : 'A1' | country:us
When importing
Then table placex contains
| object | country_code | calculated_country_code |
| N1 | None | us |
Scenario: Location overwrites country code tag
Given the scene country
And the place nodes
| osm_id | class | type | name | country_code | geometry
| 1 | highway | primary | 'name' : 'A1' | de | :us
When importing
Then table placex contains
| object | country_code | calculated_country_code |
| N1 | de | us |
Scenario: Country code tag overwrites location for countries
Given the place areas
| osm_type | osm_id | class | type | admin_level | name | country_code | geometry
| R | 1 | boundary | administrative | 2 | 'name' : 'foo' | de | (-100 40, -101 40, -101 41, -100 41, -100 40)
When importing
Then table placex contains
| object | country_code | calculated_country_code |
| R1 | de | de |
Scenario: Illegal country code tag for countries is ignored
And the place areas
| osm_type | osm_id | class | type | admin_level | name | country_code | geometry
| R | 1 | boundary | administrative | 2 | 'name' : 'foo' | xx | (-100 40, -101 40, -101 41, -100 41, -100 40)
When importing
Then table placex contains
| object | country_code | calculated_country_code |
| R1 | xx | us |
Scenario: admin level is copied over
Given the place nodes
| osm_id | class | type | admin_level | name
| 1 | place | state | 3 | 'name' : 'foo'
When importing
Then table placex contains
| object | admin_level |
| N1 | 3 |
Scenario: admin level is default 15
Given the place nodes
| osm_id | class | type | name
| 1 | amenity | prison | 'name' : 'foo'
When importing
Then table placex contains
| object | admin_level |
| N1 | 15 |
Scenario: admin level is never larger than 15
Given the place nodes
| osm_id | class | type | name | admin_level
| 1 | amenity | prison | 'name' : 'foo' | 16
When importing
Then table placex contains
| object | admin_level |
| N1 | 15 |
Scenario: postcode node without postcode is dropped
Given the place nodes
| osm_id | class | type
| 1 | place | postcode
When importing
Then table placex has no entry for N1
Scenario: postcode boundary without postcode is dropped
Given the place areas
| osm_type | osm_id | class | type | geometry
| R | 1 | boundary | postal_code | poly-area:0.1
When importing
Then table placex has no entry for R1
Scenario: search and address ranks for GB post codes correctly assigned
Given the place nodes
| osm_id | class | type | postcode | geometry
| 1 | place | postcode | E45 2CD | country:gb
| 2 | place | postcode | E45 2 | country:gb
| 3 | place | postcode | Y45 | country:gb
When importing
Then table placex contains
| object | postcode | calculated_country_code | rank_search | rank_address
| N1 | E45 2CD | gb | 25 | 5
| N2 | E45 2 | gb | 23 | 5
| N3 | Y45 | gb | 21 | 5
Scenario: wrongly formatted GB postcodes are down-ranked
Given the place nodes
| osm_id | class | type | postcode | geometry
| 1 | place | postcode | EA452CD | country:gb
| 2 | place | postcode | E45 23 | country:gb
| 3 | place | postcode | y45 | country:gb
When importing
Then table placex contains
| object | calculated_country_code | rank_search | rank_address
| N1 | gb | 30 | 30
| N2 | gb | 30 | 30
| N3 | gb | 30 | 30
Scenario: search and address rank for DE postcodes correctly assigned
Given the place nodes
| osm_id | class | type | postcode | geometry
| 1 | place | postcode | 56427 | country:de
| 2 | place | postcode | 5642 | country:de
| 3 | place | postcode | 5642A | country:de
| 4 | place | postcode | 564276 | country:de
When importing
Then table placex contains
| object | calculated_country_code | rank_search | rank_address
| N1 | de | 21 | 11
| N2 | de | 30 | 30
| N3 | de | 30 | 30
| N4 | de | 30 | 30
Scenario: search and address rank for other postcodes are correctly assigned
Given the place nodes
| osm_id | class | type | postcode | geometry
| 1 | place | postcode | 1 | country:ca
| 2 | place | postcode | X3 | country:ca
| 3 | place | postcode | 543 | country:ca
| 4 | place | postcode | 54dc | country:ca
| 5 | place | postcode | 12345 | country:ca
| 6 | place | postcode | 55TT667 | country:ca
| 7 | place | postcode | 123-65 | country:ca
| 8 | place | postcode | 12 445 4 | country:ca
| 9 | place | postcode | A1:bc10 | country:ca
When importing
Then table placex contains
| object | calculated_country_code | rank_search | rank_address
| N1 | ca | 21 | 11
| N2 | ca | 21 | 11
| N3 | ca | 21 | 11
| N4 | ca | 21 | 11
| N5 | ca | 21 | 11
| N6 | ca | 21 | 11
| N7 | ca | 25 | 11
| N8 | ca | 25 | 11
| N9 | ca | 25 | 11
Scenario: search and address ranks for places are correctly assigned
Given the named place nodes
| osm_id | class | type |
| 1 | foo | bar |
| 11 | place | Continent |
| 12 | place | continent |
| 13 | place | sea |
| 14 | place | country |
| 15 | place | state |
| 16 | place | region |
| 17 | place | county |
| 18 | place | city |
| 19 | place | island |
| 20 | place | town |
| 21 | place | village |
| 22 | place | hamlet |
| 23 | place | municipality |
| 24 | place | district |
| 25 | place | unincorporated_area |
| 26 | place | borough |
| 27 | place | suburb |
| 28 | place | croft |
| 29 | place | subdivision |
| 30 | place | isolated_dwelling |
| 31 | place | farm |
| 32 | place | locality |
| 33 | place | islet |
| 34 | place | mountain_pass |
| 35 | place | neighbourhood |
| 36 | place | house |
| 37 | place | building |
| 38 | place | houses |
And the named place nodes
| osm_id | class | type | extratags
| 100 | place | locality | 'locality' : 'townland'
| 101 | place | city | 'capital' : 'yes'
When importing
Then table placex contains
| object | rank_search | rank_address |
| N1 | 30 | 30 |
| N11 | 30 | 30 |
| N12 | 2 | 2 |
| N13 | 2 | 0 |
| N14 | 4 | 4 |
| N15 | 8 | 8 |
| N16 | 18 | 0 |
| N17 | 12 | 12 |
| N18 | 16 | 16 |
| N19 | 17 | 0 |
| N20 | 18 | 16 |
| N21 | 19 | 16 |
| N22 | 19 | 16 |
| N23 | 19 | 16 |
| N24 | 19 | 16 |
| N25 | 19 | 16 |
| N26 | 19 | 16 |
| N27 | 20 | 20 |
| N28 | 20 | 20 |
| N29 | 20 | 20 |
| N30 | 20 | 20 |
| N31 | 20 | 0 |
| N32 | 20 | 0 |
| N33 | 20 | 0 |
| N34 | 20 | 0 |
| N100 | 20 | 20 |
| N101 | 15 | 16 |
| N35 | 22 | 22 |
| N36 | 30 | 30 |
| N37 | 30 | 30 |
| N38 | 28 | 0 |
Scenario: search and address ranks for boundaries are correctly assigned
Given the named place nodes
| osm_id | class | type
| 1 | boundary | administrative
And the named place ways
| osm_id | class | type | geometry
| 10 | boundary | administrative | 10 10, 11 11
And the named place areas
| osm_type | osm_id | class | type | admin_level | geometry
| R | 20 | boundary | administrative | 2 | (1 1, 2 2, 1 2, 1 1)
| R | 21 | boundary | administrative | 32 | (3 3, 4 4, 3 4, 3 3)
| R | 22 | boundary | nature_park | 6 | (0 0, 1 0, 0 1, 0 0)
| R | 23 | boundary | natural_reserve| 10 | (0 0, 1 1, 1 0, 0 0)
When importing
Then table placex has no entry for N1
And table placex has no entry for W10
And table placex contains
| object | rank_search | rank_address
| R20 | 4 | 4
| R21 | 30 | 30
| R22 | 12 | 0
| R23 | 20 | 0
Scenario: search and address ranks for highways correctly assigned
Given the scene roads-with-pois
And the place nodes
| osm_id | class | type
| 1 | highway | bus_stop
And the place ways
| osm_id | class | type | geometry
| 1 | highway | primary | :w-south
| 2 | highway | secondary | :w-south
| 3 | highway | tertiary | :w-south
| 4 | highway | residential | :w-north
| 5 | highway | unclassified | :w-north
| 6 | highway | something | :w-north
When importing
Then table placex contains
| object | rank_search | rank_address
| N1 | 30 | 30
| W1 | 26 | 26
| W2 | 26 | 26
| W3 | 26 | 26
| W4 | 26 | 26
| W5 | 26 | 26
| W6 | 26 | 26
Scenario: rank and inclusion of landuses
And the named place nodes
| osm_id | class | type
| 2 | landuse | residential
And the named place ways
| osm_id | class | type | geometry
| 2 | landuse | residential | 1 1, 1 1.1
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
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
And the named place nodes
| osm_id | class | type
| 2 | natural | peak
| 4 | natural | volcano
| 5 | natural | foobar
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
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
When importing
And table placex contains
| object | rank_search | rank_address
| N2 | 18 | 0
| N4 | 18 | 0
| N5 | 30 | 30
| W2 | 18 | 0
| R3 | 18 | 0
| R4 | 22 | 0
| R5 | 4 | 4
| R6 | 4 | 4
| W3 | 30 | 30

View File

@@ -0,0 +1,42 @@
@DB
Feature: Creation of search terms
Tests that search_name table is filled correctly
Scenario: POIs without a name have no search entry
Given the scene roads-with-pois
And the place nodes
| osm_id | class | type | geometry
| 1 | place | house | :p-N1
And the place ways
| osm_id | class | type | geometry
| 1 | highway | residential | :w-north
When importing
Then table search_name has no entry for N1
Scenario: Named POIs inherit address from parent
Given the scene roads-with-pois
And the place nodes
| osm_id | class | type | name | geometry
| 1 | place | house | foo | :p-N1
And the place ways
| osm_id | class | type | name | geometry
| 1 | highway | residential | the road | :w-north
When importing
Then search_name table contains
| place_id | name_vector | nameaddress_vector
| N1 | foo | the road
Scenario: Roads take over the postcode from attached houses
Given the scene roads-with-pois
And the place nodes
| osm_id | class | type | housenumber | postcode | street | geometry
| 1 | place | house | 1 | 12345 | North St |:p-S1
And the place ways
| osm_id | class | type | name | geometry
| 1 | highway | residential | North St | :w-north
When importing
Then search_name table contains
| place_id | nameaddress_vector
| W1 | 12345

View File

@@ -0,0 +1,17 @@
@DB
Feature: Import of simple objects
Testing simple stuff
Scenario: Import place node
Given the place nodes:
| osm_id | class | type | name | geometry
| 1 | place | village | 'name' : 'Foo' | 10.0 -10.0
When importing
Then table placex contains
| object | class | type | name | centroid
| N1 | place | village | 'name' : 'Foo' | 10.0,-10.0 +- 1m
When sending query "Foo"
Then results contain
| ID | osm_type | osm_id
| 0 | N | 1

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

@@ -0,0 +1,92 @@
@DB
Feature: Updates of linked places
Tests that linked places are correctly added and deleted.
Scenario: Add linked place when linking relation is renamed
Given the place nodes
| osm_id | class | type | name | geometry
| 1 | place | city | foo | 0 0
And the place areas
| osm_type | osm_id | class | type | name | admin_level | geometry
| R | 1 | boundary | administrative | foo | 8 | poly-area:0.1
When importing
And sending query "foo" with dups
Then results contain
| osm_type
| R
When updating place areas
| osm_type | osm_id | class | type | name | admin_level | geometry
| R | 1 | boundary | administrative | foobar | 8 | poly-area:0.1
Then table placex contains
| object | linked_place_id
| N1 | None
When sending query "foo" with dups
Then results contain
| osm_type
| N
Scenario: Add linked place when linking relation is removed
Given the place nodes
| osm_id | class | type | name | geometry
| 1 | place | city | foo | 0 0
And the place areas
| osm_type | osm_id | class | type | name | admin_level | geometry
| R | 1 | boundary | administrative | foo | 8 | poly-area:0.1
When importing
And sending query "foo" with dups
Then results contain
| osm_type
| R
When marking for delete R1
Then table placex contains
| object | linked_place_id
| N1 | None
And sending query "foo" with dups
Then results contain
| osm_type
| N
Scenario: Remove linked place when linking relation is added
Given the place nodes
| osm_id | class | type | name | geometry
| 1 | place | city | foo | 0 0
When importing
And sending query "foo" with dups
Then results contain
| osm_type
| N
When updating place areas
| osm_type | osm_id | class | type | name | admin_level | geometry
| R | 1 | boundary | administrative | foo | 8 | poly-area:0.1
Then table placex contains
| object | linked_place_id
| N1 | R1
When sending query "foo" with dups
Then results contain
| osm_type
| R
Scenario: Remove linked place when linking relation is renamed
Given the place nodes
| osm_id | class | type | name | geometry
| 1 | place | city | foo | 0 0
And the place areas
| osm_type | osm_id | class | type | name | admin_level | geometry
| R | 1 | boundary | administrative | foobar | 8 | poly-area:0.1
When importing
And sending query "foo" with dups
Then results contain
| osm_type
| N
When updating place areas
| osm_type | osm_id | class | type | name | admin_level | geometry
| R | 1 | boundary | administrative | foo | 8 | poly-area:0.1
Then table placex contains
| object | linked_place_id
| N1 | R1
When sending query "foo" with dups
Then results contain
| osm_type
| R

View File

@@ -0,0 +1,39 @@
@DB
Feature: Update of names in place objects
Test all naming related issues in updates
Scenario: Updating postcode in postcode boundaries without ref
Given the place areas
| osm_type | osm_id | class | type | postcode | geometry
| R | 1 | boundary | postal_code | 12345 | (0 0, 1 0, 1 1, 0 1, 0 0)
When importing
And sending query "12345"
Then results contain
| ID | osm_type | osm_id
| 0 | R | 1
When updating place areas
| osm_type | osm_id | class | type | postcode | geometry
| R | 1 | boundary | postal_code | 54321 | (0 0, 1 0, 1 1, 0 1, 0 0)
And sending query "12345"
Then exactly 0 results are returned
When sending query "54321"
Then results contain
| ID | osm_type | osm_id
| 0 | R | 1
Scenario: Delete postcode from postcode boundaries without ref
Given the place areas
| osm_type | osm_id | class | type | postcode | geometry
| R | 1 | boundary | postal_code | 12345 | (0 0, 1 0, 1 1, 0 1, 0 0)
When importing
And sending query "12345"
Then results contain
| ID | osm_type | osm_id
| 0 | R | 1
When updating place areas
| osm_type | osm_id | class | type | geometry
| R | 1 | boundary | postal_code | (0 0, 1 0, 1 1, 0 1, 0 0)
Then table placex has no entry for R1

View File

@@ -0,0 +1,117 @@
@DB
Feature: Update of search terms
Tests that search_name table is filled correctly
Scenario: POI-inherited postcode remains when way type is changed
Given the scene roads-with-pois
And the place nodes
| osm_id | class | type | housenumber | postcode | street | geometry
| 1 | place | house | 1 | 12345 | North St |:p-S1
And the place ways
| osm_id | class | type | name | geometry
| 1 | highway | residential | North St | :w-north
When importing
Then search_name table contains
| place_id | nameaddress_vector
| W1 | 12345
When updating place ways
| osm_id | class | type | name | geometry
| 1 | highway | unclassified | North St | :w-north
Then search_name table contains
| place_id | nameaddress_vector
| W1 | 12345
Scenario: POI-inherited postcode remains when way name is changed
Given the scene roads-with-pois
And the place nodes
| osm_id | class | type | housenumber | postcode | street | geometry
| 1 | place | house | 1 | 12345 | North St |:p-S1
And the place ways
| osm_id | class | type | name | geometry
| 1 | highway | residential | North St | :w-north
When importing
Then search_name table contains
| place_id | nameaddress_vector
| W1 | 12345
When updating place ways
| osm_id | class | type | name | geometry
| 1 | highway | unclassified | South St | :w-north
Then search_name table contains
| place_id | nameaddress_vector
| W1 | 12345
Scenario: POI-inherited postcode remains when way geometry is changed
Given the scene roads-with-pois
And the place nodes
| osm_id | class | type | housenumber | postcode | street | geometry
| 1 | place | house | 1 | 12345 | North St |:p-S1
And the place ways
| osm_id | class | type | name | geometry
| 1 | highway | residential | North St | :w-north
When importing
Then search_name table contains
| place_id | nameaddress_vector
| W1 | 12345
When updating place ways
| osm_id | class | type | name | geometry
| 1 | highway | unclassified | South St | :w-south
Then search_name table contains
| place_id | nameaddress_vector
| W1 | 12345
Scenario: POI-inherited postcode is added when POI postcode changes
Given the scene roads-with-pois
And the place nodes
| osm_id | class | type | housenumber | postcode | street | geometry
| 1 | place | house | 1 | 12345 | North St |:p-S1
And the place ways
| osm_id | class | type | name | geometry
| 1 | highway | residential | North St | :w-north
When importing
Then search_name table contains
| place_id | nameaddress_vector
| W1 | 12345
When updating place nodes
| osm_id | class | type | housenumber | postcode | street | geometry
| 1 | place | house | 1 | 54321 | North St |:p-S1
Then search_name table contains
| place_id | nameaddress_vector
| W1 | 54321
Scenario: POI-inherited postcode remains when POI geometry changes
Given the scene roads-with-pois
And the place nodes
| osm_id | class | type | housenumber | postcode | street | geometry
| 1 | place | house | 1 | 12345 | North St |:p-S1
And the place ways
| osm_id | class | type | name | geometry
| 1 | highway | residential | North St | :w-north
When importing
Then search_name table contains
| place_id | nameaddress_vector
| W1 | 12345
When updating place nodes
| osm_id | class | type | housenumber | postcode | street | geometry
| 1 | place | house | 1 | 12345 | North St |:p-S2
Then search_name table contains
| place_id | nameaddress_vector
| W1 | 12345
Scenario: POI-inherited postcode remains when another POI is deleted
Given the scene roads-with-pois
And the place nodes
| osm_id | class | type | housenumber | postcode | street | geometry
| 1 | place | house | 1 | 12345 | North St |:p-S1
| 2 | place | house | 2 | | North St |:p-S2
And the place ways
| osm_id | class | type | name | geometry
| 1 | highway | residential | North St | :w-north
When importing
Then search_name table contains
| place_id | nameaddress_vector
| W1 | 12345
When marking for delete N2
Then search_name table contains
| place_id | nameaddress_vector
| W1 | 12345

View File

@@ -0,0 +1,73 @@
@DB
Feature: Update of simple objects
Testing simple stuff
Scenario: Do delete small boundary features
Given the place areas
| osm_type | osm_id | class | type | admin_level | geometry
| R | 1 | boundary | administrative | 3 | (0 0, 1 0, 1 1, 0 1, 0 0)
When importing
Then table placex contains
| object | rank_search
| R1 | 6
When marking for delete R1
Then table placex has no entry for R1
Scenario: Do not delete large boundary features
Given the place areas
| osm_type | osm_id | class | type | admin_level | geometry
| R | 1 | boundary | administrative | 3 | (0 0, 2 0, 2 2.1, 0 2, 0 0)
When importing
Then table placex contains
| object | rank_search
| R1 | 6
When marking for delete R1
Then table placex contains
| object | rank_search
| R1 | 6
Scenario: Do delete large features of low rank
Given the named place areas
| osm_type | osm_id | class | type | geometry
| W | 1 | place | house | (0 0, 2 0, 2 2.1, 0 2, 0 0)
| R | 1 | boundary | national_park | (0 0, 2 0, 2 2.1, 0 2, 0 0)
When importing
Then table placex contains
| object | rank_address
| R1 | 0
| W1 | 30
When marking for delete R1,W1
Then table placex has no entry for W1
Then table placex has no entry for R1
Scenario: type mutation
Given the place nodes
| osm_id | class | type | geometry
| 3 | shop | toys | 1 -1
When importing
Then table placex contains
| object | class | type
| N3 | shop | toys
When updating place nodes
| osm_id | class | type | geometry
| 3 | shop | grocery | 1 -1
Then table placex contains
| object | class | type
| N3 | shop | grocery
Scenario: remove postcode place when house number is added
Given the place nodes
| osm_id | class | type | postcode | geometry
| 3 | place | postcode | 12345 | 1 -1
When importing
Then table placex contains
| object | class | type
| N3 | place | postcode
When updating place nodes
| osm_id | class | type | postcode | housenumber | geometry
| 3 | place | house | 12345 | 13 | 1 -1
Then table placex contains
| object | class | type
| N3 | place | house

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,13 @@
@DB
Feature: Import of relations by osm2pgsql
Testing specific relation problems related to members.
Scenario: Don't import empty waterways
Given the osm nodes:
| id | tags
| 1 | 'amenity' : 'prison', 'name' : 'foo'
And the osm relations:
| id | tags | members
| 1 | 'type' : 'waterway', 'waterway' : 'river', 'name' : 'XZ' | N1
When loading osm data
Then table place has no entry for R1

View File

@@ -0,0 +1,68 @@
@DB
Feature: Import of simple objects by osm2pgsql
Testing basic tagging in osm2pgsql imports.
Scenario: Import simple objects
Given the osm nodes:
| id | tags
| 1 | 'amenity' : 'prison', 'name' : 'foo'
Given the osm nodes:
| id | geometry
| 100 | 0 0
| 101 | 0 0.1
| 102 | 0.1 0.2
| 200 | 0 0
| 201 | 0 1
| 202 | 1 1
| 203 | 1 0
And the osm ways:
| id | tags | nodes
| 1 | 'shop' : 'toys', 'name' : 'tata' | 100 101 102
| 2 | 'ref' : '45' | 200 201 202 203 200
And the osm relations:
| id | tags | members
| 1 | 'type' : 'multipolygon', 'tourism' : 'hotel', 'name' : 'XZ' | N1,W2
When loading osm data
Then table place contains
| object | class | type | name
| N1 | amenity | prison | 'name' : 'foo'
| W1 | shop | toys | 'name' : 'tata'
| R1 | tourism | hotel | 'name' : 'XZ'
Scenario: Import object with two main tags
Given the osm nodes:
| id | tags
| 1 | 'tourism' : 'hotel', 'amenity' : 'restaurant', 'name' : 'foo'
When loading osm data
Then table place contains
| object | class | type | name
| N1:tourism | tourism | hotel | 'name' : 'foo'
| N1:amenity | amenity | restaurant | 'name' : 'foo'
Scenario: Import stand-alone house number with postcode
Given the osm nodes:
| id | tags
| 1 | 'addr:housenumber' : '4', 'addr:postcode' : '3345'
When loading osm data
Then table place contains
| object | class | type
| N1 | place | house
Scenario: Landuses are only imported when named
Given the osm nodes:
| id | geometry
| 100 | 0 0
| 101 | 0 0.1
| 102 | 0.1 0.1
| 200 | 0 0
| 202 | 1 1
| 203 | 1 0
And the osm ways:
| id | tags | nodes
| 1 | 'landuse' : 'residential', 'name' : 'rainbow' | 100 101 102 100
| 2 | 'landuse' : 'residential' | 200 202 203 200
When loading osm data
Then table place contains
| object | class | type
| W1 | landuse | residential
And table place has no entry for W2

View File

@@ -0,0 +1,550 @@
@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
| name:source
Scenario: Special character in name tag
Given the osm nodes:
| id | tags
| 1 | 'highway' : 'yes', 'name: de' : 'Foo', 'name' : 'real1'
| 2 | 'highway' : 'yes', 'name:&#xa;de' : 'Foo', 'name' : 'real2'
| 3 | 'highway' : 'yes', 'name:&#x9;de' : 'Foo', 'name:\\' : 'real3'
When loading osm data
Then table place contains
| object | name
| N1 | 'name: de' : 'Foo', 'name' : 'real1'
| N2 | 'name: de' : 'Foo', 'name' : 'real2'
| N3 | 'name: de' : 'Foo', 'name:\\\\' : 'real3'
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: Footways are not included if they are sidewalks
Given the osm nodes:
| id | tags
| 2 | 'highway' : 'footway', 'name' : 'To Hell', 'footway' : 'sidewalk'
| 23 | 'highway' : 'footway', 'name' : 'x'
When loading osm data
Then table place has no entry for N2
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 | Feebourgh county,Alabama
| 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
| wikidata
| name:prefix
| name:botanical
| name:etymology:wikidata
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

@@ -0,0 +1,152 @@
@DB
Feature: Update of relations by osm2pgsql
Testing relation update by osm2pgsql.
Scenario: Remove all members of a relation
Given the osm nodes:
| id | tags
| 1 | 'amenity' : 'prison', 'name' : 'foo'
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', 'tourism' : 'hotel', 'name' : 'XZ' | N1
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

View File

@@ -0,0 +1,22 @@
@DB
Feature: Update of simple objects by osm2pgsql
Testing basic update functions of osm2pgsql.
Scenario: Import object with two main tags
Given the osm nodes:
| id | tags
| 1 | 'tourism' : 'hotel', 'amenity' : 'restaurant', 'name' : 'foo'
When loading osm data
Then table place contains
| object | class | type | name
| N1:tourism | tourism | hotel | 'name' : 'foo'
| N1:amenity | amenity | restaurant | 'name' : 'foo'
Given the osm nodes:
| action | id | tags
| M | 1 | 'tourism' : 'hotel', 'name' : 'foo'
When updating osm data
Then table place has no entry for N1:amenity
And table place contains
| object | class | type | name
| N1:tourism | tourism | hotel | 'name' : 'foo'

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

31
tests/scenes/bin/make_scenes.sh Executable file
View File

@@ -0,0 +1,31 @@
#/bin/bash -e
#
# Regenerates wkts for scenarios.
#
datadir="$( cd "$( dirname "$0" )" && cd ../data && pwd )"
if [ ! -d "$datadir" ]; then
echo "Cannot find data dir.";
exit -1;
fi
echo "Using datadir $datadir"
pushd $datadir
# remove old wkts
rm $datadir/*.wkt
# create wkts from SQL scripts
for fl in *.sql; do
echo "Processing $fl.."
cat $fl | psql -d nominatim -t -o ${fl/.sql/.wkt}
done
# create wkts from .osm files
for fl in *.osm; do
echo "Processing $fl.."
../bin/osm2wkt $fl
done
popd

101
tests/scenes/bin/osm2wkt.cc Normal file
View File

@@ -0,0 +1,101 @@
// The code in this file is released into the Public Domain.
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <osmium/area/assembler.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/sparse_mem_array.hpp>
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;
std::unordered_map<std::string, std::ofstream> m_files;
public:
void node(const osmium::Node& node) {
print_geometry(node.tags(), m_factory.create_point(node));
}
void way(const osmium::Way& way) {
if (!way.is_closed() || !way.tags().get_value_by_key("area"))
print_geometry(way.tags(), m_factory.create_linestring(way));
}
void area(const osmium::Area& area) {
if (!area.from_way() || area.tags().get_value_by_key("area"))
print_geometry(area.tags(), m_factory.create_multipolygon(area));
}
void close() {
for (auto& fd : m_files)
fd.second.close();
}
private:
void print_geometry(const osmium::TagList& tags, const std::string& wkt) {
const char* scenario = tags.get_value_by_key("test:section");
const char* id = tags.get_value_by_key("test:id");
if (scenario && id) {
auto& fd = m_files[std::string(scenario)];
if (!fd.is_open())
fd.open(std::string(scenario) + ".wkt");
fd << id << " | " << wkt << "\n";
}
}
}; // class ExportToWKTHandler
int main(int argc, char* argv[]) {
if (argc != 2) {
std::cerr << "Usage: " << argv[0] << " OSMFILE\n";
exit(1);
}
std::string input_filename {argv[1]};
osmium::area::ProblemReporterException problem_reporter;
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::osm_entity_bits::relation);
collector.read_relations(reader1);
std::cerr << "Pass 1 done\n";
index_type index_pos;
index_type index_neg;
location_handler_type location_handler(index_pos, index_neg);
std::cerr << "Pass 2...\n";
ExportToWKTHandler export_handler;
osmium::io::Reader reader2(input_filename);
osmium::apply(reader2, location_handler, export_handler, collector.handler([&export_handler](osmium::memory::Buffer&& buffer) {
osmium::apply(buffer, export_handler);
}));
reader2.close();
export_handler.close();
std::cerr << "Pass 2 done\n";
google::protobuf::ShutdownProtobufLibrary();
}

View File

@@ -0,0 +1,7 @@
n-edge-NS | POINT(1.0040019 2.000324)
n-inner | POINT(1.0039385 2.0003548)
n-outer | POINT(1.0039478 2.0004676)
n-edge-WE | POINT(1.0039599 2.0002345)
w-WE | LINESTRING(1.0031759 2.0002316,1.0040361 2.0002211,1.0042735 2.0002264)
w-NS | LINESTRING(1.0040414 2.0001051,1.0040361 2.0002211,1.0040364 2.0006377)
w-building | MULTIPOLYGON(((1.0040019 2.000324,1.0040016 2.0002344,1.0039599 2.0002345,1.0039037 2.0002347,1.0039043 2.0004389,1.0040023 2.0004386,1.0040019 2.000324)))

View File

@@ -0,0 +1 @@
select country_code, st_astext(st_pointonsurface(st_collect(geometry))) from country_osm_grid group by country_code order by country_code

View File

@@ -0,0 +1,250 @@
ad | POINT(1.58972361752509 42.54241545)
ae | POINT(54.6158905029297 24.8243131637573)
af | POINT(65.9026412963867 34.8470859527588)
ag | POINT(-61.7243069800293 17.069)
ai | POINT(-63.1057155298182 18.2546197)
al | POINT(19.8494176864624 40.2123275624912)
am | POINT(44.6422958374023 40.3782157897949)
ao | POINT(16.2192406654358 -12.7701482772827)
aq | POINT(44.999999975 -75.6569557189941)
ar | POINT(-61.1075973510742 -34.3761558532715)
as | POINT(-170.684700024275 -14.2930755)
at | POINT(14.2574706077576 47.3654232025146)
au | POINT(138.231559753418 -23.7206888198853)
aw | POINT(-69.98255055 12.555)
ax | POINT(19.9183956313477 59.81682435)
az | POINT(48.385555267334 40.6163997650146)
ba | POINT(17.1851491928101 44.2558269500732)
bb | POINT(-59.53342165 13.19)
bd | POINT(89.759895324707 24.3420524597168)
be | POINT(4.90078139305115 50.3468225048828)
bf | POINT(-0.567435041069984 11.9047117233276)
bg | POINT(24.8061628341675 43.0985908508301)
bh | POINT(50.5203291219829 25.94685735)
bi | POINT(29.5456137866089 -2.99057915)
bj | POINT(2.70062518119812 10.0279288291931)
bl | POINT(-62.7934947763772 17.907)
bm | POINT(-64.7740692745195 32.30199165)
bn | POINT(114.521968608887 4.2863885)
bo | POINT(-62.0247344970703 -17.7772369384766)
bq | POINT(-63.1432235610045 17.566)
br | POINT(-45.7706508636475 -9.5868501663208)
bs | POINT(-77.6091675884277 23.8745)
bt | POINT(90.0135078430176 27.281379699707)
bv | POINT(3.35744155625 -54.4215)
bw | POINT(23.5150556564331 -23.4839134216309)
by | POINT(26.7725925445557 53.1588516235352)
bz | POINT(-88.6348991394043 16.3395160487277)
ca | POINT(-107.74817276001 67.1261215209961)
cc | POINT(96.8442066294247 -12.0173443)
cd | POINT(24.0954418182373 -1.67713665962219)
cf | POINT(22.5870132446289 5.98438787460327)
cg | POINT(15.7887516021729 0.403886616230011)
ch | POINT(7.65705513954163 46.5744686126709)
ci | POINT(-6.31190967559814 6.6278383731842)
ck | POINT(-159.778351359569 -21.23349585)
cl | POINT(-70.4179039001465 -53.7718944549561)
cm | POINT(13.260226726532 5.94519567489624)
cn | POINT(96.4428558349609 38.0426063537598)
co | POINT(-72.5295104980469 2.45174860954285)
cr | POINT(-83.8331413269043 9.935142993927)
cu | POINT(-80.8167381286621 21.8885278701782)
cv | POINT(-24.508106575 14.929)
cw | POINT(-68.9640918594077 12.1845)
cx | POINT(105.624119513558 -10.48417)
cy | POINT(32.959223486499 35.37010195)
cz | POINT(16.3209805488586 49.5069274902344)
de | POINT(9.30716800689697 50.2128944396973)
dj | POINT(42.969040422876 11.41542855)
dk | POINT(9.18490123748779 55.5634002685547)
dm | POINT(-61.0035801928854 15.6547055)
do | POINT(-69.6285591125488 18.5884169089722)
dz | POINT(4.24749487638474 25.797215461731)
ec | POINT(-77.4583168029785 -0.982844322919846)
ee | POINT(23.9428863525391 58.439525604248)
eg | POINT(28.952935218811 28.1771860122681)
eh | POINT(-13.6903142929077 25.0124177932739)
er | POINT(39.0122375488281 14.960337638855)
es | POINT(-2.59110307693481 38.7935485839844)
et | POINT(38.6169757843018 7.71399855613708)
fi | POINT(26.8979873657227 63.5619449615479)
fj | POINT(177.918533325195 -17.7423753738403)
fk | POINT(-60.0855102539062 -51.6555919647217)
fm | POINT(151.9535889125 8.5045)
fo | POINT(-6.60483694084778 62.10000995)
fr | POINT(0.284105718135834 47.5104522705078)
ga | POINT(10.8107047080994 -0.0742915570735931)
gb | POINT(-0.928231082856655 52.0161876678467)
gd | POINT(-61.6452430375 12.191)
ge | POINT(44.1666488647461 42.0038585662842)
gf | POINT(-53.4652481079102 3.56188893318176)
gg | POINT(-2.50580395030125 49.5854381)
gh | POINT(-0.463488027453423 7.16051578521729)
gi | POINT(-5.32053155848457 36.1106663)
gl | POINT(-33.8551120758057 74.6635551452637)
gm | POINT(-16.4096023535368 13.25)
gn | POINT(-13.839409828186 10.9629158973694)
gp | POINT(-61.6871265247053 16.23049055)
gq | POINT(10.2397356033325 1.43119311332703)
gr | POINT(23.1785039901733 39.0620670318604)
gs | POINT(-36.4943086948773 -54.4306784)
gt | POINT(-90.7436828613281 15.2042865753174)
gu | POINT(144.733626445767 13.444138)
gw | POINT(-14.8352527618408 11.9248690605164)
gy | POINT(-58.4516773223877 5.73698806762695)
hk | POINT(114.18577775 22.3492361)
hm | POINT(73.6823082266602 -53.22105985)
hn | POINT(-86.9541435241699 15.2382001876831)
hr | POINT(17.499662399292 45.5268955230713)
ht | POINT(-73.5192565917969 18.3249206691162)
hu | POINT(20.3536291122437 47.5172100067139)
id | POINT(123.345050811768 -0.837919592857361)
ie | POINT(-9.00520038604736 52.8772506713867)
il | POINT(35.4631499949707 32.86165655)
im | POINT(-4.86740773691101 54.023)
in | POINT(88.6762087020508 27.86155515)
io | POINT(71.4274391359073 -6.14349685)
iq | POINT(42.5810985565186 34.2610359191895)
ir | POINT(51.268892288208 34.1931705474854)
is | POINT(-17.5178508758545 64.7168769836426)
it | POINT(10.4263944625854 44.8790493011475)
je | POINT(-2.19261599848299 49.1245833)
jm | POINT(-76.8402003547852 18.3935)
jo | POINT(36.5555210113525 30.7574186325073)
jp | POINT(138.725311279297 35.9209995269775)
ke | POINT(36.9060287475586 1.08512867614627)
kg | POINT(76.1557197570801 41.6649742126465)
kh | POINT(104.319019317627 12.9555516242981)
ki | POINT(173.633537933333 0.139)
km | POINT(44.3147485207764 -12.241)
kn | POINT(-62.6937987175 17.2555)
kp | POINT(126.655757904053 39.6457576751709)
kr | POINT(127.277404785156 36.4138870239258)
kw | POINT(47.3068407840576 29.6918055)
ky | POINT(-81.0745526670982 19.2994923579778)
kz | POINT(72.008113861084 49.8885555267334)
la | POINT(102.443916320801 19.8160953521729)
lb | POINT(35.4846443715483 33.4176673878926)
lc | POINT(-60.978944125 13.891)
li | POINT(9.54693948514429 47.15934115)
lk | POINT(80.3852043151855 8.41649961471558)
lr | POINT(-11.169605255127 4.04122126102448)
ls | POINT(28.6698419546997 -29.9453849)
lt | POINT(24.5173501968384 55.4929389953613)
lu | POINT(6.08649672997471 49.81533445)
lv | POINT(23.5103368759155 56.6714401245117)
ly | POINT(15.3684158325195 28.1217727661133)
ma | POINT(-4.0306156873703 33.2169628143311)
mc | POINT(7.47743150426578 43.62917385)
md | POINT(29.6172503477783 46.6651745)
me | POINT(19.7229134314941 43.02441345)
mf | POINT(-63.0666651534257 18.0810209)
mg | POINT(45.8637886047363 -20.5024528503418)
mh | POINT(171.949820566667 5.983)
mk | POINT(21.421085357666 41.0898007597656)
ml | POINT(-1.93310506641865 16.4699301719666)
mm | POINT(95.5462455749512 21.0962018966675)
mn | POINT(99.8113822937012 48.1861572265625)
mo | POINT(113.564416766761 22.16209625)
mp | POINT(145.213452483189 14.1490205)
mq | POINT(-60.8112834227783 14.43706925)
mr | POINT(-9.42324566841125 22.5925149917603)
ms | POINT(-62.1945521583333 16.745)
mt | POINT(14.3836306158583 35.9446731)
mu | POINT(57.551211475 -20.41)
mv | POINT(73.3929214477539 4.19375014305115)
mw | POINT(33.9572296142578 -12.2821822166443)
mx | POINT(-105.892219543457 25.8682699203491)
my | POINT(112.711540222168 2.10098683834076)
mz | POINT(37.5868968963623 -15.5801844596863)
na | POINT(16.6856970787048 -21.4657220840454)
nc | POINT(164.953224182129 -20.3888988494873)
ne | POINT(10.060417175293 19.0827360153198)
nf | POINT(167.95718166875 -29.0645)
ng | POINT(10.1778125762939 10.1780409812927)
ni | POINT(-85.8797492980957 13.2171587944031)
nl | POINT(-68.5706209441406 12.041)
no | POINT(23.1155624389648 70.0993499755859)
np | POINT(83.3625984191895 28.1310758590698)
nr | POINT(166.934792270833 -0.5275)
nu | POINT(-169.848737911905 -19.05305275)
nz | POINT(167.972099304199 -45.1305675506592)
om | POINT(56.8605518341064 20.4741315841675)
pa | POINT(-79.4016036987305 8.80656003952026)
pe | POINT(-78.6654052734375 -7.54711985588074)
pf | POINT(-145.057191213086 -16.7086236)
pg | POINT(146.646003723145 -7.37427568435669)
ph | POINT(121.483592987061 15.0996527671814)
pk | POINT(72.1134796142578 31.1462965011597)
pl | POINT(17.8813629150391 52.771821975708)
pm | POINT(-56.1951589074841 46.7832469)
pn | POINT(-130.106425528029 -25.0695595)
pr | POINT(-65.8875553967285 18.3716905)
ps | POINT(35.3980153741943 32.24773475)
pt | POINT(-8.45743942260742 40.1115436553955)
pw | POINT(134.496454875 7.3245)
py | POINT(-59.5178718566895 -22.4128150939941)
qa | POINT(51.4990362304443 24.9981677)
re | POINT(55.7734550547607 -21.3638828)
ro | POINT(26.3763284683228 45.3612003326416)
rs | POINT(20.4037199020386 44.5641384124756)
ru | POINT(116.440608978271 59.0678024291992)
rw | POINT(29.5788261333252 -1.6240443)
sa | POINT(47.7316932678223 22.4379062652588)
sb | POINT(164.638946533203 -10.2360653877258)
sc | POINT(46.3656697 -9.454)
sd | POINT(28.1472072601318 14.5642309188843)
se | POINT(15.6866798400879 60.3556804656982)
sg | POINT(103.84187219299 1.304)
sh | POINT(-12.2815573611979 -37.11546755)
si | POINT(14.0473856628607 46.390855)
sj | POINT(15.2755260467529 79.2336540222168)
sk | POINT(20.416033744812 48.869701385498)
sl | POINT(-11.4777312278748 8.78156280517578)
sm | POINT(12.4606268797657 43.9427969)
sn | POINT(-15.3711128234863 14.9947791099548)
so | POINT(46.9338359832764 9.34094429016113)
sr | POINT(-56.4855213165283 4.5773549079895)
ss | POINT(28.1357345581055 8.50933408737183)
st | POINT(6.61025854583333 0.2215)
sv | POINT(-89.3666543301004 13.4307287)
sx | POINT(-63.1539330807882 17.9345)
sy | POINT(38.1551322937012 35.3422107696533)
sz | POINT(31.782634398523 -26.14244365)
tc | POINT(-71.325541342334 21.35)
td | POINT(17.4209251403809 13.4622311592102)
tf | POINT(137.5 -67.5)
tg | POINT(1.0698350071907 7.87677597999573)
th | POINT(102.008777618408 16.4231028556824)
tj | POINT(71.9134941101074 39.0152739312988)
tk | POINT(-171.826039878679 -9.209903)
tl | POINT(126.225208282471 -8.72636747360229)
tm | POINT(57.7160358428955 39.9253444671631)
tn | POINT(9.04958724975586 34.8419933319092)
to | POINT(-176.993202209473 -23.1110429763794)
tr | POINT(32.8200283050537 39.8635063171387)
tt | POINT(-60.70793924375 11.1385)
tv | POINT(178.774993896484 -9.41685771942139)
tw | POINT(120.300746917725 23.1700229644775)
tz | POINT(33.5389289855957 -5.01840615272522)
ua | POINT(33.4433536529541 49.3061904907227)
ug | POINT(32.9652328491211 2.08584922552109)
um | POINT(-169.509930872296 16.74605815)
us | POINT(-116.395355224609 40.7137908935547)
uy | POINT(-56.4650554656982 -33.6265888214111)
uz | POINT(61.3552989959717 42.9610729217529)
va | POINT(12.3319785703086 42.0493197)
vc | POINT(-61.0990541737305 13.316)
ve | POINT(-64.8832321166992 7.69849991798401)
vg | POINT(-64.6247911940199 18.419)
vi | POINT(-64.8895090795187 18.3226325)
vn | POINT(104.201791331787 10.27644235)
vu | POINT(167.319198608398 -15.8868751525879)
wf | POINT(-176.207816222208 -13.28535775)
ws | POINT(-172.109667323427 -13.850938)
ye | POINT(45.945629119873 16.1633830070496)
yt | POINT(44.9377459760742 -12.6088246)
za | POINT(23.1948881149292 -30.4327602386475)
zm | POINT(26.3861808776855 -14.3996663093567)
zw | POINT(30.1241998672485 -19.8690795898438)

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

@@ -0,0 +1,8 @@
n-N-unglued | POINT(1.004922 2.0005155)
n-S-unglued | POINT(1.0046259 2.0002949)
n-NE | POINT(1.0050661 2.0006118)
n-SE | POINT(1.0051339 2.0003349)
n-NW | POINT(1.0047583 2.0004087)
n-SW | POINT(1.0047275 2.0003564)
w-north | LINESTRING(1.0044996 2.0004302,1.0046259 2.0003841,1.0047583 2.0004087,1.004922 2.0005155,1.0050661 2.0006118,1.0053155 2.0006241)
w-south | LINESTRING(1.0045243 2.0002241,1.0046259 2.0002949,1.0047275 2.0003564,1.004826 2.0002918,1.0049368 2.0002641,1.0051339 2.0003349,1.0053278 2.0003687)

View File

@@ -0,0 +1,11 @@
0.0001 | MULTIPOLYGON(((0.001 0,0 0,0 0.1,0.001 0.1,0.001 0)))
0.0005 | MULTIPOLYGON(((0.005 0,0 0,0 0.1,0.005 0.1,0.005 0)))
0.001 | MULTIPOLYGON(((0.01 0,0 0,0 0.1,0.01 0.1,0.01 0)))
0.005 | MULTIPOLYGON(((0.05 0,0 0,0 0.1,0.05 0.1,0.05 0)))
0.01 | MULTIPOLYGON(((0.1 0,0 0,0 0.1,0.1 0.1,0.1 0)))
0.05 | MULTIPOLYGON(((0.5 0,0 0,0 0.1,0.5 0.1,0.5 0)))
0.1 | MULTIPOLYGON(((0.1 0,0 0,0 1,0.1 1,0.1 0)))
0.5 | MULTIPOLYGON(((0.5 0,0 0,0 1,0.5 1,0.5 0)))
1.0 | MULTIPOLYGON(((1 0,0 0,0 1,1 1,1 0)))
2.0 | MULTIPOLYGON(((2 0,0 0,0 1,2 1,2 0)))
5.0 | MULTIPOLYGON(((5 0,0 0,0 1,5 1,5 0)))

View File

@@ -0,0 +1,221 @@
<?xml version='1.0' encoding='UTF-8'?>
<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

@@ -0,0 +1,6 @@
n-main-east | POINT(1.0024481 2.0003542)
n-main-west | POINT(1.001552 2.0002662)
n-alley | POINT(1.0019235 2.0005463)
n-corner | POINT(1.0019235 2.0003542)
w-alley | LINESTRING(1.0019594 2.0003086,1.0019594 2.0005756)
w-main | LINESTRING(1.0013435 2.0003118,1.0016759 2.0003053,1.0019594 2.0003086,1.0021255 2.0003151,1.0023699 2.0003118,1.0026078 2.0002988)

View File

@@ -0,0 +1,6 @@
p-N2 | POINT(1.0003904 2.0003399)
p-S1 | POINT(1.0008104 2.0002927)
p-N1 | POINT(1.0005321 2.0005288)
p-S2 | POINT(1.0006398 2.0001064)
w-north | LINESTRING(1.0001174 2.0004055,1.0004298 2.0003976,1.0006608 2.0004579,1.0010624 2.0005419)
w-south | LINESTRING(1.0001384 2.0001903,1.0007212 2.0001982,1.0010677 2.0002192)

353
tests/scenes/data/roads.osm Normal file
View File

@@ -0,0 +1,353 @@
<?xml version='1.0' encoding='UTF-8'?>
<osm version='0.6' upload='false' generator='JOSM'>
<node id='-197' action='modify' visible='true' lat='2.0006515863' lon='1.0057464449'>
<tag k='name' v='split-road' />
</node>
<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='-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='-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='-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='-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='-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='-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='-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='-117' action='modify' visible='true' lat='2.00072864414' lon='1.00046699629'>
<tag k='name' v='roads-with-pois' />
</node>
<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='-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='-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='-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='-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='-91' action='modify' visible='true' lat='2.00039759893' lon='1.00042975784'>
<tag k='test:section' v='roads-with-pois' />
</node>
<node id='-89' action='modify' visible='true' lat='2.000457941' lon='1.00066077263'>
<tag k='test:section' v='roads-with-pois' />
</node>
<node id='-87' action='modify' visible='true' lat='2.00054189517' lon='1.00106242333'>
<tag k='test:section' v='roads-with-pois' />
</node>
<node id='-85' action='modify' visible='true' lat='2.00019033703' lon='1.00013836419'>
<tag k='test:section' v='roads-with-pois' />
</node>
<node id='-83' action='modify' visible='true' lat='2.00019820773' lon='1.00072115149'>
<tag k='test:section' v='roads-with-pois' />
</node>
<node id='-81' action='modify' visible='true' lat='2.00021919628' lon='1.00106767367'>
<tag k='test:section' v='roads-with-pois' />
</node>
<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='-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='-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='-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='-71' action='modify' visible='true' lat='2.00072116924' lon='1.00358286582'>
<tag k='name' v='building-on-street-corner' />
</node>
<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='-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='-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='-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='-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='-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='-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='-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='-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='-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='-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='-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='-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='-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='-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='-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' />
<nd ref='100002' />
<nd ref='100003' />
<nd ref='100000' />
<tag k='note' v='test area, do not leave' />
</way>
</osm>

View File

@@ -0,0 +1,6 @@
w-5 | LINESTRING(1.0056855 2.0005616,1.0056087 2.0005669,1.0055106 2.0005245)
w-4a | LINESTRING(1.0062843 2.0005139,1.0061359 2.0004954,1.0060538 2.0005113,1.0059107 2.000506,1.0057358 2.0005007,1.0056855 2.0005616)
w-3 | LINESTRING(1.0061995 2.0003391,1.0062816 2.0002624,1.0063585 2.0002968,1.0063717 2.0004715,1.0062843 2.0005139)
w-2 | LINESTRING(1.0057941 2.0002809,1.0058869 2.0003259,1.0060034 2.0003497,1.0061041 2.0003577,1.0061995 2.0003391)
w-4b | LINESTRING(1.0062843 2.0005139,1.0061306 2.0005324,1.0060511 2.000543,1.0058975 2.000543,1.0057491 2.0005351,1.0056855 2.0005616)
w-1 | LINESTRING(1.0054709 2.0003603,1.0056352 2.0002782,1.0057941 2.0002809)

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)))

275
tests/steps/api_result.py Normal file
View File

@@ -0,0 +1,275 @@
""" Steps for checking the results of queries.
"""
from nose.tools import *
from lettuce import *
from tidylib import tidy_document
from collections import OrderedDict
import json
import logging
import re
from xml.dom.minidom import parseString
logger = logging.getLogger(__name__)
def _parse_xml():
""" Puts the DOM structure into more convenient python
with a similar structure as the json document, so
that the same the semantics can be used. It does not
check if the content is valid (or at least not more than
necessary to transform it into a dict structure).
"""
page = parseString(world.page).documentElement
# header info
world.result_header = OrderedDict(page.attributes.items())
logger.debug('Result header: %r' % (world.result_header))
world.results = []
# results
if page.nodeName == 'searchresults' or page.nodeName == 'lookupresults':
for node in page.childNodes:
if node.nodeName != "#text":
assert_equals(node.nodeName, 'place', msg="Unexpected element '%s'" % node.nodeName)
newresult = OrderedDict(node.attributes.items())
assert_not_in('address', newresult)
assert_not_in('geokml', newresult)
assert_not_in('extratags', newresult)
assert_not_in('namedetails', newresult)
address = OrderedDict()
for sub in node.childNodes:
if sub.nodeName == 'geokml':
newresult['geokml'] = sub.childNodes[0].toxml()
elif sub.nodeName == 'extratags':
newresult['extratags'] = {}
for tag in sub.childNodes:
assert_equals(tag.nodeName, 'tag')
attrs = dict(tag.attributes.items())
assert_in('key', attrs)
assert_in('value', attrs)
newresult['extratags'][attrs['key']] = attrs['value']
elif sub.nodeName == 'namedetails':
newresult['namedetails'] = {}
for tag in sub.childNodes:
assert_equals(tag.nodeName, 'name')
attrs = dict(tag.attributes.items())
assert_in('desc', attrs)
newresult['namedetails'][attrs['desc']] = tag.firstChild.nodeValue.strip()
elif sub.nodeName == '#text':
pass
else:
address[sub.nodeName] = sub.firstChild.nodeValue.strip()
if address:
newresult['address'] = address
world.results.append(newresult)
elif page.nodeName == 'reversegeocode':
haserror = False
address = {}
for node in page.childNodes:
if node.nodeName == 'result':
assert_equals(len(world.results), 0)
assert (not haserror)
world.results.append(OrderedDict(node.attributes.items()))
assert_not_in('display_name', world.results[0])
assert_not_in('address', world.results[0])
world.results[0]['display_name'] = node.firstChild.nodeValue.strip()
elif node.nodeName == 'error':
assert_equals(len(world.results), 0)
haserror = True
elif node.nodeName == 'addressparts':
assert (not haserror)
address = OrderedDict()
for sub in node.childNodes:
address[sub.nodeName] = sub.firstChild.nodeValue.strip()
world.results[0]['address'] = address
elif node.nodeName == 'extratags':
world.results[0]['extratags'] = {}
for tag in node.childNodes:
assert_equals(tag.nodeName, 'tag')
attrs = dict(tag.attributes.items())
assert_in('key', attrs)
assert_in('value', attrs)
world.results[0]['extratags'][attrs['key']] = attrs['value']
elif node.nodeName == 'namedetails':
world.results[0]['namedetails'] = {}
for tag in node.childNodes:
assert_equals(tag.nodeName, 'name')
attrs = dict(tag.attributes.items())
assert_in('desc', attrs)
world.results[0]['namedetails'][attrs['desc']] = tag.firstChild.nodeValue.strip()
elif node.nodeName == "#text":
pass
else:
assert False, "Unknown content '%s' in XML" % node.nodeName
else:
assert False, "Unknown document node name %s in XML" % page.nodeName
logger.debug("The following was parsed out of XML:")
logger.debug(world.results)
@step(u'a HTTP (\d+) is returned')
def api_result_http_error(step, error):
assert_equals(world.returncode, int(error))
@step(u'the result is valid( \w+)?')
def api_result_is_valid(step, fmt):
assert_equals(world.returncode, 200)
if world.response_format == 'html':
document, errors = tidy_document(world.page,
options={'char-encoding' : 'utf8'})
# assert(len(errors) == 0), "Errors found in HTML document:\n%s" % errors
world.results = document
elif world.response_format == 'xml':
_parse_xml()
elif world.response_format == 'json':
world.results = json.JSONDecoder(object_pairs_hook=OrderedDict).decode(world.page)
if world.request_type == 'reverse':
world.results = (world.results,)
else:
assert False, "Unknown page format: %s" % (world.response_format)
if fmt:
assert_equals (fmt.strip(), world.response_format)
def compare(operator, op1, op2):
if operator == 'less than':
return op1 < op2
elif operator == 'more than':
return op1 > op2
elif operator == 'exactly':
return op1 == op2
elif operator == 'at least':
return op1 >= op2
elif operator == 'at most':
return op1 <= op2
else:
raise Exception("unknown operator '%s'" % operator)
@step(u'(less than|more than|exactly|at least|at most) (\d+) results? (?:is|are) returned')
def validate_result_number(step, operator, number):
step.given('the result is valid')
numres = len(world.results)
assert compare(operator, numres, int(number)), \
"Bad number of results: expected %s %s, got %d." % (operator, number, numres)
@step(u'result (\d+) has( not)? attributes (\S+)')
def search_check_for_result_attribute(step, num, invalid, attrs):
num = int(num)
step.given('at least %d results are returned' % (num + 1))
res = world.results[num]
for attr in attrs.split(','):
if invalid:
assert_not_in(attr.strip(), res)
else:
assert_in(attr.strip(),res)
@step(u'there is a json wrapper "([^"]*)"')
def api_result_check_json_wrapper(step, wrapper):
step.given('the result is valid json')
assert_equals(world.json_callback, wrapper)
@step(u'result header contains')
def api_result_header_contains(step):
step.given('the result is valid')
for line in step.hashes:
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')
for line in step.hashes:
if 'ID' in line:
reslist = (world.results[int(line['ID'])],)
else:
reslist = world.results
for k,v in line.iteritems():
if k == 'latlon':
for curres in reslist:
world.match_geometry((float(curres['lat']), float(curres['lon'])), v)
elif k != 'ID':
for curres in reslist:
assert_in(k, curres)
if v[0] in '<>=':
# mathematical operation
evalexp = '%s %s' % (curres[k], v)
res = eval(evalexp)
logger.debug('Evaluating: %s = %s' % (res, evalexp))
assert_true(res, "Evaluation failed: %s" % (evalexp, ))
else:
# regex match
m = re.match("%s$" % (v,), curres[k])
assert_is_not_none(m, msg="field %s does not match: %s$ != %s." % (k, v, curres[k]))
@step(u'result addresses contain$')
def api_result_address_contains(step):
step.given('the result is valid')
for line in step.hashes:
if 'ID' in line:
reslist = (world.results[int(line['ID'])],)
else:
reslist = world.results
for k,v in line.iteritems():
if k != 'ID':
for res in reslist:
curres = res['address']
assert_in(k, curres)
m = re.match("%s$" % (v,), curres[k])
assert_is_not_none(m, msg="field %s does not match: %s$ != %s." % (k, v, curres[k]))
@step(u'address of result (\d+) contains')
def api_result_address_exact(step, resid):
resid = int(resid)
step.given('at least %d results are returned' % (resid + 1))
addr = world.results[resid]['address']
for line in step.hashes:
assert_in(line['type'], addr)
m = re.match("%s$" % line['value'], addr[line['type']])
assert_is_not_none(m, msg="field %s does not match: %s$ != %s." % (
line['type'], line['value'], addr[line['type']]))
#assert_equals(line['value'], addr[line['type']])
@step(u'address of result (\d+) does not contain (.*)')
def api_result_address_details_missing(step, resid, types):
resid = int(resid)
step.given('at least %d results are returned' % (resid + 1))
addr = world.results[resid]['address']
for t in types.split(','):
assert_not_in(t.strip(), addr)
@step(u'address of result (\d+) is')
def api_result_address_exact(step, resid):
resid = int(resid)
step.given('at least %d results are returned' % (resid + 1))
result = world.results[resid]
linenr = 0
assert_equals(len(step.hashes), len(result['address']))
for k,v in result['address'].iteritems():
assert_equals(step.hashes[linenr]['type'], k)
assert_equals(step.hashes[linenr]['value'], v)
linenr += 1
@step('there are( no)? duplicates')
def api_result_check_for_duplicates(step, nodups=None):
step.given('at least 1 result is returned')
resarr = []
for res in world.results:
resarr.append((res['osm_type'], res['class'],
res['type'], res['display_name']))
if nodups is None:
assert len(resarr) > len(set(resarr))
else:
assert_equal(len(resarr), len(set(resarr)))

136
tests/steps/api_setup.py Normal file
View File

@@ -0,0 +1,136 @@
""" Steps for setting up and sending API requests.
"""
from nose.tools import *
from lettuce import *
import urllib
import urllib2
import logging
logger = logging.getLogger(__name__)
def api_call(requesttype):
world.request_type = requesttype
world.json_callback = None
data = urllib.urlencode(world.params)
url = "%s/%s?%s" % (world.config.base_url, requesttype, data)
req = urllib2.Request(url=url, headers=world.header)
try:
fd = urllib2.urlopen(req)
world.page = fd.read()
world.returncode = 200
except urllib2.HTTPError, ex:
world.returncode = ex.code
world.page = None
return
pageinfo = fd.info()
assert_equal('utf-8', pageinfo.getparam('charset').lower())
pagetype = pageinfo.gettype()
fmt = world.params.get('format')
if fmt == 'html':
assert_equals('text/html', pagetype)
world.response_format = fmt
elif fmt == 'xml':
assert_equals('text/xml', pagetype)
world.response_format = fmt
elif fmt in ('json', 'jsonv2'):
if 'json_callback' in world.params:
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]
assert_equals('application/javascript', pagetype)
else:
assert_equals('application/json', pagetype)
world.response_format = 'json'
else:
if requesttype == 'reverse':
assert_equals('text/xml', pagetype)
world.response_format = 'xml'
else:
assert_equals('text/html', pagetype)
world.response_format = 'html'
logger.debug("Page received (%s):" % world.response_format)
logger.debug(world.page)
api_setup_prepare_params(None)
@before.each_scenario
def api_setup_prepare_params(scenario):
world.results = []
world.params = {}
world.header = {}
@step(u'the request parameters$')
def api_setup_parameters(step):
"""Define the parameters of the request as a hash.
Resets parameter list.
"""
world.params = step.hashes[0]
@step(u'the HTTP header$')
def api_setup_parameters(step):
"""Define additional HTTP header parameters as a hash.
Resets parameter list.
"""
world.header = step.hashes[0]
@step(u'sending( \w+)? search query "([^"]*)"( with address)?')
def api_setup_search(step, fmt, query, doaddr):
world.params['q'] = query.encode('utf8')
if doaddr:
world.params['addressdetails'] = 1
if fmt:
world.params['format'] = fmt.strip()
api_call('search')
@step(u'sending( \w+)? structured query( with address)?$')
def api_setup_structured_search(step, fmt, doaddr):
world.params.update(step.hashes[0])
if doaddr:
world.params['addressdetails'] = 1
if fmt:
world.params['format'] = fmt.strip()
api_call('search')
@step(u'looking up (\w+ )?coordinates ([-\d.]+),([-\d.]+)')
def api_setup_reverse(step, fmt, lat, lon):
world.params['lat'] = lat
world.params['lon'] = lon
if fmt and fmt.strip():
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'):
# an osm id
world.params['osmtype'] = obj[0]
world.params['osmid'] = obj[1:]
else:
world.params['place_id'] = obj
api_call('details')
@step(u'looking up (\w+) places ((?:[a-z]\d+,*)+)')
def api_setup_lookup(step, fmt, ids):
world.params['osm_ids'] = ids
if fmt and fmt.strip():
world.params['format'] = fmt.strip()
api_call('lookup')
@step(u'sending an API call (\w+)')
def api_general_call(step, call):
api_call(call)

Some files were not shown because too many files have changed in this diff Show More