mirror of
https://github.com/klokantech/tileserver-php.git
synced 2025-08-22 22:23:53 +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