Compare commits

..

206 Commits

Author SHA1 Message Date
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
140 changed files with 6940 additions and 8123 deletions

2
.gitignore vendored
View File

@@ -16,6 +16,7 @@ autom4te.cache/
config.*
configure
Makefile
!tests/scenes/bin/Makefile
Makefile.in
stamp-h1
missing
@@ -29,3 +30,4 @@ data/wiki_import.sql
data/wiki_specialphrases.sql
data/osmosischange.osc
.vagrant

View File

@@ -15,3 +15,5 @@ Nominatim was written by:
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,55 @@
2.0.1
2.5
* delete outdated entries from location_area_country
* remove remaining uses of INTEGER, to allow node ids larger than 2^31
* 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,37 +75,7 @@
* refactoring of front-end PHP code
* lots of smaller bug fixes
2.2
2.0.1
* correct database rights for www-data
* add timestamps for update output
* load postgis via extension for postgis >= 2.0
* remove non-admin boundaries from addresses
* further improve ordering of results with same importance
* merge addr:postcode tags into object addresses
* include rank and importance in reverse geocode output
* replace ST_Line_Interpolate_Point with ST_LineInterpolatePoint
(for postgis >= 2.1)
* update osm2pgsql to latest version
* properly detect changes of admin_level
* remove landuses when name is removed
* smaller fixes
2.3
* further improve ordering of results
* support for more lat/lon formats in search-as-reverse
* fix handling of GB postcodes
* new functional test suite
* support for waterway relations
* inherit postcodes from street to poi
* fix housenumber normalisation to find non-latin house numbers
* take viewbox into account for ordering of results
* pois may now inherit address tags from surrounding buildings
* improve what objects may participate in an address
* clean up handled class/type combinations to current OSM usage
* lots of bug fixes
2.3.1
* fix parse error in replication state directories (fatal during setup)
* delete outdated entries from location_area_country
* remove remaining uses of INTEGER, to allow node ids larger than 2^31

5
README
View File

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

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.3.1)
AC_INIT(Nominatim,2.5)
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;

View File

