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; }