Compare commits

...

648 Commits

Author SHA1 Message Date
Sarah Hoffmann
748fa3e28f prepare for release 3.0.0 2017-06-25 20:58:59 +02:00
Sarah Hoffmann
7ef0239f19 make naming of documentation files consistent 2017-06-25 17:18:21 +02:00
Sarah Hoffmann
2daa4ed813 add extensive debug messages for placex 2017-06-15 23:17:34 +02:00
Sarah Hoffmann
8714fa7dec refine bug report information 2017-06-14 16:18:54 +02:00
Sarah Hoffmann
896421fe9f improve update interval computation
Don't do anything if a downloaded diff is empty after all
(may be happening when an empty diff was published upstream).

Correctly compute the waiting interval before checking for new
data. As the interval is now computed based on the date of the
newest object in the database, the configured intervals need
to be adjusted slightly to take into account the time it takes
for the server to publish a diff.
2017-06-11 09:21:24 +02:00
Sarah Hoffmann
4e6c75040e Guard against network failures in getDatabaseDate()
When updating use the date from the diff file instead
as we are guaranteed to get this if the file has been
successfully loaded.
2017-06-09 21:49:31 +02:00
Sarah Hoffmann
7448d3f171 recompile installation instructions 2017-06-09 20:12:29 +02:00
Sarah Hoffmann
5e5713b90f Ignore postcodes with comma and semicolon when computing address
OSM has sometimes postcode lists for cities which should
simply be ignored.

Fixes #673.
2017-06-07 23:19:56 +02:00
Sarah Hoffmann
9785aff76c restrict linked places to place nodes
Avoids getting the wrong entry when the linked place has
double tagging.

Fixes #573.
2017-06-07 21:32:02 +02:00
Sarah Hoffmann
f4e958a66d get precomputed housenumbers and postcodes from address column 2017-06-07 20:35:41 +02:00
Sarah Hoffmann
5a5691b5b7 force update of linker when linkee is updates
Potential name changes need to be added to the linker's
name hstore.

Fixes #170.
2017-06-06 23:46:44 +02:00
Sarah Hoffmann
9848381a04 remove wip tags from all tests 2017-06-06 22:01:52 +02:00
Sarah Hoffmann
623d58b67e Remove boundries when downgrading from polygon to line
Fixes #135.
2017-06-06 21:59:36 +02:00
Sarah Hoffmann
6985abc3fd Merge pull request #745 from lonvia/restrict-poi-queries-results
limit number of considered places in POI queries
2017-06-06 20:55:15 +02:00
Sarah Hoffmann
0628aa887f adapt postcode centroid import to new address hstore
The postcode now needs to be saved in address->'postcode'
not in the postcode column which is derived only later while
indexing.

Fixes #746.

Thanks to @kkoop.
2017-06-06 20:42:13 +02:00
Sarah Hoffmann
c13094acfd limit number of considered places in POI queries
When searching for POIs in place_classtype_ tables limit the number
of objects considered to 300. The distinct and order by clauses
forced until now to retrive all matching objects and order them
first which can cause long running queries when retriving them
for large areas like the US.

Fixes #735.
2017-06-05 22:40:42 +02:00
Sarah Hoffmann
308bfcbf25 advertise official location for test data on nominatim.org 2017-06-05 22:01:42 +02:00
Sarah Hoffmann
de0ad657ba fix formatting in test README 2017-06-05 21:53:45 +02:00
Sarah Hoffmann
13674c3939 update osm2pgsql (revert use of "char") 2017-06-05 09:08:23 +02:00
Sarah Hoffmann
b9cc47ee67 Revert "use "char" type when refering to osm_type column"
This reverts commit 2dd7f0156a.
2017-06-05 09:07:47 +02:00
Sarah Hoffmann
6db110f5cb Merge pull request #742 from lonvia/compare-normalized
Require more exact match for special search terms
2017-06-05 08:44:04 +02:00
Sarah Hoffmann
af81c6aa94 add special terms import to travis testing and fixup libs 2017-06-04 23:15:19 +02:00
Sarah Hoffmann
54393addd3 disregard special phrases that do not match fully
Compare the normalized terms imported with the special
terms script with the normalized version of the query string.
Disregard them if they cannot be found. This avoids a significant
number of mismatches due to transliteration issues.

The match will only be done when a normalized word has been set
making this change backwards compatible with older databases.
2017-06-04 23:12:09 +02:00
Sarah Hoffmann
e3fb706c65 add normalized version of special search terms on import
Requires the PHP bindings for libicu, so add that as a requirement.
2017-06-04 23:12:09 +02:00
Sarah Hoffmann
2dd7f0156a use "char" type when refering to osm_type column
When using an explicit cast to char(1) when refering to the
osm_type column postgres won't use the index in some cases.
Observed only on postgres 9.5 from the original Postgres
reporsitories.

Fixes #741.
2017-06-04 14:48:53 +02:00
Sarah Hoffmann
5b8672c10a also need postgres configuration changes for bug reports 2017-06-02 14:06:53 +02:00
Sarah Hoffmann
7a14792e21 update osm2pgsql (libosmium update and clubs)
Adds club key.

Fixes #725.
2017-06-01 20:10:10 +02:00
Sarah Hoffmann
d88c484fa1 remove PHP version check
5.4 is the minimum supported version now.
2017-06-01 20:10:10 +02:00
big-o
bdd90e890b Parameter to enable JSON pretty-printing 2017-06-01 20:10:10 +02:00
Sarah Hoffmann
b5fc5e0a71 Merge pull request #739 from lonvia/max-importance
when linking places compute maximum importance
2017-06-01 00:13:22 +02:00
Sarah Hoffmann
002fa35b92 when linking places compute maximum importance
The linker and the linkee might have different wikipedia
tags and thus different importances. Prefer the higher
value.

Fixes #562.
2017-05-30 23:36:59 +02:00
Sarah Hoffmann
d023578f90 add hints about bug reporting and pull requests 2017-05-27 17:47:39 +02:00
Sarah Hoffmann
1876fe42c9 updates: always remove output file and start with correct sequence id 2017-05-27 17:02:34 +02:00
Sarah Hoffmann
86acaa5264 fix name of constant 2017-05-27 16:42:01 +02:00
Sarah Hoffmann
d898f9aabf update word statistics 2017-05-26 21:58:52 +02:00
Sarah Hoffmann
33c919ab09 Merge pull request #734 from lonvia/use-pyosmium-for-updates
Use pyosmium for updates
2017-05-26 21:43:08 +02:00
Sarah Hoffmann
deca74bc3a Merge pull request #730 from SrihariThalla/update-vagrantmd-doc
Update the formatting in Vagrant markdown doc
2017-05-26 21:39:37 +02:00
Srihari Thalla
74b3251c7a Update the formatting in Vagrant markdown doc 2017-05-26 09:38:37 +05:30
Sarah Hoffmann
65afe13f0a update docs for osmosis to pyosmium change 2017-05-25 16:53:44 +02:00
Sarah Hoffmann
bd4b1b2d08 switch from osmosis to pyosmium for updates
Pyosmium comes with convenient functions for finding the
right state and does not require external files for
rembering the state. Updates can now conveniently
set up by simply running ./utils/update.php --init-updates
and state is kept directly in the import_status table.

This change requires an update in the database schema.
Run the following to update:

ALTER TABLE import_status ADD COLUMN sequence_id integer;
ALTER TABLE import_status ADD COLUMN indexed boolean;
ALTER TABLE import_osmosis_log ADD COLUMN batchseq integer;
2017-05-25 16:26:09 +02:00
Sarah Hoffmann
1a1526ec30 Add FAQ to documentation
For the moment only copies the FAQ entries for installation from the wiki and adds one on running multiple extracts.
2017-05-24 23:29:08 +02:00
Sarah Hoffmann
6830b1229e Merge pull request #724 from lonvia/update-country-list
Update country grid SQL file and move it to nominatim.org
2017-05-13 11:48:34 +02:00
Sarah Hoffmann
e7c8b498d1 update docs for new country grid location
Also updates some dependencies.
2017-05-13 00:13:56 +02:00
Sarah Hoffmann
b15b996cc4 remove base country grid from repo
The updated country grid is significantly larger, so expect it to
be downloaded from the nominatim.org website instead.
2017-05-12 23:02:50 +02:00
Sarah Hoffmann
d8ade1c527 remove another use of place.country_code 2017-04-23 22:46:54 +02:00
Sarah Hoffmann
6043cd5ad8 update osm2pgsql (geometry fix, column reordering) 2017-04-22 18:16:22 +02:00
Sarah Hoffmann
86d5209118 Merge branch 'roques-tetris' 2017-04-22 18:14:05 +02:00
Sarah Hoffmann
c629573230 Merge pull request #708 from lonvia/check-for-invalid-geoms
make sure no invalid geometries end up in placex
2017-04-22 18:12:18 +02:00
Sarah Hoffmann
291a161cc6 make sure no invalid geometries end up in placex 2017-04-22 10:34:03 +02:00
Sarah Hoffmann
4c7145c293 Merge branch 'tetris' of https://github.com/roques/Nominatim into roques-tetris 2017-04-20 20:56:44 +02:00
Christian von Roques
4d4b95923e use SMALLINT for ranks and partition; reorder columns for alignment 2017-04-19 02:18:44 +02:00
Sarah Hoffmann
71e6d5f9a6 fix typo 2017-04-18 22:44:39 +02:00
Sarah Hoffmann
446a5a95bc get pg error on correct connection 2017-04-18 22:29:21 +02:00
Sarah Hoffmann
19edbd3581 send address interpolation import to correct postgres conn 2017-04-18 22:11:58 +02:00
Sarah Hoffmann
166737fb76 also use address column for word count computation 2017-04-18 22:11:09 +02:00
Christian von Roques
b6be33cded explicitly name columns at INSERT 2017-04-18 13:36:02 +02:00
Christian von Roques
c80637b05c deduplicate words: do not look for duplicates in empty partitions 2017-04-15 19:12:25 +02:00
Christian von Roques
3ec67b9193 update: getPostgresVersion requires a database connection 2017-04-15 19:12:25 +02:00
Christian von Roques
40debbc7b5 with PHP7 the result of new() can no longer be assigned by reference 2017-04-15 19:12:25 +02:00
Christian von Roques
ccecabfbf4 correct warm.php --search-only help text 2017-04-15 19:12:25 +02:00
Sarah Hoffmann
1e30e578e0 Merge pull request #700 from lonvia/structured-address-info
Move address information into hstore column
2017-04-13 22:12:19 +02:00
Sarah Hoffmann
29e9683293 update osm2pgsql (structured addresses and new libosmium) 2017-04-11 21:29:10 +02:00
Sarah Hoffmann
8138729aea use centroid for near feature search on rank 30
Rank 30 has some very large geometries (peninsulas, time zones,
etc.) for which a near feature search for the full geometry is
too expensive, so do the search on the centroid only.
2017-04-09 23:12:35 +02:00
Sarah Hoffmann
9bb81731f8 fix operator precedence for hstore 2017-04-09 10:06:31 +02:00
Sarah Hoffmann
050b0a2ced remove street and addr_place columns in placex
The information is onyl needed for parenting,
so no need to store it permanently.
2017-04-08 19:58:10 +02:00
Sarah Hoffmann
3bb903cf92 Remove street and addr_place from location_property_osmline
Derived columns are not needed because parent information is
always computed from scratch. So the columns are just duplicate
information.

Also get address information on nodes from address columns. The
other columns are not necessarily reliable when the node have not
been indexed yet.
2017-04-08 19:58:10 +02:00
Sarah Hoffmann
41afcaddd5 adapt more BDD tests to hstore 2017-04-08 19:58:09 +02:00
Sarah Hoffmann
8c7fa0213f fix DB bd tests for address hstore 2017-04-08 19:57:36 +02:00
Sarah Hoffmann
49b5e4dbad adapt osm2pgsql tests for new address column 2017-04-08 18:58:26 +02:00
Sarah Hoffmann
c8e79397f5 introduce address column for place tables
The column is a hstore containing the full OSM tag with key and
value.
2017-04-08 18:58:26 +02:00
Sarah Hoffmann
43eedfd253 abort osmline update correctly when way nodes are missing
Fixes #695.
2017-03-30 22:14:47 +02:00
Sarah Hoffmann
ee1b25820e Merge pull request #690 from ImreSamu/fix_install_sql_warnings
fix table/sequence ... does not exist
2017-03-27 22:41:52 +02:00
ImreSamu
193cf66328 fix sql warnings
* ERROR:  sequence "seq_postcodes" does not exist
* ERROR:  table "import_polygon_error" does not exist
* ERROR:  table "import_polygon_delete" does not exist
* ERROR:  sequence "file" does not exist
2017-03-27 01:02:29 +02:00
Sarah Hoffmann
77e55fade2 Merge pull request #683 from lonvia/more-url-function
Factor out moreurl computation
2017-03-23 18:25:09 +01:00
Sarah Hoffmann
09f1661638 move moreURL computation into Geocode and include all params
Fixes #678.
2017-03-23 00:16:58 +01:00
Sarah Hoffmann
e841422b1f remove unused code 2017-03-22 23:02:19 +01:00
Sarah Hoffmann
97ade7dd7e Merge pull request #682 from mtmail/update-docs
update docs/*.md based on vagrant/*.sh
2017-03-21 20:54:52 +01:00
marc tobias
e24f53cb34 update docs/*.md based on vagrant/*.sh 2017-03-21 13:16:29 +01:00
Sarah Hoffmann
62b7b76662 Merge pull request #680 from mtmail/git-submodule-hint
Update CMakeLists.txt
2017-03-21 12:44:10 +01:00
mtmail
c7434264ae Update CMakeLists.txt
Ran into the issue this morning.
`git submodules` => `git submodule`
2017-03-21 12:34:24 +01:00
Sarah Hoffmann
026081e131 Merge pull request #676 from mtmail/html-map-position-box-disappeared
On /search.php the map-position box disappeared behind the map tiles
2017-03-20 20:19:41 +01:00
Sarah Hoffmann
47586fd861 Merge pull request #674 from mtmail/leaflet-image-path-changed
leaflet 1.0 changed the path of the marker icon
2017-03-20 20:18:29 +01:00
marc tobias
8e79ece203 On /search.php the map-position box disappeared behind the map tiles 2017-03-20 15:38:12 +01:00
marc tobias
a23bd80a31 leaflet 1.0 changed the path of the marker icon 2017-03-20 12:27:48 +01:00
Sarah Hoffmann
f4a86ff4c4 Merge pull request #671 from mtmail/html-view-use-geojson-geometries
Html view use geojson geometries
2017-03-19 22:53:22 +01:00
Marc Tobias Metten
73c151b3ac update leaflet CSS file as well. Fixes delayed layer animation 2017-03-19 22:38:23 +01:00
Sarah Hoffmann
0a10be6586 Merge pull request #669 from lonvia/address-part-on-intersect
Add all intersecting boundaries to address list for roads
2017-03-19 21:50:45 +01:00
Marc Tobias Metten
1e3bf9729e for search,details in format=HTML return geometry in geojson, not wkt. No longer need leaflet-omnivore plugin 2017-03-19 17:31:00 +01:00
Marc Tobias Metten
924d3a8d6e update leaflet.js 0.7.7 => 1.0.3 2017-03-19 15:53:52 +01:00
Marc Tobias Metten
2a07bb8a7f remove obsolete openlayers theme files 2017-03-19 15:50:00 +01:00
Sarah Hoffmann
b3186d07f5 for roads add all intersecting boundaries to address list
When roads cross boundaries, both administrative entities should
be added to the address list, so that both entities can be used
for searching. Also allows in a second step to better sort out
addresses of POIs on such roads.

Fixes #121.
2017-03-18 12:17:48 +01:00
Sarah Hoffmann
ecee3828b3 Merge pull request #667 from lonvia/refactor-nearpoint
Factor out near point into class
2017-03-18 09:25:07 +01:00
Sarah Hoffmann
a64f992092 Merge pull request #668 from lonvia/warn-on-missing-osm2pgsql
cmake: add a more explicit hint when osm2pgsql is missing
2017-03-18 09:24:47 +01:00
Sarah Hoffmann
5682d1688d cmake: add a more explicit hint when osm2pgsql is missing
Fixes #642.
2017-03-17 23:05:06 +01:00
Sarah Hoffmann
57b35654e7 fix style 2017-03-17 22:36:22 +01:00
Sarah Hoffmann
a67edd328e Merge pull request #665 from openstreetmap/lonvia-patch-1
add unzip tool to requirements for Tiger imports
2017-03-17 22:08:01 +01:00
Sarah Hoffmann
20a4cab57e add tests for nearpoint sql functions 2017-03-16 22:12:20 +01:00
Sarah Hoffmann
ab3b556144 use NearPoint class in Search array 2017-03-16 22:04:30 +01:00
Sarah Hoffmann
1649191ffd adapt unit tests for new NearPoint type 2017-03-15 23:58:51 +01:00
Sarah Hoffmann
41fce277cd make NearPoint its own class 2017-03-15 23:47:35 +01:00
Sarah Hoffmann
39c4c7fce8 add unzip tool to requirements for Tiger imports
Fixes #663
2017-03-15 20:44:06 +01:00
Sarah Hoffmann
3a696e1895 Merge pull request #661 from mtmail/travis-ci-badge
add travis-ci badge ("build passing") to README file
2017-03-12 14:00:11 +01:00
Sarah Hoffmann
a793f698f3 Merge pull request #660 from mtmail/new-github-URL
github.com/twain47 => github.com/openstreetmap
2017-03-12 13:59:11 +01:00
marc tobias
889637321b add travis-ci badge ("build passing") to README file 2017-03-12 13:11:56 +01:00
marc tobias
a52455f160 github.com/twain47 => github.com/openstreetmap 2017-03-12 13:06:25 +01:00
Sarah Hoffmann
9358243b66 Merge pull request #659 from lonvia/full-indexing-in-tests
Fix travis tests and update CONTRIBUTING.md
2017-03-11 17:38:46 +01:00
Sarah Hoffmann
9e54d1d6eb adapt CONTRIBUTING.md to new test locations and tools 2017-03-11 17:13:24 +01:00
Sarah Hoffmann
1aaeee19a1 test: rerun indexing after updates until really all is done
There are caess where indexing needs to be done a second round
because related objects need to be updated.
2017-03-11 17:09:14 +01:00
mtmail
6153ad3b31 Merge pull request #656 from EdwardBetts/master
correct spelling mistakes
2017-03-08 16:36:40 +01:00
Edward Betts
7e3af2debc correct spelling mistakes 2017-03-08 15:06:50 +00:00
Sarah Hoffmann
450a12c6be include housenumbers and postcodes when rechecking for exact matches 2017-02-28 21:40:05 +01:00
mtmail
196c55e341 Merge pull request #649 from ldgeo/master
UI: Extra HTML headers for compatibility on MSIE>8
2017-02-28 17:18:12 +01:00
Ludovic Delauné
2c3317f582 extra headers for compatibility on IE7 2017-02-28 17:08:34 +01:00
Sarah Hoffmann
e0c066d850 make sure the flatnode file is disabled while testing 2017-02-27 22:01:06 +01:00
Sarah Hoffmann
e1cbca2572 add behave settings
removes @Fail tests
2017-02-26 16:46:41 +01:00
Sarah Hoffmann
e1095205e4 fix geometry creation from scene 2017-02-26 16:46:41 +01:00
Sarah Hoffmann
e5c79a1d1f add more interpolation update scenarios (currently failing) 2017-02-26 16:46:41 +01:00
Sarah Hoffmann
6551399bcc test: enable grid support for DB tests 2017-02-26 16:46:41 +01:00
Sarah Hoffmann
c48fb88e6b move interpolaton computation into indexing step
The interpolaton computation needs information from the osm2pgsql
slim tables which may not be available when the data is inserted.

Insertion now only adds a line with basic address information to
location_property_osmline. The line is then split during the
indexing, leading to more lines (which are complete in that case)
being inserted.

Fixes #598.
2017-02-26 16:46:41 +01:00
Sarah Hoffmann
e04838cc71 add node grids for tests and test for interpolation update 2017-02-26 16:46:41 +01:00
Sarah Hoffmann
0916d72ddf Merge pull request #644 from ldgeo/master
fix compilation error (cannot find -lpq)
2017-02-25 09:45:35 +01:00
Ludovic Delauné
a933421860 fix compilation error (cannot find -lpq) 2017-02-23 10:17:25 +01:00
Melvyn Sopacua
66d7f1a058 Set osmosis if available 2017-02-18 17:58:11 +01:00
Sarah Hoffmann
e77a07cbb3 add Kosovo to list of country names
Kosovo will remain in the same partition as Serbia to not disrupt
existing databases.
2017-02-18 16:07:37 +01:00
Sarah Hoffmann
c897b96c41 don't delete names on unknown country boundaries
If a country boundary has a country_code that is unknown to
Nominatim, it would delete all names because the coalascing
with country_name would not yield any result.
2017-02-18 13:51:21 +01:00
Sarah Hoffmann
679e4c47ce Merge pull request #632 from melvyn-sopacua/libxml2-fixes
Fix warnings:
2017-02-15 21:31:42 +01:00
Melvyn Sopacua
13ab03a03a Fix warnings:
- be consistent with (const char *) casts when assigning
- use xmlStrlen instead of strlen when dealing with xmlChar *
2017-02-15 10:17:43 +01:00
Sarah Hoffmann
56962deb30 Merge pull request #630 from lonvia/cascading-make
use properly cascading make for external make file
2017-02-15 09:55:25 +01:00
Sarah Hoffmann
e86516bbaf use properly cascading make for external make file
If make is called directly then the -j option is not
properly propagated. Instead make gives a warning
'No jobserver avilable'.
2017-02-13 21:02:49 +01:00
Sarah Hoffmann
b6acd24e5a Merge pull request #629 from melvyn-sopacua/release-2.6.0a1
Build fixes for BSD-like systems
2017-02-13 20:51:00 +01:00
Melvyn Sopacua
e31cd9717c Use CMAKE_MAKE_PROGRAM instead of hardcoded make
FreeBSD uses `gmake` instead of `make` if GNU make is required to build
a port.
2017-02-13 14:33:14 +01:00
Melvyn Sopacua
6eb6f35f24 BSD compat: use sys/endian.h if available
<byteswap.h> is a linuxism. On BSD-like systems this is <sys/endian.h>
2017-02-13 14:30:48 +01:00
Sarah Hoffmann
e9decd2574 Merge pull request #626 from rory/patch-1
Syntax improvements
2017-02-07 23:32:37 +01:00
Rory McCann
2fd9ffda43 Syntax improvements
use backticks for more fixed-width type things
2017-02-07 14:57:54 +01:00
Sarah Hoffmann
a84a7a70f3 reverse: choose interpolation only when further than point
The ST_DWithin check also includes objects that are the same distance.

Another attempt at #545.
2017-02-05 23:02:21 +01:00
Sarah Hoffmann
dcab7a19e5 reverse: disable interpolation when going up the address hierarchy
Fixes #621.
2017-02-05 13:08:51 +01:00
Sarah Hoffmann
d4c78a982e Merge pull request #620 from sebkur/improve-readme-formatting
Improve markdown of Installation section
2017-02-02 12:12:30 +01:00
Sebastian Kürten
7716e0bc92 Improve markdown of Installation section
Due to indentation issues (code within numbered list needs at least 8
spaces instead of 4) the code would not appear as code but as plain text
without a fixed size font and also without newlines appearing in the
HTML.
2017-02-02 11:58:40 +01:00
Sarah Hoffmann
5dea0658e4 Merge pull request #613 from mtmail/travis-behave-and-split-tests
Replace lettuce with behave in tests. Use python3 Split import and (p…
2017-01-21 09:14:36 +01:00
Marc Tobias Metten
cfd03d7be3 Replace lettuce with behave in tests. Use python3 Split import and (python,php) tests into two travis executions 2017-01-21 02:38:04 +01:00
Sarah Hoffmann
9240e83802 Merge pull request #610 from lonvia/set-lanugage-of-indexer
force language of pgsql to C
2017-01-16 21:09:32 +01:00
Sarah Hoffmann
2c07d5e000 Merge pull request #605 from lonvia/fix-fraction-on-interpolations
Better search radius for interpolations when reverse geocoding
2017-01-15 21:33:47 +01:00
Sarah Hoffmann
ea5fe54c6b force language of pgsql to C
Fixes #558.
2017-01-15 21:31:14 +01:00
Sarah Hoffmann
08d1ec09cc fix viewbox tests
Hamburg may not be complete in the test set
2017-01-09 21:15:41 +01:00
Sarah Hoffmann
b8db8301df reverse: reduce search radius for interpolations
Interpolations should have the same maximum search radius as
address points. Change search strategy and only search for
interpolations either before decreasing the maxRank to road
or when a POI was found and we need to check that there isn't
an interpolation that is closer.
2017-01-09 20:51:16 +01:00
Sarah Hoffmann
d18bd14045 add test for moreURL issue and debugging of test query contents 2017-01-01 17:58:21 +01:00
Sarah Hoffmann
65500927c2 Merge branch 'moreurl-with-countrycodes' of https://github.com/mtmail/Nominatim into mtmail-moreurl-with-countrycodes 2017-01-01 17:36:07 +01:00
Sarah Hoffmann
4a5a997e18 Merge pull request #600 from lonvia/behave-tests-rebased
Rework tests
2017-01-01 10:57:23 +01:00
Sarah Hoffmann
fadffeaa2d remove old bdd tests 2016-12-30 23:16:21 +01:00
Sarah Hoffmann
c0e4a74c71 add mention of required Tiger files for test database 2016-12-30 23:15:41 +01:00
Sarah Hoffmann
b2be8c3ab7 move php tests in common test dir and unify READMEs 2016-12-30 22:58:58 +01:00
Sarah Hoffmann
5252051291 add source files for test database 2016-12-30 22:58:58 +01:00
Sarah Hoffmann
ccaea09a65 move scenes directory to new test directory 2016-12-30 22:58:58 +01:00
Sarah Hoffmann
b2c1d086b5 add api tests for language, details and lookup 2016-12-30 22:58:58 +01:00
Sarah Hoffmann
3a787df934 add remaining reverse tests 2016-12-30 22:58:58 +01:00
Sarah Hoffmann
635ce30db5 add simple reverse API tests 2016-12-30 22:58:58 +01:00
Sarah Hoffmann
201f618cc7 finish search API tests 2016-12-30 22:58:58 +01:00
Sarah Hoffmann
81922fc057 more API search tests
also move directory name back to api
2016-12-30 22:58:58 +01:00
Sarah Hoffmann
b9a58b8f24 add simple direct API search tests
API tests now no longer require a running Apache installation,
instead the website php scripts are called directly using the
appropriate enivronment.
2016-12-30 22:58:58 +01:00
Sarah Hoffmann
b75aadfb6b more backslash tests 2016-12-30 22:58:58 +01:00
Sarah Hoffmann
80a74181e4 add osm2pgsql update tests 2016-12-30 22:58:58 +01:00
Sarah Hoffmann
6f4f19004c add remianing osm2pgsql import tests 2016-12-30 22:58:58 +01:00
Sarah Hoffmann
e2f23e391b add osm2pgsql broken data tests 2016-12-30 22:58:58 +01:00
Sarah Hoffmann
f2debbef19 add simple osm2pgsql tests 2016-12-30 22:58:58 +01:00
Sarah Hoffmann
21a3fc4b0f add remaining db update tests 2016-12-30 22:58:58 +01:00
Sarah Hoffmann
0e9e2bbdca add tests for updating linked features 2016-12-30 22:58:58 +01:00
Sarah Hoffmann
4f2d73aa7c add tests for interpolation updates 2016-12-30 22:58:58 +01:00
Sarah Hoffmann
c20f8b13a5 add simple db update tests 2016-12-30 22:58:58 +01:00
Sarah Hoffmann
7f4e7a2579 add interpolation tests 2016-12-30 22:58:58 +01:00
Sarah Hoffmann
82a0e23265 tests for linking 2016-12-30 22:58:58 +01:00
Sarah Hoffmann
e36e485698 add naming tests 2016-12-30 22:58:58 +01:00
Sarah Hoffmann
ddb7296663 add parenting tests 2016-12-30 22:58:58 +01:00
Sarah Hoffmann
604706a827 ad search_name import tests 2016-12-30 22:58:58 +01:00
Sarah Hoffmann
c594644aa7 add placex import tests 2016-12-30 22:58:58 +01:00
Sarah Hoffmann
47f94c6988 simple search steps 2016-12-30 22:58:57 +01:00
Sarah Hoffmann
c56c09e2c0 rename and add basic tests 2016-12-30 22:58:57 +01:00
Sarah Hoffmann
65bf6dbff7 environment for behave tests 2016-12-30 22:58:57 +01:00
Sarah Hoffmann
7273b58bbe make path to wikipedia files configurable 2016-12-28 23:38:48 +01:00
Marc Tobias Metten
adb6ea546f sMoreURL now includes countrycodes values 2016-12-22 02:06:08 +01:00
Sarah Hoffmann
3ff8bb55a7 update osm2pgsql (quoting fix) 2016-12-17 18:33:15 +01:00
Sarah Hoffmann
99c58706d3 Merge pull request #595 from mtmail/set-webserver-directoryindex
set directoryindex in Apache,nginx configuration
2016-12-16 08:51:18 +01:00
Marc Tobias Metten
523873fe16 set directoryindex in Apache,nginx configuration 2016-12-16 02:16:47 +01:00
Sarah Hoffmann
de01c5b23d Merge pull request #581 from lonvia/update-osm2pgsql
update osm2pgsql
2016-11-20 17:00:43 +01:00
Sarah Hoffmann
57dc135844 do not build osm2pgsql tests 2016-11-19 13:09:11 +01:00
Sarah Hoffmann
e24129febe update osm2pgsql (new libosmium) 2016-11-19 13:04:34 +01:00
marc tobias
b27926fd4d fix PHP warnings when reverse search was called without parameters
... or empty results
2016-11-17 22:55:05 +01:00
Sarah Hoffmann
cfb0f3f94c Merge pull request #548 from lonvia/query-ckeck-utf8
check if query is valid unicode string
2016-11-02 19:21:29 +01:00
Sarah Hoffmann
eaee6b700d adapt tiger reverse test to changed api 2016-11-02 00:11:17 +01:00
Sarah Hoffmann
032f24bfef Merge branch 'ui-easy-switch-coords' of https://github.com/mtmail/Nominatim 2016-11-01 23:49:02 +01:00
marc tobias
d93209ee48 Tiger: set osmtype=way and correct osm_id 2016-11-01 23:34:29 +01:00
marc tobias
eb79e655e6 cleanup of SQL for readability. No logic change 2016-11-01 23:33:47 +01:00
marc tobias
4f3074e538 cleanup of SQL for readability. No logic change 2016-11-01 23:33:47 +01:00
marc tobias
8312e8f539 UI: keep map position when switch to reverse. Easy switching of lat,lon to lon,lat 2016-10-30 17:45:45 +01:00
Sarah Hoffmann
d4daa0c4fa Merge pull request #568 from mtmail/z-index-fix-for-mapbounds-button
fix dropdown menu not overlapping map button
2016-10-29 12:21:49 +02:00
marc tobias
a9ad69efae add missing newline in CSS file 2016-10-29 11:25:21 +02:00
marc tobias
0a45dbf5f6 fix drodown menu not overlapping map button 2016-10-29 11:14:30 +02:00
Sarah Hoffmann
a61f852cd2 fix parameter list for renamed postgis functions
fixes #560
2016-10-24 20:39:49 +02:00
Sarah Hoffmann
26ba5bf0be Merge pull request #556 from lonvia/drop-php-53-support
Drop support for PHP < 5.4
2016-10-20 22:00:18 +02:00
Sarah Hoffmann
702f9477ab Merge pull request #557 from mtmail/test-failure-after-c0b4411
PHP unit test failed after change in c0b4411
2016-10-18 23:06:29 +02:00
Marc Tobias Metten
179542f938 PHP unit test failed after change in c0b4411 2016-10-18 22:54:01 +02:00
Sarah Hoffmann
b77e2503f5 drop support for PHP < 5.4 2016-10-17 22:28:39 +02:00
Sarah Hoffmann
1542a006cb Merge pull request #550 from lonvia/decrease-line-length
Reduce maximum line length to 199
2016-10-16 09:55:13 +02:00
Sarah Hoffmann
bb1c3f23ab reduce maximum line length to 199 for all php files 2016-10-14 00:01:16 +02:00
Sarah Hoffmann
8650e0fedd slightly relax viewbox parameter check
Allow out of bounds parameters as long as the resulting box
covers some legal coodinates.
2016-10-13 08:03:28 +02:00
Sarah Hoffmann
abac5d8ebd split long lines in Geocode.php 2016-10-13 00:27:17 +02:00
Sarah Hoffmann
aa7c8b6b5b fix viewbox parameters in tests 2016-10-13 00:26:04 +02:00
Sarah Hoffmann
e69115fd8f remove debug output 2016-10-12 22:27:46 +02:00
Sarah Hoffmann
7b1f35426d check if query is valid unicode string 2016-10-12 22:25:04 +02:00
Sarah Hoffmann
6757e1b865 properly check format of viewbox parameter 2016-10-12 22:13:07 +02:00
Sarah Hoffmann
c72e6a93dc fix typo in error message 2016-10-12 20:21:12 +02:00
Sarah Hoffmann
c0b4411337 reduce search depth when splitting word sets
Too many out-of-memory conditions with the current algorithm.
2016-10-12 20:09:20 +02:00
Sarah Hoffmann
0e613a362e fix variable name typos 2016-10-10 22:22:35 +02:00
Sarah Hoffmann
4123a3fd6b note phpcs command in contribution readme 2016-10-09 23:08:20 +02:00
Sarah Hoffmann
087522c601 details: check for unknown object and icons 2016-10-09 22:14:19 +02:00
Sarah Hoffmann
fb51d51582 fix syntax error for route boxes 2016-10-09 21:41:23 +02:00
Sarah Hoffmann
f5641037cf avoid passing temporary array by reference
PHP7 complains: Only variables should be passed by reference.
2016-10-09 21:14:59 +02:00
Sarah Hoffmann
39580057fc better error message for missing osm2pgsql 2016-10-09 21:04:53 +02:00
Sarah Hoffmann
a855ffe58e replace deprecated postgis functions
ST_Line_Locate_Point and ST_Distance_Spheroid have changed
spelling in newer version and throw a deprecation warning.
2016-10-09 20:09:59 +02:00
Sarah Hoffmann
42d473968f check for correct array for country codes
fixes trac ticket 5427
2016-10-04 20:32:22 +02:00
Rémi BOURGAREL
8a2e401025 Change on get_addressdata check for matching the condition in placex_update
On placex_update we stop the indexing to the first parent if the rank_search is above 27. We should do the same check in get_adressdata, because place with a rank_address != 30 and a search_rank > 27 will have only 1 parent.
https://github.com/twain47/Nominatim/issues/534
2016-10-04 15:49:31 +02:00
Sarah Hoffmann
a912b3448f docs: fix link 2016-10-02 17:33:49 +02:00
Sarah Hoffmann
8b896f37f3 fill interpolation array for reverse lookups via search endpoint
Fixes #540
2016-10-01 13:03:31 +02:00
Sarah Hoffmann
6bf90eb22f fix namespace use 2016-09-30 22:43:11 +02:00
Sarah Hoffmann
421174ce0c Merge pull request #538 from lonvia/update-default-languages
Update default languages and move country search term creation to setup.php
2016-09-30 20:01:20 +02:00
Sarah Hoffmann
1982978f74 move country search term creation into setup script
Search results can become odd without the country search
terms, so make their inclusion a mandatory part of the
setup.

Also adds a new configuration variable to restrict the
languages taken into account by Nominatim.
2016-09-28 23:30:44 +02:00
Sarah Hoffmann
6fd2887543 update per-country language defaults
Added missing defaults for all mono-lingual countries as per
http://wiki.openstreetmap.org/wiki/Nominatim/Country_Codes
2016-09-28 22:04:29 +02:00
Sarah Hoffmann
44ee8d9ce3 Merge pull request #533 from mtmail/PSR2-php-tests
fix PSR2 warnings in php tests
2016-09-16 21:57:38 +02:00
Sarah Hoffmann
bf77b444bf Merge pull request #532 from mtmail/PSR2-namespaces
add namespaces, method visibility according to PSR2 standard
2016-09-16 21:55:44 +02:00
Marc Tobias Metten
a7da0c90bf fix PSR2 warnings in php tests 2016-09-16 02:45:42 +02:00
Marc Tobias Metten
6238ae6032 add namespaces, method visibility according to PSR2 standard 2016-09-16 02:27:36 +02:00
Sarah Hoffmann
d437a14f25 vagrant: use old configs when updating
Otherwise we may overwrite vagrant-specific settings like
nopassword for sudo.
2016-09-15 23:08:54 +02:00
Sarah Hoffmann
e1be3d9f48 Merge branch 'PSR2-fixes-for-settings' of https://github.com/mtmail/Nominatim into mtmail-misc-psr-fixes 2016-09-15 21:53:12 +02:00
Sarah Hoffmann
e686ce8680 Merge branch 'PSR2-fixes-for-wikidata' of https://github.com/mtmail/Nominatim into mtmail-misc-psr-fixes 2016-09-15 21:51:48 +02:00
Marc Tobias Metten
93c26a0e65 half-reverting 51155b63, We dont need two of three break statements after all 2016-09-15 19:36:32 +02:00
Marc Tobias Metten
02550cc4dc PSR2 fixes for /settings 2016-09-14 03:50:18 +02:00
Marc Tobias Metten
b243aa84e2 PSR2 fixes for /wikidata and /tests-php directories 2016-09-14 03:39:17 +02:00
Marc Tobias Metten
cfed4bc204 PHP linter looks for phpcs.xml by default. Also removed a couple of exceptions that didnt cause warnings 2016-09-14 03:23:43 +02:00
Marc Tobias Metten
4a321487f3 fix indentation and misc errors according to PSR2 coding style guide 2016-09-14 03:16:46 +02:00
Marc Tobias Metten
74c06ef877 PHP linter looks for phpcs.xml by default. Also removed a couple of exceptions that didnt cause warnings 2016-09-14 03:15:46 +02:00
Marc Tobias Metten
51155b639b case statement need : instead of ;. Added more breaks 2016-09-14 03:00:57 +02:00
Marc Tobias Metten
775fdeb8e4 UI: viewbox parameter was set in wrong parameter order 2016-09-13 14:41:56 +02:00
Sarah Hoffmann
eb0b3bfa4c Merge pull request #524 from mtmail/PSR2-function-declarations
fix function declaration errors according to PSR2 coding style guide
2016-09-11 12:07:35 +02:00
Marc Tobias Metten
2a784fa3d4 fix function declaration errors according to PSR2 coding style guide 2016-09-11 05:22:51 +02:00
Marc Tobias Metten
5c40100b57 code style definitions: we no longer use tabs 2016-09-11 05:21:51 +02:00
Marc Tobias Metten
ae5cc28a1a add PHP code-sniffer to installation instructions (marked optional) 2016-09-11 05:21:15 +02:00
Sarah Hoffmann
cf39e07dba Merge pull request #522 from mtmail/PSR2-arrays
fix array-related errors according to PSR2 coding style guide
2016-09-10 23:35:25 +02:00
marc tobias
e49ed1bb13 make apt-get noninteractive. Also fixes the grub error state
grub complains about disc unique identifier having changed
2016-09-10 23:29:59 +02:00
marc tobias
3887423381 fix array-related errors according to PSR2 coding style guide 2016-09-10 21:10:52 +02:00
marc tobias
f05ea577f4 bracket spacing for if/else/for/foreach/while/switch according to PSR2 standard 2016-09-08 02:16:22 +01:00
Sarah Hoffmann
effd8e12af Merge branch 'delete-us-postcode-without-name' of https://github.com/mtmail/Nominatim 2016-09-05 23:09:32 +02:00
Sarah Hoffmann
89c157a6c1 adapt coding style for new spaces-only policy 2016-09-05 22:13:08 +02:00
Marc Tobias Metten
832547f192 tabs-to-spaces 2016-09-04 03:19:48 +02:00
Marc Tobias Metten
36fdfd92ad one US postcode has no name. Unable to find secondary source what it would have been 2016-09-04 02:15:51 +02:00
Sarah Hoffmann
cd6dcfa574 Merge pull request #498 from mtmail/move-mouse-position-info-on-map
HTML map: new button -show map bounds-
2016-08-24 22:19:48 +02:00
Sarah Hoffmann
8a796db3c9 Merge pull request #508 from mtmail/addtype-in-installation.md
typo in Installation.md
2016-08-24 08:49:45 +02:00
Marc Tobias Metten
87b6810eba HTML map: new button -show map bounds- in top right corner 2016-08-24 04:21:28 +02:00
mtmail
50c994be93 Update Installation.md
trivial typo: AddTpe => AddType
2016-08-24 01:45:36 +02:00
Marc Tobias Metten
797c2d1e74 Merge remote-tracking branch 'upstream/master' into move-mouse-position-info-on-map 2016-08-24 00:03:40 +02:00
Sarah Hoffmann
d7c469d94e Merge pull request #504 from lonvia/parameter-parser-class
factor out parameter parsing into its own class
2016-08-23 21:57:06 +02:00
Sarah Hoffmann
3b7baca46c Merge pull request #506 from mtmail/primary-vagrant-vm
specify ubuntu as primary Vagrant VM
2016-08-22 09:41:46 +02:00
marc tobias
0957bd27c6 specify ubuntu as primary Vagrant VM 2016-08-22 05:47:26 +02:00
Sarah Hoffmann
5464dec057 factor out parameter parsing into its own class
Allows to use the parsing functions in website/search.php and
utils/query.php as well.
2016-08-20 13:43:50 +02:00
Sarah Hoffmann
feb458f8dd update tests for newer planet 2016-08-19 23:57:23 +02:00
Sarah Hoffmann
9c1e0c49bf docs: give recomendations about flatnode file size
closes #501
2016-08-10 22:02:10 +02:00
Sarah Hoffmann
36f2afea8a mark checkpoint_segments parameter as deprecated
Postgresql 9.5 has checkpoint_segments removed and fails to start
if the options is given. Adds a comment to that effect.

Fixes #494.
2016-08-04 22:17:05 +02:00
Sarah Hoffmann
5c187e131a Merge pull request #499 from mtmail/travis-ci
Travis ci setup - tests pass
2016-08-03 08:35:32 +02:00
Marc Tobias Metten
cb68a2cdd2 Merge remote-tracking branch 'upstream/master' into travis-ci 2016-08-03 01:10:30 +02:00
Marc Tobias Metten
3499ed7b82 travis-ci: enable river tests again, numpy package was missing 2016-08-03 00:57:30 +02:00
Marc Tobias Metten
9ff24b9107 travis-ci: enable river tests again, numpy package was missing 2016-08-03 00:54:49 +02:00
Sarah Hoffmann
ee7a6e8f92 update paths in vagrant docs 2016-08-02 22:55:13 +02:00
Sarah Hoffmann
88d623b631 Merge pull request #497 from lonvia/forbid-execution-from-sourcedir
fail on execution of util scripts from source directory
2016-08-02 22:42:20 +02:00
mtmail
2a97ce6aed Merge pull request #476 from mtmail/travis-ci
travis-ci setup
2016-08-01 02:03:45 +02:00
Marc Tobias Metten
bb403e2e58 HTML map: new button -show map bounds- 2016-08-01 01:34:03 +02:00
Sarah Hoffmann
496d6bf168 fail on execution of util scripts from source directory
Utils scripts must be run from the build directory to make sure
we get the right paths. Rename the settings file in source and
replace the original one with an error, so that scripts
fail with an understandable error message when run from the
source directory.
2016-07-31 22:55:38 +02:00
Marc Tobias Metten
b00169e634 travis: exclude poldi, waterway tests 2016-07-31 02:33:47 +02:00
Marc Tobias Metten
9be58ffc7c travis: exclude poldi, waterway tests 2016-07-31 02:18:27 +02:00
Marc Tobias Metten
1fb847a5ad travis: exclude poldi, waterway tests 2016-07-31 02:17:28 +02:00
Marc Tobias Metten
8a823d1361 Merge remote-tracking branch 'upstream/master' into travis-ci 2016-07-30 21:53:27 +02:00
Sarah Hoffmann
ab30a69ad9 Merge pull request #490 from lonvia/streamline-class-interfaces
Code cleanup for geocode classes
2016-07-27 20:56:10 +02:00
Sarah Hoffmann
0a95bdc5f5 remove unused functions in Geocode 2016-07-26 23:10:50 +02:00
Sarah Hoffmann
d594bb238b cleanup interface of PlaceLookup
Move lookup parameters (place id, type, frac etc.) from members
to parameters for lookup().
2016-07-26 20:54:14 +02:00
Sarah Hoffmann
0d179b8c97 remove unnecessary local variable 2016-07-26 20:54:14 +02:00
Sarah Hoffmann
1b33999f10 refactor ReverseGeocode
- remove unused functions and members
- move coordinates from being members to being parameters of lookup()
2016-07-26 20:54:14 +02:00
Sarah Hoffmann
3f06d9d3ba fix typos and grammar in installation instructions 2016-07-26 20:38:44 +02:00
Sarah Hoffmann
7da9178b83 Merge pull request #487 from lonvia/unify-reverse
Remove duplicate reverse geocoding code
2016-07-25 22:15:28 +02:00
Sarah Hoffmann
a766240c06 remove duplicate reverse geocoding code
Geocode now uses ReverseGeocode directly. Note that it currently
cannot support any interpolations, neither OSM nor Tiger. But
neither did the previous version.
2016-07-24 23:58:39 +02:00
Sarah Hoffmann
a827367a2f adapt Tiger reverse test to new output format 2016-07-24 23:58:21 +02:00
Sarah Hoffmann
4f75f4cb6e remove IP blocking and rate-limiting code
Closes #472.
2016-07-18 21:33:09 +02:00
Sarah Hoffmann
975c30afba Merge pull request #486 from IrlJidel/patch-1
pgsqlRunPartitionScript needs global $aCMDResult
2016-07-16 10:09:09 +02:00
IrlJidel
ca92442601 pgsqlRunPartitionScript needs global $aCMDResult
function pgsqlRunPartitionScript  was missing global $aCMDResult

setup was failing with

...
PHP Notice:  Undefined variable: aCMDResult in /home/roles/nominatim/app/Nominatim/build/utils/setup.php on line 768
NOTICE:  type "nearplace" does not exist, skipping
..
ERROR:  relation "location_area_large_0" already exists
ERROR: pgsql returned with error code (3)
pgsql returned with error code (3)
Command exited with non-zero status 255
2016-07-14 19:49:58 +01:00
Marc Tobias Metten
77ca079688 travis-ci setup, some tests fails 2016-06-21 23:42:36 +02:00
Sarah Hoffmann
665de339e5 allow coordinates in query only with name or classtype
Coordinates with country or housenumber only do not make much
sense. Currently these combination result in queries that
require a sequential scan of search_name and normally time
out before yielding any results.

fixes #462
2016-06-15 22:41:48 +02:00
Sarah Hoffmann
84495489d9 fix links to documentation in README 2016-06-14 23:11:14 +02:00
Sarah Hoffmann
8eb0e09ce3 more instructions for Tiger imports 2016-06-14 21:44:18 +02:00
Sarah Hoffmann
2ab43f6367 reverse do not downgrade tiger and interpolation results
Also fix the type that is returned for Tiger data.

Fixes #470
2016-06-14 21:38:03 +02:00
Sarah Hoffmann
b14bc75dc4 Merge pull request #469 from lonvia/refactor-php
Some refactoring of website php
2016-06-13 20:13:38 +02:00
Sarah Hoffmann
860acbf6af add instructions to enable use of Tiger data 2016-06-13 20:07:57 +02:00
Sarah Hoffmann
10c5d7f6f6 fix more syntax errors in error functions 2016-06-12 23:25:47 +02:00
Sarah Hoffmann
e842d8793c allow parameters to be empty
Consider empty parameters as unset and use the default. Simplifies
use in forms.
2016-06-12 23:22:14 +02:00
Sarah Hoffmann
348a3082c9 fix syntax errors and update tests
Some of the tests with bad parameters now return a HTTP 400.
2016-06-12 22:51:13 +02:00
Sarah Hoffmann
033b9590bd use chksql everywhere in lib/
Replaces manual PEAR error checks and adds the chksql wrapper
where the error checks were still missing.
2016-06-12 14:58:05 +02:00
Sarah Hoffmann
95961d098d introduce chksql function for website code and move other fail functions
The default error screen now reports the full SQL even when not
in debug mode as this message is often more helpful than our
custom error message.
2016-06-12 14:34:57 +02:00
Sarah Hoffmann
7a50d2f996 factor out link formatting function and osm type translation 2016-06-12 12:39:09 +02:00
Sarah Hoffmann
6fef943e49 update links to OSM objects
/browse/ is no longer necesary in the URL
2016-06-12 09:26:58 +02:00
Sarah Hoffmann
76b9eb8098 remove now unused bAsPoints in reverse API 2016-06-11 23:27:21 +02:00
Sarah Hoffmann
d45524cbfb introduce accessor function for URL parameter
These functions take care of type conversion and check that
the parameters contain legal values. The API now returns a
Bad Request error if the format is wrong.
2016-06-11 23:07:06 +02:00
Sarah Hoffmann
aa9fff9199 polygons.php: print total number of broken polygons 2016-06-11 00:01:24 +02:00
Sarah Hoffmann
1a47376040 remove dead code 2016-06-11 00:01:24 +02:00
Sarah Hoffmann
051998dd80 Merge pull request #219 from mizabrik/master
Fix case sensitivity of cyrillic ghe
2016-06-09 21:53:56 +02:00
Sarah Hoffmann
cf4a44aaf7 introduce chksql function for phpscripts
Checks SQL query results for errors and bails out if it finds one.
Avoids some heavy code duplication all over the place.
2016-06-09 20:37:51 +02:00
Sarah Hoffmann
85c72cdccd remove --create-website function
Symlinking does not go well with the separate build directory.
The recommended method is now to serve the website directly from
build/website via an alias. 'website installation' may be
reintroduced later via cmake.
2016-06-08 23:41:36 +02:00
Sarah Hoffmann
3a41b0dfbf Merge pull request #464 from lonvia/vagrant-with-docs
Move installation documentation from wiki into /docs directory
2016-06-08 23:25:50 +02:00
Sarah Hoffmann
6436bab1be remove old vagrant scripts 2016-06-08 23:23:09 +02:00
Sarah Hoffmann
91e1e4d614 fix formatting of docs 2016-06-08 23:17:48 +02:00
Sarah Hoffmann
af93973237 add compiled vagrant docs in docs/ directory 2016-06-08 23:06:15 +02:00
Sarah Hoffmann
2e08a61565 add vagrant script for ubuntu 16 and polish everything 2016-06-08 23:03:11 +02:00
Sarah Hoffmann
0adb8cb765 fix cut&paste error in php tests 2016-06-08 22:51:56 +02:00
Sarah Hoffmann
f71e9dd187 move installation instructions from wiki page here 2016-06-07 22:47:57 +02:00
Sarah Hoffmann
186a633185 fix apache permission problems in CentOS vagrant script 2016-06-07 00:27:20 +02:00
Sarah Hoffmann
d1b1acaf1d split instruction into software installation and import
Basically leaves the part that needs to be done by the automatic
vagrant script in the bash script and moves the remaining part
into an OS-independent md file.

Also fixes some of the instructions for CentOS. Now almost runs
through (some minor issue with permission remains).
2016-06-07 00:17:15 +02:00
Sarah Hoffmann
ff6c3a705b initial version of documented CentOS7 vagrant script 2016-06-05 16:15:26 +02:00
Sarah Hoffmann
badd2e46aa provide srcdir for postgres module in VPATH and CPPFLAGS
The pgxs makefile in Postgres <= 9.2 cannot yet handle VPATH
correctly. Provide header paths explicitly and overwrite
VPATH after sourcing the pgxs file.

Fixes #454.
2016-06-05 00:35:07 +02:00
markigail
98e5ba6b61 use place_id instead of parent_place_id for excluded place_ids in interpolation lines query 2016-06-04 23:54:17 +02:00
Sarah Hoffmann
2156fb1ad7 remove reference assignment where unnecessary
Avoids a number of warnings on PHP7.
2016-06-04 23:46:19 +02:00
Sarah Hoffmann
92095c9247 Merge branch 'interpolations' 2016-06-04 23:29:11 +02:00
Sarah Hoffmann
524bd47315 fill place and osmline independently for interpolations on update
interpolation lines may be missing in osmline when the interpolation
is broken, so we cannot conclude that a way is not in place, just
because there are no entries in location_property_osmline.
2016-05-28 18:18:18 +02:00
Sarah Hoffmann
c3e21ea388 reinstate tests for geometrytype 2016-05-27 23:36:01 +02:00
Sarah Hoffmann
f0d962f8a0 fix variable name in search xml output 2016-05-27 23:35:24 +02:00
Sarah Hoffmann
e4963256e1 cmake: use explicit VPATH when calling pgxs makefile
Some postgres installations report problems with the makefile
magic that should look for the source where the Makefile is
located. So hand in the path explicitly via VPATH instead.

Fixes #453.
2016-05-24 00:24:23 +02:00
Sarah Hoffmann
362f259f47 cmake: force-set options and explicitly check for pgxs makefile
fixes #443
2016-05-23 22:20:59 +02:00
Sarah Hoffmann
8b91284f7f reintroduce addr:place for interpolation
It is perfectly valid that interpolated addresses refer to
something else than a street.

Also gets rid of the maximum interpolation size. As we don't
expand, arbitrary sizes are fine.
2016-05-15 14:24:43 +02:00
Sarah Hoffmann
2a0c7fb57a tests: permit duplicate entries in interpolation table
fixes self-intersecting interpolation test
2016-05-15 14:24:12 +02:00
Sarah Hoffmann
2fecc0c465 tests for interpolation to building type change 2016-05-15 12:37:49 +02:00
Sarah Hoffmann
94d795883f update comments and formatting 2016-05-15 12:37:20 +02:00
Sarah Hoffmann
f0f6fcf256 fix scene making scripts and add building-parallel-road scene
Scripts updated to newest libosmium and shebang fixed.
2016-05-15 12:36:16 +02:00
Sarah Hoffmann
28041cbbd9 remove duplicate index 2016-05-15 11:44:54 +02:00
Sarah Hoffmann
821949f087 get housenumber data for interpolations from place table
The placex table may not yet be filled when the interpolation
lines are computed.
2016-05-15 09:44:00 +02:00
Sarah Hoffmann
0fcab79486 fix syntax in load-data function
Also makes sure that load data runs with at least 2 threads: one
for loading placex and one for loading osmline.
2016-05-15 09:41:11 +02:00
Sarah Hoffmann
234b1b0293 Merge remote-tracking branch 'markus/master' into master 2016-05-14 21:09:57 +02:00
markigail
f07d620ee8 Change load-data in setup.php. 2016-05-11 10:22:03 +02:00
markigail
190a72cab5 Fix bug in index.c and remove column admin_level from location_property_osmline. 2016-05-08 16:46:42 +02:00
markigail
1a4f369e2b fix small bug in index.c 2016-05-03 12:52:08 +02:00
mtmail
ce112f7c20 Merge pull request #447 from lonvia/fix-array-expression
replace new-style [] expression with old-style array()
2016-05-01 11:53:54 +02:00
Sarah Hoffmann
4e0e0c1797 replace new-style [] expression with old-style array()
Also removes some unused code.

fixes #444
2016-05-01 11:22:53 +02:00
Sarah Hoffmann
54ef9105d0 Merge pull request #446 from mtmail/make-outline-clickable-in-ui
UI: the result outline (geojson/polygon) now lets the map handle clicks
2016-05-01 11:11:21 +02:00
marc tobias
9e1421fb6c UI: the result outline (geojson/polygon) now lets the map handle its clicks 2016-05-01 10:47:13 +02:00
Markus Gail
2ba9c11dd0 fix bug in Geocode.php 2016-04-29 10:24:30 +02:00
Markus Gail
db719d489f index on geometry of interpolation lines, and more improvements. 2016-04-27 17:42:59 +02:00
Sarah Hoffmann
7a5aab61ae Merge pull request #441 from mtmail/update-php-to-check-for-correct-js-file
update.php was checking for static file which is no longer part of the project
2016-04-26 21:03:58 +02:00
Marc Tobias Metten
7b4806b2e8 update.php was checking for static file which is no longer part of the project 2016-04-26 20:45:48 +02:00
Markus Gail
a10f537131 Correct merge error in Geocode.php. 2016-04-25 17:44:34 +02:00
Markus Gail
89c556d163 Coding style adaptions and correcting small errors from merge. 2016-04-25 13:58:28 +02:00
Markus Gail
b03be15442 Merge remote-tracking branch 'origin/master' into osmline
Conflicts:
	lib/Geocode.php
	lib/PlaceLookup.php
	sql/functions.sql
	sql/tables.sql
	utils/setup.php
2016-04-25 11:01:04 +02:00
Markus Gail
7879ad44cd Remove interpolation lines from placex and save them in an extra table. 2016-04-25 09:44:01 +02:00
Sarah Hoffmann
131527bdab Merge pull request #436 from lonvia/remove-location-property-tables
remove unused location_property_-partion- tables
2016-04-24 16:05:10 +02:00
Sarah Hoffmann
a244c41ea7 create_sql_functions() needs the commandline parameters
Fixes one failing test.
2016-04-23 11:07:12 +02:00
Sarah Hoffmann
a32f6c66b8 remove unused location_property_-partion- tables 2016-04-23 10:07:57 +02:00
Sarah Hoffmann
b4f0b8b728 apply marker filtering to functions.sql also after table creation
fixes #430
2016-04-21 00:00:15 +02:00
Sarah Hoffmann
af06d31d21 remove duplicate CORS header
fixes #427
2016-04-12 23:04:38 +02:00
Sarah Hoffmann
d01d0c13f4 Merge pull request #425 from lonvia/disable-aux-tables
make tables for external data (Tiger and aux) configurable
2016-04-12 23:00:24 +02:00
Sarah Hoffmann
be268f95e6 Merge pull request #424 from lonvia/cleanup-logging
clean up query logging
2016-04-12 22:58:14 +02:00
Sarah Hoffmann
a86563cfb1 make tables for external data (Tiger and aux) configurable
Introduces two new settings CONST_Use_US_Tiger_Data and
CONST_Use_Aux_Location_data, which are disabled by default.
When false the corresponding tables are ignored in queries
and updates.

Aux and tiger tables are no longer created by default. This
has to be done by the corresponding import scripts. The former
aux table creation can be found in sql/aux_tables.sql for
reference.
2016-04-07 21:47:51 +02:00
Sarah Hoffmann
009882999f clean up query logging
- remove query_log table, keeping only new_query_log
- drop unused import_npi_log table
- disable DB logging per default
- use file logging structure from osm.org
2016-04-07 20:37:27 +02:00
Sarah Hoffmann
1da4fed9b5 Merge pull request #420 from lonvia/remove-explicit-software-versions
Remove unsupported/unused features and settings
2016-04-01 23:03:01 +02:00
Sarah Hoffmann
6ee4b30ee9 remove deleted us_state* tables from tests as well 2016-04-01 22:59:54 +02:00
Sarah Hoffmann
4f9f21f661 remove state and county data for US and make postcode import optional 2016-03-30 23:21:13 +02:00
Sarah Hoffmann
527c3390f4 remove unused settings 2016-03-30 23:03:10 +02:00
Sarah Hoffmann
f9a488cd5a remove 'closed for indexing' feature
Simultanous updates are fine these days.
2016-03-30 22:53:19 +02:00
Sarah Hoffmann
02bd322c1d remove explicitly set postgres/postgis version
Get the version from the database where necessary or simply
probe for existence of features. Fake hstore_to_json when
necessary.

Bumps the minimum required versions fro postgres to 9.1 and
for postgis to 2.0.
2016-03-30 22:48:18 +02:00
Sarah Hoffmann
a0acc6e913 Merge pull request #416 from lonvia/dead-code-removal
Remove unused and/or unmaintained php code
2016-03-30 20:33:54 +02:00
Sarah Hoffmann
0419aada6e test: catch script output in as debug log output 2016-03-29 23:14:03 +02:00
Sarah Hoffmann
6f442b6617 remove unused functions in php library 2016-03-28 22:55:21 +02:00
Sarah Hoffmann
a0a5100807 remove unused files 2016-03-28 22:30:56 +02:00
Sarah Hoffmann
a769fc4ff3 remove unused/unmaintained options in import scripts 2016-03-28 22:20:31 +02:00
Sarah Hoffmann
83cca343c3 Fix fixing of coding style 2016-03-28 22:04:08 +02:00
Sarah Hoffmann
bfcbb94aed exclude Tiger stuff from required tests 2016-03-28 17:17:56 +02:00
Sarah Hoffmann
5d928d5187 adapt tests to new tiger algorithm 2016-03-28 17:08:27 +02:00
Sarah Hoffmann
23fa6018a4 make sure linked places get recomputed when unlinked
When linked the place may not be in the search index,
so it must be reindexed when being unlinked. The status
change will only have an effect during the subsequent
update, so change tests to that effect.
2016-03-28 09:51:29 +02:00
Sarah Hoffmann
53eb9a5f14 fix syntax errors in tiger code and adapt format of dummy tables 2016-03-27 23:45:20 +02:00
Sarah Hoffmann
443bfec035 Merge branch 'tigerlines' of https://github.com/markigail/Nominatim 2016-03-27 20:00:15 +02:00
Sarah Hoffmann
8534ce5ec2 tests: update for osm2gsql changes
Also fixes a missing type set for query.php tests.
2016-03-25 12:07:22 +01:00
Sarah Hoffmann
92bedbb881 Add hints about coding style
heavily borrowed from osm2pgsql
2016-03-25 12:06:30 +01:00
Sarah Hoffmann
7090604de7 reinstate NOMINATIM_SETTINGS variable
Move sourcing of this script to settings.php so that
it is loaded before anything else.
2016-03-24 22:06:54 +01:00
Markus Gail
7dd0a63b68 Fix coding style. 2016-03-23 09:34:36 +01:00
Markus Gail
a4ecd9d73e Merge branch 'tigerlines' of /home/markus/Nominatim into tiger
Conflicts:
	lib/Geocode.php
	lib/ReverseGeocode.php
	lib/lib.php
2016-03-22 11:26:39 +01:00
Markus Gail
e94b667e16 adapt to code style conventions 2016-03-21 14:15:22 +01:00
Markus Gail
f6127df15d add osm_type='tiger' to json, jsonv2 and xml output 2016-03-21 14:14:01 +01:00
Markus Gail
a8afb9bd3c Removed unnecessary test for tiger. 2016-03-21 14:14:01 +01:00
Markus Gail
86622662bf Removed some files for the commit. 2016-03-21 14:14:01 +01:00
Markus Gail
291fdd1894 Tested Version of new Tiger line storage format. 2016-03-21 14:14:01 +01:00
Markus Gail
46cef36184 Implement geocoding and reverse geocoding with tiger interpolation lines instead of points. 2016-03-21 14:14:01 +01:00
Markus Gail
bc449e10be change tiger housenumber format to save as lines instead of points and thus new interpolation 2016-03-21 14:07:12 +01:00
Markus Gail
d8703c223b adapt to code style conventions 2016-03-21 13:32:44 +01:00
Markus Gail
28166c5bb1 add osm_type='tiger' to json, jsonv2 and xml output 2016-03-21 13:32:44 +01:00
Markus Gail
54fdc572c1 Removed unnecessary test for tiger. 2016-03-21 13:32:44 +01:00
Markus Gail
6fb8fab665 Removed some files for the commit. 2016-03-21 13:32:44 +01:00
Markus Gail
df6b433066 Tested Version of new Tiger line storage format. 2016-03-21 13:32:44 +01:00
Markus Gail
26e30bf8e1 Implement geocoding and reverse geocoding with tiger interpolation lines instead of points. 2016-03-21 13:32:44 +01:00
Markus Gail
49d0ce1de4 change tiger housenumber format to save as lines instead of points and thus new interpolation 2016-03-21 13:32:44 +01:00
marc tobias
d020e05f5b query the last updated timestamp only if output format is HTML 2016-03-21 13:32:44 +01:00
marc tobias
c346c57341 corrected layout of keywords on HTML details page 2016-03-21 13:32:44 +01:00
Marc Tobias Metten
d237549496 moved bIncludePolygonAsPoints related logic into lib.php, added tests 2016-03-21 13:32:44 +01:00
Marc Tobias Metten
607fef2d8f moved bIncludePolygonAsPoints related logic into lib.php, added tests 2016-03-21 13:32:44 +01:00
Sarah Hoffmann
a50bf1c944 update osm2pgsql (WITH_LUA switch) 2016-03-16 20:05:52 +01:00
Sarah Hoffmann
4ea0074548 fix path for website installations 2016-03-16 20:02:09 +01:00
Sarah Hoffmann
4b46c73088 fix nominatim paths 2016-03-16 19:56:10 +01:00
Sarah Hoffmann
6fc32d9645 Merge branch 'cmake-port' into master
Conflicts:
	CMakeLists.txt
	lib/init.php
	settings/settings.php
2016-03-16 19:45:18 +01:00
Sarah Hoffmann
279ea25e7d Merge pull request #381 from lonvia/cmake-port
Replace autotools with cmake and update osm2pgsql
2016-03-13 21:40:38 +01:00
Sarah Hoffmann
50f17666fa Merge pull request #395 from mtmail/php7-support
fix for PHP7, added test setup
2016-03-13 21:38:57 +01:00
Sarah Hoffmann
b097840ba4 Merge pull request #396 from mtmail/fix-array-merge-warning
second argument of array_merge can be empty
2016-03-13 21:37:40 +01:00
Marc Tobias Metten
22ebd1c7a9 second argument of array_merge can be empty 2016-03-13 03:01:19 +01:00
Marc Tobias Metten
df764a3f3b fix for PHP7, added test setup 2016-03-13 02:06:46 +01:00
Sarah Hoffmann
5ccb499a6f install executables and call settings.php explicitly
Executables (including websites) need to be installed in the
build directory, so that they can find the right settings.php.
settings now defines build and source dir.
2016-03-12 09:40:43 +01:00
Sarah Hoffmann
b24ef60b33 enable test execution using ctest 2016-03-12 09:40:43 +01:00
Sarah Hoffmann
6450126933 adapt README and vagrant scripts to cmake 2016-03-12 09:40:43 +01:00
Sarah Hoffmann
314a9e52e9 use external makefile for pgxs with cmake 2016-03-12 09:40:43 +01:00
Sarah Hoffmann
5d7bd37ab2 introduce InstallPath, so that stuff can be executed from build dir 2016-03-12 09:40:43 +01:00
Sarah Hoffmann
c96e71a3d7 add actual cmake file 2016-03-12 09:40:43 +01:00
Sarah Hoffmann
e3f9581a69 move from autotools to cmake and update osm2pgsql 2016-03-12 09:40:43 +01:00
Sarah Hoffmann
1d89098f77 Merge pull request #389 from mtmail/reverse-geocode-include-geometry2
Reverse geocode include geometry (v2)
2016-03-09 23:16:51 +01:00
Marc Tobias Metten
71b3aa9cca Reverse geocode include geometry - added bounding box tests 2016-03-09 19:43:03 +01:00
Marc Tobias Metten
991bd0004a Reverse geocode include geometry 2016-03-04 20:29:09 +01:00
Marc Tobias Metten
d3ff9600b5 Merge remote-tracking branch 'upstream/master' 2016-03-04 15:42:29 +01:00
Sarah Hoffmann
df9850f5ca Merge pull request #385 from mtmail/query-lastupdated-only-for-html-output
query the last updated timestamp only if output format is HTML
2016-03-02 21:36:34 +01:00
Sarah Hoffmann
fa9677242c Merge pull request #384 from mtmail/detail-page-name-keywords-with-wordids
corrected layout of keywords on HTML details page
2016-03-02 21:34:42 +01:00
Marc Tobias Metten
131b06fec3 Merge branch 'master' of https://github.com/mtmail/Nominatim 2016-03-02 15:07:22 +01:00
marc tobias
8e2b5d7ce3 query the last updated timestamp only if output format is HTML 2016-03-02 01:22:19 +01:00
marc tobias
edaa1f7fcd corrected layout of keywords on HTML details page 2016-03-02 00:53:56 +01:00
Sarah Hoffmann
30d56b7064 enable test execution using ctest 2016-02-29 23:45:30 +01:00
Sarah Hoffmann
1ed793f000 adapt README and vagrant scripts to cmake 2016-02-29 22:26:55 +01:00
Sarah Hoffmann
ae9291f625 use external makefile for pgxs with cmake 2016-02-29 22:26:55 +01:00
Sarah Hoffmann
1ad6f4a1ce introduce InstallPath, so that stuff can be executed from build dir 2016-02-29 22:26:55 +01:00
Sarah Hoffmann
932abeb0e2 add actual cmake file 2016-02-29 22:26:55 +01:00
Sarah Hoffmann
35a0f1b246 move from autotools to cmake and update osm2pgsql 2016-02-29 22:26:55 +01:00
Sarah Hoffmann
cb3af09ebd Merge pull request #380 from mtmail/geometryText2Points
Geometry text2 points
2016-02-29 20:53:49 +01:00
Marc Tobias Metten
9fb413a126 corrected layout of keywords on HTML details page 2016-02-29 13:59:16 +01:00
Marc Tobias Metten
27406c8daa corrected layout of keywords on HTML details page 2016-02-29 13:55:19 +01:00
Marc Tobias Metten
f6129ebfee moved bIncludePolygonAsPoints related logic into lib.php, added tests 2016-02-28 17:08:20 +01:00
Marc Tobias Metten
7f5fe8c877 moved bIncludePolygonAsPoints related logic into lib.php, added tests 2016-02-28 17:06:52 +01:00
Sarah Hoffmann
07628dc05d Merge pull request #378 from mtmail/spaces-to-tabs
spaces-to-tabs for all *.php files
2016-02-27 09:56:36 +01:00
Marc Tobias Metten
78a29b5a87 spaces-to-tabs for all *.php files 2016-02-27 00:02:20 +01:00
Sarah Hoffmann
8b75e1f4c4 prepare next release 2016-02-08 23:54:06 +01:00
Sarah Hoffmann
a2994fc55c ubuntu-vagrant: install Nominatim as vagrant user 2016-02-08 23:44:27 +01:00
Sarah Hoffmann
ebdd250fa0 also show line geometries on search page 2016-02-08 23:06:27 +01:00
Sarah Hoffmann
676c565905 update vagrant readme 2016-02-08 23:05:19 +01:00
Sarah Hoffmann
4d15bdaacc add vagrant script for CentOS 2016-02-08 22:58:59 +01:00
Sarah Hoffmann
f9ee4e3bd3 update dependencies in vagrant provision file
also automatically checkout if Nominatim directory does not exist
2016-02-06 18:49:12 +01:00
Sarah Hoffmann
c2112fc6ff add xml2 configure script now missing in osm2pgsql 2016-02-06 18:22:41 +01:00
Sarah Hoffmann
8b491e8544 Merge pull request #361 from mtmail/detail-page-big-table2
UI: columns nicer aligned in details table(s)
2016-02-06 12:51:47 +01:00
Sarah Hoffmann
40588482a2 Merge pull request #362 from mtmail/fix-timeout-on-detail-pages
fix timeout on detail pages related to distance calculation
2016-02-06 12:50:38 +01:00
marc tobias
c2b68c337b remove commented-out lines 2016-02-06 12:49:59 +01:00
marc tobias
a73135aebe fix timeout on detail pages related to distance calculation 2016-02-06 12:43:12 +01:00
marc tobias
634d04068d UI: columns nicer aligned in details table(s) 2016-02-06 12:39:51 +01:00
Sarah Hoffmann
a5883337f5 Merge pull request #354 from mtmail/configurable-tile-url
make map tile layer configurable
2016-01-29 21:11:32 +01:00
Marc Tobias Metten
21385f5e51 make map tile layer configurable 2016-01-27 19:42:49 +01:00
Sarah Hoffmann
4cade95b24 more detailed introduction
fixes #261
2016-01-24 09:22:49 +01:00
Sarah Hoffmann
a9b370fcb2 reverse webpage: don't choose zoom level 0 when none is given 2016-01-22 23:11:47 +01:00
Sarah Hoffmann
355d1efe21 add a short introduction text for the web interface 2016-01-22 23:01:03 +01:00
Sarah Hoffmann
620100a5ac Merge remote-tracking branch 'mtmail/mobile-responsive' 2016-01-22 22:55:34 +01:00
marc tobias
cd37227a3c user interface: zoom dropdown for debugging on reverse search page 2016-01-22 11:54:26 +00:00
marc tobias
690d7014f8 accidentially checked in a local configuration file 2016-01-22 11:53:31 +00:00
marc tobias
ef1a7d9073 user interface: reverse search remembers zoom level after map click 2016-01-21 15:26:18 +00:00
marc tobias
8f0199008d user interface: enable scrollwheel zoom. Disable on touch devices 2016-01-21 14:47:55 +00:00
marc tobias
9f1d3ac272 user interface: less spacing in table, pushing more content above the fold 2016-01-21 13:47:00 +00:00
marc tobias
513efecc34 user interface: less whitespace in header 2016-01-21 12:03:19 +00:00
mtmail
6822e50fe5 Merge pull request #1 from lonvia/mobile-responsive-compact-header
make headers more compact
2016-01-21 11:53:52 +00:00
Sarah Hoffmann
248588fbf3 make headers more compact 2016-01-20 21:14:30 +01:00
Marc Tobias Metten
f01828ae02 accidentally checked in two data files 2016-01-20 01:25:52 +01:00
Marc Tobias Metten
47a7887d86 tests: skip tidylib, it cannot handle HTML5 2016-01-20 01:14:20 +01:00
Marc Tobias Metten
016815eda2 new reverse HTML page incl leaflet map 2016-01-19 16:15:32 +01:00
Marc Tobias Metten
f2a2c29815 responsive details-error page. Shared header and footer 2016-01-19 12:29:07 +01:00
Marc Tobias Metten
97c572b92f Merge branch 'mobile-responsive' of https://github.com/mtmail/Nominatim into mobile-responsive 2016-01-15 17:11:41 +01:00
Marc Tobias Metten
851af3db7f details.php now also responsive 2016-01-15 17:11:12 +01:00
marc tobias
fc961c14fa status after hackweekend London 2016-01-15 17:11:12 +01:00
marc tobias
91f3405713 status after hackweekend London 2016-01-15 17:11:12 +01:00
Sarah Hoffmann
645182f2c0 Merge pull request #345 from netsgnut/updated-tiger-mips
Updated FIPS map in utils/tigerAddressImport.py
2016-01-04 21:03:01 +01:00
Kelvin Wong
e0e812d09b Reverted change on FIPS 35013 to remain ASCII 2016-01-04 23:10:01 +08:00
Kelvin Wong
7e8e952b66 Additional changes to FIPS code
See http://www2.census.gov/geo/docs/reference/codes/files/national_county.txt
2016-01-04 16:18:33 +08:00
Kelvin Wong
32c8dabefe Updated FIPS map in utils/tigerAddressImport.py
See https://www.census.gov/geo/reference/county-changes.html
2016-01-04 15:34:00 +08:00
Sarah Hoffmann
b079b4713f fix versions of pip-installed python modules for vagrant 2015-12-22 22:59:19 +01:00
Sarah Hoffmann
baefb4062f fix dependences in vagrant provision script
Add missing ones and replace manually installed stuff with
distro packages where possible.
2015-12-22 22:57:38 +01:00
Sarah Hoffmann
af150bc63e Merge pull request #340 from calimeroteknik/update-with-exit-errorcodes
utils/update.php: make the process exit with an non-zero error code if the update fails
2015-12-07 20:24:03 +01:00
calimeroteknik
fb7d65b8c3 utils/update.php: use fail() whenever possible for errors 2015-12-07 14:08:02 +01:00
calimeroteknik
dbb1f5c0e2 utils/update.php: make the process exit with an non-zero error code if the update fails 2015-12-07 13:54:05 +01:00
Sarah Hoffmann
2e1281b9a0 Merge pull request #313 from mtmail/more-tests-for-libphp
more tests for lib/lib.php
2015-11-29 10:13:01 +01:00
Marc Tobias Metten
2338d04e9f more tests for libphp - incorporate lonvias feedback 2015-10-15 02:30:51 +02:00
Marc Tobias Metten
111444cd99 more tests for libphp - incorporate lonvias feedback 2015-10-15 02:28:16 +02:00
Marc Tobias Metten
10a965c3ab more tests for lib/lib.php 2015-10-15 02:03:53 +02:00
Brian Quinion
fc9e75a5e6 Revert accidental change of osm2pgsql version 2015-10-07 15:52:56 +01:00
Brian Quinion
347f8e57c7 Allow for postgis being in the default template - not an error if it already is installed 2015-10-07 14:44:59 +01:00
Sarah Hoffmann
f24b904f9a don't use isset for bool options in setup.php 2015-09-27 11:09:55 +02:00
Sarah Hoffmann
0df8a4e24f add more tables and an experimental warning to new --drop function 2015-09-27 11:00:45 +02:00
Sarah Hoffmann
ccca38f22d Merge branch 'drop' of https://github.com/woodpeck/Nominatim 2015-09-27 10:36:31 +02:00
Sarah Hoffmann
b2cca7cea1 Merge pull request #315 from PhiRub/patch-1
Fixed Lat/Long Example
2015-09-26 10:43:20 +02:00
Frederik Ramm
b5c9845448 Add --drop option to setup.php 2015-09-26 01:41:19 +02:00
Sarah Hoffmann
9fb2bf36be streamline get_name_by_language()
patch by mdeweerd
2015-09-24 23:52:03 +02:00
PhiRub
5cc1946dfc Fixed Lat/Long Example 2015-09-03 15:59:40 -05:00
Sarah Hoffmann
fe3eb40e3a disable multithreading in osm2pgsql
not really useful for gazetteer plugin and producing too much overhead
2015-08-29 13:14:11 +02:00
Sarah Hoffmann
7822b1bc25 adapt to new configure variables for postgres 2015-08-29 12:15:19 +02:00
Sarah Hoffmann
5b1eca4c48 add configure script for pgsql server libs
This used to be in osm2pgsql but now has magically disappeared.
2015-08-29 12:04:46 +02:00
Sarah Hoffmann
8375392f39 force sensible file prefixes for generated test files
libosmium needs them to detect the file type
2015-08-29 11:29:09 +02:00
Sarah Hoffmann
71ab123fbb update osm2pgsql (libosmium; source, sidewalk, wikidata tags) 2015-08-29 11:26:12 +02:00
Marc Tobias Metten
c7eea2e419 details.php now also responsive 2015-08-23 07:15:04 +02:00
marc tobias
b0d9c0598e status after hackweekend London 2015-08-23 00:08:40 +02:00
Marc Tobias Metten
1e4c22a037 more tests for lib/lib.php 2015-08-22 23:56:14 +02:00
marc tobias
ce49d3c632 status after hackweekend London 2015-08-22 23:41:25 +02:00
Sarah Hoffmann
6479768932 gazetteer: exclude sidewalks 2015-08-17 22:41:40 +02:00
Sarah Hoffmann
5c187182a3 fix json output of empty arrays 2015-08-15 09:52:48 +02:00
Sarah Hoffmann
c242386ddb use url with php prefix in more url
User may not want to set up URL rewriting for suffixes.

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

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

This is useful when getting border polygons for whole countries, but
rendering them at large scale, when most of the high resolution details
cannot be seen anyway.  For example, the unsimplified polygon data for
Germany in GeoJSON format currently makes for about 3 MB response body.
With use of this new parameter, the application can greatly reduce the
amount of downloaded data and server response time while providing its
users with the same picture.  On a typical laptop screen resolution,
zooming out to fit the whole country borders on screen, only 1/100 amount
of details could be well enough.
2015-04-27 15:16:38 +02:00
Sarah Hoffmann
07cbf1535b set software version defaults to something more recent 2015-04-19 23:49:40 +02:00
Sarah Hoffmann
5eb56c11ba prepare next release 2015-04-18 22:48:46 +02:00
Sarah Hoffmann
b82c8ceab9 ignore places without housenumber in interpolations
fixes trac ticket 5311
2015-04-18 17:47:49 +02:00
Brian Quinion
a5a0e1dd0b Various places where conversion from to ->aStructuredQuery had been missed 2015-04-07 14:04:08 +01:00
Sarah Hoffmann
ddcb95ca39 fix boundary test 2015-03-31 23:07:52 +02:00
Sarah Hoffmann
4a3dc3187c clean out dead sql code 2015-03-30 23:43:27 +02:00
Sarah Hoffmann
133dd2e974 make sure place exists before printing hierarchy 2015-03-29 19:03:51 +02:00
Sarah Hoffmann
eb1d8894b9 correctly handle comma-only exclude_place_ids 2015-03-29 18:17:52 +02:00
Sarah Hoffmann
59be7846e9 fix utf8 in tests for jsonp 2015-03-29 18:17:28 +02:00
Sarah Hoffmann
aaabf70a1c correctly quote regular expression 2015-03-29 17:23:06 +02:00
Sarah Hoffmann
987b6a70c9 use unescaped unicode in json where supported by PHP 2015-03-29 13:02:21 +02:00
Sarah Hoffmann
2bcd1aa194 avoid calling add_location for non-addressing features 2015-03-25 22:25:03 +01:00
Sarah Hoffmann
86b4df1e81 only address features can be linked with placex 2015-03-23 22:04:43 +01:00
Sarah Hoffmann
753227ae25 more strict parameter checking for reverse 2015-03-17 21:06:58 +01:00
Sarah Hoffmann
ef48ee5f80 update osm2pgsql (coastline typo) 2015-03-09 21:45:01 +01:00
Sarah Hoffmann
0930f6e728 state setup: get latest node from place, planet_osm_nodes may be empty 2015-03-09 21:33:02 +01:00
Sarah Hoffmann
6f98fa0fb3 interpolations: snap lines to points, not vice versa
Avoids the occasional rounding problem which might occur when splitting
a line anywhere but on a support point, see postgis doc for ST_Split.

Fixes #253
2015-03-08 18:25:51 +01:00
Sarah Hoffmann
555362eabe simplify bounding box computation
Makes highlighting of points reappear.
2015-03-06 20:58:09 +01:00
Sarah Hoffmann
9f4c7f4e6d update osm2pgsql (get rid of way-node index) 2015-03-05 23:09:00 +01:00
Sarah Hoffmann
1eb52879c6 replace final reference to way-node index with spatial lookup 2015-03-05 22:00:27 +01:00
Sarah Hoffmann
27ce2afbcf reorder parenting search for POI level
Push back the more expensive node-on-way parenting which is rather
rare anyways. Prefer assodicatedStreet relations and addr:* tags
instead.
2015-03-05 22:00:27 +01:00
Sarah Hoffmann
9d9745b378 add more tests for interpolations (mostly updating) 2015-03-05 22:00:27 +01:00
Sarah Hoffmann
30f087b168 switch interpolation node to using the interpolation osm id 2015-03-05 22:00:27 +01:00
Sarah Hoffmann
1ce3307b7a fix typos and make interpolation tests run 2015-03-05 22:00:26 +01:00
Sarah Hoffmann
a25810d317 write interpolated house numbers complete out and avoid reindexing 2015-03-05 22:00:26 +01:00
Sarah Hoffmann
394a00f521 computation of parent of interpolations 2015-03-05 22:00:26 +01:00
Sarah Hoffmann
9e3e7bf791 switch remaining GRANTs to configurable web user
fixes #252
2015-03-05 21:55:20 +01:00
Sarah Hoffmann
6dcdf34fda Merge pull request #250 from mtmail/patch-1
Update README.md
2015-03-03 19:55:33 +01:00
mtmail
f4d7337266 Update README.md
Added missing `shapely` library and instructions how to install `pip` on Ubuntu
2015-03-02 23:57:41 +01:00
Sarah Hoffmann
7ed580f1d5 enable NameOnlySearch per default 2015-02-27 19:55:31 +01:00
Sarah Hoffmann
c6d8e91b88 add script for recomputing word frequencies 2015-02-27 19:53:11 +01:00
Sarah Hoffmann
340b9793d6 update scene builder to compile with latest libosmium 2015-02-21 16:35:54 +01:00
Sarah Hoffmann
82e5a95f16 also drop interpolation index 2015-02-21 14:17:34 +01:00
Sarah Hoffmann
822ca14480 add makefile for test scene extractor 2015-02-21 14:11:05 +01:00
Sarah Hoffmann
b41a5c962c drop unnecessary index 2015-02-19 08:07:04 +01:00
Marc Tobias Metten
3c2c3ab674 check database results before using variable 2015-02-18 17:53:49 +01:00
Sarah Hoffmann
2b2b6ffadc drop special handling of short exact terms in address
There is a double check against exact terms, so that results with
a matching exact short term will float to the top.
2015-02-15 19:36:39 +01:00
Sarah Hoffmann
02cd91d251 update osm2pgsql (bug in relation update) 2015-02-11 22:31:30 +01:00
Sarah Hoffmann
5d87136969 reduce search area for secondary adresses when areas are involved 2015-02-09 19:35:15 +01:00
Sarah Hoffmann
0de6f37647 remove address lines with fully duplicated keywords
Mainly there to avoid having many duplicated postcode entries
in place_addressline from nodes which have tags where only
addr:postcode is recognized by Nominatim (e.g. fire hydrants).
2015-02-09 19:35:15 +01:00
Sarah Hoffmann
c9f3d7d08b disable housenumber-specific search when no address details are provided 2015-02-05 21:13:33 +01:00
Sarah Hoffmann
62ed8b9e0c add test for house number search 2015-02-04 20:39:20 +01:00
Sarah Hoffmann
cf5ced6618 order search results by existance of housenumbers
When searching for an address with housenumber, include the house
number lookup already when searching in search_name so that we do
not cut away relevant results in cases where there are too many
street pieces.
2015-02-04 20:31:30 +01:00
Sarah Hoffmann
0f84371748 actually write back the reversed final phrase when reversing the query 2015-02-04 20:29:38 +01:00
Sarah Hoffmann
43b925b258 slightly relax API tests 2015-02-03 23:17:51 +01:00
Sarah Hoffmann
b145dadd63 correctly quote display name in html search result 2015-02-03 23:12:21 +01:00
Sarah Hoffmann
7769b0a823 junctions should not appear as roads in addresses
fixes #228
2015-01-30 22:25:08 +01:00
Sarah Hoffmann
330f147b02 use _st_intersects when dealing with countries, it does not use index 2015-01-28 21:40:08 +01:00
Sarah Hoffmann
fbc5ba13f8 show class instead of yes in html search output 2015-01-27 22:22:26 +01:00
Sarah Hoffmann
c798577f70 remove hack for fixing adminitrative typo 2015-01-26 22:33:56 +01:00
Sarah Hoffmann
4c2fa68c55 details view: use class name if type is yes
fixes #209
2015-01-26 22:27:33 +01:00
Sarah Hoffmann
d1552b0904 don't use tokens from country parameter in address field of searches
fixes #218
2015-01-26 21:59:36 +01:00
Sarah Hoffmann
b121da0ca3 need phrase types in getGroupedSearches 2015-01-26 21:34:21 +01:00
Sarah Hoffmann
f6bfadaef6 Merge remote-tracking branch 'lonvia/inverse-query-II' 2015-01-23 16:46:50 +01:00
Sarah Hoffmann
b9355ac829 switch to enhanced osm2pgsql C++ version
This includes a major rewrite of the tag processing code. Much more
data is already rejected during osm2pgsql processing and names are
choosen more selectively depending on the class/type.
2015-01-23 08:13:11 +01:00
Sarah Hoffmann
f54ad3b86d adapt API tests to latest data 2015-01-22 00:06:44 +01:00
Sarah Hoffmann
e16fcf879d fully evaluate reverse order of queries
Factors out computation of search group and calls the code once
for forward evaluation and wants with reversed word order.
2015-01-21 21:40:38 +01:00
Sarah Hoffmann
021702f190 tablespace definition belongs before the where clause 2015-01-20 20:45:16 +01:00
Sarah Hoffmann
138b8a2ada remove unused functions 2015-01-16 21:36:35 +01:00
Sarah Hoffmann
352f0fdc27 finish osm2pgsql tag tests 2015-01-14 23:13:38 +01:00
Sarah Hoffmann
8c89b65082 more osm2pgsql tag tests 2015-01-13 22:16:00 +01:00
Sarah Hoffmann
f156da6b63 support tablespaces and www user config in tiger import 2015-01-11 13:44:39 +01:00
Sarah Hoffmann
759222eef2 tests for name import in osm2pgsql 2015-01-09 23:17:17 +01:00
Sarah Hoffmann
14d17a3ad4 properly close connection in test 2015-01-09 23:16:53 +01:00
Sarah Hoffmann
6d0ab44800 reuse template db for tests by default 2015-01-09 23:16:31 +01:00
Alexander Vasilyev
6704f7bbb0 fix case sensitivity of cyrillic ghe 2014-12-31 05:59:48 +03: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
291 changed files with 50035 additions and 104930 deletions

24
.gitignore vendored
View File

@@ -1,31 +1,11 @@
*.log
*.pyc
nominatim/*.d
nominatim/*.o
nominatim/nominatim
module/nominatim.so
module/nominatim.o
settings/configuration.txt
settings/download.lock
settings/state.txt
build
settings/local.php
.deps/
autom4te.cache/
config.*
configure
Makefile
Makefile.in
stamp-h1
missing
INSTALL
aclocal.m4
depcomp
install-sh
compile
data/wiki_import.sql
data/wiki_specialphrases.sql
data/osmosischange.osc
.vagrant

31
.travis.yml Normal file
View File

@@ -0,0 +1,31 @@
---
sudo: required
dist: trusty
language: python
python:
- "3.6"
addons:
postgresql: "9.6"
git:
depth: 3
env:
- TEST_SUITE=tests
- TEST_SUITE=monaco
install:
- vagrant/install-on-travis-ci.sh
before_script:
- psql -U postgres -c "create extension postgis"
script:
- cd $TRAVIS_BUILD_DIR/build
- if [[ $TEST_SUITE == "monaco" ]]; then wget --no-verbose --output-document=../data/monaco.osm.pbf http://download.geofabrik.de/europe/monaco-latest.osm.pbf; fi
- if [[ $TEST_SUITE == "monaco" ]]; then ./utils/setup.php --osm-file ../data/monaco.osm.pbf --osm2pgsql-cache 1000 --all 2>&1 | grep -v 'ETA (seconds)'; fi
- if [[ $TEST_SUITE == "monaco" ]]; then ./utils/specialphrases.php --wiki-import | psql -d test_api_nominatim >/dev/null; fi
- cd $TRAVIS_BUILD_DIR/test/php
- if [[ $TEST_SUITE == "tests" ]]; then phpunit ./ ; fi
- if [[ $TEST_SUITE == "tests" ]]; then phpcs --report-width=120 */**.php ; fi
- cd $TRAVIS_BUILD_DIR/test/bdd
- # behave --format=progress3 api
- if [[ $TEST_SUITE == "tests" ]]; then behave --format=progress3 db ; fi
- if [[ $TEST_SUITE == "tests" ]]; then behave --format=progress3 osm2pgsql ; fi
notifications:
email: false

View File

@@ -2,16 +2,17 @@ Nominatim was written by:
Brian Quinion
Sarah Hoffmann
Marc Tobias Metten
markigail
IrlJidel
Frederik Ramm
Michael Spreng
Daniele Forsi
mfn
Grant Slater
Andree Klattenhoff
IrlJidel
appelflap
b3nn0
Spin0us
Kurt Roeckx
Rodolphe Quiédeville
Marc Tobias Metten

150
CMakeLists.txt Normal file
View File

@@ -0,0 +1,150 @@
#-----------------------------------------------------------------------------
#
# CMake Config
#
# Nominatim
#
#-----------------------------------------------------------------------------
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
#-----------------------------------------------------------------------------
#
# Project version
#
#-----------------------------------------------------------------------------
project(nominatim)
set(NOMINATIM_VERSION_MAJOR 3)
set(NOMINATIM_VERSION_MINOR 0)
set(NOMINATIM_VERSION "${NOMINATIM_VERSION_MAJOR}.${NOMINATIM_VERSION_MINOR}")
add_definitions(-DNOMINATIM_VERSION="${NOMINATIM_VERSION}")
#-----------------------------------------------------------------------------
#
# Find external dependencies
#
#-----------------------------------------------------------------------------
set(BUILD_TESTS off CACHE BOOL "Build test suite" FORCE)
set(WITH_LUA off CACHE BOOL "Build with lua support" FORCE)
if (NOT EXISTS "${CMAKE_SOURCE_DIR}/osm2pgsql/CMakeLists.txt")
message(FATAL_ERROR "The osm2pgsql directory is empty.\
Did you forget to check out Nominatim recursively?\
\nTry updating submodules with: git submodule update --init")
endif()
add_subdirectory(osm2pgsql)
find_package(Threads REQUIRED)
unset(PostgreSQL_TYPE_INCLUDE_DIR CACHE)
set(PostgreSQL_TYPE_INCLUDE_DIR "/usr/include/")
find_package(PostgreSQL REQUIRED)
include_directories(${PostgreSQL_INCLUDE_DIRS})
link_directories(${PostgreSQL_LIBRARY_DIRS})
find_program(PYOSMIUM pyosmium-get-changes)
if (NOT EXISTS "${PYOSMIUM}")
set(PYOSMIUM_PATH "/nonexistent")
message(WARNING "pyosmium-get-changes not found (required for updates)")
else()
set(PYOSMIUM_PATH "${PYOSMIUM}")
message(STATUS "Using pyosmium-get-changes at ${PYOSMIUM_PATH}")
endif()
find_program(PG_CONFIG pg_config)
execute_process(COMMAND ${PG_CONFIG} --pgxs
OUTPUT_VARIABLE PGXS
OUTPUT_STRIP_TRAILING_WHITESPACE)
if (NOT EXISTS "${PGXS}")
message(FATAL_ERROR "Postgresql server package not found.")
endif()
find_package(ZLIB REQUIRED)
find_package(BZip2 REQUIRED)
find_package(LibXml2 REQUIRED)
include_directories(${LIBXML2_INCLUDE_DIR})
#-----------------------------------------------------------------------------
#
# Setup settings and paths
#
#-----------------------------------------------------------------------------
set(CUSTOMFILES
settings/phrase_settings.php
website/deletable.php
website/details.php
website/hierarchy.php
website/lookup.php
website/polygons.php
website/reverse.php
website/search.php
website/status.php
utils/blocks.php
utils/country_languages.php
utils/imports.php
utils/importWikipedia.php
utils/query.php
utils/server_compare.php
utils/setup.php
utils/specialphrases.php
utils/update.php
utils/warm.php
)
foreach (cfile ${CUSTOMFILES})
configure_file(${PROJECT_SOURCE_DIR}/${cfile} ${PROJECT_BINARY_DIR}/${cfile})
endforeach()
configure_file(${PROJECT_SOURCE_DIR}/settings/defaults.php ${PROJECT_BINARY_DIR}/settings/settings.php)
set(WEBPATHS css images js)
foreach (wp ${WEBPATHS})
execute_process(
COMMAND ln -sf ${PROJECT_SOURCE_DIR}/website/${wp} ${PROJECT_BINARY_DIR}/website/
)
endforeach()
#-----------------------------------------------------------------------------
#
# Tests
#
#-----------------------------------------------------------------------------
include(CTest)
set(TEST_BDD db osm2pgsql api)
foreach (test ${TEST_BDD})
add_test(NAME bdd_${test}
COMMAND lettuce features/${test}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests)
set_tests_properties(bdd_${test}
PROPERTIES ENVIRONMENT "NOMINATIM_DIR=${PROJECT_BINARY_DIR}")
endforeach()
add_test(NAME php
COMMAND phpunit ./
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests-php)
#-----------------------------------------------------------------------------
add_subdirectory(module)
add_subdirectory(nominatim)
add_subdirectory(docs)
#-----------------------------------------------------------------------------

100
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,100 @@
# Nominatim contribution guidelines
## Reporting Bugs
Bugs can be reported at https://github.com/openstreetmap/Nominatim/issues.
Please always open a separate issue for each problem. In particular, do
not add your bugs to closed issues. They may looks similar to you but
often are completely different from the maintainer's point of view.
### When Reporting Bad Search Results...
Please make sure to add the following information:
* the URL of the query that produces the bad result
* the result you are getting
* the expected result, preferably a link to the OSM object you want to find,
otherwise an address that is as precise as possible
To get the link to the OSM object, you can try the following:
* go to https://openstreetmap.org
* zoom to the area of the map where you expect the result and
zoom in as much as possible
* click on the question mark on the right side of the map,
then with the queston cursor on the map where your object is located
* find the object of interest in the list that appears on the left side
* click on the object and report the URL back that the browser shows
### When Reporting Problems with your Installation...
Please add the following information to your issue:
* hardware configuration: RAM size, CPUs, kind and size of disks
* Operating system (also mention if you are running on a cloud service)
* Postgres and Postgis version
* list of settings you changed in your Postgres configuration
* Nominatim version (release version or,
if you run from the git repo, the output of `git rev-parse HEAD`)
* (if applicable) exact command line of the command that was causing the issue
## Workflow for Pull Requests
We love to get pull reuqests from you. We operate the "Fork & Pull" model
explained at
https://help.github.com/articles/using-pull-requests
You should fork the project into your own repo, create a topic branch
there and then make one or more pull requests back to the openstreetmap repository.
Your pull requests will then be reviewed and discussed. Please be aware
that you are responsible for your pull requests. You should be prepared
to get change requests because as the maintainers we have to make sure
that your contribution fits well with the rest of the code. Please make
sure that you have time to react to these comments and amend the code or
engage in a conversion. Do not expect that others will pick up your code,
it will almost never happen.
Please open a separate pull request for each issue you want to address.
Don't mix multiple changes. In particular, don't mix style cleanups with
feature pull requests. If you plan to make larger changes, please open
an issue first or comment on the appropriate issue already existing so
that duplicate work can be avoided.
## Coding style
Nominatim historically hasn't followed a particular coding style but we
are in process of consolodating the style. The following rules apply:
* Python code uses the official Python style
* indention
* SQL use 2 spaces
* all other file types use 4 spaces
* [BSD style](https://en.wikipedia.org/wiki/Indent_style#Allman_style) for braces
* spaces
* spaces before and after equal signs and operators
* no trailing spaces
* no spaces after opening and before closing bracket
* leave out space between a function name and bracket
but add one between control statement(if, while, etc.) and bracket
The coding style is enforced with PHPCS and can be tested with:
```
phpcs --report-width=120 --colors */**.php
```
## Testing
Before submitting a pull request make sure that the following tests pass:
```
cd test/bdd
behave -DBUILDDIR=<builddir> db osm2pgsql
```
```
cd test/php
phpunit ./
```

14
COPYING
View File

@@ -1,12 +1,12 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
@@ -56,7 +56,7 @@ patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
@@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
@@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it

117
ChangeLog
View File

@@ -1,7 +1,86 @@
2.0.1
3.0
* delete outdated entries from location_area_country
* remove remaining uses of INTEGER, to allow node ids larger than 2^31
* move to cmake build system
* various fixes to HTML output
* reverse endpoint now can return geometries
* add support for PHP7
* move to on-the-fly computation of interpolations
* improve handling of linked places (updating)
* improve test framework:
* replace lettuce with behave
* use smaller database for API tests
* drop support for postgres < 9.1, postgis < 2.0 and PHP < 5.4
* make external data use optional (useful for imports without US)
* detect postgres and postgis versions automatically
* clean up query logging and remove unused tables
* move installation documentation into this repo
* add self-documenting vagrant scripts
* remove --create-website, recommend to use website directory in build
* add accessor functions for URL parameters and improve erro checking
* remove IP blocking and rate-limiting code
* enable CI via travis
* reformatting for more consistent coding style
* make country search term creation part of setup
* update country names and country grid
* handle roads that cross boundaries better
* keep full information on address tags
* update to refactored osm2pgsql which use libosmium based types
* switch from osmosis to pyosmium for updates
* be more strict when matching against special search terms
* handle postcode entries with mutliple values correctly
2.5
* reverse geocoding includes looking up housenumbers from Tiger data
* added parameter to return simplified geometries
* new lookup call for getting address information for OSM objects
* new namedetails and extratags parameters that expose the name and extratags
fields of the placex table
* mobile website
* reverse web view
2.4
* drop support for postgres 8.4
* rewrite address interpolation
* switch to C++ version of osm2pgsql and rewrite tag filtering
* support for bridge:name and tunnel:name, man_made, junction
* drop way-node index (reduces database size by about 15%)
* add support for configuring tablespaces and webserver user
* better evaluation of search queries in right-to-left notation
* improve house number search for streets with many duplicate entries
* code cleanup (remove unused functions and tables)
2.3
* further improve ordering of results
* support for more lat/lon formats in search-as-reverse
* fix handling of GB postcodes
* new functional test suite
* support for waterway relations
* inherit postcodes from street to poi
* fix housenumber normalisation to find non-latin house numbers
* take viewbox into account for ordering of results
* pois may now inherit address tags from surrounding buildings
* improve what objects may participate in an address
* clean up handled class/type combinations to current OSM usage
* lots of bug fixes
2.2
* correct database rights for www-data
* add timestamps for update output
* load postgis via extension for postgis >= 2.0
* remove non-admin boundaries from addresses
* further improve ordering of results with same importance
* merge addr:postcode tags into object addresses
* include rank and importance in reverse geocode output
* replace ST_Line_Interpolate_Point with ST_LineInterpolatePoint
(for postgis >= 2.1)
* update osm2pgsql to latest version
* properly detect changes of admin_level
* remove landuses when name is removed
* smaller fixes
2.1
@@ -27,33 +106,7 @@
* refactoring of front-end PHP code
* lots of smaller bug fixes
2.2
2.0.1
* correct database rights for www-data
* add timestamps for update output
* load postgis via extension for postgis >= 2.0
* remove non-admin boundaries from addresses
* further improve ordering of results with same importance
* merge addr:postcode tags into object addresses
* include rank and importance in reverse geocode output
* replace ST_Line_Interpolate_Point with ST_LineInterpolatePoint
(for postgis >= 2.1)
* update osm2pgsql to latest version
* properly detect changes of admin_level
* remove landuses when name is removed
* smaller fixes
2.3
* further improve ordering of results
* support for more lat/lon formats in search-as-reverse
* fix handling of GB postcodes
* new functional test suite
* support for waterway relations
* inherit postcodes from street to poi
* fix housenumber normalisation to find non-latin house numbers
* take viewbox into account for ordering of results
* pois may now inherit address tags from surrounding buildings
* improve what objects may participate in an address
* clean up handled class/type combinations to current OSM usage
* lots of bug fixes
* delete outdated entries from location_area_country
* remove remaining uses of INTEGER, to allow node ids larger than 2^31

View File

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

0
NEWS
View File

View File

@@ -1,3 +1,5 @@
[![Build Status](https://travis-ci.org/openstreetmap/Nominatim.svg?branch=master)](https://travis-ci.org/openstreetmap/Nominatim)
Nominatim
=========
@@ -12,34 +14,37 @@ Documentation
=============
More information about Nominatim, including usage and installation instructions,
can be found in the OSM wiki at:
can be found in the docs/ subdirectory and in the OSM wiki at:
http://wiki.openstreetmap.org/wiki/Nominatim
Installation
============
The following instructions is a quick guide to installation. A more detailed guide
how to set up your own instance of Nominatim can be found in the wiki:
http://wiki.openstreetmap.org/wiki/Nominatim/Installation
Installation steps:
0. If checking out from git run:
./autogen.sh
There are detailed installation instructions in the /docs directory.
Here is a quick summary of the necessary steps.
1. Compile Nominatim:
./configure [--enable-64bit-ids]
make
mkdir build
cd build
cmake ..
make
For more detailed installation instructions see [docs/Installation.md](docs/Installation.md).
There are also step-by-step instructions for
[Ubuntu 16.04](docs/install-on-ubuntu-16.md) and
[CentOS 7.2](docs/install-on-centos-7.md).
2. Get OSM data and import:
./utils/setup.php --osm-file <your planet file> --all
./build/utils/setup.php --osm-file <your planet file> --all
Details can be found in [docs/Import_and_update.md](docs/Import_and_update.md)
3. Point your webserver to the ./build/website directory.
3. Point your webserver to the ./website directory.
License
=======
@@ -53,4 +58,4 @@ For questions you can join the geocoding mailinglist, see
http://lists.openstreetmap.org/listinfo/geocoding
Bugs may be reported on the github project site:
https://github.com/twain47/Nominatim
https://github.com/openstreetmap/Nominatim

171
VAGRANT.md Normal file
View File

@@ -0,0 +1,171 @@
# 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/openstreetmap/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:
mkdir data
cd build
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
```
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).

69
Vagrantfile vendored Normal file
View File

@@ -0,0 +1,69 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
# Apache webserver
config.vm.network "forwarded_port", guest: 80, host: 8089
# If true, then any SSH connections made will enable agent forwarding.
config.ssh.forward_agent = true
checkout = "yes"
if ENV['CHECKOUT'] != 'y' then
config.vm.synced_folder ".", "/home/vagrant/Nominatim"
checkout = "no"
end
config.vm.define "ubuntu", primary: true do |sub|
sub.vm.box = "bento/ubuntu-16.04"
sub.vm.provision :shell do |s|
s.path = "vagrant/Install-on-Ubuntu-16.sh"
s.privileged = false
s.args = [checkout]
end
end
config.vm.define "travis" do |sub|
sub.vm.box = "bento/ubuntu-14.04"
sub.vm.provision :shell do |s|
s.path = "vagrant/install-on-travis-ci.sh"
s.privileged = false
s.args = [checkout]
end
end
config.vm.define "centos" do |sub|
sub.vm.box = "bento/centos-7.2"
sub.vm.provision :shell do |s|
s.path = "vagrant/Install-on-Centos-7.sh"
s.privileged = false
s.args = [checkout]
end
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,2 +0,0 @@
#!/bin/sh
autoreconf -vfi

View File

@@ -1,65 +0,0 @@
AC_INIT(Nominatim,2.2)
if git rev-parse HEAD 2>/dev/null >/dev/null; then
AC_SUBST([PACKAGE_VERSION], [$PACKAGE_VERSION-git-`git rev-parse --short HEAD`])
fi
dnl Required autoconf version
AC_PREREQ(2.61)
AM_INIT_AUTOMAKE([1.9.6 dist-bzip2 std-options check-news])
dnl Additional macro definitions are in here
AC_CONFIG_MACRO_DIR([osm2pgsql/m4])
dnl Generate configuration header file
AC_CONFIG_HEADER(nominatim/config.h)
dnl Find C compiler
AC_PROG_CC
dnl Find C++ compiler
AC_PROG_CXX
dnl pthread
AX_PTHREAD([], [AC_MSG_ERROR([pthread library required])])
dnl Check for Geos library
AX_LIB_GEOS
if test "x$GEOS_VERSION" = "x"
then
AC_MSG_ERROR([required library not found]);
fi
dnl Check for Proj library
AX_LIB_PROJ
if test "$HAVE_PROJ" = "no"
then
AC_MSG_ERROR([required library not found]);
fi
dnl Check for PostgresSQL client library
AX_LIB_POSTGRESQL(8.4)
if test "x$POSTGRESQL_VERSION" = "x"
then
AC_MSG_ERROR([postgresql client library not found])
fi
if test ! -f "$POSTGRESQL_PGXS"
then
AC_MSG_ERROR([postgresql server development library not found])
fi
dnl Check for bzip2 library
AX_LIB_BZIP2
if test "$HAVE_BZIP2" = "no"
then
AC_MSG_ERROR([required library not found]);
fi
dnl Check for libxml2 library
AM_PATH_XML2
AC_CONFIG_SUBDIRS([osm2pgsql])
AC_OUTPUT(Makefile nominatim/Makefile module/Makefile)

View File

@@ -1,36 +0,0 @@
# This file includes a small subset of OpenLayers code, designed to be
# integrated into another application. It includes only the Layer types
# neccesary to create tiled or untiled WMS, and does not include any Controls.
# This is the result of what was at the time called "Webmap.js" at the FOSS4G
# Web Mapping BOF.
[first]
[last]
[include]
OpenLayers/Map.js
OpenLayers/Kinetic.js
OpenLayers/Geometry/MultiLineString.js
OpenLayers/Geometry/MultiPolygon.js
OpenLayers/Format/WKT.js
OpenLayers/Layer/OSM.js
OpenLayers/Layer/Vector.js
OpenLayers/Layer/SphericalMercator.js
OpenLayers/Control/Attribution.js
OpenLayers/Control/KeyboardDefaults.js
OpenLayers/Control/Navigation.js
OpenLayers/Control/MousePosition.js
OpenLayers/Control/PanZoomBar.js
OpenLayers/Control/Permalink.js
OpenLayers/Control/TouchNavigation.js
OpenLayers/Style.js
OpenLayers/Protocol/HTTP.js
OpenLayers/Projection.js
OpenLayers/Renderer/SVG.js
OpenLayers/Renderer/VML.js
OpenLayers/Renderer/Canvas.js
[exclude]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

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

@@ -18316,7 +18316,6 @@ COPY us_postcode (postcode, x, y) FROM stdin;
45682 -82.7132476732882651 38.8141238738390513
32822 -81.2890641417997699 28.4996104146691565
10589 -73.6946260932133725 41.3319987693007462
-110.390038309796751 39.5043862981486527
95253 -121.205984758554834 38.1383772536563157
44168 -83.5412335555174792 42.4016783877205441
38870 -88.3578842735458778 34.0629206861111911

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

32
docs/CMakeLists.txt Normal file
View File

@@ -0,0 +1,32 @@
# Auto-generated vagrant install documentation
set (INSTALLDOCFILES
Install-on-Centos-7
Install-on-Ubuntu-16
)
foreach (df ${INSTALLDOCFILES})
ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${df}.md
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/bash2md.sh ${PROJECT_SOURCE_DIR}/vagrant/${df}.sh ${CMAKE_CURRENT_BINARY_DIR}/${df}.md
MAIN_DEPENDENCY ${PROJECT_SOURCE_DIR}/vagrant/${df}.sh
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/bash2md.sh
COMMENT "Creating markdown docs from vagrant/${df}.sh"
)
ADD_CUSTOM_TARGET( md_install_${df} ALL
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${df}.md
)
endforeach()
# Copied static documentation
set (GENERALDOCFILES
Installation.md
Import-and-Update.md
Faq.md
)
foreach (df ${GENERALDOCFILES})
CONFIGURE_FILE(${df} ${df})
endforeach()

127
docs/Faq.md Normal file
View File

@@ -0,0 +1,127 @@
Frequently Asked Questions
==========================
Running Your Own Instance
-------------------------
### Can I import only a few countries and also keep them up to date?
You should use the extracts and updates from http://download.geofabrik.de.
For the intial import, download the countries you need and merge them.
See [OSM Help](https://help.openstreetmap.org/questions/48843/merging-two-or-more-geographical-areas-to-import-two-or-more-osm-files-in-nominatim)
for examples how to do that. Use the resulting single osm file when
running `setup.php`.
For updates you need to download the change files for each country
once per day and apply them **separately** using
./utils/update.php --import-diff <filename> --index
See [this issue](https://github.com/openstreetmap/Nominatim/issues/60#issuecomment-18679446)
for a script that runs the updates using osmosis.
### My website shows: `XML Parsing Error: XML or text declaration not at start of entity Location</code>.`
Make sure there are no spaces at the beginning of your `settings/local.php` file.
Installation
------------
### I accidentally killed the import process after it has been running for many hours. Can it be resumed?
It is possible if the import already got to the indexing stage.
Check the last line of output that was logged before the process
was killed. If it looks like this:
Done 844 in 13 @ 64.923080 per second - Rank 26 ETA (seconds): 7.886255
then you can resume with the following command:
./utils/setup.php --index --create-search-indices --create-country-names
If the reported rank is 26 or higher, you can also safely add `-index-noanalyse`.
### When running the setup.php script I get a warning:
`PHP Warning: file_get_contents(): open_basedir restriction in effect.`
You need to adjust the [open_basedir](http://www.php.net/manual/en/ini.core.php#ini.open-basedir) setting
in your PHP configuration (php.ini file). By default this setting may look like this:
open_basedir = /srv/http/:/home/:/tmp/:/usr/share/pear/
Either add reported directories to the list or disable this setting temporarily by
dding ";" at the beginning of the line. Don't forget to enable this setting again
once you are done with the PHP command line operations.
### The Apache log contains lots of PHP warnings like this:
`PHP Warning: date_default_timezone_set() function.`
You should set the default time zone as instructed in the warning in
your `php.ini` file. Find the entry about timezone and set it to
something like this:
; Defines the default timezone used by the date functions
; http://php.net/date.timezone
date.timezone = 'America/Denver'
Or
echo "date.timezone = 'America/Denver'" > /etc/php.d/timezone.ini
### When running the import I get a version mismatch:
`COPY_END for place failed: ERROR: incompatible library "/opt/Nominatim/module/nominatim.so": version mismatch`
pg_config seems to use bad includes sometimes when multiple versions
of PostgreSQL are available in the system. Make sure you remove the
server development libraries (`postgresql-server-dev-9.1` on Ubuntu)
and recompile (`cmake .. && make`).
### I see the error: `function transliteration(text) does not exist`
Reinstall the nominatim functions with `setup.php --create--functions`
and check for any errors, e.g. a missing `nominatim.so` file.
### The website shows: `Could not get word tokens`
The server cannot access your database. Add `&debug=1` to your URL
to get the full error message.
### On CentOS the website shows `could not connect to server: No such file or directory`
On CentOS v7 the PostgreSQL server is started with `systemd`.
Check if `/usr/lib/systemd/system/httpd.service` contains a line `PrivateTmp=true`.
If so then Apache cannot see the `/tmp/.s.PGSQL.5432` file. It's a good security feature,
so use the [[#PostgreSQL_UNIX_Socket_Location_on_CentOS|preferred solution]]
However, you can solve this the quick and dirty way by commenting out that line and then run
sudo systemctl daemon-reload
sudo systemctl restart httpd
### Setup.php fails with the message: `DB Error: extension not found`
Make sure you have the Postgres extensions hstore and postgis installed.
See the installation instruction for a full list of required packages.
### When running the setup.php script I get a error:
`Cannot redeclare getDB() (previously declared in /your/path/Nominatim/lib/db.php:4)`
The message is a bit misleading as PHP needs to load the file `DB.php` and
instead re-loads Nominatim's `db.php`. To solve this make sure you
have the [http://pear.php.net/package/DB/ Pear module 'DB'] installed.
sudo pear install DB
### I forgot to delete the flatnodes file before starting an import
That's fine. For each import the flatnodes file get overwritten.
See https://help.openstreetmap.org/questions/52419/nominatim-flatnode-storage
for more information.

177
docs/Import-and-Update.md Normal file
View File

@@ -0,0 +1,177 @@
Importing a new database
========================
The following instructions explain how to create a Nominatim database
from an OSM planet file and how to keep the database up to date. It
is assumed that you have already successfully installed the Nominatim
software itself, if not return to the [installation page](Installation.md).
Configuration setup in settings/local.php
-----------------------------------------
There are lots of configuration settings you can tweak. Have a look
at `settings/settings.php` for a full list. Most should have a sensible default.
If you plan to import a large dataset (e.g. Europe, North America, planet),
you should also enable flatnode storage of node locations. With this
setting enabled, node coordinates are stored in a simple file instead
of the database. This will save you import time and disk storage.
Add to your `settings/local.php`:
@define('CONST_Osm2pgsql_Flatnode_File', '/path/to/flatnode.file');
Replace the second part with a suitable path on your system and make sure
the directory exists. There should be at least 35GB of free space.
Downloading additional data
---------------------------
### Wikipedia rankings
Wikipedia can be used as an optional auxiliary data source to help indicate
the importance of osm features. Nominatim will work without this information
but it will improve the quality of the results if this is installed.
This data is available as a binary download:
cd $NOMINATIM_SOURCE_DIR/data
wget http://www.nominatim.org/data/wikipedia_article.sql.bin
wget http://www.nominatim.org/data/wikipedia_redirect.sql.bin
Combined the 2 files are around 1.5GB and add around 30GB to the install
size of nominatim. They also increase the install time by an hour or so.
### UK postcodes
Nominatim can use postcodes from an external source to improve searches that involve a UK postcode. This data can be optionally downloaded:
cd $NOMINATIM_SOURCE_DIR/data
wget http://www.nominatim.org/data/gb_postcode_data.sql.gz
Initial import of the data
--------------------------
**Important:** first try the import with a small excerpt, for example from
[Geofabrik](http://download.geofabrik.de).
Download the data to import and load the data with the following command:
./utils/setup.php --osm-file <your data file> --all [--osm2pgsql-cache 28000] 2>&1 | tee setup.log
The `--osm2pgsql-cache` parameter is optional but strongly recommended for
planet imports. It sets the node cache size for the osm2pgsql import part
(see `-C` parameter in osm2pgsql help). 28GB are recommended for a full planet
import, for excerpts you can use less. Adapt to your available RAM to
avoid swapping, never give more than 2/3 of RAM to osm2pgsql.
Loading additional datasets
---------------------------
The following commands will create additional entries for POI searches:
./utils/specialphrases.php --wiki-import > specialphrases.sql
psql -d nominatim -f specialphrases.sql
Installing Tiger housenumber data for the US
============================================
Nominatim is able to use the official TIGER address set to complement the
OSM housenumber data in the US. You can add TIGER data to your own Nominatim
instance by following these steps:
1. Install the GDAL library and python bindings and the unzip tool
* Ubuntu: `sudo apt-get install python-gdal unzip`
* CentOS: `sudo yum install gdal-python unzip`
2. Get the TIGER 2015 data. You will need the EDGES files
(3,234 zip files, 11GB total). Choose one of the two sources:
wget -r ftp://ftp2.census.gov/geo/tiger/TIGER2015/EDGES/
wget -r ftp://mirror1.shellbot.com/census/geo/tiger/TIGER2015/EDGES/
The first one is the original source, the second a considerably faster
mirror.
3. Convert the data into SQL statements (stored in data/tiger):
./utils/imports.php --parse-tiger <tiger edge data directory>
4. Import the data into your Nominatim database:
./utils/setup.php --import-tiger-data
5. Enable use of the Tiger data in your `settings/local.php` by adding:
@define('CONST_Use_US_Tiger_Data', true);
6. Apply the new settings:
./utils/setup.php --create-functions --enable-diff-updates --create-partition-functions
Be warned that the import can take a very long time, especially if you
import all of the US. The entire US adds about 10GB to your database.
Updates
=======
There are many different possibilities to update your Nominatim database.
The following section describes how to keep it up-to-date with Pyosmium.
For a list of other methods see the output of `./utils/update.php --help`.
Installing the newest version of Pyosmium
-----------------------------------------
It is recommended to install Pyosmium via pip:
pip install --user osmium
Nominatim needs a tool called `pyosmium-get-updates` that comes with
Pyosmium. You need to tell Nominatim where to find it. Add the
following line to your `settings/local.php`:
@define('CONST_Pyosmium_Binary', '/home/user/.local/bin/pyosmium-get-changes');
The path above is fine if you used the `--user` parameter with pip.
Replace `user` with your user name.
Setting up the update process
-----------------------------
Next the update needs to be initialised. By default Nominatim is configured
to update using the global minutely diffs.
If you want a different update source you will need to add some settings
to `settings/local.php`. For example, to use the daily country extracts
diffs for Ireland from geofabrik add the following:
// base URL of the replication service
@define('CONST_Replication_Url', 'http://download.geofabrik.de/europe/ireland-and-northern-ireland-updates');
// How often upstream publishes diffs
@define('CONST_Replication_Update_Interval', '86400');
// How long to sleep if no update found yet
@define('CONST_Replication_Recheck_Interval', '900');
To set up the update process now run the following command:
./utils/update --init-updates
It outputs the date where updates will start. Recheck that this date is
what you expect.
The --init-updates command needs to be rerun whenever the replication service
is changed.
Updating Nominatim
------------------
The following command will keep your database constantly up to date:
./utils/update.php --import-osmosis-all
If you have imported multiple country extracts and want to keep them
up-to-date, have a look at the script in
[issue #60](https://github.com/openstreetmap/Nominatim/issues/60).

181
docs/Install-on-Centos-7.md Normal file
View File

@@ -0,0 +1,181 @@
*Note:* these installation instructions are also available in executable
form for use with vagrant under `vagrant/Install-on-Centos-7.sh`.
Installing the Required Software
================================
These instructions expect that you have a freshly installed CentOS version 7.
Make sure all packages are up-to-date by running:
sudo yum update -y
The standard CentOS repositories don't contain all the required packages,
you need to enable the EPEL repository as well. To enable it on CentOS,
install the epel-release RPM by running:
sudo yum install -y epel-release
Now you can install all packages needed for Nominatim:
sudo yum install -y postgresql-server postgresql-contrib postgresql-devel postgis postgis-utils \
git cmake make gcc gcc-c++ libtool policycoreutils-python \
php-pgsql php php-pear php-pear-DB php-intl libpqxx-devel proj-epsg \
bzip2-devel proj-devel geos-devel libxml2-devel boost-devel expat-devel zlib-devel
If you want to run the test suite, you need to install the following
additional packages:
sudo yum install -y python-pip python-Levenshtein python-psycopg2 \
python-numpy php-phpunit-PHPUnit
pip install --user --upgrade pip setuptools lettuce==0.2.18 six==1.9 \
haversine Shapely pytidylib
sudo pear install PHP_CodeSniffer
System Configuration
====================
The following steps are meant to configure a fresh CentOS installation
for use with Nominatim. You may skip some of the steps if you have your
OS already configured.
Creating Dedicated User Accounts
--------------------------------
Nominatim will run as a global service on your machine. It is therefore
best to install it under its own separate user account. In the following
we assume this user is called nominatim and the installation will be in
/srv/nominatim. To create the user and directory run:
sudo useradd -d /srv/nominatim -s /bin/bash -m nominatim
You may find a more suitable location if you wish.
To be able to copy and paste instructions from this manual, export
user name and home directory now like this:
export USERNAME=nominatim
export USERHOME=/srv/nominatim
**Never, ever run the installation as a root user.** You have been warned.
Make sure that system servers can read from the home directory:
chmod a+x $USERHOME
Setting up PostgreSQL
---------------------
CentOS does not automatically create a database cluster. Therefore, start
with initializing the database, then enable the server to start at boot:
sudo postgresql-setup initdb
sudo systemctl enable postgresql
Next tune the postgresql configuration, which is located in
`/var/lib/pgsql/data/postgresql.conf`. See section *Postgres Tuning* in
[the installation page](Installation.md) for the parameters to change.
Now start the postgresql service after updating this config file.
sudo systemctl restart postgresql
Finally, we need to add two postgres users: one for the user that does
the import and another for the webserver which should access the database
only for reading:
sudo -u postgres createuser -s $USERNAME
sudo -u postgres createuser apache
Setting up the Apache Webserver
-------------------------------
You need to create an alias to the website directory in your apache
configuration. Add a separate nominatim configuration to your webserver:
```
sudo tee /etc/httpd/conf.d/nominatim.conf << EOFAPACHECONF
<Directory "$USERHOME/Nominatim/build/website">
Options FollowSymLinks MultiViews
AddType text/html .php
DirectoryIndex search.php
Require all granted
</Directory>
Alias /nominatim $USERHOME/Nominatim/build/website
EOFAPACHECONF
```
Then reload apache
sudo systemctl restart httpd
Adding SELinux Security Settings
--------------------------------
It is a good idea to leave SELinux enabled and enforcing, particularly
with a web server accessible from the Internet. At a minimum the
following SELinux labeling should be done for Nominatim:
sudo semanage fcontext -a -t httpd_sys_content_t "$USERHOME/Nominatim/(website|lib|settings)(/.*)?"
sudo semanage fcontext -a -t lib_t "$USERHOME/Nominatim/module/nominatim.so"
sudo restorecon -R -v $USERHOME/Nominatim
Installing Nominatim
====================
Building and Configuration
--------------------------
Get the source code from Github and change into the source directory
cd $USERHOME
git clone --recursive git://github.com/openstreetmap/Nominatim.git
cd Nominatim
When installing the latest source from github, you also need to
download the country grid:
wget -O data/country_osm_grid.sql.gz http://www.nominatim.org/data/country_grid.sql.gz
The code must be built in a separate directory. Create this directory,
then configure and build Nominatim in there:
mkdir build
cd build
cmake $USERHOME/Nominatim
make
You need to create a minimal configuration file that tells nominatim
the name of your webserver user and the URL of the website:
```
tee settings/local.php << EOF
<?php
@define('CONST_Database_Web_User', 'apache');
@define('CONST_Website_BaseURL', '/nominatim/');
EOF
```
Nominatim is now ready to use. Continue with
[importing a database from OSM data](Import-and-Update.md).

View File

@@ -0,0 +1,167 @@
*Note:* these installation instructions are also available in executable
form for use with vagrant under vagrant/Install-on-Ubuntu-16.sh.
Installing the Required Software
================================
These instructions expect that you have a freshly installed Ubuntu 16.04.
Make sure all packages are are up-to-date by running:
sudo apt-get update -qq
Now you can install all packages needed for Nominatim:
sudo apt-get install -y build-essential cmake g++ libboost-dev libboost-system-dev \
libboost-filesystem-dev libexpat1-dev zlib1g-dev libxml2-dev\
libbz2-dev libpq-dev libgeos-dev libgeos++-dev libproj-dev \
postgresql-server-dev-9.5 postgresql-9.5-postgis-2.2 postgresql-contrib-9.5 \
apache2 php php-pgsql libapache2-mod-php php-pear php-db \
php-intl git
If you want to run the test suite, you need to install the following
additional packages:
sudo apt-get install -y python3-dev python3-pip python3-psycopg2 python3-tidylib phpunit
pip3 install --user behave nose # urllib3
sudo pear install PHP_CodeSniffer
System Configuration
====================
The following steps are meant to configure a fresh Ubuntu installation
for use with Nominatim. You may skip some of the steps if you have your
OS already configured.
Creating Dedicated User Accounts
--------------------------------
Nominatim will run as a global service on your machine. It is therefore
best to install it under its own separate user account. In the following
we assume this user is called nominatim and the installation will be in
/srv/nominatim. To create the user and directory run:
sudo useradd -d /srv/nominatim -s /bin/bash -m nominatim
You may find a more suitable location if you wish.
To be able to copy and paste instructions from this manual, export
user name and home directory now like this:
export USERNAME=nominatim
export USERHOME=/srv/nominatim
**Never, ever run the installation as a root user.** You have been warned.
Make sure that system servers can read from the home directory:
chmod a+x $USERHOME
Setting up PostgreSQL
---------------------
Tune the postgresql configuration, which is located in
`/etc/postgresql/9.5/main/postgresql.conf`. See section *Postgres Tuning* in
[the installation page](Installation.md) for the parameters to change.
Restart the postgresql service after updating this config file.
sudo systemctl restart postgresql
Finally, we need to add two postgres users: one for the user that does
the import and another for the webserver which should access the database
for reading only:
sudo -u postgres createuser -s $USERNAME
sudo -u postgres createuser www-data
Setting up the Apache Webserver
-------------------------------
You need to create an alias to the website directory in your apache
configuration. Add a separate nominatim configuration to your webserver:
```
sudo tee /etc/apache2/conf-available/nominatim.conf << EOFAPACHECONF
<Directory "$USERHOME/Nominatim/build/website">
Options FollowSymLinks MultiViews
AddType text/html .php
DirectoryIndex search.php
Require all granted
</Directory>
Alias /nominatim $USERHOME/Nominatim/build/website
EOFAPACHECONF
```
Then enable the configuration and restart apache
sudo a2enconf nominatim
sudo systemctl restart apache2
Installing Nominatim
====================
Building and Configuration
--------------------------
Get the source code from Github and change into the source directory
cd $USERHOME
git clone --recursive git://github.com/openstreetmap/Nominatim.git
cd Nominatim
When installing the latest source from github, you also need to
download the country grid:
wget -O data/country_osm_grid.sql.gz http://www.nominatim.org/data/country_grid.sql.gz
The code must be built in a separate directory. Create this directory,
then configure and build Nominatim in there:
mkdir build
cd build
cmake $USERHOME/Nominatim
make
You need to create a minimal configuration file that tells nominatim
where it is located on the webserver:
```
tee settings/local.php << EOF
<?php
@define('CONST_Website_BaseURL', '/nominatim/');
EOF
```
Nominatim is now ready to use. Continue with
[importing a database from OSM data](Import-and-Update.md).

154
docs/Installation.md Normal file
View File

@@ -0,0 +1,154 @@
Nominatim installation
======================
This page contains generic installation instructions for Nominatim and its
prerequisites. There are also step-by-step instructions available for
the following operating systems:
* [Ubuntu 16.04](Install-on-Ubuntu-16.md)
* [CentOS 7.2](Install-on-Centos-7.md)
These OS-specific instructions can also be found in executable form
in the `vagrant/` directory.
Prerequisites
-------------
### Software
For compiling:
* [cmake](https://cmake.org/)
* [libxml2](http://xmlsoft.org/)
* a recent C++ compiler
Nominatim comes with its own version of osm2pgsql. See the
[osm2pgsql README](../osm2pgsql/README.md) for additional dependencies
required for compiling osm2pgsql.
For running tests:
* [behave](http://pythonhosted.org/behave/)
* [Psycopg2](http://initd.org/psycopg)
* [nose](https://nose.readthedocs.io)
* [phpunit](https://phpunit.de)
For running Nominatim:
* [PostgreSQL](http://www.postgresql.org) (9.1 or later)
* [PostGIS](http://postgis.refractions.net) (2.0 or later)
* [PHP](http://php.net) (5.4 or later)
* PHP-pgsql
* PHP-intl (bundled with PHP)
* [PEAR::DB](http://pear.php.net/package/DB)
* a webserver (apache or nginx are recommended)
For running continuous updates:
* [pyosmium](http://osmcode.org/pyosmium/)
### Hardware
A minimum of 2GB of RAM is required or installation will fail. For a full
planet import 32GB of RAM or more strongly are recommended.
For a full planet install you will need about 500GB of hard disk space (as of
June 2016, take into account that the OSM database is growing fast). SSD disks
will help considerably to speed up import and queries.
On a 6-core machine with 32GB RAM and SSDs the import of a full planet takes
a bit more than 2 days. Without SSDs 7-8 days are more realistic.
Setup of the server
-------------------
### PostgreSQL tuning
You might want to tune your PostgreSQL installation so that the later steps
make best use of your hardware. You should tune the following parameters in
your `postgresql.conf` file.
shared_buffers (2GB)
maintenance_work_mem (10GB)
work_mem (50MB)
effective_cache_size (24GB)
synchronous_commit = off
checkpoint_segments = 100 # only for postgresql <= 9.4
checkpoint_timeout = 10min
checkpoint_completion_target = 0.9
The numbers in brackets behind some parameters seem to work fine for
32GB RAM machine. Adjust to your setup.
For the initial import, you should also set:
fsync = off
full_page_writes = off
Don't forget to reenable them after the initial import or you risk database
corruption. Autovacuum must not be switched off because it ensures that the
tables are frequently analysed.
### Webserver setup
The `website/` directory in the build directory contains the configured
website. Include the directory into your webbrowser to serve php files
from there.
#### Configure for use with Apache
Make sure your Apache configuration contains the required permissions for the
directory and create an alias:
<Directory "/srv/nominatim/build/website">
Options FollowSymLinks MultiViews
AddType text/html .php
DirectoryIndex search.php
Require all granted
</Directory>
Alias /nominatim /srv/nominatim/build/website
`/srv/nominatim/build` should be replaced with the location of your
build directory.
After making changes in the apache config you need to restart apache.
The website should now be available on http://localhost/nominatim.
#### Configure for use with Nginx
Use php-fpm as a deamon for serving PHP cgi. Install php-fpm together with nginx.
By default php listens on a network socket. If you want it to listen to a
Unix socket instead, change the pool configuration (`pool.d/www.conf`) as
follows:
; Comment out the tcp listener and add the unix socket
;listen = 127.0.0.1:9000
listen = /var/run/php5-fpm.sock
; Ensure that the daemon runs as the correct user
listen.owner = www-data
listen.group = www-data
listen.mode = 0666
Tell nginx that php files are special and to fastcgi_pass to the php-fpm
unix socket by adding the location definition to the default configuration.
root /srv/nominatim/build/website;
index search.php index.html;
location ~ [^/]\.php(/|$) {
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
if (!-f $document_root$fastcgi_script_name) {
return 404;
}
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index search.php;
include fastcgi.conf;
}
Restart the nginx and php5-fpm services and the website should now be available
on http://localhost/.
Now continue with [importing the database](Import-and-Update.md).

7
docs/bash2md.sh Executable file
View File

@@ -0,0 +1,7 @@
#!/bin/sh
#
# Extract markdown-formatted documentation from a source file
#
# Usage: bash2md.sh <infile> <outfile>
sed '/^#!/d;s:^#\( \|$\)::;s/.*#DOCS://' $1 > $2

File diff suppressed because it is too large Load Diff

157
lib/NearPoint.php Normal file
View File

@@ -0,0 +1,157 @@
<?php
namespace Nominatim;
/**
* A geographic point with a search radius.
*/
class NearPoint
{
private $fLat;
private $fLon;
private $fRadius;
private $sSQL;
public function __construct($lat, $lon, $radius = 0.1)
{
$this->fLat = (float)$lat;
$this->fLon = (float)$lon;
$this->fRadius = (float)$radius;
$this->sSQL = 'ST_SetSRID(ST_Point('.$this->fLon.','.$this->fLat.'),4326)';
}
public function lat()
{
return $this->fLat;
}
public function lon()
{
return $this->fLon;
}
public function radius()
{
return $this->fRadius;
}
public function distanceSQL($sObj)
{
return 'ST_Distance('.$this->sSQL.", $sObj)";
}
public function withinSQL($sObj)
{
return sprintf('ST_DWithin(%s, %s, %F)', $sObj, $this->sSQL, $this->fRadius);
}
/**
* Check that the coordinates are valid WSG84 coordinates.
*
* @return bool True if the coordinates are correctly bounded.
*/
public function isValid()
{
return ($this->fLat <= 90.1
&& $this->fLat >= -90.1
&& $this->fLon <= 180.1
&& $this->fLon >= -180.1);
}
/**
* Extract a coordinate point from a query string.
*
* If a coordinate is found an array of a new NearPoint and the
* remaining query is returned or false otherwise.
*
* @param string $sQuery Query to scan.
*
* @return array|false If a coordinate was found, an array with
* `pt` as the NearPoint coordinates and `query`
* with the remaining query string. False otherwiese.
*/
public static function extractFromQuery($sQuery)
{
// Do we have anything that looks like a lat/lon pair?
// returns array(lat,lon,query_with_lat_lon_removed)
// or null
$sFound = null;
$fQueryLat = null;
$fQueryLon = null;
if (preg_match('/\\b([NS])[ ]+([0-9]+[0-9.]*)[° ]+([0-9.]+)?[\']*[, ]+([EW])[ ]+([0-9]+)[° ]+([0-9]+[0-9.]*)[\']*?\\b/', $sQuery, $aData)) {
/* 1 2 3 4 5 6
* degrees decimal minutes
* N 40 26.767, W 79 58.933
* N 40°26.767, W 79°58.933
*/
$sFound = $aData[0];
$fQueryLat = ($aData[1]=='N'?1:-1) * ($aData[2] + $aData[3]/60);
$fQueryLon = ($aData[4]=='E'?1:-1) * ($aData[5] + $aData[6]/60);
} elseif (preg_match('/\\b([0-9]+)[° ]+([0-9]+[0-9.]*)?[\']*[ ]+([NS])[, ]+([0-9]+)[° ]+([0-9]+[0-9.]*)?[\' ]+([EW])\\b/', $sQuery, $aData)) {
/* 1 2 3 4 5 6
* degrees decimal minutes
* 40 26.767 N, 79 58.933 W
* 40° 26.767 N 79° 58.933 W
*/
$sFound = $aData[0];
$fQueryLat = ($aData[3]=='N'?1:-1) * ($aData[1] + $aData[2]/60);
$fQueryLon = ($aData[6]=='E'?1:-1) * ($aData[4] + $aData[5]/60);
} elseif (preg_match('/\\b([NS])[ ]([0-9]+)[° ]+([0-9]+)[\' ]+([0-9]+)[″"]*[, ]+([EW])[ ]([0-9]+)[° ]+([0-9]+)[\' ]+([0-9]+)[″"]*\\b/', $sQuery, $aData)) {
/* 1 2 3 4 5 6 7 8
* degrees decimal seconds
* N 40 26 46 W 79 58 56
* N 40° 26 46″, W 79° 58 56″
*/
$sFound = $aData[0];
$fQueryLat = ($aData[1]=='N'?1:-1) * ($aData[2] + $aData[3]/60 + $aData[4]/3600);
$fQueryLon = ($aData[5]=='E'?1:-1) * ($aData[6] + $aData[7]/60 + $aData[8]/3600);
} elseif (preg_match('/\\b([0-9]+)[° ]+([0-9]+)[\' ]+([0-9]+)[″" ]+([NS])[, ]+([0-9]+)[° ]+([0-9]+)[\' ]+([0-9]+)[″" ]+([EW])\\b/', $sQuery, $aData)) {
/* 1 2 3 4 5 6 7 8
* degrees decimal seconds
* 40 26 46 N 79 58 56 W
* 40° 26 46″ N, 79° 58 56″ W
*/
$sFound = $aData[0];
$fQueryLat = ($aData[4]=='N'?1:-1) * ($aData[1] + $aData[2]/60 + $aData[3]/3600);
$fQueryLon = ($aData[8]=='E'?1:-1) * ($aData[5] + $aData[6]/60 + $aData[7]/3600);
} elseif (preg_match('/\\b([NS])[ ]([0-9]+[0-9]*\\.[0-9]+)[°]*[, ]+([EW])[ ]([0-9]+[0-9]*\\.[0-9]+)[°]*\\b/', $sQuery, $aData)) {
/* 1 2 3 4
* degrees decimal
* N 40.446° W 79.982°
*/
$sFound = $aData[0];
$fQueryLat = ($aData[1]=='N'?1:-1) * ($aData[2]);
$fQueryLon = ($aData[3]=='E'?1:-1) * ($aData[4]);
} elseif (preg_match('/\\b([0-9]+[0-9]*\\.[0-9]+)[° ]+([NS])[, ]+([0-9]+[0-9]*\\.[0-9]+)[° ]+([EW])\\b/', $sQuery, $aData)) {
/* 1 2 3 4
* degrees decimal
* 40.446° N 79.982° W
*/
$sFound = $aData[0];
$fQueryLat = ($aData[2]=='N'?1:-1) * ($aData[1]);
$fQueryLon = ($aData[4]=='E'?1:-1) * ($aData[3]);
} elseif (preg_match('/(\\[|^|\\b)(-?[0-9]+[0-9]*\\.[0-9]+)[, ]+(-?[0-9]+[0-9]*\\.[0-9]+)(\\]|$|\\b)/', $sQuery, $aData)) {
/* 1 2 3 4
* degrees decimal
* 12.34, 56.78
* [12.456,-78.90]
*/
$sFound = $aData[0];
$fQueryLat = $aData[2];
$fQueryLon = $aData[3];
} else {
return false;
}
$oPt = new NearPoint($fQueryLat, $fQueryLon);
if (!$oPt->isValid()) return false;
$sQuery = trim(str_replace($sFound, ' ', $sQuery));
return array('pt' => $oPt, 'query' => $sQuery);
}
}

120
lib/ParameterParser.php Normal file
View File

@@ -0,0 +1,120 @@
<?php
namespace Nominatim;
class ParameterParser
{
private $aParams;
public function __construct($aParams = null)
{
$this->aParams = ($aParams === null) ? $_GET : $aParams;
}
public function getBool($sName, $bDefault = false)
{
if (!isset($this->aParams[$sName]) || strlen($this->aParams[$sName]) == 0) {
return $bDefault;
}
return (bool) $this->aParams[$sName];
}
public function getInt($sName, $bDefault = false)
{
if (!isset($this->aParams[$sName]) || strlen($this->aParams[$sName]) == 0) {
return $bDefault;
}
if (!preg_match('/^[+-]?[0-9]+$/', $this->aParams[$sName])) {
userError("Integer number expected for parameter '$sName'");
}
return (int) $this->aParams[$sName];
}
public function getFloat($sName, $bDefault = false)
{
if (!isset($this->aParams[$sName]) || strlen($this->aParams[$sName]) == 0) {
return $bDefault;
}
if (!preg_match('/^[+-]?[0-9]*\.?[0-9]+$/', $this->aParams[$sName])) {
userError("Floating-point number expected for parameter '$sName'");
}
return (float) $this->aParams[$sName];
}
public function getString($sName, $bDefault = false)
{
if (!isset($this->aParams[$sName]) || strlen($this->aParams[$sName]) == 0) {
return $bDefault;
}
return $this->aParams[$sName];
}
public function getSet($sName, $aValues, $sDefault = false)
{
if (!isset($this->aParams[$sName]) || strlen($this->aParams[$sName]) == 0) {
return $sDefault;
}
if (!in_array($this->aParams[$sName], $aValues)) {
userError("Parameter '$sName' must be one of: ".join(', ', $aValues));
}
return $this->aParams[$sName];
}
public function getStringList($sName, $aDefault = false)
{
$sValue = $this->getString($sName);
if ($sValue) {
return explode(',', $sValue);
}
return $aDefault;
}
public function getPreferredLanguages($sFallback = null)
{
if ($sFallback === null && isset($_SERVER["HTTP_ACCEPT_LANGUAGE"])) {
$sFallback = $_SERVER["HTTP_ACCEPT_LANGUAGE"];
}
$aLanguages = array();
$sLangString = $this->getString('accept-language', $sFallback);
if ($sLangString) {
if (preg_match_all('/(([a-z]{1,8})(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $sLangString, $aLanguagesParse, PREG_SET_ORDER)) {
foreach ($aLanguagesParse as $iLang => $aLanguage) {
$aLanguages[$aLanguage[1]] = isset($aLanguage[5])?(float)$aLanguage[5]:1 - ($iLang/100);
if (!isset($aLanguages[$aLanguage[2]])) $aLanguages[$aLanguage[2]] = $aLanguages[$aLanguage[1]]/10;
}
arsort($aLanguages);
}
}
if (!sizeof($aLanguages) && CONST_Default_Language) {
$aLanguages[CONST_Default_Language] = 1;
}
foreach ($aLanguages as $sLanguage => $fLanguagePref) {
$aLangPrefOrder['short_name:'.$sLanguage] = 'short_name:'.$sLanguage;
$aLangPrefOrder['name:'.$sLanguage] = 'name:'.$sLanguage;
}
$aLangPrefOrder['short_name'] = 'short_name';
$aLangPrefOrder['name'] = 'name';
$aLangPrefOrder['brand'] = 'brand';
foreach ($aLanguages as $sLanguage => $fLanguagePref) {
$aLangPrefOrder['official_name:'.$sLanguage] = 'official_name:'.$sLanguage;
}
$aLangPrefOrder['official_name'] = 'official_name';
$aLangPrefOrder['ref'] = 'ref';
$aLangPrefOrder['type'] = 'type';
return $aLangPrefOrder;
}
}

View File

@@ -1,138 +1,336 @@
<?php
class PlaceLookup
{
protected $oDB;
protected $iPlaceID;
namespace Nominatim;
protected $aLangPrefOrder = array();
class PlaceLookup
{
protected $oDB;
protected $bAddressDetails = false;
protected $aLangPrefOrder = array();
function PlaceLookup(&$oDB)
{
$this->oDB =& $oDB;
}
protected $bAddressDetails = false;
protected $bExtraTags = false;
protected $bNameDetails = false;
function setLanguagePreference($aLangPrefOrder)
{
$this->aLangPrefOrder = $aLangPrefOrder;
}
protected $bIncludePolygonAsPoints = false;
protected $bIncludePolygonAsText = false;
protected $bIncludePolygonAsGeoJSON = false;
protected $bIncludePolygonAsKML = false;
protected $bIncludePolygonAsSVG = false;
protected $fPolygonSimplificationThreshold = 0.0;
function setIncludeAddressDetails($bAddressDetails = true)
{
$this->bAddressDetails = $bAddressDetails;
}
function setPlaceID($iPlaceID)
{
$this->iPlaceID = $iPlaceID;
}
public function __construct(&$oDB)
{
$this->oDB =& $oDB;
}
function setOSMID($sType, $iID)
{
$sSQL = "select place_id from placex where osm_type = '".pg_escape_string($sType)."' and osm_id = ".(int)$iID." order by type = 'postcode' asc";
$this->iPlaceID = $this->oDB->getOne($sSQL);
}
public function setLanguagePreference($aLangPrefOrder)
{
$this->aLangPrefOrder = $aLangPrefOrder;
}
function lookup()
{
if (!$this->iPlaceID) return null;
public function setIncludeAddressDetails($bAddressDetails = true)
{
$this->bAddressDetails = $bAddressDetails;
}
$sLanguagePrefArraySQL = "ARRAY[".join(',',array_map("getDBQuoted", $this->aLangPrefOrder))."]";
public function setIncludeExtraTags($bExtraTags = false)
{
$this->bExtraTags = $bExtraTags;
}
$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;
$aPlace = $this->oDB->getRow($sSQL);
public function setIncludeNameDetails($bNameDetails = false)
{
$this->bNameDetails = $bNameDetails;
}
if (!$aPlace['place_id']) return null;
if ($this->bAddressDetails)
{
$aAddress = $this->getAddressNames();
$aPlace['aAddress'] = $aAddress;
}
public function setIncludePolygonAsPoints($b = true)
{
$this->bIncludePolygonAsPoints = $b;
}
$aClassType = getClassTypes();
$sAddressType = '';
$sClassType = $aPlace['class'].':'.$aPlace['type'].':'.$aPlace['admin_level'];
if (isset($aClassType[$sClassType]) && isset($aClassType[$sClassType]['simplelabel']))
{
$sAddressType = $aClassType[$aClassType]['simplelabel'];
}
else
{
$sClassType = $aPlace['class'].':'.$aPlace['type'];
if (isset($aClassType[$sClassType]) && isset($aClassType[$sClassType]['simplelabel']))
$sAddressType = $aClassType[$sClassType]['simplelabel'];
else $sAddressType = $aPlace['class'];
}
public function getIncludePolygonAsPoints()
{
return $this->bIncludePolygonAsPoints;
}
$aPlace['addresstype'] = $sAddressType;
public function setIncludePolygonAsText($b = true)
{
$this->bIncludePolygonAsText = $b;
}
return $aPlace;
}
public function getIncludePolygonAsText()
{
return $this->bIncludePolygonAsText;
}
function getAddressDetails($bAll = false)
{
if (!$this->iPlaceID) return null;
public function setIncludePolygonAsGeoJSON($b = true)
{
$this->bIncludePolygonAsGeoJSON = $b;
}
$sLanguagePrefArraySQL = "ARRAY[".join(',',array_map("getDBQuoted", $this->aLangPrefOrder))."]";
public function setIncludePolygonAsKML($b = true)
{
$this->bIncludePolygonAsKML = $b;
}
$sSQL = "select *,get_name_by_language(name,$sLanguagePrefArraySQL) as localname from get_addressdata(".$this->iPlaceID.")";
if (!$bAll) $sSQL .= " WHERE isaddress OR type = 'country_code'";
$sSQL .= " order by rank_address desc,isaddress desc";
public function setIncludePolygonAsSVG($b = true)
{
$this->bIncludePolygonAsSVG = $b;
}
$aAddressLines = $this->oDB->getAll($sSQL);
if (PEAR::IsError($aAddressLines))
{
var_dump($aAddressLines);
exit;
}
return $aAddressLines;
}
public function setPolygonSimplificationThreshold($f)
{
$this->fPolygonSimplificationThreshold = $f;
}
function getAddressNames()
{
$aAddressLines = $this->getAddressDetails(false);;
public function lookupOSMID($sType, $iID)
{
$sSQL = "select place_id from placex where osm_type = '".pg_escape_string($sType)."' and osm_id = ".(int)$iID." order by type = 'postcode' asc";
$iPlaceID = chksql($this->oDB->getOne($sSQL));
$aAddress = array();
$aFallback = array();
$aClassType = getClassTypes();
foreach($aAddressLines as $aLine)
{
$bFallback = false;
$aTypeLabel = false;
if (isset($aClassType[$aLine['class'].':'.$aLine['type'].':'.$aLine['admin_level']])) $aTypeLabel = $aClassType[$aLine['class'].':'.$aLine['type'].':'.$aLine['admin_level']];
elseif (isset($aClassType[$aLine['class'].':'.$aLine['type']])) $aTypeLabel = $aClassType[$aLine['class'].':'.$aLine['type']];
elseif (isset($aClassType['boundary:administrative:'.((int)($aLine['rank_address']/2))]))
{
$aTypeLabel = $aClassType['boundary:administrative:'.((int)($aLine['rank_address']/2))];
$bFallback = true;
}
else
{
$aTypeLabel = array('simplelabel'=>'address'.$aLine['rank_address']);
$bFallback = true;
}
if ($aTypeLabel && ((isset($aLine['localname']) && $aLine['localname']) || (isset($aLine['housenumber']) && $aLine['housenumber'])))
{
$sTypeLabel = strtolower(isset($aTypeLabel['simplelabel'])?$aTypeLabel['simplelabel']:$aTypeLabel['label']);
$sTypeLabel = str_replace(' ','_',$sTypeLabel);
if (!isset($aAddress[$sTypeLabel]) || (isset($aFallback[$sTypeLabel]) && $aFallback[$sTypeLabel]) || $aLine['class'] == 'place')
{
$aAddress[$sTypeLabel] = $aLine['localname']?$aLine['localname']:$aLine['housenumber'];
}
$aFallback[$sTypeLabel] = $bFallback;
}
}
return $aAddress;
}
return $this->lookup((int)$iPlaceID);
}
}
?>
public function lookup($iPlaceID, $sType = '', $fInterpolFraction = 0.0)
{
if (!$iPlaceID) return null;
$sLanguagePrefArraySQL = "ARRAY[".join(',', array_map("getDBQuoted", $this->aLangPrefOrder))."]";
$bIsTiger = CONST_Use_US_Tiger_Data && $sType == 'tiger';
$bIsInterpolation = $sType == 'interpolation';
if ($bIsTiger) {
$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, 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 country_code, ";
$sSQL .= " get_address_by_language(place_id, housenumber, $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_X(point) as lon, ST_Y(point) as lat from (select *, ST_LineInterpolatePoint(linegeo, (housenumber-startnumber::float)/(endnumber-startnumber)::float) as point from ";
$sSQL .= " (select *, ";
$sSQL .= " CASE WHEN interpolationtype='odd' THEN floor((".$fInterpolFraction."*(endnumber-startnumber)+startnumber)/2)::int*2+1";
$sSQL .= " WHEN interpolationtype='even' THEN ((".$fInterpolFraction."*(endnumber-startnumber)+startnumber)/2)::int*2";
$sSQL .= " WHEN interpolationtype='all' THEN (".$fInterpolFraction."*(endnumber-startnumber)+startnumber)::int";
$sSQL .= " END as housenumber";
$sSQL .= " from location_property_tiger where place_id = ".$iPlaceID.") as blub1) as blub2";
} elseif ($bIsInterpolation) {
$sSQL = "select place_id, partition, 'W' as osm_type, osm_id, 'place' as class, 'house' as type, null admin_level, housenumber, postcode,";
$sSQL .= " country_code, parent_place_id, null as linked_place_id, 30 as rank_address, 30 as rank_search,";
$sSQL .= " (0.75-(30::float/40)) as importance, null as indexed_status, null as indexed_date, null as wikipedia, country_code, ";
$sSQL .= " get_address_by_language(place_id, housenumber, $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_X(point) as lon, ST_Y(point) as lat from (select *, ST_LineInterpolatePoint(linegeo, (housenumber-startnumber::float)/(endnumber-startnumber)::float) as point from ";
$sSQL .= " (select *, ";
$sSQL .= " CASE WHEN interpolationtype='odd' THEN floor((".$fInterpolFraction."*(endnumber-startnumber)+startnumber)/2)::int*2+1";
$sSQL .= " WHEN interpolationtype='even' THEN ((".$fInterpolFraction."*(endnumber-startnumber)+startnumber)/2)::int*2";
$sSQL .= " WHEN interpolationtype='all' THEN (".$fInterpolFraction."*(endnumber-startnumber)+startnumber)::int";
$sSQL .= " END as housenumber";
$sSQL .= " from location_property_osmline where place_id = ".$iPlaceID.") as blub1) as blub2";
// testcase: interpolationtype=odd, startnumber=1000, endnumber=1006, fInterpolFraction=1 => housenumber=1007 => error in st_lineinterpolatepoint
// but this will never happen, because if the searched point is that close to the endnumber, the endnumber house will be directly taken from placex (in ReverseGeocode.php line 220)
// and not interpolated
} else {
$sSQL = "select placex.place_id, partition, osm_type, osm_id, class,";
$sSQL .= " type, admin_level, housenumber, postcode, country_code,";
$sSQL .= " 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, country_code, ";
$sSQL .= " get_address_by_language(place_id, -1, $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 = ".$iPlaceID;
}
$aPlace = chksql($this->oDB->getRow($sSQL), "Could not lookup place");
if (!$aPlace['place_id']) return null;
if ($this->bAddressDetails) {
// to get addressdetails for tiger data, the housenumber is needed
$iHousenumber = ($bIsTiger || $bIsInterpolation) ? $aPlace['housenumber'] : -1;
$aPlace['aAddress'] = $this->getAddressNames($aPlace['place_id'], $iHousenumber);
}
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'];
if (isset($aClassType[$sClassType]) && isset($aClassType[$sClassType]['simplelabel'])) {
$sAddressType = $aClassType[$aClassType]['simplelabel'];
} else {
$sClassType = $aPlace['class'].':'.$aPlace['type'];
if (isset($aClassType[$sClassType]) && isset($aClassType[$sClassType]['simplelabel']))
$sAddressType = $aClassType[$sClassType]['simplelabel'];
else $sAddressType = $aPlace['class'];
}
$aPlace['addresstype'] = $sAddressType;
return $aPlace;
}
public function getAddressDetails($iPlaceID, $bAll = false, $housenumber = -1)
{
$sLanguagePrefArraySQL = "ARRAY[".join(',', array_map("getDBQuoted", $this->aLangPrefOrder))."]";
$sSQL = "select *,get_name_by_language(name,$sLanguagePrefArraySQL) as localname from get_addressdata(".$iPlaceID.",".$housenumber.")";
if (!$bAll) $sSQL .= " WHERE isaddress OR type = 'country_code'";
$sSQL .= " order by rank_address desc,isaddress desc";
return chksql($this->oDB->getAll($sSQL));
}
public function getAddressNames($iPlaceID, $housenumber = -1)
{
$aAddressLines = $this->getAddressDetails($iPlaceID, false, $housenumber);
$aAddress = array();
$aFallback = array();
$aClassType = getClassTypes();
foreach ($aAddressLines as $aLine) {
$bFallback = false;
$aTypeLabel = false;
if (isset($aClassType[$aLine['class'].':'.$aLine['type'].':'.$aLine['admin_level']])) {
$aTypeLabel = $aClassType[$aLine['class'].':'.$aLine['type'].':'.$aLine['admin_level']];
} elseif (isset($aClassType[$aLine['class'].':'.$aLine['type']])) {
$aTypeLabel = $aClassType[$aLine['class'].':'.$aLine['type']];
} elseif (isset($aClassType['boundary:administrative:'.((int)($aLine['rank_address']/2))])) {
$aTypeLabel = $aClassType['boundary:administrative:'.((int)($aLine['rank_address']/2))];
$bFallback = true;
} else {
$aTypeLabel = array('simplelabel' => 'address'.$aLine['rank_address']);
$bFallback = true;
}
if ($aTypeLabel && ((isset($aLine['localname']) && $aLine['localname']) || (isset($aLine['housenumber']) && $aLine['housenumber']))) {
$sTypeLabel = strtolower(isset($aTypeLabel['simplelabel'])?$aTypeLabel['simplelabel']:$aTypeLabel['label']);
$sTypeLabel = str_replace(' ', '_', $sTypeLabel);
if (!isset($aAddress[$sTypeLabel]) || (isset($aFallback[$sTypeLabel]) && $aFallback[$sTypeLabel]) || $aLine['class'] == 'place') {
$aAddress[$sTypeLabel] = $aLine['localname']?$aLine['localname']:$aLine['housenumber'];
}
$aFallback[$sTypeLabel] = $bFallback;
}
}
return $aAddress;
}
/* returns an array which will contain the keys
* aBoundingBox
* and may also contain one or more of the keys
* asgeojson
* askml
* assvg
* astext
* lat
* lon
*/
public function getOutlines($iPlaceID, $fLon = null, $fLat = null, $fRadius = null)
{
$aOutlineResult = array();
if (!$iPlaceID) return $aOutlineResult;
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_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";
$sFrom = " from placex where place_id = ".$iPlaceID;
if ($this->fPolygonSimplificationThreshold > 0) {
$sSQL .= " from (select place_id,centroid,ST_SimplifyPreserveTopology(geometry,".$this->fPolygonSimplificationThreshold.") as geometry".$sFrom.") as plx";
} else {
$sSQL .= $sFrom;
}
$aPointPolygon = chksql($this->oDB->getRow($sSQL), "Could not get outline");
if ($aPointPolygon['place_id']) {
if ($aPointPolygon['centrelon'] !== null && $aPointPolygon['centrelat'] !== null) {
$aOutlineResult['lat'] = $aPointPolygon['centrelat'];
$aOutlineResult['lon'] = $aPointPolygon['centrelon'];
}
if ($this->bIncludePolygonAsGeoJSON) $aOutlineResult['asgeojson'] = $aPointPolygon['asgeojson'];
if ($this->bIncludePolygonAsKML) $aOutlineResult['askml'] = $aPointPolygon['askml'];
if ($this->bIncludePolygonAsSVG) $aOutlineResult['assvg'] = $aPointPolygon['assvg'];
if ($this->bIncludePolygonAsText) $aOutlineResult['astext'] = $aPointPolygon['astext'];
if ($this->bIncludePolygonAsPoints) $aOutlineResult['aPolyPoints'] = geometryText2Points($aPointPolygon['astext'], $fRadius);
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;
}
$aOutlineResult['aBoundingBox'] = array(
(string)$aPointPolygon['minlat'],
(string)$aPointPolygon['maxlat'],
(string)$aPointPolygon['minlon'],
(string)$aPointPolygon['maxlon']
);
}
}
// as a fallback we generate a bounding box without knowing the size of the geometry
if ((!isset($aOutlineResult['aBoundingBox'])) && isset($fLon)) {
//
if ($this->bIncludePolygonAsPoints) {
$sGeometryText = 'POINT('.$fLon.','.$fLat.')';
$aOutlineResult['aPolyPoints'] = geometryText2Points($sGeometryText, $fRadius);
}
$aBounds = array();
$aBounds['minlat'] = $fLat - $fRadius;
$aBounds['maxlat'] = $fLat + $fRadius;
$aBounds['minlon'] = $fLon - $fRadius;
$aBounds['maxlon'] = $fLon + $fRadius;
$aOutlineResult['aBoundingBox'] = array(
(string)$aBounds['minlat'],
(string)$aBounds['maxlat'],
(string)$aBounds['minlon'],
(string)$aBounds['maxlon']
);
}
return $aOutlineResult;
}
}

View File

@@ -1,139 +1,223 @@
<?php
class ReverseGeocode
{
protected $oDB;
protected $fLat;
protected $fLon;
protected $iMaxRank = 28;
namespace Nominatim;
protected $aLangPrefOrder = array();
class ReverseGeocode
{
protected $oDB;
protected $iMaxRank = 28;
protected $bShowAddressDetails = true;
function ReverseGeocode(&$oDB)
{
$this->oDB =& $oDB;
}
public function __construct(&$oDB)
{
$this->oDB =& $oDB;
}
function setLanguagePreference($aLangPref)
{
$this->aLangPrefOrder = $aLangPref;
}
function setIncludeAddressDetails($bAddressDetails = true)
{
$this->bAddressDetails = $bAddressDetails;
}
public function setZoom($iZoom)
{
// Zoom to rank, this could probably be calculated but a lookup gives fine control
$aZoomRank = array(
0 => 2, // Continent / Sea
1 => 2,
2 => 2,
3 => 4, // Country
4 => 4,
5 => 8, // State
6 => 10, // Region
7 => 10,
8 => 12, // County
9 => 12,
10 => 17, // City
11 => 17,
12 => 18, // Town / Village
13 => 18,
14 => 22, // Suburb
15 => 22,
16 => 26, // Street, TODO: major street?
17 => 26,
18 => 30, // or >, Building
19 => 30, // or >, Building
);
$this->iMaxRank = (isset($iZoom) && isset($aZoomRank[$iZoom]))?$aZoomRank[$iZoom]:28;
}
function setLatLon($fLat, $fLon)
{
$this->fLat = (float)$fLat;
$this->fLon = (float)$fLon;
}
/**
* Find the closest interpolation with the given search diameter.
*
* @param string $sPointSQL Reverse geocoding point as SQL
* @param float $fSearchDiam Search diameter
*
* @return Record of the interpolation or null.
*/
protected function lookupInterpolation($sPointSQL, $fSearchDiam)
{
$sSQL = 'SELECT place_id, parent_place_id, 30 as rank_search,';
$sSQL .= ' ST_LineLocatePoint(linegeo,'.$sPointSQL.') as fraction';
$sSQL .= ' , ST_Distance(linegeo,'.$sPointSQL.') as distance';
$sSQL .= ' FROM location_property_osmline';
$sSQL .= ' WHERE ST_DWithin('.$sPointSQL.', linegeo, '.$fSearchDiam.')';
$sSQL .= ' and indexed_status = 0 and startnumber is not NULL ';
$sSQL .= ' ORDER BY ST_distance('.$sPointSQL.', linegeo) ASC limit 1';
function setRank($iRank)
{
$this->iMaxRank = $iRank;
}
return chksql(
$this->oDB->getRow($sSQL),
"Could not determine closest housenumber on an osm interpolation line."
);
}
function setZoom($iZoom)
{
// Zoom to rank, this could probably be calculated but a lookup gives fine control
$aZoomRank = array(
0 => 2, // Continent / Sea
1 => 2,
2 => 2,
3 => 4, // Country
4 => 4,
5 => 8, // State
6 => 10, // Region
7 => 10,
8 => 12, // County
9 => 12,
10 => 17, // City
11 => 17,
12 => 18, // Town / Village
13 => 18,
14 => 22, // Suburb
15 => 22,
16 => 26, // Street, TODO: major street?
17 => 26,
18 => 30, // or >, Building
19 => 30, // or >, Building
);
$this->iMaxRank = (isset($iZoom) && isset($aZoomRank[$iZoom]))?$aZoomRank[$iZoom]:28;
}
/* lookup()
* returns { place_id =>, type => '(osm|tiger)' }
* fails if no place was found
*/
function lookup()
{
$sPointSQL = 'ST_SetSRID(ST_Point('.$this->fLon.','.$this->fLat.'),4326)';
$iMaxRank = $this->iMaxRank;
// Find the nearest point
$fSearchDiam = 0.0004;
$iPlaceID = null;
$aArea = false;
$fMaxAreaDistance = 1;
while(!$iPlaceID && $fSearchDiam < $fMaxAreaDistance)
{
$fSearchDiam = $fSearchDiam * 2;
public function lookup($fLat, $fLon, $bDoInterpolation = true)
{
$sPointSQL = 'ST_SetSRID(ST_Point('.$fLon.','.$fLat.'),4326)';
$iMaxRank = $this->iMaxRank;
// If we have to expand the search area by a large amount then we need a larger feature
// then there is a limit to how small the feature should be
if ($fSearchDiam > 2 && $iMaxRank > 4) $iMaxRank = 4;
if ($fSearchDiam > 1 && $iMaxRank > 9) $iMaxRank = 8;
if ($fSearchDiam > 0.8 && $iMaxRank > 10) $iMaxRank = 10;
if ($fSearchDiam > 0.6 && $iMaxRank > 12) $iMaxRank = 12;
if ($fSearchDiam > 0.2 && $iMaxRank > 17) $iMaxRank = 17;
if ($fSearchDiam > 0.1 && $iMaxRank > 18) $iMaxRank = 18;
if ($fSearchDiam > 0.008 && $iMaxRank > 22) $iMaxRank = 22;
if ($fSearchDiam > 0.001 && $iMaxRank > 26) $iMaxRank = 26;
// Find the nearest point
$fSearchDiam = 0.0004;
$iPlaceID = null;
$fMaxAreaDistance = 1;
$bIsInUnitedStates = false;
$bPlaceIsTiger = false;
$bPlaceIsLine = false;
while (!$iPlaceID && $fSearchDiam < $fMaxAreaDistance) {
$fSearchDiam = $fSearchDiam * 2;
$sSQL = 'select place_id,parent_place_id,rank_search 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 indexed_status = 0 ';
$sSQL .= ' and (ST_GeometryType(geometry) not in (\'ST_Polygon\',\'ST_MultiPolygon\') ';
$sSQL .= ' OR ST_DWithin('.$sPointSQL.', centroid, '.$fSearchDiam.'))';
$sSQL .= ' ORDER BY ST_distance('.$sPointSQL.', geometry) ASC limit 1';
if (CONST_Debug) var_dump($sSQL);
$aPlace = $this->oDB->getRow($sSQL);
if (PEAR::IsError($aPlace))
{
failInternalError("Could not determine closest place.", $sSQL, $aPlace);
}
$iPlaceID = $aPlace['place_id'];
$iParentPlaceID = $aPlace['parent_place_id'];
}
// If we have to expand the search area by a large amount then we need a larger feature
// then there is a limit to how small the feature should be
if ($fSearchDiam > 2 && $iMaxRank > 4) $iMaxRank = 4;
if ($fSearchDiam > 1 && $iMaxRank > 9) $iMaxRank = 8;
if ($fSearchDiam > 0.8 && $iMaxRank > 10) $iMaxRank = 10;
if ($fSearchDiam > 0.6 && $iMaxRank > 12) $iMaxRank = 12;
if ($fSearchDiam > 0.2 && $iMaxRank > 17) $iMaxRank = 17;
if ($fSearchDiam > 0.1 && $iMaxRank > 18) $iMaxRank = 18;
if ($fSearchDiam > 0.008 && $iMaxRank > 22) $iMaxRank = 22;
if ($fSearchDiam > 0.001 && $iMaxRank > 26) {
// try with interpolations before continuing
if ($bDoInterpolation) {
// no house found, try with interpolations
$aPlaceLine = $this->lookupInterpolation($sPointSQL, $fSearchDiam/2);
// 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)
{
$iPlaceID = $iParentPlaceID;
}
$sSQL = "select address_place_id from place_addressline where place_id = $iPlaceID order by abs(cached_rank_address - $iMaxRank) asc,cached_rank_address desc,isaddress desc,distance desc limit 1";
$iPlaceID = $this->oDB->getOne($sSQL);
if (PEAR::IsError($iPlaceID))
{
failInternalError("Could not get parent for place.", $sSQL, $iPlaceID);
}
if (!$iPlaceID)
{
$iPlaceID = $aPlace['place_id'];
}
}
if ($aPlaceLine) {
// interpolation is closer to point than placex house
$bPlaceIsLine = true;
$aPlace = $aPlaceLine;
$iPlaceID = $aPlaceLine['place_id'];
$iParentPlaceID = $aPlaceLine['parent_place_id']; // the street
$fFraction = $aPlaceLine['fraction'];
$iMaxRank = 30;
$oPlaceLookup = new PlaceLookup($this->oDB);
$oPlaceLookup->setLanguagePreference($this->aLangPrefOrder);
$oPlaceLookup->setIncludeAddressDetails($this->bAddressDetails);
$oPlaceLookup->setPlaceId($iPlaceID);
break;
}
}
// no interpolation found, continue search
$iMaxRank = 26;
}
return $oPlaceLookup->lookup();
}
}
?>
$sSQL = 'select place_id,parent_place_id,rank_search,country_code';
$sSQL .= ' 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\',\'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.'))';
$sSQL .= ' ORDER BY ST_distance('.$sPointSQL.', geometry) ASC limit 1';
if (CONST_Debug) var_dump($sSQL);
$aPlace = chksql(
$this->oDB->getRow($sSQL),
"Could not determine closest place."
);
$iPlaceID = $aPlace['place_id'];
$iParentPlaceID = $aPlace['parent_place_id'];
$bIsInUnitedStates = ($aPlace['country_code'] == 'us');
}
// If a house was found make sure there isn't an interpolation line
// that is closer
if ($bDoInterpolation && !$bPlaceIsLine && $aPlace && $aPlace['rank_search'] == 30) {
// get the distance of the house to the search point
$sSQL = 'SELECT ST_distance('.$sPointSQL.', house.geometry)';
$sSQL .= ' FROM placex as house WHERE house.place_id='.$iPlaceID;
$fDistancePlacex = chksql(
$this->oDB->getOne($sSQL),
"Could not determine distance between searched point and placex house."
);
// look for an interpolation that is closer
$aPlaceLine = $this->lookupInterpolation($sPointSQL, $fDistancePlacex);
if ($aPlaceLine && (float) $aPlaceLine['distance'] < (float) $fDistancePlacex) {
// interpolation is closer to point than placex house
$bPlaceIsLine = true;
$aPlace = $aPlaceLine;
$iPlaceID = $aPlaceLine['place_id'];
$iParentPlaceID = $aPlaceLine['parent_place_id']; // the street
$fFraction = $aPlaceLine['fraction'];
}
}
// Only street found? If it's in the US we can check TIGER data for nearest housenumber
if (CONST_Use_US_Tiger_Data && $bDoInterpolation && $bIsInUnitedStates && $this->iMaxRank >= 28 && $iPlaceID && ($aPlace['rank_search'] == 26 || $aPlace['rank_search'] == 27 )) {
$fSearchDiam = 0.001;
$sSQL = 'SELECT place_id,parent_place_id,30 as rank_search, ST_LineLocatePoint(linegeo,'.$sPointSQL.') as fraction';
//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.', linegeo, '.$fSearchDiam.')'; //no centroid anymore in Tiger data, now we have lines
$sSQL .= ' ORDER BY ST_distance('.$sPointSQL.', linegeo) ASC limit 1';
if (CONST_Debug) {
$sSQL = preg_replace('/limit 1/', 'limit 100', $sSQL);
var_dump($sSQL);
$aAllHouses = chksql($this->oDB->getAll($sSQL));
foreach ($aAllHouses as $i) {
echo $i['housenumber'] . ' | ' . $i['distance'] * 1000 . ' | ' . $i['lat'] . ' | ' . $i['lon']. ' | '. "<br>\n";
}
}
$aPlaceTiger = chksql(
$this->oDB->getRow($sSQL),
"Could not determine closest Tiger place."
);
if ($aPlaceTiger) {
if (CONST_Debug) var_dump('found Tiger housenumber', $aPlaceTiger);
$bPlaceIsTiger = true;
$aPlace = $aPlaceTiger;
$iPlaceID = $aPlaceTiger['place_id'];
$iParentPlaceID = $aPlaceTiger['parent_place_id']; // the street
$fFraction = $aPlaceTiger['fraction'];
$iMaxRank = 30;
}
}
// 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 || $bPlaceIsTiger || $bPlaceIsLine) && $iParentPlaceID) {
$iPlaceID = $iParentPlaceID;
$bPlaceIsLine = false;
$bPlaceIsTiger = false;
}
$sSQL = 'select address_place_id';
$sSQL .= ' FROM place_addressline';
$sSQL .= " WHERE place_id = $iPlaceID";
$sSQL .= " ORDER BY abs(cached_rank_address - $iMaxRank) asc,cached_rank_address desc,isaddress desc,distance desc";
$sSQL .= ' LIMIT 1';
$iPlaceID = chksql($this->oDB->getOne($sSQL), "Could not get parent for place.");
if (!$iPlaceID) {
$iPlaceID = $aPlace['place_id'];
}
}
return array(
'place_id' => $iPlaceID,
'type' => $bPlaceIsTiger ? 'tiger' : ($bPlaceIsLine ? 'interpolation' : 'osm'),
'fraction' => ($bPlaceIsTiger || $bPlaceIsLine) ? $fFraction : -1
);
}
}

View File

@@ -1,145 +1,130 @@
<?php
function getCmdOpt($aArg, $aSpec, &$aResult, $bExitOnError = false, $bExitOnUnknown = false)
{
$aQuick = array();
$aCounts = array();
foreach($aSpec as $aLine)
{
if (is_array($aLine))
{
if ($aLine[0]) $aQuick['--'.$aLine[0]] = $aLine;
if ($aLine[1]) $aQuick['-'.$aLine[1]] = $aLine;
$aCounts[$aLine[0]] = 0;
}
}
function getCmdOpt($aArg, $aSpec, &$aResult, $bExitOnError = false, $bExitOnUnknown = false)
{
$aQuick = array();
$aCounts = array();
$aResult = array();
$bUnknown = false;
$iSize = sizeof($aArg);
for ($i = 1; $i < $iSize; $i++)
{
if (isset($aQuick[$aArg[$i]]))
{
$aLine = $aQuick[$aArg[$i]];
$aCounts[$aLine[0]]++;
$xVal = null;
if ($aLine[4] == $aLine[5])
{
if ($aLine[4])
{
$xVal = array();
for($n = $aLine[4]; $i < $iSize && $n; $n--)
{
$i++;
if ($i >= $iSize || $aArg[$i][0] == '-') showUsage($aSpec, $bExitOnError, 'Parameter of \''.$aLine[0].'\' is missing');
foreach ($aSpec as $aLine) {
if (is_array($aLine)) {
if ($aLine[0]) $aQuick['--'.$aLine[0]] = $aLine;
if ($aLine[1]) $aQuick['-'.$aLine[1]] = $aLine;
$aCounts[$aLine[0]] = 0;
}
}
switch ($aLine[6])
{
case 'realpath':
$xVal[] = realpath($aArg[$i]);
break;
case 'realdir':
$sPath = realpath(dirname($aArg[$i]));
if ($sPath)
$xVal[] = $sPath . '/' . basename($aArg[$i]);
else
$xVal[] = $sPath;
break;
case 'bool':
$xVal[] = (bool)$aArg[$i];
break;
case 'int':
$xVal[] = (int)$aArg[$i];
break;
case 'float':
$xVal[] = (float)$aArg[$i];
break;
default:
$xVal[] = $aArg[$i];
break;
}
}
if ($aLine[4] == 1) $xVal = $xVal[0];
}
else
{
$xVal = true;
}
}
else
{
fail('Variable numbers of params not yet supported');
}
$aResult = array();
$bUnknown = false;
$iSize = sizeof($aArg);
for ($i = 1; $i < $iSize; $i++) {
if (isset($aQuick[$aArg[$i]])) {
$aLine = $aQuick[$aArg[$i]];
$aCounts[$aLine[0]]++;
$xVal = null;
if ($aLine[4] == $aLine[5]) {
if ($aLine[4]) {
$xVal = array();
for ($n = $aLine[4]; $i < $iSize && $n; $n--) {
$i++;
if ($i >= $iSize || $aArg[$i][0] == '-') showUsage($aSpec, $bExitOnError, 'Parameter of \''.$aLine[0].'\' is missing');
if ($aLine[3] > 1)
{
if (!array_key_exists($aLine[0], $aResult)) $aResult[$aLine[0]] = array();
$aResult[$aLine[0]][] = $xVal;
}
else
{
$aResult[$aLine[0]] = $xVal;
}
}
else
{
$bUnknown = $aArg[$i];
}
}
switch ($aLine[6]) {
case 'realpath':
$xVal[] = realpath($aArg[$i]);
break;
case 'realdir':
$sPath = realpath(dirname($aArg[$i]));
if ($sPath) {
$xVal[] = $sPath . '/' . basename($aArg[$i]);
} else {
$xVal[] = $sPath;
}
break;
case 'bool':
$xVal[] = (bool)$aArg[$i];
break;
case 'int':
$xVal[] = (int)$aArg[$i];
break;
case 'float':
$xVal[] = (float)$aArg[$i];
break;
default:
$xVal[] = $aArg[$i];
break;
}
}
if ($aLine[4] == 1) $xVal = $xVal[0];
} else {
$xVal = true;
}
} else {
fail('Variable numbers of params not yet supported');
}
if (array_key_exists('help', $aResult)) showUsage($aSpec);
if ($bUnknown && $bExitOnUnknown) showUsage($aSpec, $bExitOnError, 'Unknown option \''.$bUnknown.'\'');
if ($aLine[3] > 1) {
if (!array_key_exists($aLine[0], $aResult)) $aResult[$aLine[0]] = array();
$aResult[$aLine[0]][] = $xVal;
} else {
$aResult[$aLine[0]] = $xVal;
}
} else {
$bUnknown = $aArg[$i];
}
}
foreach($aSpec as $aLine)
{
if (is_array($aLine))
{
if ($aCounts[$aLine[0]] < $aLine[2]) showUsage($aSpec, $bExitOnError, 'Option \''.$aLine[0].'\' is missing');
if ($aCounts[$aLine[0]] > $aLine[3]) showUsage($aSpec, $bExitOnError, 'Option \''.$aLine[0].'\' is pressent too many times');
switch ($aLine[6])
{
case 'bool':
if (!array_key_exists($aLine[0], $aResult))
$aResult[$aLine[0]] = false;
break;
}
}
}
return $bUnknown;
}
if (array_key_exists('help', $aResult)) showUsage($aSpec);
if ($bUnknown && $bExitOnUnknown) showUsage($aSpec, $bExitOnError, 'Unknown option \''.$bUnknown.'\'');
function showUsage($aSpec, $bExit = false, $sError = false)
{
if ($sError)
{
echo basename($_SERVER['argv'][0]).': '.$sError."\n";
echo 'Try `'.basename($_SERVER['argv'][0]).' --help` for more information.'."\n";
exit;
}
echo "Usage: ".basename($_SERVER['argv'][0])."\n";
$bFirst = true;
foreach($aSpec as $aLine)
{
if (is_array($aLine))
{
if ($bFirst)
{
$bFirst = false;
echo "\n";
}
$aNames = array();
if ($aLine[1]) $aNames[] = '-'.$aLine[1];
if ($aLine[0]) $aNames[] = '--'.$aLine[0];
$sName = join(', ',$aNames);
echo ' '.$sName.str_repeat(' ',30-strlen($sName)).$aLine[7]."\n";
}
else
{
echo $aLine."\n";
}
}
echo "\n";
exit;
}
foreach ($aSpec as $aLine) {
if (is_array($aLine)) {
if ($aCounts[$aLine[0]] < $aLine[2]) showUsage($aSpec, $bExitOnError, 'Option \''.$aLine[0].'\' is missing');
if ($aCounts[$aLine[0]] > $aLine[3]) showUsage($aSpec, $bExitOnError, 'Option \''.$aLine[0].'\' is pressent too many times');
switch ($aLine[6]) {
case 'bool':
if (!array_key_exists($aLine[0], $aResult))
$aResult[$aLine[0]] = false;
break;
}
}
}
return $bUnknown;
}
function showUsage($aSpec, $bExit = false, $sError = false)
{
if ($sError) {
echo basename($_SERVER['argv'][0]).': '.$sError."\n";
echo 'Try `'.basename($_SERVER['argv'][0]).' --help` for more information.'."\n";
exit;
}
echo "Usage: ".basename($_SERVER['argv'][0])."\n";
$bFirst = true;
foreach ($aSpec as $aLine) {
if (is_array($aLine)) {
if ($bFirst) {
$bFirst = false;
echo "\n";
}
$aNames = array();
if ($aLine[1]) $aNames[] = '-'.$aLine[1];
if ($aLine[0]) $aNames[] = '--'.$aLine[0];
$sName = join(', ', $aNames);
echo ' '.$sName.str_repeat(' ', 30-strlen($sName)).$aLine[7]."\n";
} else {
echo $aLine."\n";
}
}
echo "\n";
exit;
}
function chksql($oSql, $sMsg = false)
{
if (PEAR::isError($oSql)) {
fail($sMsg || $oSql->getMessage(), $oSql->userinfo);
}
return $oSql;
}

View File

@@ -1,24 +1,38 @@
<?php
require_once('DB.php');
function &getDB($bNew = false, $bPersistent = false)
{
// Get the database object
$oDB =& DB::connect(CONST_Database_DSN.($bNew?'?new_link=true':''), $bPersistent);
if (PEAR::IsError($oDB))
{
var_dump(CONST_Database_DSN);
var_Dump($oDB);
fail($oDB->getMessage());
}
$oDB->setFetchMode(DB_FETCHMODE_ASSOC);
$oDB->query("SET DateStyle TO 'sql,european'");
$oDB->query("SET client_encoding TO 'utf-8'");
return $oDB;
}
require_once('DB.php');
function getDBQuoted($s)
{
return "'".pg_escape_string($s)."'";
}
function &getDB($bNew = false, $bPersistent = false)
{
// Get the database object
$oDB = chksql(
DB::connect(CONST_Database_DSN.($bNew?'?new_link=true':''), $bPersistent),
"Failed to establish database connection"
);
$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;
}
function getDBQuoted($s)
{
return "'".pg_escape_string($s)."'";
}
function getPostgresVersion(&$oDB)
{
$sVersionString = $oDB->getOne('select version()');
preg_match('#PostgreSQL ([0-9]+)[.]([0-9]+)[^0-9]#', $sVersionString, $aMatches);
return (float) ($aMatches[1].'.'.$aMatches[2]);
}
function getPostgisVersion(&$oDB)
{
$sVersionString = $oDB->getOne('select postgis_full_version()');
preg_match('#POSTGIS="([0-9]+)[.]([0-9]+)[.]([0-9]+)( r([0-9]+))?"#', $sVersionString, $aMatches);
return (float) ($aMatches[1].'.'.$aMatches[2]);
}

View File

@@ -1,8 +1,27 @@
<?php
if (file_exists(getenv('NOMINATIM_SETTINGS')))
{
require_once(getenv('NOMINATIM_SETTINGS'));
}
require_once('init.php');
require_once('cmd.php');
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

@@ -1,64 +1,100 @@
<?php
require_once('init.php');
if (CONST_NoAccessControl)
{
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: OPTIONS,GET");
if (!empty($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
{
header("Access-Control-Allow-Headers: ".$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']);
}
}
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') exit;
require_once('init.php');
require_once('ParameterParser.php');
if (CONST_ClosedForIndexing && strpos(CONST_ClosedForIndexingExceptionIPs, ','.$_SERVER["REMOTE_ADDR"].',') === false)
{
echo "Closed for re-indexing...";
exit;
}
/***************************************************************************
*
* Error handling functions
*
*/
$aBucketKeys = array();
if (isset($_SERVER["HTTP_REFERER"])) $aBucketKeys[] = str_replace('www.','',strtolower(parse_url($_SERVER["HTTP_REFERER"], PHP_URL_HOST)));
if (isset($_SERVER["REMOTE_ADDR"])) $aBucketKeys[] = $_SERVER["REMOTE_ADDR"];
if (isset($_GET["email"])) $aBucketKeys[] = $_GET["email"];
function chksql($oSql, $sMsg = "Database request failed")
{
if (!PEAR::isError($oSql)) return $oSql;
$fBucketVal = doBucket($aBucketKeys,
(defined('CONST_ConnectionBucket_PageType')?constant('CONST_ConnectionBucket_Cost_'.CONST_ConnectionBucket_PageType):1) + user_busy_cost(),
CONST_ConnectionBucket_LeakRate, CONST_ConnectionBucket_BlockLimit);
header('HTTP/1.0 500 Internal Server Error');
header('Content-type: text/html; charset=utf-8');
if ($fBucketVal > CONST_ConnectionBucket_WaitLimit && $fBucketVal < CONST_ConnectionBucket_BlockLimit)
{
$m = getBucketMemcache();
$iCurrentSleeping = $m->increment('sleepCounter');
if (false === $iCurrentSleeping)
{
$m->add('sleepCounter', 0);
$iCurrentSleeping = $m->increment('sleepCounter');
}
if ($iCurrentSleeping >= CONST_ConnectionBucket_MaxSleeping || isBucketSleeping($aBucketKeys))
{
// Too many threads sleeping already. This becomes a hard block.
$fBucketVal = doBucket($aBucketKeys, CONST_ConnectionBucket_BlockLimit, CONST_ConnectionBucket_LeakRate, CONST_ConnectionBucket_BlockLimit);
}
else
{
setBucketSleeping($aBucketKeys, true);
sleep(($fBucketVal - CONST_ConnectionBucket_WaitLimit)/CONST_ConnectionBucket_LeakRate);
$fBucketVal = doBucket($aBucketKeys, CONST_ConnectionBucket_LeakRate, CONST_ConnectionBucket_LeakRate, CONST_ConnectionBucket_BlockLimit);
setBucketSleeping($aBucketKeys, false);
}
$m->decrement('sleepCounter');
}
$sSqlError = $oSql->getMessage();
if (strpos(CONST_BlockedIPs, ','.$_SERVER["REMOTE_ADDR"].',') !== false || $fBucketVal >= CONST_ConnectionBucket_BlockLimit)
{
header("HTTP/1.0 429 Too Many Requests");
echo "Your IP has been blocked. \n";
echo CONST_BlockMessage;
exit;
}
echo <<<INTERNALFAIL
<html>
<head><title>Internal Server Error</title></head>
<body>
<h1>Internal Server Error</h1>
<p>Nominatim has encountered an internal error while accessing the database.
This may happen because the database is broken or because of a bug in
the software. If you think it is a bug, feel free to report
it over on <a href="https://github.com/openstreetmap/Nominatim/issues">
Github</a>. Please include the URL that caused the problem and the
complete error details below.</p>
<p><b>Message:</b> $sMsg</p>
<p><b>SQL Error:</b> $sSqlError</p>
<p><b>Details:</b> <pre>
INTERNALFAIL;
header('Content-type: text/html; charset=utf-8');
if (CONST_Debug) {
var_dump($oSql);
} else {
echo "<pre>\n".$oSql->getUserInfo()."</pre>";
}
echo "</pre></p></body></html>";
exit;
}
function failInternalError($sError, $sSQL = false, $vDumpVar = false)
{
header('HTTP/1.0 500 Internal Server Error');
header('Content-type: text/html; charset=utf-8');
echo "<html><body><h1>Internal Server Error</h1>";
echo '<p>Nominatim has encountered an internal error while processing your request. This is most likely because of a bug in the software.</p>';
echo "<p><b>Details:</b> ".$sError,"</p>";
echo '<p>Feel free to file an issue on <a href="https://github.com/openstreetmap/Nominatim/issues">Github</a>. ';
echo 'Please include the error message above and the URL you used.</p>';
if (CONST_Debug) {
echo "<hr><h2>Debugging Information</h2><br>";
if ($sSQL) {
echo "<h3>SQL query</h3><code>".$sSQL."</code>";
}
if ($vDumpVar) {
echo "<h3>Result</h3> <code>";
var_dump($vDumpVar);
echo "</code>";
}
}
echo "\n</body></html>\n";
exit;
}
function userError($sError)
{
header('HTTP/1.0 400 Bad Request');
header('Content-type: text/html; charset=utf-8');
echo "<html><body><h1>Bad Request</h1>";
echo '<p>Nominatim has encountered an error with your request.</p>';
echo "<p><b>Details:</b> ".$sError."</p>";
echo '<p>If you feel this error is incorrect feel file an issue on <a href="https://github.com/openstreetmap/Nominatim/issues">Github</a>. ';
echo 'Please include the error message above and the URL you used.</p>';
echo "\n</body></html>\n";
exit;
}
/***************************************************************************
* HTTP Reply header setup
*/
if (CONST_NoAccessControl) {
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: OPTIONS,GET");
if (!empty($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) {
header("Access-Control-Allow-Headers: ".$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']);
}
}
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') exit;
if (CONST_Debug) header('Content-type: text/html; charset=utf-8');

View File

@@ -1,14 +1,9 @@
<?php
@define('CONST_BasePath', dirname(dirname(__FILE__)));
require_once(CONST_BasePath.'/lib/lib.php');
require_once(CONST_BasePath.'/lib/db.php');
require_once(CONST_BasePath.'/settings/settings.php');
require_once(CONST_BasePath.'/lib/lib.php');
require_once(CONST_BasePath.'/lib/leakybucket.php');
require_once(CONST_BasePath.'/lib/db.php');
if (get_magic_quotes_gpc())
{
echo "Please disable magic quotes in your php.ini configuration\n";
exit;
}
if (get_magic_quotes_gpc()) {
echo "Please disable magic quotes in your php.ini configuration\n";
exit;
}

View File

@@ -1,168 +0,0 @@
<?php
function getBucketMemcache()
{
static $m;
if (!CONST_ConnectionBucket_MemcacheServerAddress) return null;
if (!isset($m))
{
$m = new Memcached();
$m->addServer(CONST_ConnectionBucket_MemcacheServerAddress, CONST_ConnectionBucket_MemcacheServerPort);
}
return $m;
}
function doBucket($asKey, $iRequestCost, $iLeakPerSecond, $iThreshold)
{
$m = getBucketMemcache();
if (!$m) return 0;
$iMaxVal = 0;
$t = time();
foreach($asKey as $sKey)
{
$aCurrentBlock = $m->get($sKey);
if (!$aCurrentBlock)
{
$aCurrentBlock = array($iRequestCost, $t, false);
}
else
{
// add RequestCost
// remove leak * the time since the last request
$aCurrentBlock[0] += $iRequestCost - ($t - $aCurrentBlock[1])*$iLeakPerSecond;
$aCurrentBlock[1] = $t;
}
if ($aCurrentBlock[0] <= 0)
{
$m->delete($sKey);
}
else
{
// If we have hit the threshold stop and record this to the block list
if ($aCurrentBlock[0] >= $iThreshold)
{
$aCurrentBlock[0] = $iThreshold;
// Make up to 10 attempts to record this to memcache (with locking to prevent conflicts)
$i = 10;
for($i = 0; $i < 10; $i++)
{
$aBlockedList = $m->get('blockedList', null, $hCasToken);
if (!$aBlockedList)
{
$aBlockedList = array();
$m->add('blockedList', $aBlockedList);
$aBlockedList = $m->get('blockedList', null, $hCasToken);
}
if (!isset($aBlockedList[$sKey]))
{
$aBlockedList[$sKey] = array(1, $t);
}
else
{
$aBlockedList[$sKey][0]++;
$aBlockedList[$sKey][1] = $t;
}
if (sizeof($aBlockedList) > CONST_ConnectionBucket_MaxBlockList)
{
uasort($aBlockedList, 'byValue1');
$aBlockedList = array_slice($aBlockedList, 0, CONST_ConnectionBucket_MaxBlockList);
}
$x = $m->cas($hCasToken, 'blockedList', $aBlockedList);
if ($x) break;
}
}
// Only keep in memcache until the time it would have expired (to avoid clutering memcache)
$m->set($sKey, $aCurrentBlock, $t + 1 + $aCurrentBlock[0]/$iLeakPerSecond);
}
// Bucket result in the largest bucket we find
$iMaxVal = max($iMaxVal, $aCurrentBlock[0]);
}
return $iMaxVal;
}
function isBucketSleeping($asKey)
{
$m = getBucketMemcache();
if (!$m) return false;
foreach($asKey as $sKey)
{
$aCurrentBlock = $m->get($sKey);
if ($aCurrentBlock[2]) return true;
}
return false;
}
function setBucketSleeping($asKey, $bVal)
{
$m = getBucketMemcache();
if (!$m) return false;
$iMaxVal = 0;
$t = time();
foreach($asKey as $sKey)
{
$aCurrentBlock = $m->get($sKey);
$aCurrentBlock[2] = $bVal;
$m->set($sKey, $aCurrentBlock, $t + 1 + $aCurrentBlock[0]/CONST_ConnectionBucket_LeakRate);
}
return true;
}
function byValue1($a, $b)
{
if ($a[1] == $b[1])
{
return 0;
}
return ($a[1] > $b[1]) ? -1 : 1;
}
function byLastBlockTime($a, $b)
{
if ($a['lastBlockTimestamp'] == $b['lastBlockTimestamp'])
{
return 0;
}
return ($a['lastBlockTimestamp'] > $b['lastBlockTimestamp']) ? -1 : 1;
}
function getBucketBlocks()
{
$m = getBucketMemcache();
if (!$m) return null;
$t = time();
$aBlockedList = $m->get('blockedList', null, $hCasToken);
if (!$aBlockedList) $aBlockedList = array();
foreach($aBlockedList as $sKey => $aDetails)
{
$aCurrentBlock = $m->get($sKey);
if (!$aCurrentBlock) $aCurrentBlock = array(0, $t);
$iCurrentBucketSize = max(0, $aCurrentBlock[0] - ($t - $aCurrentBlock[1])*CONST_ConnectionBucket_LeakRate);
$aBlockedList[$sKey] = array(
'totalBlocks' => $aDetails[0],
'lastBlockTimestamp' => $aDetails[1],
'isSleeping' => (isset($aCurrentBlock[2])?$aCurrentBlock[2]:false),
'currentBucketSize' => $iCurrentBucketSize,
'currentlyBlocked' => $iCurrentBucketSize + (CONST_ConnectionBucket_Cost_Reverse) >= CONST_ConnectionBucket_BlockLimit,
);
}
uasort($aBlockedList, 'byLastBlockTime');
return $aBlockedList;
}
function clearBucketBlocks()
{
$m = getBucketMemcache();
if (!$m) return false;
$m->delete('blockedList');
return true;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,90 +1,74 @@
<?php
function logStart(&$oDB, $sType = '', $sQuery = '', $aLanguageList = array())
{
$aStartTime = explode('.',microtime(true));
if (!isset($aStartTime[1])) $aStartTime[1] = '0';
$sOutputFormat = '';
if (isset($_GET['format'])) $sOutputFormat = $_GET['format'];
function logStart(&$oDB, $sType = '', $sQuery = '', $aLanguageList = array())
{
$fStartTime = microtime(true);
$aStartTime = explode('.', $fStartTime);
if (!isset($aStartTime[1])) $aStartTime[1] = '0';
$hLog = array(
date('Y-m-d H:i:s',$aStartTime[0]).'.'.$aStartTime[1],
$_SERVER["REMOTE_ADDR"],
$_SERVER['QUERY_STRING'],
$sQuery
);
$sOutputFormat = '';
if (isset($_GET['format'])) $sOutputFormat = $_GET['format'];
if (CONST_Log_DB)
{
// Log
if ($sType == 'search')
{
$oDB->query('insert into query_log values ('.getDBQuoted($hLog[0]).','.getDBQuoted($hLog[3]).','.getDBQuoted($hLog[1]).')');
}
if ($sType == 'reverse') {
$sOutQuery = (isset($_GET['lat'])?$_GET['lat']:'').'/';
if (isset($_GET['lon'])) $sOutQuery .= $_GET['lon'];
if (isset($_GET['zoom'])) $sOutQuery .= '/'.$_GET['zoom'];
} else {
$sOutQuery = $sQuery;
}
$sSQL = 'insert into new_query_log (type,starttime,query,ipaddress,useragent,language,format)';
$sSQL .= ' values ('.getDBQuoted($sType).','.getDBQuoted($hLog[0]).','.getDBQuoted($hLog[2]);
$sSQL .= ','.getDBQuoted($hLog[1]).','.getDBQuoted($_SERVER['HTTP_USER_AGENT']).','.getDBQuoted(join(',',$aLanguageList)).','.getDBQuoted($sOutputFormat).')';
$oDB->query($sSQL);
}
$hLog = array(
date('Y-m-d H:i:s', $aStartTime[0]).'.'.$aStartTime[1],
$_SERVER["REMOTE_ADDR"],
$_SERVER['QUERY_STRING'],
$sOutQuery,
$sType,
$fStartTime
);
if (CONST_Log_File && CONST_Log_File_ReverseLog != '')
{
if ($sType == 'reverse')
{
$aStartTime = explode('.',$hLog[0]);
file_put_contents(CONST_Log_File_ReverseLog,
$aStartTime[0].','.$aStartTime[1].','.
php_uname('n').','.
'"'.addslashes(isset($_SERVER['HTTP_REFERER'])?$_SERVER['HTTP_REFERER']:'').'",'.
'"'.addslashes($hLog[1]).'",'.
$_GET['lat'].','.
$_GET['lon'].','.
$_GET['zoom'].','.
'"'.addslashes($_SERVER['HTTP_USER_AGENT']).'",'.
'"'.addslashes($sOutputFormat).'"'."\n",
FILE_APPEND);
}
}
if (CONST_Log_DB) {
if (isset($_GET['email']))
$sUserAgent = $_GET['email'];
elseif (isset($_SERVER['HTTP_REFERER']))
$sUserAgent = $_SERVER['HTTP_REFERER'];
elseif (isset($_SERVER['HTTP_USER_AGENT']))
$sUserAgent = $_SERVER['HTTP_USER_AGENT'];
else $sUserAgent = '';
$sSQL = 'insert into new_query_log (type,starttime,query,ipaddress,useragent,language,format,searchterm)';
$sSQL .= ' values ('.getDBQuoted($sType).','.getDBQuoted($hLog[0]).','.getDBQuoted($hLog[2]);
$sSQL .= ','.getDBQuoted($hLog[1]).','.getDBQuoted($sUserAgent).','.getDBQuoted(join(',', $aLanguageList)).','.getDBQuoted($sOutputFormat).','.getDBQuoted($hLog[3]).')';
$oDB->query($sSQL);
}
return $hLog;
}
return $hLog;
}
function logEnd(&$oDB, $hLog, $iNumResults)
{
$aEndTime = explode('.',microtime(true));
if (!$aEndTime[1]) $aEndTime[1] = '0';
$sEndTime = date('Y-m-d H:i:s',$aEndTime[0]).'.'.$aEndTime[1];
function logEnd(&$oDB, $hLog, $iNumResults)
{
$fEndTime = microtime(true);
if (CONST_Log_DB)
{
$sSQL = 'update query_log set endtime = '.getDBQuoted($sEndTime).', results = '.$iNumResults;
$sSQL .= ' where starttime = '.getDBQuoted($hLog[0]);
$sSQL .= ' and ipaddress = '.getDBQuoted($hLog[1]);
$sSQL .= ' and query = '.getDBQuoted($hLog[3]);
$oDB->query($sSQL);
if (CONST_Log_DB) {
$aEndTime = explode('.', $fEndTime);
if (!$aEndTime[1]) $aEndTime[1] = '0';
$sEndTime = date('Y-m-d H:i:s', $aEndTime[0]).'.'.$aEndTime[1];
$sSQL = 'update new_query_log set endtime = '.getDBQuoted($sEndTime).', results = '.$iNumResults;
$sSQL .= ' where starttime = '.getDBQuoted($hLog[0]);
$sSQL .= ' and ipaddress = '.getDBQuoted($hLog[1]);
$sSQL .= ' and query = '.getDBQuoted($hLog[2]);
$oDB->query($sSQL);
}
$sSQL = 'update new_query_log set endtime = '.getDBQuoted($sEndTime).', results = '.$iNumResults;
$sSQL .= ' where starttime = '.getDBQuoted($hLog[0]);
$sSQL .= ' and ipaddress = '.getDBQuoted($hLog[1]);
$sSQL .= ' and query = '.getDBQuoted($hLog[2]);
$oDB->query($sSQL);
}
if (CONST_Log_File && CONST_Log_File_SearchLog != '')
{
$aStartTime = explode('.',$hLog[0]);
file_put_contents(CONST_Log_File_SearchLog,
$aStartTime[0].','.$aStartTime[1].','.
php_uname('n').','.
'"'.addslashes(isset($_SERVER['HTTP_REFERER'])?$_SERVER['HTTP_REFERER']:'').'",'.
'"'.addslashes($hLog[1]).'",'.
'"'.addslashes($hLog[3]).'",'.
'"'.addslashes($_SERVER['HTTP_USER_AGENT']).'",'.
'"'.addslashes((isset($_GET['format']))?$_GET['format']:'').'",'.
$iNumResults."\n",
FILE_APPEND);
}
}
if (CONST_Log_File) {
$aOutdata = sprintf(
"[%s] %.4f %d %s \"%s\"\n",
$hLog[0],
$fEndTime-$hLog[5],
$iNumResults,
$hLog[4],
$hLog[2]
);
file_put_contents(CONST_Log_File, $aOutdata, FILE_APPEND | LOCK_EX);
}
}

41
lib/output.php Normal file
View File

@@ -0,0 +1,41 @@
<?php
function formatOSMType($sType, $bIncludeExternal = true)
{
if ($sType == 'N') return 'node';
if ($sType == 'W') return 'way';
if ($sType == 'R') return 'relation';
if (!$bIncludeExternal) return '';
if ($sType == 'T') return 'way';
if ($sType == 'I') return 'way';
return '';
}
function osmLink($aFeature, $sRefText = false)
{
$sOSMType = formatOSMType($aFeature['osm_type'], false);
if ($sOSMType) {
return '<a href="//www.openstreetmap.org/'.$sOSMType.'/'.$aFeature['osm_id'].'">'.$sOSMType.' '.($sRefText?$sRefText:$aFeature['osm_id']).'</a>';
}
return '';
}
function wikipediaLink($aFeature)
{
if ($aFeature['wikipedia']) {
list($sLanguage, $sArticle) = explode(':', $aFeature['wikipedia']);
return '<a href="https://'.$sLanguage.'.wikipedia.org/wiki/'.urlencode($sArticle).'" target="_blank">'.$aFeature['wikipedia'].'</a>';
}
return '';
}
function detailsLink($aFeature, $sTitle = false)
{
if (!$aFeature['place_id']) return '';
return '<a href="details.php?place_id='.$aFeature['place_id'].'">'.($sTitle?$sTitle:$aFeature['place_id']).'</a>';
}

View File

@@ -0,0 +1,133 @@
<?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 $fLat; ?>" >
<span id="switch-coords">&lt;&gt;</span>
<input name="lon" type="text" class="form-control input-sm" placeholder="longitude" value="<?php echo $fLon; ?>" >
max zoom
<select name="zoom" class="form-control input-sm">
<option value="" <?php if ($iZoom === false) echo 'selected="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 = $iZoom === $iZoomLevel;
echo '<option value="'.$iZoomLevel.'"'.($bSel?' selected="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 (count($aPlace)>0) { ?>
<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 id="map-position-inner"></div>
<div id="map-position-close"><a href="#">hide</a></div>
</div>
<div id="map"></div>
</div>
</div> <!-- /content -->
<script type="text/javascript">
<?php
$aNominatimMapInit = array(
'zoom' => $iZoom !== false ? $iZoom : CONST_Default_Zoom,
'lat' => $fLat !== false ? $fLat : CONST_Default_Lat,
'lon' => $fLon !== false ? $fLon : 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

@@ -1,28 +1,56 @@
<?php
$aFilteredPlaces = array();
if (!sizeof($aPlace))
{
if (isset($sError))
$aFilteredPlaces['error'] = $sError;
else
$aFilteredPlaces['error'] = 'Unable to geocode';
}
else
{
if ($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)
{
$aFilteredPlaces['osm_type'] = $sOSMType;
$aFilteredPlaces['osm_id'] = $aPlace['osm_id'];
}
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'];
}
$aFilteredPlaces = array();
javascript_renderData($aFilteredPlaces);
if (!sizeof($aPlace))
{
if (isset($sError))
$aFilteredPlaces['error'] = $sError;
else
$aFilteredPlaces['error'] = 'Unable to geocode';
}
else
{
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 = formatOSMType($aPlace['osm_type']);
if ($sOSMType)
{
$aFilteredPlaces['osm_type'] = $sOSMType;
$aFilteredPlaces['osm_id'] = $aPlace['osm_id'];
}
if (isset($aPlace['lat'])) $aFilteredPlaces['lat'] = $aPlace['lat'];
if (isset($aPlace['lon'])) $aFilteredPlaces['lon'] = $aPlace['lon'];
$aFilteredPlaces['display_name'] = $aPlace['langaddress'];
if (isset($aPlace['aAddress'])) $aFilteredPlaces['address'] = $aPlace['aAddress'];
if (isset($aPlace['sExtraTags'])) $aFilteredPlaces['extratags'] = $aPlace['sExtraTags'];
if (isset($aPlace['sNameDetails'])) $aFilteredPlaces['namedetails'] = $aPlace['sNameDetails'];
if (isset($aPlace['aBoundingBox']))
{
$aFilteredPlaces['boundingbox'] = $aPlace['aBoundingBox'];
}
if (isset($aPlace['asgeojson']))
{
$aFilteredPlaces['geojson'] = json_decode($aPlace['asgeojson']);
}
if (isset($aPlace['assvg']))
{
$aFilteredPlaces['svg'] = $aPlace['assvg'];
}
if (isset($aPlace['astext']))
{
$aFilteredPlaces['geotext'] = $aPlace['astext'];
}
if (isset($aPlace['askml']))
{
$aFilteredPlaces['geokml'] = $aPlace['askml'];
}
}
javascript_renderData($aFilteredPlaces);

View File

@@ -1,38 +1,68 @@
<?php
$aFilteredPlaces = array();
if (!sizeof($aPlace))
{
if (isset($sError))
$aFilteredPlaces['error'] = $sError;
else
$aFilteredPlaces['error'] = 'Unable to geocode';
}
else
{
if ($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)
{
$aFilteredPlaces['osm_type'] = $sOSMType;
$aFilteredPlaces['osm_id'] = $aPlace['osm_id'];
}
if (isset($aPlace['lat'])) $aFilteredPlaces['lat'] = $aPlace['lat'];
if (isset($aPlace['lon'])) $aFilteredPlaces['lon'] = $aPlace['lon'];
$aFilteredPlaces = array();
$aFilteredPlaces['place_rank'] = $aPlace['rank_search'];
if (!sizeof($aPlace))
{
if (isset($sError))
$aFilteredPlaces['error'] = $sError;
else
$aFilteredPlaces['error'] = 'Unable to geocode';
}
else
{
if ($aPlace['place_id']) $aFilteredPlaces['place_id'] = $aPlace['place_id'];
$aFilteredPlaces['licence'] = "Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright";
$sOSMType = formatOSMType($aPlace['osm_type']);
if ($sOSMType)
{
$aFilteredPlaces['osm_type'] = $sOSMType;
$aFilteredPlaces['osm_id'] = $aPlace['osm_id'];
}
if (isset($aPlace['lat'])) $aFilteredPlaces['lat'] = $aPlace['lat'];
if (isset($aPlace['lon'])) $aFilteredPlaces['lon'] = $aPlace['lon'];
$aFilteredPlaces['category'] = $aPlace['class'];
$aFilteredPlaces['type'] = $aPlace['type'];
$aFilteredPlaces['place_rank'] = $aPlace['rank_search'];
$aFilteredPlaces['importance'] = $aPlace['importance'];
$aFilteredPlaces['category'] = $aPlace['class'];
$aFilteredPlaces['type'] = $aPlace['type'];
$aFilteredPlaces['addresstype'] = strtolower($aPlace['addresstype']);
$aFilteredPlaces['importance'] = $aPlace['importance'];
$aFilteredPlaces['display_name'] = $aPlace['langaddress'];
$aFilteredPlaces['name'] = $aPlace['placename'];
if ($bShowAddressDetails && $aPlace['aAddress'] && sizeof($aPlace['aAddress'])) $aFilteredPlaces['address'] = $aPlace['aAddress'];
}
$aFilteredPlaces['addresstype'] = strtolower($aPlace['addresstype']);
javascript_renderData($aFilteredPlaces);
$aFilteredPlaces['display_name'] = $aPlace['langaddress'];
$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'];
if (isset($aPlace['aBoundingBox']))
{
$aFilteredPlaces['boundingbox'] = $aPlace['aBoundingBox'];
}
if (isset($aPlace['asgeojson']))
{
$aFilteredPlaces['geojson'] = json_decode($aPlace['asgeojson']);
}
if (isset($aPlace['assvg']))
{
$aFilteredPlaces['svg'] = $aPlace['assvg'];
}
if (isset($aPlace['astext']))
{
$aFilteredPlaces['geotext'] = $aPlace['astext'];
}
if (isset($aPlace['askml']))
{
$aFilteredPlaces['geokml'] = $aPlace['askml'];
}
}
javascript_renderData($aFilteredPlaces);

View File

@@ -1,45 +1,103 @@
<?php
header("content-type: text/xml; charset=UTF-8");
header("content-type: text/xml; charset=UTF-8");
echo "<";
echo "?xml version=\"1.0\" encoding=\"UTF-8\" ?";
echo ">\n";
echo "<";
echo "?xml version=\"1.0\" encoding=\"UTF-8\" ?";
echo ">\n";
echo "<reversegeocode";
echo " timestamp='".date(DATE_RFC822)."'";
echo " attribution='Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright'";
echo " querystring='".htmlspecialchars($_SERVER['QUERY_STRING'], ENT_QUOTES)."'";
echo ">\n";
echo "<reversegeocode";
echo " timestamp='".date(DATE_RFC822)."'";
echo " attribution='Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright'";
echo " querystring='".htmlspecialchars($_SERVER['QUERY_STRING'], ENT_QUOTES)."'";
echo ">\n";
if (!sizeof($aPlace))
{
if (isset($sError))
echo "<error>$sError</error>";
else
echo "<error>Unable to geocode</error>";
}
else
{
echo "<result";
if ($aPlace['place_id']) echo ' place_id="'.$aPlace['place_id'].'"';
$sOSMType = ($aPlace['osm_type'] == 'N'?'node':($aPlace['osm_type'] == 'W'?'way':($aPlace['osm_type'] == 'R'?'relation':'')));
if ($sOSMType) echo ' osm_type="'.$sOSMType.'"'.' osm_id="'.$aPlace['osm_id'].'"';
if ($aPlace['ref']) echo ' ref="'.htmlspecialchars($aPlace['ref']).'"';
if (isset($aPlace['lat'])) echo ' lat="'.htmlspecialchars($aPlace['lat']).'"';
if (isset($aPlace['lon'])) echo ' lon="'.htmlspecialchars($aPlace['lon']).'"';
echo ">".htmlspecialchars($aPlace['langaddress'])."</result>";
if (!sizeof($aPlace))
{
if (isset($sError))
echo "<error>$sError</error>";
else
echo "<error>Unable to geocode</error>";
}
else
{
echo "<result";
if ($aPlace['place_id']) echo ' place_id="'.$aPlace['place_id'].'"';
$sOSMType = formatOSMType($aPlace['osm_type']);
if ($sOSMType) echo ' osm_type="'.$sOSMType.'"'.' osm_id="'.$aPlace['osm_id'].'"';
if ($aPlace['ref']) echo ' ref="'.htmlspecialchars($aPlace['ref']).'"';
if (isset($aPlace['lat'])) echo ' lat="'.htmlspecialchars($aPlace['lat']).'"';
if (isset($aPlace['lon'])) echo ' lon="'.htmlspecialchars($aPlace['lon']).'"';
if (isset($aPlace['aBoundingBox']))
{
echo ' boundingbox="';
echo join(',', $aPlace['aBoundingBox']);
echo '"';
}
if ($bShowAddressDetails) {
echo "<addressparts>";
foreach($aPlace['aAddress'] as $sKey => $sValue)
{
$sKey = str_replace(' ','_',$sKey);
echo "<$sKey>";
echo htmlspecialchars($sValue);
echo "</$sKey>";
}
echo "</addressparts>";
}
}
if (isset($aPlace['asgeojson']))
{
echo ' geojson=\'';
echo $aPlace['asgeojson'];
echo '\'';
}
echo "</reversegeocode>";
if (isset($aPlace['assvg']))
{
echo ' geosvg=\'';
echo $aPlace['assvg'];
echo '\'';
}
if (isset($aPlace['astext']))
{
echo ' geotext=\'';
echo $aPlace['astext'];
echo '\'';
}
echo ">".htmlspecialchars($aPlace['langaddress'])."</result>";
if (isset($aPlace['aAddress']))
{
echo "<addressparts>";
foreach($aPlace['aAddress'] as $sKey => $sValue)
{
$sKey = str_replace(' ','_',$sKey);
echo "<$sKey>";
echo htmlspecialchars($sValue);
echo "</$sKey>";
}
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>";
}
if (isset($aPlace['askml']))
{
echo "\n<geokml>";
echo $aPlace['askml'];
echo "</geokml>";
}
}
echo "</reversegeocode>";

View File

@@ -1,180 +1,122 @@
<?php
header("content-type: text/html; charset=UTF-8");
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 osmMapUrl($aFeature)
{
if (isset($sFeature['error_x']) && isset($sFeature['error_y']))
{
$sBaseUrl = '//www.openstreetmap.org/';
$sOSMType = formatOSMType($aFeature['osm_type'], false);
if ($sOSMType)
{
$sBaseUrl += $sOSMType.'/'.$aFeature['osm_id'];
}
return '<a href="'.$sBaseUrl.'?mlat='.$aFeature['error_y'].'&mlon='.$aFeature['error_x'].'">view on osm.org</a>';
}
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 = formatOSMType($aFeature['osm_type'], false);
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 "//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>
<div>
OSM: <span class="label"><?php echo osmLink($aPointDetails); ?><span>
</div>
<h4>Error</h4>
<p>
<?php echo $aPointDetails['errormessage']?$aPointDetails['errormessage']:'unknown'; ?>
</p>
<?php echo osmMapUrl($aPointDetails); ?>
<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,226 +1,258 @@
<?php
header("content-type: text/html; charset=UTF-8");
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>
<?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" />
<script src="js/OpenLayers.js" type="text/javascript"></script>
<script src="js/tiles.js" type="text/javascript"></script>
<script type="text/javascript">
</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']))
{
$iPrevRank = $aAddressLine['rank_address'];
$sPrevLocalName = $aAddressLine['localname'];
}
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";
}
echo "</div>\n";
function headline3($sTitle)
{
echo "<tr class='all-columns'><td colspan='6'><h3>".$sTitle."</h3></td></tr>\n";
}
if ($aLinkedLines)
{
echo "<h2>Linked Places</h2>\n";
echo '<div class="linked">';
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";
}
echo "</div>\n";
}
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>';
}
}
if ($aPlaceSearchNameKeywords)
{
echo '<h2>Name Keywords</h2>';
foreach($aPlaceSearchNameKeywords as $aRow)
{
echo '<div>'.$aRow['word_token']."</div>\n";
}
}
function kv($sKey,$sValue)
{
echo ' <tr><td>' . $sKey . '</td><td>'.$sValue.'</td></tr>'. "\n";
}
if ($aPlaceSearchAddressKeywords)
{
echo '<h2>Address Keywords</h2>';
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";
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;
}
$aGroupedAddressLines = array();
foreach($aParentOfLines as $aAddressLine)
{
if (!isset($aGroupedAddressLines[$aAddressLine['type']])) $aGroupedAddressLines[$aAddressLine['type']] = array();
$aGroupedAddressLines[$aAddressLine['type']][] = $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";
}
}
if (sizeof($aParentOfLines) >= 500) {
echo '<p>There are more child objects which are not shown.</p>';
}
echo '</div>';
}
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>' . osmLink($aAddressLine) . "</td>\n";
echo ' <td>' . (isset($aAddressLine['admin_level']) ? $aAddressLine['admin_level'] : '') . "</td>\n";
echo ' <td>' . format_distance($aAddressLine['distance'])."</td>\n";
echo ' <td>' . detailsLink($aAddressLine,'details &gt;') . "</td>\n";
echo "</tr>\n";
}
function _one_keyword_row($keyword_token,$word_id){
echo "<tr>\n";
echo '<td>';
// mark partial tokens (those starting with a space) with a star for readability
echo ($keyword_token[0]==' '?'*':'');
echo $keyword_token;
if (isset($word_id))
{
echo '</td><td>word id: '.$word_id;
}
echo "</td></tr>\n";
}
// echo '<h2>Other Parts:</h2>';
// echo '<h2>Linked To:</h2>';
?>
</body>
<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' , osmLink($aPointDetails) );
if ($aPointDetails['wikipedia'])
{
kv('Wikipedia Calculated' , wikipediaLink($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>Distance</td>
<td></td>
</tr>
</thead>
<tbody>
<?php
foreach($aAddressLines as $aAddressLine)
{
_one_row($aAddressLine);
}
?>
<?php
if ($aLinkedLines)
{
headline('Linked Places');
foreach($aLinkedLines as $aAddressLine)
{
_one_row($aAddressLine);
}
}
if ($aPlaceSearchNameKeywords)
{
headline('Name Keywords');
foreach($aPlaceSearchNameKeywords as $aRow)
{
_one_keyword_row($aRow['word_token'], $aRow['word_id']);
}
}
if ($aPlaceSearchAddressKeywords)
{
headline('Address Keywords');
foreach($aPlaceSearchAddressKeywords as $aRow)
{
_one_keyword_row($aRow['word_token'], $aRow['word_id']);
}
}
if (sizeof($aParentOfLines))
{
headline('Parent Of');
$aGroupedAddressLines = array();
foreach($aParentOfLines as $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);
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 "</table>\n";
?>
</div>
</div>
</div>
<script type="text/javascript">
<?php
$aNominatimMapInit = array(
'tile_url' => $sTileURL,
'tile_attribution' => $sTileAttribution
);
echo 'var nominatim_map_init = ' . json_encode($aNominatimMapInit, JSON_PRETTY_PRINT) . ';';
$aPlace = array(
'asgeojson' => $aPointDetails['asgeojson'],
'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,13 @@
<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/nominatim-ui.js"></script>

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,24 @@
<p>
Before reporting problems please read the <a target="_blank" href="http://wiki.openstreetmap.org/wiki/Nominatim">user documentation</a>
and
<a target="_blank" href="http://wiki.openstreetmap.org/wiki/Nominatim/FAQ">FAQ</a>.
If your problem relates to the address of a particular search result please use the 'details' link
to check how the address was generated before reporting a problem.
</p>
<p>
Use <a target="_blank" href="https://github.com/openstreetmap/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,88 +1,88 @@
<?php
$aOutput = array();
$aOutput['licence'] = "Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright";
$aOutput['batch'] = array();
$aOutput = array();
$aOutput['licence'] = "Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright";
$aOutput['batch'] = array();
foreach($aBatchResults as $aSearchResults)
{
if (!$aSearchResults) $aSearchResults = array();
$aFilteredPlaces = array();
foreach($aSearchResults as $iResNum => $aPointDetails)
{
$aPlace = array(
'place_id'=>$aPointDetails['place_id'],
);
foreach($aBatchResults as $aSearchResults)
{
if (!$aSearchResults) $aSearchResults = array();
$aFilteredPlaces = array();
foreach($aSearchResults as $iResNum => $aPointDetails)
{
$aPlace = array(
'place_id'=>$aPointDetails['place_id'],
);
$sOSMType = ($aPointDetails['osm_type'] == 'N'?'node':($aPointDetails['osm_type'] == 'W'?'way':($aPointDetails['osm_type'] == 'R'?'relation':'')));
if ($sOSMType)
{
$aPlace['osm_type'] = $sOSMType;
$aPlace['osm_id'] = $aPointDetails['osm_id'];
}
$sOSMType = formatOSMType($aPointDetails['osm_type']);
if ($sOSMType)
{
$aPlace['osm_type'] = $sOSMType;
$aPlace['osm_id'] = $aPointDetails['osm_id'];
}
if (isset($aPointDetails['aBoundingBox']))
{
$aPlace['boundingbox'] = array(
$aPointDetails['aBoundingBox'][0],
$aPointDetails['aBoundingBox'][1],
$aPointDetails['aBoundingBox'][2],
$aPointDetails['aBoundingBox'][3]);
if (isset($aPointDetails['aBoundingBox']))
{
$aPlace['boundingbox'] = array(
$aPointDetails['aBoundingBox'][0],
$aPointDetails['aBoundingBox'][1],
$aPointDetails['aBoundingBox'][2],
$aPointDetails['aBoundingBox'][3]);
if (isset($aPointDetails['aPolyPoints']) && $bShowPolygons)
{
$aPlace['polygonpoints'] = $aPointDetails['aPolyPoints'];
}
}
if (isset($aPointDetails['aPolyPoints']) && $bShowPolygons)
{
$aPlace['polygonpoints'] = $aPointDetails['aPolyPoints'];
}
}
if (isset($aPointDetails['zoom']))
{
$aPlace['zoom'] = $aPointDetails['zoom'];
}
if (isset($aPointDetails['zoom']))
{
$aPlace['zoom'] = $aPointDetails['zoom'];
}
$aPlace['lat'] = $aPointDetails['lat'];
$aPlace['lon'] = $aPointDetails['lon'];
$aPlace['display_name'] = $aPointDetails['name'];
$aPlace['place_rank'] = $aPointDetails['rank_search'];
$aPlace['lat'] = $aPointDetails['lat'];
$aPlace['lon'] = $aPointDetails['lon'];
$aPlace['display_name'] = $aPointDetails['name'];
$aPlace['place_rank'] = $aPointDetails['rank_search'];
$aPlace['category'] = $aPointDetails['class'];
$aPlace['type'] = $aPointDetails['type'];
$aPlace['category'] = $aPointDetails['class'];
$aPlace['type'] = $aPointDetails['type'];
$aPlace['importance'] = $aPointDetails['importance'];
$aPlace['importance'] = $aPointDetails['importance'];
if (isset($aPointDetails['icon']))
{
$aPlace['icon'] = $aPointDetails['icon'];
}
if (isset($aPointDetails['icon']))
{
$aPlace['icon'] = $aPointDetails['icon'];
}
if (isset($aPointDetails['address']) && sizeof($aPointDetails['address'])>0)
{
$aPlace['address'] = $aPointDetails['address'];
}
if (isset($aPointDetails['address']) && sizeof($aPointDetails['address'])>0)
{
$aPlace['address'] = $aPointDetails['address'];
}
if (isset($aPointDetails['asgeojson']))
{
$aPlace['geojson'] = json_decode($aPointDetails['asgeojson']);
}
if (isset($aPointDetails['asgeojson']))
{
$aPlace['geojson'] = json_decode($aPointDetails['asgeojson']);
}
if (isset($aPointDetails['assvg']))
{
$aPlace['svg'] = $aPointDetails['assvg'];
}
if (isset($aPointDetails['assvg']))
{
$aPlace['svg'] = $aPointDetails['assvg'];
}
if (isset($aPointDetails['astext']))
{
$aPlace['geotext'] = $aPointDetails['astext'];
}
if (isset($aPointDetails['astext']))
{
$aPlace['geotext'] = $aPointDetails['astext'];
}
if (isset($aPointDetails['askml']))
{
$aPlace['geokml'] = $aPointDetails['askml'];
}
if (isset($aPointDetails['askml']))
{
$aPlace['geokml'] = $aPointDetails['askml'];
}
$aFilteredPlaces[] = $aPlace;
}
$aOutput['batch'][] = $aFilteredPlaces;
}
$aFilteredPlaces[] = $aPlace;
}
$aOutput['batch'][] = $aFilteredPlaces;
}
javascript_renderData($aOutput, array('geojson'));
javascript_renderData($aOutput, array('geojson'));

View File

@@ -1,298 +1,114 @@
<?php
header("content-type: text/html; charset=UTF-8");
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" />
<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>
<?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 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>
<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 class="form-group search-button-group">
<button type="submit" class="btn btn-primary btn-sm">Search</button>
<?php if (CONST_Search_AreaPolygons) { ?>
<input type="hidden" value="1" name="polygon_geojson" />
<?php } ?>
<input type="hidden" name="viewbox" value="<?php if (isset($aMoreParams['viewbox'])) echo ($aMoreParams['viewbox']); ?>" />
<div class="checkbox-inline">
<input type="checkbox" id="use_viewbox" <?php if (isset($aMoreParams['viewbox'])) echo "checked='checked'"; ?>>
<label for="use_viewbox">apply viewbox</label>
</div>
</div>
<div class="search-type-link">
<a id="switch-to-reverse" href="<?php echo CONST_Website_BaseURL; ?>reverse.php?format=html">reverse search</a>
</div>
</form>
<?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'].');">';
}
<div id="content">
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>';
}
<?php if ($sQuery) { ?>
?>
<div class="disclaimer">Addresses and postcodes are approximate
<input type="button" value="Report Problem" onclick="$('report').style.visibility=($('report').style.visibility=='hidden'?'visible':'hidden')"/>
</div>
</div>
<?php
}
?>
<div id="searchresults" class="sidebar">
<?php
$i = 0;
foreach($aSearchResults as $iResNum => $aResult)
{
<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>
echo '<div class="result" data-position=' . $i . '>';
<!--
<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>
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>
<?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 id="map-position-inner"></div>
<div id="map-position-close"><a href="#">hide</a></div>
</div>
<div id="map"></div>
</div>
</div> <!-- /content -->
<script type="text/javascript">
<?php
$aNominatimMapInit = array(
'zoom' => CONST_Default_Zoom,
'lat' => CONST_Default_Lat,
'lon' => CONST_Default_Lon,
'tile_url' => CONST_Map_Tile_URL,
'tile_attribution' => CONST_Map_Tile_Attribution
);
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'); ?>
<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>
</html>

View File

@@ -1,80 +1,79 @@
<?php
header("content-type: application/json; charset=UTF-8");
header("content-type: application/json; charset=UTF-8");
$aFilteredPlaces = array();
foreach($aSearchResults as $iResNum => $aPointDetails)
{
$aPlace = array(
'place_id'=>$aPointDetails['place_id'],
'licence'=>"Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright",
);
$aFilteredPlaces = array();
foreach($aSearchResults as $iResNum => $aPointDetails)
{
$aPlace = array(
'place_id'=>$aPointDetails['place_id'],
'licence'=>"Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright",
);
$sOSMType = formatOSMType($aPointDetails['osm_type']);
if ($sOSMType)
{
$aPlace['osm_type'] = $sOSMType;
$aPlace['osm_id'] = $aPointDetails['osm_id'];
}
$sOSMType = ($aPointDetails['osm_type'] == 'N'?'node':($aPointDetails['osm_type'] == 'W'?'way':($aPointDetails['osm_type'] == 'R'?'relation':'')));
if ($sOSMType)
{
$aPlace['osm_type'] = $sOSMType;
$aPlace['osm_id'] = $aPointDetails['osm_id'];
}
if (isset($aPointDetails['aBoundingBox']))
{
$aPlace['boundingbox'] = $aPointDetails['aBoundingBox'];
if (isset($aPointDetails['aBoundingBox']))
{
$aPlace['boundingbox'] = array(
$aPointDetails['aBoundingBox'][0],
$aPointDetails['aBoundingBox'][1],
$aPointDetails['aBoundingBox'][2],
$aPointDetails['aBoundingBox'][3]);
if (isset($aPointDetails['aPolyPoints']))
{
$aPlace['polygonpoints'] = $aPointDetails['aPolyPoints'];
}
}
if (isset($aPointDetails['aPolyPoints']) && $bShowPolygons)
{
$aPlace['polygonpoints'] = $aPointDetails['aPolyPoints'];
}
}
if (isset($aPointDetails['zoom']))
{
$aPlace['zoom'] = $aPointDetails['zoom'];
}
if (isset($aPointDetails['zoom']))
{
$aPlace['zoom'] = $aPointDetails['zoom'];
}
$aPlace['lat'] = $aPointDetails['lat'];
$aPlace['lon'] = $aPointDetails['lon'];
$aPlace['display_name'] = $aPointDetails['name'];
$aPlace['lat'] = $aPointDetails['lat'];
$aPlace['lon'] = $aPointDetails['lon'];
$aPlace['display_name'] = $aPointDetails['name'];
$aPlace['class'] = $aPointDetails['class'];
$aPlace['type'] = $aPointDetails['type'];
$aPlace['class'] = $aPointDetails['class'];
$aPlace['type'] = $aPointDetails['type'];
$aPlace['importance'] = $aPointDetails['importance'];
$aPlace['importance'] = $aPointDetails['importance'];
if (isset($aPointDetails['icon']) && $aPointDetails['icon'])
{
$aPlace['icon'] = $aPointDetails['icon'];
}
if (isset($aPointDetails['icon']) && $aPointDetails['icon'])
{
$aPlace['icon'] = $aPointDetails['icon'];
}
if (isset($aPointDetails['address']))
{
$aPlace['address'] = $aPointDetails['address'];
}
if (isset($aPointDetails['address']))
{
$aPlace['address'] = $aPointDetails['address'];
}
if (isset($aPointDetails['asgeojson']))
{
$aPlace['geojson'] = json_decode($aPointDetails['asgeojson']);
}
if (isset($aPointDetails['asgeojson']))
{
$aPlace['geojson'] = json_decode($aPointDetails['asgeojson']);
}
if (isset($aPointDetails['assvg']))
{
$aPlace['svg'] = $aPointDetails['assvg'];
}
if (isset($aPointDetails['assvg']))
{
$aPlace['svg'] = $aPointDetails['assvg'];
}
if (isset($aPointDetails['astext']))
{
$aPlace['geotext'] = $aPointDetails['astext'];
}
if (isset($aPointDetails['astext']))
{
$aPlace['geotext'] = $aPointDetails['astext'];
}
if (isset($aPointDetails['askml']))
{
$aPlace['geokml'] = $aPointDetails['askml'];
}
if (isset($aPointDetails['askml']))
{
$aPlace['geokml'] = $aPointDetails['askml'];
}
if (isset($aPointDetails['sExtraTags'])) $aPlace['extratags'] = $aPointDetails['sExtraTags'];
if (isset($aPointDetails['sNameDetails'])) $aPlace['namedetails'] = $aPointDetails['sNameDetails'];
$aFilteredPlaces[] = $aPlace;
}
$aFilteredPlaces[] = $aPlace;
}
javascript_renderData($aFilteredPlaces);
javascript_renderData($aFilteredPlaces);

View File

@@ -1,79 +1,79 @@
<?php
$aFilteredPlaces = array();
foreach($aSearchResults as $iResNum => $aPointDetails)
{
$aPlace = array(
'place_id'=>$aPointDetails['place_id'],
'licence'=>"Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright",
);
$sOSMType = ($aPointDetails['osm_type'] == 'N'?'node':($aPointDetails['osm_type'] == 'W'?'way':($aPointDetails['osm_type'] == 'R'?'relation':'')));
if ($sOSMType)
{
$aPlace['osm_type'] = $sOSMType;
$aPlace['osm_id'] = $aPointDetails['osm_id'];
}
$aFilteredPlaces = array();
foreach($aSearchResults as $iResNum => $aPointDetails)
{
$aPlace = array(
'place_id'=>$aPointDetails['place_id'],
'licence'=>"Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright",
);
if (isset($aPointDetails['aBoundingBox']))
{
$aPlace['boundingbox'] = array(
$aPointDetails['aBoundingBox'][0],
$aPointDetails['aBoundingBox'][1],
$aPointDetails['aBoundingBox'][2],
$aPointDetails['aBoundingBox'][3]);
$sOSMType = formatOSMType($aPointDetails['osm_type']);
if ($sOSMType)
{
$aPlace['osm_type'] = $sOSMType;
$aPlace['osm_id'] = $aPointDetails['osm_id'];
}
if (isset($aPointDetails['aPolyPoints']) && $bShowPolygons)
{
$aPlace['polygonpoints'] = $aPointDetails['aPolyPoints'];
}
}
if (isset($aPointDetails['aBoundingBox']))
{
$aPlace['boundingbox'] = $aPointDetails['aBoundingBox'];
if (isset($aPointDetails['zoom']))
{
$aPlace['zoom'] = $aPointDetails['zoom'];
}
if (isset($aPointDetails['aPolyPoints']))
{
$aPlace['polygonpoints'] = $aPointDetails['aPolyPoints'];
}
}
$aPlace['lat'] = $aPointDetails['lat'];
$aPlace['lon'] = $aPointDetails['lon'];
$aPlace['display_name'] = $aPointDetails['name'];
$aPlace['place_rank'] = $aPointDetails['rank_search'];
if (isset($aPointDetails['zoom']))
{
$aPlace['zoom'] = $aPointDetails['zoom'];
}
$aPlace['category'] = $aPointDetails['class'];
$aPlace['type'] = $aPointDetails['type'];
$aPlace['lat'] = $aPointDetails['lat'];
$aPlace['lon'] = $aPointDetails['lon'];
$aPlace['display_name'] = $aPointDetails['name'];
$aPlace['place_rank'] = $aPointDetails['rank_search'];
$aPlace['importance'] = $aPointDetails['importance'];
$aPlace['category'] = $aPointDetails['class'];
$aPlace['type'] = $aPointDetails['type'];
if (isset($aPointDetails['icon']))
{
$aPlace['icon'] = $aPointDetails['icon'];
}
$aPlace['importance'] = $aPointDetails['importance'];
if (isset($aPointDetails['address']) && sizeof($aPointDetails['address'])>0)
{
$aPlace['address'] = $aPointDetails['address'];
}
if (isset($aPointDetails['icon']))
{
$aPlace['icon'] = $aPointDetails['icon'];
}
if (isset($aPointDetails['asgeojson']))
{
$aPlace['geojson'] = json_decode($aPointDetails['asgeojson']);
}
if (isset($aPointDetails['address']) && sizeof($aPointDetails['address'])>0)
{
$aPlace['address'] = $aPointDetails['address'];
}
if (isset($aPointDetails['assvg']))
{
$aPlace['svg'] = $aPointDetails['assvg'];
}
if (isset($aPointDetails['asgeojson']))
{
$aPlace['geojson'] = json_decode($aPointDetails['asgeojson']);
}
if (isset($aPointDetails['astext']))
{
$aPlace['geotext'] = $aPointDetails['astext'];
}
if (isset($aPointDetails['assvg']))
{
$aPlace['svg'] = $aPointDetails['assvg'];
}
if (isset($aPointDetails['askml']))
{
$aPlace['geokml'] = $aPointDetails['askml'];
}
if (isset($aPointDetails['astext']))
{
$aPlace['geotext'] = $aPointDetails['astext'];
}
$aFilteredPlaces[] = $aPlace;
}
if (isset($aPointDetails['askml']))
{
$aPlace['geokml'] = $aPointDetails['askml'];
}
javascript_renderData($aFilteredPlaces, array('geojson'));
if (isset($aPointDetails['sExtraTags'])) $aPlace['extratags'] = $aPointDetails['sExtraTags'];
if (isset($aPointDetails['sNameDetails'])) $aPlace['namedetails'] = $aPointDetails['sNameDetails'];
$aFilteredPlaces[] = $aPlace;
}
javascript_renderData($aFilteredPlaces);

View File

@@ -1,124 +1,158 @@
<?php
header("content-type: text/xml; charset=UTF-8");
header("content-type: text/xml; charset=UTF-8");
echo "<";
echo "?xml version=\"1.0\" encoding=\"UTF-8\" ?";
echo ">\n";
echo "<";
echo "?xml version=\"1.0\" encoding=\"UTF-8\" ?";
echo ">\n";
echo "<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)."'";
if ($sViewBox) echo " viewbox='".htmlspecialchars($sViewBox, ENT_QUOTES)."'";
echo " polygon='".($bShowPolygons?'true':'false')."'";
if (sizeof($aExcludePlaceIDs))
{
echo " exclude_place_ids='".htmlspecialchars(join(',',$aExcludePlaceIDs))."'";
}
if ($sMoreURL)
{
echo " more_url='".htmlspecialchars($sMoreURL)."'";
}
echo ">\n";
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)."'";
if (isset($aMoreParams['viewbox'])) echo " viewbox='".htmlspecialchars($aMoreParams['viewbox'], ENT_QUOTES)."'";
echo " polygon='".(isset($aMoreParams['polygon'])?'true':'false')."'";
if (isset($aMoreParams['exclude_place_ids']))
{
echo " exclude_place_ids='".htmlspecialchars($aMoreParams['exclude_place_ids'])."'";
}
echo " more_url='".htmlspecialchars($sMoreURL)."'";
echo ">\n";
foreach($aSearchResults as $iResNum => $aResult)
{
echo "<place place_id='".$aResult['place_id']."'";
$sOSMType = ($aResult['osm_type'] == 'N'?'node':($aResult['osm_type'] == 'W'?'way':($aResult['osm_type'] == 'R'?'relation':'')));
if ($sOSMType)
{
echo " osm_type='$sOSMType'";
echo " osm_id='".$aResult['osm_id']."'";
}
echo " place_rank='".$aResult['rank_search']."'";
foreach($aSearchResults as $iResNum => $aResult)
{
echo "<place place_id='".$aResult['place_id']."'";
$sOSMType = formatOSMType($aResult['osm_type']);
if ($sOSMType)
{
echo " osm_type='$sOSMType'";
echo " osm_id='".$aResult['osm_id']."'";
}
echo " place_rank='".$aResult['rank_search']."'";
if (isset($aResult['aBoundingBox']))
{
echo ' boundingbox="';
echo $aResult['aBoundingBox'][0];
echo ','.$aResult['aBoundingBox'][1];
echo ','.$aResult['aBoundingBox'][2];
echo ','.$aResult['aBoundingBox'][3];
echo '"';
if (isset($aResult['aBoundingBox']))
{
echo ' boundingbox="';
echo join(',',$aResult['aBoundingBox']);
echo '"';
if ($bShowPolygons && isset($aResult['aPolyPoints']))
{
echo ' polygonpoints=\'';
echo json_encode($aResult['aPolyPoints']);
echo '\'';
}
}
if (isset($aResult['aPolyPoints']))
{
echo ' polygonpoints=\'';
echo json_encode($aResult['aPolyPoints']);
echo '\'';
}
}
if (isset($aResult['asgeojson']))
{
echo ' geojson=\'';
echo $aResult['asgeojson'];
echo '\'';
}
if (isset($aResult['asgeojson']))
{
echo ' geojson=\'';
echo $aResult['asgeojson'];
echo '\'';
}
if (isset($aResult['assvg']))
{
echo ' geosvg=\'';
echo $aResult['assvg'];
echo '\'';
}
if (isset($aResult['assvg']))
{
echo ' geosvg=\'';
echo $aResult['assvg'];
echo '\'';
}
if (isset($aResult['astext']))
{
echo ' geotext=\'';
echo $aResult['astext'];
echo '\'';
}
if (isset($aResult['astext']))
{
echo ' geotext=\'';
echo $aResult['astext'];
echo '\'';
}
if (isset($aResult['zoom']))
{
echo " zoom='".$aResult['zoom']."'";
}
if (isset($aResult['zoom']))
{
echo " zoom='".$aResult['zoom']."'";
}
echo " lat='".$aResult['lat']."'";
echo " lon='".$aResult['lon']."'";
echo " display_name='".htmlspecialchars($aResult['name'], ENT_QUOTES)."'";
echo " lat='".$aResult['lat']."'";
echo " lon='".$aResult['lon']."'";
echo " display_name='".htmlspecialchars($aResult['name'], ENT_QUOTES)."'";
echo " class='".htmlspecialchars($aResult['class'])."'";
echo " type='".htmlspecialchars($aResult['type'], ENT_QUOTES)."'";
echo " importance='".htmlspecialchars($aResult['importance'])."'";
if (isset($aResult['icon']) && $aResult['icon'])
{
echo " icon='".htmlspecialchars($aResult['icon'], ENT_QUOTES)."'";
}
echo " class='".htmlspecialchars($aResult['class'])."'";
echo " type='".htmlspecialchars($aResult['type'], ENT_QUOTES)."'";
echo " importance='".htmlspecialchars($aResult['importance'])."'";
if (isset($aResult['icon']) && $aResult['icon'])
{
echo " icon='".htmlspecialchars($aResult['icon'], ENT_QUOTES)."'";
}
if (isset($aResult['address']) || isset($aResult['askml']))
{
echo ">";
}
$bHasDelim = false;
if (isset($aResult['askml']))
{
echo "\n<geokml>";
echo $aResult['askml'];
echo "</geokml>";
}
if (isset($aResult['askml']))
{
if (!$bHasDelim)
{
$bHasDelim = true;
echo ">";
}
echo "\n<geokml>";
echo $aResult['askml'];
echo "</geokml>";
}
if (isset($aResult['address']))
{
echo "\n";
foreach($aResult['address'] as $sKey => $sValue)
{
$sKey = str_replace(' ','_',$sKey);
echo "<$sKey>";
echo htmlspecialchars($sValue);
echo "</$sKey>";
}
}
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['address']) || isset($aResult['askml']))
{
echo "</place>";
}
else
{
echo "/>";
}
}
echo "</searchresults>";
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)
{
$sKey = str_replace(' ','_',$sKey);
echo "<$sKey>";
echo htmlspecialchars($sValue);
echo "</$sKey>";
}
}
if ($bHasDelim)
{
echo "</place>";
}
else
{
echo "/>";
}
}
echo "</" . (isset($sXmlRootTag)?$sXmlRootTag:'searchresults') . ">";

10
module/CMakeLists.txt Normal file
View File

@@ -0,0 +1,10 @@
# just use the pgxs makefile
ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/dummy
COMMAND PGXS=${PGXS} PG_CONFIG=${PG_CONFIG} MODSRCDIR=${CMAKE_CURRENT_SOURCE_DIR} $(MAKE) -f ${CMAKE_CURRENT_SOURCE_DIR}/Makefile
COMMENT "Running external makefile ${PGXS}"
)
ADD_CUSTOM_TARGET( nominatim_lib ALL
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/dummy
)

View File

@@ -1,8 +1,9 @@
MODULES = nominatim
PGXS := @POSTGRESQL_PGXS@
PG_CONFIG := @PG_CONFIG@
PG_CPPFLAGS = -I$(MODSRCDIR)
include $(PGXS)
VPATH = $(MODSRCDIR)
all:
chmod 755 nominatim.so

File diff suppressed because one or more lines are too long

12
nominatim/CMakeLists.txt Normal file
View File

@@ -0,0 +1,12 @@
add_executable(nominatim export.c geometry.cpp import.c index.c input.c nominatim.c postgresql.c sprompt.c)
include(CheckIncludeFile)
CHECK_INCLUDE_FILE(byteswap.h HAVE_BYTESWAP_H)
CHECK_INCLUDE_FILE(sys/endian.h HAVE_SYS_ENDIAN_H)
if(HAVE_BYTESWAP_H)
target_compile_definitions(nominatim PRIVATE HAVE_BYTESWAP_H)
endif(HAVE_BYTESWAP_H)
if(HAVE_SYS_ENDIAN_H)
target_compile_definitions(nominatim PRIVATE HAVE_SYS_ENDIAN_H)
endif(HAVE_SYS_ENDIAN_H)
target_link_libraries(nominatim ${LIBXML2_LIBRARIES} ${ZLIB_LIBRARIES} ${BZIP2_LIBRARIES} ${PostgreSQL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})

View File

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

@@ -486,7 +486,7 @@ void EndElement(xmlTextReaderPtr reader, const xmlChar *name)
}
paramValues[7] = (const char *)featureExtraTagString;
if (strlen(feature.parentPlaceID) == 0)
if (xmlStrlen(feature.parentPlaceID) == 0)
paramValues[8] = "0";
else
paramValues[8] = (const char *)feature.parentPlaceID;
@@ -541,10 +541,10 @@ void EndElement(xmlTextReaderPtr reader, const xmlChar *name)
if (featureNameLines)
{
if (strlen(feature.parentPlaceID) > 0 && featureAddressLines == 0)
if (xmlStrlen(feature.parentPlaceID) > 0 && featureAddressLines == 0)
{
paramValues[0] = (const char *)place_id;
paramValues[1] = feature.parentPlaceID;
paramValues[1] = (const char *)feature.parentPlaceID;
if (verbose) fprintf(stderr, "search_name_from_parent_insert: INSERT %s %s\n", paramValues[0], paramValues[1]);
res = PQexecPrepared(conn, "search_name_from_parent_insert", 2, paramValues, NULL, NULL, 0);
if (PQresultStatus(res) != PGRES_COMMAND_OK)

View File

@@ -1,4 +1,6 @@
/*
* triggers indexing (reparenting etc.) through setting resetting indexed_status: update placex/osmline set indexed_status = 0 where indexed_status > 0
* triggers placex_update and osmline_update
*/
#include <stdio.h>
@@ -19,34 +21,255 @@
extern int verbose;
void nominatim_index(int rank_min, int rank_max, int num_threads, const char *conninfo, const char *structuredoutputfile)
void run_indexing(int rank, int interpolation, PGconn *conn, int num_threads,
struct index_thread_data * thread_data, const char *structuredoutputfile)
{
struct index_thread_data * thread_data;
pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;
int tuples, count, sleepcount;
pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;
time_t rankStartTime;
int rankTotalTuples;
int rankCountTuples;
float rankPerSecond;
PGconn *conn;
PGresult * res;
PGresult * resSectors;
PGresult * resPlaces;
PGresult * resNULL;
int rank;
int i;
int iSector;
int iResult;
const char *paramValues[2];
int paramLengths[2];
int paramFormats[2];
uint32_t paramRank;
uint32_t paramSector;
uint32_t sector;
xmlTextWriterPtr writer;
pthread_mutex_t writer_mutex = PTHREAD_MUTEX_INITIALIZER;
// Create the output file
writer = NULL;
if (structuredoutputfile)
{
writer = nominatim_exportXMLStart(structuredoutputfile);
}
if (interpolation)
{
fprintf(stderr, "Starting interpolation lines (location_property_osmline)\n");
}
else
{
fprintf(stderr, "Starting rank %d\n", rank);
}
rankCountTuples = 0;
rankPerSecond = 0;
paramRank = PGint32(rank);
paramValues[0] = (char *)&paramRank;
paramLengths[0] = sizeof(paramRank);
paramFormats[0] = 1;
if (interpolation)
{
resSectors = PQexecPrepared(conn, "index_sectors_osmline", 0, NULL, 0, NULL, 1);
}
else
{
resSectors = PQexecPrepared(conn, "index_sectors", 1, paramValues, paramLengths, paramFormats, 1);
}
if (PQresultStatus(resSectors) != PGRES_TUPLES_OK)
{
fprintf(stderr, "index_sectors: SELECT failed: %s", PQerrorMessage(conn));
PQclear(resSectors);
exit(EXIT_FAILURE);
}
if (PQftype(resSectors, 0) != PG_OID_INT4)
{
fprintf(stderr, "Sector value has unexpected type\n");
PQclear(resSectors);
exit(EXIT_FAILURE);
}
if (PQftype(resSectors, 1) != PG_OID_INT8)
{
fprintf(stderr, "Sector value has unexpected type\n");
PQclear(resSectors);
exit(EXIT_FAILURE);
}
rankTotalTuples = 0;
for (iSector = 0; iSector < PQntuples(resSectors); iSector++)
{
rankTotalTuples += PGint64(*((uint64_t *)PQgetvalue(resSectors, iSector, 1)));
}
rankStartTime = time(0);
for (iSector = 0; iSector <= PQntuples(resSectors); iSector++)
{
if (iSector > 0)
{
resPlaces = PQgetResult(conn);
if (PQresultStatus(resPlaces) != PGRES_TUPLES_OK)
{
fprintf(stderr, "index_sector_places: SELECT failed: %s", PQerrorMessage(conn));
PQclear(resPlaces);
exit(EXIT_FAILURE);
}
if (PQftype(resPlaces, 0) != PG_OID_INT8)
{
fprintf(stderr, "Place_id value has unexpected type\n");
PQclear(resPlaces);
exit(EXIT_FAILURE);
}
resNULL = PQgetResult(conn);
if (resNULL != NULL)
{
fprintf(stderr, "Unexpected non-null response\n");
exit(EXIT_FAILURE);
}
}
if (iSector < PQntuples(resSectors))
{
sector = PGint32(*((uint32_t *)PQgetvalue(resSectors, iSector, 0)));
// fprintf(stderr, "\n Starting sector %d size %ld\n", sector, PGint64(*((uint64_t *)PQgetvalue(resSectors, iSector, 1))));
// Get all the place_id's for this sector
paramRank = PGint32(rank);
paramSector = PGint32(sector);
if (rankTotalTuples-rankCountTuples < num_threads*1000)
{
// no sectors
if (interpolation)
{
iResult = PQsendQueryPrepared(conn, "index_nosector_places_osmline", 0, NULL, 0, NULL, 1);
}
else
{
paramValues[0] = (char *)&paramRank;
paramLengths[0] = sizeof(paramRank);
paramFormats[0] = 1;
iResult = PQsendQueryPrepared(conn, "index_nosector_places", 1, paramValues, paramLengths, paramFormats, 1);
}
}
else
{
if (interpolation)
{
iResult = PQsendQueryPrepared(conn, "index_sector_places_osmline", 1, paramValues, paramLengths, paramFormats, 1);
paramValues[0] = (char *)&paramSector;
paramLengths[0] = sizeof(paramSector);
paramFormats[0] = 1;
}
else
{
paramValues[0] = (char *)&paramRank;
paramLengths[0] = sizeof(paramRank);
paramFormats[0] = 1;
paramValues[1] = (char *)&paramSector;
paramLengths[1] = sizeof(paramSector);
paramFormats[1] = 1;
iResult = PQsendQueryPrepared(conn, "index_sector_places", 2, paramValues, paramLengths, paramFormats, 1);
}
}
if (!iResult)
{
fprintf(stderr, "index_sector_places: SELECT failed: %s", PQerrorMessage(conn));
PQclear(resPlaces);
exit(EXIT_FAILURE);
}
}
if (iSector > 0)
{
count = 0;
rankPerSecond = 0;
tuples = PQntuples(resPlaces);
if (tuples > 0)
{
// Spawn threads
for (i = 0; i < num_threads; i++)
{
thread_data[i].res = resPlaces;
thread_data[i].tuples = tuples;
thread_data[i].count = &count;
thread_data[i].count_mutex = &count_mutex;
thread_data[i].writer = writer;
thread_data[i].writer_mutex = &writer_mutex;
if (interpolation)
{
thread_data[i].table = 0; // use interpolations table
}
else
{
thread_data[i].table = 1; // use placex table
}
pthread_create(&thread_data[i].thread, NULL, &nominatim_indexThread, (void *)&thread_data[i]);
}
// Monitor threads to give user feedback
sleepcount = 0;
while (count < tuples)
{
usleep(1000);
// Aim for one update per second
if (sleepcount++ > 500)
{
rankPerSecond = ((float)rankCountTuples + (float)count) / MAX(difftime(time(0), rankStartTime),1);
if(interpolation)
{
fprintf(stderr, " Done %i in %i @ %f per second - Interpolation lines ETA (seconds): %f\n", (rankCountTuples + count), (int)(difftime(time(0), rankStartTime)), rankPerSecond, ((float)(rankTotalTuples - (rankCountTuples + count)))/rankPerSecond);
}
else
{
fprintf(stderr, " Done %i in %i @ %f per second - Rank %i ETA (seconds): %f\n", (rankCountTuples + count), (int)(difftime(time(0), rankStartTime)), rankPerSecond, rank, ((float)(rankTotalTuples - (rankCountTuples + count)))/rankPerSecond);
}
sleepcount = 0;
}
}
// Wait for everything to finish
for (i = 0; i < num_threads; i++)
{
pthread_join(thread_data[i].thread, NULL);
}
rankCountTuples += tuples;
}
// Finished sector
rankPerSecond = (float)rankCountTuples / MAX(difftime(time(0), rankStartTime),1);
fprintf(stderr, " Done %i in %i @ %f per second - ETA (seconds): %f\n", rankCountTuples, (int)(difftime(time(0), rankStartTime)), rankPerSecond, ((float)(rankTotalTuples - rankCountTuples))/rankPerSecond);
PQclear(resPlaces);
}
if (rankTotalTuples-rankCountTuples < num_threads*20 && iSector < PQntuples(resSectors))
{
iSector = PQntuples(resSectors) - 1;
}
}
// Finished rank
fprintf(stderr, "\r Done %i in %i @ %f per second - FINISHED\n\n", rankCountTuples, (int)(difftime(time(0), rankStartTime)), rankPerSecond);
PQclear(resSectors);
}
void nominatim_index(int rank_min, int rank_max, int num_threads, const char *conninfo, const char *structuredoutputfile)
{
struct index_thread_data * thread_data;
PGconn *conn;
PGresult * res;
int rank;
int i;
xmlTextWriterPtr writer;
pthread_mutex_t writer_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -70,6 +293,16 @@ void nominatim_index(int rank_min, int rank_max, int num_threads, const char *co
exit(EXIT_FAILURE);
}
PQclear(res);
res = PQprepare(conn, "index_sectors_osmline",
"select geometry_sector,count(*) from location_property_osmline where indexed_status > 0 group by geometry_sector order by geometry_sector",
0, NULL);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "Failed preparing index_sectors: %s\n", PQerrorMessage(conn));
exit(EXIT_FAILURE);
}
PQclear(res);
pg_prepare_params[0] = PG_OID_INT4;
res = PQprepare(conn, "index_nosectors",
@@ -104,7 +337,28 @@ void nominatim_index(int rank_min, int rank_max, int num_threads, const char *co
exit(EXIT_FAILURE);
}
PQclear(res);
pg_prepare_params[0] = PG_OID_INT4;
res = PQprepare(conn, "index_sector_places_osmline",
"select place_id from location_property_osmline where geometry_sector = $1 and indexed_status > 0",
1, pg_prepare_params);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "Failed preparing index_sector_places: %s\n", PQerrorMessage(conn));
exit(EXIT_FAILURE);
}
PQclear(res);
res = PQprepare(conn, "index_nosector_places_osmline",
"select place_id from location_property_osmline where indexed_status > 0 order by geometry_sector",
0, NULL);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "Failed preparing index_nosector_places: %s\n", PQerrorMessage(conn));
exit(EXIT_FAILURE);
}
PQclear(res);
// Build the data for each thread
thread_data = (struct index_thread_data *)malloc(sizeof(struct index_thread_data)*num_threads);
for (i = 0; i < num_threads; i++)
@@ -122,199 +376,53 @@ void nominatim_index(int rank_min, int rank_max, int num_threads, const char *co
1, pg_prepare_params);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "Failed preparing index_placex: %s\n", PQerrorMessage(conn));
fprintf(stderr, "Failed preparing index_placex: %s\n", PQerrorMessage(thread_data[i].conn));
exit(EXIT_FAILURE);
}
PQclear(res);
pg_prepare_params[0] = PG_OID_INT8;
res = PQprepare(thread_data[i].conn, "index_osmline",
"update location_property_osmline set indexed_status = 0 where place_id = $1",
1, pg_prepare_params);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "Failed preparing index_osmline: %s\n", PQerrorMessage(thread_data[i].conn));
exit(EXIT_FAILURE);
}
PQclear(res);
/*res = PQexec(thread_data[i].conn, "set enable_seqscan = false");
// Make sure the error message is not localized as we parse it later.
res = PQexec(thread_data[i].conn, "SET lc_messages TO 'C'");
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "Failed disabling sequential scan: %s\n", PQerrorMessage(conn));
fprintf(stderr, "Failed to set langauge: %s\n", PQerrorMessage(thread_data[i].conn));
exit(EXIT_FAILURE);
}
PQclear(res);*/
PQclear(res);
nominatim_exportCreatePreparedQueries(thread_data[i].conn);
}
// Create the output file
writer = NULL;
if (structuredoutputfile)
{
writer = nominatim_exportXMLStart(structuredoutputfile);
}
fprintf(stderr, "Starting indexing rank (%i to %i) using %i threads\n", rank_min, rank_max, num_threads);
for (rank = rank_min; rank <= rank_max; rank++)
{
fprintf(stderr, "Starting rank %d\n", rank);
rankCountTuples = 0;
rankPerSecond = 0;
paramRank = PGint32(rank);
paramValues[0] = (char *)&paramRank;
paramLengths[0] = sizeof(paramRank);
paramFormats[0] = 1;
// if (rank < 16)
// resSectors = PQexecPrepared(conn, "index_nosectors", 1, paramValues, paramLengths, paramFormats, 1);
// else
resSectors = PQexecPrepared(conn, "index_sectors", 1, paramValues, paramLengths, paramFormats, 1);
if (PQresultStatus(resSectors) != PGRES_TUPLES_OK)
// OSMLINE: do reindexing (=> reparenting) for interpolation lines at rank 30, but before all other objects of rank 30
// reason: houses (rank 30) depend on the updated interpolation line, when reparenting (see placex_update in functions.sql)
if (rank == 30)
{
fprintf(stderr, "index_sectors: SELECT failed: %s", PQerrorMessage(conn));
PQclear(resSectors);
exit(EXIT_FAILURE);
run_indexing(rank, 1, conn, num_threads, thread_data, structuredoutputfile);
}
if (PQftype(resSectors, 0) != PG_OID_INT4)
{
fprintf(stderr, "Sector value has unexpected type\n");
PQclear(resSectors);
exit(EXIT_FAILURE);
}
if (PQftype(resSectors, 1) != PG_OID_INT8)
{
fprintf(stderr, "Sector value has unexpected type\n");
PQclear(resSectors);
exit(EXIT_FAILURE);
}
rankTotalTuples = 0;
for (iSector = 0; iSector < PQntuples(resSectors); iSector++)
{
rankTotalTuples += PGint64(*((uint64_t *)PQgetvalue(resSectors, iSector, 1)));
}
rankStartTime = time(0);
for (iSector = 0; iSector <= PQntuples(resSectors); iSector++)
{
if (iSector > 0)
{
resPlaces = PQgetResult(conn);
if (PQresultStatus(resPlaces) != PGRES_TUPLES_OK)
{
fprintf(stderr, "index_sector_places: SELECT failed: %s", PQerrorMessage(conn));
PQclear(resPlaces);
exit(EXIT_FAILURE);
}
if (PQftype(resPlaces, 0) != PG_OID_INT8)
{
fprintf(stderr, "Place_id value has unexpected type\n");
PQclear(resPlaces);
exit(EXIT_FAILURE);
}
resNULL = PQgetResult(conn);
if (resNULL != NULL)
{
fprintf(stderr, "Unexpected non-null response\n");
exit(EXIT_FAILURE);
}
}
if (iSector < PQntuples(resSectors))
{
sector = PGint32(*((uint32_t *)PQgetvalue(resSectors, iSector, 0)));
// fprintf(stderr, "\n Starting sector %d size %ld\n", sector, PGint64(*((uint64_t *)PQgetvalue(resSectors, iSector, 1))));
// Get all the place_id's for this sector
paramRank = PGint32(rank);
paramValues[0] = (char *)&paramRank;
paramLengths[0] = sizeof(paramRank);
paramFormats[0] = 1;
paramSector = PGint32(sector);
paramValues[1] = (char *)&paramSector;
paramLengths[1] = sizeof(paramSector);
paramFormats[1] = 1;
if (rankTotalTuples-rankCountTuples < num_threads*1000)
{
iResult = PQsendQueryPrepared(conn, "index_nosector_places", 1, paramValues, paramLengths, paramFormats, 1);
}
else
{
iResult = PQsendQueryPrepared(conn, "index_sector_places", 2, paramValues, paramLengths, paramFormats, 1);
}
if (!iResult)
{
fprintf(stderr, "index_sector_places: SELECT failed: %s", PQerrorMessage(conn));
PQclear(resPlaces);
exit(EXIT_FAILURE);
}
}
if (iSector > 0)
{
count = 0;
rankPerSecond = 0;
tuples = PQntuples(resPlaces);
if (tuples > 0)
{
// Spawn threads
for (i = 0; i < num_threads; i++)
{
thread_data[i].res = resPlaces;
thread_data[i].tuples = tuples;
thread_data[i].count = &count;
thread_data[i].count_mutex = &count_mutex;
thread_data[i].writer = writer;
thread_data[i].writer_mutex = &writer_mutex;
pthread_create(&thread_data[i].thread, NULL, &nominatim_indexThread, (void *)&thread_data[i]);
}
// Monitor threads to give user feedback
sleepcount = 0;
while (count < tuples)
{
usleep(1000);
// Aim for one update per second
if (sleepcount++ > 500)
{
rankPerSecond = ((float)rankCountTuples + (float)count) / MAX(difftime(time(0), rankStartTime),1);
fprintf(stderr, " Done %i in %i @ %f per second - Rank %i ETA (seconds): %f\n", (rankCountTuples + count), (int)(difftime(time(0), rankStartTime)), rankPerSecond, rank, ((float)(rankTotalTuples - (rankCountTuples + count)))/rankPerSecond);
sleepcount = 0;
}
}
// Wait for everything to finish
for (i = 0; i < num_threads; i++)
{
pthread_join(thread_data[i].thread, NULL);
}
rankCountTuples += tuples;
}
// Finished sector
rankPerSecond = (float)rankCountTuples / MAX(difftime(time(0), rankStartTime),1);
fprintf(stderr, " Done %i in %i @ %f per second - ETA (seconds): %f\n", rankCountTuples, (int)(difftime(time(0), rankStartTime)), rankPerSecond, ((float)(rankTotalTuples - rankCountTuples))/rankPerSecond);
PQclear(resPlaces);
}
if (rankTotalTuples-rankCountTuples < num_threads*20 && iSector < PQntuples(resSectors))
{
iSector = PQntuples(resSectors) - 1;
}
}
// Finished rank
fprintf(stderr, "\r Done %i in %i @ %f per second - FINISHED \n\n", rankCountTuples, (int)(difftime(time(0), rankStartTime)), rankPerSecond);
PQclear(resSectors);
run_indexing(rank, 0, conn, num_threads, thread_data, structuredoutputfile);
}
if (writer)
{
nominatim_exportXMLEnd(writer);
}
// Close all connections
for (i = 0; i < num_threads; i++)
{
PQfinish(thread_data[i].conn);
}
PQfinish(conn);
// Close all connections
for (i = 0; i < num_threads; i++)
{
PQfinish(thread_data[i].conn);
}
PQfinish(conn);
}
void *nominatim_indexThread(void * thread_data_in)
@@ -324,12 +432,15 @@ void *nominatim_indexThread(void * thread_data_in)
PGresult *res;
const char *paramValues[1];
const char *paramValues[1];
int paramLengths[1];
int paramFormats[1];
uint64_t paramPlaceID;
uint64_t place_id;
time_t updateStartTime;
uint64_t place_id;
time_t updateStartTime;
uint table;
table = (uint)(thread_data->table);
while (1)
{
@@ -348,37 +459,58 @@ void *nominatim_indexThread(void * thread_data_in)
if (verbose) fprintf(stderr, " Processing place_id %ld\n", place_id);
updateStartTime = time(0);
int done = 0;
int done = 0;
if (thread_data->writer)
{
nominatim_exportPlaceQueries(place_id, thread_data->conn, &querySet);
}
while(!done)
{
paramPlaceID = PGint64(place_id);
paramValues[0] = (char *)&paramPlaceID;
paramLengths[0] = sizeof(paramPlaceID);
paramFormats[0] = 1;
res = PQexecPrepared(thread_data->conn, "index_placex", 1, paramValues, paramLengths, paramFormats, 1);
if (PQresultStatus(res) == PGRES_COMMAND_OK)
done = 1;
else
{
if (!strncmp(PQerrorMessage(thread_data->conn), "ERROR: deadlock detected", 25))
{
fprintf(stderr, "index_placex: UPDATE failed - deadlock, retrying (%ld)\n", place_id);
PQclear(res);
sleep(rand() % 10);
}
else
{
fprintf(stderr, "index_placex: UPDATE failed: %s", PQerrorMessage(thread_data->conn));
PQclear(res);
exit(EXIT_FAILURE);
}
}
while(!done)
{
paramPlaceID = PGint64(place_id);
paramValues[0] = (char *)&paramPlaceID;
paramLengths[0] = sizeof(paramPlaceID);
paramFormats[0] = 1;
if (table == 1) // table=1 for placex
{
res = PQexecPrepared(thread_data->conn, "index_placex", 1, paramValues, paramLengths, paramFormats, 1);
}
else // table=0 for osmline
{
res = PQexecPrepared(thread_data->conn, "index_osmline", 1, paramValues, paramLengths, paramFormats, 1);
}
if (PQresultStatus(res) == PGRES_COMMAND_OK)
done = 1;
else
{
if (!strncmp(PQerrorMessage(thread_data->conn), "ERROR: deadlock detected", 25))
{
if (table == 1)
{
fprintf(stderr, "index_placex: UPDATE failed - deadlock, retrying (%ld)\n", place_id);
}
else
{
fprintf(stderr, "index_osmline: UPDATE failed - deadlock, retrying (%ld)\n", place_id);
}
PQclear(res);
sleep(rand() % 10);
}
else
{
if (table == 1)
{
fprintf(stderr, "index_placex: UPDATE failed: %s", PQerrorMessage(thread_data->conn));
}
else
{
fprintf(stderr, "index_osmline: UPDATE failed: %s", PQerrorMessage(thread_data->conn));
}
PQclear(res);
exit(EXIT_FAILURE);
}
}
}
PQclear(res);
if (difftime(time(0), updateStartTime) > 1) fprintf(stderr, " Slow place_id %ld\n", place_id);

View File

@@ -14,6 +14,7 @@ struct index_thread_data
pthread_mutex_t * count_mutex;
xmlTextWriterPtr writer;
pthread_mutex_t * writer_mutex;
uint table;
};
void nominatim_index(int rank_min, int rank_max, int num_threads, const char *conninfo, const char *structuredoutputfile);
void *nominatim_indexThread(void * thread_data_in);

View File

@@ -115,7 +115,7 @@ int main(int argc, char *argv[])
PGconn *conn;
fprintf(stderr, "nominatim version %s\n\n", VERSION);
fprintf(stderr, "nominatim version %s\n\n", NOMINATIM_VERSION);
while (1)
{

View File

@@ -20,7 +20,7 @@ struct output_options
int expire_tiles_zoom_min; /* Minimum zoom level for tile expiry list */
const char *expire_tiles_filename; /* File name to output expired tiles list to */
int enable_hstore; /* add an additional hstore column with objects key/value pairs */
int enable_multi; /* Output multi-geometries intead of several simple geometries */
int enable_multi; /* Output multi-geometries instead of several simple geometries */
char** hstore_columns; /* list of columns that should be written into their own hstore column */
int n_hstore_columns; /* number of hstore columns */
};

View File

@@ -7,7 +7,11 @@
#define PG_OID_INT8 20
#define PG_OID_INT4 23
#if defined(HAVE_BYTESWAP_H)
#include <byteswap.h>
#elif defined(HAVE_SYS_ENDIAN_H)
#include <sys/endian.h>
#endif
#if __BYTE_ORDER == __BIG_ENDIAN
#define PGint16(x) (x)

152
phpcs.xml Normal file
View File

@@ -0,0 +1,152 @@
<?xml version="1.0"?>
<ruleset name="Nominatim Standard">
<description>Nominatim coding standard</description>
<!-- based on another standard, you can find it here -->
<!-- /usr/share/php/PHP/CodeSniffer/Standards/PSR2/ruleset.xml -->
<!-- https://github.com/squizlabs/PHP_CodeSniffer/blob/master/CodeSniffer/Standards/PSR2/ruleset.xml -->
<rule ref="PSR2"/>
<rule ref="Generic.Files.LineLength">
<properties>
<property name="lineLimit" value="199"/>
<property name="absoluteLineLimit" value="199"/>
</properties>
</rule>
<!-- "A file should declare new symbols (classes, functions, constants, etc.) and cause no
other side effects, or it should execute logic with side effects, but should not do both."
... we have too many script and includes to be able to enforce that.
-->
<rule ref="PSR1.Files.SideEffects.FoundWithSymbols">
<severity>0</severity>
</rule>
<!-- **************************************************************
DOCUMENTATION
************************************************************** -->
<rule ref="PEAR.Commenting.FunctionComment.Missing">
<severity>0</severity>
</rule>
<!-- **************************************************************
COMMENTS
************************************************************** -->
<!-- any comments in the lines before function() are better than forcing
a PHPdoc style right now -->
<rule ref="PEAR.Commenting.FunctionComment.WrongStyle">
<severity>0</severity>
</rule>
<!-- We allow comments after statements -->
<rule ref="Squiz.Commenting.PostStatementComment.Found">
<severity>0</severity>
</rule>
<!-- ... even without space e.g. //some words -->
<rule ref="Squiz.Commenting.InlineComment.NoSpaceBefore">
<severity>0</severity>
</rule>
<!-- blank lines after inline comments are fine -->
<rule ref="Squiz.Commenting.InlineComment.SpacingAfter">
<severity>0</severity>
</rule>
<!-- Comments don't have to start uppercase -->
<rule ref="Squiz.Commenting.InlineComment.NotCapital">
<severity>0</severity>
</rule>
<!-- Comments don't have to end with one of .!? -->
<rule ref="Squiz.Commenting.InlineComment.InvalidEndChar">
<severity>0</severity>
</rule>
<!-- Empty comments are fine -->
<rule ref="Squiz.Commenting.InlineComment.Empty">
<severity>0</severity>
</rule>
<!-- **************************************************************
INDENTATION, SPACING
************************************************************** -->
<!-- We don't need 2 blank lines after function -->
<rule ref="Squiz.WhiteSpace.FunctionSpacing.After">
<severity>0</severity>
</rule>
<!-- Aligned looks nicer, but causes too many warnings currently -->
<rule ref="Generic.Formatting.MultipleStatementAlignment.NotSame">
<severity>0</severity>
</rule>
<rule ref="Generic.Formatting.MultipleStatementAlignment.NotSameWarning">
<severity>0</severity>
</rule>
<!-- Aligned looks nicer, but causes too many warnings currently -->
<rule ref="Squiz.Arrays.ArrayDeclaration.DoubleArrowNotAligned">
<severity>0</severity>
</rule>
<!-- **************************************************************
VARIABLES
************************************************************** -->
<!-- CONST_this_var is fine, we don't need ConstThisVar -->
<rule ref="Generic.NamingConventions.UpperCaseConstantName.ConstantNotUpperCase">
<severity>0</severity>
</rule>
<!-- simply disagree with "Each line in an array declaration must end in a comma" -->
<rule ref="Squiz.Arrays.ArrayDeclaration.NoCommaAfterLast">
<severity>0</severity>
</rule>
<rule ref="Squiz.Arrays.ArrayDeclaration.NoComma">
<severity>0</severity>
</rule>
<!-- We allow "$abc = array($aPoint[1], $aPoint[2])" -->
<rule ref="Squiz.Arrays.ArrayDeclaration.SingleLineNotAllowed">
<severity>0</severity>
</rule>
<!-- **************************************************************
CONTROL STRUCTURES
************************************************************** -->
<!-- we allow "if (a) echo 'b'" without brackets -->
<rule ref="Generic.ControlStructures.InlineControlStructure.NotAllowed">
<severity>0</severity>
</rule>
<!-- We allow "if (a)". No need for "if (a === TRUE)" -->
<rule ref="Squiz.Operators.ComparisonOperatorUsage.ImplicitTrue">
<severity>0</severity>
</rule>
<!-- ... same for "if (!a)" -->
<rule ref="Squiz.Operators.ComparisonOperatorUsage.NotAllowed">
<severity>0</severity>
</rule>
</ruleset>

View File

@@ -8,13 +8,13 @@
processIsolation="false"
stopOnFailure="false"
syntaxCheck="true"
bootstrap="tests-php/bootstrap.php"
bootstrap="test/php/bootstrap.php"
>
<php>
</php>
<testsuites>
<testsuite name="Nominatim PHP Test Suite">
<directory>./tests-php/Nominatim</directory>
<directory>./test/php/Nominatim</directory>
</testsuite>
</testsuites>
<filter>

123
settings/defaults.php Normal file
View File

@@ -0,0 +1,123 @@
<?php
@define('CONST_BasePath', '@CMAKE_SOURCE_DIR@');
@define('CONST_InstallPath', '@CMAKE_BINARY_DIR@');
if (file_exists(getenv('NOMINATIM_SETTINGS'))) require_once(getenv('NOMINATIM_SETTINGS'));
if (file_exists(CONST_InstallPath.'/settings/local.php')) require_once(CONST_InstallPath.'/settings/local.php');
if (isset($_GET['debug']) && $_GET['debug']) @define('CONST_Debug', true);
// 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);
// Restrict search languages.
// Normally Nominatim will include all language variants of name:XX
// in the search index. Set this to a comma separated list of language
// codes, to restrict import to a subset of languages.
// Currently only affects the import of country names and special phrases.
@define('CONST_Languages', false);
// Rules for normalizing terms for comparison before doing comparisons.
// The default is to remove accents and punctuation and to lower-case the
// term. Spaces are kept but collapsed to one standard space.
@define('CONST_Term_Normalization_Rules', ":: NFD (); [:Nonspacing Mark:] >; :: lower (); [[:Punctuation:][:Space:]]+ > ' '; :: NFC ();");
// Set to false to avoid importing extra postcodes for the US.
@define('CONST_Use_Extra_US_Postcodes', true);
/* Set to true after importing Tiger house number data for the US.
Note: The tables must already exist or queries will throw errors.
After changing this setting run ./utils/setup --create-functions
again. */
@define('CONST_Use_US_Tiger_Data', false);
/* Set to true after importing other external house number data.
Note: the aux tables must already exist or queries will throw errors.
After changing this setting run ./utils/setup --create-functions
again. */
@define('CONST_Use_Aux_Location_data', false);
// 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', '');
// Paths
@define('CONST_ExtraDataPath', CONST_BasePath.'/data');
@define('CONST_Osm2pgsql_Binary', CONST_InstallPath.'/osm2pgsql/osm2pgsql');
@define('CONST_Pyosmium_Binary', '@PYOSMIUM_PATH@');
@define('CONST_Tiger_Data_Path', CONST_ExtraDataPath.'/tiger');
@define('CONST_Wikipedia_Data_Path', CONST_ExtraDataPath);
// 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
// Base URL of replication service
@define('CONST_Replication_Url', 'http://planet.openstreetmap.org/replication/minute');
// Maximum size in MB of data to download per batch
@define('CONST_Replication_Max_Diff_size', '30');
// How long until the service publishes the next diff
// (relative to the age of data in the diff).
@define('CONST_Replication_Update_Interval', '75');
// How long to sleep when no update could be found
@define('CONST_Replication_Recheck_Interval', '60');
// Website settings
@define('CONST_NoAccessControl', true);
@define('CONST_Website_BaseURL', 'http://'.php_uname('n').'/');
// Language to assume when none is supplied with the query.
// When set to false, the local language (i.e. the name tag without suffix)
// will be used.
@define('CONST_Default_Language', false);
// Appearance of the map in the debug interface.
@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', true);
@define('CONST_Search_BatchMode', false);
@define('CONST_Search_TryDroppedAddressTerms', 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);
// Maximum number of OSM ids that may be queried at once
// for the places endpoint.
@define('CONST_Places_Max_ID_count', 50);
// Number of different geometry formats that may be queried in parallel.
// Set to zero to disable polygon output.
@define('CONST_PolygonOutput_MaximumTypes', 1);
// Log settings
// Set to true to log into new_query_log table.
// You should set up a cron job that regularly clears out this table.
@define('CONST_Log_DB', false);
// Set to a file name to enable logging to a file.
@define('CONST_Log_File', false);

View File

@@ -1,165 +0,0 @@
amenity airport
amenity arts_centre
amenity atm
amenity auditorium
amenity bank
amenity bar
amenity bench
amenity bicycle_parking
amenity bicycle_rental
amenity brothel
amenity bureau_de_change
amenity bus_station
amenity cafe
amenity car_rental
amenity car_wash
amenity casino
amenity cinema
amenity clinic
amenity club
amenity college
amenity community_centre
amenity courthouse
amenity crematorium
amenity dentist
amenity doctors
amenity dormitory
amenity drinking_water
amenity driving_school
amenity embassy
amenity emergency_phone
amenity fast_food
amenity ferry_terminal
amenity fire_hydrant
amenity fire_station
amenity fountain
amenity fuel
amenity grave_yard
amenity hall
amenity health_centre
amenity hospital
amenity hotel
amenity hunting_stand
amenity ice_cream
amenity kindergarten
amenity library
amenity market
amenity marketplace
amenity nightclub
amenity nursery
amenity nursing_home
amenity office
amenity park
amenity parking
amenity pharmacy
amenity place_of_worship
amenity police
amenity post_box
amenity post_office
amenity preschool
amenity prison
amenity pub
amenity public_building
amenity public_market
amenity reception_area
amenity restaurant
amenity retirement_home
amenity sauna
amenity school
amenity shelter
amenity shop
amenity shopping
amenity social_club
amenity studio
amenity supermarket
amenity taxi
amenity telephone
amenity theatre
amenity toilets
amenity townhall
amenity university
amenity veterinary
amenity waste_basket
amenity wifi
amenity youth_centre
boundary administrative
building apartments
building block
building bunker
building chapel
building church
building commercial
building dormitory
building entrance
building faculty
building farm
building flats
building garage
building hospital
building hotel
building house
building industrial
building office
building public
building residential
building retail
building school
building shop
building stadium
building store
building terrace
building tower
building train_station
building university
highway bridleway
highway bus_stop
highway construction
highway cycleway
highway distance_marker
highway emergency_access_point
highway footway
highway gate
highway motorway_junction
highway path
highway pedestrian
highway platform
highway primary
highway primary_link
highway raceway
highway road
highway secondary
highway secondary_link
highway services
highway steps
highway tertiary
highway track
highway trail
highway trunk
highway trunk_link
highway unsurfaced
historic archaeological_site
historic battlefield
historic building
historic castle
historic church
historic house
historic icon
historic manor
historic memorial
historic mine
historic monument
historic museum
historic ruins
historic tower
historic wayside_cross
historic wayside_shrine
historic wreck
landuse cemetery
landuse commercial
landuse construction
landuse farm
landuse farmland
landuse farmyard
landuse forest
landuse grass
landuse industrial

View File

@@ -1,51 +1,20 @@
<?php
# These settings control the import of special phrases from the wiki.
# Languages to download the special phrases for.
$aLanguageIn = array(
'af',
'ar',
'br',
'ca',
'cs',
'de',
'en',
'es',
'et',
'eu',
'fa',
'fi',
'fr',
'gl',
'hr',
'hu',
'ia',
'is',
'it',
'ja',
'mk',
'nl',
'no',
'pl',
'ps',
'pt',
'ru',
'sk',
'sv',
'uk',
'vi',
);
// These settings control the import of special phrases from the wiki.
# class/type combinations to exclude
$aTagsBlacklist = array(
'boundary' => array('administrative'),
'place' => array('house', 'houses'),
);
# If a class is in the white list then all types will
# be ignored except the ones given in the list.
# Also use this list to exclude an entire class from
# special phrases.
$aTagsWhitelist = array(
'highway' => array('bus_stop', 'rest_area', 'raceway'),
'building' => array(),
);
// class/type combinations to exclude
$aTagsBlacklist
= array(
'boundary' => array('administrative'),
'place' => array('house', 'houses'),
);
// If a class is in the white list then all types will
// be ignored except the ones given in the list.
// Also use this list to exclude an entire class from
// special phrases.
$aTagsWhitelist
= array(
'highway' => array('bus_stop', 'rest_area', 'raceway'),
'building' => array(),
);

View File

@@ -1,85 +1,4 @@
<?php
if (file_exists(CONST_BasePath.'/settings/local.php')) require_once(CONST_BasePath.'/settings/local.php');
if (isset($_GET['debug']) && $_GET['debug']) @define('CONST_Debug', true);
// General settings
@define('CONST_Debug', false);
@define('CONST_Database_DSN', 'pgsql://@/nominatim'); // <driver>://<username>:<password>@<host>:<port>/<database>
@define('CONST_Max_Word_Frequency', '50000');
@define('CONST_Limit_Reindexing', true);
// Software versions
@define('CONST_Postgresql_Version', '9.1'); // values: 8.3, 8.4, 9.0, 9.1, 9.2
@define('CONST_Postgis_Version', '1.5'); // values: 1.5, 2.0
// 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');
// osm2pgsql settings
@define('CONST_Osm2pgsql_Flatnode_File', null);
// Replication settings
@define('CONST_Replication_Url', 'http://planet.openstreetmap.org/replication/minute');
@define('CONST_Replication_MaxInterval', '3600');
@define('CONST_Replication_Update_Interval', '60'); // How often upstream publishes diffs
@define('CONST_Replication_Recheck_Interval', '60'); // How long to sleep if no update found yet
// Connection buckets to rate limit people being nasty
@define('CONST_ConnectionBucket_MemcacheServerAddress', false);
@define('CONST_ConnectionBucket_MemcacheServerPort', 11211);
@define('CONST_ConnectionBucket_MaxBlockList', 100);
@define('CONST_ConnectionBucket_LeakRate', 1);
@define('CONST_ConnectionBucket_BlockLimit', 10);
@define('CONST_ConnectionBucket_WaitLimit', 6);
@define('CONST_ConnectionBucket_MaxSleeping', 10);
@define('CONST_ConnectionBucket_Cost_Reverse', 1);
@define('CONST_ConnectionBucket_Cost_Search', 2);
@define('CONST_ConnectionBucket_Cost_Details', 3);
@define('CONST_ConnectionBucket_Cost_Status', 1);
// Override this function to add an adjustment factor to the cost
// based on server load. e.g. getBlockingProcesses
if (!function_exists('user_busy_cost'))
{
function user_busy_cost()
{
return 0;
}
}
// Website settings
@define('CONST_NoAccessControl', true);
@define('CONST_ClosedForIndexing', false);
@define('CONST_ClosedForIndexingExceptionIPs', '');
@define('CONST_BlockedIPs', '');
@define('CONST_BulkUserIPs', '');
@define('CONST_BlockMessage', ''); // additional info to show for blocked IPs
@define('CONST_Website_BaseURL', 'http://'.php_uname('n').'/');
@define('CONST_Tile_Default', 'Mapnik');
@define('CONST_Default_Language', false);
@define('CONST_Default_Lat', 20.0);
@define('CONST_Default_Lon', 0.0);
@define('CONST_Default_Zoom', 2);
@define('CONST_Search_AreaPolygons_Enabled', true);
@define('CONST_Search_AreaPolygons', true);
@define('CONST_Search_BatchMode', false);
@define('CONST_Search_TryDroppedAddressTerms', false);
@define('CONST_Search_NameOnlySearchFrequencyThreshold', false);
// Set to zero to disable polygon output
@define('CONST_PolygonOutput_MaximumTypes', 1);
// Log settings
@define('CONST_Log_DB', true);
@define('CONST_Log_File', false);
@define('CONST_Log_File_Format', 'TODO'); // Currently hard coded
@define('CONST_Log_File_SearchLog', '');
@define('CONST_Log_File_ReverseLog', '');
echo "ERROR: Scripts must be run from build directory.\n";
exit;

6
sql/aux_tables.sql Normal file
View File

@@ -0,0 +1,6 @@
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-user}";

File diff suppressed because it is too large Load Diff

View File

@@ -1,30 +1,28 @@
-- 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_osmline_parent_place_id ON location_property_osmline USING BTREE (parent_place_id) {ts:search-index};
-- start
CREATE INDEX idx_location_property_-partition-_centroid ON location_property_-partition- USING GIST (centroid);
-- end
CREATE INDEX idx_search_name_country_centroid ON search_name_country USING GIST (centroid) {ts:address-index};
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

@@ -6,8 +6,11 @@ TRUNCATE location_area;
DROP SEQUENCE seq_place;
CREATE SEQUENCE seq_place start 100000;
insert into placex (osm_type, osm_id, class, type, name, admin_level, housenumber, street, isin, postcode, country_code, extratags, geometry) select * from place where osm_type = 'N';
insert into placex (osm_type, osm_id, class, type, name, admin_level, housenumber, street, isin, postcode, country_code, extratags, geometry) select * from place where osm_type = 'W';
insert into placex (osm_type, osm_id, class, type, name, admin_level, housenumber, street, isin, postcode, country_code, extratags, geometry) select * from place where osm_type = 'R';
insert into placex (osm_type, osm_id, class, type, name, admin_level, housenumber, street, isin, postcode, country_code, extratags, geometry)
select osm_type, osm_id, class, type, name, admin_level, housenumber, street, isin, postcode, country_code, extratags, geometry from place where osm_type = 'N';
insert into placex (osm_type, osm_id, class, type, name, admin_level, housenumber, street, isin, postcode, country_code, extratags, geometry)
select osm_type, osm_id, class, type, name, admin_level, housenumber, street, isin, postcode, country_code, extratags, geometry from place where osm_type = 'W';
insert into placex (osm_type, osm_id, class, type, name, admin_level, housenumber, street, isin, postcode, country_code, extratags, geometry)
select osm_type, osm_id, class, type, name, admin_level, housenumber, street, isin, postcode, country_code, extratags, geometry from place where osm_type = 'R';
--select count(*) from (select create_interpolation(osm_id, housenumber) from placex where indexed=false and class='place' and type='houses') as x;

View File

@@ -1,4 +1,4 @@
create or replace function getNearFeatures(in_partition INTEGER, point GEOMETRY, maxrank INTEGER, isin_tokens INT[]) RETURNS setof nearfeaturecentr AS $$
create or replace function getNearFeatures(in_partition INTEGER, feature GEOMETRY, maxrank INTEGER, isin_tokens INT[]) RETURNS setof nearfeaturecentr AS $$
DECLARE
r nearfeaturecentr%rowtype;
BEGIN
@@ -6,14 +6,14 @@ BEGIN
-- start
IF in_partition = -partition- THEN
FOR r IN
SELECT place_id, keywords, rank_address, rank_search, min(ST_Distance(point, centroid)) as distance, isguess, centroid FROM (
SELECT * FROM location_area_large_-partition- WHERE ST_Contains(geometry, point) and rank_search < maxrank
SELECT place_id, keywords, rank_address, rank_search, min(ST_Distance(feature, centroid)) as distance, isguess, centroid FROM (
SELECT * FROM location_area_large_-partition- WHERE ST_Intersects(geometry, feature) and rank_search < maxrank
UNION ALL
SELECT * FROM location_area_country WHERE ST_Contains(geometry, point) and rank_search < maxrank
SELECT * FROM location_area_country WHERE ST_Intersects(geometry, feature) and rank_search < maxrank
) as location_area
GROUP BY place_id, keywords, rank_address, rank_search, isguess, centroid
ORDER BY rank_address, isin_tokens && keywords desc, isguess asc,
ST_Distance(point, centroid) *
ST_Distance(feature, centroid) *
CASE
WHEN rank_address = 16 AND rank_search = 15 THEN 0.2 -- capital city
WHEN rank_address = 16 AND rank_search = 16 THEN 0.25 -- city
@@ -65,13 +65,15 @@ BEGIN
END IF;
IF in_rank_search <= 4 THEN
INSERT INTO location_area_country values (in_partition, in_place_id, in_country_code, in_keywords, in_rank_search, in_rank_address, in_estimate, in_centroid, in_geometry);
INSERT INTO location_area_country (partition, place_id, country_code, keywords, rank_search, rank_address, isguess, centroid, geometry)
values (in_partition, in_place_id, in_country_code, in_keywords, in_rank_search, in_rank_address, in_estimate, in_centroid, in_geometry);
RETURN TRUE;
END IF;
-- start
IF in_partition = -partition- THEN
INSERT INTO location_area_large_-partition- values (in_partition, in_place_id, in_country_code, in_keywords, in_rank_search, in_rank_address, in_estimate, in_centroid, in_geometry);
INSERT INTO location_area_large_-partition- (partition, place_id, country_code, keywords, rank_search, rank_address, isguess, centroid, geometry)
values (in_partition, in_place_id, in_country_code, in_keywords, in_rank_search, in_rank_address, in_estimate, in_centroid, in_geometry);
RETURN TRUE;
END IF;
-- end
@@ -203,14 +205,14 @@ DECLARE
BEGIN
DELETE FROM search_name WHERE place_id = in_place_id;
INSERT INTO search_name values (in_place_id, in_rank_search, in_rank_address, in_importance, in_country_code,
in_name_vector, in_nameaddress_vector, in_centroid);
INSERT INTO search_name (place_id, search_rank, address_rank, importance, country_code, name_vector, nameaddress_vector, centroid)
values (in_place_id, in_rank_search, in_rank_address, in_importance, in_country_code, in_name_vector, in_nameaddress_vector, in_centroid);
IF in_rank_search <= 4 THEN
DELETE FROM search_name_country WHERE place_id = in_place_id;
IF in_rank_address > 0 THEN
INSERT INTO search_name_country values (in_place_id, in_rank_search, in_rank_address,
in_name_vector, in_geometry);
INSERT INTO search_name_country (place_id, search_rank, address_rank, name_vector, centroid)
values (in_place_id, in_rank_search, in_rank_address, in_name_vector, in_geometry);
END IF;
RETURN TRUE;
END IF;
@@ -219,8 +221,8 @@ BEGIN
IF in_partition = -partition- THEN
DELETE FROM search_name_-partition- values WHERE place_id = in_place_id;
IF in_rank_address > 0 THEN
INSERT INTO search_name_-partition- values (in_place_id, in_rank_search, in_rank_address,
in_name_vector, in_geometry);
INSERT INTO search_name_-partition- (place_id, search_rank, address_rank, name_vector, centroid)
values (in_place_id, in_rank_search, in_rank_address, in_name_vector, in_geometry);
END IF;
RETURN TRUE;
END IF;
@@ -261,7 +263,8 @@ BEGIN
-- start
IF in_partition = -partition- THEN
DELETE FROM location_road_-partition- where place_id = in_place_id;
INSERT INTO location_road_-partition- values (in_partition, in_place_id, in_country_code, in_geometry);
INSERT INTO location_road_-partition- (partition, place_id, country_code, geometry)
values (in_partition, in_place_id, in_country_code, in_geometry);
RETURN TRUE;
END IF;
-- end

View File

@@ -7,8 +7,8 @@ drop type if exists nearfeature cascade;
create type nearfeature as (
place_id BIGINT,
keywords int[],
rank_address integer,
rank_search integer,
rank_address smallint,
rank_search smallint,
distance float,
isguess boolean
);
@@ -17,8 +17,8 @@ drop type if exists nearfeaturecentr cascade;
create type nearfeaturecentr as (
place_id BIGINT,
keywords int[],
rank_address integer,
rank_search integer,
rank_address smallint,
rank_search smallint,
distance float,
isguess boolean,
centroid GEOMETRY
@@ -27,42 +27,37 @@ create type nearfeaturecentr as (
drop table IF EXISTS search_name_blank CASCADE;
CREATE TABLE search_name_blank (
place_id BIGINT,
search_rank integer,
address_rank integer,
search_rank smallint,
address_rank smallint,
name_vector integer[]
);
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 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 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_road_-partition- (
partition integer,
place_id BIGINT,
partition SMALLINT,
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

View File

@@ -1,155 +0,0 @@
drop table import_npi_log;
CREATE TABLE import_npi_log (
npiid integer,
batchend timestamp,
batchsize integer,
starttime timestamp,
endtime timestamp,
event text
);
drop table IF EXISTS word;
CREATE TABLE word (
word_id INTEGER,
word_token text,
word_trigram text,
word text,
class text,
type text,
country_code varchar(2),
search_name_count INTEGER,
operator TEXT
);
SELECT AddGeometryColumn('word', 'location', 4326, 'GEOMETRY', 2);
CREATE INDEX idx_word_word_id on word USING BTREE (word_id);
CREATE INDEX idx_word_word_token on word USING BTREE (word_token);
GRANT SELECT ON word TO "www-data" ;
DROP SEQUENCE seq_word;
CREATE SEQUENCE seq_word start 1;
drop table IF EXISTS location_property CASCADE;
CREATE TABLE location_property (
place_id BIGINT,
partition integer,
parent_place_id BIGINT,
housenumber TEXT,
postcode TEXT
);
SELECT AddGeometryColumn('location_property', 'centroid', 4326, 'POINT', 2);
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);
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);
drop table IF EXISTS search_name_blank CASCADE;
CREATE TABLE search_name_blank (
place_id BIGINT,
search_rank integer,
address_rank integer,
importance FLOAT,
country_code varchar(2),
name_vector integer[],
nameaddress_vector integer[]
);
SELECT AddGeometryColumn('search_name_blank', 'centroid', 4326, 'GEOMETRY', 2);
drop table IF EXISTS search_name;
CREATE TABLE search_name () INHERITS (search_name_blank);
CREATE INDEX search_name_name_vector_idx ON search_name USING GIN (name_vector gin__int_ops) WITH (fastupdate = off);
CREATE INDEX searchnameplacesearch_search_nameaddress_vector_idx ON search_name USING GIN (nameaddress_vector gin__int_ops) WITH (fastupdate = off);
CREATE INDEX idx_search_name_centroid ON search_name USING GIST (centroid);
CREATE INDEX idx_search_name_place_id ON search_name USING BTREE (place_id);
drop table IF EXISTS place_addressline;
CREATE TABLE place_addressline (
place_id BIGINT,
address_place_id BIGINT,
fromarea boolean,
isaddress boolean,
distance float,
cached_rank_address integer
);
CREATE INDEX idx_place_addressline_place_id on place_addressline USING BTREE (place_id);
CREATE INDEX idx_place_addressline_address_place_id on place_addressline USING BTREE (address_place_id);
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
);
CREATE INDEX idx_place_boundingbox_place_id on place_boundingbox USING BTREE (place_id);
SELECT AddGeometryColumn('place_boundingbox', 'outline', 4326, 'GEOMETRY', 2);
CREATE INDEX idx_place_boundingbox_outline ON place_boundingbox USING GIST (outline);
GRANT SELECT on place_boundingbox to "www-data" ;
GRANT INSERT on place_boundingbox to "www-data" ;
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;
CREATE TABLE placex (
place_id BIGINT NOT NULL,
partition integer,
osm_type char(1),
osm_id INTEGER,
class TEXT NOT NULL,
type TEXT NOT NULL,
name HSTORE,
admin_level INTEGER,
housenumber TEXT,
street TEXT,
isin TEXT,
postcode TEXT,
country_code varchar(2),
extratags HSTORE,
parent_place_id BIGINT,
linked_place_id BIGINT,
rank_address INTEGER,
rank_search INTEGER,
importance FLOAT,
indexed_status INTEGER,
indexed_date TIMESTAMP,
geometry_sector INTEGER
);
SELECT AddGeometryColumn('placex', 'geometry', 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_rank_search ON placex USING BTREE (rank_search);
CREATE INDEX idx_placex_rank_address ON placex USING BTREE (rank_address);
CREATE INDEX idx_placex_geometry ON placex USING GIST (geometry);
CREATE INDEX idx_placex_parent_place_id ON placex USING BTREE (parent_place_id) where parent_place_id IS NOT NULL;
DROP SEQUENCE seq_place;
CREATE SEQUENCE seq_place start 1;
GRANT SELECT on placex to "www-data" ;
GRANT UPDATE ON placex to "www-data" ;
GRANT SELECT ON search_name to "www-data" ;
GRANT DELETE on search_name to "www-data" ;
GRANT INSERT on search_name to "www-data" ;
GRANT SELECT on place_addressline to "www-data" ;
GRANT INSERT ON place_addressline to "www-data" ;
GRANT DELETE on place_addressline to "www-data" ;
GRANT SELECT ON seq_word to "www-data" ;
GRANT UPDATE ON seq_word to "www-data" ;
GRANT INSERT ON word to "www-data" ;
GRANT SELECT on country to "www-data" ;

View File

@@ -1,41 +1,21 @@
drop table import_status;
drop table if exists import_status;
CREATE TABLE import_status (
lastimportdate timestamp NOT NULL
lastimportdate timestamp NOT NULL,
sequence_id integer,
indexed boolean
);
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,
batchseq integer,
batchsize integer,
starttime timestamp,
endtime timestamp,
event text
);
drop table import_npi_log;
CREATE TABLE import_npi_log (
npiid integer,
batchend timestamp,
batchsize integer,
starttime timestamp,
endtime timestamp,
event text
);
--drop table IF EXISTS query_log;
CREATE TABLE query_log (
starttime timestamp,
query text,
ipaddress text,
endtime timestamp,
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" ;
CREATE TABLE new_query_log (
type text,
starttime timestamp,
@@ -43,28 +23,19 @@ CREATE TABLE new_query_log (
useragent text,
language text,
query text,
searchterm text,
endtime timestamp,
results integer,
format text,
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}" ;
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" ;
GRANT SELECT ON TABLE country_name TO "{www-user}";
GRANT SELECT ON TABLE gb_postcode TO "{www-user}";
drop table IF EXISTS word;
CREATE TABLE word (
@@ -76,34 +47,32 @@ 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),
keywords INTEGER[],
rank_search INTEGER NOT NULL,
rank_address INTEGER NOT NULL,
partition SMALLINT,
rank_search SMALLINT NOT NULL,
rank_address SMALLINT NOT NULL,
country_code VARCHAR(2),
isguess BOOL
);
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 (
place_id BIGINT,
partition integer,
parent_place_id BIGINT,
partition SMALLINT,
housenumber TEXT,
postcode TEXT
);
@@ -113,120 +82,112 @@ 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 (
place_id BIGINT,
parent_place_id BIGINT,
startnumber INTEGER,
endnumber INTEGER,
partition SMALLINT,
linegeo GEOMETRY,
interpolationtype TEXT,
postcode TEXT);
GRANT SELECT ON location_property_tiger TO "{www-user}";
drop table if exists location_property_osmline;
CREATE TABLE location_property_osmline (
place_id BIGINT NOT NULL,
osm_id BIGINT,
parent_place_id BIGINT,
geometry_sector INTEGER,
indexed_date TIMESTAMP,
startnumber INTEGER,
endnumber INTEGER,
partition SMALLINT,
indexed_status SMALLINT,
linegeo GEOMETRY,
interpolationtype TEXT,
address HSTORE,
postcode TEXT,
country_code VARCHAR(2)
){ts:search-data};
CREATE UNIQUE INDEX idx_osmline_place_id ON location_property_osmline USING BTREE (place_id) {ts:search-index};
CREATE INDEX idx_osmline_geometry_sector ON location_property_osmline USING BTREE (geometry_sector) {ts:address-index};
CREATE INDEX idx_osmline_linegeo ON location_property_osmline USING GIST (linegeo) {ts:search-index};
GRANT SELECT ON location_property_osmline TO "{www-user}";
drop table IF EXISTS search_name;
CREATE TABLE search_name (
place_id BIGINT,
search_rank integer,
address_rank integer,
importance FLOAT,
country_code varchar(2),
search_rank SMALLINT,
address_rank SMALLINT,
name_vector integer[],
nameaddress_vector integer[]
);
nameaddress_vector integer[],
country_code varchar(2)
) {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 (
place_id BIGINT,
address_place_id BIGINT,
distance FLOAT,
cached_rank_address SMALLINT,
fromarea boolean,
isaddress boolean,
distance float,
cached_rank_address integer
);
CREATE INDEX idx_place_addressline_place_id on place_addressline USING BTREE (place_id);
isaddress boolean
) {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,
LIKE place INCLUDING CONSTRAINTS,
parent_place_id BIGINT,
linked_place_id BIGINT,
rank_address INTEGER,
rank_search INTEGER,
importance FLOAT,
indexed_status INTEGER,
indexed_date TIMESTAMP,
wikipedia TEXT, -- calculated wikipedia article name (language:title)
geometry_sector INTEGER,
calculated_country_code varchar(2)
);
rank_address SMALLINT,
rank_search SMALLINT,
partition SMALLINT,
indexed_status SMALLINT,
LIKE place INCLUDING CONSTRAINTS,
wikipedia TEXT, -- calculated wikipedia article name (language:title)
country_code varchar(2),
housenumber TEXT,
postcode TEXT
) {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} WHERE linked_place_id IS NOT NULL;
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
-- insert creates the location tables, creates location indexes if indexed == true
CREATE TRIGGER placex_before_insert BEFORE INSERT ON placex
FOR EACH ROW EXECUTE PROCEDURE placex_insert();
CREATE TRIGGER osmline_before_insert BEFORE INSERT ON location_property_osmline
FOR EACH ROW EXECUTE PROCEDURE osmline_insert();
-- update insert creates the location tables
CREATE TRIGGER placex_before_update BEFORE UPDATE ON placex
FOR EACH ROW EXECUTE PROCEDURE placex_update();
CREATE TRIGGER osmline_before_update BEFORE UPDATE ON location_property_osmline
FOR EACH ROW EXECUTE PROCEDURE osmline_update();
-- diff update triggers
CREATE TRIGGER placex_before_delete AFTER DELETE ON placex
@@ -236,16 +197,13 @@ 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;
DROP SEQUENCE IF EXISTS seq_postcodes;
CREATE SEQUENCE seq_postcodes start 1;
drop table import_polygon_error;
DROP TABLE IF EXISTS import_polygon_error;
CREATE TABLE import_polygon_error (
osm_type char(1),
osm_id INTEGER,
osm_id BIGINT,
osm_type CHAR(1),
class TEXT NOT NULL,
type TEXT NOT NULL,
name HSTORE,
@@ -256,19 +214,19 @@ 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;
DROP TABLE IF EXISTS import_polygon_delete;
CREATE TABLE import_polygon_delete (
osm_type char(1),
osm_id INTEGER,
osm_id BIGINT,
osm_type CHAR(1),
class TEXT NOT NULL,
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;
DROP SEQUENCE IF EXISTS file;
CREATE SEQUENCE file start 1;
-- null table so it won't error

View File

@@ -1,12 +1,13 @@
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);
--index only on parent_place_id
CREATE INDEX idx_location_property_tiger_parent_place_id_imp ON location_property_tiger_import (parent_place_id) {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;
ALTER INDEX idx_location_property_tiger_parent_place_id_imp RENAME TO idx_location_property_tiger_housenumber_parent_place_id;
ALTER INDEX idx_location_property_tiger_place_id_imp RENAME TO idx_location_property_tiger_place_id;
DROP FUNCTION tigger_create_interpolation (linegeo geometry, in_startnumber integer, in_endnumber integer, interpolationtype text, in_street text, in_isin text, in_postcode text);
DROP FUNCTION tiger_line_import (linegeo geometry, in_startnumber integer, in_endnumber integer, interpolationtype text, in_street text, in_isin text, in_postcode text);

View File

@@ -1,19 +1,15 @@
DROP TABLE IF EXISTS location_property_tiger_import;
CREATE TABLE location_property_tiger_import () INHERITS (location_property);
CREATE TABLE location_property_tiger_import (linegeo GEOMETRY, place_id BIGINT, partition INTEGER, parent_place_id BIGINT, startnumber INTEGER, endnumber INTEGER, interpolationtype TEXT, postcode TEXT);
CREATE OR REPLACE FUNCTION tigger_create_interpolation(linegeo GEOMETRY, in_startnumber INTEGER,
CREATE OR REPLACE FUNCTION tiger_line_import(linegeo GEOMETRY, in_startnumber INTEGER,
in_endnumber INTEGER, interpolationtype TEXT,
in_street TEXT, in_isin TEXT, in_postcode TEXT) RETURNS INTEGER
AS $$
DECLARE
startnumber INTEGER;
endnumber INTEGER;
stepsize INTEGER;
housenum INTEGER;
newpoints INTEGER;
numberrange INTEGER;
rangestartnumber INTEGER;
place_centroid GEOMETRY;
out_partition INTEGER;
out_parent_place_id BIGINT;
@@ -31,7 +27,6 @@ BEGIN
END IF;
numberrange := endnumber - startnumber;
rangestartnumber := startnumber;
IF (interpolationtype = 'odd' AND startnumber%2 = 0) OR (interpolationtype = 'even' AND startnumber%2 = 1) THEN
startnumber := startnumber + 1;
@@ -75,15 +70,11 @@ BEGIN
END LOOP;
END IF;
newpoints := 0;
FOR housenum IN startnumber..endnumber BY stepsize LOOP
insert into location_property_tiger_import (place_id, partition, parent_place_id, housenumber, postcode, centroid)
values (nextval('seq_place'), out_partition, out_parent_place_id, housenum, in_postcode,
ST_LineInterpolatePoint(linegeo, (housenum::float-rangestartnumber::float)/numberrange::float));
newpoints := newpoints + 1;
END LOOP;
--insert street(line) into import table
insert into location_property_tiger_import (linegeo, place_id, partition, parent_place_id, startnumber, endnumber, interpolationtype, postcode)
values (linegeo, nextval('seq_place'), out_partition, out_parent_place_id, startnumber, endnumber, interpolationtype, in_postcode);
RETURN newpoints;
RETURN 1;
END;
$$
LANGUAGE plpgsql;

View File

@@ -1,9 +0,0 @@
\a
\t
\o /tmp/bigintupdate.sql
select 'alter table "'||relname||'" alter '||attname||' type bigint;' from pg_attribute join pg_class on
(attrelid = oid) where attname like '%place_id%' and attnum > 0 and relkind = 'r'::"char" and atttypid = 23
and not relname::text ~ '^.*_[0-9]+$' order by 'alter table "'||relname||'" alter '||attname||' type
bigint;';
\o
\i /tmp/bigintupdate.sql

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 address->'postcode' as v from place where address ? 'postcode') as w where v is not null;
select count(getorcreate_housenumber_id(make_standard_name(v))) from (select distinct address->'housenumber' as v from place where address ? 'housenumber') 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;

138
test/README.md Normal file
View File

@@ -0,0 +1,138 @@
This directory contains functional and unit tests for the Nominatim API.
Prerequisites
=============
* Python 3 (https://www.python.org/)
* behave test framework >= 1.2.5 (https://github.com/behave/behave)
* nose (https://nose.readthedocs.org)
* pytidylib (http://countergram.com/open-source/pytidylib)
* psycopg2 (http://initd.org/psycopg/)
To get the prerequisites on a a fresh Ubuntu LTS 16.04 run:
[sudo] apt-get install python3-dev python3-pip python3-psycopg2 python3-tidylib phpunit php-cgi
pip3 install --user behave nose
Overall structure
=================
There are two kind of tests in this test suite. There are functional tests
which test the API interface using a BDD test framework and there are unit
tests for specific PHP functions.
This test directory is sturctured as follows:
```
-+- bdd Functional API tests
| \
| +- steps Step implementations for test descriptions
| +- osm2pgsql Tests for data import via osm2pgsql
| +- db Tests for internal data processing on import and update
| +- api Tests for API endpoints (search, reverse, etc.)
|
+- php PHP unit tests
+- scenes Geometry test data
+- testdb Base data for generating API test database
```
PHP Unit Tests
==============
Unit tests can be found in the php/ directory and tests selected php functions.
Very low coverage.
To execute the test suite run
cd test/php
phpunit ../
It will read phpunit.xml which points to the library, test path, bootstrap
strip and set other parameters.
BDD Functional Tests
====================
Functional tests are written as BDD instructions. For more information on
the philosophy of BDD testing, see http://pythonhosted.org/behave/philosophy.html
Usage
-----
To run the functional tests, do
cd test/bdd
behave
The tests can be configured with a set of environment variables:
* `BUILD_DIR` - build directory of Nominatim installation to test
* `TEMPLATE_DB` - name of template database used as a skeleton for
the test databases (db tests)
* `TEST_DB` - name of test database (db tests)
* `ABI_TEST_DB` - name of the database containing the API test data (api tests)
* `TEST_SETTINGS_TEMPLATE` - file to write temporary Nominatim settings to
* `REMOVE_TEMPLATE` - if true, the template database will not be reused during
the next run. Reusing the base templates speeds up tests
considerably but might lead to outdated errors for some
changes in the database layout.
* `KEEP_TEST_DB` - if true, the test database will not be dropped after a test
is finished. Should only be used if one single scenario is
run, otherwise the result is undefined.
Logging can be defined through command line parameters of behave itself. Check
out `behave --help` for details. Also keep an eye out for the 'work-in-progress'
feature of behave which comes in handy when writing new tests.
Writing Tests
-------------
The following explanation assume that the reader is familiar with the BDD
notations of features, scenarios and steps.
All possible steps can be found in the `steps` directory and should ideally
be documented.
### API Tests (`test/bdd/api`)
These tests are meant to test the different API endpoints and their parameters.
They require a preimported test database, which consists of the import of a
planet extract. A precompiled PBF with the necessary data can be downloaded from
http://www.nominatim.org/data/test/nominatim-api-testdata.pbf
The polygons defining the extract can be found in the test/testdb
directory. There is also a reduced set of wikipedia data for this extract,
which you need to import as well. For Tiger tests the data of South Dakota
is required. Get the Tiger files `46*`.
The official test dataset is derived from the 160725 planet. Newer
planets are likely to work as well but you may see isolated test
failures where the data has changed. To recreate the input data
for the test database run:
wget http://free.nchc.org.tw/osm.planet/pbf/planet-160725.osm.pbf
osmconvert planet-160725.osm.pbf -B=test/testdb/testdb.polys -o=testdb.pbf
Before importing make sure to add the following to your local settings:
@define('CONST_Database_DSN', 'pgsql://@/test_api_nominatim');
@define('CONST_Wikipedia_Data_Path', CONST_BasePath.'/test/testdb');
### Indexing Tests (`test/bdd/db`)
These tests check the import and update of the Nominatim database. They do not
test the correctness of osm2pgsql. Each test will write some data into the `place`
table (and optionally `the planet_osm_*` tables if required) and then run
Nominatim's processing functions on that.
These tests need to create their own test databases. By default they will be
called `test_template_nominatim` and `test_nominatim`. Names can be changed with
the environment variables `TEMPLATE_DB` and `TEST_DB`. The user running the tests
needs superuser rights for postgres.
### Import Tests (`test/bdd/osm2pgsql`)
These tests check that data is imported correctly into the place table. They
use the same template database as the Indexing tests, so the same remarks apply.

3
test/bdd/.behaverc Normal file
View File

@@ -0,0 +1,3 @@
[behave]
show_skipped=False
tags=~@Fail

View File

@@ -0,0 +1,14 @@
@APIDB
Feature: Object details
Check details page for correctness
Scenario Outline: Details via OSM id
When sending details query for <object>
Then the result is valid html
Examples:
| object |
| 492887 |
| N4267356889 |
| W230804120 |
| R123924 |

View File

@@ -0,0 +1,17 @@
@APIDB
Feature: Places by osm_type and osm_id Tests
Simple tests for internal server errors and response format.
Scenario Outline: address lookup for existing node, way, relation
When sending <format> lookup query for N3284625766,W6065798,,R123924,X99,N0
Then the result is valid <format>
And exactly 3 results are returned
Examples:
| format |
| xml |
| json |
Scenario: address lookup for non-existing or invalid node, way, relation
When sending xml lookup query for X99,,N0,nN158845944,ABC,,W9
Then exactly 0 results are returned

View File

@@ -0,0 +1,36 @@
@APIDB
Feature: Localization of reverse search results
Scenario: default language
When sending json reverse coordinates 18.1147,-15.95
Then result addresses contain
| ID | country |
| 0 | Mauritanie موريتانيا |
Scenario: accept-language parameter
When sending json reverse coordinates 18.1147,-15.95
| accept-language |
| en,fr |
Then result addresses contain
| ID | country |
| 0 | Mauritania |
Scenario: HTTP accept language header
Given the HTTP header
| accept-language |
| fr-ca,fr;q=0.8,en-ca;q=0.5,en;q=0.3 |
When sending json reverse coordinates 18.1147,-15.95
Then result addresses contain
| ID | country |
| 0 | Mauritanie |
Scenario: accept-language parameter and HTTP header
Given the HTTP header
| accept-language |
| fr-ca,fr;q=0.8,en-ca;q=0.5,en;q=0.3 |
When sending json reverse coordinates 18.1147,-15.95
| accept-language |
| en |
Then result addresses contain
| ID | country |
| 0 | Mauritania |

View File

@@ -0,0 +1,102 @@
@APIDB
Feature: Parameters for Reverse API
Testing different parameter options for reverse API.
Scenario Outline: Reverse-geocoding without address
When sending <format> reverse coordinates 53.603,10.041
| addressdetails |
| 0 |
Then exactly 1 result is returned
And result has not attributes address
Examples:
| format |
| json |
| jsonv2 |
| xml |
Scenario Outline: Reverse Geocoding with extratags
When sending <format> reverse coordinates 10.776234290950017,106.70425325632095
| extratags |
| 1 |
Then result 0 has attributes extratags
Examples:
| format |
| xml |
| json |
| jsonv2 |
Scenario Outline: Reverse Geocoding with namedetails
When sending <format> reverse coordinates 10.776455623137625,106.70175343751907
| namedetails |
| 1 |
Then result 0 has attributes namedetails
Examples:
| format |
| xml |
| json |
| jsonv2 |
Scenario Outline: Reverse Geocoding contains TEXT geometry
When sending <format> reverse coordinates 47.165989816710066,9.515774846076965
| polygon_text |
| 1 |
Then result 0 has attributes <response_attribute>
Examples:
| format | response_attribute |
| xml | geotext |
| json | geotext |
| jsonv2 | geotext |
Scenario Outline: Reverse Geocoding contains polygon-as-points geometry
When sending <format> reverse coordinates 47.165989816710066,9.515774846076965
| polygon |
| 1 |
Then result 0 has not attributes <response_attribute>
Examples:
| format | response_attribute |
| xml | polygonpoints |
| json | polygonpoints |
| jsonv2 | polygonpoints |
Scenario Outline: Reverse Geocoding contains SVG geometry
When sending <format> reverse coordinates 47.165989816710066,9.515774846076965
| polygon_svg |
| 1 |
Then result 0 has attributes <response_attribute>
Examples:
| format | response_attribute |
| xml | geosvg |
| json | svg |
| jsonv2 | svg |
Scenario Outline: Reverse Geocoding contains KML geometry
When sending <format> reverse coordinates 47.165989816710066,9.515774846076965
| polygon_kml |
| 1 |
Then result 0 has attributes <response_attribute>
Examples:
| format | response_attribute |
| xml | geokml |
| json | geokml |
| jsonv2 | geokml |
Scenario Outline: Reverse Geocoding contains GEOJSON geometry
When sending <format> reverse coordinates 47.165989816710066,9.515774846076965
| polygon_geojson |
| 1 |
Then result 0 has attributes <response_attribute>
Examples:
| format | response_attribute |
| xml | geojson |
| json | geojson |
| jsonv2 | geojson |

View File

@@ -0,0 +1,25 @@
@APIDB
Feature: Reverse geocoding
Testing the reverse function
@Tiger
Scenario: TIGER house number
When sending jsonv2 reverse coordinates 45.3345,-97.5214
Then results contain
| osm_type | category | type |
| way | place | house |
And result addresses contain
| house_number | road | postcode | country_code |
| 906 | West 1st Street | 57274 | us |
@Tiger
Scenario: No TIGER house number for zoom < 18
When sending jsonv2 reverse coordinates 45.3345,-97.5214
| zoom |
| 17 |
Then results contain
| osm_type | category |
| way | highway |
And result addresses contain
| road | postcode | country_code |
| West 1st Street | 57274 | us |

View File

@@ -0,0 +1,129 @@
@APIDB
Feature: Simple Reverse Tests
Simple tests for internal server errors and response format.
Scenario Outline: Simple reverse-geocoding
When sending reverse coordinates <lat>,<lon>
Then the result is valid xml
When sending xml reverse coordinates <lat>,<lon>
Then the result is valid xml
When sending json reverse coordinates <lat>,<lon>
Then the result is valid json
When sending jsonv2 reverse coordinates <lat>,<lon>
Then the result is valid json
When sending html reverse coordinates <lat>,<lon>
Then the result is valid html
Examples:
| lat | lon |
| 0.0 | 0.0 |
| -34.830 | -56.105 |
| 45.174 | -103.072 |
| 21.156 | -12.2744 |
Scenario Outline: Testing different parameters
When sending reverse coordinates 53.603,10.041
| param | value |
| <parameter> | <value> |
Then the result is valid xml
When sending html reverse coordinates 53.603,10.041
| param | value |
| <parameter> | <value> |
Then the result is valid html
When sending xml reverse coordinates 53.603,10.041
| param | value |
| <parameter> | <value> |
Then the result is valid xml
When sending json reverse coordinates 53.603,10.041
| param | value |
| <parameter> | <value> |
Then the result is valid json
When sending jsonv2 reverse coordinates 53.603,10.041
| param | value |
| <parameter> | <value> |
Then the result is valid json
Examples:
| parameter | value |
| polygon | 1 |
| polygon | 0 |
| polygon_text | 1 |
| polygon_text | 0 |
| polygon_kml | 1 |
| polygon_kml | 0 |
| polygon_geojson | 1 |
| polygon_geojson | 0 |
| polygon_svg | 1 |
| polygon_svg | 0 |
Scenario Outline: Wrapping of legal jsonp requests
When sending <format> reverse coordinates 67.3245,0.456
| json_callback |
| foo |
Then the result is valid json
Examples:
| format |
| json |
| jsonv2 |
Scenario Outline: Boundingbox is returned
When sending <format> reverse coordinates 14.62,108.1
| zoom |
| 4 |
Then result has bounding box in 9,20,102,113
Examples:
| format |
| json |
| jsonv2 |
| xml |
Scenario Outline: Reverse-geocoding with zoom
When sending <format> reverse coordinates 53.603,10.041
| zoom |
| 10 |
Then exactly 1 result is returned
Examples:
| format |
| json |
| jsonv2 |
| html |
| xml |
Scenario: Missing lon parameter
When sending reverse coordinates 52.52,
Then a HTTP 400 is returned
Scenario: Missing lat parameter
When sending reverse coordinates ,52.52
Then a HTTP 400 is returned
Scenario: Missing osm_id parameter
When sending reverse coordinates ,
| osm_type |
| N |
Then a HTTP 400 is returned
Scenario: Missing osm_type parameter
When sending reverse coordinates ,
| osm_id |
| 3498564 |
Then a HTTP 400 is returned
Scenario Outline: Bad format for lat or lon
When sending reverse coordinates ,
| lat | lon |
| <lat> | <lon> |
Then a HTTP 400 is returned
Examples:
| lat | lon |
| 48.9660 | 8,4482 |
| 48,9660 | 8.4482 |
| 48,9660 | 8,4482 |
| 48.966.0 | 8.4482 |
| 48.966 | 8.448.2 |
| Nan | 8.448 |
| 48.966 | Nan |

View File

@@ -0,0 +1,62 @@
@APIDB
Feature: Localization of search results
Scenario: default language
When sending json search query "Vietnam"
Then results contain
| ID | display_name |
| 0 | Vit Nam |
Scenario: accept-language first
When sending json search query "Mauretanien"
| accept-language |
| en,de |
Then results contain
| ID | display_name |
| 0 | Mauritania |
Scenario: accept-language missing
When sending json search query "Mauretanien"
| accept-language |
| xx,fr,en,de |
Then results contain
| ID | display_name |
| 0 | Mauritanie |
Scenario: http accept language header first
Given the HTTP header
| accept-language |
| fr-ca,fr;q=0.8,en-ca;q=0.5,en;q=0.3 |
When sending json search query "Mauretanien"
Then results contain
| ID | display_name |
| 0 | Mauritanie |
Scenario: http accept language header and accept-language
Given the HTTP header
| accept-language |
| fr-ca,fr;q=0.8,en-ca;q=0.5,en;q=0.3 |
When sending json search query "Mauretanien"
| accept-language |
| de,en |
Then results contain
| ID | display_name |
| 0 | Mauretanien |
Scenario: http accept language header fallback
Given the HTTP header
| accept-language |
| fr-ca,en-ca;q=0.5 |
When sending json search query "Mauretanien"
Then results contain
| ID | display_name |
| 0 | Mauritanie |
Scenario: http accept language header fallback (upper case)
Given the HTTP header
| accept-language |
| fr-FR;q=0.8,en-ca;q=0.5 |
When sending json search query "Mauretanie"
Then results contain
| ID | display_name |
| 0 | Mauritanie |

View File

@@ -0,0 +1,300 @@
@APIDB
Feature: Search queries
Testing different queries and parameters
Scenario: Simple XML search
When sending xml search query "Schaan"
Then result 0 has attributes place_id,osm_type,osm_id
And result 0 has attributes place_rank,boundingbox
And result 0 has attributes lat,lon,display_name
And result 0 has attributes class,type,importance,icon
And result 0 has not attributes address
And result 0 has bounding box in 46.5,47.5,9,10
Scenario: Simple JSON search
When sending json search query "Vaduz"
Then result 0 has attributes place_id,licence,icon,class,type
And result 0 has attributes osm_type,osm_id,boundingbox
And result 0 has attributes lat,lon,display_name,importance
And result 0 has not attributes address
And result 0 has bounding box in 46.5,47.5,9,10
Scenario: JSON search with addressdetails
When sending json search query "Montevideo" with address
Then address of result 0 is
| type | value |
| city | Montevideo |
| state | Montevideo |
| country | Uruguay |
| country_code | uy |
Scenario: XML search with addressdetails
When sending xml search query "Aleg" with address
| accept-language |
| en |
Then address of result 0 is
| type | value |
| city | Aleg |
| state | Brakna |
| country | Mauritania |
| country_code | mr |
Scenario: coordinate search with addressdetails
When sending json search query "14.271104294939,107.69828796387"
| accept-language |
| en |
Then results contain
| display_name |
| Plei Ya Rê, Kon Tum province, Vietnam |
Scenario: Address details with unknown class types
When sending json search query "Hundeauslauf, Hamburg" with address
Then results contain
| ID | class | type |
| 0 | leisure | dog_park |
And result addresses contain
| ID | address29 |
| 0 | Hundeauslauf |
And address of result 0 has no types leisure,dog_park
Scenario: Disabling deduplication
When sending json search query "Sievekingsallee, Hamburg"
Then there are no duplicates
When sending json search query "Sievekingsallee, Hamburg"
| dedupe |
| 0 |
Then there are duplicates
Scenario: Search with bounded viewbox in right area
When sending json search query "restaurant" with address
| bounded | viewbox |
| 1 | -56.16786,-34.84061,-56.12525,-34.86526 |
Then result addresses contain
| city |
| Montevideo |
Scenario: Search with bounded viewboxlbrt in right area
When sending json search query "restaurant" with address
| bounded | viewboxlbrt |
| 1 | -56.16786,-34.86526,-56.12525,-34.84061 |
Then result addresses contain
| city |
| Montevideo |
Scenario: No POI search with unbounded viewbox
When sending json search query "restaurant"
| viewbox |
| 9.93027,53.61634,10.10073,53.54500 |
Then results contain
| display_name |
| ^[^,]*[Rr]estaurant.* |
Scenario: bounded search remains within viewbox, even with no results
When sending json search query "restaurant"
| bounded | viewbox |
| 1 | 43.5403125,-5.6563282,43.54285,-5.662003 |
Then less than 1 result is returned
Scenario: bounded search remains within viewbox with results
When sending json search query "restaurant"
| bounded | viewbox |
| 1 | 9.93027,53.61634,10.10073,53.54500 |
Then result has bounding box in 53.54500,53.61634,9.93027,10.10073
Scenario: Prefer results within viewbox
When sending json search query "25 de Mayo" with address
| accept-language |
| en |
Then result addresses contain
| ID | state |
| 0 | Salto |
When sending json search query "25 de Mayo" with address
| accept-language | viewbox |
| en | -56.35879,-34.18330,-56.31618,-34.20815 |
Then result addresses contain
| ID | state |
| 0 | Florida |
Scenario: Overly large limit number for search results
When sending json search query "restaurant"
| limit |
| 1000 |
Then at most 50 results are returned
Scenario: Limit number of search results
When sending json search query "restaurant"
| limit |
| 4 |
Then exactly 4 results are returned
Scenario: Restrict to feature type country
When sending xml search query "Uruguay"
Then results contain
| ID | place_rank |
| 1 | 16 |
When sending xml search query "Uruguay"
| featureType |
| country |
Then results contain
| place_rank |
| 4 |
Scenario: Restrict to feature type state
When sending xml search query "Dakota"
Then results contain
| place_rank |
| 12 |
When sending xml search query "Dakota"
| featureType |
| state |
Then results contain
| place_rank |
| 8 |
Scenario: Restrict to feature type city
When sending xml search query "vaduz"
Then results contain
| ID | place_rank |
| 1 | 30 |
When sending xml search query "vaduz"
| featureType |
| city |
Then results contain
| place_rank |
| 16 |
Scenario: Restrict to feature type settlement
When sending json search query "Burg"
Then results contain
| ID | class |
| 1 | amenity |
When sending json search query "Burg"
| featureType |
| settlement |
Then results contain
| class | type |
| boundary | administrative |
Scenario Outline: Search with polygon threshold (json)
When sending json search query "switzerland"
| polygon_geojson | polygon_threshold |
| 1 | <th> |
Then at least 1 result is returned
And result 0 has attributes geojson
Examples:
| th |
| -1 |
| 0.0 |
| 0.5 |
| 999 |
Scenario Outline: Search with polygon threshold (xml)
When sending xml search query "switzerland"
| polygon_geojson | polygon_threshold |
| 1 | <th> |
Then at least 1 result is returned
And result 0 has attributes geojson
Examples:
| th |
| -1 |
| 0.0 |
| 0.5 |
| 999 |
Scenario Outline: Search with invalid polygon threshold (xml)
When sending xml search query "switzerland"
| polygon_geojson | polygon_threshold |
| 1 | <th> |
Then a HTTP 400 is returned
Examples:
| th |
| x |
| ;; |
| 1m |
Scenario Outline: Search with extratags
When sending <format> search query "Hauptstr"
| extratags |
| 1 |
Then result has attributes extratags
Examples:
| format |
| xml |
| json |
| jsonv2 |
Scenario Outline: Search with namedetails
When sending <format> search query "Hauptstr"
| namedetails |
| 1 |
Then result has attributes namedetails
Examples:
| format |
| xml |
| json |
| jsonv2 |
Scenario Outline: Search result with contains TEXT geometry
When sending <format> search query "Highmore"
| polygon_text |
| 1 |
Then result has attributes <response_attribute>
Examples:
| format | response_attribute |
| xml | geotext |
| json | geotext |
| jsonv2 | geotext |
Scenario Outline: Search result contains polygon-as-points geometry
When sending <format> search query "Highmore"
| polygon |
| 1 |
Then result has attributes <response_attribute>
Examples:
| format | response_attribute |
| xml | polygonpoints |
| json | polygonpoints |
| jsonv2 | polygonpoints |
Scenario Outline: Search result contains SVG geometry
When sending <format> search query "Highmore"
| polygon_svg |
| 1 |
Then result has attributes <response_attribute>
Examples:
| format | response_attribute |
| xml | geosvg |
| json | svg |
| jsonv2 | svg |
Scenario Outline: Search result contains KML geometry
When sending <format> search query "Highmore"
| polygon_kml |
| 1 |
Then result has attributes <response_attribute>
Examples:
| format | response_attribute |
| xml | geokml |
| json | geokml |
| jsonv2 | geokml |
Scenario Outline: Search result contains GEOJSON geometry
When sending <format> search query "Highmore"
| polygon_geojson |
| 1 |
Then result has attributes <response_attribute>
Examples:
| format | response_attribute |
| xml | geojson |
| json | geojson |
| jsonv2 | geojson |

View File

@@ -0,0 +1,67 @@
@APIDB
Feature: Search queries
Generic search result correctness
Scenario: House number search for non-street address
When sending json search query "2 Steinwald, Austria" with address
| accept-language |
| en |
Then address of result 0 is
| type | value |
| house_number | 2 |
| hamlet | Steinwald |
| postcode | 6811 |
| country | Austria |
| country_code | at |
Scenario: House number interpolation even
When sending json search query "Schellingstr 86, Hamburg" with address
| accept-language |
| de |
Then address of result 0 is
| type | value |
| house_number | 86 |
| road | Schellingstraße |
| suburb | Eilbek |
| postcode | 22089 |
| city_district | Wandsbek |
| state | Hamburg |
| country | Deutschland |
| country_code | de |
Scenario: House number interpolation odd
When sending json search query "Schellingstr 73, Hamburg" with address
| accept-language |
| de |
Then address of result 0 is
| type | value |
| house_number | 73 |
| road | Schellingstraße |
| suburb | Eilbek |
| postcode | 22089 |
| city_district | Wandsbek |
| state | Hamburg |
| country | Deutschland |
| country_code | de |
@Tiger
Scenario: TIGER house number
When sending json search query "323 22nd Street Southwest, Huron"
Then results contain
| osm_type |
| way |
Scenario: Search with class-type feature
When sending jsonv2 search query "Hotel in California"
Then results contain
| place_rank |
| 30 |
# https://trac.openstreetmap.org/ticket/5094
Scenario: housenumbers are ordered by complete match first
When sending json search query "6395 geminis, montevideo" with address
Then result addresses contain
| ID | house_number |
| 0 | 6395 |
| 1 | 6395 BIS |

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