30
30
#include "maptile.h"
31
31
#include "mapproject.h"
33
static void msTileResetMetatileLevel(mapObj *map) {
34
hashTableObj *meta = &(map->web.metadata);
35
const char *zero = "0";
36
const char *value = NULL;
38
/* Is the tile_metatile_levetl set... */
39
if((value = msLookupHashTable(meta, "tile_metatile_level")) != NULL) {
40
msRemoveHashTable(meta, "tile_metatile_level");
41
msInsertHashTable(meta, "tile_metatile_level", zero);
43
/* No tile_metatile_level value. */
45
msInsertHashTable(meta, "tile_metatile_level", zero);
49
/************************************************************************
50
* msTileGetGMapCoords *
51
************************************************************************/
52
static int msTileGetGMapCoords(const char *coordstring, int *x, int *y, int *zoom) {
58
coords = msStringSplit(coordstring, ' ', &(num_coords));
59
if( num_coords != 3 ) {
60
msSetError(MS_WEBERR, "Invalid number of tile coordinates (should be three).", "msTileSetup()");
65
msSetError(MS_WEBERR, "Tile parameter not set.", "msTileSetup()");
70
*x = strtol(coords[0], NULL, 10);
72
*y = strtol(coords[1], NULL, 10);
74
*zoom = strtol(coords[2], NULL, 10);
80
/************************************************************************
82
************************************************************************/
83
static void msTileGetParams(mapObj *map, tileParams *params) {
85
const char *value = NULL;
86
hashTableObj *meta = &(map->web.metadata);
88
params->tile_size = SPHEREMERC_IMAGE_SIZE;
90
/* Check for tile buffer, set to buffer==0 as default */
91
if((value = msLookupHashTable(meta, "tile_map_edge_buffer")) != NULL) {
92
params->map_edge_buffer = atoi(value);
94
msDebug("msTileSetParams(): tile_map_edge_buffer = %d\n", params->map_edge_buffer);
97
params->map_edge_buffer = 0;
99
/* Check for metatile size, set to tile==metatile as default */
100
if((value = msLookupHashTable(meta, "tile_metatile_level")) != NULL) {
101
params->metatile_level = atoi(value);
102
/* Quietly force metatile_level to be sane */
103
if( params->metatile_level < 0 )
104
params->metatile_level = 0;
105
if( params->metatile_level > 2 )
106
params->metatile_level = 2;
108
msDebug("msTileSetParams(): tile_metatile_level = %d\n", params->metatile_level);
111
params->metatile_level = 0;
115
/************************************************************************
116
* msTileExtractSubTile *
118
************************************************************************/
119
static imageObj* msTileExtractSubTile(const mapservObj *msObj, const imageObj *img) {
121
int width, height, mini, minj, maxi, maxj;
123
imageObj* imgOut = NULL;
125
rendererVTableObj *renderer;
126
rasterBufferObj imgBuffer;
128
if( !MS_RENDERER_PLUGIN(msObj->map->outputformat)
129
|| msObj->map->outputformat->renderer != img->format->renderer ||
130
! MS_MAP_RENDERER(msObj->map)->supports_pixel_buffer ) {
131
msSetError(MS_MISCERR,"unsupported or mixed renderers","msTileExtractSubTile()");
134
renderer = MS_MAP_RENDERER(msObj->map);
136
if (renderer->getRasterBufferHandle((imageObj*)img,&imgBuffer) != MS_SUCCESS) {
142
** Load the metatiling information from the map file.
144
msTileGetParams(msObj->map, ¶ms);
147
** Initialize values for the metatile clip area.
149
width = img->width - 2*params.map_edge_buffer;
150
height = img->height - 2*params.map_edge_buffer;
151
mini = params.map_edge_buffer;
152
minj = params.map_edge_buffer;
153
maxi = img->width - params.map_edge_buffer - 1;
154
maxj = img->height - params.map_edge_buffer - 1;
156
if( msObj->TileMode == TILE_GMAP ) {
159
if( msObj->TileCoords ) {
160
if( msTileGetGMapCoords(msObj->TileCoords, &x, &y, &zoom) == MS_FAILURE )
164
msSetError(MS_WEBERR, "Tile parameter not set.", "msTileSetup()");
168
if(msObj->map->debug)
169
msDebug("msTileExtractSubTile(): gmaps coords (x: %d, y: %d)\n",x,y);
172
** The bottom N bits of the coordinates give us the subtile
173
** location relative to the metatile.
175
x = (0xffff ^ (0xffff << params.metatile_level)) & x;
176
y = (0xffff ^ (0xffff << params.metatile_level)) & y;
178
if(msObj->map->debug)
179
msDebug("msTileExtractSubTile(): gmaps image coords (x: %d, y: %d)\n",x,y);
181
mini = mini + x * params.tile_size;
182
minj = minj + y * params.tile_size;
185
else if( msObj->TileMode == TILE_VE ) {
190
if( strlen( msObj->TileCoords ) - params.metatile_level < 0 ) {
195
** Process the last elements of the VE coordinate string to place the
196
** requested tile in the context of the metatile
198
for( i = strlen( msObj->TileCoords ) - params.metatile_level;
199
i < strlen( msObj->TileCoords );
202
j = msObj->TileCoords[i];
203
tsize = width / zoom;
204
if( j == '1' || j == '3' ) mini += tsize;
205
if( j == '2' || j == '3' ) minj += tsize;
210
return(NULL); /* Huh? Should have a mode. */
213
imgOut = msImageCreate(params.tile_size, params.tile_size, msObj->map->outputformat, NULL, NULL, msObj->map->resolution, msObj->map->defresolution, NULL);
215
if( imgOut == NULL ) {
219
if(msObj->map->debug)
220
msDebug("msTileExtractSubTile(): extracting (%d x %d) tile, top corner (%d, %d)\n",params.tile_size,params.tile_size,mini,minj);
224
renderer->mergeRasterBuffer(imgOut,&imgBuffer,1.0,mini, minj,0, 0,params.tile_size, params.tile_size);
33
230
/************************************************************************
131
335
#ifdef USE_TILE_API
133
337
mapObj *map = msObj->map;
338
double dx, dy, buffer;
341
/* Read the tile-mode map file parameters */
342
msTileGetParams(msObj->map, ¶ms);
136
344
if( msObj->TileMode == TILE_GMAP ) {
139
char **coords = NULL;
141
346
double zoomfactor, tilesize, xmin, xmax, ymin, ymax;
143
348
if( msObj->TileCoords ) {
144
coords = msStringSplit(msObj->TileCoords, ' ', &(num_coords));
145
if( num_coords != 3 ) {
146
msSetError(MS_WEBERR, "Invalid number of tile coordinates (should be three).", "msTileSetExtent()");
349
if( msTileGetGMapCoords(msObj->TileCoords, &x, &y, &zoom) == MS_FAILURE )
151
353
msSetError(MS_WEBERR, "Tile parameter not set.", "msTileSetup()");
155
x = strtol(coords[0], NULL, 10);
156
y = strtol(coords[1], NULL, 10);
157
zoom = strtol(coords[2], NULL, 10);
358
msDebug("msTileSetExtent(): gmaps coords (x: %d, y: %d, z: %d)\n",x,y,zoom);
361
** If we are metatiling, adjust the zoom level appropriately,
362
** then scale back the x/y coordinates to match the new level.
364
if( params.metatile_level > 0 ) {
365
zoom = zoom - params.metatile_level;
366
x = x >> params.metatile_level;
367
y = y >> params.metatile_level;
371
msDebug("msTileSetExtent(): gmaps metacoords (x: %d, y: %d, z: %d)\n",x,y,zoom);
159
373
zoomfactor = pow(2.0, (double)zoom);
162
* Calculate the ground extents of the tile request.
376
** Calculate the ground extents of the tile request.
164
378
/* printf("X: %i Y: %i Z: %i\n",x,y,zoom); */
165
379
tilesize = SPHEREMERC_GROUND_SIZE / zoomfactor;
166
380
xmin = (x * tilesize) - (SPHEREMERC_GROUND_SIZE / 2.0);
205
423
return(MS_FAILURE); /* Huh? Should have a mode. */
427
** Set the output tile size.
429
msObj->ImgCols = SPHEREMERC_IMAGE_SIZE << params.metatile_level;
430
msObj->ImgRows = SPHEREMERC_IMAGE_SIZE << params.metatile_level;
431
map->width = SPHEREMERC_IMAGE_SIZE << params.metatile_level;
432
map->height = SPHEREMERC_IMAGE_SIZE << params.metatile_level;
435
msDebug("msTileSetExtent(): base image size (%d x %d)\n",map->width,map->height);
439
** First calculate ground units in the buffer at current extent
441
buffer = params.map_edge_buffer * (map->extent.maxx - map->extent.minx) / (double)map->width;
443
** Then adjust the map extents out by that amount
445
map->extent.minx -= buffer;
446
map->extent.maxx += buffer;
447
map->extent.miny -= buffer;
448
map->extent.maxy += buffer;
450
** Finally adjust the map image size by the pixel buffer
452
map->width += 2 * params.map_edge_buffer;
453
map->height += 2 * params.map_edge_buffer;
454
msObj->ImgCols += 2 * params.map_edge_buffer;
455
msObj->ImgRows += 2 * params.map_edge_buffer;
458
msDebug("msTileSetExtent(): buffered image size (%d x %d)\n",map->width,map->height);
209
461
** Adjust the extents inwards by 1/2 pixel so they are from
216
468
dy = (map->extent.maxy - map->extent.miny) / map->height;
217
469
map->extent.miny += dy*0.5;
218
470
map->extent.maxy -= dy*0.5;
221
** Set the output tile size.
473
** Ensure the labelcache buffer is greater than the tile buffer.
223
msObj->ImgCols = SPHEREMERC_IMAGE_SIZE;
224
msObj->ImgRows = SPHEREMERC_IMAGE_SIZE;
225
map->width = SPHEREMERC_IMAGE_SIZE;
226
map->height = SPHEREMERC_IMAGE_SIZE;
475
if( params.map_edge_buffer > 0 ) {
477
hashTableObj *meta = &(map->web.metadata);
478
char tilebufferstr[64];
480
/* Write the tile buffer to a string */
481
snprintf(tilebufferstr, sizeof(tilebufferstr), "-%d", params.map_edge_buffer);
483
/* Hm, the labelcache buffer is set... */
484
if((value = msLookupHashTable(meta, "labelcache_map_edge_buffer")) != NULL) {
485
/* If it's too small, replace with a bigger one */
486
if( params.map_edge_buffer > abs(atoi(value)) ) {
487
msRemoveHashTable(meta, "labelcache_map_edge_buffer");
488
msInsertHashTable(meta, "labelcache_map_edge_buffer", tilebufferstr);
491
/* No labelcache buffer value? Then we use the tile buffer. */
493
msInsertHashTable(meta, "labelcache_map_edge_buffer", tilebufferstr);
229
498
msDebug( "msTileSetExtent (%f, %f) (%f, %f)\n", map->extent.minx, map->extent.miny, map->extent.maxx, map->extent.maxy);