Merge pull request #1124 from tschaub/xyz
Allow tilegrid creation from projection or extent.
This commit is contained in:
@@ -5092,19 +5092,48 @@ olx.tilegrid.WMTSOptions.prototype.tileSizes;
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {{maxZoom: number}}
|
||||
* @typedef {{extent: (ol.Extent|undefined),
|
||||
* maxZoom: (number|undefined),
|
||||
* minZoom: (number|undefined),
|
||||
* tileSize: (number|undefined)}}
|
||||
* @api
|
||||
*/
|
||||
olx.tilegrid.XYZOptions;
|
||||
|
||||
|
||||
/**
|
||||
* Maximum zoom.
|
||||
* @type {number}
|
||||
* Extent for the tile grid. The origin for an XYZ tile grid is the top-left
|
||||
* corner of the extent. The zero level of the grid is defined by the
|
||||
* resolution at which one tile fits in the provided extent. If not provided,
|
||||
* the extent of the EPSG:3857 projection is used.
|
||||
* @type {ol.Extent|undefined}
|
||||
*/
|
||||
olx.tilegrid.XYZOptions.prototype.extent;
|
||||
|
||||
|
||||
/**
|
||||
* Maximum zoom. The default is `ol.DEFAULT_MAX_ZOOM`. This determines the
|
||||
* number of levels in the grid set. For example, a `maxZoom` of 21 means there
|
||||
* are 22 levels in the grid set.
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
olx.tilegrid.XYZOptions.prototype.maxZoom;
|
||||
|
||||
|
||||
/**
|
||||
* Minimum zoom. Default is 0.
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
olx.tilegrid.XYZOptions.prototype.minZoom;
|
||||
|
||||
|
||||
/**
|
||||
* Tile size in pixels. Default is 256. (Only square tiles are supported.)
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
olx.tilegrid.XYZOptions.prototype.tileSize;
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {{resolutions: !Array.<number>}}
|
||||
* @api
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
goog.provide('ol.Extent');
|
||||
goog.provide('ol.extent');
|
||||
goog.provide('ol.extent.Corner');
|
||||
goog.provide('ol.extent.Relationship');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
@@ -17,6 +18,18 @@ goog.require('ol.TransformFunction');
|
||||
ol.Extent;
|
||||
|
||||
|
||||
/**
|
||||
* Extent corner.
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.extent.Corner = {
|
||||
BOTTOM_LEFT: 'bottom-left',
|
||||
BOTTOM_RIGHT: 'bottom-right',
|
||||
TOP_LEFT: 'top-left',
|
||||
TOP_RIGHT: 'top-right'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Relationship to an extent.
|
||||
* @enum {number}
|
||||
@@ -456,6 +469,30 @@ ol.extent.getCenter = function(extent) {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get a corner coordinate of an extent.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {ol.extent.Corner} corner Corner.
|
||||
* @return {ol.Coordinate} Corner coordinate.
|
||||
*/
|
||||
ol.extent.getCorner = function(extent, corner) {
|
||||
var coordinate;
|
||||
if (corner === ol.extent.Corner.BOTTOM_LEFT) {
|
||||
coordinate = ol.extent.getBottomLeft(extent);
|
||||
} else if (corner === ol.extent.Corner.BOTTOM_RIGHT) {
|
||||
coordinate = ol.extent.getBottomRight(extent);
|
||||
} else if (corner === ol.extent.Corner.TOP_LEFT) {
|
||||
coordinate = ol.extent.getTopLeft(extent);
|
||||
} else if (corner === ol.extent.Corner.TOP_RIGHT) {
|
||||
coordinate = ol.extent.getTopRight(extent);
|
||||
} else {
|
||||
goog.asserts.fail('Invalid corner: %s', corner);
|
||||
}
|
||||
goog.asserts.assert(goog.isDef(coordinate));
|
||||
return coordinate;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent1 Extent 1.
|
||||
* @param {ol.Extent} extent2 Extent 2.
|
||||
|
||||
@@ -89,7 +89,9 @@ ol.source.BingMaps.prototype.handleImageryMetadataResponse =
|
||||
var resource = response.resourceSets[0].resources[0];
|
||||
|
||||
goog.asserts.assert(resource.imageWidth == resource.imageHeight);
|
||||
var sourceProjection = this.getProjection();
|
||||
var tileGrid = new ol.tilegrid.XYZ({
|
||||
extent: ol.tilegrid.extentFromProjection(sourceProjection),
|
||||
minZoom: resource.zoomMin,
|
||||
maxZoom: resource.zoomMax,
|
||||
tileSize: resource.imageWidth
|
||||
@@ -97,7 +99,6 @@ ol.source.BingMaps.prototype.handleImageryMetadataResponse =
|
||||
this.tileGrid = tileGrid;
|
||||
|
||||
var culture = this.culture_;
|
||||
var sourceProjection = this.getProjection();
|
||||
this.tileUrlFunction = ol.TileUrlFunction.withTileCoordTransform(
|
||||
tileGrid.createTileCoordTransform(),
|
||||
ol.TileUrlFunction.createFromTileUrlFunctions(
|
||||
|
||||
@@ -54,10 +54,11 @@ ol.source.TileJSON.prototype.handleTileJSONResponse = function(tileJSON) {
|
||||
|
||||
var epsg4326Projection = ol.proj.get('EPSG:4326');
|
||||
|
||||
var sourceProjection = this.getProjection();
|
||||
var extent;
|
||||
if (goog.isDef(tileJSON.bounds)) {
|
||||
var transform = ol.proj.getTransformFromProjections(
|
||||
epsg4326Projection, this.getProjection());
|
||||
epsg4326Projection, sourceProjection);
|
||||
extent = ol.extent.applyTransform(tileJSON.bounds, transform);
|
||||
}
|
||||
|
||||
@@ -67,6 +68,7 @@ ol.source.TileJSON.prototype.handleTileJSONResponse = function(tileJSON) {
|
||||
var minZoom = tileJSON.minzoom || 0;
|
||||
var maxZoom = tileJSON.maxzoom || 22;
|
||||
var tileGrid = new ol.tilegrid.XYZ({
|
||||
extent: ol.tilegrid.extentFromProjection(sourceProjection),
|
||||
maxZoom: maxZoom,
|
||||
minZoom: minZoom
|
||||
});
|
||||
|
||||
@@ -17,14 +17,12 @@ goog.require('ol.tilegrid.XYZ');
|
||||
* @api
|
||||
*/
|
||||
ol.source.XYZ = function(options) {
|
||||
|
||||
var projection = goog.isDef(options.projection) ?
|
||||
options.projection : 'EPSG:3857';
|
||||
|
||||
var maxZoom = goog.isDef(options.maxZoom) ? options.maxZoom : 18;
|
||||
|
||||
var tileGrid = new ol.tilegrid.XYZ({
|
||||
maxZoom: maxZoom
|
||||
extent: ol.tilegrid.extentFromProjection(projection),
|
||||
maxZoom: options.maxZoom
|
||||
});
|
||||
|
||||
goog.base(this, {
|
||||
|
||||
@@ -8,6 +8,8 @@ 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');
|
||||
goog.require('ol.proj.METERS_PER_UNIT');
|
||||
goog.require('ol.proj.Projection');
|
||||
goog.require('ol.proj.Units');
|
||||
@@ -404,31 +406,93 @@ 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]);
|
||||
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 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);
|
||||
}
|
||||
ol.tilegrid.createForExtent =
|
||||
function(extent, opt_maxZoom, opt_tileSize, opt_corner) {
|
||||
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 resolutions = ol.tilegrid.resolutionsFromExtent(
|
||||
extent, opt_maxZoom, tileSize);
|
||||
|
||||
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
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a resolutions array from an extent. A zoom factor of 2 is assumed.
|
||||
* @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).
|
||||
* @return {!Array.<number>} Resolutions array.
|
||||
*/
|
||||
ol.tilegrid.resolutionsFromExtent =
|
||||
function(extent, opt_maxZoom, opt_tileSize) {
|
||||
var maxZoom = goog.isDef(opt_maxZoom) ?
|
||||
opt_maxZoom : ol.DEFAULT_MAX_ZOOM;
|
||||
|
||||
var height = ol.extent.getHeight(extent);
|
||||
var width = ol.extent.getWidth(extent);
|
||||
|
||||
var tileSize = goog.isDef(opt_tileSize) ?
|
||||
opt_tileSize : ol.DEFAULT_TILE_SIZE;
|
||||
var maxResolution = Math.max(
|
||||
width / tileSize, height / tileSize);
|
||||
|
||||
var length = maxZoom + 1;
|
||||
var resolutions = new Array(length);
|
||||
for (var z = 0; z < length; ++z) {
|
||||
resolutions[z] = maxResolution / Math.pow(2, z);
|
||||
}
|
||||
return resolutions;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.proj.ProjectionLike} 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 = ol.tilegrid.extentFromProjection(projection);
|
||||
return ol.tilegrid.createForExtent(
|
||||
extent, opt_maxZoom, opt_tileSize, opt_corner);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Generate a tile grid extent from a projection. If the projection has an
|
||||
* extent, it is used. If not, a global extent is assumed.
|
||||
* @param {ol.proj.ProjectionLike} projection Projection.
|
||||
* @return {ol.Extent} Extent.
|
||||
*/
|
||||
ol.tilegrid.extentFromProjection = function(projection) {
|
||||
projection = ol.proj.get(projection);
|
||||
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 extent;
|
||||
};
|
||||
|
||||
@@ -4,6 +4,8 @@ goog.require('goog.math');
|
||||
goog.require('ol');
|
||||
goog.require('ol.TileCoord');
|
||||
goog.require('ol.TileRange');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.extent.Corner');
|
||||
goog.require('ol.proj');
|
||||
goog.require('ol.proj.EPSG3857');
|
||||
goog.require('ol.tilecoord');
|
||||
@@ -22,19 +24,16 @@ goog.require('ol.tilegrid.TileGrid');
|
||||
* @api
|
||||
*/
|
||||
ol.tilegrid.XYZ = function(options) {
|
||||
|
||||
var resolutions = new Array(options.maxZoom + 1);
|
||||
var z;
|
||||
var size = 2 * ol.proj.EPSG3857.HALF_SIZE / ol.DEFAULT_TILE_SIZE;
|
||||
for (z = 0; z <= options.maxZoom; ++z) {
|
||||
resolutions[z] = size / Math.pow(2, z);
|
||||
}
|
||||
var extent = goog.isDef(options.extent) ?
|
||||
options.extent : ol.proj.EPSG3857.EXTENT;
|
||||
var resolutions = ol.tilegrid.resolutionsFromExtent(
|
||||
extent, options.maxZoom, options.tileSize);
|
||||
|
||||
goog.base(this, {
|
||||
minZoom: options.minZoom,
|
||||
origin: [-ol.proj.EPSG3857.HALF_SIZE, ol.proj.EPSG3857.HALF_SIZE],
|
||||
origin: ol.extent.getCorner(extent, ol.extent.Corner.TOP_LEFT),
|
||||
resolutions: resolutions,
|
||||
tileSize: ol.DEFAULT_TILE_SIZE
|
||||
tileSize: options.tileSize
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
@@ -177,6 +177,31 @@ describe('ol.extent', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('getCorner', function() {
|
||||
var extent = [1, 2, 3, 4];
|
||||
|
||||
it('gets the bottom left', function() {
|
||||
var corner = ol.extent.Corner.BOTTOM_LEFT;
|
||||
expect(ol.extent.getCorner(extent, corner)).to.eql([1, 2]);
|
||||
});
|
||||
|
||||
it('gets the bottom right', function() {
|
||||
var corner = ol.extent.Corner.BOTTOM_RIGHT;
|
||||
expect(ol.extent.getCorner(extent, corner)).to.eql([3, 2]);
|
||||
});
|
||||
|
||||
it('gets the top left', function() {
|
||||
var corner = ol.extent.Corner.TOP_LEFT;
|
||||
expect(ol.extent.getCorner(extent, corner)).to.eql([1, 4]);
|
||||
});
|
||||
|
||||
it('gets the top right', function() {
|
||||
var corner = ol.extent.Corner.TOP_RIGHT;
|
||||
expect(ol.extent.getCorner(extent, corner)).to.eql([3, 4]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('getForViewAndSize', function() {
|
||||
|
||||
it('works for a unit square', function() {
|
||||
@@ -538,5 +563,6 @@ describe('ol.extent', function() {
|
||||
|
||||
goog.require('goog.vec.Mat4');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.extent.Corner');
|
||||
goog.require('ol.extent.Relationship');
|
||||
goog.require('ol.proj');
|
||||
|
||||
@@ -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');
|
||||
|
||||
Reference in New Issue
Block a user