From 404d123623ee47f5790cce0f681bdce94e255498 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Thu, 19 Jul 2012 17:48:39 +0200 Subject: [PATCH] add TileGrid getTileCoordForArbitraryResolution and getTileCoordPixelBoundsForArbitraryResolution + tests, based on @tschaub work --- src/ol/tilegrid/tilegrid.js | 69 ++++++++++++ src/ol/tilegrid/tilegrid_test.js | 176 +++++++++++++++++++++++++++++++ 2 files changed, 245 insertions(+) diff --git a/src/ol/tilegrid/tilegrid.js b/src/ol/tilegrid/tilegrid.js index 85fff11749..b48521753d 100644 --- a/src/ol/tilegrid/tilegrid.js +++ b/src/ol/tilegrid/tilegrid.js @@ -4,6 +4,7 @@ goog.require('goog.array'); goog.require('goog.asserts'); goog.require('ol.Coordinate'); goog.require('ol.Extent'); +goog.require('ol.PixelBounds'); goog.require('ol.Size'); goog.require('ol.TileBounds'); goog.require('ol.TileCoord'); @@ -156,6 +157,52 @@ ol.TileGrid.prototype.getTileCoord = function(z, coordinate) { }; +/** + * @param {number} z Z. + * @param {number} resolution Resolution. + * @param {goog.math.Coordinate} coordinate Coordinate. + * @return {ol.TileCoord} Tile coordinate. + */ +ol.TileGrid.prototype.getTileCoordForArbitraryResolution = function( + z, resolution, coordinate) { + var resolutionForZ = this.getResolution(z); + var scale = resolution / resolutionForZ; + var origin = this.getOrigin(z); + + var offsetFromOrigin = new goog.math.Coordinate( + Math.floor((coordinate.x - origin.x) / resolution), + Math.floor((coordinate.y - origin.y) / resolution)); + + var tileSize = this.getTileSize(); + tileSize = new goog.math.Size(tileSize.width / scale, + tileSize.height / scale); + + var x, y; + x = Math.floor(offsetFromOrigin.x / tileSize.width); + y = Math.floor(offsetFromOrigin.y / tileSize.height); + + var tileCoord = new ol.TileCoord(z, x, y); + var tileCoordPixelBounds = + this.getTileCoordPixelBoundsForArbitraryResolution( + tileCoord, resolution); + + // adjust x to allow for stretched tiles + if (offsetFromOrigin.x < tileCoordPixelBounds.minX) { + tileCoord.x -= 1; + } else if (offsetFromOrigin.x >= tileCoordPixelBounds.maxX) { + tileCoord.x += 1; + } + // adjust y to allow for stretched tiles + if (offsetFromOrigin.y < tileCoordPixelBounds.minY) { + tileCoord.y -= 1; + } else if (offsetFromOrigin.y >= tileCoordPixelBounds.maxY) { + tileCoord.y += 1; + } + + return tileCoord; +}; + + /** * @param {ol.TileCoord} tileCoord Tile coordinate. * @return {ol.Coordinate} Tile center. @@ -203,6 +250,28 @@ ol.TileGrid.prototype.getTileCoordExtent = function(tileCoord) { }; +/** + * @param {ol.TileCoord} tileCoord Tile coordinate. + * @param {number} resolution Resolution. + * @return {ol.PixelBounds} Pixel bounds. + */ +ol.TileGrid.prototype.getTileCoordPixelBoundsForArbitraryResolution = function( + tileCoord, resolution) { + var resolutionForZ = this.getResolution(tileCoord.z); + var scale = resolution / resolutionForZ; + var tileSize = this.getTileSize(); + tileSize = new goog.math.Size(tileSize.width / scale, + tileSize.height / scale); + var minX, maxX, minY, maxY; + minX = Math.round(tileCoord.x * tileSize.width); + maxX = Math.round((tileCoord.x + 1) * tileSize.width); + minY = Math.round(tileCoord.y * tileSize.height); + maxY = Math.round((tileCoord.y + 1) * tileSize.height); + + return new ol.PixelBounds(minX, minY, maxX, maxY); +}; + + /** * @param {ol.TileCoord} tileCoord Tile coordinate. * @return {number} Tile resolution. diff --git a/src/ol/tilegrid/tilegrid_test.js b/src/ol/tilegrid/tilegrid_test.js index 84f904a17c..84e9702eab 100644 --- a/src/ol/tilegrid/tilegrid_test.js +++ b/src/ol/tilegrid/tilegrid_test.js @@ -129,6 +129,181 @@ function testGetTileCoordYSouth() { } +function testGetTileCoordForArbitraryResolution() { + + var tileSize = new ol.Size(256, 256); + var tileGrid = new ol.TileGrid([10], extent, origin, tileSize); + + var coordinate; + var tileCoord; + + // gets the first tile at the origin + coordinate = new ol.Coordinate(0, 0); + tileCoord = tileGrid.getTileCoordForArbitraryResolution( + 0, 10, coordinate); + assertEquals(0, tileCoord.z); + assertEquals(0, tileCoord.x); + assertEquals(0, tileCoord.y); + + // gets one tile northwest of the origin + coordinate = new ol.Coordinate(-1280, 1280); + tileCoord = tileGrid.getTileCoordForArbitraryResolution( + 0, 10, coordinate); + assertEquals(0, tileCoord.z); + assertEquals(-1, tileCoord.x); + assertEquals(0, tileCoord.y); + + // gets one tile northeast of the origin + coordinate = new ol.Coordinate(1280, 1280); + tileCoord = tileGrid.getTileCoordForArbitraryResolution( + 0, 10, coordinate); + assertEquals(0, tileCoord.z); + assertEquals(0, tileCoord.x); + assertEquals(0, tileCoord.y); + + // gets one tile southeast of the origin + coordinate = new ol.Coordinate(1280, -1280); + tileCoord = tileGrid.getTileCoordForArbitraryResolution( + 0, 10, coordinate); + assertEquals(0, tileCoord.z); + assertEquals(0, tileCoord.x); + assertEquals(-1, tileCoord.y); + + // gets one tile southwest of the origin + coordinate = new ol.Coordinate(-1280, -1280); + tileCoord = tileGrid.getTileCoordForArbitraryResolution( + 0, 10, coordinate); + assertEquals(0, tileCoord.z); + assertEquals(-1, tileCoord.x); + assertEquals(-1, tileCoord.y); + + // gets the tile to the east when on the edge + coordinate = new ol.Coordinate(2560, -1280); + tileCoord = tileGrid.getTileCoordForArbitraryResolution( + 0, 10, coordinate); + assertEquals(0, tileCoord.z); + assertEquals(1, tileCoord.x); + assertEquals(-1, tileCoord.y); + + // gets the tile to the north when on the edge + coordinate = new ol.Coordinate(1280, -2560); + tileCoord = tileGrid.getTileCoordForArbitraryResolution( + 0, 10, coordinate); + assertEquals(0, tileCoord.z); + assertEquals(0, tileCoord.x); + assertEquals(-1, tileCoord.y); + + // pixels are top aligned to the origin + coordinate = new ol.Coordinate(1280, -2559.999); + tileCoord = tileGrid.getTileCoordForArbitraryResolution( + 0, 10, coordinate); + assertEquals(0, tileCoord.z); + assertEquals(0, tileCoord.x); + assertEquals(-1, tileCoord.y); + + // pixels are left aligned to the origin + coordinate = new ol.Coordinate(2559.999, -1280); + tileCoord = tileGrid.getTileCoordForArbitraryResolution( + 0, 10, coordinate); + assertEquals(0, tileCoord.z); + assertEquals(0, tileCoord.x); + assertEquals(-1, tileCoord.y); +} + +function testGetTileCoordForArbitraryResolutionFractional() { + + var tileSize = new ol.Size(256, 256); + var tileGrid = new ol.TileGrid([1 / 3], extent, origin, tileSize); + + var coordinate; + var tileCoord; + + // These tests render at a resolution of 1. Because the layer's + // closest resolution is 1/3, the images are scaled by 1/3. + // In this scenario, every third tile will be one pixel wider when + // rendered (0,0 is normal; 1,0 is wider; 0,1 is taller; etc.) + + // gets the first tile at the origin + coordinate = new ol.Coordinate(0, 0); + tileCoord = tileGrid.getTileCoordForArbitraryResolution( + 0, 1, coordinate); + assertEquals(0, tileCoord.z); + assertEquals(0, tileCoord.x); + assertEquals(0, tileCoord.y); + + // gets the 1,0 tile at 256/3,0 + coordinate = new ol.Coordinate(256 / 3, 0); + tileCoord = tileGrid.getTileCoordForArbitraryResolution( + 0, 1, coordinate); + assertEquals(0, tileCoord.z); + assertEquals(1, tileCoord.x); + assertEquals(0, tileCoord.y); + + // still gets the 1,0 tile at 512/3,0 - wider tile + coordinate = new ol.Coordinate(512 / 3, 0); + tileCoord = tileGrid.getTileCoordForArbitraryResolution( + 0, 1, coordinate); + assertEquals(0, tileCoord.z); + assertEquals(1, tileCoord.x); + assertEquals(0, tileCoord.y); + + // gets the 2,0 tile at 513/3,0 + coordinate = new ol.Coordinate(513 / 3, 0); + tileCoord = tileGrid.getTileCoordForArbitraryResolution( + 0, 1, coordinate); + assertEquals(0, tileCoord.z); + assertEquals(2, tileCoord.x); + assertEquals(0, tileCoord.y); + + // gets the 3,0 tile at 768/3,0 + coordinate = new ol.Coordinate(768 / 3, 0); + tileCoord = tileGrid.getTileCoordForArbitraryResolution( + 0, 1, coordinate); + assertEquals(0, tileCoord.z); + assertEquals(3, tileCoord.x); + assertEquals(0, tileCoord.y); + + // gets the 4,0 tile at 1024/3,0 + coordinate = new ol.Coordinate(1024 / 3, 0); + tileCoord = tileGrid.getTileCoordForArbitraryResolution( + 0, 1, coordinate); + assertEquals(0, tileCoord.z); + assertEquals(4, tileCoord.x); + assertEquals(0, tileCoord.y); + + // still gets the 4,0 tile at 1280/3,0 - wider tile + coordinate = new ol.Coordinate(1280 / 3, 0); + tileCoord = tileGrid.getTileCoordForArbitraryResolution( + 0, 1, coordinate); + assertEquals(0, tileCoord.z); + assertEquals(4, tileCoord.x); + assertEquals(0, tileCoord.y); + + // gets the 5,0 tile at 1281/3,0 + coordinate = new ol.Coordinate(1281 / 3, 0); + tileCoord = tileGrid.getTileCoordForArbitraryResolution( + 0, 1, coordinate); + assertEquals(0, tileCoord.z); + assertEquals(5, tileCoord.x); + assertEquals(0, tileCoord.y); + + // gets the 0,1 tile at 0,-256/3 + coordinate = new ol.Coordinate(0, -256 / 3); + tileCoord = tileGrid.getTileCoordForArbitraryResolution( + 0, 1, coordinate); + assertEquals(0, tileCoord.z); + assertEquals(0, tileCoord.x); + assertEquals(-2, tileCoord.y); + + // still gets the 0,1 tile at 0,-512/3 - taller tile + coordinate = new ol.Coordinate(0, -512 / 3); + tileCoord = tileGrid.getTileCoordForArbitraryResolution( + 0, 1, coordinate); + assertEquals(0, tileCoord.z); + assertEquals(0, tileCoord.x); + assertEquals(-2, tileCoord.y); +} + function testGetTileCoordCenter() { @@ -150,6 +325,7 @@ function testGetTileCoordCenter() { } + function testGetTileCoordExtent() { var tileGrid = new ol.TileGrid(resolutions, extent, origin, tileSize);