mirror of
https://github.com/klokantech/tileserver-php.git
synced 2025-08-29 01:00:34 +02:00
Compare commits
22 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
324129f8f8 | ||
|
59c2d03552 | ||
|
bd8c6b286f | ||
|
8fa1bfcbab | ||
|
41dd3ec847 | ||
|
b7b41e9725 | ||
|
ff7c48f0b0 | ||
|
780e1c6796 | ||
|
fcf88d62c0 | ||
|
ad902c1a46 | ||
|
d241d32716 | ||
|
4eee2225db | ||
|
121308fbf8 | ||
|
1aeb3bdb8c | ||
|
82414cb082 | ||
|
0d4d50ab9c | ||
|
efcb733670 | ||
|
184a363778 | ||
|
edce8b391b | ||
|
754de66927 | ||
|
ab4980c06b | ||
|
555154b2d8 |
99
.htaccess
Normal file
99
.htaccess
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
# tileserver.php integration with Apache via .htaccess
|
||||||
|
|
||||||
|
# Restrictions for data crawlers
|
||||||
|
Options -Indexes
|
||||||
|
Options +FollowSymLinks
|
||||||
|
Options -MultiViews
|
||||||
|
|
||||||
|
# Optional CORS header for cross-domain origin access to all data
|
||||||
|
#<ifModule mod_headers.c>
|
||||||
|
# Header set Access-Control-Allow-Origin *
|
||||||
|
#</ifModule>
|
||||||
|
|
||||||
|
# Mapping of the WMTS standardized URLs to real files and XML capabilities to tileserver.php
|
||||||
|
|
||||||
|
RewriteEngine On
|
||||||
|
|
||||||
|
# WMTS RESTful
|
||||||
|
# ------------
|
||||||
|
# The file can be accessed directly:
|
||||||
|
# Example: http://www.tileserver.com/grandcanyon/10/192/401.png
|
||||||
|
|
||||||
|
# map /wmts/layer/[ANYTHING]z/x/y.ext -> /layer/z/x/y.ext (WMTS ignoring tilematrixset,style,..)
|
||||||
|
# BTW This is used only by Gaia which ignores the <ResourceURL template="...">
|
||||||
|
RewriteRule ^wmts/([\w\d\._-]+)/.*?(\d+)/(\d+)/(\d+)\.(\w+)$ $1/$2/$4/$3.$5 [L]
|
||||||
|
# Example: http://www.tileserver.com/wmts/grandcanyon/style/tilematrixset/10/192/401.png
|
||||||
|
|
||||||
|
# map /layer/[ANYTHING]z/x/y.ext -> /layer/z/x/y.ext (WMTS ignoring tilematrix,style,..)
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
|
RewriteRule ^([\w\d\._-]+)/.+?(\d+)/(\d+)/(\d+)\.(\w+)$ $1/$2/$3/$4.$5 [L]
|
||||||
|
# Example: http://www.tileserver.com/grandcanyon/style/tilematrixset/10/192/401.png
|
||||||
|
|
||||||
|
# rewrite .jpeg -> .jpg
|
||||||
|
RewriteRule ^(.+).jpeg$ $1.jpg [L]
|
||||||
|
|
||||||
|
# MBTiles support at /layer/z/x/y.ext - loads the tile from mbtiles with php
|
||||||
|
# TODO: serve also 404 errors for tiles
|
||||||
|
RewriteRule ^([^\/]+\.mbtiles)\/.*?(\d+)\/(\d+)\/(\d+)\.(\w+)$ tileserver-mbtiles.php?tileset=$1&z=$2&x=$3&y=$4&ext=$5 [L]
|
||||||
|
RewriteRule ^([^\/]+\.mbtiles)\/.*?(\d+)\/(\d+)\/(\d+)\.grid.json?$ tileserver-mbtiles.php?tileset=$1&z=$2&x=$3&y=$4&ext=grid [QSA,L]
|
||||||
|
# TODO: use mod_sqlite if available to map the tiles to URL directly by apache
|
||||||
|
|
||||||
|
# WMTS KVP
|
||||||
|
# --------
|
||||||
|
# map the /?key=value&... -> /layer/z/x/y.ext KVP getTile queries directly to files
|
||||||
|
|
||||||
|
# format passed as mime-extension, cleaning formats (jpeg->jpg)
|
||||||
|
RewriteCond %{QUERY_STRING} ^(.*)format=image/jpeg(.*)$ [NC]
|
||||||
|
RewriteRule ^(.*)$ $1?%1format=jpg%2 [N]
|
||||||
|
RewriteCond %{QUERY_STRING} ^(.*)format=jpeg(.*)$ [NC]
|
||||||
|
RewriteRule ^(.*)$ $1?%1format=jpg%2 [N]
|
||||||
|
RewriteCond %{QUERY_STRING} ^(.*)format=image/png(.*)$ [NC]
|
||||||
|
RewriteRule ^(.*)$ $1?%1format=png%2 [N]
|
||||||
|
|
||||||
|
# variable order of keys: TODO: sort the same way as mime-extension to fixed order
|
||||||
|
RewriteCond %{QUERY_STRING} ^.*request=gettile.*layer=([\w\d\._-]+).*tilematrix=(\d+).*tilerow=(\d+).*tilecol=(\d+).*format=(\w+).*$ [NC]
|
||||||
|
RewriteRule ^ %1/%2/%3/%4.%5 [L]
|
||||||
|
RewriteCond %{QUERY_STRING} ^.*request=gettile.*layer=([\w\d\._-]+).*format=(\w+).*tilematrix=(\d+).*tilerow=(\d+).*tilecol=(\d+).*$ [NC]
|
||||||
|
RewriteRule ^ %1/%3/%5/%4.%2 [L]
|
||||||
|
RewriteCond %{QUERY_STRING} ^.*request=gettile.*layer=([\w\d\._-]+).*tilematrix=(\d+).*tilecol=(\d+).*tilerow=(\d+).*format=(\w+).*$ [NC]
|
||||||
|
RewriteRule ^ %1/%2/%4/%3.%5 [L]
|
||||||
|
# Example: http://www.tileserver.com/wmts?request=getTile&layer=grandcanyon&tileMatrix=10&tilerow=192&tilecol=401&format=png
|
||||||
|
# Example: http://www.tileserver.com/wmts?service=WMTS&request=GetTile&version=1.0.0&layer=ne2geo&style=&format=image/jpeg&TileMatrixSet=WGS84&TileMatrix=1&TileRow=2&TileCol=2
|
||||||
|
|
||||||
|
# WMTS ServiceMetadata (GetCapabilities)
|
||||||
|
# --------------------------------------
|
||||||
|
RewriteRule ^.*WMTSCapabilities.xml$ tileserver-wmts.php [QSA,L]
|
||||||
|
RewriteRule ^wmts$ tileserver-wmts.php [QSA,L]
|
||||||
|
RewriteCond %{QUERY_STRING} ^.*request=getcapabilities.*$ [NC]
|
||||||
|
RewriteRule ^ tileserver-wmts.php [L]
|
||||||
|
# Example: http://www.tileserver.com/dev/?service=WMTS&version=1.0.0&request=GetCapabilities
|
||||||
|
|
||||||
|
# TMS XML (ArcBruTile)
|
||||||
|
# --------------------
|
||||||
|
RewriteRule ^tms$ tileserver-tms.php [QSA,L]
|
||||||
|
RewriteRule ^(.+)/tms$ tileserver-tms.php?layer=$1 [QSA,L]
|
||||||
|
# Example: http://www.tileserver.com/dev/?service=WMTS&version=1.0.0&request=GetCapabilities
|
||||||
|
|
||||||
|
# request for non-existent tiles -> layer/none.png or none.png
|
||||||
|
#RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
|
#RewriteRule ^([\w\d\._-]+)/(\d+)/(\d+)/(\d+)\.png$ $1/none.png [L]
|
||||||
|
#RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
|
#RewriteRule ^([\w\d\._-]+)/none\.png$ none.png [L]
|
||||||
|
|
||||||
|
# request for non-existent tiles -> layer/none.jpg or none.jpg
|
||||||
|
#RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
|
#RewriteRule ^([\w\d\._-]+)/(\d+)/(\d+)/(\d+)\.jpg$ $1/none.jpg [L]
|
||||||
|
#RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
|
#RewriteRule ^([\w\d\._-]+)/none\.jpg$ none.jpg [L]
|
||||||
|
|
||||||
|
# TileJSON JSONP wrapper for MapBOX.js API
|
||||||
|
RewriteRule ^maps.jsonp?$ tileserver.php?service=json [QSA,L]
|
||||||
|
RewriteCond %{REQUEST_URI} !\.grid\.json [NC]
|
||||||
|
RewriteRule ^(.+).jsonp?$ tileserver.php?service=json&layer=$1 [QSA,L]
|
||||||
|
|
||||||
|
# If-Modified-Since (if php is not installed as cgi then comment lines below)
|
||||||
|
#RewriteRule .* - [E=HTTP_IF_MODIFIED_SINCE:%{HTTP:If-Modified-Since}]
|
||||||
|
#RewriteRule .* - [E=HTTP_IF_NONE_MATCH:%{HTTP:If-None-Match}]
|
||||||
|
|
||||||
|
# handle all request on the root '/' by tileserver.php
|
||||||
|
RewriteRule ^$ tileserver.php?service=html [QSA,L]
|
260
README.md
260
README.md
@@ -1,4 +1,258 @@
|
|||||||
tileserver.php
|
=================================================
|
||||||
==============
|
TileServer PHP - OGC Web Map Tiling Server (WMTS)
|
||||||
|
=================================================
|
||||||
|
|
||||||
Easy to install OGC WMTS compliant map tile server for pre-rendered maps made with MapTiler / TileMill / MBTiles
|
This server distributes maps to desktop, web, and mobile applications from
|
||||||
|
a standard Apache+PHP web hosting.
|
||||||
|
|
||||||
|
It is a free and open-source project implementing OGC WMTS standard for
|
||||||
|
pre-rendered map tiles made with [MapTiler](http://www.maptiler.com/), GDAL2Tiles,
|
||||||
|
or available as MBTiles files.
|
||||||
|
|
||||||
|
It is the easiest and cheapest way how to serve zoomable maps in a
|
||||||
|
standardized way - practically from any ordinary web hosting.
|
||||||
|
|
||||||
|
It is easy to install - just copy the project files to a PHP-enabled
|
||||||
|
directory along with your map data containing metadata.json file.
|
||||||
|
|
||||||
|
It comes with an online interface showing the list of the maps and step-by-step guides for desktop GIS software:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
This project is developed in PHP, not because it is the best language for
|
||||||
|
development of web applications, but because it maximally simplify the
|
||||||
|
deployment on large number of web hosting providers including various free
|
||||||
|
web hostings.
|
||||||
|
|
||||||
|
Tiles are served directly by Apache with mod_rewrite rules as static files
|
||||||
|
and therefore are very fast and with correct HTTP caching headers.
|
||||||
|
Only XML metadata are delivered via PHP.
|
||||||
|
MBTiles are served via PHP, unless they are unpacked with mbutil.
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- Apache webserver (with mod_rewrite / .htaccess supported)
|
||||||
|
- PHP 5.2+
|
||||||
|
|
||||||
|
(or anther webserver implementing mod_rewrite rules and PHP)
|
||||||
|
|
||||||
|
Installation:
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Download the project files as a zip archive or source code from GitHub and
|
||||||
|
unpack it into a web-hosting of your choice.
|
||||||
|
|
||||||
|
If you access the web address relevant to the installation directory,
|
||||||
|
the TileServer.php Server should display you a welcome message and further
|
||||||
|
instructions.
|
||||||
|
|
||||||
|
Then you can upload to the web hosting your mapping data - a directory with
|
||||||
|
tiles rendered with [MapTiler](http://www.maptiler.com/).
|
||||||
|
|
||||||
|
Tiles produced by open-source GDAL2Tiles or MapTiler and tiles in .mbtiles
|
||||||
|
files can be easily converted to required structure (XYZ with top-left origin
|
||||||
|
and metadata.json file).
|
||||||
|
|
||||||
|
The OpenSource utility mbutil (https://github.com/mapbox/mbutil) produces
|
||||||
|
exactly the required format.
|
||||||
|
|
||||||
|
Direct reading of .mbtiles files is supported, but with decreased performance
|
||||||
|
compared to the static files in a directory. Therefore the data management,
|
||||||
|
especially upload over FTP or similar protocols, is easier.
|
||||||
|
|
||||||
|
Supported protocols:
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
- OpenGIS WMTS 1.0.0
|
||||||
|
|
||||||
|
The Open Geospatial Consortium (OGC) Web Map Tile Service (WMTS)
|
||||||
|
Both KVP and RESTful version 1.0.0:
|
||||||
|
http://www.opengeospatial.org/standards/wmts/
|
||||||
|
|
||||||
|
Target is maximal compliance to the standard.
|
||||||
|
|
||||||
|
Exposed at http://[...]/wmts
|
||||||
|
|
||||||
|
- OSGeo TMS 1.0.0
|
||||||
|
|
||||||
|
The OSGeo Tile Maps Service, but with inverted y-coordinates:
|
||||||
|
http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification
|
||||||
|
This means request compatible with OpenStreetMap tile servers.
|
||||||
|
|
||||||
|
Target is "InvertedTMS" implementation used by the ArcBruTile client
|
||||||
|
which is available from http://arcbrutile.codeplex.com/ and uses
|
||||||
|
flipped y-axis.
|
||||||
|
|
||||||
|
Exposed at http://[...]/tms
|
||||||
|
|
||||||
|
- TileJSON.js
|
||||||
|
|
||||||
|
Metadata about the individual maps in a ready to use form for web
|
||||||
|
clients following the standard http://mapbox.com/developers/tilejson/
|
||||||
|
and with support for JSONP access.
|
||||||
|
|
||||||
|
Exposed at http://[...]/layer.jsonp
|
||||||
|
|
||||||
|
- Direct access with XYZ tile requests (to existing tiles in a directory
|
||||||
|
or to .mbtiles)
|
||||||
|
|
||||||
|
Compatible with Google Maps API / Bing SDK / OpenStreetMap clients.
|
||||||
|
|
||||||
|
Exposed at http://[...]/layer/z/x/y.ext
|
||||||
|
|
||||||
|
- MapBox UTFgrid request (for existing tiles in .mbtiles with UTFgrid support). Callback is supported
|
||||||
|
|
||||||
|
Example https://www.mapbox.com/demo/visiblemap/
|
||||||
|
Specification https://github.com/mapbox/utfgrid-spec
|
||||||
|
|
||||||
|
Exposed at http://[...]/layer/z/x/y.grid.json
|
||||||
|
|
||||||
|
|
||||||
|
To use the OGC WMTS services point your client (desktop or web) to the URL
|
||||||
|
of 'directory' where you installed tileserver.php project with suffix "wmts".
|
||||||
|
|
||||||
|
For example: http://www.example.com/directory/wmts
|
||||||
|
|
||||||
|
You can also install the project into a root directory of a virtual server:
|
||||||
|
Then the address is: http://www.example.com/wmts
|
||||||
|
|
||||||
|
Similarly for another end points.
|
||||||
|
|
||||||
|
The supported WMTS requests includes:
|
||||||
|
|
||||||
|
GetCapabilities RESTful/KVP:
|
||||||
|
|
||||||
|
http://[...]/1.0.0/WMTSCapabilities.xml
|
||||||
|
http://[...]?service=wmts&request=getcapabilities&version=1.0.0
|
||||||
|
|
||||||
|
GetTile RESTful/KVP:
|
||||||
|
|
||||||
|
http://[...]/layer/[ANYTHING-OPTIONAL][z]/[x]/[y].[ext]
|
||||||
|
http://[...]?service=wmts&request=getTile&layer=[layer]&tilematrix=[z]&tilerow=[y]&tilecol=[y]&format=[ext]
|
||||||
|
|
||||||
|
Another example requests are mentioned in the .htaccess.
|
||||||
|
|
||||||
|
Performance from the web clients
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
It is highly recommended to map several domain names to the service, such as:
|
||||||
|
http://a.example.com/, http://b.example.com/, http://c.example.com/.
|
||||||
|
This can be done with DNS CNAME records pointing to your hosting.
|
||||||
|
The reason for this is that traditionally browsers will not send more then two
|
||||||
|
simultaneous http request to the same domain - with multiple domains for the
|
||||||
|
same server you can better saturate the network and receive the maps faster.
|
||||||
|
|
||||||
|
Performance
|
||||||
|
-----------
|
||||||
|
|
||||||
|
In case the data are available in a form of directory with XYZ tiles, then
|
||||||
|
Apache webserver is serving these files directly as WMTS RESTful or KVP.
|
||||||
|
|
||||||
|
This means performance is excellent, maps are delivered very fast and large
|
||||||
|
number of concurrent visitors can be handled even with quite a low-end
|
||||||
|
hardware or cheap/free web hosting providers.
|
||||||
|
|
||||||
|
Mod_rewrite rules are utilized to ensure the HTTP requests defined in the OCG
|
||||||
|
WMTS standard are served, and Apache preserve standard caching headers & eTag.
|
||||||
|
|
||||||
|
The performance should be significantly better then performance of any other
|
||||||
|
tile caching project (such as TileCache.org or GeoWebCache).
|
||||||
|
|
||||||
|
Performance graph for "apache static" comparing other tile caching projects
|
||||||
|
is available online at:
|
||||||
|
http://code.google.com/p/mod-geocache/wiki/PreliminaryBenchmark
|
||||||
|
|
||||||
|
Limits of actual implementation
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
With intention, in this moment the project supports only:
|
||||||
|
- Mercator tiles (a la OpenStreetMap) and Geodetic tiles (WGS84 unprojected)
|
||||||
|
with known and described tiling scheme.
|
||||||
|
- All tiles must be 256x256 pixels.
|
||||||
|
- We enforce and require XYZ (top-left origin) tiling schema (even for TMS).
|
||||||
|
|
||||||
|
Password protection
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
HTTP Simple Authentication can be easily added to the server.
|
||||||
|
Edit the .htaccess and add these lines:
|
||||||
|
|
||||||
|
AuthUserFile /full/path/to/.htpasswd
|
||||||
|
AuthType Basic
|
||||||
|
AuthName "Secure WMTS"
|
||||||
|
Require valid-user
|
||||||
|
|
||||||
|
Create a file called .htpasswd with user:password format.
|
||||||
|
You can use a command-line utility:
|
||||||
|
|
||||||
|
$ htpasswd -c .htpasswd [your-user-login]
|
||||||
|
|
||||||
|
Or an online service:
|
||||||
|
|
||||||
|
http://www.htaccesstools.com/htpasswd-generator/
|
||||||
|
|
||||||
|
HTTPS / SSL support
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
TileServer.php can run without any problems over HTTPS, if required.
|
||||||
|
|
||||||
|
Microsoft Windows web-hosting
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
The TileServer.php should run on Windows-powered webservers with Apache
|
||||||
|
installation if PHP 5.2+ and mod_rewrite are available.
|
||||||
|
|
||||||
|
With the IIS webserver hosting, you may need PHP and IIRF module
|
||||||
|
(http://iirf.codeplex.com/) and alter appropriately the rewrite rules.
|
||||||
|
|
||||||
|
Credits / Contributors
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Project developed initially by Klokan Technologies GmbH, Switzerland in
|
||||||
|
cooperation with National Oceanic and Atmospheric Administration - NOAA, USA.
|
||||||
|
|
||||||
|
Petr Pridal - Klokan Technologies GmbH <petr.pridal@klokantech.com>
|
||||||
|
Jason Woolard - NOAA <jason.woolard@noaa.gov>
|
||||||
|
Jon Sellars - NOAA <jon.sellars@noaa.gov>
|
||||||
|
|
||||||
|
Tested WMTS/TMS clients
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
- QuantumGIS Desktop 1.9+ - open with Layer->Add WMS layer
|
||||||
|
http://www.qgis.org/
|
||||||
|
- ESRI ArcGIS Desktop 10.1+ - native WMTS implementation supported
|
||||||
|
http://www.esri.com/software/arcgis/arcgis-for-desktop
|
||||||
|
- ArcBruTiles plugin for ArcGIS 9.3+ - via TMS endpoint
|
||||||
|
http://arcbrutile.codeplex.com/
|
||||||
|
- OpenLayers WMTS Layer - including parsing GetCapabilities
|
||||||
|
http://www.openlayers.org/
|
||||||
|
- GAIA - native WMTS (issues with 3857 to be fixed)
|
||||||
|
http://www.thecarbonproject.com/gaia.php
|
||||||
|
- MapBox.js - the loading of maps via TileJSON
|
||||||
|
|
||||||
|
BSD License
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Copyright (C) 2012 Klokan Technologies GmbH
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
123
tileserver-mbtiles.php
Normal file
123
tileserver-mbtiles.php
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// Based on: https://github.com/Zverik/mbtiles-php
|
||||||
|
// Read: https://github.com/klokantech/tileserver-php/issues/1
|
||||||
|
// TODO: clean the code!!!
|
||||||
|
|
||||||
|
if (!is_file($_GET['tileset'])) {
|
||||||
|
header('HTTP/1.0 404 Not Found');
|
||||||
|
echo "<h1>404 Not Found</h1>";
|
||||||
|
echo "TileServer.php could not found what you requested.";
|
||||||
|
die();
|
||||||
|
// TODO: if ($_GET['ext'] == 'png') { ...
|
||||||
|
// TODO: better image 256x256px !!!
|
||||||
|
// header("Content-type: image/png");
|
||||||
|
//print("\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x06\x00\x00\x00\x1f\x15\xc4\x89\x00\x00\x00\rIDAT\x08\xd7c````\x00\x00\x00\x05\x00\x01^\xf3*:\x00\x00\x00\x00IEND\xaeB`\x82");
|
||||||
|
}
|
||||||
|
$tileset = $_GET['tileset'];
|
||||||
|
|
||||||
|
if (isset($_GET['tileset'])) {
|
||||||
|
|
||||||
|
$tileset = $_GET['tileset'];
|
||||||
|
$flip = true;
|
||||||
|
try {
|
||||||
|
$db = new PDO('sqlite:' . $tileset, '', '', array(PDO::ATTR_PERSISTENT => true));
|
||||||
|
if (!isset($db)) {
|
||||||
|
header('Content-type: text/plain');
|
||||||
|
print 'Incorrect tileset name: ' . $_GET['tileset'];
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
// http://c.tile.openstreetmap.org/12/2392/1190.png
|
||||||
|
$z = floatval($_GET['z']);
|
||||||
|
$y = floatval($_GET['y']);
|
||||||
|
$x = floatval($_GET['x']);
|
||||||
|
if ($flip) {
|
||||||
|
$y = pow(2, $z) - 1 - $y;
|
||||||
|
}
|
||||||
|
if ($_GET['ext'] != 'grid' && $_GET['ext'] != 'json') {
|
||||||
|
|
||||||
|
|
||||||
|
$result = $db->query('select tile_data as t from tiles where zoom_level=' . $z . ' and tile_column=' . $x . ' and tile_row=' . $y);
|
||||||
|
$data = $result->fetchColumn();
|
||||||
|
if (!isset($data) || $data === FALSE) {
|
||||||
|
// TODO: Put here ready to use empty tile!!!
|
||||||
|
$png = imagecreatetruecolor(256, 256);
|
||||||
|
imagesavealpha($png, true);
|
||||||
|
$trans_colour = imagecolorallocatealpha($png, 0, 0, 0, 127);
|
||||||
|
imagefill($png, 0, 0, $trans_colour);
|
||||||
|
header('Content-type: image/png');
|
||||||
|
imagepng($png);
|
||||||
|
//header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found');
|
||||||
|
} else {
|
||||||
|
$result = $db->query('select value from metadata where name="format"');
|
||||||
|
$resultdata = $result->fetchColumn();
|
||||||
|
$format = isset($resultdata) && $resultdata !== FALSE ? $resultdata : 'png';
|
||||||
|
if ($format == 'jpg')
|
||||||
|
$format = 'jpeg';
|
||||||
|
header('Content-type: image/' . $format);
|
||||||
|
print $data;
|
||||||
|
}
|
||||||
|
} elseif ($_GET['ext'] == 'grid' || $_GET['ext'] == 'json') {
|
||||||
|
//Get and return UTFgrid
|
||||||
|
$result = $db->query('SELECT grid FROM grids WHERE tile_column = ' . $x . ' AND tile_row = ' . $y . ' AND zoom_level = ' . $z);
|
||||||
|
$data = $result->fetchColumn();
|
||||||
|
|
||||||
|
if (!isset($data) || $data === FALSE) {
|
||||||
|
// if not exists grid data return empty json
|
||||||
|
header('Access-Control-Allow-Origin: *');
|
||||||
|
echo 'grid({});';
|
||||||
|
die;
|
||||||
|
} else {
|
||||||
|
$grid = gzuncompress($data);
|
||||||
|
$grid = substr(trim($grid), 0, -1);
|
||||||
|
|
||||||
|
//adds legend (data) to output
|
||||||
|
$grid .= ',"data":{';
|
||||||
|
$result = $db->query('SELECT key_name as key, key_json as json FROM grid_data WHERE zoom_level=' . $z . ' and tile_column=' . $x . ' and tile_row=' . $y);
|
||||||
|
while ($r = $result->fetch(PDO::FETCH_ASSOC)) {
|
||||||
|
$grid .= '"' . $r['key'] . '":' . $r['json'] . ',';
|
||||||
|
}
|
||||||
|
$grid = rtrim($grid, ',') . '}}';
|
||||||
|
|
||||||
|
// CORS headers
|
||||||
|
header('Access-Control-Allow-Origin: *');
|
||||||
|
|
||||||
|
if (isset($_GET['callback'])) {
|
||||||
|
header("Content-Type:text/javascript charset=utf-8");
|
||||||
|
echo $_GET['callback'] . '(' . $grid . ');';
|
||||||
|
} else {
|
||||||
|
header("Content-Type:text/javascript; charset=utf-8");
|
||||||
|
echo 'grid(' . $grid . ');';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
header('Content-type: text/plain');
|
||||||
|
print 'Error querying the database: ' . $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
function getbaseurl() {
|
||||||
|
return 'http://'.$_SERVER['HTTP_HOST'].preg_replace('/\/(1.0.0\/)?[^\/]*$/','/',$_SERVER['REQUEST_URI']);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function readparams($db) {
|
||||||
|
$params = array();
|
||||||
|
$result = $db->query('select name, value from metadata');
|
||||||
|
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
|
||||||
|
$params[$row['name']] = $row['value'];
|
||||||
|
}
|
||||||
|
return $params;
|
||||||
|
}
|
||||||
|
|
||||||
|
function readzooms($db) {
|
||||||
|
$zooms = array();
|
||||||
|
$result = $db->query('select zoom_level from tiles group by zoom_level order by zoom_level');
|
||||||
|
while ($zoom = $result->fetchColumn()) {
|
||||||
|
$zooms[] = $zoom;
|
||||||
|
}
|
||||||
|
return $zooms;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
85
tileserver-tms.php
Normal file
85
tileserver-tms.php
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* TileServer.php project
|
||||||
|
* ======================
|
||||||
|
* https://github.com/klokantech/tileserver-php/
|
||||||
|
* Copyright (C) 2012 - Klokan Technologies GmbH
|
||||||
|
*/
|
||||||
|
|
||||||
|
require "tileserver.php";
|
||||||
|
|
||||||
|
header("Content-type: application/xml");
|
||||||
|
|
||||||
|
echo "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
|
||||||
|
|
||||||
|
// Accepted GET strings
|
||||||
|
$layer = (array_key_exists('layer', $_GET)) ? $_GET['layer'] : "";
|
||||||
|
|
||||||
|
# -----------
|
||||||
|
# TMS SERVICE
|
||||||
|
# -----------
|
||||||
|
if ($layer === ""):
|
||||||
|
|
||||||
|
$maps = maps();
|
||||||
|
?>
|
||||||
|
<TileMapService version="1.0.0">
|
||||||
|
<TileMaps>
|
||||||
|
<?php
|
||||||
|
foreach ($maps as $m) {
|
||||||
|
$basename = $m['basename'];
|
||||||
|
$title = (array_key_exists('name', $m )) ? $m['name'] : $basename;
|
||||||
|
$profile = $m['profile'];
|
||||||
|
if ($profile == 'geodetic')
|
||||||
|
$srs = "EPSG:4326";
|
||||||
|
else
|
||||||
|
$srs = "EPSG:3857";
|
||||||
|
echo " <TileMap title=\"$title\" srs=\"$srs\" type=\"InvertedTMS\" profile=\"global-$profile\" href=\"$baseUrl$basename/tms\" />\n";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</TileMaps>
|
||||||
|
</TileMapService>
|
||||||
|
<?php
|
||||||
|
die;
|
||||||
|
# ---------
|
||||||
|
# TMS LAYER
|
||||||
|
# ---------
|
||||||
|
else:
|
||||||
|
$m = layer($layer);
|
||||||
|
$basename = $m['basename'];
|
||||||
|
$title = (array_key_exists('name', $m )) ? $m['name'] : $basename;
|
||||||
|
$description = (array_key_exists('description', $m )) ? $m['description'] : "";
|
||||||
|
$bounds = $m['bounds'];
|
||||||
|
$profile = $m['profile'];
|
||||||
|
if ($profile == 'geodetic') {
|
||||||
|
$srs = "EPSG:4326";
|
||||||
|
$originx = -180.0;
|
||||||
|
$originy = -90.0;
|
||||||
|
$initialResolution = 0.703125;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$srs = "EPSG:3857";
|
||||||
|
$originx = -20037508.342789;
|
||||||
|
$originy = -20037508.342789;
|
||||||
|
list( $minx, $miny ) = $mercator->LatLonToMeters($bounds[1], $bounds[0]);
|
||||||
|
list( $maxx, $maxy ) = $mercator->LatLonToMeters($bounds[3], $bounds[2]);
|
||||||
|
$bounds = array( $minx, $miny, $maxx, $maxy );
|
||||||
|
$initialResolution = 156543.03392804062;
|
||||||
|
}
|
||||||
|
$format = $m['format'];
|
||||||
|
$mime = ($format == 'jpg') ? 'image/jpeg' : 'image/png';
|
||||||
|
?>
|
||||||
|
<TileMap version="1.0.0" tilemapservice="<?php echo $baseUrl.$basename ?>" type="InvertedTMS">
|
||||||
|
<Title><?php echo htmlspecialchars($title) ?></Title>
|
||||||
|
<Abstract><?php echo htmlspecialchars($description) ?></Abstract>
|
||||||
|
<SRS><?php echo $srs ?></SRS>
|
||||||
|
<BoundingBox minx="<?php echo $bounds[0] ?>" miny="<?php echo $bounds[1] ?>" maxx="<?php echo $bounds[2] ?>" maxy="<?php echo $bounds[3] ?>" />
|
||||||
|
<Origin x="<?php echo $originx ?>" y="<?php echo $originy ?>"/>
|
||||||
|
<TileFormat width="256" height="256" mime-type="<?php echo $mime ?>" extension="<?php echo $format ?>"/>
|
||||||
|
<TileSets profile="global-<?php echo $profile ?>">
|
||||||
|
<?php for ($zoom = $m['minzoom']; $zoom < $m['maxzoom']+1; $zoom++ ) { ?>
|
||||||
|
<TileSet href="<?php echo $baseUrl.$basename.'/'.$zoom ?>" units-per-pixel="<?php echo $initialResolution / pow(2, $zoom) ?>" order="<?php echo $zoom ?>" />
|
||||||
|
<?php } ?>
|
||||||
|
</TileSets>
|
||||||
|
</TileMap>
|
||||||
|
<?php
|
||||||
|
endif; ?>
|
472
tileserver-wmts.php
Normal file
472
tileserver-wmts.php
Normal file
@@ -0,0 +1,472 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* TileServer.php project
|
||||||
|
* ======================
|
||||||
|
* https://github.com/klokantech/tileserver-php/
|
||||||
|
* Copyright (C) 2012 - Klokan Technologies GmbH
|
||||||
|
*/
|
||||||
|
|
||||||
|
require "tileserver.php";
|
||||||
|
|
||||||
|
$maps = maps();
|
||||||
|
|
||||||
|
header("Content-type: application/xml");
|
||||||
|
|
||||||
|
echo "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"; ?>
|
||||||
|
<Capabilities xmlns="http://www.opengis.net/wmts/1.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gml="http://www.opengis.net/gml" xsi:schemaLocation="http://www.opengis.net/wmts/1.0 http://schemas.opengis.net/wmts/1.0/wmtsGetCapabilities_response.xsd" version="1.0.0">
|
||||||
|
<!-- Service Identification -->
|
||||||
|
<ows:ServiceIdentification>
|
||||||
|
<ows:Title><?php echo $config['serverTitle'] ?></ows:Title>
|
||||||
|
<ows:ServiceType>OGC WMTS</ows:ServiceType>
|
||||||
|
<ows:ServiceTypeVersion>1.0.0</ows:ServiceTypeVersion>
|
||||||
|
</ows:ServiceIdentification>
|
||||||
|
<!-- Operations Metadata -->
|
||||||
|
<ows:OperationsMetadata>
|
||||||
|
<ows:Operation name="GetCapabilities">
|
||||||
|
<ows:DCP>
|
||||||
|
<ows:HTTP>
|
||||||
|
<ows:Get xlink:href="<?php echo $baseUrl ?>wmts/1.0.0/WMTSCapabilities.xml">
|
||||||
|
<ows:Constraint name="GetEncoding">
|
||||||
|
<ows:AllowedValues>
|
||||||
|
<ows:Value>RESTful</ows:Value>
|
||||||
|
</ows:AllowedValues>
|
||||||
|
</ows:Constraint>
|
||||||
|
</ows:Get>
|
||||||
|
<!-- add KVP binding in 10.1 -->
|
||||||
|
<ows:Get xlink:href="<?php echo $baseUrl ?>wmts?">
|
||||||
|
<ows:Constraint name="GetEncoding">
|
||||||
|
<ows:AllowedValues>
|
||||||
|
<ows:Value>KVP</ows:Value>
|
||||||
|
</ows:AllowedValues>
|
||||||
|
</ows:Constraint>
|
||||||
|
</ows:Get>
|
||||||
|
</ows:HTTP>
|
||||||
|
</ows:DCP>
|
||||||
|
</ows:Operation>
|
||||||
|
<ows:Operation name="GetTile">
|
||||||
|
<ows:DCP>
|
||||||
|
<ows:HTTP>
|
||||||
|
<ows:Get xlink:href="<?php echo $baseUrl ?>wmts/">
|
||||||
|
<ows:Constraint name="GetEncoding">
|
||||||
|
<ows:AllowedValues>
|
||||||
|
<ows:Value>RESTful</ows:Value>
|
||||||
|
</ows:AllowedValues>
|
||||||
|
</ows:Constraint>
|
||||||
|
</ows:Get>
|
||||||
|
<ows:Get xlink:href="<?php echo $baseUrl ?>wmts?">
|
||||||
|
<ows:Constraint name="GetEncoding">
|
||||||
|
<ows:AllowedValues>
|
||||||
|
<ows:Value>KVP</ows:Value>
|
||||||
|
</ows:AllowedValues>
|
||||||
|
</ows:Constraint>
|
||||||
|
</ows:Get>
|
||||||
|
</ows:HTTP>
|
||||||
|
</ows:DCP>
|
||||||
|
</ows:Operation>
|
||||||
|
</ows:OperationsMetadata>
|
||||||
|
<Contents>
|
||||||
|
|
||||||
|
<!--Layer-->
|
||||||
|
<?php
|
||||||
|
|
||||||
|
foreach ($maps as $m) {
|
||||||
|
$basename = $m['basename'];
|
||||||
|
$title = (array_key_exists('name', $m )) ? $m['name'] : $basename;
|
||||||
|
$profile = $m['profile'];
|
||||||
|
$bounds = $m['bounds'];
|
||||||
|
$format = $m['format'];
|
||||||
|
$mime = ($format == 'jpg') ? 'image/jpeg' : 'image/png';
|
||||||
|
if ($profile == 'geodetic') {
|
||||||
|
$tileMatrixSet = "WGS84";
|
||||||
|
} else {
|
||||||
|
$tileMatrixSet = "GoogleMapsCompatible";
|
||||||
|
list( $minx, $miny ) = $mercator->LatLonToMeters($bounds[1], $bounds[0]);
|
||||||
|
list( $maxx, $maxy ) = $mercator->LatLonToMeters($bounds[3], $bounds[2]);
|
||||||
|
$bounds3857 = array( $minx, $miny, $maxx, $maxy );
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
<Layer>
|
||||||
|
<ows:Title><?php echo $title ?></ows:Title>
|
||||||
|
<ows:Identifier><?php echo $basename ?></ows:Identifier>
|
||||||
|
<?php /* GAIA client does not like it
|
||||||
|
if ($profile == 'mercator') { ?>
|
||||||
|
<ows:BoundingBox crs="urn:ogc:def:crs:EPSG::102100">
|
||||||
|
<ows:LowerCorner><?php echo $bounds3857[1], ' ', $bounds3857[0] ?></ows:LowerCorner>
|
||||||
|
<ows:UpperCorner><?php echo $bounds3857[3], ' ', $bounds3857[2] ?></ows:UpperCorner>
|
||||||
|
</ows:BoundingBox>
|
||||||
|
<?php } */ ?>
|
||||||
|
<ows:WGS84BoundingBox crs="urn:ogc:def:crs:OGC:2:84">
|
||||||
|
<ows:LowerCorner><?php echo $bounds[0], ' ', $bounds[1] ?></ows:LowerCorner>
|
||||||
|
<ows:UpperCorner><?php echo $bounds[2], ' ', $bounds[3] ?></ows:UpperCorner>
|
||||||
|
</ows:WGS84BoundingBox>
|
||||||
|
<Style isDefault="true">
|
||||||
|
<ows:Identifier>default</ows:Identifier>
|
||||||
|
</Style>
|
||||||
|
<Format><?php echo $mime ?></Format>
|
||||||
|
<TileMatrixSetLink>
|
||||||
|
<TileMatrixSet><?php echo $tileMatrixSet ?></TileMatrixSet>
|
||||||
|
</TileMatrixSetLink>
|
||||||
|
<ResourceURL format="<?php echo $mime ?>" resourceType="tile" template="<?php echo $baseUrl ?><?php echo $basename ?>/{TileMatrixSet}/{TileMatrix}/{TileCol}/{TileRow}.<?php echo $format ?>"/>
|
||||||
|
</Layer>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<!--TileMatrixSet-->
|
||||||
|
|
||||||
|
<TileMatrixSet>
|
||||||
|
<ows:Title>GoogleMapsCompatible</ows:Title>
|
||||||
|
<ows:Abstract>the wellknown 'GoogleMapsCompatible' tile matrix set defined by OGC WMTS specification</ows:Abstract>
|
||||||
|
<ows:Identifier>GoogleMapsCompatible</ows:Identifier>
|
||||||
|
<ows:SupportedCRS>urn:ogc:def:crs:EPSG:6.18:3:3857</ows:SupportedCRS>
|
||||||
|
<WellKnownScaleSet>urn:ogc:def:wkss:OGC:1.0:GoogleMapsCompatible</WellKnownScaleSet>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>0</ows:Identifier>
|
||||||
|
<ScaleDenominator>559082264.0287178</ScaleDenominator>
|
||||||
|
<TopLeftCorner>-20037508.34278925 20037508.34278925</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>1</MatrixWidth>
|
||||||
|
<MatrixHeight>1</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>1</ows:Identifier>
|
||||||
|
<ScaleDenominator>279541132.0143589</ScaleDenominator>
|
||||||
|
<TopLeftCorner>-20037508.34278925 20037508.34278925</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>2</MatrixWidth>
|
||||||
|
<MatrixHeight>2</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>2</ows:Identifier>
|
||||||
|
<ScaleDenominator>139770566.0071794</ScaleDenominator>
|
||||||
|
<TopLeftCorner>-20037508.34278925 20037508.34278925</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>4</MatrixWidth>
|
||||||
|
<MatrixHeight>4</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>3</ows:Identifier>
|
||||||
|
<ScaleDenominator>69885283.00358972</ScaleDenominator>
|
||||||
|
<TopLeftCorner>-20037508.34278925 20037508.34278925</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>8</MatrixWidth>
|
||||||
|
<MatrixHeight>8</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>4</ows:Identifier>
|
||||||
|
<ScaleDenominator>34942641.50179486</ScaleDenominator>
|
||||||
|
<TopLeftCorner>-20037508.34278925 20037508.34278925</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>16</MatrixWidth>
|
||||||
|
<MatrixHeight>16</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>5</ows:Identifier>
|
||||||
|
<ScaleDenominator>17471320.75089743</ScaleDenominator>
|
||||||
|
<TopLeftCorner>-20037508.34278925 20037508.34278925</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>32</MatrixWidth>
|
||||||
|
<MatrixHeight>32</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>6</ows:Identifier>
|
||||||
|
<ScaleDenominator>8735660.375448715</ScaleDenominator>
|
||||||
|
<TopLeftCorner>-20037508.34278925 20037508.34278925</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>64</MatrixWidth>
|
||||||
|
<MatrixHeight>64</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>7</ows:Identifier>
|
||||||
|
<ScaleDenominator>4367830.187724357</ScaleDenominator>
|
||||||
|
<TopLeftCorner>-20037508.34278925 20037508.34278925</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>128</MatrixWidth>
|
||||||
|
<MatrixHeight>128</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>8</ows:Identifier>
|
||||||
|
<ScaleDenominator>2183915.093862179</ScaleDenominator>
|
||||||
|
<TopLeftCorner>-20037508.34278925 20037508.34278925</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>256</MatrixWidth>
|
||||||
|
<MatrixHeight>256</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>9</ows:Identifier>
|
||||||
|
<ScaleDenominator>1091957.546931089</ScaleDenominator>
|
||||||
|
<TopLeftCorner>-20037508.34278925 20037508.34278925</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>512</MatrixWidth>
|
||||||
|
<MatrixHeight>512</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>10</ows:Identifier>
|
||||||
|
<ScaleDenominator>545978.7734655447</ScaleDenominator>
|
||||||
|
<TopLeftCorner>-20037508.34278925 20037508.34278925</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>1024</MatrixWidth>
|
||||||
|
<MatrixHeight>1024</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>11</ows:Identifier>
|
||||||
|
<ScaleDenominator>272989.3867327723</ScaleDenominator>
|
||||||
|
<TopLeftCorner>-20037508.34278925 20037508.34278925</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>2048</MatrixWidth>
|
||||||
|
<MatrixHeight>2048</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>12</ows:Identifier>
|
||||||
|
<ScaleDenominator>136494.6933663862</ScaleDenominator>
|
||||||
|
<TopLeftCorner>-20037508.34278925 20037508.34278925</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>4096</MatrixWidth>
|
||||||
|
<MatrixHeight>4096</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>13</ows:Identifier>
|
||||||
|
<ScaleDenominator>68247.34668319309</ScaleDenominator>
|
||||||
|
<TopLeftCorner>-20037508.34278925 20037508.34278925</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>8192</MatrixWidth>
|
||||||
|
<MatrixHeight>8192</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>14</ows:Identifier>
|
||||||
|
<ScaleDenominator>34123.67334159654</ScaleDenominator>
|
||||||
|
<TopLeftCorner>-20037508.34278925 20037508.34278925</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>16384</MatrixWidth>
|
||||||
|
<MatrixHeight>16384</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>15</ows:Identifier>
|
||||||
|
<ScaleDenominator>17061.83667079827</ScaleDenominator>
|
||||||
|
<TopLeftCorner>-20037508.34278925 20037508.34278925</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>32768</MatrixWidth>
|
||||||
|
<MatrixHeight>32768</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>16</ows:Identifier>
|
||||||
|
<ScaleDenominator>8530.918335399136</ScaleDenominator>
|
||||||
|
<TopLeftCorner>-20037508.34278925 20037508.34278925</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>65536</MatrixWidth>
|
||||||
|
<MatrixHeight>65536</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>17</ows:Identifier>
|
||||||
|
<ScaleDenominator>4265.459167699568</ScaleDenominator>
|
||||||
|
<TopLeftCorner>-20037508.34278925 20037508.34278925</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>131072</MatrixWidth>
|
||||||
|
<MatrixHeight>131072</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>18</ows:Identifier>
|
||||||
|
<ScaleDenominator>2132.729583849784</ScaleDenominator>
|
||||||
|
<TopLeftCorner>-20037508.34278925 20037508.34278925</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>262144</MatrixWidth>
|
||||||
|
<MatrixHeight>262144</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
</TileMatrixSet>
|
||||||
|
|
||||||
|
<TileMatrixSet>
|
||||||
|
<ows:Identifier>WGS84</ows:Identifier>
|
||||||
|
<ows:Title>GoogleCRS84Quad</ows:Title>
|
||||||
|
<ows:SupportedCRS>urn:ogc:def:crs:EPSG:6.3:4326</ows:SupportedCRS>
|
||||||
|
<ows:BoundingBox crs="urn:ogc:def:crs:EPSG:6.3:4326">
|
||||||
|
<LowerCorner>-180.000000 -90.000000</LowerCorner>
|
||||||
|
<UpperCorner>180.000000 90.000000</UpperCorner>
|
||||||
|
</ows:BoundingBox>
|
||||||
|
<WellKnownScaleSet>urn:ogc:def:wkss:OGC:1.0:GoogleCRS84Quad</WellKnownScaleSet>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>0</ows:Identifier>
|
||||||
|
<ScaleDenominator>279541132.01435887813568115234</ScaleDenominator>
|
||||||
|
<TopLeftCorner>90.000000 -180.000000</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>2</MatrixWidth>
|
||||||
|
<MatrixHeight>1</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>1</ows:Identifier>
|
||||||
|
<ScaleDenominator>139770566.00717943906784057617</ScaleDenominator>
|
||||||
|
<TopLeftCorner>90.000000 -180.000000</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>4</MatrixWidth>
|
||||||
|
<MatrixHeight>2</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>2</ows:Identifier>
|
||||||
|
<ScaleDenominator>69885283.00358971953392028809</ScaleDenominator>
|
||||||
|
<TopLeftCorner>90.000000 -180.000000</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>8</MatrixWidth>
|
||||||
|
<MatrixHeight>4</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>3</ows:Identifier>
|
||||||
|
<ScaleDenominator>34942641.50179485976696014404</ScaleDenominator>
|
||||||
|
<TopLeftCorner>90.000000 -180.000000</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>16</MatrixWidth>
|
||||||
|
<MatrixHeight>8</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>4</ows:Identifier>
|
||||||
|
<ScaleDenominator>17471320.75089742988348007202</ScaleDenominator>
|
||||||
|
<TopLeftCorner>90.000000 -180.000000</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>32</MatrixWidth>
|
||||||
|
<MatrixHeight>16</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>5</ows:Identifier>
|
||||||
|
<ScaleDenominator>8735660.37544871494174003601</ScaleDenominator>
|
||||||
|
<TopLeftCorner>90.000000 -180.000000</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>64</MatrixWidth>
|
||||||
|
<MatrixHeight>32</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>6</ows:Identifier>
|
||||||
|
<ScaleDenominator>4367830.18772435747087001801</ScaleDenominator>
|
||||||
|
<TopLeftCorner>90.000000 -180.000000</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>128</MatrixWidth>
|
||||||
|
<MatrixHeight>64</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>7</ows:Identifier>
|
||||||
|
<ScaleDenominator>2183915.09386217873543500900</ScaleDenominator>
|
||||||
|
<TopLeftCorner>90.000000 -180.000000</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>256</MatrixWidth>
|
||||||
|
<MatrixHeight>128</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>8</ows:Identifier>
|
||||||
|
<ScaleDenominator>1091957.54693108936771750450</ScaleDenominator>
|
||||||
|
<TopLeftCorner>90.000000 -180.000000</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>512</MatrixWidth>
|
||||||
|
<MatrixHeight>256</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>9</ows:Identifier>
|
||||||
|
<ScaleDenominator>545978.77346554468385875225</ScaleDenominator>
|
||||||
|
<TopLeftCorner>90.000000 -180.000000</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>1024</MatrixWidth>
|
||||||
|
<MatrixHeight>512</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>10</ows:Identifier>
|
||||||
|
<ScaleDenominator>272989.38673277234192937613</ScaleDenominator>
|
||||||
|
<TopLeftCorner>90.000000 -180.000000</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>2048</MatrixWidth>
|
||||||
|
<MatrixHeight>1024</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>11</ows:Identifier>
|
||||||
|
<ScaleDenominator>136494.69336638617096468806</ScaleDenominator>
|
||||||
|
<TopLeftCorner>90.000000 -180.000000</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>4096</MatrixWidth>
|
||||||
|
<MatrixHeight>2048</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>12</ows:Identifier>
|
||||||
|
<ScaleDenominator>68247.34668319308548234403</ScaleDenominator>
|
||||||
|
<TopLeftCorner>90.000000 -180.000000</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>8192</MatrixWidth>
|
||||||
|
<MatrixHeight>4096</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>13</ows:Identifier>
|
||||||
|
<ScaleDenominator>34123.67334159654274117202</ScaleDenominator>
|
||||||
|
<TopLeftCorner>90.000000 -180.000000</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>16384</MatrixWidth>
|
||||||
|
<MatrixHeight>8192</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>14</ows:Identifier>
|
||||||
|
<ScaleDenominator>17061.83667079825318069197</ScaleDenominator>
|
||||||
|
<TopLeftCorner>90.000000 -180.000000</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>32768</MatrixWidth>
|
||||||
|
<MatrixHeight>16384</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>15</ows:Identifier>
|
||||||
|
<ScaleDenominator>8530.91833539912659034599</ScaleDenominator>
|
||||||
|
<TopLeftCorner>90.000000 -180.000000</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>65536</MatrixWidth>
|
||||||
|
<MatrixHeight>32768</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>16</ows:Identifier>
|
||||||
|
<ScaleDenominator>4265.45916769956329517299</ScaleDenominator>
|
||||||
|
<TopLeftCorner>90.000000 -180.000000</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>131072</MatrixWidth>
|
||||||
|
<MatrixHeight>65536</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
<TileMatrix>
|
||||||
|
<ows:Identifier>17</ows:Identifier>
|
||||||
|
<ScaleDenominator>2132.72958384978574031265</ScaleDenominator>
|
||||||
|
<TopLeftCorner>90.000000 -180.000000</TopLeftCorner>
|
||||||
|
<TileWidth>256</TileWidth>
|
||||||
|
<TileHeight>256</TileHeight>
|
||||||
|
<MatrixWidth>262144</MatrixWidth>
|
||||||
|
<MatrixHeight>131072</MatrixHeight>
|
||||||
|
</TileMatrix>
|
||||||
|
</TileMatrixSet>
|
||||||
|
|
||||||
|
</Contents>
|
||||||
|
<ServiceMetadataURL xlink:href="<?php echo $baseUrl ?>wmts/1.0.0/WMTSCapabilities.xml"/>
|
||||||
|
</Capabilities>
|
415
tileserver.php
Normal file
415
tileserver.php
Normal file
@@ -0,0 +1,415 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* TileServer.php project
|
||||||
|
* ======================
|
||||||
|
* https://github.com/klokantech/tileserver-php/
|
||||||
|
* Copyright (C) 2012 - Klokan Technologies GmbH
|
||||||
|
*/
|
||||||
|
|
||||||
|
# Set you own config values here:
|
||||||
|
$config = array(
|
||||||
|
"baseUrls" => array("http://localhost/"),
|
||||||
|
"serverTitle" => "TileServer.php v0.1",
|
||||||
|
);
|
||||||
|
|
||||||
|
# PHP debugging
|
||||||
|
ini_set("error_reporting", "true");
|
||||||
|
error_reporting(E_ALL|E_STRCT);
|
||||||
|
|
||||||
|
# Global variable + ccepted GET / POST variables from the outside world
|
||||||
|
$baseUrl = $config['baseUrls'][0];
|
||||||
|
// TODO: We can detext the baseUrl as well - for defined requests
|
||||||
|
|
||||||
|
$service = (array_key_exists('service', $_GET)) ? $_GET['service'] : "";
|
||||||
|
$layer = (array_key_exists('layer', $_GET)) ? $_GET['layer'] : "";
|
||||||
|
$callback = (array_key_exists('callback', $_GET)) ? $_GET['callback'] : "";
|
||||||
|
|
||||||
|
# CORS header
|
||||||
|
header('Access-Control-Allow-Origin: *');
|
||||||
|
|
||||||
|
# ------------
|
||||||
|
# TEST SERVICE
|
||||||
|
# ------------
|
||||||
|
if ($service == 'test') {
|
||||||
|
header("Content-Type: text/plain; charset=utf-8");
|
||||||
|
echo "TileServer.php (", $config['serverTitle'], ') at ', $baseUrl;
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
# ------------
|
||||||
|
# HTML SERVICE
|
||||||
|
# ------------
|
||||||
|
if ($service == 'html'):
|
||||||
|
$maps = maps();
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<title><?php echo $config['serverTitle'] ?></title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="http://maptilercdn.s3.amazonaws.com/tileserver.css" />
|
||||||
|
<script src="http://maptilercdn.s3.amazonaws.com/tileserver.js"></script>
|
||||||
|
<body>
|
||||||
|
<script>tileserver(null,'<?php echo $baseUrl ?>tms','<?php echo $baseUrl ?>wmts');</script>
|
||||||
|
<h1>Welcome to <?php echo $config['serverTitle'] ?></h1>
|
||||||
|
<p>
|
||||||
|
This server distributes maps to desktop, web, and mobile applications.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The mapping data are available as OpenGIS Web Map Tiling Service (OGC WMTS), OSGEO Tile Map Service (TMS), and popular XYZ urls described with TileJSON metadata.
|
||||||
|
</p>
|
||||||
|
<?php
|
||||||
|
|
||||||
|
# Test if the config value for baseUrls is set correctly
|
||||||
|
if ((strpos($baseUrl, $_SERVER['HTTP_HOST']) === false) or ($baseUrl[strlen($baseUrl)-1] !== '/')) {
|
||||||
|
// TODO: Make a test with ?service=test and suggest the value - or is there any way how to get URL for actual directory with mod_rewrite in use ?
|
||||||
|
?>
|
||||||
|
<h3 style="color:darkred;">Wrong configuration of the "BaseURL" in tileserver.php</h3>
|
||||||
|
<p style="color:darkred; font-style: italic;">
|
||||||
|
Please modify 'tileserver.php' file and replace the '<?php echo $baseUrl ?>' in the $config variable with '<?php echo selfUrl(); ?>' (with slash in the end) or other correct address to your server. Multiple CNAME can be used for better performance - more in <a href="readme.md">readme.txt</a>.
|
||||||
|
</p>
|
||||||
|
<?php }
|
||||||
|
# Are there some maps on the server?
|
||||||
|
if (count($maps) == 0) { ?>
|
||||||
|
|
||||||
|
<h3 style="color:darkred;">No maps available yet</h3>
|
||||||
|
<p style="color:darkred; font-style: italic;">
|
||||||
|
Ready to go - just upload some maps into directory: <?php echo getcwd(); ?>/ on this server.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Note: The maps can be a directory with tiles in XYZ format with metadata.json file.<br/>
|
||||||
|
You can easily convert existing geodata (GeoTIFF, ECW, MrSID, etc) to this tile structure with <a href="http://www.maptiler.com">MapTiler Cluster</a> or open-source projects such as <a href="http://www.klokan.cz/projects/gdal2tiles/">GDAL2Tiles</a> or <a href="http://www.maptiler.org/">MapTiler</a> or simply upload any maps in MBTiles format made by <a href="http://www.tilemill.com/">TileMill</a>. Helpful is also the <a href="https://github.com/mapbox/mbutil">mbutil</a> tool. Serving directly from .mbtiles files is supported, but with decreased performance.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
# Print the available maps
|
||||||
|
} else {
|
||||||
|
// print_r($maps);
|
||||||
|
echo "<h3>Available maps</h3>";
|
||||||
|
echo "<ul>";
|
||||||
|
foreach ($maps as $map) {
|
||||||
|
// echo "<li><a href=\"".$map['basename']."\">".$map['name']."</a>" ;
|
||||||
|
echo "<li>".$map['name'];
|
||||||
|
}
|
||||||
|
echo "</ul>";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
die;
|
||||||
|
endif;
|
||||||
|
|
||||||
|
# ------------
|
||||||
|
# JSON SERVICE
|
||||||
|
# ------------
|
||||||
|
if ($service == 'json'):
|
||||||
|
header("Content-Type:application/json; charset=utf-8");
|
||||||
|
|
||||||
|
if ($layer) {
|
||||||
|
$output = metadataTileJson(layer($layer));
|
||||||
|
} else {
|
||||||
|
$maps = maps();
|
||||||
|
$tilejsons = array();
|
||||||
|
foreach ($maps as $map)
|
||||||
|
$tilejsons[] = metadataTileJson($map);
|
||||||
|
$output = $tilejsons;
|
||||||
|
}
|
||||||
|
$output = json_encode($output);
|
||||||
|
$output = str_replace("\\/","/",$output);
|
||||||
|
if ($callback) echo "$callback($output);";
|
||||||
|
else echo $output;
|
||||||
|
die;
|
||||||
|
endif;
|
||||||
|
|
||||||
|
|
||||||
|
# INTERNAL FUNCTIONS:
|
||||||
|
|
||||||
|
function maps() {
|
||||||
|
$maps = array();
|
||||||
|
# Scan all directories with metadata.json
|
||||||
|
$mjs = glob('*/metadata.json');
|
||||||
|
if ($mjs) foreach ($mjs as $mj) $maps[] = metadataFromMetadataJson($mj);
|
||||||
|
# Scan all mbtiles
|
||||||
|
$mbts = glob('*.mbtiles');
|
||||||
|
if ($mbts) foreach ($mbts as $mbt) $maps[] = metadataFromMbtiles($mbt);
|
||||||
|
return $maps;
|
||||||
|
}
|
||||||
|
|
||||||
|
function layer( $layer ) {
|
||||||
|
if (strpos($layer, '.mbtiles') === false)
|
||||||
|
return metadataFromMetadataJson($layer.'/metadata.json');
|
||||||
|
else
|
||||||
|
return metadataFromMbtiles($layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
function metadataFromMetadataJson( $jsonFileName ) {
|
||||||
|
$metadata = json_decode( file_get_contents($jsonFileName), true );
|
||||||
|
$metadata = metadataValidation($metadata);
|
||||||
|
$metadata['basename'] = str_replace('/metadata.json', '', $jsonFileName);
|
||||||
|
return $metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
function metadataFromMbtiles( $mbt ) {
|
||||||
|
$metadata = array();
|
||||||
|
$db = new PDO('sqlite:'.$mbt,'','',array(PDO::ATTR_PERSISTENT => true));
|
||||||
|
if (isset($db)) {
|
||||||
|
$result = $db->query('select * from metadata');
|
||||||
|
$resultdata = $result->fetchAll();
|
||||||
|
foreach ($resultdata as $r) {
|
||||||
|
$metadata[$r['name']] = $r['value'];
|
||||||
|
}
|
||||||
|
$metadata = metadataValidation($metadata);
|
||||||
|
$metadata['basename'] = $mbt;
|
||||||
|
}
|
||||||
|
return $metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
function metadataValidation( $metadata ) {
|
||||||
|
if (array_key_exists('bounds', $metadata )) {
|
||||||
|
// TODO: Calculate bounds from tiles if bounds is missing - with GlobalMercator
|
||||||
|
$metadata['bounds'] = array_map( 'floatval', explode(',', $metadata['bounds'] ));
|
||||||
|
}
|
||||||
|
if (!array_key_exists('profile', $metadata )) {
|
||||||
|
$metadata['profile'] = 'mercator';
|
||||||
|
}
|
||||||
|
// TODO: detect format, minzoom, maxzoom, thumb
|
||||||
|
// scandir() for directory / SQL for mbtiles
|
||||||
|
if (array_key_exists('minzoom', $metadata ))
|
||||||
|
$metadata['minzoom'] = intval( $metadata['minzoom'] );
|
||||||
|
else
|
||||||
|
$metadata['minzoom'] = 0;
|
||||||
|
if (array_key_exists('maxzoom', $metadata ))
|
||||||
|
$metadata['maxzoom'] = intval( $metadata['maxzoom'] );
|
||||||
|
else
|
||||||
|
$metadata['maxzoom'] = 18;
|
||||||
|
if (!array_key_exists('format', $metadata )) {
|
||||||
|
$metadata['format'] = 'png';
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
if (!array_key_exists('thumb', $metadata )) {
|
||||||
|
$metadata['profile'] = 'mercator';
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return $metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
function metadataTileJson( $metadata ) {
|
||||||
|
global $config;
|
||||||
|
$metadata['tilejson'] = '2.0.0';
|
||||||
|
$metadata['scheme'] = 'xyz';
|
||||||
|
$tiles = array();
|
||||||
|
foreach($config['baseUrls'] as $url)
|
||||||
|
$tiles[] = $url.$metadata['basename'].'/{z}/{x}/{y}.'.$metadata['format'];
|
||||||
|
#print_r($tiles);
|
||||||
|
$metadata['tiles'] = $tiles;
|
||||||
|
return $metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
function selfUrl( $serverOnly = false ) {
|
||||||
|
if(!isset($_SERVER['REQUEST_URI'])){
|
||||||
|
$serverrequri = $_SERVER['PHP_SELF'];
|
||||||
|
}else{
|
||||||
|
$serverrequri = $_SERVER['REQUEST_URI'];
|
||||||
|
}
|
||||||
|
$s = empty($_SERVER["HTTPS"]) ? '' : ($_SERVER["HTTPS"] == "on") ? "s" : "";
|
||||||
|
$port = ($_SERVER["SERVER_PORT"] == "80") ? "" : (":".$_SERVER["SERVER_PORT"]);
|
||||||
|
if ($serverOnly) return 'http'.$s.'://'.$_SERVER['SERVER_NAME'].$port."/";
|
||||||
|
return 'http'.$s.'://'.$_SERVER['SERVER_NAME'].$port.$serverrequri;
|
||||||
|
}
|
||||||
|
|
||||||
|
function doConditionalGet($timestamp) {
|
||||||
|
$last_modified = gmdate('D, d M Y H:i:s \G\M\T', $timestamp);
|
||||||
|
$etag = '"'.md5($last_modified).'"';
|
||||||
|
// Send the headers
|
||||||
|
header("Last-Modified: $last_modified");
|
||||||
|
header("ETag: $etag");
|
||||||
|
// See if the client has provided the required headers
|
||||||
|
$if_modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ?
|
||||||
|
stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']) :
|
||||||
|
false;
|
||||||
|
$if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH']) ?
|
||||||
|
stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) :
|
||||||
|
false;
|
||||||
|
if (!$if_modified_since && !$if_none_match) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// At least one of the headers is there - check them
|
||||||
|
if ($if_none_match && $if_none_match != $etag) {
|
||||||
|
return; // etag is there but doesn't match
|
||||||
|
}
|
||||||
|
if ($if_modified_since && $if_modified_since != $last_modified) {
|
||||||
|
return; // if-modified-since is there but doesn't match
|
||||||
|
}
|
||||||
|
// Nothing has changed since their last request - serve a 304 and exit
|
||||||
|
header('HTTP/1.0 304 Not Modified');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO: https://github.com/klokantech/tileserver-php/issues/2
|
||||||
|
|
||||||
|
function geoToMercTile($lon, $lat, $zoom) {
|
||||||
|
$xtile = floor((($lon + 180) / 360) * pow(2, $zoom));
|
||||||
|
$ytile = floor((1 - log(tan(deg2rad($lat)) + 1 / cos(deg2rad($lat))) / pi()) /2 * pow(2, $zoom));
|
||||||
|
return array($xtile, $ytile);
|
||||||
|
}
|
||||||
|
|
||||||
|
function geoToGeoTile($lon, $lat, $zoom) {
|
||||||
|
$res = 180 / 256.0 / pow(2, $zoom);
|
||||||
|
$xtile = floor( ceil( (180 + $lat) / $res / 256.0 ) - 1 );
|
||||||
|
$ytile = floor( ceil( (90 + $lon) / $res / 256.0 ) - 1 );
|
||||||
|
return array($xtile, $ytile);
|
||||||
|
}
|
||||||
|
|
||||||
|
function tileRange($bounds, $minzoom, $maxzoom) {
|
||||||
|
for ($z=$minzoom; $z < $maxzoom+1; $z++) {
|
||||||
|
print "$z\n";
|
||||||
|
list($minx, $miny) = geoToMercTile($bounds[0], $bounds[1], $z);
|
||||||
|
list($maxx, $maxy) = geoToMercTile($bounds[2], $bounds[3], $z);
|
||||||
|
print_r( array($minx, $miny, $maxx, $maxy) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Better use the port of Klokans' GlobalMapTiles:
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
GlobalMapTiles - part of Aggregate Map Tools
|
||||||
|
Version 1.0
|
||||||
|
Copyright (c) 2009 The Bivings Group
|
||||||
|
All rights reserved.
|
||||||
|
Author: John Bafford
|
||||||
|
|
||||||
|
http://www.bivings.com/
|
||||||
|
http://bafford.com/softare/aggregate-map-tools/
|
||||||
|
|
||||||
|
Based on GDAL2Tiles / globalmaptiles.py
|
||||||
|
Original python version Copyright (c) 2008 Klokan Petr Pridal. All rights reserved.
|
||||||
|
http://www.klokan.cz/projects/gdal2tiles/
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class GlobalMercator
|
||||||
|
{
|
||||||
|
var $tileSize;
|
||||||
|
var $initialResolution;
|
||||||
|
var $originShift;
|
||||||
|
|
||||||
|
//Initialize the TMS Global Mercator pyramid
|
||||||
|
function __construct($tileSize = 256)
|
||||||
|
{
|
||||||
|
$this->tileSize = $tileSize;
|
||||||
|
$this->initialResolution = 2 * M_PI * 6378137 / $this->tileSize;
|
||||||
|
# 156543.03392804062 for tileSize 256 Pixels
|
||||||
|
$this->originShift = 2 * M_PI * 6378137 / 2.0;
|
||||||
|
# 20037508.342789244
|
||||||
|
}
|
||||||
|
|
||||||
|
//Converts given lat/lon in WGS84 Datum to XY in Spherical Mercator EPSG:900913
|
||||||
|
function LatLonToMeters($lat, $lon)
|
||||||
|
{
|
||||||
|
$mx = $lon * $this->originShift / 180.0;
|
||||||
|
$my = log( tan((90 + $lat) * M_PI / 360.0 )) / (M_PI / 180.0);
|
||||||
|
|
||||||
|
$my *= $this->originShift / 180.0;
|
||||||
|
|
||||||
|
return array($mx, $my);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Converts XY point from Spherical Mercator EPSG:900913 to lat/lon in WGS84 Datum
|
||||||
|
function MetersToLatLon($mx, $my)
|
||||||
|
{
|
||||||
|
$lon = ($mx / $this->originShift) * 180.0;
|
||||||
|
$lat = ($my / $this->originShift) * 180.0;
|
||||||
|
|
||||||
|
$lat = 180 / M_PI * (2 * atan( exp( $lat * M_PI / 180.0)) - M_PI / 2.0);
|
||||||
|
|
||||||
|
return array($lat, $lon);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Converts pixel coordinates in given zoom level of pyramid to EPSG:900913
|
||||||
|
function PixelsToMeters($px, $py, $zoom)
|
||||||
|
{
|
||||||
|
$res = $this->Resolution($zoom);
|
||||||
|
$mx = $px * $res - $this->originShift;
|
||||||
|
$my = $py * $res - $this->originShift;
|
||||||
|
|
||||||
|
return array($mx, $my);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Converts EPSG:900913 to pyramid pixel coordinates in given zoom level
|
||||||
|
function MetersToPixels($mx, $my, $zoom)
|
||||||
|
{
|
||||||
|
$res = $this->Resolution( $zoom );
|
||||||
|
|
||||||
|
$px = ($mx + $this->originShift) / $res;
|
||||||
|
$py = ($my + $this->originShift) / $res;
|
||||||
|
|
||||||
|
return array($px, $py);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Returns a tile covering region in given pixel coordinates
|
||||||
|
function PixelsToTile($px, $py)
|
||||||
|
{
|
||||||
|
$tx = ceil( $px / $this->tileSize ) - 1;
|
||||||
|
$ty = ceil( $py / $this->tileSize ) - 1;
|
||||||
|
|
||||||
|
return array($tx, $ty);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Returns tile for given mercator coordinates
|
||||||
|
function MetersToTile($mx, $my, $zoom)
|
||||||
|
{
|
||||||
|
list($px, $py) = $this->MetersToPixels($mx, $my, $zoom);
|
||||||
|
|
||||||
|
return $this->PixelsToTile($px, $py);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Returns bounds of the given tile in EPSG:900913 coordinates
|
||||||
|
function TileBounds($tx, $ty, $zoom)
|
||||||
|
{
|
||||||
|
list($minx, $miny) = $this->PixelsToMeters( $tx*$this->tileSize, $ty*$this->tileSize, $zoom );
|
||||||
|
list($maxx, $maxy) = $this->PixelsToMeters( ($tx+1)*$this->tileSize, ($ty+1)*$this->tileSize, $zoom );
|
||||||
|
|
||||||
|
return array($minx, $miny, $maxx, $maxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Returns bounds of the given tile in latutude/longitude using WGS84 datum
|
||||||
|
function TileLatLonBounds($tx, $ty, $zoom)
|
||||||
|
{
|
||||||
|
$bounds = $this->TileBounds($tx, $ty, $zoom);
|
||||||
|
|
||||||
|
list($minLat, $minLon) = $this->MetersToLatLon($bounds[0], $bounds[1]);
|
||||||
|
list($maxLat, $maxLon) = $this->MetersToLatLon($bounds[2], $bounds[3]);
|
||||||
|
|
||||||
|
return array($minLat, $minLon, $maxLat, $maxLon);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Resolution (meters/pixel) for given zoom level (measured at Equator)
|
||||||
|
function Resolution($zoom)
|
||||||
|
{
|
||||||
|
return $this->initialResolution / (1 << $zoom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$mercator = new GlobalMercator();
|
||||||
|
?>
|
Reference in New Issue
Block a user