1 |
3032
|
perry
|
<?php
|
2 |
|
|
/*
|
3 |
|
|
|
4 |
|
|
This is a PHP file to be used as a backend for a ka-Map layer. It requires
|
5 |
|
|
PHP with Mapscript and libgd modules installed. The top of the file
|
6 |
|
|
is a configuration section: please edit the variables in this configuration
|
7 |
|
|
section to meet your needs, then rename this file to tile.php or something
|
8 |
|
|
similar and put it in a web accessible directory. More information
|
9 |
|
|
on the OpenLayers ka-Map layer is available from:
|
10 |
|
|
|
11 |
|
|
http://trac.openlayers.org/wiki/OpenLayers.Layer.KaMap
|
12 |
|
|
|
13 |
|
|
*/
|
14 |
|
|
/**********************************************************************
|
15 |
|
|
*
|
16 |
|
|
* $Id$
|
17 |
|
|
*
|
18 |
|
|
* purpose: a simple phpmapscript-based tile renderer that implements
|
19 |
|
|
* rudimentary caching for reasonable efficiency. Note the
|
20 |
|
|
* cache never shrinks in this version so your disk could
|
21 |
|
|
* easily fill up!
|
22 |
|
|
*
|
23 |
|
|
* author: Paul Spencer (pspencer@dmsolutions.ca)
|
24 |
|
|
*
|
25 |
|
|
* modifications by Daniel Morissette (dmorissette@dmsolutions.ca)
|
26 |
|
|
*
|
27 |
|
|
* Modified by Christopher Schmidt for OpenLayers redistribution.
|
28 |
|
|
*
|
29 |
|
|
**********************************************************************
|
30 |
|
|
*
|
31 |
|
|
* Copyright (c) 2005, DM Solutions Group Inc.
|
32 |
|
|
*
|
33 |
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
34 |
|
|
* copy of this software and associated documentation files (the "Software"),
|
35 |
|
|
* to deal in the Software without restriction, including without limitation
|
36 |
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
37 |
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
38 |
|
|
* Software is furnished to do so, subject to the following conditions:
|
39 |
|
|
*
|
40 |
|
|
* The above copyright notice and this permission notice shall be included
|
41 |
|
|
* in all copies or substantial portions of the Software.
|
42 |
|
|
*
|
43 |
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
44 |
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
45 |
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
46 |
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
47 |
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
48 |
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
49 |
|
|
* DEALINGS IN THE SOFTWARE.
|
50 |
|
|
*
|
51 |
|
|
**********************************************************************/
|
52 |
|
|
|
53 |
|
|
|
54 |
|
|
/******************************************************************************
|
55 |
|
|
* basic system configuration
|
56 |
|
|
*
|
57 |
|
|
* kaMap! uses PHP/MapScript and the PHP GD extension to
|
58 |
|
|
* render tiles, and uses PHP/MapScript to generate initialization parameters
|
59 |
|
|
* a legend, and a keymap from the selected map file.
|
60 |
|
|
*
|
61 |
|
|
* Make sure to set the correct module names for your PHP extensions.
|
62 |
|
|
*
|
63 |
|
|
* WINDOWS USERS: you will likely need to use php_gd2.dll instead of php_gd.dll
|
64 |
|
|
*/
|
65 |
|
|
$szPHPMapScriptModule = 'php_mapscript.'.PHP_SHLIB_SUFFIX;
|
66 |
|
|
$szPHPGDModule = 'php_gd.'.PHP_SHLIB_SUFFIX;
|
67 |
|
|
|
68 |
|
|
/******************************************************************************
|
69 |
|
|
* tile generation parameters
|
70 |
|
|
*
|
71 |
|
|
* kaMap! generates tiles to load in the client application by first rendering
|
72 |
|
|
* larger areas from the map file and then slicing them up into smaller tiles.
|
73 |
|
|
* This approach reduces the overhead of loading PHP/MapScript and PHP GD and
|
74 |
|
|
* drawing the map file. These larger areas are referred to as metaTiles in
|
75 |
|
|
* the code. You can set the size of both the small tiles and the metaTiles
|
76 |
|
|
* here. A reasonable size for the small tiles seems to be 200 pixels square.
|
77 |
|
|
* Smaller tiles seem to cause problems in client browsers by causing too many
|
78 |
|
|
* images to be created and thus slowing performance of live dragging. Larger
|
79 |
|
|
* tiles take longer to download to the client and are inefficient.
|
80 |
|
|
*
|
81 |
|
|
* The number of smaller tiles that form a metaTile can also be configured.
|
82 |
|
|
* This parameter allows tuning of the tile generator to ensure optimal
|
83 |
|
|
* performance and for label placement. MapServer will produce labels only
|
84 |
|
|
* within a rendered area. If the area is too small then features may be
|
85 |
|
|
* labelled multiple times. If the area is too large, it may exceed MapServer,s
|
86 |
|
|
* maximum map size (by default 2000x2000) or be too resource-intensive on the
|
87 |
|
|
* server, ultimately reducing performance.
|
88 |
|
|
*/
|
89 |
|
|
$tileWidth = 256;
|
90 |
|
|
$tileHeight = 256;
|
91 |
|
|
$metaWidth = 5;
|
92 |
|
|
$metaHeight = 5;
|
93 |
|
|
/* $metaBuffer = Buffer size in pixels to add around metatiles to avoid
|
94 |
|
|
* rendering issues along the edge of the map image
|
95 |
|
|
*/
|
96 |
|
|
$metaBuffer = 10;
|
97 |
|
|
|
98 |
|
|
/******************************************************************************
|
99 |
|
|
* in-image debugging information - tile location, outlines etc.
|
100 |
|
|
* to use this, you need to remove images from your cache first. This also
|
101 |
|
|
* affects the meta tiles - if debug is on, they are not deleted.
|
102 |
|
|
*/
|
103 |
|
|
$bDebug = false;
|
104 |
|
|
|
105 |
|
|
/******************************************************************************
|
106 |
|
|
* aszMapFiles - an array of map files available to the application. How this
|
107 |
|
|
* is used is determined by the application. Each map file is entered into
|
108 |
|
|
* this array as a key->value pair.
|
109 |
|
|
*
|
110 |
|
|
* The key is the name to be used by the tile caching system to store cached
|
111 |
|
|
* tiles within the base cache directory. This key should be a single word
|
112 |
|
|
* that uniquely identifies the map.
|
113 |
|
|
*
|
114 |
|
|
* The value associated with each key is an array of three values. The first
|
115 |
|
|
* value is a human-readable name to be presented to the user (should the
|
116 |
|
|
* application choose to do so) and the second value is the path to the map
|
117 |
|
|
* file. It is assumed that the map file is fully configured for use with
|
118 |
|
|
* MapServer/MapScript as no error checking or setting of values is done. The
|
119 |
|
|
* third value is an array of scale values for zooming.
|
120 |
|
|
*/
|
121 |
|
|
|
122 |
|
|
$aszMapFiles = array(
|
123 |
|
|
"world" => array( "World", "/path/to/your/mapfile",
|
124 |
|
|
array( 10000 ), # in openlayers, the scale array doesn't matter.
|
125 |
|
|
"PNG24")
|
126 |
|
|
|
127 |
|
|
/* Add more elements to this array to offer multiple mapfiles */
|
128 |
|
|
|
129 |
|
|
);
|
130 |
|
|
|
131 |
|
|
/******************************************************************************
|
132 |
|
|
* figure out which map file to use and set up the necessary variables for
|
133 |
|
|
* the rest of the code to use. This does need to be done on every page load
|
134 |
|
|
* unfortunately.
|
135 |
|
|
*
|
136 |
|
|
* szMap should be set to the default map file to use but can change if
|
137 |
|
|
* this script is called with map=<mapname>.
|
138 |
|
|
*/
|
139 |
|
|
$szMap = 'world';
|
140 |
|
|
|
141 |
|
|
/******************************************************************************
|
142 |
|
|
* kaMap! caching
|
143 |
|
|
*
|
144 |
|
|
* this is the directory within which kaMap! will create its tile cache. The
|
145 |
|
|
* directory does NOT have to be web-accessible, but it must be writable by the
|
146 |
|
|
* web-server-user and allow creation of both directories AND files.
|
147 |
|
|
*
|
148 |
|
|
* the tile caching system will create a separate subdirectory within the base
|
149 |
|
|
* cache directory for each map file. Within the cache directory for each map
|
150 |
|
|
* file, directories will be created for each group of layers. Within the group
|
151 |
|
|
* directories, directories will be created at each of the configured scales
|
152 |
|
|
* for the application (see mapfile configuration above.)
|
153 |
|
|
*/
|
154 |
|
|
$szBaseCacheDir = "/var/cache/kamap/";
|
155 |
|
|
|
156 |
|
|
/***** END OF CONFIGURABLE STUFF - unless you know what you are doing *****/
|
157 |
|
|
/***** *****/
|
158 |
|
|
/***** *****/
|
159 |
|
|
/***** *****/
|
160 |
|
|
/***** END OF CONFIGURABLE STUFF - unless you know what you are doing *****/
|
161 |
|
|
|
162 |
|
|
if (isset($_REQUEST['map']) && isset($aszMapFiles[$_REQUEST['map']]))
|
163 |
|
|
{
|
164 |
|
|
$szMap = $_REQUEST['map'];
|
165 |
|
|
}
|
166 |
|
|
|
167 |
|
|
$szMapCacheDir = $szBaseCacheDir.$szMap."/";
|
168 |
|
|
$szMapName = $aszMapFiles[$szMap][0];
|
169 |
|
|
$szMapFile = $aszMapFiles[$szMap][1];
|
170 |
|
|
$anScales = $aszMapFiles[$szMap][2];
|
171 |
|
|
setOutputFormat($aszMapFiles[$szMap][3]);
|
172 |
|
|
/******************************************************************************
|
173 |
|
|
* output format of the map and resulting tiles
|
174 |
|
|
*
|
175 |
|
|
* The output format used with MapServer can greatly affect appearance and
|
176 |
|
|
* performance. It is recommended to use an 8 bit format such as PNG
|
177 |
|
|
*
|
178 |
|
|
* NOTE: the tile caching code in tile.php is not configurable here. It
|
179 |
|
|
* currently assumes that it is outputting 8bit PNG files. If you change to
|
180 |
|
|
* PNG24 here then you will need to update tile.php to use the gd function
|
181 |
|
|
* imagecreatetruecolor. If you change the output format to jpeg then
|
182 |
|
|
* you would need to change imagepng() to imagejpeg(). A nice enhancement
|
183 |
|
|
* would be to make that fully configurable from here.
|
184 |
|
|
*/
|
185 |
|
|
function setOutputFormat($szFormat)
|
186 |
|
|
{
|
187 |
|
|
switch($szFormat) {
|
188 |
|
|
case "PNG24":
|
189 |
|
|
$GLOBALS['szMapImageFormat'] = 'PNG24'; //mapscript format name
|
190 |
|
|
$GLOBALS['szMapImageCreateFunction'] = "imagecreatefrompng"; // appropriate GD function
|
191 |
|
|
$GLOBALS['szImageExtension'] = '.png'; //file extension
|
192 |
|
|
$GLOBALS['szImageCreateFunction'] = "imagecreatetruecolor"; //or imagecreatetruecolor if PNG24 ...
|
193 |
|
|
$GLOBALS['szImageOutputFunction'] = "imagepng"; //or imagegif, imagejpeg ...
|
194 |
|
|
$GLOBALS['szImageHeader'] = 'image/png'; //the content-type of the image
|
195 |
|
|
break;
|
196 |
|
|
case "GIF":
|
197 |
|
|
$GLOBALS['szMapImageFormat'] = 'GIF'; //mapscript format name
|
198 |
|
|
$GLOBALS['szMapImageCreateFunction'] = "imagecreatefromgif"; // appropriate GD function
|
199 |
|
|
$GLOBALS['szImageExtension'] = '.gif'; //file extension
|
200 |
|
|
$GLOBALS['szImageCreateFunction'] = "imagecreate"; //or imagecreatetruecolor if PNG24 ...
|
201 |
|
|
$GLOBALS['szImageOutputFunction'] = "imagegif"; //or imagegif, imagejpeg ...
|
202 |
|
|
$GLOBALS['szImageHeader'] = 'image/gif'; //the content-type of the image
|
203 |
|
|
break;
|
204 |
|
|
case "JPEG":
|
205 |
|
|
$GLOBALS['szMapImageFormat'] = 'JPEG'; //mapscript format name
|
206 |
|
|
$GLOBALS['szMapImageCreateFunction'] = "imagecreatefromjpeg"; // appropriate GD function
|
207 |
|
|
$GLOBALS['szImageExtension'] = '.jpg'; //file extension
|
208 |
|
|
$GLOBALS['szImageCreateFunction'] = "imagecreatetruecolor"; //or imagecreatetruecolor if PNG24 ...
|
209 |
|
|
$GLOBALS['szImageOutputFunction'] = "imagejpeg"; //or imagegif, imagejpeg ...
|
210 |
|
|
$GLOBALS['szImageHeader'] = 'image/jpeg'; //the content-type of the image
|
211 |
|
|
break;
|
212 |
|
|
case "PNG":
|
213 |
|
|
$GLOBALS['szMapImageFormat'] = 'PNG'; //mapscript format name
|
214 |
|
|
$GLOBALS['szMapImageCreateFunction'] = "imagecreatefrompng"; // appropriate GD function
|
215 |
|
|
$GLOBALS['szImageExtension'] = '.png'; //file extension
|
216 |
|
|
$GLOBALS['szImageCreateFunction'] = "imagecreate"; //or imagecreatetruecolor if PNG24 ...
|
217 |
|
|
$GLOBALS['szImageOutputFunction'] = "imagepng"; //or imagegif, imagejpeg ...
|
218 |
|
|
$GLOBALS['szImageHeader'] = 'image/png'; //the content-type of the image
|
219 |
|
|
break;
|
220 |
|
|
case "DITHERED":
|
221 |
|
|
case "PNG8":
|
222 |
|
|
$GLOBALS['szMapImageFormat'] = 'dithered';
|
223 |
|
|
$GLOBALS['szMapImageCreateFunction'] = "imagecreatefrompng";
|
224 |
|
|
$GLOBALS['szImageExtension'] = '.png';
|
225 |
|
|
$GLOBALS['szImageCreateFunction'] = "imagecreate";
|
226 |
|
|
$GLOBALS['szImageOutputFunction'] = "imagepng";
|
227 |
|
|
$GLOBALS['szImageHeader'] = 'image/png';
|
228 |
|
|
break;
|
229 |
|
|
}
|
230 |
|
|
}
|
231 |
|
|
|
232 |
|
|
/**
|
233 |
|
|
* create all directories in a directory tree - found on the php web site
|
234 |
|
|
* under the mkdir function ...
|
235 |
|
|
*/
|
236 |
|
|
function makeDirs($strPath, $mode = 0775)
|
237 |
|
|
{
|
238 |
|
|
return is_dir($strPath) or ( makeDirs(dirname($strPath), $mode) and mkdir($strPath, $mode) );
|
239 |
|
|
}
|
240 |
|
|
|
241 |
|
|
/**
|
242 |
|
|
* This function replaces all special characters in the given string.
|
243 |
|
|
*
|
244 |
|
|
* @param szString string - The string to convert.
|
245 |
|
|
*
|
246 |
|
|
* @return string converted
|
247 |
|
|
*/
|
248 |
|
|
function normalizeString($szString)
|
249 |
|
|
{
|
250 |
|
|
// Normalize string by replacing all special characters
|
251 |
|
|
// e.g. "http://my.host.com/cgi-bin/mywms?"
|
252 |
|
|
// becomes "http___my_host_com_cgi_bin_mywms_"
|
253 |
|
|
return preg_replace("/(\W)/", "_", $szString);
|
254 |
|
|
}
|
255 |
|
|
|
256 |
|
|
/* bug 1253 - root permissions required to delete cached files */
|
257 |
|
|
$orig_umask = umask(0);
|
258 |
|
|
|
259 |
|
|
/* create the main cache directory if necessary */
|
260 |
|
|
if (!@is_dir($szMapCacheDir))
|
261 |
|
|
makeDirs($szMapCacheDir);
|
262 |
|
|
|
263 |
|
|
/* get the various request parameters
|
264 |
|
|
* also need to make sure inputs are clean, especially those used to
|
265 |
|
|
* build paths and filenames
|
266 |
|
|
*/
|
267 |
|
|
/*
|
268 |
|
|
* the tile renderer accepts several parameters and returns a tile image from
|
269 |
|
|
* the cache, creating the tile only if necessary.
|
270 |
|
|
*
|
271 |
|
|
* all requests include the pixel location of the request at a certain scale
|
272 |
|
|
* and this script figures out the geographic location of the tile from the
|
273 |
|
|
* scale assuming that 0,0 in pixels is 0,0 in geographic units
|
274 |
|
|
*
|
275 |
|
|
* Request parameters are:
|
276 |
|
|
*
|
277 |
|
|
* map: the name of the map to use. This is handled by config.php.
|
278 |
|
|
*
|
279 |
|
|
* t: top pixel position
|
280 |
|
|
* l: left pixel position
|
281 |
|
|
* s: scale
|
282 |
|
|
* g: (optional) comma-delimited list of group names to draw
|
283 |
|
|
* layers: (optional) comma-delimited list of layers to draw
|
284 |
|
|
* force: optional. If set, force redraw of the meta tile. This was added to
|
285 |
|
|
* help with invalid images sometimes being generated.
|
286 |
|
|
* tileid: (optional) can be used instead of t+l to specify the tile coord.,
|
287 |
|
|
* useful in regenerating the cache
|
288 |
|
|
*/
|
289 |
|
|
|
290 |
|
|
$top = isset( $_REQUEST['t'] ) ? intval($_REQUEST['t']) : 0;
|
291 |
|
|
$left = isset( $_REQUEST['l'] ) ? intval($_REQUEST['l']) : 0;
|
292 |
|
|
$scale = isset( $_REQUEST['s'] ) ? $_REQUEST['s'] : $anScales[0];
|
293 |
|
|
$bForce = isset($_REQUEST['force'])? true : false;
|
294 |
|
|
$groups = isset( $_REQUEST['g'] ) ? $_REQUEST['g'] : "";
|
295 |
|
|
$layers = isset( $_REQUEST['layers'] ) ? $_REQUEST['layers'] : "";
|
296 |
|
|
|
297 |
|
|
// dynamic imageformat ----------------------------------------------
|
298 |
|
|
//use the function in config.php to set the output format
|
299 |
|
|
if (isset($_REQUEST['i']))
|
300 |
|
|
setOutputFormat( $_REQUEST['i'] );
|
301 |
|
|
//----------------------------------------------------------------
|
302 |
|
|
|
303 |
|
|
/* tileid=t#####l#### can be used instead of t+l parameters. Useful in
|
304 |
|
|
* regenerating the cache for instance.
|
305 |
|
|
*/
|
306 |
|
|
if (isset( $_REQUEST['tileid']) &&
|
307 |
|
|
preg_match("/t(-?\d+)l(-?\d+)/", $_REQUEST['tileid'], $aMatch) )
|
308 |
|
|
{
|
309 |
|
|
$top = intval($aMatch[1]);
|
310 |
|
|
$left = intval($aMatch[2]);
|
311 |
|
|
}
|
312 |
|
|
|
313 |
|
|
/* Calculate the metatile's top-left corner coordinates.
|
314 |
|
|
* Include the $metaBuffer around the metatile to account for various
|
315 |
|
|
* rendering issues happening around the edge of a map
|
316 |
|
|
*/
|
317 |
|
|
$metaLeft = floor( ($left)/($tileWidth*$metaWidth) ) * $tileWidth * $metaWidth;
|
318 |
|
|
$metaTop = floor( ($top)/($tileHeight*$metaHeight) ) * $tileHeight *$metaHeight;
|
319 |
|
|
$szMetaTileId = "t".$metaTop."l".$metaLeft;
|
320 |
|
|
$metaLeft -= $metaBuffer;
|
321 |
|
|
$metaTop -= $metaBuffer;
|
322 |
|
|
|
323 |
|
|
/* caching is done by scale value, then groups and layers and finally metatile
|
324 |
|
|
* and tile id. Create a new directory if necessary
|
325 |
|
|
*/
|
326 |
|
|
$szGroupDir = $groups != "" ? normalizeString($groups) : "def";
|
327 |
|
|
$szLayerDir = $layers != "" ? normalizeString($layers) : "def";
|
328 |
|
|
|
329 |
|
|
$szCacheDir = $szMapCacheDir."/".$scale."/".$szGroupDir."/".$szLayerDir."/".$szMetaTileId;
|
330 |
|
|
if (!@is_dir($szCacheDir))
|
331 |
|
|
makeDirs($szCacheDir);
|
332 |
|
|
|
333 |
|
|
/* resolve cache hit - clear the os stat cache if necessary */
|
334 |
|
|
$szTileId = "t".$top."l".$left;
|
335 |
|
|
$szCacheFile = $szCacheDir."/".$szTileId.$szImageExtension;
|
336 |
|
|
clearstatcache();
|
337 |
|
|
|
338 |
|
|
$szMetaDir = $szCacheDir."/meta";
|
339 |
|
|
if (!@is_Dir($szMetaDir))
|
340 |
|
|
makeDirs($szMetaDir);
|
341 |
|
|
|
342 |
|
|
/* simple locking in case there are several requests for the same meta
|
343 |
|
|
tile at the same time - only draw it once to help with performance */
|
344 |
|
|
$szLockFile = $szMetaDir."/lock_".$metaTop."_".$metaLeft;
|
345 |
|
|
$fpLockFile = fopen($szLockFile, "a+");
|
346 |
|
|
clearstatcache();
|
347 |
|
|
if (!file_exists($szCacheFile) || $bForce)
|
348 |
|
|
{
|
349 |
|
|
flock($fpLockFile, LOCK_EX);
|
350 |
|
|
fwrite($fpLockFile, ".");
|
351 |
|
|
|
352 |
|
|
//check once more to see if the cache file was created while waiting for
|
353 |
|
|
//the lock
|
354 |
|
|
clearstatcache();
|
355 |
|
|
if (!file_exists($szCacheFile) || $bForce)
|
356 |
|
|
{
|
357 |
|
|
if (!extension_loaded('MapScript'))
|
358 |
|
|
{
|
359 |
|
|
dl( $szPHPMapScriptModule );
|
360 |
|
|
}
|
361 |
|
|
if (!extension_loaded('gd'))
|
362 |
|
|
{
|
363 |
|
|
dl( $szPHPGDModule);
|
364 |
|
|
}
|
365 |
|
|
|
366 |
|
|
if (!@is_Dir($szMetaDir))
|
367 |
|
|
makeDirs($szMetaDir);
|
368 |
|
|
|
369 |
|
|
$oMap = ms_newMapObj($szMapFile);
|
370 |
|
|
|
371 |
|
|
/* Metatile width/height include 2x the metaBuffer value */
|
372 |
|
|
$oMap->set('width', $tileWidth * $metaWidth + 2*$metaBuffer);
|
373 |
|
|
$oMap->set('height', $tileHeight * $metaHeight + 2*$metaBuffer);
|
374 |
|
|
|
375 |
|
|
/* Tell MapServer to not render labels inside the metaBuffer area
|
376 |
|
|
* (new in 4.6)
|
377 |
|
|
* TODO: Until MapServer bugs 1353/1355 are resolved, we need to
|
378 |
|
|
* pass a negative value for "labelcache_map_edge_buffer"
|
379 |
|
|
*/
|
380 |
|
|
$oMap->setMetadata("labelcache_map_edge_buffer", -$metaBuffer);
|
381 |
|
|
|
382 |
|
|
$inchesPerUnit = array(1, 12, 63360.0, 39.3701, 39370.1, 4374754);
|
383 |
|
|
$geoWidth = $scale/($oMap->resolution*$inchesPerUnit[$oMap->units]);
|
384 |
|
|
$geoHeight = $scale/($oMap->resolution*$inchesPerUnit[$oMap->units]);
|
385 |
|
|
|
386 |
|
|
/* draw the metatile */
|
387 |
|
|
$minx = $metaLeft * $geoWidth;
|
388 |
|
|
$maxx = $minx + $geoWidth * $oMap->width;
|
389 |
|
|
$maxy = -1 * $metaTop * $geoHeight;
|
390 |
|
|
$miny = $maxy - $geoHeight * $oMap->height;
|
391 |
|
|
|
392 |
|
|
$nLayers = $oMap->numlayers;
|
393 |
|
|
$oMap->setExtent($minx,$miny,$maxx,$maxy);
|
394 |
|
|
$oMap->selectOutputFormat( $szMapImageFormat );
|
395 |
|
|
$aszLayers = array();
|
396 |
|
|
if ($groups || $layers)
|
397 |
|
|
{
|
398 |
|
|
/* Draw only specified layers instead of default from mapfile*/
|
399 |
|
|
if ($layers)
|
400 |
|
|
{
|
401 |
|
|
$aszLayers = explode(",", $layers);
|
402 |
|
|
}
|
403 |
|
|
|
404 |
|
|
if ($groups)
|
405 |
|
|
{
|
406 |
|
|
$aszGroups = explode(",", $groups);
|
407 |
|
|
}
|
408 |
|
|
|
409 |
|
|
for($i=0;$i<$nLayers;$i++)
|
410 |
|
|
{
|
411 |
|
|
$oLayer = $oMap->getLayer($i);
|
412 |
|
|
if (($aszGroups && in_array($oLayer->group,$aszGroups)) ||
|
413 |
|
|
($aszLayers && in_array($oLayer->name,$aszLayers)) ||
|
414 |
|
|
($aszGroups && $oLayer->group == '' &&
|
415 |
|
|
in_array( "__base__", $aszGroups)))
|
416 |
|
|
{
|
417 |
|
|
$oLayer->set("status", MS_ON );
|
418 |
|
|
}
|
419 |
|
|
else
|
420 |
|
|
{
|
421 |
|
|
$oLayer->set("status", MS_OFF );
|
422 |
|
|
}
|
423 |
|
|
}
|
424 |
|
|
//need transparency if groups or layers are used
|
425 |
|
|
$oMap->outputformat->set("transparent", MS_ON );
|
426 |
|
|
}
|
427 |
|
|
else
|
428 |
|
|
{
|
429 |
|
|
$oMap->outputformat->set("transparent", MS_OFF );
|
430 |
|
|
}
|
431 |
|
|
|
432 |
|
|
|
433 |
|
|
$szMetaImg = $szMetaDir."/t".$metaTop."l".$metaLeft.$szImageExtension;
|
434 |
|
|
$oImg = $oMap->draw();
|
435 |
|
|
$oImg->saveImage($szMetaImg);
|
436 |
|
|
$oImg->free();
|
437 |
|
|
eval("\$oGDImg = ".$szMapImageCreateFunction."('".$szMetaImg."');");
|
438 |
|
|
if ($bDebug)
|
439 |
|
|
{
|
440 |
|
|
$blue = imagecolorallocate($oGDImg, 0, 0, 255);
|
441 |
|
|
imagerectangle($oGDImg, 0, 0, $tileWidth * $metaWidth - 1, $tileHeight * $metaHeight - 1, $blue );
|
442 |
|
|
}
|
443 |
|
|
for($i=0;$i<$metaWidth;$i++)
|
444 |
|
|
{
|
445 |
|
|
for ($j=0;$j<$metaHeight;$j++)
|
446 |
|
|
{
|
447 |
|
|
eval("\$oTile = ".$szImageCreateFunction."( ".$tileWidth.",".$tileHeight." );");
|
448 |
|
|
// Allocate BG color for the tile (in case the metatile has transparent BG)
|
449 |
|
|
$nTransparent = imagecolorallocate($oTile, $oMap->imagecolor->red, $oMap->imagecolor->green, $oMap->imagecolor->blue);
|
450 |
|
|
//if ($oMap->outputformat->transparent == MS_ON)
|
451 |
|
|
//{
|
452 |
|
|
imagecolortransparent( $oTile,$nTransparent);
|
453 |
|
|
//}
|
454 |
|
|
$tileTop = $j*$tileHeight + $metaBuffer;
|
455 |
|
|
$tileLeft = $i*$tileWidth + $metaBuffer;
|
456 |
|
|
imagecopy( $oTile, $oGDImg, 0, 0, $tileLeft, $tileTop, $tileWidth, $tileHeight );
|
457 |
|
|
/* debugging stuff */
|
458 |
|
|
if ($bDebug)
|
459 |
|
|
{
|
460 |
|
|
$black = imagecolorallocate($oTile, 1, 1, 1);
|
461 |
|
|
$green = imagecolorallocate($oTile, 0, 128, 0 );
|
462 |
|
|
$red = imagecolorallocate($oTile, 255, 0, 0);
|
463 |
|
|
imagerectangle( $oTile, 1, 1, $tileWidth-2, $tileHeight-2, $green );
|
464 |
|
|
imageline( $oTile, 0, $tileHeight/2, $tileWidth-1, $tileHeight/2, $red);
|
465 |
|
|
imageline( $oTile, $tileWidth/2, 0, $tileWidth/2, $tileHeight-1, $red);
|
466 |
|
|
imagestring ( $oTile, 3, 10, 10, ($metaLeft+$tileLeft)." x ".($metaTop+$tileTop), $black );
|
467 |
|
|
imagestring ( $oTile, 3, 10, 30, ($minx+$i*$geoWidth)." x ".($maxy - $j*$geoHeight), $black );
|
468 |
|
|
}
|
469 |
|
|
$szTileImg = $szCacheDir."/t".($metaTop+$tileTop)."l".($metaLeft+$tileLeft).$szImageExtension;
|
470 |
|
|
eval("$szImageOutputFunction( \$oTile, '".$szTileImg."' );");
|
471 |
|
|
imagedestroy($oTile);
|
472 |
|
|
$oTile = null;
|
473 |
|
|
}
|
474 |
|
|
}
|
475 |
|
|
if ($oGDImg != null)
|
476 |
|
|
{
|
477 |
|
|
imagedestroy($oGDImg);
|
478 |
|
|
$oGDImg = null;
|
479 |
|
|
}
|
480 |
|
|
if (!$bDebug)
|
481 |
|
|
{
|
482 |
|
|
unlink( $szMetaImg );
|
483 |
|
|
}
|
484 |
|
|
}
|
485 |
|
|
//release the exclusive lock
|
486 |
|
|
flock($fpLockFile, LOCK_UN );
|
487 |
|
|
}
|
488 |
|
|
|
489 |
|
|
//acquire shared lock for reading to prevent a problem that could occur
|
490 |
|
|
//if a tile exists but is only partially generated.
|
491 |
|
|
flock($fpLockFile, LOCK_SH);
|
492 |
|
|
|
493 |
|
|
$h = fopen($szCacheFile, "r");
|
494 |
|
|
header("Content-Type: ".$szImageHeader);
|
495 |
|
|
header("Content-Length: " . filesize($szCacheFile));
|
496 |
|
|
header("Expires: " . date( "D, d M Y H:i:s GMT", time() + 31536000 ));
|
497 |
|
|
header("Cache-Control: max-age=31536000, must-revalidate" );
|
498 |
|
|
fpassthru($h);
|
499 |
|
|
fclose($h);
|
500 |
|
|
|
501 |
|
|
//release lock
|
502 |
|
|
fclose($fpLockFile);
|
503 |
|
|
|
504 |
|
|
/* bug 1253 - root permissions required to delete cached files */
|
505 |
|
|
umask($orig_umask);
|
506 |
|
|
|
507 |
|
|
exit;
|
508 |
|
|
?>
|