From 63ad916ca7879930f3e4836b55f672352c68d943 Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Fri, 11 Oct 2013 17:21:10 -0600 Subject: [PATCH] Function for creating tile grids from extents --- src/ol/tilegrid/tilegrid.js | 62 +++++++++++++++++++------- test/spec/ol/tilegrid/tilegrid.test.js | 60 +++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 15 deletions(-) diff --git a/src/ol/tilegrid/tilegrid.js b/src/ol/tilegrid/tilegrid.js index 8996b786d2..eca53f7626 100644 --- a/src/ol/tilegrid/tilegrid.js +++ b/src/ol/tilegrid/tilegrid.js @@ -8,6 +8,7 @@ goog.require('ol.TileCoord'); goog.require('ol.TileRange'); goog.require('ol.array'); goog.require('ol.extent'); +goog.require('ol.extent.Corner'); goog.require('ol.proj.METERS_PER_UNIT'); goog.require('ol.proj.Projection'); goog.require('ol.proj.Units'); @@ -404,31 +405,62 @@ ol.tilegrid.getForProjection = function(projection) { /** - * @param {ol.proj.Projection} projection Projection. - * @param {number=} opt_maxZoom Maximum zoom level. - * @param {number=} opt_tileSize Tile size. + * @param {ol.Extent} extent Extent. + * @param {number=} opt_maxZoom Maximum zoom level (default is + * ol.DEFAULT_MAX_ZOOM). + * @param {number=} opt_tileSize Tile size (default uses ol.DEFAULT_TILE_SIZE). + * @param {ol.extent.Corner=} opt_corner Extent corner (default is + * ol.extent.Corner.BOTTOM_LEFT). * @return {ol.tilegrid.TileGrid} TileGrid instance. */ -ol.tilegrid.createForProjection = - function(projection, opt_maxZoom, opt_tileSize) { - var projectionExtent = projection.getExtent(); - var size = goog.isNull(projectionExtent) ? - 360 * ol.proj.METERS_PER_UNIT[ol.proj.Units.DEGREES] / - projection.getMetersPerUnit() : - Math.max(projectionExtent[2] - projectionExtent[0], - projectionExtent[3] - projectionExtent[1]); +ol.tilegrid.createForExtent = + function(extent, opt_maxZoom, opt_tileSize, opt_corner) { var maxZoom = goog.isDef(opt_maxZoom) ? opt_maxZoom : ol.DEFAULT_MAX_ZOOM; - var tileSize = goog.isDef(opt_tileSize) ? opt_tileSize : ol.DEFAULT_TILE_SIZE; + + var tileSize = goog.isDef(opt_tileSize) ? + opt_tileSize : ol.DEFAULT_TILE_SIZE; + + var corner = goog.isDef(opt_corner) ? + opt_corner : ol.extent.Corner.BOTTOM_LEFT; + + var extentHeight = ol.extent.getHeight(extent); + var extentWidth = ol.extent.getWidth(extent); + + var maxResolution = Math.max( + extentWidth / tileSize, extentHeight / tileSize); + var resolutions = new Array(maxZoom + 1); - var maxResolution = size / tileSize; + for (var z = 0, zz = resolutions.length; z < zz; ++z) { resolutions[z] = maxResolution / Math.pow(2, z); } + return new ol.tilegrid.TileGrid({ - origin: goog.isNull(projectionExtent) ? [0, 0] : - ol.extent.getBottomLeft(projectionExtent), + origin: ol.extent.getCorner(extent, corner), resolutions: resolutions, tileSize: tileSize }); }; + + +/** + * @param {ol.proj.Projection} projection Projection. + * @param {number=} opt_maxZoom Maximum zoom level (default is + * ol.DEFAULT_MAX_ZOOM). + * @param {number=} opt_tileSize Tile size (default uses ol.DEFAULT_TILE_SIZE). + * @param {ol.extent.Corner=} opt_corner Extent corner (default is + * ol.extent.Corner.BOTTOM_LEFT). + * @return {ol.tilegrid.TileGrid} TileGrid instance. + */ +ol.tilegrid.createForProjection = + function(projection, opt_maxZoom, opt_tileSize, opt_corner) { + var extent = projection.getExtent(); + if (goog.isNull(extent)) { + var half = 180 * ol.proj.METERS_PER_UNIT[ol.proj.Units.DEGREES] / + projection.getMetersPerUnit(); + extent = ol.extent.createOrUpdate(-half, -half, half, half); + } + return ol.tilegrid.createForExtent( + extent, opt_maxZoom, opt_tileSize, opt_corner); +}; diff --git a/test/spec/ol/tilegrid/tilegrid.test.js b/test/spec/ol/tilegrid/tilegrid.test.js index 08e1063a4b..747b695364 100644 --- a/test/spec/ol/tilegrid/tilegrid.test.js +++ b/test/spec/ol/tilegrid/tilegrid.test.js @@ -161,6 +161,18 @@ describe('ol.tilegrid.TileGrid', function() { }); }); + describe('createForExtent', function() { + it('allows creation of tile grid from extent', function() { + var extent = ol.extent.createOrUpdate(-100, -100, 100, 100); + var grid = ol.tilegrid.createForExtent(extent); + expect(grid).to.be.a(ol.tilegrid.TileGrid); + + var resolutions = grid.getResolutions(); + expect(resolutions.length).to.be(ol.DEFAULT_MAX_ZOOM + 1); + expect(grid.getOrigin()).to.eql([-100, -100]); + }); + }); + describe('createForProjection', function() { it('allows easier creation of a tile grid', function() { @@ -200,6 +212,50 @@ describe('ol.tilegrid.TileGrid', function() { ol.DEFAULT_TILE_SIZE / Math.pow(2, 5)); }); + it('assumes origin is bottom-left', function() { + var projection = ol.proj.get('EPSG:3857'); + var grid = ol.tilegrid.createForProjection(projection); + var origin = grid.getOrigin(); + var half = ol.proj.EPSG3857.HALF_SIZE; + expect(origin).to.eql([-half, -half]); + }); + + it('accepts bottom-left as corner', function() { + var projection = ol.proj.get('EPSG:3857'); + var grid = ol.tilegrid.createForProjection( + projection, undefined, undefined, ol.extent.Corner.BOTTOM_LEFT); + var origin = grid.getOrigin(); + var half = ol.proj.EPSG3857.HALF_SIZE; + expect(origin).to.eql([-half, -half]); + }); + + it('accepts bottom-right as corner', function() { + var projection = ol.proj.get('EPSG:3857'); + var grid = ol.tilegrid.createForProjection( + projection, undefined, undefined, ol.extent.Corner.BOTTOM_RIGHT); + var origin = grid.getOrigin(); + var half = ol.proj.EPSG3857.HALF_SIZE; + expect(origin).to.eql([half, -half]); + }); + + it('accepts top-left as corner', function() { + var projection = ol.proj.get('EPSG:3857'); + var grid = ol.tilegrid.createForProjection( + projection, undefined, undefined, ol.extent.Corner.TOP_LEFT); + var origin = grid.getOrigin(); + var half = ol.proj.EPSG3857.HALF_SIZE; + expect(origin).to.eql([-half, half]); + }); + + it('accepts top-right as corner', function() { + var projection = ol.proj.get('EPSG:3857'); + var grid = ol.tilegrid.createForProjection( + projection, undefined, undefined, ol.extent.Corner.TOP_RIGHT); + var origin = grid.getOrigin(); + var half = ol.proj.EPSG3857.HALF_SIZE; + expect(origin).to.eql([half, half]); + }); + }); describe('getForProjection', function() { @@ -643,8 +699,12 @@ describe('ol.tilegrid.TileGrid', function() { }); goog.require('ol.Coordinate'); +goog.require('ol.extent'); +goog.require('ol.extent.Corner'); goog.require('ol.proj'); goog.require('ol.proj.METERS_PER_UNIT'); +goog.require('ol.proj'); +goog.require('ol.proj.EPSG3857'); goog.require('ol.proj.Projection'); goog.require('ol.proj.Units'); goog.require('ol.tilegrid.TileGrid');