From 797dba2cdbabd8fa0a78c32a7b3bfcdbff29eea8 Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Mon, 18 Feb 2013 17:09:33 -0700 Subject: [PATCH] Correct range for extent and resolution Tile ranges are inclusive. When getting the tile range for an extent, the top-right corner of the extent should be considered with a different intersection policy than the bottom-left corner. --- src/ol/tilegrid/tilegrid.js | 46 ++++++++++----- test/spec/ol/tilegrid.test.js | 102 ++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+), 13 deletions(-) diff --git a/src/ol/tilegrid/tilegrid.js b/src/ol/tilegrid/tilegrid.js index ba9e6ff441..7786581932 100644 --- a/src/ol/tilegrid/tilegrid.js +++ b/src/ol/tilegrid/tilegrid.js @@ -183,10 +183,10 @@ ol.tilegrid.TileGrid.prototype.getTileRangeExtent = function(z, tileRange) { */ ol.tilegrid.TileGrid.prototype.getTileRangeForExtentAndResolution = function( extent, resolution) { - var min = this.getTileCoordForCoordAndResolution( + var min = this.getTileCoordForCoordAndResolution_( new ol.Coordinate(extent.minX, extent.minY), resolution); - var max = this.getTileCoordForCoordAndResolution( - new ol.Coordinate(extent.maxX, extent.maxY), resolution); + var max = this.getTileCoordForCoordAndResolution_( + new ol.Coordinate(extent.maxX, extent.maxY), resolution, true); return new ol.TileRange(min.x, min.y, max.x, max.y); }; @@ -233,26 +233,46 @@ ol.tilegrid.TileGrid.prototype.getTileCoordExtent = function(tileCoord) { /** + * Get the tile coordinate for the given map coordinate and resolution. This + * method considers that coordinates that intersect tile boundaries should be + * assigned the higher tile coordinate. + * * @param {ol.Coordinate} coordinate Coordinate. * @param {number} resolution Resolution. * @return {ol.TileCoord} Tile coordinate. */ ol.tilegrid.TileGrid.prototype.getTileCoordForCoordAndResolution = function( coordinate, resolution) { + return this.getTileCoordForCoordAndResolution_(coordinate, resolution); +}; + + +/** + * @param {ol.Coordinate} coordinate Coordinate. + * @param {number} resolution Resolution. + * @param {boolean=} opt_reverseIntersectionPolicy Instead of letting edge + * intersections go to the higher tile coordinate, let edge intersections + * go to the lower tile coordinate. + * @return {ol.TileCoord} Tile coordinate. + * @private + */ +ol.tilegrid.TileGrid.prototype.getTileCoordForCoordAndResolution_ = function( + coordinate, resolution, opt_reverseIntersectionPolicy) { var z = this.getZForResolution(resolution); var scale = resolution / this.getResolution(z); var origin = this.getOrigin(z); - - var offsetFromOrigin = new ol.Coordinate( - Math.floor((coordinate.x - origin.x) / resolution), - Math.floor((coordinate.y - origin.y) / resolution)); - var tileSize = this.getTileSize(); - tileSize = new ol.Size(tileSize.width / scale, - tileSize.height / scale); - var x = Math.floor(offsetFromOrigin.x / tileSize.width); - var y = Math.floor(offsetFromOrigin.y / tileSize.height); + var x = scale * (coordinate.x - origin.x) / (resolution * tileSize.width); + var y = scale * (coordinate.y - origin.y) / (resolution * tileSize.height); + + if (!opt_reverseIntersectionPolicy) { + x = Math.floor(x); + y = Math.floor(y); + } else { + x = Math.ceil(x) - 1; + y = Math.ceil(y) - 1; + } return new ol.TileCoord(z, x, y); }; @@ -266,7 +286,7 @@ ol.tilegrid.TileGrid.prototype.getTileCoordForCoordAndResolution = function( ol.tilegrid.TileGrid.prototype.getTileCoordForCoordAndZ = function(coordinate, z) { var resolution = this.getResolution(z); - return this.getTileCoordForCoordAndResolution(coordinate, resolution); + return this.getTileCoordForCoordAndResolution_(coordinate, resolution); }; diff --git a/test/spec/ol/tilegrid.test.js b/test/spec/ol/tilegrid.test.js index 63451a1668..abcb2c358a 100644 --- a/test/spec/ol/tilegrid.test.js +++ b/test/spec/ol/tilegrid.test.js @@ -258,6 +258,68 @@ describe('ol.tilegrid.TileGrid', function() { }); }); + + describe('getTileCoordForCoordAndResolution_', function() { + it('returns higher tile coord for intersections by default', function() { + var tileGrid = new ol.tilegrid.TileGrid({ + resolutions: resolutions, + extent: extent, + origin: origin, + tileSize: tileSize + }); + + var coordinate; + var tileCoord; + + // gets higher tile for edge intersection + coordinate = new ol.Coordinate(0, 0); + tileCoord = tileGrid.getTileCoordForCoordAndResolution_( + coordinate, 100); + expect(tileCoord.z).toEqual(3); + expect(tileCoord.x).toEqual(0); + expect(tileCoord.y).toEqual(0); + + // gets higher tile for edge intersection + coordinate = new ol.Coordinate(100000, 100000); + tileCoord = tileGrid.getTileCoordForCoordAndResolution_( + coordinate, 100); + expect(tileCoord.z).toEqual(3); + expect(tileCoord.x).toEqual(10); + expect(tileCoord.y).toEqual(10); + + }); + + it('handles alt intersection policy', function() { + var tileGrid = new ol.tilegrid.TileGrid({ + resolutions: resolutions, + extent: extent, + origin: origin, + tileSize: tileSize + }); + + var coordinate; + var tileCoord; + + // can get lower tile for edge intersection + coordinate = new ol.Coordinate(0, 0); + tileCoord = tileGrid.getTileCoordForCoordAndResolution_( + coordinate, 100, true); + expect(tileCoord.z).toEqual(3); + expect(tileCoord.x).toEqual(-1); + expect(tileCoord.y).toEqual(-1); + + // gets higher tile for edge intersection + coordinate = new ol.Coordinate(100000, 100000); + tileCoord = tileGrid.getTileCoordForCoordAndResolution_( + coordinate, 100, true); + expect(tileCoord.z).toEqual(3); + expect(tileCoord.x).toEqual(9); + expect(tileCoord.y).toEqual(9); + + }); + + }); + describe('getTileCoordCenter', function() { it('returns the expected center', function() { var tileGrid = new ol.tilegrid.TileGrid({ @@ -312,6 +374,46 @@ describe('ol.tilegrid.TileGrid', function() { }); }); + describe('getTileRangeForExtentAndResolution', function() { + it('returns the expected TileRange', function() { + var tileGrid = new ol.tilegrid.TileGrid({ + resolutions: resolutions, + extent: extent, + origin: origin, + tileSize: tileSize + }); + var tileRange; + + tileRange = tileGrid.getTileRangeForExtentAndResolution(extent, + resolutions[0]); + expect(tileRange.minY).toEqual(0); + expect(tileRange.minX).toEqual(0); + expect(tileRange.maxX).toEqual(0); + expect(tileRange.maxY).toEqual(0); + + tileRange = tileGrid.getTileRangeForExtentAndResolution(extent, + resolutions[1]); + expect(tileRange.minX).toEqual(0); + expect(tileRange.minY).toEqual(0); + expect(tileRange.maxX).toEqual(1); + expect(tileRange.maxY).toEqual(1); + + tileRange = tileGrid.getTileRangeForExtentAndResolution(extent, + resolutions[2]); + expect(tileRange.minX).toEqual(0); + expect(tileRange.minY).toEqual(0); + expect(tileRange.maxX).toEqual(3); + expect(tileRange.maxY).toEqual(3); + + tileRange = tileGrid.getTileRangeForExtentAndResolution(extent, + resolutions[3]); + expect(tileRange.minX).toEqual(0); + expect(tileRange.minY).toEqual(0); + expect(tileRange.maxX).toEqual(9); + expect(tileRange.maxY).toEqual(9); + }); + }); + describe('getTileRangeForExtentAndZ', function() { it('returns the expected TileRange', function() { var tileGrid = new ol.tilegrid.TileGrid({