Skip to content

Commit

Permalink
Added support for the use of tile_map_edge_buffer when using WMS with…
Browse files Browse the repository at this point in the history
… tiled=true vendor specific parameter (WMS-C)

This is a rebase of #5199
on top of latest main, with the addition of a test.

Comments of #5199 (comment)
have been only adressed by adding appropriate TODOs in the code.

Co-authored-by: deduikertjes <deduikertjes@xs4all.nl>
  • Loading branch information
rouault and deduikertjes committed Feb 12, 2021
1 parent e69561e commit 31d255a
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 0 deletions.
89 changes: 89 additions & 0 deletions mapwms.cpp
Expand Up @@ -867,6 +867,7 @@ int msWMSLoadGetMapParams(mapObj *map, int nVersion,
const char *request = NULL;
int status = 0;
const char *layerlimit = NULL;
bool tiled = false;

const char *sldenabled=NULL;
const char *sld_url=NULL;
Expand Down Expand Up @@ -1172,6 +1173,10 @@ int msWMSLoadGetMapParams(mapObj *map, int nVersion,
else if (strcasecmp(names[i], "BBOX_PIXEL_IS_POINT") == 0) {
bbox_pixel_is_point = (strcasecmp(values[i], "TRUE") == 0);
}
/* Vendor specific TILED (WMS-C) */
else if (strcasecmp(names[i], "TILED") == 0) {
tiled = (strcasecmp(values[i], "TRUE") == 0);
}
/* Vendor-specific FILTER, added in RFC-118 */
else if (strcasecmp(names[i], "FILTER") == 0) {
filter = values[i];
Expand Down Expand Up @@ -1239,6 +1244,50 @@ int msWMSLoadGetMapParams(mapObj *map, int nVersion,
adjust_extent = true;
}

if (tiled) {
const char *value;
hashTableObj *meta = &(map->web.metadata);
int map_edge_buffer = 0;

if ((value = msLookupHashTable(meta, "tile_map_edge_buffer")) != NULL) {
map_edge_buffer = atoi(value);
}
if (map_edge_buffer > 0) {
/* adjust bbox and width and height to the buffer */
const double buffer_x = map_edge_buffer * (map->extent.maxx - map->extent.minx) / (double)map->width;
const double buffer_y = map_edge_buffer * (map->extent.maxy - map->extent.miny) / (double)map->height;

// TODO: we should probably clamp the extent to avoid going outside of -180,-90,180,90 for geographic CRS for example
map->extent.minx -= buffer_x;
map->extent.maxx += buffer_x;
map->extent.miny -= buffer_y;
map->extent.maxy += buffer_y;

map->width += 2 * map_edge_buffer;
map->height += 2 * map_edge_buffer;

if( map_edge_buffer > 0 ) {
char tilebufferstr[64];

/* Write the tile buffer to a string */
snprintf(tilebufferstr, sizeof(tilebufferstr), "-%d", map_edge_buffer);

/* Hm, the labelcache buffer is set... */
if((value = msLookupHashTable(meta, "labelcache_map_edge_buffer")) != NULL) {
/* If it's too small, replace with a bigger one */
if( map_edge_buffer > abs(atoi(value)) ) {
msRemoveHashTable(meta, "labelcache_map_edge_buffer");
msInsertHashTable(meta, "labelcache_map_edge_buffer", tilebufferstr);
}
}
/* No labelcache buffer value? Then we use the tile buffer. */
else {
msInsertHashTable(meta, "labelcache_map_edge_buffer", tilebufferstr);
}
}
}
}

/*
** If any select layers have a default time, we will apply the default
** time value even if no TIME request was in the url.
Expand Down Expand Up @@ -3718,6 +3767,46 @@ int msWMSGetMap(mapObj *map, int nVersion, char **names, char **values, int nume
img = msDrawMap(map, drawquerymap);
}

/* see if we have tiled = true and a buffer */
/* if so, clip the image */
for (int i=0; i<numentries; i++) {
if (strcasecmp(names[i], "TILED") == 0 && strcasecmp(values[i], "TRUE") == 0) {
hashTableObj *meta = &(map->web.metadata);
const char *value;

if ((value = msLookupHashTable(meta, "tile_map_edge_buffer")) != NULL) {
const int map_edge_buffer = atoi(value);
if ( map_edge_buffer > 0 ) {
/* we have to clip the image */

// TODO: we could probably avoid the use of an intermediate image
// by playing with the rasterBufferObj's data->rgb.pixels and data->rgb.row_stride values.
rendererVTableObj* renderer = MS_MAP_RENDERER(map);
rasterBufferObj imgBuffer;
if( renderer->getRasterBufferHandle((imageObj*)img,&imgBuffer) != MS_SUCCESS )
{
msFreeImage(img);
return MS_FAILURE;
}

int width = map->width - map_edge_buffer - map_edge_buffer;
int height = map->height - map_edge_buffer - map_edge_buffer;
imageObj* tmp = msImageCreate( width, height, map->outputformat, NULL, NULL, map->resolution, map->defresolution, NULL);

if((MS_FAILURE == renderer->mergeRasterBuffer(tmp,&imgBuffer,1.0,map_edge_buffer, map_edge_buffer,0, 0, width, height ))) {
msFreeImage(tmp);
msFreeImage(img);
img = NULL;
} else {
msFreeImage(img);
img = tmp;
}
}
}
break;
}
}

if (img == NULL)
return msWMSException(map, nVersion, NULL, wms_exception_format);

Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
80 changes: 80 additions & 0 deletions msautotest/wxs/wms_tiled.map
@@ -0,0 +1,80 @@
#
# Test WMS-C TILED=TRUE
#
# REQUIRES: INPUT=GDAL OUTPUT=PNG SUPPORTS=WMS

# RUN_PARMS: wms_tiled_tiled_disabled.png [MAPSERV] QUERY_STRING="map=[MAPFILE]&VERSION=1.3.0&REQUEST=GetMap&CRS=EPSG%3A4326&BBOX=44.1,-65.755,47.3,-58.375&WIDTH=400&HEIGHT=400&LAYERS=popplace&STYLES=&FORMAT=image%2Fpng" > [RESULT_DEMIME]

# RUN_PARMS: wms_tiled_tiled_enabled.png [MAPSERV] QUERY_STRING="map=[MAPFILE]&VERSION=1.3.0&REQUEST=GetMap&CRS=EPSG%3A4326&BBOX=44.1,-65.755,47.3,-58.375&WIDTH=400&HEIGHT=400&LAYERS=popplace&STYLES=&FORMAT=image%2Fpng&TILED=TRUE" > [RESULT_DEMIME]

MAP

NAME WMS_TILED
STATUS ON
SIZE 400 300
UNITS DD
IMAGECOLOR 255 255 255
SHAPEPATH ./data
SYMBOLSET etc/symbols.sym
FONTSET etc/fonts.txt

OUTPUTFORMAT
NAME GDPNG
DRIVER "GD/PNG"
MIMETYPE "image/png"
EXTENSION "png"
END


#
# Start of web interface definition
#
WEB

IMAGEPATH "/tmp/ms_tmp/"
IMAGEURL "/ms_tmp/"

METADATA
"wms_title" "Test simple wms"
"wms_onlineresource" "http://localhost/path/to/wms_simple?"
"wms_srs" "EPSG:42304 EPSG:42101 EPSG:4269 EPSG:4326"
"ows_schemas_location" "http://ogc.dmsolutions.ca"
"wms_sld_enabled" "false"
"ows_enable_request" "*"
"tile_map_edge_buffer" "50"
END
END

PROJECTION
"init=epsg:4326"
END


#
# Start of layer definitions
#


LAYER
NAME popplace
DATA popplace
METADATA
"wms_title" "popplace"
"wms_description" "Cities of I.P.E."
END
TYPE POINT
STATUS ON
PROJECTION
"init=./data/epsg2:42304"
END
DUMP TRUE
CLASS
SYMBOL 2
SIZE 40
NAME "Cities"
COLOR 0 0 0
END
END # Layer


END # Map File

0 comments on commit 31d255a

Please sign in to comment.