From b6a5e6619ad6beb174c302ea64d568c642fb9ca1 Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Mon, 2 Apr 2007 17:18:38 +0000 Subject: [PATCH] #529 give tiles gutters - all layers that use Tile.Image must now look after layer.imageSize and layer.imageOffset - this is handled by layer.setTileSize - for untiled layers, setTileSize must be defined by the subclass - gutters are currently supported in Layer.Mapserver and Layer.WMS git-svn-id: http://svn.openlayers.org/trunk/openlayers@2979 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf --- examples/gutter.html | 49 +++++++++++++ examples/mapserver.html | 3 +- examples/mapserver_untiled.html | 4 +- examples/wms-untiled.html | 34 +++++++++ lib/OpenLayers/Layer.js | 86 ++++++++++++++++++++++- lib/OpenLayers/Layer/MapServer.js | 12 ++-- lib/OpenLayers/Layer/MapServer/Untiled.js | 21 ++++-- lib/OpenLayers/Layer/WMS.js | 11 +-- lib/OpenLayers/Layer/WMS/Untiled.js | 21 ++++-- lib/OpenLayers/Tile/Image.js | 43 ++++++++---- tests/Layer/test_MapServer.html | 10 +-- tests/Layer/test_MapServer_Untiled.html | 4 +- tests/Layer/test_WMS.html | 52 ++++++++++++-- tests/Tile/test_Image.html | 57 +++++++++++++-- 14 files changed, 351 insertions(+), 56 deletions(-) create mode 100644 examples/gutter.html create mode 100644 examples/wms-untiled.html diff --git a/examples/gutter.html b/examples/gutter.html new file mode 100644 index 0000000000..f8ddf64da2 --- /dev/null +++ b/examples/gutter.html @@ -0,0 +1,49 @@ + + + + + + + +

OpenLayers Gutter Example

+
+

+ When you render tiles with certain types of symbols, there are artifacts + at tile edges that make symbology not look continuous. In the center of + the above map (when it first loads), the large orange road is split + vertically by a tile. Open the layer switcher and change to the layer + with a 15 pixel gutter to see how the symbology looks nicer. +

+ + + diff --git a/examples/mapserver.html b/examples/mapserver.html index 1adb31f2ee..518e2c5950 100644 --- a/examples/mapserver.html +++ b/examples/mapserver.html @@ -18,7 +18,8 @@ function init(){ map = new OpenLayers.Map( 'map' ); layer = new OpenLayers.Layer.MapServer( "OpenLayers WMS", - "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} ); + "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'}, + {gutter: 15}); map.addLayer(layer); map.setCenter(new OpenLayers.LonLat(lon, lat), zoom); diff --git a/examples/mapserver_untiled.html b/examples/mapserver_untiled.html index b724db0dfa..123b6cf27c 100644 --- a/examples/mapserver_untiled.html +++ b/examples/mapserver_untiled.html @@ -2,8 +2,8 @@ diff --git a/examples/wms-untiled.html b/examples/wms-untiled.html new file mode 100644 index 0000000000..37edc0e01c --- /dev/null +++ b/examples/wms-untiled.html @@ -0,0 +1,34 @@ + + + + + + + +
+ + diff --git a/lib/OpenLayers/Layer.js b/lib/OpenLayers/Layer.js index c84f448365..d687237a78 100644 --- a/lib/OpenLayers/Layer.js +++ b/lib/OpenLayers/Layer.js @@ -65,12 +65,45 @@ OpenLayers.Layer.prototype = { * @type Boolean */ inRange: false, + + /** + * For layers that use Tile.Image, the image size is cached here. For + * layers without a gutter, the image size is equal to the tile size. + * For layers with a gutter, the image is larger than the tile by twice + * the gutter in each dimension. + * + * @type OpenLayers.Size + * @private + */ + imageSize: null, + + /** + * For layers that use Tile.Image, the image offset is cached here. + * Layers without a gutter have zero offset. For layers with a gutter, + * the image offset represents displacement due to the gutter. + * + * @type OpenLayers.Pixel + * @private + */ + imageOffset: null, // OPTIONS /** @type Array */ options: null, + /** Determines the width (in pixels) of the gutter around image tiles + * to ignore. By setting this property to a non-zero value, images + * will be requested that are wider and taller than the tile size by + * a value of 2 x gutter. This allows artifacts of rendering at tile + * edges to be ignored. Set a gutter value that is equal to half the size + * of the widest symbol that needs to be displayed. Defaults to zero. + * Non-tiled layers always have zero gutter. + * + * @type Int + */ + gutter: 0, + /** @type String */ projection: null, @@ -243,9 +276,41 @@ OpenLayers.Layer.prototype = { if (!this.isBaseLayer) { this.inRange = this.calculateInRange(); - } + } + + // deal with gutters + this.setTileSize(); }, + /** + * Set the tile size based on the map size. This also sets layer.imageSize + * and layer.imageOffset for use by Tile.Image. + * + * @param OpenLayers.Size + */ + setTileSize: function(size) { + var tileSize = (size) ? size : + ((this.tileSize) ? this.tileSize : + this.map.getTileSize()); + this.tileSize = tileSize; + if(this.gutter) { + // layers with gutters need non-null tile sizes + //if(tileSize == null) { + // OpenLayers.console.error("Error in layer.setMap() for " + + // this.name + ": layers with gutters " + + // "need non-null tile sizes"); + //} + this.imageOffset = new OpenLayers.Pixel(-this.gutter, -this.gutter); + this.imageSize = new OpenLayers.Size(tileSize.w + (2 * this.gutter), + tileSize.h + (2 * this.gutter)); + } else { + // layers without gutters may have null tile size - as long + // as they don't rely on Tile.Image + this.imageSize = tileSize; + this.imageOffset = new OpenLayers.Pixel(0, 0); + } + }, + /** * @returns Whether or not the layer should be displayed (if in range) * @type Boolean @@ -559,6 +624,23 @@ OpenLayers.Layer.prototype = { return px; }, + /** + * Adjusts the extent of a bounds in map units by the layer's gutter + * in pixels. + * + * @param {OpenLayers.Bounds} bounds + * @type OpenLayers.Bounds + * @return A bounds adjusted in height and width by the gutter + */ + adjustBoundsByGutter: function(bounds) { + var mapGutter = this.gutter * this.map.getResolution(); + bounds = new OpenLayers.Bounds(bounds.left - mapGutter, + bounds.bottom - mapGutter, + bounds.right + mapGutter, + bounds.top + mapGutter); + return bounds; + }, + /** * Sets the opacity for the entire layer (all images) * @param {Float} opacity @@ -566,7 +648,7 @@ OpenLayers.Layer.prototype = { setOpacity: function(opacity) { this.opacity = opacity; for(var i=0; i