From: Markus Gail Date: Mon, 21 Mar 2016 13:26:39 +0000 (+0100) Subject: Merge branch 'tigerlines' of /home/markus/Nominatim into tiger X-Git-Tag: v3.0.0~190^2~1 X-Git-Url: https://git.openstreetmap.org./nominatim.git/commitdiff_plain/a4ecd9d73e93a56aeee336c7fa7e18aa42bd9e03?hp=d8703c223b50f87a6adb779311f651853e6d4e36 Merge branch 'tigerlines' of /home/markus/Nominatim into tiger Conflicts: lib/Geocode.php lib/ReverseGeocode.php lib/lib.php --- diff --git a/.gitignore b/.gitignore index b6625912..23fb34a6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,33 +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 -!tests/scenes/bin/Makefile -Makefile.in -stamp-h1 -missing -INSTALL -aclocal.m4 -depcomp -install-sh -compile - data/wiki_import.sql data/wiki_specialphrases.sql data/osmosischange.osc -.vagrant \ No newline at end of file +.vagrant diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..dca35eca --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,127 @@ +#----------------------------------------------------------------------------- +# +# 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 2) +set(NOMINATIM_VERSION_MINOR 5) + +set(NOMINATIM_VERSION "${NOMINATIM_VERSION_MAJOR}.${NOMINATIM_VERSION_MINOR}") + +add_definitions(-DNOMINATIM_VERSION="${NOMINATIM_VERSION}") + + +#----------------------------------------------------------------------------- +# +# Find external dependencies +# +#----------------------------------------------------------------------------- + +set(BUILD_TESTS on) +set(WITH_LUA off) +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}) + +find_program(PG_CONFIG pg_config) +execute_process(COMMAND ${PG_CONFIG} --pgxs + OUTPUT_VARIABLE PGXS + OUTPUT_STRIP_TRAILING_WHITESPACE) + +find_package(ZLIB REQUIRED) + +find_package(BZip2 REQUIRED) + +find_package(LibXml2 REQUIRED) +include_directories(${LIBXML2_INCLUDE_DIR}) + +#----------------------------------------------------------------------------- +# +# Setup settings and paths +# +#----------------------------------------------------------------------------- + +set(CUSTOMFILES + settings/settings.php + 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() + +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) + +#----------------------------------------------------------------------------- diff --git a/Makefile.am b/Makefile.am deleted file mode 100644 index 2ade09a5..00000000 --- a/Makefile.am +++ /dev/null @@ -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 diff --git a/README b/README index 224b6569..7a760ff6 100644 --- a/README +++ b/README @@ -29,13 +29,11 @@ is cloned as well by running `git submodule update --init`. Installation steps: -0. If checking out from git run: - - ./autogen.sh - 1. Compile Nominatim: - ./configure + mkdir build + cd build + cmake .. make 2. Get OSM data and import: diff --git a/Vagrantfile b/Vagrantfile index 30bc9375..f32640f1 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -14,6 +14,10 @@ Vagrant.configure("2") do |config| sub.vm.box = "ubuntu/trusty64" sub.vm.provision :shell, :path => "vagrant/ubuntu-trusty-provision.sh" end + config.vm.define "ubuntu-php7" do |sub| + sub.vm.box = "ubuntu/trusty64" + sub.vm.provision :shell, :path => "vagrant/ubuntu-trusty-php7-provision.sh" + end config.vm.define "centos" do |sub| sub.vm.box = "bento/centos-7.2" sub.vm.provision :shell, :path => "vagrant/centos-7-provision.sh" diff --git a/autogen.sh b/autogen.sh deleted file mode 100755 index 68341a59..00000000 --- a/autogen.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -autoreconf -vfi diff --git a/configure.ac b/configure.ac deleted file mode 100644 index 53a8e871..00000000 --- a/configure.ac +++ /dev/null @@ -1,67 +0,0 @@ -AC_INIT(Nominatim,2.5) -if git rev-parse HEAD 2>/dev/null >/dev/null; then - AC_SUBST([PACKAGE_VERSION], [$PACKAGE_VERSION-git-`git rev-parse --short HEAD`]) -fi - -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 -m4_include([m4/ax_lib_postgresql_svr.m4]) -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(9.0) -if test "x$POSTGRESQL_VERSION" = "x" -then - AC_MSG_ERROR([postgresql client library not found]) -fi -AX_LIB_POSTGRESQL_SVR(9.0) -if test ! -f "$POSTGRESQL_PGXS" -then - AC_MSG_ERROR([postgresql server development library not found]) -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) diff --git a/contrib/openlayers.cfg b/contrib/openlayers.cfg deleted file mode 100644 index 61dc4fc5..00000000 --- a/contrib/openlayers.cfg +++ /dev/null @@ -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] - - diff --git a/lib/Geocode.php b/lib/Geocode.php index c24c84ae..4b15b3c8 100644 --- a/lib/Geocode.php +++ b/lib/Geocode.php @@ -1,4 +1,6 @@ $aResult) { // Default - $fDiameter = 0.0001; - - if (isset($aClassType[$aResult['class'].':'.$aResult['type'].':'.$aResult['admin_level']]['defdiameter']) - && $aClassType[$aResult['class'].':'.$aResult['type'].':'.$aResult['admin_level']]['defdiameter']) - { - $fDiameter = $aClassType[$aResult['class'].':'.$aResult['type'].':'.$aResult['admin_level']]['defdiameter']; - } - elseif (isset($aClassType[$aResult['class'].':'.$aResult['type']]['defdiameter']) - && $aClassType[$aResult['class'].':'.$aResult['type']]['defdiameter']) + $fDiameter = getResultDiameter($aResult); + + $oPlaceLookup = new PlaceLookup($this->oDB); + $oPlaceLookup->setIncludePolygonAsPoints($this->bIncludePolygonAsPoints); + $oPlaceLookup->setIncludePolygonAsText($this->bIncludePolygonAsText); + $oPlaceLookup->setIncludePolygonAsGeoJSON($this->bIncludePolygonAsGeoJSON); + $oPlaceLookup->setIncludePolygonAsKML($this->bIncludePolygonAsKML); + $oPlaceLookup->setIncludePolygonAsSVG($this->bIncludePolygonAsSVG); + $oPlaceLookup->setPolygonSimplificationThreshold($this->fPolygonSimplificationThreshold); + + $aOutlineResult = $oPlaceLookup->getOutlines($aResult['place_id'], $aResult['lon'], $aResult['lat'], $fDiameter/2); + if ($aOutlineResult) { - $fDiameter = $aClassType[$aResult['class'].':'.$aResult['type']]['defdiameter']; - } - $fRadius = $fDiameter / 2; - - if (CONST_Search_AreaPolygons) - { - // Get the bounding box and outline polygon - $sSQL = "select place_id,0 as numfeatures,st_area(geometry) as area,"; - $sSQL .= "ST_Y(centroid) as centrelat,ST_X(centroid) as centrelon,"; - $sSQL .= "ST_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 = ".$aResult['place_id']; - if ($this->fPolygonSimplificationThreshold > 0) - { - $sSQL .= " from (select place_id,centroid,ST_SimplifyPreserveTopology(geometry,".$this->fPolygonSimplificationThreshold.") as geometry".$sFrom.") as plx"; - } - else - { - $sSQL .= $sFrom; - } - - $aPointPolygon = $this->oDB->getRow($sSQL); - if (PEAR::IsError($aPointPolygon)) - { - failInternalError("Could not get outline.", $sSQL, $aPointPolygon); - } - - if ($aPointPolygon['place_id']) - { - if ($this->bIncludePolygonAsGeoJSON) $aResult['asgeojson'] = $aPointPolygon['asgeojson']; - if ($this->bIncludePolygonAsKML) $aResult['askml'] = $aPointPolygon['askml']; - if ($this->bIncludePolygonAsSVG) $aResult['assvg'] = $aPointPolygon['assvg']; - if ($this->bIncludePolygonAsText) $aResult['astext'] = $aPointPolygon['astext']; - - if ($aPointPolygon['centrelon'] !== null && $aPointPolygon['centrelat'] !== null ) - { - $aResult['lat'] = $aPointPolygon['centrelat']; - $aResult['lon'] = $aPointPolygon['centrelon']; - } - - if ($this->bIncludePolygonAsPoints) - { - $aPolyPoints[] = geometryText2Points($aPointPolygon['astext'],$fRadius); - - // Output data suitable for display (points and a bounding box) - if (isset($aPolyPoints)) - { - $aResult['aPolyPoints'] = array(); - foreach($aPolyPoints as $aPoint) - { - $aResult['aPolyPoints'][] = array($aPoint[1], $aPoint[2]); - } - } - } - - if (abs($aPointPolygon['minlat'] - $aPointPolygon['maxlat']) < 0.0000001) - { - $aPointPolygon['minlat'] = $aPointPolygon['minlat'] - $fRadius; - $aPointPolygon['maxlat'] = $aPointPolygon['maxlat'] + $fRadius; - } - if (abs($aPointPolygon['minlon'] - $aPointPolygon['maxlon']) < 0.0000001) - { - $aPointPolygon['minlon'] = $aPointPolygon['minlon'] - $fRadius; - $aPointPolygon['maxlon'] = $aPointPolygon['maxlon'] + $fRadius; - } - $aResult['aBoundingBox'] = array((string)$aPointPolygon['minlat'],(string)$aPointPolygon['maxlat'],(string)$aPointPolygon['minlon'],(string)$aPointPolygon['maxlon']); - } + $aResult = array_merge($aResult, $aOutlineResult); } - + if ($aResult['extra_place'] == 'city') { $aResult['class'] = 'place'; @@ -1767,32 +1702,6 @@ $aResult['rank_search'] = 16; } - if (!isset($aResult['aBoundingBox'])) - { - $iSteps = max(8,min(100,$fRadius * 3.14 * 100000)); - $fStepSize = (2*pi())/$iSteps; - $aPointPolygon['minlat'] = $aResult['lat'] - $fRadius; - $aPointPolygon['maxlat'] = $aResult['lat'] + $fRadius; - $aPointPolygon['minlon'] = $aResult['lon'] - $fRadius; - $aPointPolygon['maxlon'] = $aResult['lon'] + $fRadius; - - // Output data suitable for display (points and a bounding box) - if ($this->bIncludePolygonAsPoints) - { - $aPolyPoints = array(); - for($f = 0; $f < 2*pi(); $f += $fStepSize) - { - $aPolyPoints[] = array('',$aResult['lon']+($fRadius*sin($f)),$aResult['lat']+($fRadius*cos($f))); - } - $aResult['aPolyPoints'] = array(); - foreach($aPolyPoints as $aPoint) - { - $aResult['aPolyPoints'][] = array($aPoint[1], $aPoint[2]); - } - } - $aResult['aBoundingBox'] = array((string)$aPointPolygon['minlat'],(string)$aPointPolygon['maxlat'],(string)$aPointPolygon['minlon'],(string)$aPointPolygon['maxlon']); - } - // Is there an icon set for this type of result? if (isset($aClassType[$aResult['class'].':'.$aResult['type']]['icon']) && $aClassType[$aResult['class'].':'.$aResult['type']]['icon']) diff --git a/lib/PlaceLookup.php b/lib/PlaceLookup.php index 55e0f11c..985ed224 100644 --- a/lib/PlaceLookup.php +++ b/lib/PlaceLookup.php @@ -17,6 +17,14 @@ protected $bNameDetails = false; + protected $bIncludePolygonAsPoints = false; + protected $bIncludePolygonAsText = false; + protected $bIncludePolygonAsGeoJSON = false; + protected $bIncludePolygonAsKML = false; + protected $bIncludePolygonAsSVG = false; + protected $fPolygonSimplificationThreshold = 0.0; + + function PlaceLookup(&$oDB) { $this->oDB =& $oDB; @@ -48,6 +56,48 @@ } } + + function setIncludePolygonAsPoints($b = true) + { + $this->bIncludePolygonAsPoints = $b; + } + + function getIncludePolygonAsPoints() + { + return $this->bIncludePolygonAsPoints; + } + + function setIncludePolygonAsText($b = true) + { + $this->bIncludePolygonAsText = $b; + } + + function getIncludePolygonAsText() + { + return $this->bIncludePolygonAsText; + } + + function setIncludePolygonAsGeoJSON($b = true) + { + $this->bIncludePolygonAsGeoJSON = $b; + } + + function setIncludePolygonAsKML($b = true) + { + $this->bIncludePolygonAsKML = $b; + } + + function setIncludePolygonAsSVG($b = true) + { + $this->bIncludePolygonAsSVG = $b; + } + + function setPolygonSimplificationThreshold($f) + { + $this->fPolygonSimplificationThreshold = $f; + } + + function setPlaceID($iPlaceID) { $this->iPlaceID = $iPlaceID; @@ -83,7 +133,7 @@ $sSQL = "select place_id,partition, 'T' as osm_type, place_id as osm_id, 'place' as class, 'house' as type, null as admin_level, housenumber, null as street, null as isin, postcode,"; $sSQL .= " 'us' as country_code, parent_place_id, null as linked_place_id, 30 as rank_address, 30 as rank_search,"; $sSQL .= " coalesce(null,0.75-(30::float/40)) as importance, null as indexed_status, null as indexed_date, null as wikipedia, 'us' as calculated_country_code, "; - $sSQL .= " get_address_by_language(place_id, housenumber,$sLanguagePrefArraySQL) as langaddress,"; + $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,"; @@ -229,5 +279,110 @@ 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 + 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 = $this->oDB->getRow($sSQL); + if (PEAR::IsError($aPointPolygon)) + { + echo var_dump($aPointPolygon); + failInternalError("Could not get outline.", $sSQL, $aPointPolygon); + } + + 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'] + ); + } + } // CONST_Search_AreaPolygons + + // 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; + } } ?> diff --git a/lib/ReverseGeocode.php b/lib/ReverseGeocode.php index 2a901e3b..3dff161e 100644 --- a/lib/ReverseGeocode.php +++ b/lib/ReverseGeocode.php @@ -9,6 +9,14 @@ protected $aLangPrefOrder = array(); + protected $bIncludePolygonAsPoints = false; + protected $bIncludePolygonAsText = false; + protected $bIncludePolygonAsGeoJSON = false; + protected $bIncludePolygonAsKML = false; + protected $bIncludePolygonAsSVG = false; + protected $fPolygonSimplificationThreshold = 0.0; + + function ReverseGeocode(&$oDB) { $this->oDB =& $oDB; @@ -58,6 +66,48 @@ $this->iMaxRank = (isset($iZoom) && isset($aZoomRank[$iZoom]))?$aZoomRank[$iZoom]:28; } + function setIncludePolygonAsPoints($b = true) + { + $this->bIncludePolygonAsPoints = $b; + } + + function getIncludePolygonAsPoints() + { + return $this->bIncludePolygonAsPoints; + } + + function setIncludePolygonAsText($b = true) + { + $this->bIncludePolygonAsText = $b; + } + + function getIncludePolygonAsText() + { + return $this->bIncludePolygonAsText; + } + + function setIncludePolygonAsGeoJSON($b = true) + { + $this->bIncludePolygonAsGeoJSON = $b; + } + + function setIncludePolygonAsKML($b = true) + { + $this->bIncludePolygonAsKML = $b; + } + + function setIncludePolygonAsSVG($b = true) + { + $this->bIncludePolygonAsSVG = $b; + } + + function setPolygonSimplificationThreshold($f) + { + $this->fPolygonSimplificationThreshold = $f; + } + + // returns { place_id =>, type => '(osm|tiger)' } + // fails if no place was found function lookup() { $sPointSQL = 'ST_SetSRID(ST_Point('.$this->fLon.','.$this->fLat.'),4326)'; @@ -86,7 +136,8 @@ if ($fSearchDiam > 0.008 && $iMaxRank > 22) $iMaxRank = 22; if ($fSearchDiam > 0.001 && $iMaxRank > 26) $iMaxRank = 26; - $sSQL = 'select place_id,parent_place_id,rank_search,calculated_country_code from placex'; + $sSQL = 'select place_id,parent_place_id,rank_search,calculated_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)'; @@ -116,9 +167,7 @@ $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'; - - // print all house numbers in the parent (street) - /*if (CONST_Debug) + if (CONST_Debug) { $sSQL = preg_replace('/limit 1/', 'limit 100', $sSQL); var_dump($sSQL); @@ -128,7 +177,7 @@ { echo $i['housenumber'] . ' | ' . $i['distance'] * 1000 . ' | ' . $i['lat'] . ' | ' . $i['lon']. ' | '. "
\n"; } - }*/ + } $aPlaceTiger = $this->oDB->getRow($sSQL); if (PEAR::IsError($aPlace)) @@ -153,7 +202,11 @@ { $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"; + $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 = $this->oDB->getOne($sSQL); if (PEAR::IsError($iPlaceID)) { @@ -166,8 +219,9 @@ } return array('place_id' => $iPlaceID, - 'type' => $bPlaceIsTiger ? 'tiger' : 'osm', - 'fraction' => $bPlaceIsTiger ? $iFraction : -1 ); + 'type' => $bPlaceIsTiger ? 'tiger' : 'osm', + 'fraction' => $bPlaceIsTiger ? $iFraction : -1); } + } ?> diff --git a/lib/init.php b/lib/init.php index 67efdbfd..26952d05 100644 --- a/lib/init.php +++ b/lib/init.php @@ -1,8 +1,5 @@ ".htmlspecialchars($aPlace['langaddress']).""; if (isset($aPlace['aAddress'])) @@ -63,6 +97,14 @@ } echo ""; } + + if (isset($aPlace['askml'])) + { + echo "\n"; + echo $aPlace['askml']; + echo ""; + } + } echo ""; diff --git a/lib/template/search-json.php b/lib/template/search-json.php index aae90622..0bfbc904 100644 --- a/lib/template/search-json.php +++ b/lib/template/search-json.php @@ -18,11 +18,7 @@ if (isset($aPointDetails['aBoundingBox'])) { - $aPlace['boundingbox'] = array( - $aPointDetails['aBoundingBox'][0], - $aPointDetails['aBoundingBox'][1], - $aPointDetails['aBoundingBox'][2], - $aPointDetails['aBoundingBox'][3]); + $aPlace['boundingbox'] = $aPointDetails['aBoundingBox']; if (isset($aPointDetails['aPolyPoints']) && $bShowPolygons) { diff --git a/lib/template/search-jsonv2.php b/lib/template/search-jsonv2.php index 8dc20219..6f23ae26 100644 --- a/lib/template/search-jsonv2.php +++ b/lib/template/search-jsonv2.php @@ -16,11 +16,7 @@ if (isset($aPointDetails['aBoundingBox'])) { - $aPlace['boundingbox'] = array( - $aPointDetails['aBoundingBox'][0], - $aPointDetails['aBoundingBox'][1], - $aPointDetails['aBoundingBox'][2], - $aPointDetails['aBoundingBox'][3]); + $aPlace['boundingbox'] = $aPointDetails['aBoundingBox']; if (isset($aPointDetails['aPolyPoints']) && $bShowPolygons) { diff --git a/lib/template/search-xml.php b/lib/template/search-xml.php index 5d8b26bc..54217933 100644 --- a/lib/template/search-xml.php +++ b/lib/template/search-xml.php @@ -36,10 +36,7 @@ if (isset($aResult['aBoundingBox'])) { echo ' boundingbox="'; - echo $aResult['aBoundingBox'][0]; - echo ','.$aResult['aBoundingBox'][1]; - echo ','.$aResult['aBoundingBox'][2]; - echo ','.$aResult['aBoundingBox'][3]; + echo join(',',$aResult['aBoundingBox']); echo '"'; if ($bShowPolygons && isset($aResult['aPolyPoints'])) diff --git a/m4/ax_lib_postgresql_svr.m4 b/m4/ax_lib_postgresql_svr.m4 deleted file mode 100644 index 56ecb5b4..00000000 --- a/m4/ax_lib_postgresql_svr.m4 +++ /dev/null @@ -1,125 +0,0 @@ -# SYNOPSIS -# -# AX_LIB_POSTGRESQL_SVR([MINIMUM-VERSION]) -# -# DESCRIPTION -# -# This macro provides tests of availability of PostgreSQL server library -# -# This macro calls: -# -# AC_SUBST(POSTGRESQL_PGXS) -# AC_SUBST(POSTGRESQL_SERVER_CFLAGS) -# -# LICENSE -# -# Copyright (c) 2008 Mateusz Loskot -# Copyright (c) 2015 Sarah Hoffmann -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. - -AC_DEFUN([AX_LIB_POSTGRESQL_SVR], -[ - AC_ARG_WITH([postgresql], - AC_HELP_STRING([--with-postgresql-svr=@<:@ARG@:>@], - [use PostgreSQL server library @<:@default=yes@:>@, optionally specify path to pg_config] - ), - [ - if test "$withval" = "no"; then - want_postgresql="no" - elif test "$withval" = "yes"; then - want_postgresql="yes" - else - want_postgresql="yes" - PG_CONFIG="$withval" - fi - ], - [want_postgresql="yes"] - ) - - dnl - dnl Check PostgreSQL server libraries - dnl - - if test "$want_postgresql" = "yes"; then - - if test -z "$PG_CONFIG" -o test; then - AC_PATH_PROG([PG_CONFIG], [pg_config], []) - fi - - if test ! -x "$PG_CONFIG"; then - AC_MSG_ERROR([$PG_CONFIG does not exist or it is not an exectuable file]) - PG_CONFIG="no" - found_postgresql="no" - fi - - if test "$PG_CONFIG" != "no"; then - AC_MSG_CHECKING([for PostgreSQL server libraries]) - - POSTGRESQL_SERVER_CFLAGS="-I`$PG_CONFIG --includedir-server`" - - POSTGRESQL_VERSION=`$PG_CONFIG --version | sed -e 's#PostgreSQL ##'` - - POSTGRESQL_PGXS=`$PG_CONFIG --pgxs` - if test -f "$POSTGRESQL_PGXS" - then - found_postgresql="yes" - AC_MSG_RESULT([yes]) - fi - else - found_postgresql="no" - AC_MSG_RESULT([no]) - fi - fi - - dnl - dnl Check if required version of PostgreSQL is available - dnl - - - postgresql_version_req=ifelse([$1], [], [], [$1]) - - if test "$found_postgresql" = "yes" -a -n "$postgresql_version_req"; then - - AC_MSG_CHECKING([if PostgreSQL version is >= $postgresql_version_req]) - - dnl Decompose required version string of PostgreSQL - dnl and calculate its number representation - postgresql_version_req_major=`expr $postgresql_version_req : '\([[0-9]]*\)'` - postgresql_version_req_minor=`expr $postgresql_version_req : '[[0-9]]*\.\([[0-9]]*\)'` - postgresql_version_req_micro=`expr $postgresql_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'` - if test "x$postgresql_version_req_micro" = "x"; then - postgresql_version_req_micro="0" - fi - - postgresql_version_req_number=`expr $postgresql_version_req_major \* 1000000 \ - \+ $postgresql_version_req_minor \* 1000 \ - \+ $postgresql_version_req_micro` - - dnl Decompose version string of installed PostgreSQL - dnl and calculate its number representation - postgresql_version_major=`expr $POSTGRESQL_VERSION : '\([[0-9]]*\)'` - postgresql_version_minor=`expr $POSTGRESQL_VERSION : '[[0-9]]*\.\([[0-9]]*\)'` - postgresql_version_micro=`expr $POSTGRESQL_VERSION : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'` - if test "x$postgresql_version_micro" = "x"; then - postgresql_version_micro="0" - fi - - postgresql_version_number=`expr $postgresql_version_major \* 1000000 \ - \+ $postgresql_version_minor \* 1000 \ - \+ $postgresql_version_micro` - - postgresql_version_check=`expr $postgresql_version_number \>\= $postgresql_version_req_number` - if test "$postgresql_version_check" = "1"; then - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - fi - fi - - AC_SUBST([POSTGRESQL_PGXS]) - AC_SUBST([POSTGRESQL_SERVER_CFLAGS]) -]) - diff --git a/m4/ax_lib_xml2.m4 b/m4/ax_lib_xml2.m4 deleted file mode 100644 index d0cd2cb5..00000000 --- a/m4/ax_lib_xml2.m4 +++ /dev/null @@ -1,150 +0,0 @@ -# SYNOPSIS -# -# AX_LIB_XML2([MINIMUM-VERSION]) -# -# DESCRIPTION -# -# This macro provides tests of availability of xml2 'libxml2' library -# of particular version or newer. -# -# AX_LIB_LIBXML2 macro takes only one argument which is optional. If -# there is no required version passed, then macro does not run version -# test. -# -# The --with-libxml2 option takes one of three possible values: -# -# no - do not check for xml2 library -# -# yes - do check for xml2 library in standard locations (xml2-config -# should be in the PATH) -# -# path - complete path to xml2-config utility, use this option if xml2-config -# can't be found in the PATH -# -# This macro calls: -# -# AC_SUBST(XML2_CFLAGS) -# AC_SUBST(XML2_LDFLAGS) -# AC_SUBST(XML2_VERSION) -# -# And sets: -# -# HAVE_XML2 -# -# LICENSE -# -# Copyright (c) 2009 Hartmut Holzgraefe -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. - -AC_DEFUN([AX_LIB_XML2], -[ - AC_ARG_WITH([libxml2], - AC_HELP_STRING([--with-libxml2=@<:@ARG@:>@], - [use libxml2 library @<:@default=yes@:>@, optionally specify path to xml2-config] - ), - [ - if test "$withval" = "no"; then - want_libxml2="no" - elif test "$withval" = "yes"; then - want_libxml2="yes" - else - want_libxml2="yes" - XML2_CONFIG="$withval" - fi - ], - [want_libxml2="yes"] - ) - - XML2_CFLAGS="" - XML2_LDFLAGS="" - XML2_VERSION="" - - dnl - dnl Check xml2 libraries (libxml2) - dnl - - if test "$want_libxml2" = "yes"; then - - if test -z "$XML2_CONFIG" -o test; then - AC_PATH_PROG([XML2_CONFIG], [xml2-config], []) - fi - - if test ! -x "$XML2_CONFIG"; then - AC_MSG_ERROR([$XML2_CONFIG does not exist or it is not an exectuable file]) - XML2_CONFIG="no" - found_libxml2="no" - fi - - if test "$XML2_CONFIG" != "no"; then - AC_MSG_CHECKING([for xml2 libraries]) - - XML2_CFLAGS="`$XML2_CONFIG --cflags`" - XML2_LDFLAGS="`$XML2_CONFIG --libs`" - - XML2_VERSION=`$XML2_CONFIG --version` - - AC_DEFINE([HAVE_XML2], [1], - [Define to 1 if xml2 libraries are available]) - - found_libxml2="yes" - AC_MSG_RESULT([yes]) - else - found_libxml2="no" - AC_MSG_RESULT([no]) - fi - fi - - dnl - dnl Check if required version of xml2 is available - dnl - - - libxml2_version_req=ifelse([$1], [], [], [$1]) - - - if test "$found_libxml2" = "yes" -a -n "$libxml2_version_req"; then - - AC_MSG_CHECKING([if libxml2 version is >= $libxml2_version_req]) - - dnl Decompose required version string of libxml2 - dnl and calculate its number representation - libxml2_version_req_major=`expr $libxml2_version_req : '\([[0-9]]*\)'` - libxml2_version_req_minor=`expr $libxml2_version_req : '[[0-9]]*\.\([[0-9]]*\)'` - libxml2_version_req_micro=`expr $libxml2_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'` - if test "x$libxml2_version_req_micro" = "x"; then - libxml2_version_req_micro="0" - fi - - libxml2_version_req_number=`expr $libxml2_version_req_major \* 1000000 \ - \+ $libxml2_version_req_minor \* 1000 \ - \+ $libxml2_version_req_micro` - - dnl Decompose version string of installed PostgreSQL - dnl and calculate its number representation - libxml2_version_major=`expr $XML2_VERSION : '\([[0-9]]*\)'` - libxml2_version_minor=`expr $XML2_VERSION : '[[0-9]]*\.\([[0-9]]*\)'` - libxml2_version_micro=`expr $XML2_VERSION : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'` - if test "x$libxml2_version_micro" = "x"; then - libxml2_version_micro="0" - fi - - libxml2_version_number=`expr $libxml2_version_major \* 1000000 \ - \+ $libxml2_version_minor \* 1000 \ - \+ $libxml2_version_micro` - - libxml2_version_check=`expr $libxml2_version_number \>\= $libxml2_version_req_number` - if test "$libxml2_version_check" = "1"; then - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - fi - fi - - AC_SUBST([XML2_VERSION]) - AC_SUBST([XML2_CFLAGS]) - AC_SUBST([XML2_LDFLAGS]) -]) - diff --git a/module/CMakeLists.txt b/module/CMakeLists.txt new file mode 100644 index 00000000..5e507a9e --- /dev/null +++ b/module/CMakeLists.txt @@ -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} make -f ${CMAKE_CURRENT_SOURCE_DIR}/Makefile + COMMENT "Running external makefile ${PGXS}" + ) + +ADD_CUSTOM_TARGET( nominatim_lib ALL + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/dummy + ) + diff --git a/module/Makefile.in b/module/Makefile similarity index 70% rename from module/Makefile.in rename to module/Makefile index fcaa41fa..783a6602 100644 --- a/module/Makefile.in +++ b/module/Makefile @@ -1,6 +1,4 @@ MODULES = nominatim -PGXS := @POSTGRESQL_PGXS@ -PG_CONFIG := @PG_CONFIG@ include $(PGXS) all: diff --git a/nominatim/CMakeLists.txt b/nominatim/CMakeLists.txt new file mode 100644 index 00000000..53b5073b --- /dev/null +++ b/nominatim/CMakeLists.txt @@ -0,0 +1,4 @@ +add_executable(nominatim export.c geometry.cpp import.c index.c input.c nominatim.c postgresql.c sprompt.c) + +target_link_libraries(nominatim ${LIBXML2_LIBRARIES} ${ZLIB_LIBRARIES} ${BZIP2_LIBRARIES} ${PostgreSQL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) + diff --git a/nominatim/Makefile.am b/nominatim/Makefile.am deleted file mode 100644 index d27ae554..00000000 --- a/nominatim/Makefile.am +++ /dev/null @@ -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_CPPFLAGS@ @XML_CPPFLAGS@ @BZIP2_CFLAGS@ @GEOS_CFLAGS@ @PROJ_CFLAGS@ -DVERSION='"@PACKAGE_VERSION@"' -AM_CPPFLAGS = @PTHREAD_CFLAGS@ @POSTGRESQL_CPPFLAGS@ @XML_CPPFLAGS@ @BZIP2_CFLAGS@ @GEOS_CFLAGS@ @PROJ_CFLAGS@ - -nominatim_LDADD = @PTHREAD_CFLAGS@ @POSTGRESQL_LDFLAGS@ @POSTGRESQL_LIBS@ @XML_LIBS@ @BZIP2_LDFLAGS@ @BZIP2_LIBS@ @GEOS_LDFLAGS@ @GEOS_LIBS@ @PROJ_LDFLAGS@ @PROJ_LIBS@ -lz - diff --git a/nominatim/nominatim.c b/nominatim/nominatim.c index 7a9e6e9e..1771be2e 100644 --- a/nominatim/nominatim.c +++ b/nominatim/nominatim.c @@ -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) { diff --git a/osm2pgsql b/osm2pgsql index 8179cdb6..d0af11f2 160000 --- a/osm2pgsql +++ b/osm2pgsql @@ -1 +1 @@ -Subproject commit 8179cdb67e70d7fb5605ab6ddedfd0bd3347db47 +Subproject commit d0af11f267a202c7c1961c2061d121c726d8db3a diff --git a/settings/settings.php b/settings/settings.php index 3427d5e0..d48aff73 100644 --- a/settings/settings.php +++ b/settings/settings.php @@ -1,10 +1,12 @@ ://:@:/ + @define('CONST_Database_DSN', 'pgsql://@/nominatim'); // ://:@:/ @define('CONST_Database_Web_User', 'www-data'); @define('CONST_Max_Word_Frequency', '50000'); @define('CONST_Limit_Reindexing', true); @@ -23,7 +25,7 @@ // 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_Osm2pgsql_Binary', CONST_InstallPath.'/osm2pgsql/osm2pgsql'); @define('CONST_Osmosis_Binary', '/usr/bin/osmosis'); @define('CONST_Tiger_Data_Path', CONST_BasePath.'/data/tiger'); diff --git a/tests-php/Nominatim/NominatimTest.php b/tests-php/Nominatim/NominatimTest.php index 129fa012..8213be00 100644 --- a/tests-php/Nominatim/NominatimTest.php +++ b/tests-php/Nominatim/NominatimTest.php @@ -12,6 +12,51 @@ class NominatimTest extends \PHPUnit_Framework_TestCase } + public function test_getClassTypesWithImportance() + { + $aClasses = getClassTypesWithImportance(); + + $this->assertGreaterThan( + 200, + count($aClasses) + ); + + $this->assertEquals( + array( + 'label' => "Country", + 'frequency' => 0, + 'icon' => "poi_boundary_administrative", + 'defzoom' => 6, + 'defdiameter' => 15, + 'importance' => 3 + ), + $aClasses['place:country'] + ); + } + + + public function test_getResultDiameter() + { + $aResult = array(); + $this->assertEquals( + 0.0001, + getResultDiameter($aResult) + ); + + $aResult = array('class' => 'place', 'type' => 'country'); + $this->assertEquals( + 15, + getResultDiameter($aResult) + ); + + $aResult = array('class' => 'boundary', 'type' => 'administrative', 'admin_level' => 6); + $this->assertEquals( + 0.32, + getResultDiameter($aResult) + ); + } + + public function test_addQuotes() { // FIXME: not quoting existing quote signs is probably a bug @@ -142,6 +187,7 @@ class NominatimTest extends \PHPUnit_Framework_TestCase 65536, count( getWordSets(array_fill( 0, 18, 'a'),0) ) ); + } } @@ -206,8 +252,71 @@ class NominatimTest extends \PHPUnit_Framework_TestCase geometryText2Points('MULTIPOLYGON(((30 20, 45 40, 10 40, 30 20)),((15 5, 40 10, 10 20, 5 10, 15 5)))', $fRadius) ); + // you might say we're creating a circle + public function test_createPointsAroundCenter() + { + $aPoints = createPointsAroundCenter(0, 0, 2); + $this->assertEquals( + 101, + count($aPoints) + ); + $this->assertEquals( + array( + ['', 0, 2], + ['', 0.12558103905863, 1.9960534568565], + ['', 0.25066646712861, 1.984229402629] + ), + array_splice($aPoints, 0, 3) + ); } + public function test_geometryText2Points() + { + $fRadius = 1; + // invalid value + $this->assertEquals( + NULL, + geometryText2Points('', $fRadius) + ); + + // POINT + $aPoints = geometryText2Points('POINT(10 20)', $fRadius); + $this->assertEquals( + 101, + count($aPoints) + ); + $this->assertEquals( + array( + [10, 21], + [10.062790519529, 20.998026728428], + [10.125333233564, 20.992114701314] + ), + array_splice($aPoints, 0,3) + ); + + // POLYGON + $this->assertEquals( + array( + ['30', '10'], + ['40', '40'], + ['20', '40'], + ['10', '20'], + ['30', '10'] + ), + geometryText2Points('POLYGON((30 10, 40 40, 20 40, 10 20, 30 10))', $fRadius) + ); + + // MULTIPOLYGON + $this->assertEquals( + array( + ['30', '20'], // first polygon only + ['45', '40'], + ['10', '40'], + ['30', '20'], + ), + geometryText2Points('MULTIPOLYGON(((30 20, 45 40, 10 40, 30 20)),((15 5, 40 10, 10 20, 5 10, 15 5)))', $fRadius) + ); + } } diff --git a/tests/features/api/reverse.feature b/tests/features/api/reverse.feature index fa636acf..39519177 100644 --- a/tests/features/api/reverse.feature +++ b/tests/features/api/reverse.feature @@ -11,6 +11,15 @@ Feature: Reverse geocoding | ID | country | 0 | Deutschland + + Scenario: Boundingbox is returned + Given the request parameters + | format | zoom + | xml | 4 + When looking up coordinates 53.9788769,13.0830313 + And results contain valid boundingboxes + + @Tiger Scenario: TIGER house number Given the request parameters @@ -61,3 +70,75 @@ Feature: Reverse geocoding | xml | json | jsonv2 + + + Scenario Outline: Reverse Geocoding contains TEXT geometry + Given the request parameters + | polygon_text + | 1 + When looking up coordinates 48.86093,2.2978 + Then result 0 has attributes + + Examples: + | format | response_attribute + | xml | geotext + | json | geotext + | jsonv2 | geotext + + Scenario Outline: Reverse Geocoding contains polygon-as-points geometry + Given the request parameters + | polygon + | 1 + When looking up coordinates 48.86093,2.2978 + Then result 0 has not attributes + + Examples: + | format | response_attribute + | xml | polygonpoints + | json | polygonpoints + | jsonv2 | polygonpoints + + + + Scenario Outline: Reverse Geocoding contains SVG geometry + Given the request parameters + | polygon_svg + | 1 + When looking up coordinates 48.86093,2.2978 + Then result 0 has attributes + + Examples: + | format | response_attribute + | xml | geosvg + | json | svg + | jsonv2 | svg + + + Scenario Outline: Reverse Geocoding contains KML geometry + Given the request parameters + | polygon_kml + | 1 + When looking up coordinates 48.86093,2.2978 + Then result 0 has attributes + + Examples: + | format | response_attribute + | xml | geokml + | json | geokml + | jsonv2 | geokml + + + Scenario Outline: Reverse Geocoding contains GEOJSON geometry + Given the request parameters + | polygon_geojson + | 1 + When looking up coordinates 48.86093,2.2978 + Then result 0 has attributes + + Examples: + | format | response_attribute + | xml | geojson + | json | geojson + | jsonv2 | geojson + + diff --git a/tests/features/api/reverse_simple.feature b/tests/features/api/reverse_simple.feature index 8621ec65..5d79fd4b 100644 --- a/tests/features/api/reverse_simple.feature +++ b/tests/features/api/reverse_simple.feature @@ -17,6 +17,49 @@ Feature: Simple Reverse Tests | -79.34 | 23.5 | 0.23 | -178.555 + Scenario Outline: Testing different parameters + Given the request parameters + | + | + When sending search query "Manchester" + Then the result is valid html + Given the request parameters + | + | + When sending html search query "Manchester" + Then the result is valid html + Given the request parameters + | + | + When sending xml search query "Manchester" + Then the result is valid xml + Given the request parameters + | + | + When sending json search query "Manchester" + Then the result is valid json + Given the request parameters + | + | + When sending jsonv2 search query "Manchester" + 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 Given the request parameters | json_callback diff --git a/tests/features/api/search_params.feature b/tests/features/api/search_params.feature index 7099c72f..150d6bdc 100644 --- a/tests/features/api/search_params.feature +++ b/tests/features/api/search_params.feature @@ -8,6 +8,7 @@ Feature: Search queries 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 results contain valid boundingboxes Scenario: Simple JSON search When sending json search query "Vaduz" @@ -15,6 +16,7 @@ Feature: Search queries 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 results contain valid boundingboxes Scenario: JSON search with addressdetails When sending json search query "Montevideo" with address @@ -230,3 +232,73 @@ Feature: Search queries | xml | json | jsonv2 + + + Scenario Outline: Search result with contains TEXT geometry + Given the request parameters + | polygon_text + | 1 + When sending search query "switzerland" + Then result 0 has attributes + + Examples: + | format | response_attribute + | xml | geotext + | json | geotext + | jsonv2 | geotext + + Scenario Outline: Search result contains polygon-as-points geometry + Given the request parameters + | polygon + | 1 + When sending search query "switzerland" + Then result 0 has attributes + + Examples: + | format | response_attribute + | xml | polygonpoints + | json | polygonpoints + | jsonv2 | polygonpoints + + + + Scenario Outline: Search result contains SVG geometry + Given the request parameters + | polygon_svg + | 1 + When sending search query "switzerland" + Then result 0 has attributes + + Examples: + | format | response_attribute + | xml | geosvg + | json | svg + | jsonv2 | svg + + + Scenario Outline: Search result contains KML geometry + Given the request parameters + | polygon_kml + | 1 + When sending search query "switzerland" + Then result 0 has attributes + + Examples: + | format | response_attribute + | xml | geokml + | json | geokml + | jsonv2 | geokml + + + Scenario Outline: Search result contains GEOJSON geometry + Given the request parameters + | polygon_geojson + | 1 + When sending search query "switzerland" + Then result 0 has attributes + + Examples: + | format | response_attribute + | xml | geojson + | json | geojson + | jsonv2 | geojson diff --git a/tests/steps/api_result.py b/tests/steps/api_result.py index 4910c157..2644d4a2 100644 --- a/tests/steps/api_result.py +++ b/tests/steps/api_result.py @@ -98,6 +98,8 @@ def _parse_xml(): attrs = dict(tag.attributes.items()) assert_in('desc', attrs) world.results[0]['namedetails'][attrs['desc']] = tag.firstChild.nodeValue.strip() + elif node.nodeName == "geokml": + world.results[0]['geokml'] = node elif node.nodeName == "#text": pass else: @@ -209,6 +211,15 @@ def api_result_contains(step): m = re.match("%s$" % (v,), curres[k]) assert_is_not_none(m, msg="field %s does not match: %s$ != %s." % (k, v, curres[k])) +@step(u'results contain valid boundingboxes$') +def api_result_address_contains(step): + step.given('the result is valid') + for curres in world.results: + bb = curres['boundingbox'] + if world.response_format == 'json': + bb = ','.join(bb) + m = re.match('^(-?\d+\.\d+),(-?\d+\.\d+),(-?\d+\.\d+),(-?\d+\.\d+)$', bb) + assert_is_not_none(m, msg="invalid boundingbox: %s." % (curres['boundingbox'])) @step(u'result addresses contain$') def api_result_address_contains(step): diff --git a/tests/steps/db_results.py b/tests/steps/db_results.py index c3ac9445..71a30927 100644 --- a/tests/steps/db_results.py +++ b/tests/steps/db_results.py @@ -11,7 +11,6 @@ import psycopg2 import psycopg2.extensions import psycopg2.extras import os -import subprocess import random import json import re diff --git a/tests/steps/db_setup.py b/tests/steps/db_setup.py index e1315ed9..8041c6cc 100644 --- a/tests/steps/db_setup.py +++ b/tests/steps/db_setup.py @@ -266,7 +266,8 @@ def query_cmd(step, query, with_dups): '--search', query] if with_dups is not None: cmd.append('--nodedupe') - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + proc = subprocess.Popen(cmd, cwd=world.config.source_dir, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) (outp, err) = proc.communicate() assert (proc.returncode == 0), "query.php failed with message: %s" % err world.page = outp diff --git a/tests/steps/osm2pgsql_setup.py b/tests/steps/osm2pgsql_setup.py index eaa14573..4b03b1ea 100644 --- a/tests/steps/osm2pgsql_setup.py +++ b/tests/steps/osm2pgsql_setup.py @@ -155,7 +155,8 @@ def osm2pgsql_load_place(step): cmd = [os.path.join(world.config.source_dir, 'utils', 'setup.php')] cmd.extend(['--osm-file', fname, '--import-data','--osm2pgsql-cache', '300']) - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + proc = subprocess.Popen(cmd, cwd=world.config.source_dir, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) (outp, outerr) = proc.communicate() assert (proc.returncode == 0), "OSM data import failed:\n%s\n%s\n" % (outp, outerr) @@ -204,7 +205,8 @@ def osm2pgsql_update_place(step): cmd = [os.path.join(world.config.source_dir, 'utils', 'update.php')] cmd.extend(['--import-diff', fname]) - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + proc = subprocess.Popen(cmd, cwd=world.config.source_dir, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) (outp, outerr) = proc.communicate() assert (proc.returncode == 0), "OSM data update failed:\n%s\n%s\n" % (outp, outerr) diff --git a/tests/steps/terrain.py b/tests/steps/terrain.py index e9561d1a..349deafe 100644 --- a/tests/steps/terrain.py +++ b/tests/steps/terrain.py @@ -23,7 +23,7 @@ class NominatimConfig: logging.basicConfig(level=loglevel) # Nominatim test setup self.base_url = os.environ.get('NOMINATIM_SERVER', 'http://localhost/nominatim') - self.source_dir = os.path.abspath(os.environ.get('NOMINATIM_DIR', '..')) + self.source_dir = os.path.abspath(os.environ.get('NOMINATIM_DIR', '../build')) self.template_db = os.environ.get('TEMPLATE_DB', 'test_template_nominatim') self.test_db = os.environ.get('TEST_DB', 'test_nominatim') self.local_settings_file = os.environ.get('NOMINATIM_SETTINGS', '/tmp/nominatim_settings.php') @@ -52,7 +52,8 @@ def write_nominatim_config(dbname): def run_nominatim_script(script, *args): cmd = [os.path.join(world.config.source_dir, 'utils', '%s.php' % script)] cmd.extend(['--%s' % x for x in args]) - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + proc = subprocess.Popen(cmd, cwd=world.config.source_dir, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) (outp, outerr) = proc.communicate() assert (proc.returncode == 0), "Script '%s' failed:\n%s\n%s\n" % (script, outp, outerr) @@ -176,8 +177,9 @@ def db_template_setup(): conn.close() # execute osm2pgsql on an empty file to get the right tables osm2pgsql = os.path.join(world.config.source_dir, 'osm2pgsql', 'osm2pgsql') - proc = subprocess.Popen([osm2pgsql, '-lsc', '-O', 'gazetteer', '-d', world.config.template_db, '-'], - stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + proc = subprocess.Popen([osm2pgsql, '-lsc', '-r', 'xml', '-O', 'gazetteer', '-d', world.config.template_db, '-'], + cwd=world.config.source_dir, stdin=subprocess.PIPE, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) [outstr, errstr] = proc.communicate(input='') world.run_nominatim_script('setup', 'create-functions', 'create-tables', 'create-partition-tables', 'create-partition-functions', 'load-data', 'create-search-indices') diff --git a/utils/blocks.php b/utils/blocks.php index bd5efd00..28c48c58 100755 --- a/utils/blocks.php +++ b/utils/blocks.php @@ -1,8 +1,9 @@ #!/usr/bin/php -Cq 1000) fail("unable to obtain state file"); - file_put_contents(CONST_BasePath.'/settings/state.txt', $sStateFile); + file_put_contents(CONST_InstallPath.'/settings/state.txt', $sStateFile); echo "Updating DB status\n"; pg_query($oDB->connection, 'TRUNCATE import_status'); $sSQL = "INSERT INTO import_status VALUES('".$aRepMatch[2]."')"; @@ -657,7 +658,7 @@ $bDidSomething = true; $sOutputFile = ''; if (isset($aCMDResult['index-output'])) $sOutputFile = ' -F '.$aCMDResult['index-output']; - $sBaseCmd = CONST_BasePath.'/nominatim/nominatim -i -d '.$aDSNInfo['database'].' -P '.$aDSNInfo['port'].' -t '.$iInstances.$sOutputFile; + $sBaseCmd = CONST_InstallPath.'/nominatim/nominatim -i -d '.$aDSNInfo['database'].' -P '.$aDSNInfo['port'].' -t '.$iInstances.$sOutputFile; passthruCheckReturn($sBaseCmd.' -R 4'); if (!$aCMDResult['index-noanalyse']) pgsqlRunScript('ANALYSE'); passthruCheckReturn($sBaseCmd.' -r 5 -R 25'); @@ -709,14 +710,14 @@ fail("Target directory does not exist."); } - @symlink(CONST_BasePath.'/website/details.php', $sTargetDir.'/details.php'); - @symlink(CONST_BasePath.'/website/reverse.php', $sTargetDir.'/reverse.php'); - @symlink(CONST_BasePath.'/website/search.php', $sTargetDir.'/search.php'); - @symlink(CONST_BasePath.'/website/search.php', $sTargetDir.'/index.php'); - @symlink(CONST_BasePath.'/website/lookup.php', $sTargetDir.'/lookup.php'); - @symlink(CONST_BasePath.'/website/deletable.php', $sTargetDir.'/deletable.php'); - @symlink(CONST_BasePath.'/website/polygons.php', $sTargetDir.'/polygons.php'); - @symlink(CONST_BasePath.'/website/status.php', $sTargetDir.'/status.php'); + @symlink(CONST_InstallPath.'/website/details.php', $sTargetDir.'/details.php'); + @symlink(CONST_InstallPath.'/website/reverse.php', $sTargetDir.'/reverse.php'); + @symlink(CONST_InstallPath.'/website/search.php', $sTargetDir.'/search.php'); + @symlink(CONST_InstallPath.'/website/search.php', $sTargetDir.'/index.php'); + @symlink(CONST_InstallPath.'/website/lookup.php', $sTargetDir.'/lookup.php'); + @symlink(CONST_InstallPath.'/website/deletable.php', $sTargetDir.'/deletable.php'); + @symlink(CONST_InstallPath.'/website/polygons.php', $sTargetDir.'/polygons.php'); + @symlink(CONST_InstallPath.'/website/status.php', $sTargetDir.'/status.php'); @symlink(CONST_BasePath.'/website/images', $sTargetDir.'/images'); @symlink(CONST_BasePath.'/website/js', $sTargetDir.'/js'); @symlink(CONST_BasePath.'/website/css', $sTargetDir.'/css'); diff --git a/utils/specialphrases.php b/utils/specialphrases.php index 97b60dde..189a7a3e 100755 --- a/utils/specialphrases.php +++ b/utils/specialphrases.php @@ -1,9 +1,10 @@ #!/usr/bin/php -Cq /etc/sudoers.d/99-$USERNAME-user +# chmod 0440 /etc/sudoers.d/99-$USERNAME-user +# service sudo restart +# +# # add basic .profile +# cp -r .ssh .profile .bashrc /home/$USERNAME/ +# chown -R $USERNAME /home/$USERNAME/.* +# chgrp -R $USERNAME /home/$USERNAME/.* +# +# # now ideally login as $USERNAME and continue +# su $USERNAME -l +# fi + + +sudo apt-get update -qq +sudo apt-get upgrade -y +sudo apt-get install -y build-essential libgeos-dev libpq-dev libbz2-dev \ + libtool automake libproj-dev libboost-dev libboost-system-dev \ + libboost-filesystem-dev libboost-thread-dev libexpat-dev +sudo apt-get autoremove -y + +# get arrow-keys working in terminal (e.g. editing in vi) +echo 'stty sane' >> ~/.bash_profile +echo 'export TERM=linux' >> ~/.bash_profile +source ~/.bash_profile + + +### +### PostgreSQL 9.3 + PostGIS 2.1 +### + +sudo apt-get install -y postgresql-9.3-postgis-2.1 postgresql-contrib-9.3 postgresql-server-dev-9.3 +# already included: proj-bin libgeos-dev + +# make sure OS-authenticated users (e.g. $USERNAME) can access +sudo sed -i "s/ident/trust/" /etc/postgresql/9.3/main/pg_hba.conf +sudo sed -i "s/md5/trust/" /etc/postgresql/9.3/main/pg_hba.conf +sudo sed -i "s/peer/trust/" /etc/postgresql/9.3/main/pg_hba.conf +sudo /etc/init.d/postgresql restart + +# creates the role +sudo -u postgres createuser -s $USERNAME + + + +### +### PHP for frontend +### +sudo LC_ALL=C.UTF-8 add-apt-repository -y ppa:ondrej/php +sudo apt-get update -qq +sudo apt-get install -y apache2 +sudo apt-get install -y php7.0 php7.0-pgsql php7.0-fpm libapache2-mod-php7.0 php-pear php-db + + +# get rid of some warning +# where is the ini file? 'php --ini' +echo "date.timezone = 'Etc/UTC'" | sudo tee /etc/php/7.0/cli/conf.d/99-timezone.ini > /dev/null + + + +### +### Nominatim +### +sudo apt-get install -y libgeos-c1 libgeos++-dev libxml2-dev + +## Part 2: Nominatim installaion + +# now ideally login as $USERNAME and continue +cd /home/$USERNAME + +# If the Nominatim source is not being shared with the host, check out source. +if [ ! -d "Nominatim" ]; then + sudo apt-get install -y git + sudo -u $USERNAME git clone --recursive https://github.com/twain47/Nominatim.git +fi + +cd Nominatim + +sudo -u $USERNAME ./autogen.sh +sudo -u $USERNAME ./configure +sudo -u $USERNAME make +chmod +x ./ +chmod +x ./module + + +LOCALSETTINGS_FILE='settings/local.php' +if [[ -e "$LOCALSETTINGS_FILE" ]]; then + echo "$LOCALSETTINGS_FILE already exist, writing to settings/local-vagrant.php instead." + LOCALSETTINGS_FILE='settings/local-vagrant.php' +fi + +# IP=`curl -s http://bot.whatismyipaddress.com` +IP=localhost +echo " $LOCALSETTINGS_FILE + + + + + + + +### +### Setup Apache/website +### + +sudo -u postgres createuser -SDR www-data + +echo ' +Listen 8089 + + # DirectoryIndex index.html + # ErrorDocument 403 /index.html + + DocumentRoot "/var/www/" + + + Options FollowSymLinks MultiViews + AddType text/html .php + + +' | sudo tee /etc/apache2/sites-enabled/nominatim.conf > /dev/null + + +service apache2 graceful + + +mkdir -m 755 /var/www/nominatim +chown $USERNAME /var/www/nominatim +sudo -u $USERNAME ./utils/setup.php --create-website /var/www/nominatim + + +# if you get 'permission denied for relation word', then try +# GRANT usage ON SCHEMA public TO "www-data"; +# GRANT SELECT ON ALL TABLES IN SCHEMA public TO "www-data"; + +## +## Test suite (Python) +## https://github.com/twain47/Nominatim/tree/master/tests +## +apt-get install -y python-dev python-pip python-Levenshtein python-shapely \ + python-psycopg2 tidy python-nose python-tidylib +pip install certifi # deals with "SNI extension to TLS is not available" warning +pip install lettuce==0.2.18 six==1.7 haversine +pip install --upgrade pip setuptools + +## Test suite (PHP) +## https://github.com/twain47/Nominatim/tree/master/tests-php +wget --quiet https://phar.phpunit.de/phpunit.phar +chmod +x phpunit.phar +mv phpunit.phar /usr/local/bin/phpunit + diff --git a/vagrant/ubuntu-trusty-provision.sh b/vagrant/ubuntu-trusty-provision.sh index 84e98e23..8e35bf7d 100755 --- a/vagrant/ubuntu-trusty-provision.sh +++ b/vagrant/ubuntu-trusty-provision.sh @@ -36,7 +36,7 @@ USERNAME=vagrant sudo apt-get update -qq sudo apt-get upgrade -y sudo apt-get install -y build-essential libgeos-dev libpq-dev libbz2-dev \ - libtool automake libproj-dev libboost-dev libboost-system-dev \ + libtool cmake libproj-dev libboost-dev libboost-system-dev \ libboost-filesystem-dev libboost-thread-dev libexpat-dev sudo apt-get autoremove -y @@ -89,13 +89,13 @@ cd /home/$USERNAME # If the Nominatim source is not being shared with the host, check out source. if [ ! -d "Nominatim" ]; then sudo apt-get install -y git - sudo -u $USERNAME git clone --recursive https://github.com/twain47/Nominatim.git + sudo -H -u $USERNAME git clone --recursive https://github.com/twain47/Nominatim.git fi cd Nominatim - -sudo -u $USERNAME ./autogen.sh -sudo -u $USERNAME ./configure +sudo -u $USERNAME mkdir build-vagrant +cd build-vagrant +sudo -u $USERNAME cmake .. sudo -u $USERNAME make chmod +x ./ chmod +x ./module @@ -147,7 +147,7 @@ Listen 8089 ' | sudo tee /etc/apache2/sites-enabled/nominatim.conf > /dev/null -apache2ctl graceful +service apache2 graceful mkdir -m 755 /var/www/nominatim diff --git a/website/deletable.php b/website/deletable.php index 5d6ee15d..3283bb83 100755 --- a/website/deletable.php +++ b/website/deletable.php @@ -1,5 +1,6 @@ CONST_PolygonOutput_MaximumTypes) + { + if (CONST_PolygonOutput_MaximumTypes) + { + userError("Select only ".CONST_PolygonOutput_MaximumTypes." polgyon output option"); + } + else + { + userError("Polygon output is disabled"); + } + exit; + } + + + // Polygon simplification threshold (optional) + $fThreshold = 0.0; + if (isset($_GET['polygon_threshold'])) $fThreshold = (float)$_GET['polygon_threshold']; + + $oDB =& getDB(); ini_set('memory_limit', '200M'); @@ -63,6 +94,21 @@ $oPlaceLookup->setIncludeNameDetails(getParamBool('namedetails', false)); $aPlace = $oPlaceLookup->lookupPlace($aLookup); + + $oPlaceLookup->setIncludePolygonAsPoints($bAsPoints); + $oPlaceLookup->setIncludePolygonAsText($bAsText); + $oPlaceLookup->setIncludePolygonAsGeoJSON($bAsGeoJSON); + $oPlaceLookup->setIncludePolygonAsKML($bAsKML); + $oPlaceLookup->setIncludePolygonAsSVG($bAsSVG); + $oPlaceLookup->setPolygonSimplificationThreshold($fThreshold); + + $fRadius = $fDiameter = getResultDiameter($aPlace); + $aOutlineResult = $oPlaceLookup->getOutlines($aPlace['place_id'], $aPlace['lon'], $aPlace['lat'], $fRadius); + + if ($aOutlineResult) + { + $aPlace = array_merge($aPlace, $aOutlineResult); + } } else { diff --git a/website/search.php b/website/search.php index c216c884..8b160f8f 100755 --- a/website/search.php +++ b/website/search.php @@ -1,7 +1,8 @@ setLanguagePreference($aLangPrefOrder); diff --git a/website/status.php b/website/status.php index 832f4600..f4e696a4 100644 --- a/website/status.php +++ b/website/status.php @@ -1,7 +1,8 @@