@@ -6,12 +6,15 @@
protected $aLangPrefOrder = array();
protected $bIncludeAddressDetails = false;
protected $bIncludeExtraTags = false;
protected $bIncludeNameDetails = false;
protected $bIncludePolygonAsPoints = false;
protected $bIncludePolygonAsText = false;
protected $bIncludePolygonAsGeoJSON = false;
protected $bIncludePolygonAsKML = false;
protected $bIncludePolygonAsSVG = false;
protected $fPolygonSimplificationThreshold = 0.0;
protected $aExcludePlaceIDs = array();
protected $bDeDupe = true;
@@ -67,6 +70,16 @@
return $this->bIncludeAddressDetails;
}
function getIncludeExtraTags()
{
return $this->bIncludeExtraTags;
}
function getIncludeNameDetails()
{
return $this->bIncludeNameDetails;
}
function setIncludePolygonAsPoints($b = true)
{
$this->bIncludePolygonAsPoints = $b;
@@ -102,6 +115,11 @@
$this->bIncludePolygonAsSVG = $b;
}
function setPolygonSimplificationThreshold($f)
{
$this->fPolygonSimplificationThreshold = $f;
}
function setDeDupe($bDeDupe = true)
{
$this->bDeDupe = (bool)$bDeDupe;
@@ -208,6 +226,11 @@
function loadParamArray($aParams)
{
if (isset($aParams['addressdetails'])) $this->bIncludeAddressDetails = (bool)$aParams['addressdetails'];
if ((float) CONST_Postgresql_Version > 9.2)
{
if (isset($aParams['extratags'])) $this->bIncludeExtraTags = (bool)$aParams['extratags'];
if (isset($aParams['namedetails'])) $this->bIncludeNameDetails = (bool)$aParams['namedetails'];
}
if (isset($aParams['bounded'])) $this->bBoundedSearch = (bool)$aParams['bounded'];
if (isset($aParams['dedupe'])) $this->bDeDupe = (bool)$aParams['dedupe'];
@@ -222,9 +245,12 @@
foreach(explode(',',$aParams['exclude_place_ids']) as $iExcludedPlaceID)
{
$iExcludedPlaceID = (int)$iExcludedPlaceID;
if ($iExcludedPlaceID) $aExcludePlaceIDs[$iExcludedPlaceID] = $iExcludedPlaceID;
if ($iExcludedPlaceID)
$aExcludePlaceIDs[$iExcludedPlaceID] = $iExcludedPlaceID;
}
$this->aExcludePlaceIDs = $aExcludePlaceIDs;
if (isset($aExcludePlaceIDs))
$this->aExcludePlaceIDs = $aExcludePlaceIDs;
}
// Only certain ranks of feature
@@ -380,6 +406,8 @@
$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->bIncludeExtraTags) $sSQL .= "hstore_to_json(extratags)::text as extra,";
if ($this->bIncludeNameDetails) $sSQL .= "hstore_to_json(name)::text as names,";
$sSQL .= "avg(ST_X(centroid)) as lon,avg(ST_Y(centroid)) as lat, ";
$sSQL .= $sImportanceSQL."coalesce(importance,0.75-(rank_search::float/40)) as importance, ";
$sSQL .= "(select max(p.importance*(p.rank_address+2)) from place_addressline s, placex p where s.place_id = min(CASE WHEN placex.rank_search < 28 THEN placex.place_id ELSE placex.parent_place_id END) and p.place_id = s.address_place_id and s.isaddress and p.importance is not null) as addressimportance, ";
@@ -396,6 +424,8 @@
$sSQL .= ",langaddress ";
$sSQL .= ",placename ";
$sSQL .= ",ref ";
if ($this->bIncludeExtraTags) $sSQL .= ",extratags";
if ($this->bIncludeNameDetails) $sSQL .= ",name";
$sSQL .= ",extratags->'place' ";
if (30 >= $this->iMinAddressRank && 30 <= $this->iMaxAddressRank)
@@ -405,6 +435,8 @@
$sSQL .= "get_address_by_language(place_id, $sLanguagePrefArraySQL) as langaddress,";
$sSQL .= "null as placename,";
$sSQL .= "null as ref,";
if ($this->bIncludeExtraTags) $sSQL .= "null as extra,";
if ($this->bIncludeNameDetails) $sSQL .= "null as names,";
$sSQL .= "avg(ST_X(centroid)) as lon,avg(ST_Y(centroid)) as lat, ";
$sSQL .= $sImportanceSQL."-1.15 as importance, ";
$sSQL .= "(select max(p.importance*(p.rank_address+2)) from place_addressline s, placex p where s.place_id = min(location_property_tiger.parent_place_id) and p.place_id = s.address_place_id and s.isaddress and p.importance is not null) as addressimportance, ";
@@ -418,6 +450,8 @@
$sSQL .= "get_address_by_language(place_id, $sLanguagePrefArraySQL) as langaddress,";
$sSQL .= "null as placename,";
$sSQL .= "null as ref,";
if ($this->bIncludeExtraTags) $sSQL .= "null as extra,";
if ($this->bIncludeNameDetails) $sSQL .= "null as names,";
$sSQL .= "avg(ST_X(centroid)) as lon,avg(ST_Y(centroid)) as lat, ";
$sSQL .= $sImportanceSQL."-1.10 as importance, ";
$sSQL .= "(select max(p.importance*(p.rank_address+2)) from place_addressline s, placex p where s.place_id = min(location_property_aux.parent_place_id) and p.place_id = s.address_place_id and s.isaddress and p.importance is not null) as addressimportance, ";
@@ -441,6 +475,283 @@
return $aSearchResults;
}
function getGroupedSearches($aSearches, $aPhraseTypes, $aPhrases, $aValidTokens, $aWordFrequencyScores, $bStructuredPhrases)
{
/*
Calculate all searches using aValidTokens i.e.
'Wodsworth Road, Sheffield' =>
Phrase Wordset
0 0 (wodsworth road)
0 1 (wodsworth)(road)
1 0 (sheffield)
Score how good the search is so they can be ordered
*/
foreach($aPhrases as $iPhrase => $sPhrase)
{
$aNewPhraseSearches = array();
if ($bStructuredPhrases) $sPhraseType = $aPhraseTypes[$iPhrase];
else $sPhraseType = '';
foreach($aPhrases[$iPhrase]['wordsets'] as $iWordSet => $aWordset)
{
// Too many permutations - too expensive
if ($iWordSet > 120) break;
$aWordsetSearches = $aSearches;
// Add all words from this wordset
foreach($aWordset as $iToken => $sToken)
{
//echo "<br><b>$sToken</b>";
$aNewWordsetSearches = array();
foreach($aWordsetSearches as $aCurrentSearch)
{
//echo "<i>";
//var_dump($aCurrentSearch);
//echo "</i>";
// If the token is valid
if (isset($aValidTokens[' '.$sToken]))
{
foreach($aValidTokens[' '.$sToken] as $aSearchTerm)
{
$aSearch = $aCurrentSearch;
$aSearch['iSearchRank']++;
if (($sPhraseType == '' || $sPhraseType == 'country') && !empty($aSearchTerm['country_code']) && $aSearchTerm['country_code'] != '0')
{
if ($aSearch['sCountryCode'] === false)
{
$aSearch['sCountryCode'] = strtolower($aSearchTerm['country_code']);
// Country is almost always at the end of the string - increase score for finding it anywhere else (optimisation)
if (($iToken+1 != sizeof($aWordset) || $iPhrase+1 != sizeof($aPhrases)))
{
$aSearch['iSearchRank'] += 5;
}
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
elseif (isset($aSearchTerm['lat']) && $aSearchTerm['lat'] !== '' && $aSearchTerm['lat'] !== null)
{
if ($aSearch['fLat'] === '')
{
$aSearch['fLat'] = $aSearchTerm['lat'];
$aSearch['fLon'] = $aSearchTerm['lon'];
$aSearch['fRadius'] = $aSearchTerm['radius'];
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
elseif ($sPhraseType == 'postalcode')
{
// We need to try the case where the postal code is the primary element (i.e. no way to tell if it is (postalcode, city) OR (city, postalcode) so try both
if (isset($aSearchTerm['word_id']) && $aSearchTerm['word_id'])
{
// If we already have a name try putting the postcode first
if (sizeof($aSearch['aName']))
{
$aNewSearch = $aSearch;
$aNewSearch['aAddress'] = array_merge($aNewSearch['aAddress'], $aNewSearch['aName']);
$aNewSearch['aName'] = array();
$aNewSearch['aName'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aNewSearch;
}
if (sizeof($aSearch['aName']))
{
if ((!$bStructuredPhrases || $iPhrase > 0) && $sPhraseType != 'country' && (!isset($aValidTokens[$sToken]) || strpos($sToken, ' ') !== false))
{
$aSearch['aAddress'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
}
else
{
$aCurrentSearch['aFullNameAddress'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
$aSearch['iSearchRank'] += 1000; // skip;
}
}
else
{
$aSearch['aName'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
//$aSearch['iNamePhrase'] = $iPhrase;
}
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
elseif (($sPhraseType == '' || $sPhraseType == 'street') && $aSearchTerm['class'] == 'place' && $aSearchTerm['type'] == 'house')
{
if ($aSearch['sHouseNumber'] === '')
{
$aSearch['sHouseNumber'] = $sToken;
// sanity check: if the housenumber is not mainly made
// up of numbers, add a penalty
if (preg_match_all("/[^0-9]/", $sToken, $aMatches) > 2) $aSearch['iSearchRank']++;
// also housenumbers should appear in the first or second phrase
if ($iPhrase > 1) $aSearch['iSearchRank'] += 1;
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
/*
// Fall back to not searching for this item (better than nothing)
$aSearch = $aCurrentSearch;
$aSearch['iSearchRank'] += 1;
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
*/
}
}
elseif ($sPhraseType == '' && $aSearchTerm['class'] !== '' && $aSearchTerm['class'] !== null)
{
if ($aSearch['sClass'] === '')
{
$aSearch['sOperator'] = $aSearchTerm['operator'];
$aSearch['sClass'] = $aSearchTerm['class'];
$aSearch['sType'] = $aSearchTerm['type'];
if (sizeof($aSearch['aName'])) $aSearch['sOperator'] = 'name';
else $aSearch['sOperator'] = 'near'; // near = in for the moment
if (strlen($aSearchTerm['operator']) == 0) $aSearch['iSearchRank'] += 1;
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
elseif (isset($aSearchTerm['word_id']) && $aSearchTerm['word_id'])
{
if (sizeof($aSearch['aName']))
{
if ((!$bStructuredPhrases || $iPhrase > 0) && $sPhraseType != 'country' && (!isset($aValidTokens[$sToken]) || strpos($sToken, ' ') !== false))
{
$aSearch['aAddress'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
}
else
{
$aCurrentSearch['aFullNameAddress'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
$aSearch['iSearchRank'] += 1000; // skip;
}
}
else
{
$aSearch['aName'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
//$aSearch['iNamePhrase'] = $iPhrase;
}
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
}
// Look for partial matches.
// Note that there is no point in adding country terms here
// because country are omitted in the address.
if (isset($aValidTokens[$sToken]) && $sPhraseType != 'country')
{
// Allow searching for a word - but at extra cost
foreach($aValidTokens[$sToken] as $aSearchTerm)
{
if (isset($aSearchTerm['word_id']) && $aSearchTerm['word_id'])
{
if ((!$bStructuredPhrases || $iPhrase > 0) && sizeof($aCurrentSearch['aName']) && strpos($sToken, ' ') === false)
{
$aSearch = $aCurrentSearch;
$aSearch['iSearchRank'] += 1;
if ($aWordFrequencyScores[$aSearchTerm['word_id']] < CONST_Max_Word_Frequency)
{
$aSearch['aAddress'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
elseif (isset($aValidTokens[' '.$sToken])) // revert to the token version?
{
$aSearch['aAddressNonSearch'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
$aSearch['iSearchRank'] += 1;
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
foreach($aValidTokens[' '.$sToken] as $aSearchTermToken)
{
if (empty($aSearchTermToken['country_code'])
&& empty($aSearchTermToken['lat'])
&& empty($aSearchTermToken['class']))
{
$aSearch = $aCurrentSearch;
$aSearch['iSearchRank'] += 1;
$aSearch['aAddress'][$aSearchTermToken['word_id']] = $aSearchTermToken['word_id'];
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
}
else
{
$aSearch['aAddressNonSearch'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
if (preg_match('#^[0-9]+$#', $sToken)) $aSearch['iSearchRank'] += 2;
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
if (!sizeof($aCurrentSearch['aName']) || $aCurrentSearch['iNamePhrase'] == $iPhrase)
{
$aSearch = $aCurrentSearch;
$aSearch['iSearchRank'] += 1;
if (!sizeof($aCurrentSearch['aName'])) $aSearch['iSearchRank'] += 1;
if (preg_match('#^[0-9]+$#', $sToken)) $aSearch['iSearchRank'] += 2;
if ($aWordFrequencyScores[$aSearchTerm['word_id']] < CONST_Max_Word_Frequency)
$aSearch['aName'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
else
$aSearch['aNameNonSearch'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
$aSearch['iNamePhrase'] = $iPhrase;
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
}
}
else
{
// Allow skipping a word - but at EXTREAM cost
//$aSearch = $aCurrentSearch;
//$aSearch['iSearchRank']+=100;
//$aNewWordsetSearches[] = $aSearch;
}
}
// Sort and cut
usort($aNewWordsetSearches, 'bySearchRank');
$aWordsetSearches = array_slice($aNewWordsetSearches, 0, 50);
}
//var_Dump('<hr>',sizeof($aWordsetSearches)); exit;
$aNewPhraseSearches = array_merge($aNewPhraseSearches, $aNewWordsetSearches);
usort($aNewPhraseSearches, 'bySearchRank');
$aSearchHash = array();
foreach($aNewPhraseSearches as $iSearch => $aSearch)
{
$sHash = serialize($aSearch);
if (isset($aSearchHash[$sHash])) unset($aNewPhraseSearches[$iSearch]);
else $aSearchHash[$sHash] = 1;
}
$aNewPhraseSearches = array_slice($aNewPhraseSearches, 0, 50);
}
// Re-group the searches by their score, junk anything over 20 as just not worth trying
$aGroupedSearches = array();
foreach($aNewPhraseSearches as $aSearch)
{
if ($aSearch['iSearchRank'] < $this->iMaxRank)
{
if (!isset($aGroupedSearches[$aSearch['iSearchRank']])) $aGroupedSearches[$aSearch['iSearchRank']] = array();
$aGroupedSearches[$aSearch['iSearchRank']][] = $aSearch;
}
}
ksort($aGroupedSearches);
$iSearchCount = 0;
$aSearches = array();
foreach($aGroupedSearches as $iScore => $aNewSearches)
{
$iSearchCount += sizeof($aNewSearches);
$aSearches = array_merge($aSearches, $aNewSearches);
if ($iSearchCount > 50) break;
}
//if (CONST_Debug) _debugDumpGroupedSearches($aGroupedSearches, $aValidTokens);
}
return $aGroupedSearches;
}
/* Perform the actual query lookup.
Returns an ordered list of results, each with the following fields:
@@ -476,7 +787,6 @@
if (!$this->sQuery && !$this->aStructuredQuery) return false;
$sLanguagePrefArraySQL = "ARRAY[".join(',',array_map("getDBQuoted",$this->aLangPrefOrder))."]";
$sCountryCodesSQL = false;
if ($this->aCountryCodes && sizeof($this->aCountryCodes))
{
@@ -579,10 +889,10 @@
preg_match_all('/\\[([\\w ]*)\\]/u', $sQuery, $aSpecialTermsRaw, PREG_SET_ORDER);
$aSpecialTerms = array();
if (isset($aStructuredQuery['amenity']) && $aStructuredQuery['amenity'])
if (isset($this->aStructuredQuery['amenity']) && $this->aStructuredQuery['amenity'])
{
$aSpecialTermsRaw[] = array('['.$aStructuredQuery['amenity'].']', $aStructuredQuery['amenity']);
unset($aStructuredQuery['amenity']);
$aSpecialTermsRaw[] = array('['.$this->aStructuredQuery['amenity'].']', $this->aStructuredQuery['amenity']);
unset($this->aStructuredQuery['amenity']);
}
foreach($aSpecialTermsRaw as $aSpecialTerm)
{
@@ -680,8 +990,8 @@
foreach($aDatabaseWords as $aToken)
{
// Very special case - require 2 letter country param to match the country code found
if ($bStructuredPhrases && $aToken['country_code'] && !empty($aStructuredQuery['country'])
&& strlen($aStructuredQuery['country']) == 2 && strtolower($aStructuredQuery['country']) != $aToken['country_code'])
if ($bStructuredPhrases && $aToken['country_code'] && !empty($this->aStructuredQuery['country'])
&& strlen($this->aStructuredQuery['country']) == 2 && strtolower($this->aStructuredQuery['country']) != $aToken['country_code'])
{
continue;
}
@@ -755,287 +1065,38 @@
// Start the search process
$aResultPlaceIDs = array();
/*
Calculate all searches using aValidTokens i.e.
'Wodsworth Road, Sheffield' =>
$aGroupedSearches = $this->getGroupedSearches($aSearches, $aPhraseTypes, $aPhrases, $aValidTokens, $aWordFrequencyScores, $bStructuredPhrases);
Phrase Wordset
0 0 (wodsworth road)
0 1 (wodsworth)(road)
1 0 (sheffield)
Score how good the search is so they can be ordered
*/
foreach($aPhrases as $iPhrase => $sPhrase)
if ($this->bReverseInPlan)
{
$aNewPhraseSearches = array();
if ($bStructuredPhrases) $sPhraseType = $aPhraseTypes[$iPhrase];
else $sPhraseType = '';
foreach($aPhrases[$iPhrase]['wordsets'] as $iWordSet => $aWordset)
// Reverse phrase array and also reverse the order of the wordsets in
// the first and final phrase. Don't bother about phrases in the middle
// because order in the address doesn't matter.
$aPhrases = array_reverse($aPhrases);
$aPhrases[0]['wordsets'] = getInverseWordSets($aPhrases[0]['words'], 0);
if (sizeof($aPhrases) > 1)
{
// Too many permutations - too expensive
if ($iWordSet > 120) break;
$aFinalPhrase = end($aPhrases);
$aPhrases[sizeof($aPhrases)-1]['wordsets'] = getInverseWordSets($aFinalPhrase['words'], 0);
}
$aReverseGroupedSearches = $this->getGroupedSearches($aSearches, null, $aPhrases, $aValidTokens, $aWordFrequencyScores, false);
$aWordsetSearches = $aSearches;
// Add all words from this wordset
foreach($aWordset as $iToken => $sToken)
foreach($aGroupedSearches as $aSearches)
{
foreach($aSearches as $aSearch)
{
//echo "<br><b>$sToken</b>";
$aNewWordsetSearches = array();
foreach($aWordsetSearches as $aCurrentSearch)
if ($aSearch['iSearchRank'] < $this->iMaxRank)
{
//echo "<i>";
//var_dump($aCurrentSearch);
//echo "</i>";
// If the token is valid
if (isset($aValidTokens[' '.$sToken]))
{
foreach($aValidTokens[' '.$sToken] as $aSearchTerm)
{
$aSearch = $aCurrentSearch;
$aSearch['iSearchRank']++;
if (($sPhraseType == '' || $sPhraseType == 'country') && !empty($aSearchTerm['country_code']) && $aSearchTerm['country_code'] != '0')
{
if ($aSearch['sCountryCode'] === false)
{
$aSearch['sCountryCode'] = strtolower($aSearchTerm['country_code']);
// Country is almost always at the end of the string - increase score for finding it anywhere else (optimisation)
// If reverse order is enabled, it may appear at the beginning as well.
if (($iToken+1 != sizeof($aWordset) || $iPhrase+1 != sizeof($aPhrases)) &&
(!$this->bReverseInPlan || $iToken > 0 || $iPhrase > 0))
{
$aSearch['iSearchRank'] += 5;
}
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
elseif (isset($aSearchTerm['lat']) && $aSearchTerm['lat'] !== '' && $aSearchTerm['lat'] !== null)
{
if ($aSearch['fLat'] === '')
{
$aSearch['fLat'] = $aSearchTerm['lat'];
$aSearch['fLon'] = $aSearchTerm['lon'];
$aSearch['fRadius'] = $aSearchTerm['radius'];
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
elseif ($sPhraseType == 'postalcode')
{
// We need to try the case where the postal code is the primary element (i.e. no way to tell if it is (postalcode, city) OR (city, postalcode) so try both
if (isset($aSearchTerm['word_id']) && $aSearchTerm['word_id'])
{
// If we already have a name try putting the postcode first
if (sizeof($aSearch['aName']))
{
$aNewSearch = $aSearch;
$aNewSearch['aAddress'] = array_merge($aNewSearch['aAddress'], $aNewSearch['aName']);
$aNewSearch['aName'] = array();
$aNewSearch['aName'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aNewSearch;
}
if (sizeof($aSearch['aName']))
{
if ((!$bStructuredPhrases || $iPhrase > 0) && $sPhraseType != 'country' && (!isset($aValidTokens[$sToken]) || strlen($sToken) < 4 || strpos($sToken, ' ') !== false))
{
$aSearch['aAddress'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
}
else
{
$aCurrentSearch['aFullNameAddress'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
$aSearch['iSearchRank'] += 1000; // skip;
}
}
else
{
$aSearch['aName'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
//$aSearch['iNamePhrase'] = $iPhrase;
}
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
elseif (($sPhraseType == '' || $sPhraseType == 'street') && $aSearchTerm['class'] == 'place' && $aSearchTerm['type'] == 'house')
{
if ($aSearch['sHouseNumber'] === '')
{
$aSearch['sHouseNumber'] = $sToken;
// sanity check: if the housenumber is not mainly made
// up of numbers, add a penalty
if (preg_match_all("/[^0-9]/", $sToken, $aMatches) > 2) $aSearch['iSearchRank']++;
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
/*
// Fall back to not searching for this item (better than nothing)
$aSearch = $aCurrentSearch;
$aSearch['iSearchRank'] += 1;
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
*/
}
}
elseif ($sPhraseType == '' && $aSearchTerm['class'] !== '' && $aSearchTerm['class'] !== null)
{
if ($aSearch['sClass'] === '')
{
$aSearch['sOperator'] = $aSearchTerm['operator'];
$aSearch['sClass'] = $aSearchTerm['class'];
$aSearch['sType'] = $aSearchTerm['type'];
if (sizeof($aSearch['aName'])) $aSearch['sOperator'] = 'name';
else $aSearch['sOperator'] = 'near'; // near = in for the moment
if (strlen($aSearchTerm['operator']) == 0) $aSearch['iSearchRank'] += 1;
// Do we have a shortcut id?
if ($aSearch['sOperator'] == 'name')
{
$sSQL = "select get_tagpair('".$aSearch['sClass']."', '".$aSearch['sType']."')";
if ($iAmenityID = $this->oDB->getOne($sSQL))
{
$aValidTokens[$aSearch['sClass'].':'.$aSearch['sType']] = array('word_id' => $iAmenityID);
$aSearch['aName'][$iAmenityID] = $iAmenityID;
$aSearch['sClass'] = '';
$aSearch['sType'] = '';
}
}
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
elseif (isset($aSearchTerm['word_id']) && $aSearchTerm['word_id'])
{
if (sizeof($aSearch['aName']))
{
if ((!$bStructuredPhrases || $iPhrase > 0) && $sPhraseType != 'country' && (!isset($aValidTokens[$sToken]) || strlen($sToken) < 4 || strpos($sToken, ' ') !== false))
{
$aSearch['aAddress'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
}
else
{
$aCurrentSearch['aFullNameAddress'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
$aSearch['iSearchRank'] += 1000; // skip;
}
}
else
{
$aSearch['aName'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
//$aSearch['iNamePhrase'] = $iPhrase;
}
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
}
if (isset($aValidTokens[$sToken]))
{
// Allow searching for a word - but at extra cost
foreach($aValidTokens[$sToken] as $aSearchTerm)
{
if (isset($aSearchTerm['word_id']) && $aSearchTerm['word_id'])
{
if ((!$bStructuredPhrases || $iPhrase > 0) && sizeof($aCurrentSearch['aName']) && strpos($sToken, ' ') === false)
{
$aSearch = $aCurrentSearch;
$aSearch['iSearchRank'] += 1;
if ($aWordFrequencyScores[$aSearchTerm['word_id']] < CONST_Max_Word_Frequency)
{
$aSearch['aAddress'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
elseif (isset($aValidTokens[' '.$sToken]) && strlen($sToken) >= 4) // revert to the token version?
{
$aSearch['aAddressNonSearch'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
$aSearch['iSearchRank'] += 1;
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
foreach($aValidTokens[' '.$sToken] as $aSearchTermToken)
{
if (empty($aSearchTermToken['country_code'])
&& empty($aSearchTermToken['lat'])
&& empty($aSearchTermToken['class']))
{
$aSearch = $aCurrentSearch;
$aSearch['iSearchRank'] += 1;
$aSearch['aAddress'][$aSearchTermToken['word_id']] = $aSearchTermToken['word_id'];
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
}
else
{
$aSearch['aAddressNonSearch'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
if (preg_match('#^[0-9]+$#', $sToken)) $aSearch['iSearchRank'] += 2;
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
if (!sizeof($aCurrentSearch['aName']) || $aCurrentSearch['iNamePhrase'] == $iPhrase)
{
$aSearch = $aCurrentSearch;
$aSearch['iSearchRank'] += 1;
if (!sizeof($aCurrentSearch['aName'])) $aSearch['iSearchRank'] += 1;
if (preg_match('#^[0-9]+$#', $sToken)) $aSearch['iSearchRank'] += 2;
if ($aWordFrequencyScores[$aSearchTerm['word_id']] < CONST_Max_Word_Frequency)
$aSearch['aName'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
else
$aSearch['aNameNonSearch'][$aSearchTerm['word_id']] = $aSearchTerm['word_id'];
$aSearch['iNamePhrase'] = $iPhrase;
if ($aSearch['iSearchRank'] < $this->iMaxRank) $aNewWordsetSearches[] = $aSearch;
}
}
}
}
else
{
// Allow skipping a word - but at EXTREAM cost
//$aSearch = $aCurrentSearch;
//$aSearch['iSearchRank']+=100;
//$aNewWordsetSearches[] = $aSearch;
}
if (!isset($aReverseGroupedSearches[$aSearch['iSearchRank']])) $aReverseGroupedSearches[$aSearch['iSearchRank']] = array();
$aReverseGroupedSearches[$aSearch['iSearchRank']][] = $aSearch;
}
// Sort and cut
usort($aNewWordsetSearches, 'bySearchRank');
$aWordsetSearches = array_slice($aNewWordsetSearches, 0, 50);
}
//var_Dump('<hr>',sizeof($aWordsetSearches)); exit;
$aNewPhraseSearches = array_merge($aNewPhraseSearches, $aNewWordsetSearches);
usort($aNewPhraseSearches, 'bySearchRank');
$aSearchHash = array();
foreach($aNewPhraseSearches as $iSearch => $aSearch)
{
$sHash = serialize($aSearch);
if (isset($aSearchHash[$sHash])) unset($aNewPhraseSearches[$iSearch]);
else $aSearchHash[$sHash] = 1;
}
$aNewPhraseSearches = array_slice($aNewPhraseSearches, 0, 50);
}
// Re-group the searches by their score, junk anything over 20 as just not worth trying
$aGroupedSearches = array();
foreach($aNewPhraseSearches as $aSearch)
{
if ($aSearch['iSearchRank'] < $this->iMaxRank)
{
if (!isset($aGroupedSearches[$aSearch['iSearchRank']])) $aGroupedSearches[$aSearch['iSearchRank']] = array();
$aGroupedSearches[$aSearch['iSearchRank']][] = $aSearch;
}
}
$aGroupedSearches = $aReverseGroupedSearches;
ksort($aGroupedSearches);
$iSearchCount = 0;
$aSearches = array();
foreach($aGroupedSearches as $iScore => $aNewSearches)
{
$iSearchCount += sizeof($aNewSearches);
$aSearches = array_merge($aSearches, $aNewSearches);
if ($iSearchCount > 50) break;
}
//if (CONST_Debug) _debugDumpGroupedSearches($aGroupedSearches, $aValidTokens);
}
}
else
{
@@ -1054,30 +1115,7 @@
if (CONST_Debug) var_Dump($aGroupedSearches);
if ($this->bReverseInPlan)
{
$aCopyGroupedSearches = $aGroupedSearches;
foreach($aCopyGroupedSearches as $iGroup => $aSearches)
{
foreach($aSearches as $iSearch => $aSearch)
{
if (sizeof($aSearch['aAddress']))
{
$iReverseItem = array_pop($aSearch['aAddress']);
if (isset($aPossibleMainWordIDs[$iReverseItem]))
{
$aSearch['aAddress'] = array_merge($aSearch['aAddress'], $aSearch['aName']);
$aSearch['aName'] = array($iReverseItem);
$aGroupedSearches[$iGroup][] = $aSearch;
}
//$aReverseSearch['aName'][$iReverseItem] = $iReverseItem;
//$aGroupedSearches[$iGroup][] = $aReverseSearch;
}
}
}
}
if (CONST_Search_TryDroppedAddressTerms && sizeof($aStructuredQuery) > 0)
if (CONST_Search_TryDroppedAddressTerms && sizeof($this->aStructuredQuery) > 0)
{
$aCopyGroupedSearches = $aGroupedSearches;
foreach($aCopyGroupedSearches as $iGroup => $aSearches)
@@ -1156,6 +1194,8 @@
{
$sSQL = "select place_id from placex where calculated_country_code='".$aSearch['sCountryCode']."' and rank_search = 4";
if ($sCountryCodesSQL) $sSQL .= " and calculated_country_code in ($sCountryCodesSQL)";
if ($bBoundingBoxSearch)
$sSQL .= " and _st_intersects($this->sViewboxSmallSQL, geometry)";
$sSQL .= " order by st_area(geometry) desc limit 1";
if (CONST_Debug) var_dump($sSQL);
$aPlaceIDs = $this->oDB->getCol($sSQL);
@@ -1221,6 +1261,12 @@
$aTerms = array();
$aOrder = array();
if ($aSearch['sHouseNumber'] && sizeof($aSearch['aAddress']))
{
$sHouseNumberRegex = '\\\\m'.$aSearch['sHouseNumber'].'\\\\M';
$aOrder[] = "exists(select place_id from placex where parent_place_id = search_name.place_id and transliteration(housenumber) ~* E'".$sHouseNumberRegex."' limit 1) desc";
}
// TODO: filter out the pointless search terms (2 letter name tokens and less)
// they might be right - but they are just too darned expensive to run
if (sizeof($aSearch['aName'])) $aTerms[] = "name_vector @> ARRAY[".join($aSearch['aName'],",")."]";
@@ -1301,7 +1347,7 @@
$sSQL .= " where ".join(' and ',$aTerms);
$sSQL .= " order by ".join(', ',$aOrder);
if ($aSearch['sHouseNumber'] || $aSearch['sClass'])
$sSQL .= " limit 50";
$sSQL .= " limit 20";
elseif (!sizeof($aSearch['aName']) && !sizeof($aSearch['aAddress']) && $aSearch['sClass'])
$sSQL .= " limit 1";
else
@@ -1566,23 +1612,49 @@
$aRecheckWords = preg_split('/\b[\s,\\-]*/u',$sQuery);
foreach($aRecheckWords as $i => $sWord)
{
if (!$sWord) unset($aRecheckWords[$i]);
if (!preg_match('/\pL/', $sWord)) unset($aRecheckWords[$i]);
}
if (CONST_Debug) { echo '<i>Recheck words:<\i>'; var_dump($aRecheckWords); }
foreach($aSearchResults as $iResNum => $aResult)
{
// Default
$fDiameter = 0.0001;
if (isset($aClassType[$aResult['class'].':'.$aResult['type'].':'.$aResult['admin_level']]['defdiameter'])
&& $aClassType[$aResult['class'].':'.$aResult['type'].':'.$aResult['admin_level']]['defdiameter'])
{
$fDiameter = $aClassType[$aResult['class'].':'.$aResult['type'].':'.$aResult['admin_level']]['defdiameter'];
}
elseif (isset($aClassType[$aResult['class'].':'.$aResult['type']]['defdiameter'])
&& $aClassType[$aResult['class'].':'.$aResult['type']]['defdiameter'])
{
$fDiameter = $aClassType[$aResult['class'].':'.$aResult['type']]['defdiameter'];
}
$fRadius = $fDiameter / 2;
if (CONST_Search_AreaPolygons)
{
// Get the bounding box and outline polygon
$sSQL = "select place_id,0 as numfeatures,st_area(geometry) as area,";
$sSQL .= "ST_Y(centroid) as centrelat,ST_X(centroid) as centrelon,";
$sSQL .= "ST_Y(ST_PointN(ST_ExteriorRing(Box2D(geometry)),4)) as minlat,ST_Y(ST_PointN(ST_ExteriorRing(Box2D(geometry)),2)) as maxlat,";
$sSQL .= "ST_X(ST_PointN(ST_ExteriorRing(Box2D(geometry)),1)) as minlon,ST_X(ST_PointN(ST_ExteriorRing(Box2D(geometry)),3)) as maxlon";
$sSQL .= "ST_YMin(geometry) as minlat,ST_YMax(geometry) as maxlat,";
$sSQL .= "ST_XMin(geometry) as minlon,ST_XMax(geometry) as maxlon";
if ($this->bIncludePolygonAsGeoJSON) $sSQL .= ",ST_AsGeoJSON(geometry) as asgeojson";
if ($this->bIncludePolygonAsKML) $sSQL .= ",ST_AsKML(geometry) as askml";
if ($this->bIncludePolygonAsSVG) $sSQL .= ",ST_AsSVG(geometry) as assvg";
if ($this->bIncludePolygonAsText || $this->bIncludePolygonAsPoints) $sSQL .= ",ST_AsText(geometry) as astext";
$sSQL .= " from placex where place_id = ".$aResult['place_id'].' and st_geometrytype(Box2D(geometry)) = \'ST_Polygon\'';
$sFrom = " from placex where place_id = ".$aResult['place_id'];
if ($this->fPolygonSimplificationThreshold > 0)
{
$sSQL .= " from (select place_id,centroid,ST_SimplifyPreserveTopology(geometry,".$this->fPolygonSimplificationThreshold.") as geometry".$sFrom.") as plx";
}
else
{
$sSQL .= $sFrom;
}
$aPointPolygon = $this->oDB->getRow($sSQL);
if (PEAR::IsError($aPointPolygon))
{
@@ -1604,7 +1676,7 @@
if ($this->bIncludePolygonAsPoints)
{
// Translate geometary string to point array
// Translate geometry string to point array
if (preg_match('#POLYGON\\(\\(([- 0-9.,]+)#',$aPointPolygon['astext'],$aMatch))
{
preg_match_all('/(-?[0-9.]+) (-?[0-9.]+)/',$aMatch[1],$aPolyPoints,PREG_SET_ORDER);
@@ -1615,18 +1687,13 @@
}
elseif (preg_match('#POINT\\((-?[0-9.]+) (-?[0-9.]+)\\)#',$aPointPolygon['astext'],$aMatch))
{
$fRadius = 0.01;
$iSteps = ($fRadius * 40000)^2;
$iSteps = max(8, min(100, ($fRadius * 40000)^2));
$fStepSize = (2*pi())/$iSteps;
$aPolyPoints = array();
for($f = 0; $f < 2*pi(); $f += $fStepSize)
{
$aPolyPoints[] = array('',$aMatch[1]+($fRadius*sin($f)),$aMatch[2]+($fRadius*cos($f)));
}
$aPointPolygon['minlat'] = $aPointPolygon['minlat'] - $fRadius;
$aPointPolygon['maxlat'] = $aPointPolygon['maxlat'] + $fRadius;
$aPointPolygon['minlon'] = $aPointPolygon['minlon'] - $fRadius;
$aPointPolygon['maxlon'] = $aPointPolygon['maxlon'] + $fRadius;
}
}
@@ -1639,7 +1706,18 @@
$aResult['aPolyPoints'][] = array($aPoint[1], $aPoint[2]);
}
}
$aResult['aBoundingBox'] = array($aPointPolygon['minlat'],$aPointPolygon['maxlat'],$aPointPolygon['minlon'],$aPointPolygon['maxlon']);
if (abs($aPointPolygon['minlat'] - $aPointPolygon['maxlat']) < 0.0000001)
{
$aPointPolygon['minlat'] = $aPointPolygon['minlat'] - $fRadius;
$aPointPolygon['maxlat'] = $aPointPolygon['maxlat'] + $fRadius;
}
if (abs($aPointPolygon['minlon'] - $aPointPolygon['maxlon']) < 0.0000001)
{
$aPointPolygon['minlon'] = $aPointPolygon['minlon'] - $fRadius;
$aPointPolygon['maxlon'] = $aPointPolygon['maxlon'] + $fRadius;
}
$aResult['aBoundingBox'] = array((string)$aPointPolygon['minlat'],(string)$aPointPolygon['maxlat'],(string)$aPointPolygon['minlon'],(string)$aPointPolygon['maxlon']);
}
}
@@ -1652,28 +1730,8 @@
if (!isset($aResult['aBoundingBox']))
{
// Default
$fDiameter = 0.0001;
if (isset($aClassType[$aResult['class'].':'.$aResult['type'].':'.$aResult['admin_level']]['defdiameter'])
&& $aClassType[$aResult['class'].':'.$aResult['type'].':'.$aResult['admin_level']]['defdiameter'])
{
$fDiameter = $aClassType[$aResult['class'].':'.$aResult['type'].':'.$aResult['admin_level']]['defzoom'];
}
elseif (isset($aClassType[$aResult['class'].':'.$aResult['type']]['defdiameter'])
&& $aClassType[$aResult['class'].':'.$aResult['type']]['defdiameter'])
{
$fDiameter = $aClassType[$aResult['class'].':'.$aResult['type']]['defdiameter'];
}
$fRadius = $fDiameter / 2;
$iSteps = max(8,min(100,$fRadius * 3.14 * 100000));
$fStepSize = (2*pi())/$iSteps;
$aPolyPoints = array();
for($f = 0; $f < 2*pi(); $f += $fStepSize)
{
$aPolyPoints[] = array('',$aResult['lon']+($fRadius*sin($f)),$aResult['lat']+($fRadius*cos($f)));
}
$aPointPolygon['minlat'] = $aResult['lat'] - $fRadius;
$aPointPolygon['maxlat'] = $aResult['lat'] + $fRadius;
$aPointPolygon['minlon'] = $aResult['lon'] - $fRadius;
@@ -1682,6 +1740,11 @@
// Output data suitable for display (points and a bounding box)
if ($this->bIncludePolygonAsPoints)
{
$aPolyPoints = array();
for($f = 0; $f < 2*pi(); $f += $fStepSize)
{
$aPolyPoints[] = array('',$aResult['lon']+($fRadius*sin($f)),$aResult['lat']+($fRadius*cos($f)));
}
$aResult['aPolyPoints'] = array();
foreach($aPolyPoints as $aPoint)
{
@@ -1718,6 +1781,30 @@
}
}
if ($this->bIncludeExtraTags)
{
if ($aResult['extra'])
{
$aResult['sExtraTags'] = json_decode($aResult['extra']);
}
else
{
$aResult['sExtraTags'] = (object) array();
}
}
if ($this->bIncludeNameDetails)
{
if ($aResult['names'])
{
$aResult['sNameDetails'] = json_decode($aResult['names']);
}
else
{
$aResult['sNameDetails'] = (object) array();
}
}
// Adjust importance for the number of exact string matches in the result
$aResult['importance'] = max(0.001,$aResult['importance']);
$iCountWords = 0;
@@ -1727,7 +1814,7 @@
if (stripos($sAddress, $sWord)!==false)
{
$iCountWords++;
if (preg_match("/(^|,)\s*$sWord\s*(,|$)/", $sAddress)) $iCountWords += 0.1;
if (preg_match("/(^|,)\s*".preg_quote($sWord, '/')."\s*(,|$)/", $sAddress)) $iCountWords += 0.1;
}
}
@@ -1746,12 +1833,13 @@
if (isset($aClassType[$aResult['class'].':'.$aResult['type']]['importance'])
&& $aClassType[$aResult['class'].':'.$aResult['type']]['importance'])
{
$aResult['foundorder'] = $aResult['foundorder'] + 0.000001 * $aClassType[$aResult['class'].':'.$aResult['type']]['importance'];
$aResult['foundorder'] += 0.0001 * $aClassType[$aResult['class'].':'.$aResult['type']]['importance'];
}
else
{
$aResult['foundorder'] = $aResult['foundorder'] + 0.001;
$aResult['foundorder'] += 0.01;
}
if (CONST_Debug) { var_dump($aResult); }
$aSearchResults[$iResNum] = $aResult;
}
uasort($aSearchResults, 'byImportance');
@@ -1764,7 +1852,6 @@
$bFirst = true;
foreach($aToFilter as $iResNum => $aResult)
{
if ($aResult['type'] == 'adminitrative') $aResult['type'] = 'administrative';
$this->aExcludePlaceIDs[$aResult['place_id']] = $aResult['place_id'];
if ($bFirst)
{

View File

@@ -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();

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

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

@@ -6,3 +6,26 @@
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,6 +39,12 @@
exit;
}
function getParamBool($name, $default=false)
{
if (!isset($_GET[$name])) return $default;
return (bool) $_GET[$name];
}
function fail($sError, $sUserError = false)
{
@@ -193,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)
{
@@ -358,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',),
@@ -418,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',),
@@ -460,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'=>'',),
@@ -492,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,),
@@ -540,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'=>'',),
@@ -606,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'=>'',),
@@ -628,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'=>'',),
@@ -649,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']))
{
@@ -943,7 +970,7 @@
}
// degrees decimal seconds
// N 40 26 46 W 79 58 56
// 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))
{
@@ -994,4 +1021,4 @@
$sQuery = trim(str_replace($sFound, ' ', $sQuery));
return array('lat' => $fQueryLat, 'lon' => $fQueryLon, 'query' => $sQuery);
}
}

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 = [
'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, JSON_PRETTY_PRINT) . ';';
echo 'var nominatim_results = ' . json_encode([$aPlace], JSON_PRETTY_PRINT) . ';';
?>
</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,172 +1,212 @@
<?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>\n";
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>\n";
echo "<h2>Address</h2>\n";
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>\n";
return '';
}
echo "</div>\n";
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";
}
?>
<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>\n";
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">'.$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>';
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>\n";
_one_row($aAddressLine);
}
echo "</div>\n";
}
if ($aPlaceSearchNameKeywords)
{
echo '<h2>Name Keywords</h2>';
headline('Name Keywords');
foreach($aPlaceSearchNameKeywords as $aRow)
{
echo '<div>'.$aRow['word_token']."</div>\n";
@@ -175,52 +215,74 @@
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>\n";
}
}
if (sizeof($aParentOfLines))
{
echo "<h2>Parent Of:</h2>\n<div>\n";
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>\n";
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="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">'.$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>\n";
}
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 = [
'tile_url' => $sTileURL,
'tile_attribution' => $sTileAttribution
];
echo 'var nominatim_map_init = ' . json_encode($aNominatimMapInit, JSON_PRETTY_PRINT) . ';';
$aPlace = [
'outlinestring' => $aPointDetails['outlinestring'],
'lon' => $aPointDetails['lon'],
'lat' => $aPointDetails['lat'],
];
echo 'var nominatim_result = ' . json_encode($aPlace, JSON_PRETTY_PRINT) . ';';
?>
</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 ($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 = [
'zoom' => $iZoom,
'lat' => $fLat,
'lon' => $fLon,
'tile_url' => $sTileURL,
'tile_attribution' => $sTileAttribution
];
echo 'var nominatim_map_init = ' . json_encode($aNominatimMapInit, JSON_PRETTY_PRINT) . ';';
echo 'var nominatim_results = ' . json_encode($aSearchResults, JSON_PRETTY_PRINT) . ';';
?>
</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

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

@@ -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,

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

@@ -1,7 +1,7 @@
<?php
namespace Nominatim;
require 'lib/lib.php';
require '../lib/lib.php';
class NominatimTest extends \PHPUnit_Framework_TestCase
@@ -74,4 +74,78 @@ class NominatimTest extends \PHPUnit_Framework_TestCase
}
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) )
);
}
}

View File

@@ -6,7 +6,8 @@ https://phpunit.de/manual/4.2/en/
installed.
To execute the test suite run
$ phpunit
$ cd tests-php
$ phpunit ./
It will read phpunit.xml which points to the library, test path, bootstrap
strip and set other parameters.

View File

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

View File

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

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

View File

@@ -11,3 +11,53 @@ Feature: Reverse geocoding
| 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

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

View File

@@ -16,17 +16,17 @@ Feature: Search queries
Scenario: House number search for non-street address
Given the request parameters
| accept-language
| en
When sending json search query "4 Pomocnia, Poland" with address
Then address of result 0 is
| en
When sending json search query "4 Pomocnia, Pokrzywnica, Poland" with address
Then address of result 0 contains
| type | value
| house_number | 4
| suburb | Pomocnia
| county | gmina Pokrzywnica
| state | Masovian Voivodeship
| postcode | 06-121
| country | Poland
| country_code | pl
Then address of result 0 does not contain road
Scenario: House number interpolation even
Given the request parameters
@@ -36,7 +36,7 @@ Feature: Search queries
Then address of result 0 contains
| type | value
| house_number | 140
| road | rue Don Bosco
| road | [Rr]ue Don Bosco
| city | Saguenay
| state | Quebec
| country | Canada
@@ -50,16 +50,18 @@ Feature: Search queries
Then address of result 0 contains
| type | value
| house_number | 141
| road | rue Don Bosco
| 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
@@ -72,3 +74,9 @@ Feature: Search queries
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

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

View File

@@ -27,9 +27,9 @@ Feature: Search queries
Scenario: XML search with addressdetails
When sending xml search query "Inuvik" with address
Then address of result 0 is
Then address of result 0 contains
| type | value
| town | Inuvik
| city | Inuvik
| state | Northwest Territories
| country | Canada
| country_code | ca
@@ -41,7 +41,7 @@ Feature: Search queries
| 0 | leisure | hackerspace
And result addresses contain
| ID | address29
| 0 | foobar
| 0 | Chaospott
And address of result 0 does not contain leisure,hackerspace
Scenario: Disabling deduplication
@@ -70,7 +70,7 @@ Feature: Search queries
Then result addresses contain
| ID | city
| 0 | Chicago
Scenario: No POI search with unbounded viewbox
Given the request parameters
| viewbox
@@ -83,7 +83,7 @@ Feature: Search queries
Scenario: bounded search remains within viewbox, even with no results
Given the request parameters
| bounded | viewbox
| 1 | -5.662003,43.54285,-5.6563282,43.5403125
| 1 | 43.54285,-5.662003,43.5403125,-5.6563282
When sending json search query "restaurant"
Then less than 1 result is returned
@@ -170,3 +170,63 @@ Feature: Search queries
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

@@ -51,6 +51,10 @@ Feature: Simple Tests
| limit | 1000
| dedupe | 1
| dedupe | 0
| extratags | 1
| extratags | 0
| namedetails | 1
| namedetails | 0
Scenario: Search with invalid output format
Given the request parameters
@@ -166,6 +170,13 @@ Feature: Simple Tests
| attr | value
| exclude_place_ids | 123,76,342565
Scenario: Empty XML search with bad exluded place ids
Given the request parameters
| exclude_place_ids
| ,
When sending xml search query "jghrleoxsbwjer"
Then result header has no attribute exclude_place_ids
Scenario Outline: Wrapping of legal jsonp search requests
Given the request parameters
| json_callback

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -26,3 +26,17 @@ Feature: Creation of search terms
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,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,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

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

View File

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

View File

@@ -0,0 +1,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

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -27,17 +27,35 @@ def _parse_xml():
world.results = []
# results
if page.nodeName == 'searchresults':
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:
@@ -65,6 +83,21 @@ def _parse_xml():
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:
@@ -86,12 +119,14 @@ def api_result_is_valid(step, fmt):
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
# 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)
@@ -143,6 +178,11 @@ def api_result_header_contains(step):
assert_in(line['attr'], world.result_header)
m = re.match("%s$" % (line['value'],), world.result_header[line['attr']])
@step(u'result header has no attribute (.*)')
def api_result_header_contains_not(step, attr):
step.given('the result is valid')
assert_not_in(attr, world.result_header)
@step(u'results contain$')
def api_result_contains(step):
step.given('at least 1 result is returned')
@@ -194,7 +234,10 @@ def api_result_address_exact(step, resid):
addr = world.results[resid]['address']
for line in step.hashes:
assert_in(line['type'], addr)
assert_equals(line['value'], addr[line['type']])
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):

View File

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

View File

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

View File

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

View File

@@ -108,7 +108,7 @@ def _sort_xml_entries(x, y):
def write_osm_obj(fd, obj):
if obj['type'] == 'N':
fd.write('<node id="%(id)d" lat="%(lat).8f" lon="%(lon).8f" version="%(version)s" timestamp="%(timestamp)%" changeset="%(changeset)s" uid="%(uid)s" user="%(user)s"'% obj)
fd.write('<node id="%(id)d" lat="%(lat).8f" lon="%(lon).8f" version="%(version)s" timestamp="%(timestamp)s" changeset="%(changeset)s" uid="%(uid)s" user="%(user)s"'% obj)
if obj['tags'] is None:
fd.write('/>\n')
else:
@@ -140,7 +140,7 @@ def osm2pgsql_load_place(step):
world.osm2pgsql.sort(cmp=_sort_xml_entries)
# create a OSM file in /tmp
with tempfile.NamedTemporaryFile(dir='/tmp', delete=False) as fd:
with tempfile.NamedTemporaryFile(dir='/tmp', suffix='.osm', delete=False) as fd:
fname = fd.name
fd.write("<?xml version='1.0' encoding='UTF-8'?>\n")
fd.write('<osm version="0.6" generator="test-nominatim" timestamp="2014-08-26T20:22:02Z">\n')
@@ -154,7 +154,7 @@ def osm2pgsql_load_place(step):
logger.debug( "Filename: %s" % fname)
cmd = [os.path.join(world.config.source_dir, 'utils', 'setup.php')]
cmd.extend(['--osm-file', fname, '--import-data'])
cmd.extend(['--osm-file', fname, '--import-data','--osm2pgsql-cache', '300'])
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(outp, outerr) = proc.communicate()
assert (proc.returncode == 0), "OSM data import failed:\n%s\n%s\n" % (outp, outerr)
@@ -188,7 +188,7 @@ def osm2pgsql_update_place(step):
world.run_nominatim_script('setup', 'index', 'index-noanalyse')
world.run_nominatim_script('setup', 'create-functions', 'create-partition-functions', 'enable-diff-updates')
with tempfile.NamedTemporaryFile(dir='/tmp', delete=False) as fd:
with tempfile.NamedTemporaryFile(dir='/tmp', suffix='.osc', delete=False) as fd:
fname = fd.name
fd.write("<?xml version='1.0' encoding='UTF-8'?>\n")
fd.write('<osmChange version="0.6" generator="Osmosis 0.43.1">\n')

View File

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

View File

@@ -10,95 +10,20 @@
array('quiet', 'q', 0, 1, 0, 0, 'bool', 'Quiet output'),
array('verbose', 'v', 0, 1, 0, 0, 'bool', 'Verbose output'),
array('parse-tiger', '', 0, 1, 1, 1, 'realpath', 'Convert tiger edge files to nominatim sql import'),
array('parse-tiger-2011', '', 0, 1, 1, 1, 'realpath', 'Convert tiger edge files to nominatim sql import - datafiles from 2011 or later (source: edges directory of tiger data)'),
array('parse-tiger', '', 0, 1, 1, 1, 'realpath', 'Convert tiger edge files to nominatim sql import - datafiles from 2011 or later (source: edges directory of tiger data)'),
);
getCmdOpt($_SERVER['argv'], $aCMDOptions, $aCMDResult, true, true);
$bDidSomething = false;
if (isset($aCMDResult['parse-tiger']))
{
$bDidSomething = true;
foreach(glob($aCMDResult['parse-tiger'].'/??_*', GLOB_ONLYDIR) as $sStateFolder)
{
preg_match('#([0-9]{2})_(.*)#',basename($sStateFolder), $aMatch);
var_dump($aMatch);
exit;
foreach(glob($sStateFolder.'/?????_*', GLOB_ONLYDIR) as $sCountyFolder)
{
set_time_limit(30);
preg_match('#([0-9]{5})_(.*)#',basename($sCountyFolder), $aMatch);
$sCountyID = $aMatch[1];
$sCountyName = str_replace('_', ' ', $aMatch[2]);
$sImportFile = $sCountyFolder.'/tl_2009_'.$sCountyID.'_edges.zip';
$sCountyName = str_replace("'", "''", $sCountyName);
$sCountyName = str_replace(" County", "", $sCountyName);
echo "'$sCountyID' : '$sCountyName' ,\n";
}
}
exit;
if (!file_exists(CONST_BasePath.'/data/tiger2009')) mkdir(CONST_BasePath.'/data/tiger2009');
if (!file_exists(CONST_Tiger_Data_Path)) mkdir(CONST_Tiger_Data_Path);
$sTempDir = tempnam('/tmp', 'tiger');
unlink($sTempDir);
mkdir($sTempDir);
foreach(glob($aCMDResult['parse-tiger'].'/??_*', GLOB_ONLYDIR) as $sStateFolder)
{
foreach(glob($sStateFolder.'/?????_*', GLOB_ONLYDIR) as $sCountyFolder)
{
set_time_limit(30);
preg_match('#([0-9]{5})_(.*)#',basename($sCountyFolder), $aMatch);
$sCountyID = $aMatch[1];
$sCountyName = str_replace('_', ' ', $aMatch[2]);
$sImportFile = $sCountyFolder.'/tl_2009_'.$sCountyID.'_edges.zip';
echo "$sCountyID, $sCountyName\n";
if (!file_exists($sImportFile))
{
echo "Missing: $sImportFile\n";
}
$sUnzipCmd = "unzip -d $sTempDir $sImportFile";
exec($sUnzipCmd);
if (!file_exists($sTempDir.'/tl_2009_'.$sCountyID.'_edges.shp'))
{
echo "Failed unzip ($sCountyID)\n";
}
else
{
$sParseCmd = CONST_BasePath.'/utils/tigerAddressImport.py '.$sTempDir.'/tl_2009_'.$sCountyID.'_edges.shp';
exec($sParseCmd);
if (!file_exists($sTempDir.'/tl_2009_'.$sCountyID.'_edges.osm1.osm'))
{
echo "Failed parse ($sCountyID)\n";
}
else
{
copy($sTempDir.'/tl_2009_'.$sCountyID.'_edges.osm1.osm', CONST_BasePath.'/data/tiger2009/'.$sCountyID.'.sql');
}
}
// Cleanup
foreach(glob($sTempDir.'/*') as $sTmpFile)
{
unlink($sTmpFile);
}
}
}
}
if (isset($aCMDResult['parse-tiger-2011']))
{
if (!file_exists(CONST_BasePath.'/data/tiger2011')) mkdir(CONST_BasePath.'/data/tiger2011');
$sTempDir = tempnam('/tmp', 'tiger');
unlink($sTempDir);
mkdir($sTempDir);
$bDidSomething = true;
foreach(glob($aCMDResult['parse-tiger-2011'].'/tl_20??_?????_edges.zip', 0) as $sImportFile)
foreach(glob($aCMDResult['parse-tiger'].'/tl_20??_?????_edges.zip', 0) as $sImportFile)
{
set_time_limit(30);
preg_match('#([0-9]{5})_(.*)#',basename($sImportFile), $aMatch);
@@ -122,7 +47,7 @@
}
else
{
copy($sOsmFile, CONST_BasePath.'/data/tiger2011/'.$sCountyID.'.sql');
copy($sOsmFile, CONST_Tiger_Data_Path.'/'.$sCountyID.'.sql');
}
}
// Cleanup

View File

@@ -33,13 +33,13 @@
array('disable-token-precalc', '', 0, 1, 0, 0, 'bool', 'Disable name precalculation (EXPERT)'),
array('import-tiger-data', '', 0, 1, 0, 0, 'bool', 'Import tiger data (not included in \'all\')'),
array('calculate-postcodes', '', 0, 1, 0, 0, 'bool', 'Calculate postcode centroids'),
array('create-roads', '', 0, 1, 0, 0, 'bool', ''),
array('osmosis-init', '', 0, 1, 0, 0, 'bool', 'Generate default osmosis configuration'),
array('index', '', 0, 1, 0, 0, 'bool', 'Index the data'),
array('index-noanalyse', '', 0, 1, 0, 0, 'bool', 'Do not perform analyse operations during index (EXPERT)'),
array('index-output', '', 0, 1, 1, 1, 'string', 'File to dump index information to'),
array('create-search-indices', '', 0, 1, 0, 0, 'bool', 'Create additional indices required for search and update'),
array('create-website', '', 0, 1, 1, 1, 'realpath', 'Create symlinks to setup web directory'),
array('drop', '', 0, 1, 0, 0, 'bool', 'Drop tables needed for updates, making the database readonly (EXPERIMENTAL)'),
);
getCmdOpt($_SERVER['argv'], $aCMDOptions, $aCMDResult, true, true);
@@ -79,16 +79,20 @@
}
// Assume we can steal all the cache memory in the box (unless told otherwise)
$iCacheMemory = (isset($aCMDResult['osm2pgsql-cache'])?$aCMDResult['osm2pgsql-cache']:getCacheMemoryMB());
if ($iCacheMemory > getTotalMemoryMB())
if (isset($aCMDResult['osm2pgsql-cache']))
{
$iCacheMemory = $aCMDResult['osm2pgsql-cache'];
}
else
{
$iCacheMemory = getCacheMemoryMB();
echo "WARNING: resetting cache memory to $iCacheMemory\n";
}
$aDSNInfo = DB::parseDSN(CONST_Database_DSN);
if (!isset($aDSNInfo['port']) || !$aDSNInfo['port']) $aDSNInfo['port'] = 5432;
$fPostgisVersion = (float) CONST_Postgis_Version;
if ($aCMDResult['create-db'] || $aCMDResult['all'])
{
echo "Create DB\n";
@@ -126,12 +130,11 @@
pgsqlRunScript('CREATE EXTENSION hstore');
}
$fPostgisVersion = (float) CONST_Postgis_Version;
if ($fPostgisVersion < 2.0) {
pgsqlRunScriptFile(CONST_Path_Postgresql_Postgis.'/postgis.sql');
pgsqlRunScriptFile(CONST_Path_Postgresql_Postgis.'/spatial_ref_sys.sql');
} else {
pgsqlRunScript('CREATE EXTENSION postgis');
pgsqlRunScript('CREATE EXTENSION IF NOT EXISTS postgis');
}
if ($fPostgisVersion < 2.1) {
// Function was renamed in 2.1 and throws an annoying deprecation warning
@@ -190,7 +193,15 @@
{
$osm2pgsql .= ' --flat-nodes '.CONST_Osm2pgsql_Flatnode_File;
}
$osm2pgsql .= ' -lsc -O gazetteer --hstore';
if (CONST_Tablespace_Osm2pgsql_Data)
$osm2pgsql .= ' --tablespace-slim-data '.CONST_Tablespace_Osm2pgsql_Data;
if (CONST_Tablespace_Osm2pgsql_Index)
$osm2pgsql .= ' --tablespace-slim-index '.CONST_Tablespace_Osm2pgsql_Index;
if (CONST_Tablespace_Place_Data)
$osm2pgsql .= ' --tablespace-main-data '.CONST_Tablespace_Place_Data;
if (CONST_Tablespace_Place_Index)
$osm2pgsql .= ' --tablespace-main-index '.CONST_Tablespace_Place_Index;
$osm2pgsql .= ' -lsc -O gazetteer --hstore --number-processes 1';
$osm2pgsql .= ' -C '.$iCacheMemory;
$osm2pgsql .= ' -P '.$aDSNInfo['port'];
$osm2pgsql .= ' -d '.$aDSNInfo['database'].' '.$aCMDResult['osm-file'];
@@ -215,6 +226,15 @@
if ($aCMDResult['enable-debug-statements']) $sTemplate = str_replace('--DEBUG:', '', $sTemplate);
if (CONST_Limit_Reindexing) $sTemplate = str_replace('--LIMIT INDEXING:', '', $sTemplate);
pgsqlRunScript($sTemplate);
if ($fPostgisVersion < 2.0) {
echo "Helper functions for postgis < 2.0\n";
$sTemplate = file_get_contents(CONST_BasePath.'/sql/postgis_15_aux.sql');
} else {
echo "Helper functions for postgis >= 2.0\n";
$sTemplate = file_get_contents(CONST_BasePath.'/sql/postgis_20_aux.sql');
}
pgsqlRunScript($sTemplate);
}
if ($aCMDResult['create-minimal-tables'])
@@ -249,13 +269,30 @@
if ($aCMDResult['create-tables'] || $aCMDResult['all'])
{
echo "Tables\n";
$bDidSomething = true;
pgsqlRunScriptFile(CONST_BasePath.'/sql/tables.sql');
echo "Tables\n";
$sTemplate = file_get_contents(CONST_BasePath.'/sql/tables.sql');
$sTemplate = str_replace('{www-user}', CONST_Database_Web_User, $sTemplate);
$sTemplate = replace_tablespace('{ts:address-data}',
CONST_Tablespace_Address_Data, $sTemplate);
$sTemplate = replace_tablespace('{ts:address-index}',
CONST_Tablespace_Address_Index, $sTemplate);
$sTemplate = replace_tablespace('{ts:search-data}',
CONST_Tablespace_Search_Data, $sTemplate);
$sTemplate = replace_tablespace('{ts:search-index}',
CONST_Tablespace_Search_Index, $sTemplate);
$sTemplate = replace_tablespace('{ts:aux-data}',
CONST_Tablespace_Aux_Data, $sTemplate);
$sTemplate = replace_tablespace('{ts:aux-index}',
CONST_Tablespace_Aux_Index, $sTemplate);
pgsqlRunScript($sTemplate, false);
// re-run the functions
echo "Functions\n";
$sTemplate = file_get_contents(CONST_BasePath.'/sql/functions.sql');
$sTemplate = str_replace('{modulepath}',CONST_BasePath.'/module', $sTemplate);
$sTemplate = str_replace('{modulepath}',
CONST_BasePath.'/module', $sTemplate);
pgsqlRunScript($sTemplate);
}
@@ -273,6 +310,18 @@
if (!$aCMDResult['no-partitions']) $aPartitions[] = 0;
$sTemplate = file_get_contents(CONST_BasePath.'/sql/partition-tables.src.sql');
$sTemplate = replace_tablespace('{ts:address-data}',
CONST_Tablespace_Address_Data, $sTemplate);
$sTemplate = replace_tablespace('{ts:address-index}',
CONST_Tablespace_Address_Index, $sTemplate);
$sTemplate = replace_tablespace('{ts:search-data}',
CONST_Tablespace_Search_Data, $sTemplate);
$sTemplate = replace_tablespace('{ts:search-index}',
CONST_Tablespace_Search_Index, $sTemplate);
$sTemplate = replace_tablespace('{ts:aux-data}',
CONST_Tablespace_Aux_Data, $sTemplate);
$sTemplate = replace_tablespace('{ts:aux-index}',
CONST_Tablespace_Aux_Index, $sTemplate);
preg_match_all('#^-- start(.*?)^-- end#ms', $sTemplate, $aMatches, PREG_SET_ORDER);
foreach($aMatches as $aMatch)
{
@@ -420,40 +469,17 @@
pgsqlRunScript('ANALYSE');
}
if ($aCMDResult['create-roads'])
{
$bDidSomething = true;
$oDB =& getDB();
$aDBInstances = array();
for($i = 0; $i < $iInstances; $i++)
{
$aDBInstances[$i] =& getDB(true);
if (!pg_query($aDBInstances[$i]->connection, 'set enable_bitmapscan = off')) fail(pg_last_error($oDB->connection));
$sSQL = 'select count(*) from (select insertLocationRoad(partition, place_id, calculated_country_code, geometry) from ';
$sSQL .= 'placex where osm_id % '.$iInstances.' = '.$i.' and rank_search between 26 and 27 and class = \'highway\') as x ';
if ($aCMDResult['verbose']) echo "$sSQL\n";
if (!pg_send_query($aDBInstances[$i]->connection, $sSQL)) fail(pg_last_error($oDB->connection));
}
$bAnyBusy = true;
while($bAnyBusy)
{
$bAnyBusy = false;
for($i = 0; $i < $iInstances; $i++)
{
if (pg_connection_busy($aDBInstances[$i]->connection)) $bAnyBusy = true;
}
sleep(1);
echo '.';
}
echo "\n";
}
if ($aCMDResult['import-tiger-data'])
{
$bDidSomething = true;
pgsqlRunScriptFile(CONST_BasePath.'/sql/tiger_import_start.sql');
$sTemplate = file_get_contents(CONST_BasePath.'/sql/tiger_import_start.sql');
$sTemplate = str_replace('{www-user}', CONST_Database_Web_User, $sTemplate);
$sTemplate = replace_tablespace('{ts:aux-data}',
CONST_Tablespace_Aux_Data, $sTemplate);
$sTemplate = replace_tablespace('{ts:aux-index}',
CONST_Tablespace_Aux_Index, $sTemplate);
pgsqlRunScript($sTemplate, false);
$aDBInstances = array();
for($i = 0; $i < $iInstances; $i++)
@@ -461,7 +487,7 @@
$aDBInstances[$i] =& getDB(true);
}
foreach(glob(CONST_BasePath.'/data/tiger2011/*.sql') as $sFile)
foreach(glob(CONST_Tiger_Data_Path.'/*.sql') as $sFile)
{
echo $sFile.': ';
$hFile = fopen($sFile, "r");
@@ -505,7 +531,13 @@
}
echo "Creating indexes\n";
pgsqlRunScriptFile(CONST_BasePath.'/sql/tiger_import_finish.sql');
$sTemplate = file_get_contents(CONST_BasePath.'/sql/tiger_import_finish.sql');
$sTemplate = str_replace('{www-user}', CONST_Database_Web_User, $sTemplate);
$sTemplate = replace_tablespace('{ts:aux-data}',
CONST_Tablespace_Aux_Data, $sTemplate);
$sTemplate = replace_tablespace('{ts:aux-index}',
CONST_Tablespace_Aux_Index, $sTemplate);
pgsqlRunScript($sTemplate, false);
}
if ($aCMDResult['calculate-postcodes'] || $aCMDResult['all'])
@@ -526,7 +558,7 @@
if (!pg_query($oDB->connection, $sSQL)) fail(pg_last_error($oDB->connection));
}
if ($aCMDResult['osmosis-init'] || $aCMDResult['all'])
if ($aCMDResult['osmosis-init'] || ($aCMDResult['all'] && !$aCMDResult['drop'])) // no use doing osmosis-init when dropping update tables
{
$bDidSomething = true;
$oDB =& getDB();
@@ -554,7 +586,7 @@
}
// Find the last node in the DB
$iLastOSMID = $oDB->getOne("select max(id) from planet_osm_nodes");
$iLastOSMID = $oDB->getOne("select max(osm_id) from place where osm_type = 'N'");
// Lookup the timestamp that node was created (less 3 hours for margin for changsets to be closed)
$sLastNodeURL = 'http://www.openstreetmap.org/api/0.6/node/'.$iLastOSMID."/1";
@@ -647,6 +679,12 @@
if (!$aCMDResult['no-partitions']) $aPartitions[] = 0;
$sTemplate = file_get_contents(CONST_BasePath.'/sql/indices.src.sql');
$sTemplate = replace_tablespace('{ts:address-index}',
CONST_Tablespace_Address_Index, $sTemplate);
$sTemplate = replace_tablespace('{ts:search-index}',
CONST_Tablespace_Search_Index, $sTemplate);
$sTemplate = replace_tablespace('{ts:aux-index}',
CONST_Tablespace_Aux_Index, $sTemplate);
preg_match_all('#^-- start(.*?)^-- end#ms', $sTemplate, $aMatches, PREG_SET_ORDER);
foreach($aMatches as $aMatch)
{
@@ -675,6 +713,7 @@
@symlink(CONST_BasePath.'/website/reverse.php', $sTargetDir.'/reverse.php');
@symlink(CONST_BasePath.'/website/search.php', $sTargetDir.'/search.php');
@symlink(CONST_BasePath.'/website/search.php', $sTargetDir.'/index.php');
@symlink(CONST_BasePath.'/website/lookup.php', $sTargetDir.'/lookup.php');
@symlink(CONST_BasePath.'/website/deletable.php', $sTargetDir.'/deletable.php');
@symlink(CONST_BasePath.'/website/polygons.php', $sTargetDir.'/polygons.php');
@symlink(CONST_BasePath.'/website/status.php', $sTargetDir.'/status.php');
@@ -691,6 +730,69 @@
}
}
if ($aCMDResult['drop'])
{
// The implementation is potentially a bit dangerous because it uses
// a positive selection of tables to keep, and deletes everything else.
// Including any tables that the unsuspecting user might have manually
// created. USE AT YOUR OWN PERIL.
$bDidSomething = true;
// tables we want to keep. everything else goes.
$aKeepTables = array(
"*columns",
"import_polygon_*",
"import_status",
"place_addressline",
"location_property*",
"placex",
"search_name",
"seq_*",
"word",
"query_log",
"new_query_log",
"gb_postcode",
"spatial_ref_sys",
"country_name",
"place_classtype_*"
);
$oDB =& getDB();
$aDropTables = array();
$aHaveTables = $oDB->getCol("SELECT tablename FROM pg_tables WHERE schemaname='public'");
if (PEAR::isError($aHaveTables))
{
fail($aPartitions->getMessage());
}
foreach($aHaveTables as $sTable)
{
$bFound = false;
foreach ($aKeepTables as $sKeep)
{
if (fnmatch($sKeep, $sTable))
{
$bFound = true;
break;
}
}
if (!$bFound) array_push($aDropTables, $sTable);
}
foreach ($aDropTables as $sDrop)
{
if ($aCMDResult['verbose']) echo "dropping table $sDrop\n";
@pg_query($oDB->connection, "DROP TABLE $sDrop CASCADE");
// ignore warnings/errors as they might be caused by a table having
// been deleted already by CASCADE
}
if (!is_null(CONST_Osm2pgsql_Flatnode_File))
{
if ($aCMDResult['verbose']) echo "deleting ".CONST_Osm2pgsql_Flatnode_File."\n";
unlink(CONST_Osm2pgsql_Flatnode_File);
}
}
if (!$bDidSomething)
{
showUsage($aCMDOptions, true);
@@ -758,14 +860,14 @@
}
function pgsqlRunScript($sScript)
function pgsqlRunScript($sScript, $bfatal = true)
{
global $aCMDResult;
// Convert database DSN to psql parameters
$aDSNInfo = DB::parseDSN(CONST_Database_DSN);
if (!isset($aDSNInfo['port']) || !$aDSNInfo['port']) $aDSNInfo['port'] = 5432;
$sCMD = 'psql -p '.$aDSNInfo['port'].' -d '.$aDSNInfo['database'];
if (!$aCMDResult['ignore-errors'])
if ($bfatal && !$aCMDResult['ignore-errors'])
$sCMD .= ' -v ON_ERROR_STOP=1';
$aDescriptors = array(
0 => array('pipe', 'r'),
@@ -784,7 +886,7 @@
}
fclose($ahPipes[0]);
$iReturn = proc_close($hProcess);
if ($iReturn > 0)
if ($bfatal && $iReturn > 0)
{
fail("pgsql returned with error code ($iReturn)");
}
@@ -852,3 +954,15 @@
passthru($cmd, $result);
if ($result != 0) fail('Error executing external command: '.$cmd);
}
function replace_tablespace($sTemplate, $sTablespace, $sSql)
{
if ($sTablespace)
$sSql = str_replace($sTemplate, 'TABLESPACE "'.$sTablespace.'"',
$sSql);
else
$sSql = str_replace($sTemplate, '', $sSql);
return $sSql;
}

View File

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

View File

@@ -197,32 +197,33 @@ county_fips = {
'02013' : 'Aleutians East, AK' ,
'02016' : 'Aleutians West, AK' ,
'02020' : 'Anchorage, AK' ,
'02230' : 'Skagway Municipality' ,
'02050' : 'Bethel, AK' ,
'02060' : 'Bristol Bay, AK' ,
'02068' : 'Denali, AK' ,
'02070' : 'Dillingham, AK' ,
'02090' : 'Fairbanks North Star, AK' ,
'02100' : 'Haines, AK' ,
'02105' : 'Hoonah-Angoon Census Area' ,
'02105' : 'Hoonah-Angoon Census Area, AK' ,
'02110' : 'Juneau, AK' ,
'02122' : 'Kenai Peninsula, AK' ,
'02130' : 'Ketchikan Gateway, AK' ,
'02150' : 'Kodiak Island, AK' ,
'02158' : 'Kusilvak Census Area, AK' ,
'02164' : 'Lake and Peninsula, AK' ,
'02170' : 'Matanuska-Susitna, AK' ,
'02180' : 'Nome, AK' ,
'02185' : 'North Slope, AK' ,
'02188' : 'Northwest Arctic, AK' ,
'02195' : 'Petersburg Census Area' ,
'02198' : 'Prince of Wales-Hyder Census Area' ,
'02195' : 'Petersburg, AK' ,
'02198' : 'Prince of Wales-Hyder Census Area, AK' ,
'02201' : 'Prince of Wales-Outer Ketchikan, AK' ,
'02220' : 'Sitka, AK' ,
'02230' : 'Skagway, AK' ,
'02232' : 'Skagway-Hoonah-Angoon, AK' ,
'02240' : 'Southeast Fairbanks, AK' ,
'02261' : 'Valdez-Cordova, AK' ,
'02270' : 'Wade Hampton, AK' ,
'02275' : 'Wrangell City and Borough' ,
'02275' : 'Wrangell City and Borough, AK' ,
'02280' : 'Wrangell-Petersburg, AK' ,
'02282' : 'Yakutat, AK' ,
'02290' : 'Yukon-Koyukuk, AK' ,
@@ -786,7 +787,7 @@ county_fips = {
'17093' : 'Kendall, IL' ,
'17095' : 'Knox, IL' ,
'17097' : 'Lake, IL' ,
'17099' : 'La Salle, IL' ,
'17099' : 'LaSalle, IL' ,
'17101' : 'Lawrence, IL' ,
'17103' : 'Lee, IL' ,
'17105' : 'Livingston, IL' ,
@@ -1289,7 +1290,7 @@ county_fips = {
'22053' : 'Jefferson Davis, LA' ,
'22055' : 'Lafayette, LA' ,
'22057' : 'Lafourche, LA' ,
'22059' : 'La Salle, LA' ,
'22059' : 'LaSalle, LA' ,
'22061' : 'Lincoln, LA' ,
'22063' : 'Livingston, LA' ,
'22065' : 'Madison, LA' ,
@@ -1365,7 +1366,7 @@ county_fips = {
'24043' : 'Washington, MD' ,
'24045' : 'Wicomico, MD' ,
'24047' : 'Worcester, MD' ,
'24510' : 'Baltimore city, MD' ,
'24510' : 'Baltimore City, MD' ,
'25000' : 'MASSACHUSETTS' ,
'25001' : 'Barnstable, MA' ,
'25003' : 'Berkshire, MA' ,
@@ -1751,7 +1752,7 @@ county_fips = {
'29225' : 'Webster, MO' ,
'29227' : 'Worth, MO' ,
'29229' : 'Wright, MO' ,
'29510' : 'St. Louis city, MO' ,
'29510' : 'St. Louis City, MO' ,
'30000' : 'MONTANA' ,
'30001' : 'Beaverhead, MT' ,
'30003' : 'Big Horn, MT' ,
@@ -1921,7 +1922,7 @@ county_fips = {
'32029' : 'Storey, NV' ,
'32031' : 'Washoe, NV' ,
'32033' : 'White Pine, NV' ,
'32510' : 'Carson City city, NV' ,
'32510' : 'Carson City, NV' ,
'33000' : 'NEW HAMPSHIRE' ,
'33001' : 'Belknap, NH' ,
'33003' : 'Carroll, NH' ,
@@ -2583,6 +2584,7 @@ county_fips = {
'46097' : 'Miner, SD' ,
'46099' : 'Minnehaha, SD' ,
'46101' : 'Moody, SD' ,
'46102' : 'Oglala Lakota, SD' ,
'46103' : 'Pennington, SD' ,
'46105' : 'Perkins, SD' ,
'46107' : 'Potter, SD' ,
@@ -3326,97 +3328,97 @@ county_fips = {
'56043' : 'Washakie, WY' ,
'56045' : 'Weston, WY' ,
'60000' : 'AMERICAN SAMOA',
'60010' : 'Eastern district, AS' ,
'60020' : 'Manua district, AS' ,
'60030' : 'Rose island, AS' ,
'60040' : 'Swains island, AS' ,
'60050' : 'Western district, AS' ,
'60010' : 'Eastern District, AS' ,
'60020' : 'Manu\'a District, AS' ,
'60030' : 'Rose Island, AS' ,
'60040' : 'Swains Island, AS' ,
'60050' : 'Western District, AS' ,
'66000' : 'GUAM' ,
'66010' : 'Guam, GU' ,
'69000' : 'COMMONWEALTH OF THE NORTHERN MARIANA ISLANDS' ,
'69085' : 'Commonwealth of the Northern Mariana Islands, MP' ,
'69100' : 'Commonwealth of the Northern Mariana Islands, MP' ,
'69110' : 'Commonwealth of the Northern Mariana Islands, MP' ,
'69120' : 'Commonwealth of the Northern Mariana Islands, MP' ,
'72000' : 'PUERTO RICO',
'72001' : 'Adjuntas, PR',
'72003' : 'Aguada, PR',
'72005' : 'Aguadilla, PR',
'72007' : 'Aguas Buenas, PR',
'72009' : 'Aibonito, PR',
'72011' : 'Anasco, PR',
'72013' : 'Arecibo, PR',
'72015' : 'Arroyo, PR',
'72017' : 'Barceloneta, PR',
'72019' : 'Barranquitas, PR',
'72021' : 'Bayamon, PR',
'72023' : 'Cabo Rojo, PR',
'72025' : 'Caguas, PR',
'72027' : 'Camuy, PR',
'72029' : 'Canovanas, PR',
'72031' : 'Carolina, PR',
'72033' : 'Catano, PR',
'72035' : 'Cayey, PR',
'72037' : 'Ceiba, PR',
'72039' : 'Ciales, PR',
'72041' : 'Cidra, PR',
'72043' : 'Coamo, PR',
'72045' : 'Comerio, PR',
'72047' : 'Corozal, PR',
'72049' : 'Culebra, PR',
'72051' : 'Dorado, PR',
'72053' : 'Fajardo, PR',
'72054' : 'Florida, PR',
'72055' : 'Guanica, PR',
'72057' : 'Guayama, PR',
'72059' : 'Guayanilla, PR',
'72061' : 'Guaynabo, PR',
'72063' : 'Gurabo, PR',
'72065' : 'Hatillo, PR',
'72067' : 'Hormigueros, PR',
'72069' : 'Humacao, PR',
'72071' : 'Isabela, PR',
'72073' : 'Jayuya, PR',
'72075' : 'Juana Diaz, PR',
'72077' : 'Juncos, PR',
'72079' : 'Lajas, PR',
'72081' : 'Lares, PR',
'72083' : 'Las Marias, PR',
'72085' : 'Las Piedras, PR',
'72087' : 'Loiza, PR',
'72089' : 'Luquillo, PR',
'72091' : 'Manati, PR',
'72093' : 'Maricao, PR',
'72095' : 'Maunabo, PR',
'72097' : 'Mayaguez, PR',
'72099' : 'Moca, PR',
'72101' : 'Morovis, PR',
'72103' : 'Naguabo, PR',
'72105' : 'Naranjito, PR',
'72107' : 'Orocovis, PR',
'72109' : 'Patillas, PR',
'72111' : 'Penuelas, PR',
'72113' : 'Ponce, PR',
'72115' : 'Quebradillas, PR',
'72117' : 'Rincon, PR',
'72119' : 'Rio Grande, PR',
'72121' : 'Sabana Grande, PR',
'72123' : 'Salinas, PR',
'72125' : 'San German, PR',
'72127' : 'San Juan, PR',
'72129' : 'San Lorenzo, PR',
'72131' : 'San Sebastian, PR',
'72133' : 'Santa Isabel, PR',
'72135' : 'Toa Alta, PR',
'72137' : 'Toa Baja, PR',
'72139' : 'Trujillo Alto, PR',
'72141' : 'Utuado, PR',
'72143' : 'Vega Alta, PR',
'72145' : 'Vega Baja, PR',
'72147' : 'Vieques, PR',
'72149' : 'Villalba, PR',
'72151' : 'Yabucoa, PR',
'72153' : 'Yauco, PR',
'69085' : 'Northern Islands, MP' ,
'69100' : 'Rota, MP' ,
'69110' : 'Saipan, MP' ,
'69120' : 'Tinian, MP' ,
'72000' : 'PUERTO RICO' ,
'72001' : 'Adjuntas, PR' ,
'72003' : 'Aguada, PR' ,
'72005' : 'Aguadilla, PR' ,
'72007' : 'Aguas Buenas, PR' ,
'72009' : 'Aibonito, PR' ,
'72011' : 'Anasco, PR' ,
'72013' : 'Arecibo, PR' ,
'72015' : 'Arroyo, PR' ,
'72017' : 'Barceloneta, PR' ,
'72019' : 'Barranquitas, PR' ,
'72021' : 'Bayamon, PR' ,
'72023' : 'Cabo Rojo, PR' ,
'72025' : 'Caguas, PR' ,
'72027' : 'Camuy, PR' ,
'72029' : 'Canovanas, PR' ,
'72031' : 'Carolina, PR' ,
'72033' : 'Catano, PR' ,
'72035' : 'Cayey, PR' ,
'72037' : 'Ceiba, PR' ,
'72039' : 'Ciales, PR' ,
'72041' : 'Cidra, PR' ,
'72043' : 'Coamo, PR' ,
'72045' : 'Comerio, PR' ,
'72047' : 'Corozal, PR' ,
'72049' : 'Culebra, PR' ,
'72051' : 'Dorado, PR' ,
'72053' : 'Fajardo, PR' ,
'72054' : 'Florida, PR' ,
'72055' : 'Guanica, PR' ,
'72057' : 'Guayama, PR' ,
'72059' : 'Guayanilla, PR' ,
'72061' : 'Guaynabo, PR' ,
'72063' : 'Gurabo, PR' ,
'72065' : 'Hatillo, PR' ,
'72067' : 'Hormigueros, PR' ,
'72069' : 'Humacao, PR' ,
'72071' : 'Isabela, PR' ,
'72073' : 'Jayuya, PR' ,
'72075' : 'Juana Diaz, PR' ,
'72077' : 'Juncos, PR' ,
'72079' : 'Lajas, PR' ,
'72081' : 'Lares, PR' ,
'72083' : 'Las Marias, PR' ,
'72085' : 'Las Piedras, PR' ,
'72087' : 'Loiza, PR' ,
'72089' : 'Luquillo, PR' ,
'72091' : 'Manati, PR' ,
'72093' : 'Maricao, PR' ,
'72095' : 'Maunabo, PR' ,
'72097' : 'Mayaguez, PR' ,
'72099' : 'Moca, PR' ,
'72101' : 'Morovis, PR' ,
'72103' : 'Naguabo, PR' ,
'72105' : 'Naranjito, PR' ,
'72107' : 'Orocovis, PR' ,
'72109' : 'Patillas, PR' ,
'72111' : 'Penuelas, PR' ,
'72113' : 'Ponce, PR' ,
'72115' : 'Quebradillas, PR' ,
'72117' : 'Rincon, PR' ,
'72119' : 'Rio Grande, PR' ,
'72121' : 'Sabana Grande, PR' ,
'72123' : 'Salinas, PR' ,
'72125' : 'San German, PR' ,
'72127' : 'San Juan, PR' ,
'72129' : 'San Lorenzo, PR' ,
'72131' : 'San Sebastian, PR' ,
'72133' : 'Santa Isabel, PR' ,
'72135' : 'Toa Alta, PR' ,
'72137' : 'Toa Baja, PR' ,
'72139' : 'Trujillo Alto, PR' ,
'72141' : 'Utuado, PR' ,
'72143' : 'Vega Alta, PR' ,
'72145' : 'Vega Baja, PR' ,
'72147' : 'Vieques, PR' ,
'72149' : 'Villalba, PR' ,
'72151' : 'Yabucoa, PR' ,
'72153' : 'Yauco, PR' ,
'78000' : 'VIRGIN ISLANDS' ,
'78010' : 'St. Croix, VI' ,
'78020' : 'St. John, VI' ,
@@ -3433,7 +3435,7 @@ def fipsstate(fips,countyfp):
return tags
if fips not in fipscodes:
raise KeyError, 'missing FIPS code', fips
raise KeyError('missing FIPS code', fips)
state, statecode, isocode = fipscodes[fips]
county_fips_code = fips + "" + countyfp
@@ -3478,69 +3480,69 @@ def parse_shp_for_osm( filename ):
# WAY ID
tags[iSource + ":way_id"] = int( poFeature.GetField("TLID") )
# FEATURE IDENTIFICATION
# FEATURE IDENTIFICATION
mtfcc = poFeature.GetField("MTFCC");
if mtfcc != None:
if mtfcc == "L4010": #Pipeline
tags["man_made"] = "pipeline"
if mtfcc == "L4020": #Powerline
tags["power"] = "line"
if mtfcc == "L4031": #Aerial Tramway/Ski Lift
tags["aerialway"] = "cable_car"
if mtfcc == "L4110": #Fence Line
tags["barrier"] = "fence"
if mtfcc == "L4125": #Cliff/Escarpment
tags["natural"] = "cliff"
if mtfcc == "L4165": #Ferry Crossing
tags["route"] = "ferry"
if mtfcc == "R1011": #Railroad Feature (Main, Spur, or Yard)
tags["railway"] = "rail"
ttyp = poFeature.GetField("TTYP")
if ttyp != None:
if ttyp == "S":
tags["service"] = "spur"
if ttyp == "Y":
tags["service"] = "yard"
tags["tiger:ttyp"] = ttyp
if mtfcc == "R1051": #Carline, Streetcar Track, Monorail, Other Mass Transit Rail)
tags["railway"] = "light_rail"
if mtfcc == "R1052": #Cog Rail Line, Incline Rail Line, Tram
tags["railway"] = "incline"
if mtfcc == "S1100":
tags["highway"] = "primary"
if mtfcc == "S1200":
tags["highway"] = "secondary"
if mtfcc == "S1400":
tags["highway"] = "residential"
if mtfcc == "S1500":
tags["highway"] = "track"
if mtfcc == "S1630": #Ramp
tags["highway"] = "motorway_link"
if mtfcc == "S1640": #Service Drive usually along a limited access highway
tags["highway"] = "service"
if mtfcc == "S1710": #Walkway/Pedestrian Trail
tags["highway"] = "path"
if mtfcc == "S1720":
tags["highway"] = "steps"
if mtfcc == "S1730": #Alley
tags["highway"] = "service"
tags["service"] = "alley"
if mtfcc == "S1740": #Private Road for service vehicles (logging, oil, fields, ranches, etc.)
tags["highway"] = "service"
tags["access"] = "private"
if mtfcc == "S1750": #Private Driveway
tags["highway"] = "service"
tags["access"] = "private"
tags["service"] = "driveway"
if mtfcc == "S1780": #Parking Lot Road
tags["highway"] = "service"
tags["service"] = "parking_aisle"
if mtfcc == "S1820": #Bike Path or Trail
tags["highway"] = "cycleway"
if mtfcc == "S1830": #Bridle Path
tags["highway"] = "bridleway"
tags["tiger:mtfcc"] = mtfcc
if mtfcc == "L4010": #Pipeline
tags["man_made"] = "pipeline"
if mtfcc == "L4020": #Powerline
tags["power"] = "line"
if mtfcc == "L4031": #Aerial Tramway/Ski Lift
tags["aerialway"] = "cable_car"
if mtfcc == "L4110": #Fence Line
tags["barrier"] = "fence"
if mtfcc == "L4125": #Cliff/Escarpment
tags["natural"] = "cliff"
if mtfcc == "L4165": #Ferry Crossing
tags["route"] = "ferry"
if mtfcc == "R1011": #Railroad Feature (Main, Spur, or Yard)
tags["railway"] = "rail"
ttyp = poFeature.GetField("TTYP")
if ttyp != None:
if ttyp == "S":
tags["service"] = "spur"
if ttyp == "Y":
tags["service"] = "yard"
tags["tiger:ttyp"] = ttyp
if mtfcc == "R1051": #Carline, Streetcar Track, Monorail, Other Mass Transit Rail)
tags["railway"] = "light_rail"
if mtfcc == "R1052": #Cog Rail Line, Incline Rail Line, Tram
tags["railway"] = "incline"
if mtfcc == "S1100":
tags["highway"] = "primary"
if mtfcc == "S1200":
tags["highway"] = "secondary"
if mtfcc == "S1400":
tags["highway"] = "residential"
if mtfcc == "S1500":
tags["highway"] = "track"
if mtfcc == "S1630": #Ramp
tags["highway"] = "motorway_link"
if mtfcc == "S1640": #Service Drive usually along a limited access highway
tags["highway"] = "service"
if mtfcc == "S1710": #Walkway/Pedestrian Trail
tags["highway"] = "path"
if mtfcc == "S1720":
tags["highway"] = "steps"
if mtfcc == "S1730": #Alley
tags["highway"] = "service"
tags["service"] = "alley"
if mtfcc == "S1740": #Private Road for service vehicles (logging, oil, fields, ranches, etc.)
tags["highway"] = "service"
tags["access"] = "private"
if mtfcc == "S1750": #Private Driveway
tags["highway"] = "service"
tags["access"] = "private"
tags["service"] = "driveway"
if mtfcc == "S1780": #Parking Lot Road
tags["highway"] = "service"
tags["service"] = "parking_aisle"
if mtfcc == "S1820": #Bike Path or Trail
tags["highway"] = "cycleway"
if mtfcc == "S1830": #Bridle Path
tags["highway"] = "bridleway"
tags["tiger:mtfcc"] = mtfcc
# FEATURE NAME
if poFeature.GetField("FULLNAME"):
@@ -3548,20 +3550,20 @@ def parse_shp_for_osm( filename ):
name = poFeature.GetField( "FULLNAME" )
tags["name"] = name
#Attempt to guess highway grade
if name[0:2] == "I-":
tags["highway"] = "motorway"
if name[0:3] == "US ":
tags["highway"] = "primary"
if name[0:3] == "US-":
tags["highway"] = "primary"
if name[0:3] == "Hwy":
if tags["highway"] != "primary":
tags["highway"] = "secondary"
#Attempt to guess highway grade
if name[0:2] == "I-":
tags["highway"] = "motorway"
if name[0:3] == "US ":
tags["highway"] = "primary"
if name[0:3] == "US-":
tags["highway"] = "primary"
if name[0:3] == "Hwy":
if tags["highway"] != "primary":
tags["highway"] = "secondary"
divroad = poFeature.GetField("DIVROAD")
if divroad != None:
if divroad == "Y" and "highway" in tags and tags["highway"] == "residential":
if divroad == "Y" and "highway" in tags and tags["highway"] == "residential":
tags["highway"] = "tertiary"
tags["tiger:separated"] = divroad
@@ -3618,10 +3620,10 @@ def parse_shp_for_osm( filename ):
# ====================================
projcs_wkt = \
"""GEOGCS["GCS_North_American_1983",
DATUM["D_North_American_1983",
SPHEROID["GRS_1980",6378137,298.257222101]],
PRIMEM["Greenwich",0],
UNIT["Degree",0.017453292519943295]]"""
DATUM["D_North_American_1983",
SPHEROID["GRS_1980",6378137,298.257222101]],
PRIMEM["Greenwich",0],
UNIT["Degree",0.017453292519943295]]"""
from_proj = osr.SpatialReference()
from_proj.ImportFromWkt( projcs_wkt )
@@ -3642,12 +3644,12 @@ def length(segment, nodelist):
pointid, (lat, lon) = nodelist[ round_point( point ) ]
if first:
first = False
else:
#The approximate number of feet in one degree of longitute
else:
#The approximate number of feet in one degree of longitute
lrad = math.radians(lat)
lon_feet = 365527.822 * math.cos(lrad) - 306.75853 * math.cos(3 * lrad) + 0.3937 * math.cos(5 * lrad)
distance += math.sqrt(((lat - previous[0])*lat_feet)**2 + ((lon - previous[1])*lon_feet)**2)
previous = (lat, lon)
distance += math.sqrt(((lat - previous[0])*lat_feet)**2 + ((lon - previous[1])*lon_feet)**2)
previous = (lat, lon)
return distance
def addressways(waylist, nodelist, first_id):
@@ -3657,7 +3659,7 @@ def addressways(waylist, nodelist, first_id):
distance = float(address_distance)
ret = []
for waykey, segments in waylist.iteritems():
for waykey, segments in waylist.items():
waykey = dict(waykey)
rsegments = []
lsegments = []
@@ -3666,11 +3668,11 @@ def addressways(waylist, nodelist, first_id):
rsegment = []
lastpoint = None
#Don't pull back the ends of very short ways too much
seglength = length(segment, nodelist)
if seglength < float(address_pullback) * 3.0:
pullback = seglength / 3.0
else:
#Don't pull back the ends of very short ways too much
seglength = length(segment, nodelist)
if seglength < float(address_pullback) * 3.0:
pullback = seglength / 3.0
else:
pullback = float(address_pullback)
if "tiger:lfromadd" in waykey:
lfromadd = waykey["tiger:lfromadd"]
@@ -3687,88 +3689,88 @@ def addressways(waylist, nodelist, first_id):
if "tiger:rtoadd" in waykey:
rtoadd = waykey["tiger:rtoadd"]
else:
rtoadd = None
rtoadd = None
if rfromadd != None and rtoadd != None:
right = True
else:
right = False
else:
right = False
if lfromadd != None and ltoadd != None:
left = True
else:
left = False
else:
left = False
if left or right:
first = True
first = True
firstpointid, firstpoint = nodelist[ round_point( segment[0] ) ]
finalpointid, finalpoint = nodelist[ round_point( segment[len(segment) - 1] ) ]
for point in segment:
pointid, (lat, lon) = nodelist[ round_point( point ) ]
#The approximate number of feet in one degree of longitute
#The approximate number of feet in one degree of longitute
lrad = math.radians(lat)
lon_feet = 365527.822 * math.cos(lrad) - 306.75853 * math.cos(3 * lrad) + 0.3937 * math.cos(5 * lrad)
#Calculate the points of the offset ways
if lastpoint != None:
#Skip points too close to start
if math.sqrt((lat * lat_feet - firstpoint[0] * lat_feet)**2 + (lon * lon_feet - firstpoint[1] * lon_feet)**2) < pullback:
#Preserve very short ways (but will be rendered backwards)
if pointid != finalpointid:
continue
#Skip points too close to end
if math.sqrt((lat * lat_feet - finalpoint[0] * lat_feet)**2 + (lon * lon_feet - finalpoint[1] * lon_feet)**2) < pullback:
#Preserve very short ways (but will be rendered backwards)
if (pointid != firstpointid) and (pointid != finalpointid):
continue
#Skip points too close to start
if math.sqrt((lat * lat_feet - firstpoint[0] * lat_feet)**2 + (lon * lon_feet - firstpoint[1] * lon_feet)**2) < pullback:
#Preserve very short ways (but will be rendered backwards)
if pointid != finalpointid:
continue
#Skip points too close to end
if math.sqrt((lat * lat_feet - finalpoint[0] * lat_feet)**2 + (lon * lon_feet - finalpoint[1] * lon_feet)**2) < pullback:
#Preserve very short ways (but will be rendered backwards)
if (pointid != firstpointid) and (pointid != finalpointid):
continue
X = (lon - lastpoint[1]) * lon_feet
Y = (lat - lastpoint[0]) * lat_feet
Y = (lat - lastpoint[0]) * lat_feet
if Y != 0:
theta = math.pi/2 - math.atan( X / Y)
Xp = math.sin(theta) * distance
Yp = math.cos(theta) * distance
theta = math.pi/2 - math.atan( X / Y)
Xp = math.sin(theta) * distance
Yp = math.cos(theta) * distance
else:
Xp = 0
if X > 0:
if X > 0:
Yp = -distance
else:
else:
Yp = distance
if Y > 0:
Xp = -Xp
else:
Yp = -Yp
if first:
first = False
dX = - (Yp * (pullback / distance)) / lon_feet #Pull back the first point
dY = (Xp * (pullback / distance)) / lat_feet
if left:
if Y > 0:
Xp = -Xp
else:
Yp = -Yp
if first:
first = False
dX = - (Yp * (pullback / distance)) / lon_feet #Pull back the first point
dY = (Xp * (pullback / distance)) / lat_feet
if left:
lpoint = (lastpoint[0] + (Yp / lat_feet) - dY, lastpoint[1] + (Xp / lon_feet) - dX)
lsegment.append( (id, lpoint) )
id += 1
if right:
id += 1
if right:
rpoint = (lastpoint[0] - (Yp / lat_feet) - dY, lastpoint[1] - (Xp / lon_feet) - dX)
rsegment.append( (id, rpoint) )
id += 1
id += 1
else:
#round the curves
if delta[1] != 0:
theta = abs(math.atan(delta[0] / delta[1]))
else:
theta = math.pi / 2
if Xp != 0:
theta = theta - abs(math.atan(Yp / Xp))
else: theta = theta - math.pi / 2
r = 1 + abs(math.tan(theta/2))
if left:
lpoint = (lastpoint[0] + (Yp + delta[0]) * r / (lat_feet * 2), lastpoint[1] + (Xp + delta[1]) * r / (lon_feet * 2))
else:
#round the curves
if delta[1] != 0:
theta = abs(math.atan(delta[0] / delta[1]))
else:
theta = math.pi / 2
if Xp != 0:
theta = theta - abs(math.atan(Yp / Xp))
else: theta = theta - math.pi / 2
r = 1 + abs(math.tan(theta/2))
if left:
lpoint = (lastpoint[0] + (Yp + delta[0]) * r / (lat_feet * 2), lastpoint[1] + (Xp + delta[1]) * r / (lon_feet * 2))
lsegment.append( (id, lpoint) )
id += 1
if right:
if right:
rpoint = (lastpoint[0] - (Yp + delta[0]) * r / (lat_feet * 2), lastpoint[1] - (Xp + delta[1]) * r / (lon_feet * 2))
rsegment.append( (id, rpoint) )
id += 1
@@ -3778,116 +3780,116 @@ def addressways(waylist, nodelist, first_id):
#Add in the last node
dX = - (Yp * (pullback / distance)) / lon_feet
dY = (Xp * (pullback / distance)) / lat_feet
if left:
dX = - (Yp * (pullback / distance)) / lon_feet
dY = (Xp * (pullback / distance)) / lat_feet
if left:
lpoint = (lastpoint[0] + (Yp + delta[0]) / (lat_feet * 2) + dY, lastpoint[1] + (Xp + delta[1]) / (lon_feet * 2) + dX )
lsegment.append( (id, lpoint) )
id += 1
if right:
if right:
rpoint = (lastpoint[0] - Yp / lat_feet + dY, lastpoint[1] - Xp / lon_feet + dX)
rsegment.append( (id, rpoint) )
id += 1
#Generate the tags for ways and nodes
rtags = []
ltags = []
tags = []
rtags = []
ltags = []
tags = []
zipr = ''
zipl = ''
name = ''
county = ''
if "tiger:zip_right" in waykey:
zipr = waykey["tiger:zip_right"]
if "tiger:zip_right" in waykey:
zipr = waykey["tiger:zip_right"]
rtags.append( "<tag k=\"addr:postcode\" v=\"%s\" />" % zipr )
if "tiger:zip_left" in waykey:
zipl = waykey["tiger:zip_left"]
if "tiger:zip_left" in waykey:
zipl = waykey["tiger:zip_left"]
ltags.append( "<tag k=\"addr:postcode\" v=\"%s\" />" % zipl )
if "name" in waykey:
name = waykey["name"]
tags.append( "<tag k=\"addr:street\" v=\"%s\" />" % name )
if "is_in:state" in waykey:
state = waykey["is_in:state"]
if "is_in:state" in waykey:
state = waykey["is_in:state"]
tags.append( "<tag k=\"addr:state\" v=\"%s\" />" % state )
if "tiger:county" in waykey:
county = waykey["tiger:county"]
if "tiger:county" in waykey:
county = waykey["tiger:county"]
tags.append( "<tag k=\"addr:county\" v=\"%s\" />" % county )
if "is_in:country_code" in waykey:
country = waykey["is_in:country_code"]
if "is_in:country_code" in waykey:
country = waykey["is_in:country_code"]
tags.append( "<tag k=\"addr:country\" v=\"%s\" />" % country )
if "tiger:separated" in waykey:
separated = waykey["tiger:separated"]
else:
separated = "N"
ltags.extend(tags)
rtags.extend(tags)
if "tiger:separated" in waykey:
separated = waykey["tiger:separated"]
else:
separated = "N"
ltags.extend(tags)
rtags.extend(tags)
#Write the nodes of the offset ways
if right:
if right:
rlinestring = [];
for i, point in rsegment:
rlinestring.append( "%f %f" % (point[1], point[0]) )
if left:
if left:
llinestring = [];
for i, point in lsegment:
llinestring.append( "%f %f" % (point[1], point[0]) )
if right:
if right:
rsegments.append( rsegment )
if left:
if left:
lsegments.append( lsegment )
rtofromint = right #Do the addresses convert to integers?
ltofromint = left #Do the addresses convert to integers?
if right:
try: rfromint = int(rfromadd)
except:
print("Non integer address: %s" % rfromadd)
rtofromint = False
try: rtoint = int(rtoadd)
except:
print("Non integer address: %s" % rtoadd)
rtofromint = False
if left:
try: lfromint = int(lfromadd)
except:
print("Non integer address: %s" % lfromadd)
ltofromint = False
try: ltoint = int(ltoadd)
except:
print("Non integer address: %s" % ltoadd)
ltofromint = False
import_guid = time.strftime( '%Y%m%d%H%M%S' )
if right:
id += 1
rtofromint = right #Do the addresses convert to integers?
ltofromint = left #Do the addresses convert to integers?
if right:
try: rfromint = int(rfromadd)
except:
print("Non integer address: %s" % rfromadd)
rtofromint = False
try: rtoint = int(rtoadd)
except:
print("Non integer address: %s" % rtoadd)
rtofromint = False
if left:
try: lfromint = int(lfromadd)
except:
print("Non integer address: %s" % lfromadd)
ltofromint = False
try: ltoint = int(ltoadd)
except:
print("Non integer address: %s" % ltoadd)
ltofromint = False
import_guid = time.strftime( '%Y%m%d%H%M%S' )
if right:
id += 1
interpolationtype = "";
if rtofromint:
if rtofromint:
if (rfromint % 2) == 0 and (rtoint % 2) == 0:
if separated == "Y": #Doesn't matter if there is another side
if separated == "Y": #Doesn't matter if there is another side
# ret.append( "<tag k=\"addr:interpolation\" v=\"even\" />" )
interpolationtype = "even";
elif ltofromint and (lfromint % 2) == 1 and (ltoint % 2) == 1:
elif ltofromint and (lfromint % 2) == 1 and (ltoint % 2) == 1:
interpolationtype = "even";
# ret.append( "<tag k=\"addr:interpolation\" v=\"even\" />" )
else:
else:
interpolationtype = "all";
# ret.append( "<tag k=\"addr:interpolation\" v=\"all\" />" )
elif (rfromint % 2) == 1 and (rtoint % 2) == 1:
if separated == "Y": #Doesn't matter if there is another side
if separated == "Y": #Doesn't matter if there is another side
interpolationtype = "odd";
# ret.append( "<tag k=\"addr:interpolation\" v=\"odd\" />" )
elif ltofromint and (lfromint % 2) == 0 and (ltoint % 2) == 0:
elif ltofromint and (lfromint % 2) == 0 and (ltoint % 2) == 0:
interpolationtype = "odd";
# ret.append( "<tag k=\"addr:interpolation\" v=\"odd\" />" )
else:
else:
interpolationtype = "all";
# ret.append( "<tag k=\"addr:interpolation\" v=\"all\" />" )
else:
else:
interpolationtype = "all";
# ret.append( "<tag k=\"addr:interpolation\" v=\"all\" />" )
else:
else:
interpolationtype = "all";
# ret.append( "<tag k=\"addr:interpolation\" v=\"all\" />" )
# ret.extend(rtags)
# ret.extend(rtags)
# ret.append( "<tag k=\"source\" v=\"%s_import_v%s_%s\" />" % (iSource, VERSION, import_guid) )
# ret.append( "<tag k=\"attribution\" v=\"%s\" />" % (iAttrib) )
# ret.append( "</way>" )
@@ -3895,27 +3897,27 @@ def addressways(waylist, nodelist, first_id):
ret.append( "select tigger_create_interpolation(ST_GeomFromText('LINESTRING(%s)',4326), '%s', '%s', '%s', '%s', '%s', '%s');" %
( ",".join(rlinestring), rfromadd.replace("'", "''"), rtoadd.replace("'", "''"), interpolationtype.replace("'", "''"), name.replace("'", "''"), county.replace("'", "''"), zipr.replace("'", "''") ) )
if left:
id += 1
if ltofromint:
if left:
id += 1
if ltofromint:
if (lfromint % 2) == 0 and (ltoint % 2) == 0:
if separated == "Y":
if separated == "Y":
interpolationtype = "even";
elif rtofromint and (rfromint % 2) == 1 and (rtoint % 2) == 1:
elif rtofromint and (rfromint % 2) == 1 and (rtoint % 2) == 1:
interpolationtype = "even";
else:
else:
interpolationtype = "all";
elif (lfromint % 2) == 1 and (ltoint % 2) == 1:
if separated == "Y":
if separated == "Y":
interpolationtype = "odd";
elif rtofromint and (rfromint %2 ) == 0 and (rtoint % 2) == 0:
elif rtofromint and (rfromint %2 ) == 0 and (rtoint % 2) == 0:
interpolationtype = "odd";
else:
else:
interpolationtype = "all";
else:
else:
interpolationtype = "all";
else:
else:
interpolationtype = "all";
ret.append( "select tigger_create_interpolation(ST_GeomFromText('LINESTRING(%s)',4326), '%s', '%s', '%s', '%s', '%s', '%s');" %
( ",".join(llinestring), lfromadd.replace("'", "''"), ltoadd.replace("'", "''"), interpolationtype.replace("'", "''"), name.replace("'", "''"), county.replace("'", "''"), zipl.replace("'", "''") ) )
@@ -4023,7 +4025,7 @@ def compile_waylist( parsed_gisdata, blank_way_id ):
#Group by iSource:way_id
for geom, tags in parsed_gisdata:
way_key = tags.copy()
way_key = ( way_key[iSource + ':way_id'], tuple( [(k,v) for k,v in way_key.iteritems()] ) )
way_key = ( way_key[iSource + ':way_id'], tuple( [(k,v) for k,v in way_key.items()] ) )
if way_key not in waylist:
waylist[way_key] = []
@@ -4031,7 +4033,7 @@ def compile_waylist( parsed_gisdata, blank_way_id ):
waylist[way_key].append( geom )
ret = {}
for (way_id, way_key), segments in waylist.iteritems():
for (way_id, way_key), segments in waylist.items():
if way_id != blank_way_id:
ret[way_key] = glom_all( segments )
@@ -4047,42 +4049,42 @@ def shape_to_osm( shp_filename, base_filename, blank_way_id ):
import_guid = time.strftime( '%Y%m%d%H%M%S' )
print "parsing shpfile"
print("parsing shpfile")
parsed_features = parse_shp_for_osm( shp_filename )
print "compiling nodelist"
print("compiling nodelist")
i, nodelist = compile_nodelist( parsed_features )
print "compiling waylist"
print("compiling waylist")
waylist = compile_waylist( parsed_features, blank_way_id )
filenumber = 1
objectcount = 0
seen = {}
print "preparing address ways"
print("preparing address ways")
ret = addressways(waylist, nodelist, i)
osm_filename = "%s%d.osm" % (base_filename, filenumber)
print "writing %s" %osm_filename
print("writing %s" %osm_filename)
fp = open( osm_filename, "w" )
fp.write( "\n".join( ret ) )
fp.close()
filenumber += 1
print "constructing osm xml file"
print("constructing osm xml file")
ret = []
ret.append( "<?xml version='1.0' encoding='UTF-8'?>" )
ret.append( "<osm version='0.6' generator='shape_to_osm.py'>" )
for waykey, segments in waylist.iteritems():
for waykey, segments in waylist.items():
for segment in segments:
#write the nodes
#write the nodes
for point in segment:
id, (lat, lon) = nodelist[ round_point( point ) ]
if id not in seen:
seen[id] = True
#write node
#write node
ret.append( " <node id='-%d' action='create' visible='true' lat='%f' lon='%f' >" % (id, lat, lon) )
ret.append( " </node>" )
objectcount += 1
@@ -4090,7 +4092,7 @@ def shape_to_osm( shp_filename, base_filename, blank_way_id ):
pass
#print "Skipping node %d" %id
#write the way
#write the way
ret.append( " <way id='-%d' action='create' visible='true'>" % i )
ids = [ nodelist[ round_point( point ) ][0] for point in segment ]
@@ -4099,7 +4101,7 @@ def shape_to_osm( shp_filename, base_filename, blank_way_id ):
for id in ids:
count += 1
ret.append( " <nd ref='-%d' />" % id )
if (count % Max_Waylength == 0) and (count != len(ids)): #Split the way
if (count % Max_Waylength == 0) and (count != len(ids)): #Split the way
for k, v in waykey:
ret.append( " <tag k=\"%s\" v=\"%s\" />" % (k, escape(str(v))) )
ret.append( " <tag k=\"source\" v=\"%s_import_v%s_%s\" />" % (iSource, VERSION, import_guid) )
@@ -4107,7 +4109,7 @@ def shape_to_osm( shp_filename, base_filename, blank_way_id ):
ret.append( " </way>" )
objectcount += 1
i += 1
i += 1
ret.append( " <way id='-%d' action='create' visible='true'>" % i )
ret.append( " <nd ref='-%d' />" % id )
@@ -4121,10 +4123,10 @@ def shape_to_osm( shp_filename, base_filename, blank_way_id ):
i += 1
if objectcount > maxNodes: #Write a file
if objectcount > maxNodes: #Write a file
ret.append( "</osm>" )
osm_filename = "%s%d.osm" % (base_filename, filenumber)
print "writing %s" %osm_filename
print("writing %s" %osm_filename)
fp = open( osm_filename, "w" )
fp.write( "\n".join( ret ) )
fp.close()
@@ -4139,7 +4141,7 @@ def shape_to_osm( shp_filename, base_filename, blank_way_id ):
ret.append( "</osm>" )
osm_filename = "%s%d.osm" % (base_filename, filenumber)
print "writing %s" %osm_filename
print("writing %s" %osm_filename)
fp = open( osm_filename, "w" )
fp.write( "\n".join( ret ) )
fp.close()
@@ -4147,7 +4149,7 @@ def shape_to_osm( shp_filename, base_filename, blank_way_id ):
if __name__ == '__main__':
import sys, os.path
if len(sys.argv) < 2:
print "%s filename.shp [filename.osm]" % sys.argv[0]
print("%s filename.shp [filename.osm]" % sys.argv[0])
sys.exit()
shape = sys.argv[1]
if len(sys.argv) > 2:
@@ -4155,6 +4157,6 @@ if __name__ == '__main__':
else:
osm = shape[0:-4] + ".osm"
id = "1.shp"
# Left over from massGIS unknown usage, but works fine hardcoded to "1.shp" which was the valu on a test of the actual mass data,
#id = os.path.basename(shape).split("_")[-1]
# Left over from massGIS unknown usage, but works fine hardcoded to "1.shp" which was the valu on a test of the actual mass data,
#id = os.path.basename(shape).split("_")[-1]
shape_to_osm( shape, osm, id )

View File

@@ -54,15 +54,13 @@
// Lock to prevent multiple copies running
if (exec('/bin/ps uww | grep '.basename(__FILE__).' | grep -v /dev/null | grep -v grep -c', $aOutput2, $iResult) > 1)
{
echo "Copy already running\n";
exit;
fail("Copy already running\n");
}
if (!isset($aResult['max-load'])) $aResult['max-load'] = 1.9;
if (!isset($aResult['max-blocking'])) $aResult['max-blocking'] = 3;
if (getBlockingProcesses() > $aResult['max-blocking'])
{
echo "Too many blocking processes for import\n";
exit;
fail("Too many blocking processes for import\n");
}
*/
@@ -83,7 +81,7 @@
$iCacheMemory = getCacheMemoryMB();
echo "WARNING: resetting cache memory to $iCacheMemory\n";
}
$sOsm2pgsqlCmd = CONST_Osm2pgsql_Binary.' -klas -C '.$iCacheMemory.' -O gazetteer -d '.$aDSNInfo['database'].' -P '.$aDSNInfo['port'];
$sOsm2pgsqlCmd = CONST_Osm2pgsql_Binary.' -klas --number-processes 1 -C '.$iCacheMemory.' -O gazetteer -d '.$aDSNInfo['database'].' -P '.$aDSNInfo['port'];
if (!is_null(CONST_Osm2pgsql_Flatnode_File))
{
$sOsm2pgsqlCmd .= ' --flat-nodes '.CONST_Osm2pgsql_Flatnode_File;
@@ -120,8 +118,7 @@
$sNextFile = $aResult['import-diff'];
if (!file_exists($sNextFile))
{
echo "Cannot open $sNextFile\n";
exit;
fail("Cannot open $sNextFile\n");
}
// Don't update the import status - we don't know what this file contains
$sUpdateSQL = 'update import_status set lastimportdate = now() where false';
@@ -137,8 +134,7 @@
if ($iErrorLevel)
{
echo "Error from osm2pgsql, $iErrorLevel\n";
exit;
fail("Error from osm2pgsql, $iErrorLevel\n");
}
// Move the date onwards
@@ -205,8 +201,7 @@
exec($sCMD, $sJunk, $iErrorLevel);
if ($iErrorLevel)
{
echo "Error converting osm to osc, osmosis returned: $iErrorLevel\n";
exit;
fail("Error converting osm to osc, osmosis returned: $iErrorLevel\n");
}
}
else
@@ -221,8 +216,7 @@
$hProc = proc_open($sCMD, $aSpec, $aPipes);
if (!is_resource($hProc))
{
echo "Error converting osm to osc, osmosis failed\n";
exit;
fail("Error converting osm to osc, osmosis failed\n");
}
fwrite($aPipes[0], $sModifyXMLstr);
fclose($aPipes[0]);
@@ -237,7 +231,7 @@
echo "Error converting osm to osc, osmosis returned: $iError\n";
echo $sOut;
echo $sErrors;
exit;
exit(-1);
}
}
@@ -247,8 +241,7 @@
exec($sCMD, $sJunk, $iErrorLevel);
if ($iErrorLevel)
{
echo "osm2pgsql exited with error level $iErrorLevel\n";
exit;
fail("osm2pgsql exited with error level $iErrorLevel\n");
}
}
@@ -257,8 +250,7 @@
$pgver = (float) CONST_Postgresql_Version;
if ($pgver < 9.3) {
echo "ERROR: deduplicate is only currently supported in postgresql 9.3";
exit;
fail("ERROR: deduplicate is only currently supported in postgresql 9.3");
}
$oDB =& getDB();
@@ -281,7 +273,7 @@
if (PEAR::isError($aTokenSet))
{
var_dump($aTokenSet, $sSQL);
exit;
exit(1);
}
$aKeep = array_shift($aTokenSet);
@@ -297,7 +289,7 @@
if (PEAR::isError($x))
{
var_dump($x);
exit;
exit(1);
}
$sSQL = "update search_name set";
@@ -307,7 +299,7 @@
if (PEAR::isError($x))
{
var_dump($x);
exit;
exit(1);
}
$sSQL = "update location_area_country set";
@@ -317,7 +309,7 @@
if (PEAR::isError($x))
{
var_dump($x);
exit;
exit(1);
}
foreach ($aPartitions as $sPartition)
@@ -329,7 +321,7 @@
if (PEAR::isError($x))
{
var_dump($x);
exit;
exit(1);
}
$sSQL = "update location_area_country set";
@@ -339,7 +331,7 @@
if (PEAR::isError($x))
{
var_dump($x);
exit;
exit(1);
}
}
@@ -348,7 +340,7 @@
if (PEAR::isError($x))
{
var_dump($x);
exit;
exit(1);
}
}
@@ -364,8 +356,7 @@
{
if (strpos(CONST_Replication_Url, 'download.geofabrik.de') !== false && CONST_Replication_Update_Interval < 86400) {
echo "Error: Update interval too low for download.geofabrik.de. Please check install documentation (http://wiki.openstreetmap.org/wiki/Nominatim/Installation#Updates)\n";
exit;
fail("Error: Update interval too low for download.geofabrik.de. Please check install documentation (http://wiki.openstreetmap.org/wiki/Nominatim/Installation#Updates)\n");
}
$sImportFile = CONST_BasePath.'/data/osmosischange.osc';
@@ -527,7 +518,7 @@
$fDuration = time() - $fStartTime;
echo date('Y-m-d H:i:s')." Completed all for $sBatchEnd in ".round($fDuration/60,2)." minutes\n";
if (!$aResult['import-osmosis-all']) exit;
if (!$aResult['import-osmosis-all']) exit(0);
if ( CONST_Replication_Update_Interval > 60 )
{
@@ -549,7 +540,7 @@
if (PEAR::isError($iNPIID))
{
var_dump($iNPIID);
exit;
exit(1);
}
$sConfigDirectory = CONST_BasePath.'/settings';
$sCMDImportTemplate = $sBasePath.'/nominatim/nominatim -d gazetteer -P 5433 -I -T '.$sBasePath.'/nominatim/partitionedtags.def -F ';
@@ -580,8 +571,7 @@
exec($sCMDImport, $sJunk, $iErrorLevel);
if ($iErrorLevel)
{
echo "Error: $iErrorLevel\n";
exit;
fail("Error: $iErrorLevel\n");
}
$sBatchEnd = $iNPIID;
echo "Completed for $sBatchEnd in ".round((time()-$fCMDStartTime)/60,2)." minutes\n";

View File

@@ -0,0 +1,107 @@
#!/bin/bash
# This script sets up a Nominatim installation on a CentOS 7 box.
#
# For more detailed CentOS installation instructions see also
# http://wiki.openstreetmap.org/wiki/Nominatim/Installation_on_CentOS
## Part 1: System preparation
## During 'vagrant provision' this script runs as root and the current
## directory is '/root'
USERNAME=vagrant
yum update -y
yum install -y epel-release
yum install -y postgresql-server postgresql-contrib postgresql-devel postgis postgis-utils \
make automake gcc gcc-c++ libtool policycoreutils-python \
php-pgsql php php-pear php-pear-DB libpqxx-devel proj-epsg \
bzip2-devel proj-devel geos-devel libxml2-devel boost-devel \
expat-devel zlib-devel
# Create a cluster and start up postgresql.
postgresql-setup initdb
systemctl enable postgresql
systemctl start postgresql
# We leave postgresql in its default configuration here. This is only
# suitable for small extracts.
# Create the necessary postgres users.
sudo -u postgres createuser -s vagrant
sudo -u postgres createuser apache
# Create the website directory.
mkdir -m 755 /var/www/html/nominatim
chown vagrant /var/www/html/nominatim
# Set up the necessary rights on SELinux.
semanage fcontext -a -t httpd_sys_content_t "/home/vagrant/Nominatim/(website|lib|settings)(/.*)?"
semanage fcontext -a -t lib_t "/home/vagrant/Nominatim/module/nominatim.so"
semanage port -a -t http_port_t -p tcp 8089
restorecon -R -v /home/vagrant/Nominatim
# Configure apache site.
echo '
Listen 8089
<VirtualHost *:8089>
# DirectoryIndex index.html
# ErrorDocument 403 /index.html
DocumentRoot "/var/www/html/"
<Directory "/var/www/html/nominatim/">
Options FollowSymLinks MultiViews
AddType text/html .php
</Directory>
</VirtualHost>
' | sudo tee /etc/httpd/conf.d/nominatim.conf > /dev/null
# Restart apache to enable the site configuration.
systemctl enable httpd
systemctl restart httpd
## Part 2: Nominatim installaion
# now ideally login as $USERNAME and continue
cd /home/$USERNAME
# If the Nominatim source is not being shared with the host, check out source.
if [ ! -d "Nominatim" ]; then
yum install -y git
sudo -u $USERNAME git clone --recursive https://github.com/twain47/Nominatim.git
fi
# Configure and compile the source.
cd Nominatim
sudo -u $USERNAME ./autogen.sh
sudo -u $USERNAME ./configure
sudo -u $USERNAME make
# Make sure that postgres has access to the nominatim library.
chmod +x /home/$USERNAME
chmod +x ./
chmod +x ./module
# Create customized settings suitable for this VM installation.
LOCALSETTINGS_FILE='settings/local.php'
if [[ -e "$LOCALSETTINGS_FILE" ]]; then
echo "$LOCALSETTINGS_FILE already exist, writing to settings/local-vagrant.php instead."
LOCALSETTINGS_FILE='settings/local-vagrant.php'
fi
IP=localhost
echo "<?php
// General settings
@define('CONST_Database_DSN', 'pgsql://@/nominatim');
// Paths
@define('CONST_Postgresql_Version', '9.2');
@define('CONST_Postgis_Version', '2.0');
@define('CONST_Database_Web_User', 'apache');
// Website settings
@define('CONST_Website_BaseURL', 'http://$IP:8089/nominatim/');
" > $LOCALSETTINGS_FILE
# Install the web interface.
sudo -u $USERNAME ./utils/setup.php --create-website /var/www/html/nominatim

View File

@@ -0,0 +1,174 @@
#!/bin/bash
# This script sets up a Nominatim installation on a Ubuntu box.
#
# For more detailed installation instructions see also
# http://wiki.openstreetmap.org/wiki/Nominatim/Installation
## Part 1: System preparation
## During 'vagrant provision' this script runs as root and the current
## directory is '/root'
USERNAME=vagrant
###
### maybe create ubuntu user
###
# if [[ ! `id -u $USERNAME` ]]; then
# useradd $USERNAME --create-home --shell /bin/bash
#
# # give sudo power
# echo "$USERNAME ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/99-$USERNAME-user
# chmod 0440 /etc/sudoers.d/99-$USERNAME-user
# service sudo restart
#
# # add basic .profile
# cp -r .ssh .profile .bashrc /home/$USERNAME/
# chown -R $USERNAME /home/$USERNAME/.*
# chgrp -R $USERNAME /home/$USERNAME/.*
#
# # now ideally login as $USERNAME and continue
# su $USERNAME -l
# fi
sudo apt-get update -qq
sudo apt-get upgrade -y
sudo apt-get install -y build-essential libgeos-dev libpq-dev libbz2-dev \
libtool automake libproj-dev libboost-dev libboost-system-dev \
libboost-filesystem-dev libboost-thread-dev libexpat-dev
sudo apt-get autoremove -y
# get arrow-keys working in terminal (e.g. editing in vi)
echo 'stty sane' >> ~/.bash_profile
echo 'export TERM=linux' >> ~/.bash_profile
source ~/.bash_profile
###
### PostgreSQL 9.3 + PostGIS 2.1
###
sudo apt-get install -y postgresql-9.3-postgis-2.1 postgresql-contrib-9.3 postgresql-server-dev-9.3
# already included: proj-bin libgeos-dev
# make sure OS-authenticated users (e.g. $USERNAME) can access
sudo sed -i "s/ident/trust/" /etc/postgresql/9.3/main/pg_hba.conf
sudo sed -i "s/md5/trust/" /etc/postgresql/9.3/main/pg_hba.conf
sudo sed -i "s/peer/trust/" /etc/postgresql/9.3/main/pg_hba.conf
sudo /etc/init.d/postgresql restart
# creates the role
sudo -u postgres createuser -s $USERNAME
###
### PHP for frontend
###
sudo apt-get install -y php5 php5-pgsql php-pear php-db
# get rid of some warning
# where is the ini file? 'php --ini'
echo "date.timezone = 'Etc/UTC'" | sudo tee /etc/php5/cli/conf.d/99-timezone.ini > /dev/null
###
### Nominatim
###
sudo apt-get install -y libgeos-c1 libgeos++-dev libxml2-dev
## Part 2: Nominatim installaion
# now ideally login as $USERNAME and continue
cd /home/$USERNAME
# If the Nominatim source is not being shared with the host, check out source.
if [ ! -d "Nominatim" ]; then
sudo apt-get install -y git
sudo -u $USERNAME git clone --recursive https://github.com/twain47/Nominatim.git
fi
cd Nominatim
sudo -u $USERNAME ./autogen.sh
sudo -u $USERNAME ./configure
sudo -u $USERNAME make
chmod +x ./
chmod +x ./module
LOCALSETTINGS_FILE='settings/local.php'
if [[ -e "$LOCALSETTINGS_FILE" ]]; then
echo "$LOCALSETTINGS_FILE already exist, writing to settings/local-vagrant.php instead."
LOCALSETTINGS_FILE='settings/local-vagrant.php'
fi
# IP=`curl -s http://bot.whatismyipaddress.com`
IP=localhost
echo "<?php
// General settings
@define('CONST_Database_DSN', 'pgsql://@/nominatim');
// Paths
@define('CONST_Postgresql_Version', '9.3');
@define('CONST_Postgis_Version', '2.1');
// Website settings
@define('CONST_Website_BaseURL', 'http://$IP:8089/nominatim/');
" > $LOCALSETTINGS_FILE
###
### Setup Apache/website
###
sudo -u postgres createuser -SDR www-data
echo '
Listen 8089
<VirtualHost *:8089>
# DirectoryIndex index.html
# ErrorDocument 403 /index.html
DocumentRoot "/var/www/"
<Directory "/var/www/nominatim/">
Options FollowSymLinks MultiViews
AddType text/html .php
</Directory>
</VirtualHost>
' | sudo tee /etc/apache2/sites-enabled/nominatim.conf > /dev/null
apache2ctl graceful
mkdir -m 755 /var/www/nominatim
chown $USERNAME /var/www/nominatim
sudo -u $USERNAME ./utils/setup.php --create-website /var/www/nominatim
# if you get 'permission denied for relation word', then try
# GRANT usage ON SCHEMA public TO "www-data";
# GRANT SELECT ON ALL TABLES IN SCHEMA public TO "www-data";
##
## Test suite (Python)
## https://github.com/twain47/Nominatim/tree/master/tests
##
apt-get install -y python-dev python-pip python-Levenshtein python-shapely \
python-psycopg2 tidy python-nose python-tidylib
pip install lettuce==0.2.18 six==1.7 haversine
## Test suite (PHP)
## https://github.com/twain47/Nominatim/tree/master/tests-php
apt-get install -y phpunit

14
website/css/bootstrap-theme.min.css vendored Executable file

File diff suppressed because one or more lines are too long

14
website/css/bootstrap.min.css vendored Executable file

File diff suppressed because one or more lines are too long

31
website/css/common.css Normal file
View File

@@ -0,0 +1,31 @@
header {
width: 100%;
padding: 5px 15px;
z-index: 5;
}
header .brand {
white-space: nowrap;
}
header .brand a:hover{
text-decoration: none;
}
header .brand h1 {
display: inline;
font-size: 1.5em;
color: #333;
}
header .brand > img {
display: inline-block;
margin-right: 5px;
margin-top: -5px;
}
header #last-updated {
font-size: 0.7em;
white-space: nowrap;
text-align: center;
}

View File

@@ -1,12 +1,34 @@
body {
margin:0px;
padding:16px;
background:#ffffff;
height: 100%;
font: normal 12px/15px arial,sans-serif;
h1 {
margin: 10px 0;
padding-left: 8px;
}
.line{
margin-left:20px;
h2 {
font-size: 2em;
padding-left: 8px;
background-color: white;
}
h3 {
font-size: 1.5em;
padding-left: 8px;
}
tr.all-columns {
background-color: white !important;
border: none;
}
tr.all-columns td {
border-top: none !important;
padding-left: 0 !important;
}
.table {
width: 100%;
}
.table td {
font-size: 0.9em;
}
.table>thead>tr>td, .table>tbody>tr>td {
padding: 2px 8px;
}
.name{
font-weight: bold;
@@ -18,9 +40,22 @@ body {
color:#800;
}
#map {
width:500px;
height:500px;
border: 2px solid #666;
float: right;
width:100%;
height:300px;
border: 1px solid #666;
}
#mapicon {
margin: 10px 0;
}
footer {
text-align: center;
padding: 2em 0;
font-size: 0.8em;
clear: both;
color: #333;
}
footer p {
margin: 1em;
}

479
website/css/leaflet.css Normal file
View File

@@ -0,0 +1,479 @@
/* required styles */
.leaflet-map-pane,
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow,
.leaflet-tile-pane,
.leaflet-tile-container,
.leaflet-overlay-pane,
.leaflet-shadow-pane,
.leaflet-marker-pane,
.leaflet-popup-pane,
.leaflet-overlay-pane svg,
.leaflet-zoom-box,
.leaflet-image-layer,
.leaflet-layer {
position: absolute;
left: 0;
top: 0;
}
.leaflet-container {
overflow: hidden;
-ms-touch-action: none;
touch-action: none;
}
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
-webkit-user-drag: none;
}
.leaflet-marker-icon,
.leaflet-marker-shadow {
display: block;
}
/* map is broken in FF if you have max-width: 100% on tiles */
.leaflet-container img {
max-width: none !important;
}
/* stupid Android 2 doesn't understand "max-width: none" properly */
.leaflet-container img.leaflet-image-layer {
max-width: 15000px !important;
}
.leaflet-tile {
filter: inherit;
visibility: hidden;
}
.leaflet-tile-loaded {
visibility: inherit;
}
.leaflet-zoom-box {
width: 0;
height: 0;
}
/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
.leaflet-overlay-pane svg {
-moz-user-select: none;
}
.leaflet-tile-pane { z-index: 2; }
.leaflet-objects-pane { z-index: 3; }
.leaflet-overlay-pane { z-index: 4; }
.leaflet-shadow-pane { z-index: 5; }
.leaflet-marker-pane { z-index: 6; }
.leaflet-popup-pane { z-index: 7; }
.leaflet-vml-shape {
width: 1px;
height: 1px;
}
.lvml {
behavior: url(#default#VML);
display: inline-block;
position: absolute;
}
/* control positioning */
.leaflet-control {
position: relative;
z-index: 7;
pointer-events: auto;
}
.leaflet-top,
.leaflet-bottom {
position: absolute;
z-index: 1000;
pointer-events: none;
}
.leaflet-top {
top: 0;
}
.leaflet-right {
right: 0;
}
.leaflet-bottom {
bottom: 0;
}
.leaflet-left {
left: 0;
}
.leaflet-control {
float: left;
clear: both;
}
.leaflet-right .leaflet-control {
float: right;
}
.leaflet-top .leaflet-control {
margin-top: 10px;
}
.leaflet-bottom .leaflet-control {
margin-bottom: 10px;
}
.leaflet-left .leaflet-control {
margin-left: 10px;
}
.leaflet-right .leaflet-control {
margin-right: 10px;
}
/* zoom and fade animations */
.leaflet-fade-anim .leaflet-tile,
.leaflet-fade-anim .leaflet-popup {
opacity: 0;
-webkit-transition: opacity 0.2s linear;
-moz-transition: opacity 0.2s linear;
-o-transition: opacity 0.2s linear;
transition: opacity 0.2s linear;
}
.leaflet-fade-anim .leaflet-tile-loaded,
.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
opacity: 1;
}
.leaflet-zoom-anim .leaflet-zoom-animated {
-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
-moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
-o-transition: -o-transform 0.25s cubic-bezier(0,0,0.25,1);
transition: transform 0.25s cubic-bezier(0,0,0.25,1);
}
.leaflet-zoom-anim .leaflet-tile,
.leaflet-pan-anim .leaflet-tile,
.leaflet-touching .leaflet-zoom-animated {
-webkit-transition: none;
-moz-transition: none;
-o-transition: none;
transition: none;
}
.leaflet-zoom-anim .leaflet-zoom-hide {
visibility: hidden;
}
/* cursors */
.leaflet-clickable {
cursor: pointer;
}
.leaflet-container {
cursor: -webkit-grab;
cursor: -moz-grab;
}
.leaflet-popup-pane,
.leaflet-control {
cursor: auto;
}
.leaflet-dragging .leaflet-container,
.leaflet-dragging .leaflet-clickable {
cursor: move;
cursor: -webkit-grabbing;
cursor: -moz-grabbing;
}
/* visual tweaks */
.leaflet-container {
background: #ddd;
outline: 0;
}
.leaflet-container a {
color: #0078A8;
}
.leaflet-container a.leaflet-active {
outline: 2px solid orange;
}
.leaflet-zoom-box {
border: 2px dotted #38f;
background: rgba(255,255,255,0.5);
}
/* general typography */
.leaflet-container {
font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif;
}
/* general toolbar styles */
.leaflet-bar {
box-shadow: 0 1px 5px rgba(0,0,0,0.65);
border-radius: 4px;
}
.leaflet-bar a,
.leaflet-bar a:hover {
background-color: #fff;
border-bottom: 1px solid #ccc;
width: 26px;
height: 26px;
line-height: 26px;
display: block;
text-align: center;
text-decoration: none;
color: black;
}
.leaflet-bar a,
.leaflet-control-layers-toggle {
background-position: 50% 50%;
background-repeat: no-repeat;
display: block;
}
.leaflet-bar a:hover {
background-color: #f4f4f4;
}
.leaflet-bar a:first-child {
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.leaflet-bar a:last-child {
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-bottom: none;
}
.leaflet-bar a.leaflet-disabled {
cursor: default;
background-color: #f4f4f4;
color: #bbb;
}
.leaflet-touch .leaflet-bar a {
width: 30px;
height: 30px;
line-height: 30px;
}
/* zoom control */
.leaflet-control-zoom-in,
.leaflet-control-zoom-out {
font: bold 18px 'Lucida Console', Monaco, monospace;
text-indent: 1px;
}
.leaflet-control-zoom-out {
font-size: 20px;
}
.leaflet-touch .leaflet-control-zoom-in {
font-size: 22px;
}
.leaflet-touch .leaflet-control-zoom-out {
font-size: 24px;
}
/* layers control */
.leaflet-control-layers {
box-shadow: 0 1px 5px rgba(0,0,0,0.4);
background: #fff;
border-radius: 5px;
}
.leaflet-control-layers-toggle {
background-image: url(images/layers.png);
width: 36px;
height: 36px;
}
.leaflet-retina .leaflet-control-layers-toggle {
background-image: url(images/layers-2x.png);
background-size: 26px 26px;
}
.leaflet-touch .leaflet-control-layers-toggle {
width: 44px;
height: 44px;
}
.leaflet-control-layers .leaflet-control-layers-list,
.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
display: none;
}
.leaflet-control-layers-expanded .leaflet-control-layers-list {
display: block;
position: relative;
}
.leaflet-control-layers-expanded {
padding: 6px 10px 6px 6px;
color: #333;
background: #fff;
}
.leaflet-control-layers-selector {
margin-top: 2px;
position: relative;
top: 1px;
}
.leaflet-control-layers label {
display: block;
}
.leaflet-control-layers-separator {
height: 0;
border-top: 1px solid #ddd;
margin: 5px -10px 5px -6px;
}
/* attribution and scale controls */
.leaflet-container .leaflet-control-attribution {
background: #fff;
background: rgba(255, 255, 255, 0.7);
margin: 0;
}
.leaflet-control-attribution,
.leaflet-control-scale-line {
padding: 0 5px;
color: #333;
}
.leaflet-control-attribution a {
text-decoration: none;
}
.leaflet-control-attribution a:hover {
text-decoration: underline;
}
.leaflet-container .leaflet-control-attribution,
.leaflet-container .leaflet-control-scale {
font-size: 11px;
}
.leaflet-left .leaflet-control-scale {
margin-left: 5px;
}
.leaflet-bottom .leaflet-control-scale {
margin-bottom: 5px;
}
.leaflet-control-scale-line {
border: 2px solid #777;
border-top: none;
line-height: 1.1;
padding: 2px 5px 1px;
font-size: 11px;
white-space: nowrap;
overflow: hidden;
-moz-box-sizing: content-box;
box-sizing: content-box;
background: #fff;
background: rgba(255, 255, 255, 0.5);
}
.leaflet-control-scale-line:not(:first-child) {
border-top: 2px solid #777;
border-bottom: none;
margin-top: -2px;
}
.leaflet-control-scale-line:not(:first-child):not(:last-child) {
border-bottom: 2px solid #777;
}
.leaflet-touch .leaflet-control-attribution,
.leaflet-touch .leaflet-control-layers,
.leaflet-touch .leaflet-bar {
box-shadow: none;
}
.leaflet-touch .leaflet-control-layers,
.leaflet-touch .leaflet-bar {
border: 2px solid rgba(0,0,0,0.2);
background-clip: padding-box;
}
/* popup */
.leaflet-popup {
position: absolute;
text-align: center;
}
.leaflet-popup-content-wrapper {
padding: 1px;
text-align: left;
border-radius: 12px;
}
.leaflet-popup-content {
margin: 13px 19px;
line-height: 1.4;
}
.leaflet-popup-content p {
margin: 18px 0;
}
.leaflet-popup-tip-container {
margin: 0 auto;
width: 40px;
height: 20px;
position: relative;
overflow: hidden;
}
.leaflet-popup-tip {
width: 17px;
height: 17px;
padding: 1px;
margin: -10px auto 0;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
}
.leaflet-popup-content-wrapper,
.leaflet-popup-tip {
background: white;
box-shadow: 0 3px 14px rgba(0,0,0,0.4);
}
.leaflet-container a.leaflet-popup-close-button {
position: absolute;
top: 0;
right: 0;
padding: 4px 4px 0 0;
text-align: center;
width: 18px;
height: 14px;
font: 16px/14px Tahoma, Verdana, sans-serif;
color: #c3c3c3;
text-decoration: none;
font-weight: bold;
background: transparent;
}
.leaflet-container a.leaflet-popup-close-button:hover {
color: #999;
}
.leaflet-popup-scrolled {
overflow: auto;
border-bottom: 1px solid #ddd;
border-top: 1px solid #ddd;
}
.leaflet-oldie .leaflet-popup-content-wrapper {
zoom: 1;
}
.leaflet-oldie .leaflet-popup-tip {
width: 24px;
margin: 0 auto;
-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
}
.leaflet-oldie .leaflet-popup-tip-container {
margin-top: -1px;
}
.leaflet-oldie .leaflet-control-zoom,
.leaflet-oldie .leaflet-control-layers,
.leaflet-oldie .leaflet-popup-content-wrapper,
.leaflet-oldie .leaflet-popup-tip {
border: 1px solid #999;
}
/* div icon */
.leaflet-div-icon {
background: #fff;
border: 1px solid #666;
}

View File

@@ -1,166 +1,141 @@
* {-moz-box-sizing: border-box;}
body {
margin:0px;
padding:0px;
overflow: hidden;
background:#ffffff;
height: 100%;
font: normal 12px/15px arial,sans-serif;
form {
width: 100%;
padding: 1em 15px;
}
#seachheader {
position:absolute;
z-index:5;
top:0px;
left:0px;
width:100%;
height:38px;
background:#F0F7FF;
border-bottom: 2px solid #75ADFF;
form #q {
min-width: 500px;
}
#q {
width:300px;
@media (max-width: 850px) {
form #q {
min-width: 400px;
}
#seachheaderfade1, #seachheaderfade2, #seachheaderfade3, #seachheaderfade4{
position:absolute;
z-index:4;
top:0px;
left:0px;
width:100%;
opacity: 0.15;
filter: alpha(opacity = 15);
background:#000000;
border: 1px solid #000000;
}
#seachheaderfade1{
height:39px;
form .checkbox-inline {
margin-left: 10px;
}
#seachheaderfade2{
height:40px;
}
#seachheaderfade3{
height:41px;
}
#seachheaderfade4{
height:42px;
}
#searchresultsfade1, #searchresultsfade2, #searchresultsfade3, #searchresultsfade4 {
position:absolute;
z-index:2;
top:0px;
left:200px;
height: 100%;
opacity: 0.2;
filter: alpha(opacity = 20);
background:#ffffff;
border: 1px solid #ffffff;
}
#searchresultsfade1{
width:1px;
}
#searchresultsfade2{
width:2px;
}
#searchresultsfade3{
width:3px;
}
#searchresultsfade4{
width:4px;
form label {
font-weight: normal;
}
#searchresults{
position:absolute;
z-index:3;
top:41px;
width:200px;
.search-type-link {
display: inline;
margin-right: 2em;
position: absolute;
right: 0
}
.sidebar {
width: 25%;
padding: 15px;
padding-top: 0;
display: inline-block;
float: left;
}
#map-wrapper {
position: relative;
min-height: 700px;
width: 75%;
padding-right: 20px;
display: inline-block;
float: left;
}
#map {
height: 100%;
background:#ffffff;
border: 1px solid #ffffff;
overflow: auto;
}
#map{
position:absolute;
z-index:1;
top:38px;
left:200px;
width:100%;
height:100%;
min-height: 700px;
background:#eee;
}
#report{
position:absolute;
z-index:2;
top:38px;
left:200px;
width:100%;
height:100%;
background:#eee;
font: normal 12px/15px arial,sans-serif;
padding:20px;
}
#report table {
margin-left:20px;
}
#report th {
vertical-align:top;
text-align:left;
}
#report td.button {
text-align:right;
#map-position {
position: absolute;
top: 0;
right: 20px;
padding: 0 5px;
color: #333;
font-size: 11px;
background-color: rgba(255, 255, 255, 0.7);
z-index: 100;
}
.result {
margin:5px;
margin-bottom:0px;
padding:2px;
padding-left:4px;
padding-right:4px;
border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
font-size: 0.8em;
margin: 5px;
margin-top:0px;
padding: 4px 8px;
border-radius: 2px;
background:#F0F7FF;
border: 2px solid #D7E7FF;
font: normal 12px/15px arial,sans-serif;
cursor:pointer;
}
.result img{
float:right;
}
.result .latlon{
display: none;
}
.result .place_id{
display: none;
}
.result .type{
color: #999;
text-align:center;
font: normal 9px/10px arial,sans-serif;
padding-top:4px;
}
.result .details, .result .details a{
color: #999;
text-align:center;
font: normal 9px/10px arial,sans-serif;
padding-top:4px;
}
.noresults{
color: #000;
text-align:center;
font: normal 12px arial,sans-serif;
padding-top:4px;
}
.more{
color: #ccc;
text-align:center;
padding-top:4px;
}
.disclaimer{
color: #ccc;
text-align:center;
font: normal 9px/10px arial,sans-serif;
padding-top:4px;
}
form{
margin:0px;
padding:0px;
min-height: 5em;
}
.result.highlight {
background-color: #D9E7F7;
border-color: #9DB9E4;
}
.result.highlight .details {
margin: 10px auto;
display: block;
max-width: 10em;
}
.result img{
float: right;
}
.result .type{
color: gray;
font-size: 0.8em;
}
.result .details {
display: none;
}
.noresults{
text-align: center;
padding: 1em;
}
.more{
text-align:center;
margin-top: 1em;
}
footer {
text-align: center;
padding: 2em 0;
font-size: 0.8em;
clear: both;
color: #333;
}
footer p {
margin: 1em;
}
@media (max-width: 768px) {
#content {
top: 0;
position: relative;
}
#map-wrapper {
width: 100%;
max-height: 300px;
padding: 20px;
}
#map-position {
top: 20px;
right: 20px;
}
#map {
height: 300px;
}
.sidebar {
width: 100%;
}
.search-button-group {
display: inline
}
}

View File

@@ -25,6 +25,7 @@
$_GET['place_id'] = $oDB->getOne("select place_id from placex where osm_type = '".$_GET['osmtype']."' and osm_id = ".(int)$_GET['osmid']." order by type = 'postcode' asc");
// Be nice about our error messages for broken geometry
if (!$_GET['place_id'])
{
$aPointDetails = $oDB->getRow("select osm_type, osm_id, errormessage, class, type, get_name_by_language(name,$sLanguagePrefArraySQL) as localname, ST_AsText(prevgeometry) as prevgeom, ST_AsText(newgeometry) as newgeom from import_polygon_error where osm_type = '".$_GET['osmtype']."' and osm_id = ".(int)$_GET['osmid']." order by updated desc limit 1");
@@ -34,12 +35,18 @@
$aPointDetails['error_x'] = $aMatches[1];
$aPointDetails['error_y'] = $aMatches[2];
}
else
{
$aPointDetails['error_x'] = 0;
$aPointDetails['error_y'] = 0;
}
include(CONST_BasePath.'/lib/template/details-error-'.$sOutputFormat.'.php');
exit;
}
}
}
if (!isset($_GET['place_id']))
{
echo "Please select a place id";
@@ -81,30 +88,46 @@
// Get all alternative names (languages, etc)
$sSQL = "select (each(name)).key,(each(name)).value from placex where place_id = $iPlaceID order by (each(name)).key";
$aPointDetails['aNames'] = $oDB->getAssoc($sSQL);
if (PEAR::isError($aPointDetails['aNames'])) // possible timeout
{
$aPointDetails['aNames'] = [];
}
// Extra tags
$sSQL = "select (each(extratags)).key,(each(extratags)).value from placex where place_id = $iPlaceID order by (each(extratags)).key";
$aPointDetails['aExtraTags'] = $oDB->getAssoc($sSQL);
if (PEAR::isError($aPointDetails['aExtraTags'])) // possible timeout
{
$aPointDetails['aExtraTags'] = [];
}
// Address
$aAddressLines = getAddressDetails($oDB, $sLanguagePrefArraySQL, $iPlaceID, $aPointDetails['country_code'], true);
// Linked places
$sSQL = "select placex.place_id, osm_type, osm_id, class, type, housenumber, admin_level, rank_address, ST_GeometryType(geometry) in ('ST_Polygon','ST_MultiPolygon') as isarea, st_distance(geometry, placegeometry) as distance, ";
$sSQL = "select placex.place_id, osm_type, osm_id, class, type, housenumber, admin_level, rank_address, ST_GeometryType(geometry) in ('ST_Polygon','ST_MultiPolygon') as isarea, ST_Distance_Spheroid(geometry, placegeometry, 'SPHEROID[\"WGS 84\",6378137,298.257223563, AUTHORITY[\"EPSG\",\"7030\"]]') as distance, ";
$sSQL .= " get_name_by_language(name,$sLanguagePrefArraySQL) as localname, length(name::text) as namelength ";
$sSQL .= " from placex, (select geometry as placegeometry from placex where place_id = $iPlaceID) as x";
$sSQL .= " from placex, (select centroid as placegeometry from placex where place_id = $iPlaceID) as x";
$sSQL .= " where linked_place_id = $iPlaceID";
$sSQL .= " order by rank_address asc,rank_search asc,get_name_by_language(name,$sLanguagePrefArraySQL),housenumber";
$aLinkedLines = $oDB->getAll($sSQL);
if (PEAR::isError($aLinkedLines)) // possible timeout
{
$aLinkedLines = [];
}
// All places this is an imediate parent of
$sSQL = "select obj.place_id, osm_type, osm_id, class, type, housenumber, admin_level, rank_address, ST_GeometryType(geometry) in ('ST_Polygon','ST_MultiPolygon') as isarea, st_distance(geometry, placegeometry) as distance, ";
$sSQL = "select obj.place_id, osm_type, osm_id, class, type, housenumber, admin_level, rank_address, ST_GeometryType(geometry) in ('ST_Polygon','ST_MultiPolygon') as isarea, ST_Distance_Spheroid(geometry, placegeometry, 'SPHEROID[\"WGS 84\",6378137,298.257223563, AUTHORITY[\"EPSG\",\"7030\"]]') as distance, ";
$sSQL .= " get_name_by_language(name,$sLanguagePrefArraySQL) as localname, length(name::text) as namelength ";
$sSQL .= " from (select placex.place_id, osm_type, osm_id, class, type, housenumber, admin_level, rank_address, rank_search, geometry, name from placex ";
$sSQL .= " where parent_place_id = $iPlaceID order by rank_address asc,rank_search asc limit 500) as obj,";
$sSQL .= " (select geometry as placegeometry from placex where place_id = $iPlaceID) as x";
$sSQL .= " (select centroid as placegeometry from placex where place_id = $iPlaceID) as x";
$sSQL .= " order by rank_address asc,rank_search asc,localname,housenumber";
$aParentOfLines = $oDB->getAll($sSQL);
if (PEAR::isError($aParentOfLines)) // possible timeout
{
$aParentOfLines = [];
}
$aPlaceSearchNameKeywords = false;
$aPlaceSearchAddressKeywords = false;
@@ -112,12 +135,31 @@
{
$sSQL = "select * from search_name where place_id = $iPlaceID";
$aPlaceSearchName = $oDB->getRow($sSQL);
if (PEAR::isError($aPlaceSearchName)) // possible timeout
{
$aPlaceSearchName = [];
}
$sSQL = "select * from word where word_id in (".substr($aPlaceSearchName['name_vector'],1,-1).")";
$aPlaceSearchNameKeywords = $oDB->getAll($sSQL);
if (PEAR::isError($aPlaceSearchNameKeywords)) // possible timeout
{
$aPlaceSearchNameKeywords = [];
}
$sSQL = "select * from word where word_id in (".substr($aPlaceSearchName['nameaddress_vector'],1,-1).")";
$aPlaceSearchAddressKeywords = $oDB->getAll($sSQL);
if (PEAR::isError($aPlaceSearchAddressKeywords)) // possible timeout
{
$aPlaceSearchAddressKeywords = [];
}
}
logEnd($oDB, $hLog, 1);
$sTileURL = CONST_Map_Tile_URL;
$sTileAttribution = CONST_Map_Tile_Attribution;
include(CONST_BasePath.'/lib/template/details-'.$sOutputFormat.'.php');

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
website/images/layers.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

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