/* Copyright (c) 2006 MetaCarta, Inc., published under the BSD license. * See http://svn.openlayers.org/trunk/openlayers/license.txt for the full * text of the license. */ // @require: OpenLayers/Layer.js // @require: OpenLayers/Util.js OpenLayers.Layer.Grid = Class.create(); OpenLayers.Layer.Grid.TILE_WIDTH = 256; OpenLayers.Layer.Grid.TILE_HEIGHT = 256; OpenLayers.Layer.Grid.prototype = Object.extend( new OpenLayers.Layer(), { // str: url url: null, // hash: params params: null, // tileSize: OpenLayers.Size tileSize: null, // grid: Array(Array()) // this is an array of rows, each row is an array of tiles grid: null, /** * @param {str} name * @param {str} url * @param {hash} params */ initialize: function(name, url, params) { var newArguments = arguments; if (arguments.length > 0) { newArguments = [name]; } OpenLayers.Layer.prototype.initialize.apply(this, newArguments); this.url = url; this.params = params; this.tileSize = new OpenLayers.Size(OpenLayers.Layer.Grid.TILE_WIDTH, OpenLayers.Layer.Grid.TILE_HEIGHT); }, /** * */ destroy: function() { this.params = null; this.clearGrid(); this.grid = null; OpenLayers.Layer.prototype.destroy.apply(this, arguments); }, setTileSize: function (size) { this.tileSize = size.copyOf(); }, /** * moveTo * moveTo is a function called whenever the map is moved. All the moving * of actual 'tiles' is done by the map, but moveTo's role is to accept * a bounds and make sure the data that that bounds requires is pre-loaded. * @param {OpenLayers.Bounds} */ moveTo:function(bounds,zoomChanged) { if (!this.getVisibility()) { if (zoomChanged) { this.grid = null; } return; } if (!this.grid || zoomChanged) { this._initTiles(); } else { var i = 0; while (this.getGridBounds().bottom > bounds.bottom) { this.insertRow(false); } while (this.getGridBounds().left > bounds.left) { this.insertColumn(true); } while (this.getGridBounds().top < bounds.top) { this.insertRow(true); } while (this.getGridBounds().right < bounds.right) { this.insertColumn(false); } } }, getGridBounds:function() { var topLeftTile = this.grid[0][0]; var bottomRightTile = this.grid[this.grid.length-1][this.grid[0].length-1]; return new OpenLayers.Bounds(topLeftTile.bounds.left, bottomRightTile.bounds.bottom, bottomRightTile.bounds.right, topLeftTile.bounds.top); }, /** */ _initTiles:function() { //first of all, clear out the main div this.div.innerHTML = ""; //now clear out the old grid and start a new one this.clearGrid(); this.grid = new Array(); var viewSize = this.map.getSize(); var bounds = this.map.getExtent(); var extent = this.map.getFullExtent(); var resolution = this.map.getResolution(); var tilelon = resolution*this.tileSize.w; var tilelat = resolution*this.tileSize.h; var offsetlon = bounds.left - extent.left; var tilecol = Math.floor(offsetlon/tilelon); var tilecolremain = offsetlon/tilelon - tilecol; var tileoffsetx = -tilecolremain * this.tileSize.w; var tileoffsetlon = extent.left + tilecol * tilelon; var offsetlat = bounds.top - (extent.bottom + tilelat); var tilerow = Math.ceil(offsetlat/tilelat); var tilerowremain = tilerow - offsetlat/tilelat; var tileoffsety = -tilerowremain * this.tileSize.h; var tileoffsetlat = extent.bottom + tilerow * tilelat; tileoffsetx = Math.round(tileoffsetx); // heaven help us tileoffsety = Math.round(tileoffsety); this.origin = new OpenLayers.Pixel(tileoffsetx,tileoffsety); var startX = tileoffsetx; var startLon = tileoffsetlon; do { var row = new Array(); this.grid.append(row); tileoffsetlon = startLon; tileoffsetx = startX; do { var tileBounds = new OpenLayers.Bounds(tileoffsetlon, tileoffsetlat, tileoffsetlon+tilelon, tileoffsetlat+tilelat); var tile = this.addTile(tileBounds, new OpenLayers.Pixel(tileoffsetx - parseInt(this.map.layerContainerDiv.style.left), tileoffsety - parseInt(this.map.layerContainerDiv.style.top)) ); tile.draw((this.params.TRANSPARENT == 'true')); row.append(tile); tileoffsetlon += tilelon; tileoffsetx += this.tileSize.w; } while (tileoffsetlon < bounds.right) tileoffsetlat -= tilelat; tileoffsety += this.tileSize.h; } while(tileoffsetlat > bounds.bottom - tilelat) }, /** * @param {bool} prepend - if true, prepend to beginning. * if false, then append to end */ insertRow:function(prepend) { var modelRowIndex = (prepend) ? 0 : (this.grid.length - 1); var modelRow = this.grid[modelRowIndex]; var newRow = new Array(); var resolution = this.map.getResolution(); var deltaY = (prepend) ? -this.tileSize.h : this.tileSize.h; var deltaLat = resolution * -deltaY; for (var i=0; i < modelRow.length; i++) { var modelTile = modelRow[i]; var bounds = modelTile.bounds.copyOf(); var position = modelTile.position.copyOf(); bounds.bottom = bounds.bottom + deltaLat; bounds.top = bounds.top + deltaLat; position.y = position.y + deltaY; var newTile = this.addTile(bounds, position); newTile.draw((this.params.TRANSPARENT == 'true')); newRow.append(newTile); } if (newRow.length>0){ if (prepend) { this.grid.prepend(newRow); } else { this.grid.append(newRow); } } }, /** * @param {bool} prepend - if true, prepend to beginning. * if false, then append to end */ insertColumn:function(prepend) { var modelCellIndex; var deltaX = (prepend) ? -this.tileSize.w : this.tileSize.w; var resolution = this.map.getResolution(); var deltaLon = resolution * deltaX; for (var i=0; i 0) { var row = this.grid[0]; while(row.length > 0) { var tile = row[0]; tile.destroy(); row.remove(tile); } this.grid.remove(row); } } }, /** * addTile gives subclasses of Grid the opportunity to create an * OpenLayer.Tile of their choosing. The implementer should initialize * the new tile and take whatever steps necessary to display it. * * @param {OpenLayers.Bounds} bounds * * @returns The added OpenLayers.Tile * @type OpenLayers.Tile */ addTile:function(bounds,position) { // Should be implemented by subclasses }, /** @final @type String */ CLASS_NAME: "OpenLayers.Grid" });