| 1 |
<?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: tile.php,v 1.33 2006/02/07 03:19:55 pspencer Exp $ |
|---|
| 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 |
?> |
|---|