From d4f011d00cb9256b2b37eee44b34978cf6ea353b Mon Sep 17 00:00:00 2001 From: ahocevar Date: Wed, 10 Oct 2012 12:22:57 +0200 Subject: [PATCH 1/9] Absolute calculation of tile bounds This avoids cumulated tile bounds errors for layer types that do not use a tile row/column index in requests (e.g. WMS). --- lib/OpenLayers/Layer/Grid.js | 14 ++++++++++---- tests/Layer/WMS.html | 12 ++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/lib/OpenLayers/Layer/Grid.js b/lib/OpenLayers/Layer/Grid.js index fcb2b42e64..bc1d36cb0e 100644 --- a/lib/OpenLayers/Layer/Grid.js +++ b/lib/OpenLayers/Layer/Grid.js @@ -867,7 +867,8 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { * * Returns: * {Object} containing properties tilelon, tilelat, tileoffsetlat, - * tileoffsetlat, tileoffsetx, tileoffsety + * tileoffsetlat, tileoffsetx, tileoffsety and optional startrow, startcol + * for grid layouts where absolute tile bounds calculation is possible. */ calculateGridLayout: function(bounds, origin, resolution) { var tilelon = resolution * this.tileSize.w; @@ -894,7 +895,8 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { return { tilelon: tilelon, tilelat: tilelat, tileoffsetlon: tileoffsetlon, tileoffsetlat: tileoffsetlat, - tileoffsetx: tileoffsetx, tileoffsety: tileoffsety + tileoffsetx: tileoffsetx, tileoffsety: tileoffsety, + startcol: tilecol, startrow: tilerow }; }, @@ -1012,12 +1014,16 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { Math.pow(tileCenter.lat - center.lat, 2) }); - tileoffsetlon += tilelon; + tileoffsetlon = 'startcol' in tileLayout ? + origin.lon + (tileLayout.startcol + colidx) * tilelon : + tileoffsetlon + tilelon; tileoffsetx += Math.round(tileSize.w); } while ((tileoffsetlon <= bounds.right + tilelon * this.buffer) || colidx < minCols); - tileoffsetlat -= tilelat; + tileoffsetlat = 'startrow' in tileLayout ? + origin.lat + (tileLayout.startrow - rowidx) * tilelat : + tileoffsetlat - tilelat; tileoffsety += Math.round(tileSize.h); } while((tileoffsetlat >= bounds.bottom - tilelat * this.buffer) || rowidx < minRows); diff --git a/tests/Layer/WMS.html b/tests/Layer/WMS.html index 0e9fb9a8fc..fc292b809e 100644 --- a/tests/Layer/WMS.html +++ b/tests/Layer/WMS.html @@ -533,6 +533,18 @@ map.destroy(); } + + function test_tileBounds(t) { + t.plan(1); + var map = new OpenLayers.Map("map", {projection: "EPSG:3857"}); + var layer = new OpenLayers.Layer.WMS("wms", "../../img/blank.gif"); + map.addLayer(layer); + map.setCenter([0, 0], 1); + map.pan(2, -100); + map.zoomIn(); + t.eq(layer.grid[1][0].bounds, new OpenLayers.Bounds(-10018754.17, 0, 0, 10018754.17), "no floating point errors"); + map.destroy(); + } From c5bb52d93f9f4fe7221962ae994653c31da392cd Mon Sep 17 00:00:00 2001 From: ahocevar Date: Thu, 11 Oct 2012 21:22:52 +0200 Subject: [PATCH 2/9] No deltas for tile bounds/position calculation Now we also do not use deltas for shiftRow and shiftColumn. Some refactoring was done so we do not need different calculateGridLayout methods for layers with top-left and bottom-left tile origin. TODO: With this commit, ArcGisCache and KaMap layers are broken. --- lib/OpenLayers/Layer/Grid.js | 172 ++++++++++++++++--------------- lib/OpenLayers/Layer/KaMap.js | 3 +- lib/OpenLayers/Layer/MapGuide.js | 36 ------- lib/OpenLayers/Layer/Zoomify.js | 36 ------- tests/Layer/WMS.html | 16 ++- 5 files changed, 104 insertions(+), 159 deletions(-) diff --git a/lib/OpenLayers/Layer/Grid.js b/lib/OpenLayers/Layer/Grid.js index bc1d36cb0e..e0502fabb9 100644 --- a/lib/OpenLayers/Layer/Grid.js +++ b/lib/OpenLayers/Layer/Grid.js @@ -270,6 +270,14 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { * tile that could not be loaded. */ + /** + * Property: gridLayout + * {Object} containing properties tilelon, tilelat, tileoffsetlat, + * tileoffsetlat, tileoffsetx, tileoffsety and optional startrow, startcol + * for grid layouts where absolute tile bounds calculation is possible. + */ + gridLayout: null, + /** * Constructor: OpenLayers.Layer.Grid * Create a new grid layer @@ -363,6 +371,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { } this.grid = []; this.gridResolution = null; + this.gridLayout = null; } }, @@ -866,9 +875,8 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { * resolution - {Number} * * Returns: - * {Object} containing properties tilelon, tilelat, tileoffsetlat, - * tileoffsetlat, tileoffsetx, tileoffsety and optional startrow, startcol - * for grid layouts where absolute tile bounds calculation is possible. + * {Object} Object containing properties tilelon, tilelat, tileoffsetx, + * tileoffsety, startcol, startrow */ calculateGridLayout: function(bounds, origin, resolution) { var tilelon = resolution * this.tileSize.w; @@ -884,17 +892,16 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { var tilecol = Math.floor(offsetlon/tilelon) - this.buffer; var tilecolremain = offsetlon/tilelon - tilecol; var tileoffsetx = -tilecolremain * tileSize.w; - var tileoffsetlon = origin.lon + tilecol * tilelon; - var offsetlat = bounds.top - (origin.lat + tilelat); - var tilerow = Math.ceil(offsetlat/tilelat) + this.buffer; + var rowSign = this.tileOriginCorner.substr(0, 1) === "t" ? 1 : -1; + + var offsetlat = rowSign * (origin.lat - bounds.top + tilelat); + var tilerow = Math[~rowSign ? 'floor' : 'ceil'](offsetlat/tilelat) - this.buffer * rowSign; var tilerowremain = tilerow - offsetlat/tilelat; - var tileoffsety = -tilerowremain * tileSize.h; - var tileoffsetlat = origin.lat + tilerow * tilelat; + var tileoffsety = rowSign * tilerowremain * tileSize.h; return { tilelon: tilelon, tilelat: tilelat, - tileoffsetlon: tileoffsetlon, tileoffsetlat: tileoffsetlat, tileoffsetx: tileoffsetx, tileoffsety: tileoffsety, startcol: tilecol, startrow: tilerow }; @@ -927,6 +934,30 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { return origin; }, + /** + * Method: getTileBoundsForGridIndex + * + * Parameters: + * row - {Number} The row of the grid + * col - {Number} The column of the grid + * + * Returns: + * {} The bounds for the tile at (row, col) + */ + getTileBoundsForGridIndex: function(row, col) { + var origin = this.getTileOrigin(); + var tileLayout = this.gridLayout; + var tilelon = tileLayout.tilelon; + var tilelat = tileLayout.tilelat; + var rowSign = this.tileOriginCorner.substr(0, 1) === "t" ? 1 : -1; + var minX = origin.lon + (tileLayout.startcol + col) * tilelon; + var minY = origin.lat - (tileLayout.startrow + row * rowSign) * tilelat * rowSign; + return new OpenLayers.Bounds( + minX, minY, + minX + tilelon, minY + tilelat + ); + }, + /** * Method: initGriddedTiles * @@ -956,50 +987,34 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { 2 * this.buffer + 1; var tileLayout = this.calculateGridLayout(bounds, origin, serverResolution); - var tileoffsetx = Math.round(tileLayout.tileoffsetx); // heaven help us - var tileoffsety = Math.round(tileLayout.tileoffsety); + this.gridLayout = tileLayout; - var tileoffsetlon = tileLayout.tileoffsetlon; - var tileoffsetlat = tileLayout.tileoffsetlat; + var startX = Math.round(tileLayout.tileoffsetx); // heaven help us + var startY = Math.round(tileLayout.tileoffsety); var tilelon = tileLayout.tilelon; var tilelat = tileLayout.tilelat; - - var startX = tileoffsetx; - var startLon = tileoffsetlon; - - var rowidx = 0; var layerContainerDivLeft = this.map.layerContainerOriginPx.x; var layerContainerDivTop = this.map.layerContainerOriginPx.y; var tileData = [], center = this.map.getCenter(); + + var rowidx = 0; do { - var row = this.grid[rowidx++]; + var row = this.grid[rowidx]; if (!row) { row = []; this.grid.push(row); } - - tileoffsetlon = startLon; - tileoffsetx = startX; + var colidx = 0; - do { - var tileBounds = - new OpenLayers.Bounds(tileoffsetlon, - tileoffsetlat, - tileoffsetlon + tilelon, - tileoffsetlat + tilelat); - - var x = tileoffsetx; - x -= layerContainerDivLeft; - - var y = tileoffsety; - y -= layerContainerDivTop; - + var tileBounds = this.getTileBoundsForGridIndex(rowidx, colidx); + var x = startX + colidx * tileSize.w - layerContainerDivLeft; + var y = startY + rowidx * tileSize.h - layerContainerDivTop; var px = new OpenLayers.Pixel(x, y); - var tile = row[colidx++]; + var tile = row[colidx]; if (!tile) { tile = this.addTile(tileBounds, px); this.addTileMonitoringHooks(tile); @@ -1014,18 +1029,12 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { Math.pow(tileCenter.lat - center.lat, 2) }); - tileoffsetlon = 'startcol' in tileLayout ? - origin.lon + (tileLayout.startcol + colidx) * tilelon : - tileoffsetlon + tilelon; - tileoffsetx += Math.round(tileSize.w); - } while ((tileoffsetlon <= bounds.right + tilelon * this.buffer) + colidx += 1; + } while ((tileBounds.right <= bounds.right + tilelon * this.buffer) || colidx < minCols); - tileoffsetlat = 'startrow' in tileLayout ? - origin.lat + (tileLayout.startrow - rowidx) * tilelat : - tileoffsetlat - tilelat; - tileoffsety += Math.round(tileSize.h); - } while((tileoffsetlat >= bounds.bottom - tilelat * this.buffer) + rowidx += 1; + } while((tileBounds.bottom >= bounds.bottom - tilelat * this.buffer) || rowidx < minRows); //shave off exceess rows and colums @@ -1200,31 +1209,28 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { * if false, then append to end * tileSize - {Object} rendered tile size; object with w and h properties */ - shiftRow:function(prepend, tileSize) { - var modelRowIndex = (prepend) ? 0 : (this.grid.length - 1); + shiftRow: function(prepend, tileSize) { var grid = this.grid; - var modelRow = grid[modelRowIndex]; - + var rowIndex = prepend ? 0 : (grid.length - 1); var sign = prepend ? -1 : 1; - var deltaLat = this.getServerResolution() * -sign * this.tileSize.h; + var rowSign = this.tileOriginCorner.substr(0, 1) === "t" ? 1 : -1; + var tileLayout = this.gridLayout; + tileLayout.startrow += sign * rowSign; - var row = (prepend) ? grid.pop() : grid.shift(); + var bounds = this.getTileBoundsForGridIndex(rowIndex, 0); + var position = this.map.getViewPortPxFromLonLat( + new OpenLayers.LonLat(bounds.left, bounds.top) + ); + var y = Math.round(position.y - this.map.layerContainerOriginPx.y); - for (var i=0, len=modelRow.length; i} - * origin - {} - * resolution - {Number} - * - * Returns: - * {Object} Object containing properties tilelon, tilelat, tileoffsetlat, - * tileoffsetlat, tileoffsetx, tileoffsety - */ - calculateGridLayout: function(bounds, origin, resolution) { - var tilelon = resolution * this.tileSize.w; - var tilelat = resolution * this.tileSize.h; - - var offsetlon = bounds.left - origin.lon; - var tilecol = Math.floor(offsetlon/tilelon) - this.buffer; - var tilecolremain = offsetlon/tilelon - tilecol; - var tileoffsetx = -tilecolremain * this.tileSize.w; - var tileoffsetlon = origin.lon + tilecol * tilelon; - - var offsetlat = origin.lat - bounds.top + tilelat; - var tilerow = Math.floor(offsetlat/tilelat) - this.buffer; - var tilerowremain = tilerow - offsetlat/tilelat; - var tileoffsety = tilerowremain * this.tileSize.h; - var tileoffsetlat = origin.lat - tilelat*tilerow; - - return { - tilelon: tilelon, tilelat: tilelat, - tileoffsetlon: tileoffsetlon, tileoffsetlat: tileoffsetlat, - tileoffsetx: tileoffsetx, tileoffsety: tileoffsety - }; - }, - CLASS_NAME: "OpenLayers.Layer.MapGuide" }); diff --git a/lib/OpenLayers/Layer/Zoomify.js b/lib/OpenLayers/Layer/Zoomify.js index d0b482ab29..8c5a8a9e4d 100644 --- a/lib/OpenLayers/Layer/Zoomify.js +++ b/lib/OpenLayers/Layer/Zoomify.js @@ -256,41 +256,5 @@ OpenLayers.Layer.Zoomify = OpenLayers.Class(OpenLayers.Layer.Grid, { this.map.maxExtent.top); }, - /** - * Method: calculateGridLayout - * Generate parameters for the grid layout. This - * - * Parameters: - * bounds - {} - * origin - {} - * resolution - {Number} - * - * Returns: - * {Object} Object containing properties tilelon, tilelat, tileoffsetlat, - * tileoffsetlat, tileoffsetx, tileoffsety - */ - calculateGridLayout: function(bounds, origin, resolution) { - var tilelon = resolution * this.tileSize.w; - var tilelat = resolution * this.tileSize.h; - - var offsetlon = bounds.left - origin.lon; - var tilecol = Math.floor(offsetlon/tilelon) - this.buffer; - var tilecolremain = offsetlon/tilelon - tilecol; - var tileoffsetx = -tilecolremain * this.tileSize.w; - var tileoffsetlon = origin.lon + tilecol * tilelon; - - var offsetlat = origin.lat - bounds.top + tilelat; - var tilerow = Math.floor(offsetlat/tilelat) - this.buffer; - var tilerowremain = tilerow - offsetlat/tilelat; - var tileoffsety = tilerowremain * this.tileSize.h; - var tileoffsetlat = origin.lat - tilelat*tilerow; - - return { - tilelon: tilelon, tilelat: tilelat, - tileoffsetlon: tileoffsetlon, tileoffsetlat: tileoffsetlat, - tileoffsetx: tileoffsetx, tileoffsety: tileoffsety - }; - }, - CLASS_NAME: "OpenLayers.Layer.Zoomify" }); diff --git a/tests/Layer/WMS.html b/tests/Layer/WMS.html index fc292b809e..9577acea91 100644 --- a/tests/Layer/WMS.html +++ b/tests/Layer/WMS.html @@ -535,15 +535,27 @@ } function test_tileBounds(t) { - t.plan(1); + // do not defer moveGriddedTiles + var isNative = OpenLayers.Animation.isNative; + OpenLayers.Animation.isNative = true; + t.plan(2); + var map = new OpenLayers.Map("map", {projection: "EPSG:3857"}); var layer = new OpenLayers.Layer.WMS("wms", "../../img/blank.gif"); map.addLayer(layer); map.setCenter([0, 0], 1); map.pan(2, -100); map.zoomIn(); - t.eq(layer.grid[1][0].bounds, new OpenLayers.Bounds(-10018754.17, 0, 0, 10018754.17), "no floating point errors"); + t.eq(layer.grid[1][0].bounds, new OpenLayers.Bounds(-10018754.17, 0, 0, 10018754.17), "no floating point errors after zooming"); + map.zoomTo(14); + var bounds = layer.grid[0][0].bounds.clone(); + map.pan(260, 520); + map.pan(-260, -520); + t.eq(layer.grid[0][0].bounds, bounds, "no floating point errors after dragging back and forth"); + console.log(bounds.toString()) + map.destroy(); + OpenLayers.Animation.isNative = isNative; } From e7292ecbe2ecee5f5254bec7655da4fc52575ae1 Mon Sep 17 00:00:00 2001 From: ahocevar Date: Thu, 11 Oct 2012 22:26:59 +0200 Subject: [PATCH 3/9] Fixing ArcGISCache layer This is done by caching the tileOrigin at grid creation time. --- lib/OpenLayers/Layer/ArcGISCache.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/OpenLayers/Layer/ArcGISCache.js b/lib/OpenLayers/Layer/ArcGISCache.js index 27173392c4..e52ea645e6 100644 --- a/lib/OpenLayers/Layer/ArcGISCache.js +++ b/lib/OpenLayers/Layer/ArcGISCache.js @@ -358,6 +358,17 @@ OpenLayers.Layer.ArcGISCache = OpenLayers.Class(OpenLayers.Layer.XYZ, { return OpenLayers.Layer.XYZ.prototype.clone.apply(this, [obj]); }, + /** + * Method: initGriddedTiles + * + * Parameters: + * bounds - {} + */ + initGriddedTiles: function(bounds) { + delete this._tileOrigin; + OpenLayers.Layer.XYZ.prototype.initGriddedTiles.apply(this, arguments); + }, + /** * Method: getMaxExtent * Get this layer's maximum extent. @@ -379,8 +390,11 @@ OpenLayers.Layer.ArcGISCache = OpenLayers.Class(OpenLayers.Layer.XYZ, { * {} The tile origin. */ getTileOrigin: function() { - var extent = this.getMaxExtent(); - return new OpenLayers.LonLat(extent.left, extent.bottom); + if (!this._tileOrigin) { + var extent = this.getMaxExtent(); + this._tileOrigin = new OpenLayers.LonLat(extent.left, extent.bottom); + } + return this._tileOrigin; }, /** From 7df5e3ca8ebb46b52ff6477260cf6d2c7f9ead31 Mon Sep 17 00:00:00 2001 From: ahocevar Date: Thu, 11 Oct 2012 23:54:04 +0200 Subject: [PATCH 4/9] Fixing KaMap layer This also fixes an issue that has gone unnoticed for a while: the grid did not cover the bottom of the map viewport, but instead covered an invisible area above the top of the map viewport. --- lib/OpenLayers/Layer/KaMap.js | 32 ++++++++++++++++++++++++++------ tests/Layer/WrapDateLine.html | 6 +++--- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/lib/OpenLayers/Layer/KaMap.js b/lib/OpenLayers/Layer/KaMap.js index 2abd9ea65f..2a7c77322a 100644 --- a/lib/OpenLayers/Layer/KaMap.js +++ b/lib/OpenLayers/Layer/KaMap.js @@ -92,8 +92,8 @@ OpenLayers.Layer.KaMap = OpenLayers.Class(OpenLayers.Layer.Grid, { * resolution - {Number} * * Returns: - * {Object} Object containing properties tilelon, tilelat, tileoffsetlat, - * tileoffsetlat, tileoffsetx, tileoffsety + * {Object} Object containing properties tilelon, tilelat, tileoffsetx, + * tileoffsety, startcol, startrow */ calculateGridLayout: function(bounds, origin, resolution) { var tilelon = resolution*this.tileSize.w; @@ -103,22 +103,42 @@ OpenLayers.Layer.KaMap = OpenLayers.Class(OpenLayers.Layer.Grid, { var tilecol = Math.floor(offsetlon/tilelon) - this.buffer; var tilecolremain = offsetlon/tilelon - tilecol; var tileoffsetx = -tilecolremain * this.tileSize.w; - var tileoffsetlon = tilecol * tilelon; var offsetlat = bounds.top; - var tilerow = Math.ceil(offsetlat/tilelat) + this.buffer; + var tilerow = Math.floor(offsetlat/tilelat) + this.buffer; var tilerowremain = tilerow - offsetlat/tilelat; var tileoffsety = -(tilerowremain+1) * this.tileSize.h; - var tileoffsetlat = tilerow * tilelat; return { tilelon: tilelon, tilelat: tilelat, - tileoffsetlon: tileoffsetlon, tileoffsetlat: tileoffsetlat, tileoffsetx: tileoffsetx, tileoffsety: tileoffsety, startcol: tilecol, startrow: tilerow }; }, + /** + * Method: getTileBoundsForGridIndex + * + * Parameters: + * row - {Number} The row of the grid + * col - {Number} The column of the grid + * + * Returns: + * {} The bounds for the tile at (row, col) + */ + getTileBoundsForGridIndex: function(row, col) { + var origin = this.getTileOrigin(); + var tileLayout = this.gridLayout; + var tilelon = tileLayout.tilelon; + var tilelat = tileLayout.tilelat; + var minX = (tileLayout.startcol + col) * tilelon; + var minY = (tileLayout.startrow - row) * tilelat; + return new OpenLayers.Bounds( + minX, minY, + minX + tilelon, minY + tilelat + ); + }, + /** * APIMethod: clone * diff --git a/tests/Layer/WrapDateLine.html b/tests/Layer/WrapDateLine.html index 700abf3f34..6b84362d59 100644 --- a/tests/Layer/WrapDateLine.html +++ b/tests/Layer/WrapDateLine.html @@ -154,9 +154,9 @@ var m = new OpenLayers.Map('map', {adjustZoom: function(z) {return z;}}); m.addLayer(layer); m.zoomToMaxExtent(); - t.eq(layer.grid[5][7].url, "http://www.openlayers.org/world/index.php?g=satellite&map=world&i=jpeg&t=0&l=-256&s=221471921.25", "grid[5][7] kamap is okay"); - t.eq(layer.grid[5][6].url, "http://www.openlayers.org/world/index.php?g=satellite&map=world&i=jpeg&t=0&l=0&s=221471921.25", "grid[5][6] kamap is okay"); - t.eq(layer.grid[5][5].url, "http://www.openlayers.org/world/index.php?g=satellite&map=world&i=jpeg&t=0&l=-256&s=221471921.25", "grid[5][5] is okay"); + t.eq(layer.grid[4][7].url, "http://www.openlayers.org/world/index.php?g=satellite&map=world&i=jpeg&t=0&l=-256&s=221471921.25", "grid[5][7] kamap is okay"); + t.eq(layer.grid[4][6].url, "http://www.openlayers.org/world/index.php?g=satellite&map=world&i=jpeg&t=0&l=0&s=221471921.25", "grid[5][6] kamap is okay"); + t.eq(layer.grid[4][5].url, "http://www.openlayers.org/world/index.php?g=satellite&map=world&i=jpeg&t=0&l=-256&s=221471921.25", "grid[5][5] is okay"); t.ok(layer.grid[7][6].url == null, "no latitudinal wrapping - tile not loaded if outside maxExtent"); m.destroy(); } From f78d127b1c43398401af082d90d188545f350436 Mon Sep 17 00:00:00 2001 From: ahocevar Date: Thu, 11 Oct 2012 23:59:17 +0200 Subject: [PATCH 5/9] Removing console.log line --- tests/Layer/WMS.html | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Layer/WMS.html b/tests/Layer/WMS.html index 9577acea91..7f9f020676 100644 --- a/tests/Layer/WMS.html +++ b/tests/Layer/WMS.html @@ -552,7 +552,6 @@ map.pan(260, 520); map.pan(-260, -520); t.eq(layer.grid[0][0].bounds, bounds, "no floating point errors after dragging back and forth"); - console.log(bounds.toString()) map.destroy(); OpenLayers.Animation.isNative = isNative; From 66455600c7e5a45dd5bf7dfd8266c33603d5c253 Mon Sep 17 00:00:00 2001 From: ahocevar Date: Fri, 12 Oct 2012 03:10:42 +0200 Subject: [PATCH 6/9] Better precision for right and top corners --- lib/OpenLayers/Layer/Grid.js | 10 ++++++---- tests/Layer/WMS.html | 5 +++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/OpenLayers/Layer/Grid.js b/lib/OpenLayers/Layer/Grid.js index e0502fabb9..637c6c163e 100644 --- a/lib/OpenLayers/Layer/Grid.js +++ b/lib/OpenLayers/Layer/Grid.js @@ -949,12 +949,14 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { var tileLayout = this.gridLayout; var tilelon = tileLayout.tilelon; var tilelat = tileLayout.tilelat; + var startcol = tileLayout.startcol; + var startrow = tileLayout.startrow; var rowSign = this.tileOriginCorner.substr(0, 1) === "t" ? 1 : -1; - var minX = origin.lon + (tileLayout.startcol + col) * tilelon; - var minY = origin.lat - (tileLayout.startrow + row * rowSign) * tilelat * rowSign; return new OpenLayers.Bounds( - minX, minY, - minX + tilelon, minY + tilelat + origin.lon + (startcol + col) * tilelon, + origin.lat - (startrow + row * rowSign) * tilelat * rowSign, + origin.lon + (startcol + col + 1) * tilelon, + origin.lat - (startrow + (row - 1) * rowSign) * tilelat * rowSign ); }, diff --git a/tests/Layer/WMS.html b/tests/Layer/WMS.html index 7f9f020676..cdc00705a3 100644 --- a/tests/Layer/WMS.html +++ b/tests/Layer/WMS.html @@ -538,7 +538,7 @@ // do not defer moveGriddedTiles var isNative = OpenLayers.Animation.isNative; OpenLayers.Animation.isNative = true; - t.plan(2); + t.plan(3); var map = new OpenLayers.Map("map", {projection: "EPSG:3857"}); var layer = new OpenLayers.Layer.WMS("wms", "../../img/blank.gif"); @@ -547,11 +547,12 @@ map.pan(2, -100); map.zoomIn(); t.eq(layer.grid[1][0].bounds, new OpenLayers.Bounds(-10018754.17, 0, 0, 10018754.17), "no floating point errors after zooming"); - map.zoomTo(14); + map.setCenter([0, 0], 14); var bounds = layer.grid[0][0].bounds.clone(); map.pan(260, 520); map.pan(-260, -520); t.eq(layer.grid[0][0].bounds, bounds, "no floating point errors after dragging back and forth"); + t.eq(bounds.right, 0, "0 is 0, and not some super small number"); map.destroy(); OpenLayers.Animation.isNative = isNative; From ff4a1b2468edb3184b1f03ea4e9fbd2f3b2107b3 Mon Sep 17 00:00:00 2001 From: ahocevar Date: Fri, 12 Oct 2012 03:23:56 +0200 Subject: [PATCH 7/9] Optimizing positions for rendering Calculating pixel positions from origin and grid index causes alignment issues in the grid. By going back to incremental positioning, we get a result without blank spaces between tiles again. --- lib/OpenLayers/Layer/Grid.js | 54 ++++++++++++----------------------- lib/OpenLayers/Layer/KaMap.js | 9 ++---- lib/OpenLayers/Tile/Image.js | 4 +-- 3 files changed, 22 insertions(+), 45 deletions(-) diff --git a/lib/OpenLayers/Layer/Grid.js b/lib/OpenLayers/Layer/Grid.js index 637c6c163e..db5e288ec7 100644 --- a/lib/OpenLayers/Layer/Grid.js +++ b/lib/OpenLayers/Layer/Grid.js @@ -875,34 +875,23 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { * resolution - {Number} * * Returns: - * {Object} Object containing properties tilelon, tilelat, tileoffsetx, - * tileoffsety, startcol, startrow + * {Object} Object containing properties tilelon, tilelat, startcol, + * startrow */ calculateGridLayout: function(bounds, origin, resolution) { var tilelon = resolution * this.tileSize.w; var tilelat = resolution * this.tileSize.h; - var ratio = resolution / this.map.getResolution(), - tileSize = { - w: Math.round(this.tileSize.w * ratio), - h: Math.round(this.tileSize.h * ratio) - }; - var offsetlon = bounds.left - origin.lon; var tilecol = Math.floor(offsetlon/tilelon) - this.buffer; - var tilecolremain = offsetlon/tilelon - tilecol; - var tileoffsetx = -tilecolremain * tileSize.w; var rowSign = this.tileOriginCorner.substr(0, 1) === "t" ? 1 : -1; var offsetlat = rowSign * (origin.lat - bounds.top + tilelat); var tilerow = Math[~rowSign ? 'floor' : 'ceil'](offsetlat/tilelat) - this.buffer * rowSign; - var tilerowremain = tilerow - offsetlat/tilelat; - var tileoffsety = rowSign * tilerowremain * tileSize.h; return { tilelon: tilelon, tilelat: tilelat, - tileoffsetx: tileoffsetx, tileoffsety: tileoffsety, startcol: tilecol, startrow: tilerow }; @@ -991,15 +980,19 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { var tileLayout = this.calculateGridLayout(bounds, origin, serverResolution); this.gridLayout = tileLayout; - var startX = Math.round(tileLayout.tileoffsetx); // heaven help us - var startY = Math.round(tileLayout.tileoffsety); - var tilelon = tileLayout.tilelon; var tilelat = tileLayout.tilelat; var layerContainerDivLeft = this.map.layerContainerOriginPx.x; var layerContainerDivTop = this.map.layerContainerOriginPx.y; + var tileBounds = this.getTileBoundsForGridIndex(0, 0); + var startPx = this.map.getViewPortPxFromLonLat( + new OpenLayers.LonLat(tileBounds.left, tileBounds.top) + ); + startPx.x = Math.round(startPx.x) - layerContainerDivLeft; + startPx.y = Math.round(startPx.y) - layerContainerDivTop; + var tileData = [], center = this.map.getCenter(); var rowidx = 0; @@ -1012,10 +1005,10 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { var colidx = 0; do { - var tileBounds = this.getTileBoundsForGridIndex(rowidx, colidx); - var x = startX + colidx * tileSize.w - layerContainerDivLeft; - var y = startY + rowidx * tileSize.h - layerContainerDivTop; - var px = new OpenLayers.Pixel(x, y); + tileBounds = this.getTileBoundsForGridIndex(rowidx, colidx); + var px = startPx.clone(); + px.x = px.x + colidx * Math.round(tileSize.w); + px.y = px.y + rowidx * Math.round(tileSize.h); var tile = row[colidx]; if (!tile) { tile = this.addTile(tileBounds, px); @@ -1219,17 +1212,12 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { var tileLayout = this.gridLayout; tileLayout.startrow += sign * rowSign; - var bounds = this.getTileBoundsForGridIndex(rowIndex, 0); - var position = this.map.getViewPortPxFromLonLat( - new OpenLayers.LonLat(bounds.left, bounds.top) - ); - var y = Math.round(position.y - this.map.layerContainerOriginPx.y); - + var modelRow = grid[rowIndex]; var row = grid[prepend ? 'pop' : 'shift'](); for (var i=0, len=row.length; i Date: Fri, 12 Oct 2012 16:11:10 +0200 Subject: [PATCH 8/9] Updating and fixing API docs --- lib/OpenLayers/Layer/Grid.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/OpenLayers/Layer/Grid.js b/lib/OpenLayers/Layer/Grid.js index db5e288ec7..d77aaa643f 100644 --- a/lib/OpenLayers/Layer/Grid.js +++ b/lib/OpenLayers/Layer/Grid.js @@ -272,9 +272,8 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { /** * Property: gridLayout - * {Object} containing properties tilelon, tilelat, tileoffsetlat, - * tileoffsetlat, tileoffsetx, tileoffsety and optional startrow, startcol - * for grid layouts where absolute tile bounds calculation is possible. + * {Object} Object containing properties tilelon, tilelat, startcol, + * startrow */ gridLayout: null, From a0acf1e550287974a81e626af4cac575950eda94 Mon Sep 17 00:00:00 2001 From: ahocevar Date: Fri, 12 Oct 2012 16:16:44 +0200 Subject: [PATCH 9/9] Calculating rowSign only once --- lib/OpenLayers/Layer/Grid.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/OpenLayers/Layer/Grid.js b/lib/OpenLayers/Layer/Grid.js index d77aaa643f..ba6af27c49 100644 --- a/lib/OpenLayers/Layer/Grid.js +++ b/lib/OpenLayers/Layer/Grid.js @@ -276,6 +276,13 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { * startrow */ gridLayout: null, + + /** + * Property: rowSign + * {Number} 1 for grids starting at the top, -1 for grids starting at the + * bottom. This is used for several grid index and offset calculations. + */ + rowSign: null, /** * Constructor: OpenLayers.Layer.Grid @@ -308,6 +315,8 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { this.moveTimerId = null; }, this); } + + this.rowSign = this.tileOriginCorner.substr(0, 1) === "t" ? 1 : -1; }, /** @@ -884,7 +893,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { var offsetlon = bounds.left - origin.lon; var tilecol = Math.floor(offsetlon/tilelon) - this.buffer; - var rowSign = this.tileOriginCorner.substr(0, 1) === "t" ? 1 : -1; + var rowSign = this.rowSign; var offsetlat = rowSign * (origin.lat - bounds.top + tilelat); var tilerow = Math[~rowSign ? 'floor' : 'ceil'](offsetlat/tilelat) - this.buffer * rowSign; @@ -939,7 +948,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { var tilelat = tileLayout.tilelat; var startcol = tileLayout.startcol; var startrow = tileLayout.startrow; - var rowSign = this.tileOriginCorner.substr(0, 1) === "t" ? 1 : -1; + var rowSign = this.rowSign; return new OpenLayers.Bounds( origin.lon + (startcol + col) * tilelon, origin.lat - (startrow + row * rowSign) * tilelat * rowSign, @@ -1207,7 +1216,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { var grid = this.grid; var rowIndex = prepend ? 0 : (grid.length - 1); var sign = prepend ? -1 : 1; - var rowSign = this.tileOriginCorner.substr(0, 1) === "t" ? 1 : -1; + var rowSign = this.rowSign; var tileLayout = this.gridLayout; tileLayout.startrow += sign * rowSign;