Pass transformed tile coordinates to the tileUrlFunction

This commit is contained in:
Andreas Hocevar
2015-06-12 09:45:03 +02:00
parent fad3cf9672
commit 6a4d1c9b89
21 changed files with 189 additions and 350 deletions
+1 -1
View File
@@ -3,7 +3,7 @@ template: example.html
title: XYZ Esri EPSG:4326 tileSize 512 example title: XYZ Esri EPSG:4326 tileSize 512 example
shortdesc: Example of a XYZ source in EPSG:4326 using Esri 512x512 tiles. shortdesc: Example of a XYZ source in EPSG:4326 using Esri 512x512 tiles.
docs: > docs: >
ArcGIS REST tile services with custom tile sizes (here: 512x512 pixels) and projection (here: EPSG:4326) are supported by `ol.source.XYZ`. A custom tile grid and tile url function are required. ArcGIS REST tile services with custom tile sizes (here: 512x512 pixels) and projection (here: EPSG:4326) are supported by `ol.source.XYZ`. A custom tile url function is used to handle zoom level offsets.
tags: "xyz, esri, tilesize, custom projection" tags: "xyz, esri, tilesize, custom projection"
--- ---
<div class="row-fluid"> <div class="row-fluid">
+10 -38
View File
@@ -1,33 +1,19 @@
goog.require('ol.Attribution'); goog.require('ol.Attribution');
goog.require('ol.Map'); goog.require('ol.Map');
goog.require('ol.View'); goog.require('ol.View');
goog.require('ol.extent');
goog.require('ol.layer.Tile'); goog.require('ol.layer.Tile');
goog.require('ol.proj'); goog.require('ol.proj');
goog.require('ol.source.TileImage'); goog.require('ol.source.XYZ');
goog.require('ol.tilegrid.TileGrid');
var attribution = new ol.Attribution({ var attribution = new ol.Attribution({
html: 'Copyright:&copy; 2013 ESRI, i-cubed, GeoEye' html: 'Copyright:&copy; 2013 ESRI, i-cubed, GeoEye'
}); });
var projection = ol.proj.get('EPSG:4326'); var projection = ol.proj.get('EPSG:4326');
var projectionExtent = projection.getExtent();
// The tile size supported by the ArcGIS tile service. // The tile size supported by the ArcGIS tile service.
var tileSize = 512; var tileSize = 512;
// Calculate the resolutions supported by the ArcGIS tile service.
// There are 16 resolutions, with a factor of 2 between successive
// resolutions. The max resolution is such that the world (360°)
// fits into two (512x512 px) tiles.
var maxResolution = ol.extent.getWidth(projectionExtent) / (tileSize * 2);
var resolutions = new Array(16);
var z;
for (z = 0; z < 16; ++z) {
resolutions[z] = maxResolution / Math.pow(2, z);
}
var urlTemplate = 'http://services.arcgisonline.com/arcgis/rest/services/' + var urlTemplate = 'http://services.arcgisonline.com/arcgis/rest/services/' +
'ESRI_Imagery_World_2D/MapServer/tile/{z}/{y}/{x}'; 'ESRI_Imagery_World_2D/MapServer/tile/{z}/{y}/{x}';
@@ -35,31 +21,17 @@ var map = new ol.Map({
target: 'map', target: 'map',
layers: [ layers: [
new ol.layer.Tile({ new ol.layer.Tile({
/* ol.source.XYZ and ol.tilegrid.TileGrid have no resolutions config */ source: new ol.source.XYZ({
source: new ol.source.TileImage({
attributions: [attribution], attributions: [attribution],
tileUrlFunction: function(tileCoord, pixelRatio, projection) { maxZoom: 16,
var z = tileCoord[0];
var x = tileCoord[1];
var y = -tileCoord[2] - 1;
// wrap the world on the X axis
var n = Math.pow(2, z + 1); // 2 tiles at z=0
x = x % n;
if (x * n < 0) {
// x and n differ in sign so add n to wrap the result
// to the correct sign
x = x + n;
}
return urlTemplate.replace('{z}', z.toString())
.replace('{y}', y.toString())
.replace('{x}', x.toString());
},
projection: projection, projection: projection,
tileGrid: new ol.tilegrid.TileGrid({ tileSize: 512,
origin: ol.extent.getTopLeft(projectionExtent), tileUrlFunction: function(tileCoord) {
resolutions: resolutions, return urlTemplate.replace('{z}', (tileCoord[0] - 1).toString())
tileSize: 512 .replace('{x}', tileCoord[1].toString())
}) .replace('{y}', tileCoord[2].toString());
},
wrapX: true
}) })
}) })
], ],
+1 -1
View File
@@ -6133,7 +6133,7 @@ olx.tilegrid;
/** /**
* @typedef {{createTileCoordTransform: (undefined|function({extent: (ol.Extent|undefined)}):function(ol.TileCoord, ol.proj.Projection, ol.TileCoord=):ol.TileCoord), * @typedef {{transformTileCoord: (undefined|function(ol.TileCoord, ol.TileCoord=):ol.TileCoord),
* extent: (ol.Extent|undefined), * extent: (ol.Extent|undefined),
* minZoom: (number|undefined), * minZoom: (number|undefined),
* origin: (ol.Coordinate|undefined), * origin: (ol.Coordinate|undefined),
+26 -28
View File
@@ -114,34 +114,32 @@ ol.source.BingMaps.prototype.handleImageryMetadataResponse =
this.tileGrid = tileGrid; this.tileGrid = tileGrid;
var culture = this.culture_; var culture = this.culture_;
this.tileUrlFunction = ol.TileUrlFunction.withTileCoordTransform( this.tileUrlFunction = ol.TileUrlFunction.createFromTileUrlFunctions(
tileGrid.createTileCoordTransform(), goog.array.map(
ol.TileUrlFunction.createFromTileUrlFunctions( resource.imageUrlSubdomains,
goog.array.map( function(subdomain) {
resource.imageUrlSubdomains, var imageUrl = resource.imageUrl
function(subdomain) { .replace('{subdomain}', subdomain)
var imageUrl = resource.imageUrl .replace('{culture}', culture);
.replace('{subdomain}', subdomain) return (
.replace('{culture}', culture); /**
return ( * @param {ol.TileCoord} tileCoord Tile coordinate.
/** * @param {number} pixelRatio Pixel ratio.
* @param {ol.TileCoord} tileCoord Tile coordinate. * @param {ol.proj.Projection} projection Projection.
* @param {number} pixelRatio Pixel ratio. * @return {string|undefined} Tile URL.
* @param {ol.proj.Projection} projection Projection. */
* @return {string|undefined} Tile URL. function(tileCoord, pixelRatio, projection) {
*/ goog.asserts.assert(ol.proj.equivalent(
function(tileCoord, pixelRatio, projection) { projection, sourceProjection),
goog.asserts.assert(ol.proj.equivalent( 'projections are equivalent');
projection, sourceProjection), if (goog.isNull(tileCoord)) {
'projections are equivalent'); return undefined;
if (goog.isNull(tileCoord)) { } else {
return undefined; return imageUrl.replace(
} else { '{quadkey}', ol.tilecoord.quadKey(tileCoord));
return imageUrl.replace( }
'{quadkey}', ol.tilecoord.quadKey(tileCoord)); });
} }));
});
})));
if (resource.imageryProviders) { if (resource.imageryProviders) {
var transform = ol.proj.getTransformFromProjections( var transform = ol.proj.getTransformFromProjections(
+1 -3
View File
@@ -75,9 +75,7 @@ ol.source.TileJSON.prototype.handleTileJSONResponse = function(tileJSON) {
}); });
this.tileGrid = tileGrid; this.tileGrid = tileGrid;
this.tileUrlFunction = ol.TileUrlFunction.withTileCoordTransform( this.tileUrlFunction = ol.TileUrlFunction.createFromTemplates(tileJSON.tiles);
tileGrid.createTileCoordTransform(),
ol.TileUrlFunction.createFromTemplates(tileJSON.tiles));
if (goog.isDef(tileJSON.attribution) && if (goog.isDef(tileJSON.attribution) &&
goog.isNull(this.getAttributions())) { goog.isNull(this.getAttributions())) {
+6 -3
View File
@@ -217,8 +217,10 @@ ol.source.Tile.prototype.getTilePixelSize =
/** /**
* Handles x-axis wrapping and returns a tile coordinate when it is within * Handles x-axis wrapping and returns a tile coordinate transformed from the
* the resolution and extent range. * internal tile scheme to the tile grid's tile scheme. When the tile coordinate
* is outside the resolution and extent range of the tile grid, `null` will be
* returned.
* @param {ol.TileCoord} tileCoord Tile coordinate. * @param {ol.TileCoord} tileCoord Tile coordinate.
* @param {ol.proj.Projection=} opt_projection Projection. * @param {ol.proj.Projection=} opt_projection Projection.
* @return {ol.TileCoord} Tile coordinate to be passed to the tileUrlFunction or * @return {ol.TileCoord} Tile coordinate to be passed to the tileUrlFunction or
@@ -233,7 +235,8 @@ ol.source.Tile.prototype.getTileCoordForTileUrlFunction =
if (this.getWrapX()) { if (this.getWrapX()) {
tileCoord = ol.tilecoord.wrapX(tileCoord, tileGrid, projection); tileCoord = ol.tilecoord.wrapX(tileCoord, tileGrid, projection);
} }
return ol.tilecoord.restrictByExtentAndZ(tileCoord, tileGrid); return ol.tilecoord.withinExtentAndZ(tileCoord, tileGrid) ?
tileGrid.transformTileCoord(tileCoord) : null;
}; };
+4 -4
View File
@@ -136,9 +136,7 @@ ol.source.TileUTFGrid.prototype.handleTileJSONResponse = function(tileJSON) {
return; return;
} }
this.tileUrlFunction_ = ol.TileUrlFunction.withTileCoordTransform( this.tileUrlFunction_ = ol.TileUrlFunction.createFromTemplates(grids);
tileGrid.createTileCoordTransform(),
ol.TileUrlFunction.createFromTemplates(grids));
if (goog.isDef(tileJSON.attribution)) { if (goog.isDef(tileJSON.attribution)) {
var attributionExtent = goog.isDef(extent) ? var attributionExtent = goog.isDef(extent) ?
@@ -175,7 +173,9 @@ ol.source.TileUTFGrid.prototype.getTile =
} else { } else {
goog.asserts.assert(projection, 'argument projection is truthy'); goog.asserts.assert(projection, 'argument projection is truthy');
var tileCoord = [z, x, y]; var tileCoord = [z, x, y];
var tileUrl = this.tileUrlFunction_(tileCoord, pixelRatio, projection); var urlTileCoord =
this.getTileCoordForTileUrlFunction(tileCoord, projection);
var tileUrl = this.tileUrlFunction_(urlTileCoord, pixelRatio, projection);
var tile = new ol.source.TileUTFGridTile_( var tile = new ol.source.TileUTFGridTile_(
tileCoord, tileCoord,
goog.isDef(tileUrl) ? ol.TileState.IDLE : ol.TileState.EMPTY, goog.isDef(tileUrl) ? ol.TileState.IDLE : ol.TileState.EMPTY,
+1 -9
View File
@@ -3,7 +3,6 @@ goog.provide('ol.source.TileVector');
goog.require('goog.array'); goog.require('goog.array');
goog.require('goog.asserts'); goog.require('goog.asserts');
goog.require('goog.object'); goog.require('goog.object');
goog.require('ol.TileCoord');
goog.require('ol.TileUrlFunction'); goog.require('ol.TileUrlFunction');
goog.require('ol.featureloader'); goog.require('ol.featureloader');
goog.require('ol.source.State'); goog.require('ol.source.State');
@@ -52,12 +51,6 @@ ol.source.TileVector = function(options) {
*/ */
this.tileUrlFunction_ = ol.TileUrlFunction.nullTileUrlFunction; this.tileUrlFunction_ = ol.TileUrlFunction.nullTileUrlFunction;
/**
* @private
* @type {ol.TileCoordTransformType}
*/
this.tileCoordTransform_ = this.tileGrid_.createTileCoordTransform();
/** /**
* @private * @private
* @type {Object.<string, Array.<ol.Feature>>} * @type {Object.<string, Array.<ol.Feature>>}
@@ -254,7 +247,6 @@ ol.source.TileVector.prototype.getTileKeyZXY_ = function(z, x, y) {
*/ */
ol.source.TileVector.prototype.loadFeatures = ol.source.TileVector.prototype.loadFeatures =
function(extent, resolution, projection) { function(extent, resolution, projection) {
var tileCoordTransform = this.tileCoordTransform_;
var tileGrid = this.tileGrid_; var tileGrid = this.tileGrid_;
var tileUrlFunction = this.tileUrlFunction_; var tileUrlFunction = this.tileUrlFunction_;
var tiles = this.tiles_; var tiles = this.tiles_;
@@ -278,7 +270,7 @@ ol.source.TileVector.prototype.loadFeatures =
tileCoord[0] = z; tileCoord[0] = z;
tileCoord[1] = x; tileCoord[1] = x;
tileCoord[2] = y; tileCoord[2] = y;
tileCoordTransform(tileCoord, projection, tileCoord); tileGrid.transformTileCoord(tileCoord, tileCoord);
var url = tileUrlFunction(tileCoord, 1, projection); var url = tileUrlFunction(tileCoord, 1, projection);
if (goog.isDef(url)) { if (goog.isDef(url)) {
tiles[tileKey] = []; tiles[tileKey] = [];
-4
View File
@@ -180,10 +180,6 @@ ol.source.WMTS = function(options) {
goog.array.map(this.urls_, createFromWMTSTemplate)) : goog.array.map(this.urls_, createFromWMTSTemplate)) :
ol.TileUrlFunction.nullTileUrlFunction; ol.TileUrlFunction.nullTileUrlFunction;
tileUrlFunction = ol.TileUrlFunction.withTileCoordTransform(
ol.tilegrid.createOriginTopLeftTileCoordTransform(tileGrid),
tileUrlFunction);
goog.base(this, { goog.base(this, {
attributions: options.attributions, attributions: options.attributions,
crossOrigin: options.crossOrigin, crossOrigin: options.crossOrigin,
-17
View File
@@ -37,12 +37,6 @@ ol.source.XYZ = function(options) {
wrapX: goog.isDef(options.wrapX) ? options.wrapX : true wrapX: goog.isDef(options.wrapX) ? options.wrapX : true
}); });
/**
* @private
* @type {ol.TileCoordTransformType}
*/
this.tileCoordTransform_ = tileGrid.createTileCoordTransform();
if (goog.isDef(options.tileUrlFunction)) { if (goog.isDef(options.tileUrlFunction)) {
this.setTileUrlFunction(options.tileUrlFunction); this.setTileUrlFunction(options.tileUrlFunction);
} else if (goog.isDef(options.urls)) { } else if (goog.isDef(options.urls)) {
@@ -55,17 +49,6 @@ ol.source.XYZ = function(options) {
goog.inherits(ol.source.XYZ, ol.source.TileImage); goog.inherits(ol.source.XYZ, ol.source.TileImage);
/**
* @inheritDoc
* @api
*/
ol.source.XYZ.prototype.setTileUrlFunction = function(tileUrlFunction) {
goog.base(this, 'setTileUrlFunction',
ol.TileUrlFunction.withTileCoordTransform(
this.tileCoordTransform_, tileUrlFunction));
};
/** /**
* Set the URL to use for requests. * Set the URL to use for requests.
* @param {string} url URL. * @param {string} url URL.
+25 -26
View File
@@ -5,7 +5,6 @@ goog.require('ol');
goog.require('ol.ImageTile'); goog.require('ol.ImageTile');
goog.require('ol.TileCoord'); goog.require('ol.TileCoord');
goog.require('ol.TileState'); goog.require('ol.TileState');
goog.require('ol.TileUrlFunction');
goog.require('ol.dom'); goog.require('ol.dom');
goog.require('ol.proj'); goog.require('ol.proj');
goog.require('ol.source.TileImage'); goog.require('ol.source.TileImage');
@@ -88,35 +87,35 @@ ol.source.Zoomify = function(opt_options) {
resolutions.reverse(); resolutions.reverse();
var tileGrid = new ol.tilegrid.Zoomify({ var tileGrid = new ol.tilegrid.Zoomify({
extent: [0, 0, size[0], size[1]],
resolutions: resolutions resolutions: resolutions
}); });
var url = options.url; var url = options.url;
var tileUrlFunction = ol.TileUrlFunction.withTileCoordTransform(
tileGrid.createTileCoordTransform({extent: [0, 0, size[0], size[1]]}), /**
/** * @this {ol.source.TileImage}
* @this {ol.source.TileImage} * @param {ol.TileCoord} tileCoord Tile Coordinate.
* @param {ol.TileCoord} tileCoord Tile Coordinate. * @param {number} pixelRatio Pixel ratio.
* @param {number} pixelRatio Pixel ratio. * @param {ol.proj.Projection} projection Projection.
* @param {ol.proj.Projection} projection Projection. * @return {string|undefined} Tile URL.
* @return {string|undefined} Tile URL. */
*/ function tileUrlFunction(tileCoord, pixelRatio, projection) {
function(tileCoord, pixelRatio, projection) { if (goog.isNull(tileCoord)) {
if (goog.isNull(tileCoord)) { return undefined;
return undefined; } else {
} else { var tileCoordZ = tileCoord[0];
var tileCoordZ = tileCoord[0]; var tileCoordX = tileCoord[1];
var tileCoordX = tileCoord[1]; var tileCoordY = tileCoord[2];
var tileCoordY = tileCoord[2]; var tileIndex =
var tileIndex = tileCoordX +
tileCoordX + tileCoordY * tierSizeInTiles[tileCoordZ][0] +
tileCoordY * tierSizeInTiles[tileCoordZ][0] + tileCountUpToTier[tileCoordZ];
tileCountUpToTier[tileCoordZ]; var tileGroup = (tileIndex / ol.DEFAULT_TILE_SIZE) | 0;
var tileGroup = (tileIndex / ol.DEFAULT_TILE_SIZE) | 0; return url + 'TileGroup' + tileGroup + '/' +
return url + 'TileGroup' + tileGroup + '/' + tileCoordZ + '-' + tileCoordX + '-' + tileCoordY + '.jpg';
tileCoordZ + '-' + tileCoordX + '-' + tileCoordY + '.jpg'; }
} }
});
goog.base(this, { goog.base(this, {
attributions: options.attributions, attributions: options.attributions,
+5 -5
View File
@@ -165,15 +165,15 @@ ol.tilecoord.wrapX = function(tileCoord, tileGrid, projection) {
/** /**
* @param {ol.TileCoord} tileCoord Tile coordinate. * @param {ol.TileCoord} tileCoord Tile coordinate.
* @param {!ol.tilegrid.TileGrid} tileGrid Tile grid. * @param {!ol.tilegrid.TileGrid} tileGrid Tile grid.
* @return {ol.TileCoord} Tile coordinate. * @return {boolean} Tile coordinate is within extent and zoom level range.
*/ */
ol.tilecoord.restrictByExtentAndZ = function(tileCoord, tileGrid) { ol.tilecoord.withinExtentAndZ = function(tileCoord, tileGrid) {
var z = tileCoord[0]; var z = tileCoord[0];
var x = tileCoord[1]; var x = tileCoord[1];
var y = tileCoord[2]; var y = tileCoord[2];
if (tileGrid.getMinZoom() > z || z > tileGrid.getMaxZoom()) { if (tileGrid.getMinZoom() > z || z > tileGrid.getMaxZoom()) {
return null; return false;
} }
var extent = tileGrid.getExtent(); var extent = tileGrid.getExtent();
var tileRange; var tileRange;
@@ -183,8 +183,8 @@ ol.tilecoord.restrictByExtentAndZ = function(tileCoord, tileGrid) {
tileRange = tileGrid.getTileRangeForExtentAndZ(extent, z); tileRange = tileGrid.getTileRangeForExtentAndZ(extent, z);
} }
if (goog.isNull(tileRange)) { if (goog.isNull(tileRange)) {
return tileCoord; return true;
} else { } else {
return tileRange.containsXY(x, y) ? tileCoord : null; return tileRange.containsXY(x, y);
} }
}; };
+24 -46
View File
@@ -114,20 +114,15 @@ ol.tilegrid.TileGrid = function(options) {
/** /**
* Creates a TileCoord transform function for use with this tile grid. * TileCoord transform function for use with this tile grid. Transforms the
* Transforms the internal tile coordinates with bottom-left origin to * internal tile coordinates with bottom-left origin to the tile coordinates
* the tile coordinates used by the {@link ol.TileUrlFunction}. * used by the source's {@link ol.TileUrlFunction}.
* The returned function expects an {@link ol.TileCoord} as first and an * @param {ol.TileCoord} tileCoord Tile coordinate.
* {@link ol.proj.Projection} as second argument and returns a transformed * @param {ol.TileCoord=} opt_tileCoord Destination tile coordinate.
* {@link ol.TileCoord}. * @return {ol.TileCoord} Tile coordinate.
* @param {{extent: (ol.Extent|undefined)}=} opt_options Options.
* @return {function(ol.TileCoord, ol.proj.Projection, ol.TileCoord=):
* ol.TileCoord} Tile coordinate transform.
* @api
*/ */
this.createTileCoordTransform = goog.isDef(options.createTileCoordTransform) ? this.transformTileCoord = goog.isDef(options.transformTileCoord) ?
options.createTileCoordTransform : options.transformTileCoord : goog.functions.identity;
goog.functions.identity;
/** /**
* @private * @private
@@ -582,15 +577,7 @@ ol.tilegrid.createXYZ = function(opt_options) {
options.extent, options.maxZoom, options.tileSize); options.extent, options.maxZoom, options.tileSize);
delete options.maxZoom; delete options.maxZoom;
/** options.transformTileCoord = ol.tilegrid.originTopLeftTileCoordTransform;
* @param {{extent: (ol.Extent|undefined)}=} opt_options Options.
* @return {function(ol.TileCoord, ol.proj.Projection, ol.TileCoord=):
* ol.TileCoord} Tile coordinate transform.
* @this {ol.tilegrid.TileGrid}
*/
options.createTileCoordTransform = function(opt_options) {
return ol.tilegrid.createOriginTopLeftTileCoordTransform(this);
};
return new ol.tilegrid.TileGrid(options); return new ol.tilegrid.TileGrid(options);
}; };
@@ -663,29 +650,20 @@ ol.tilegrid.extentFromProjection = function(projection) {
/** /**
* @param {ol.tilegrid.TileGrid} tileGrid Tile grid. * @param {ol.TileCoord} tileCoord Tile coordinate.
* @return {function(ol.TileCoord, ol.proj.Projection, ol.TileCoord=): * @param {ol.TileCoord=} opt_tileCoord Destination tile coordinate.
* ol.TileCoord} Tile coordinate transform. * @return {ol.TileCoord} Tile coordinate.
* @this {ol.tilegrid.TileGrid}
*/ */
ol.tilegrid.createOriginTopLeftTileCoordTransform = function(tileGrid) { ol.tilegrid.originTopLeftTileCoordTransform =
goog.asserts.assert(!goog.isNull(tileGrid), 'tileGrid required'); function(tileCoord, opt_tileCoord) {
return ( if (goog.isNull(tileCoord)) {
/** return null;
* @param {ol.TileCoord} tileCoord Tile coordinate. }
* @param {ol.proj.Projection} projection Projection. var z = tileCoord[0];
* @param {ol.TileCoord=} opt_tileCoord Destination tile coordinate. var fullTileRange = this.getFullTileRange(z);
* @return {ol.TileCoord} Tile coordinate. var height = (goog.isNull(fullTileRange) || fullTileRange.minY < 0) ?
*/ 0 : fullTileRange.getHeight();
function(tileCoord, projection, opt_tileCoord) { return ol.tilecoord.createOrUpdate(
if (goog.isNull(tileCoord)) { z, tileCoord[1], height - tileCoord[2] - 1, opt_tileCoord);
return null;
}
var z = tileCoord[0];
var fullTileRange = tileGrid.getFullTileRange(z);
var height = (goog.isNull(fullTileRange) || fullTileRange.minY < 0) ?
0 : fullTileRange.getHeight();
return ol.tilecoord.createOrUpdate(
z, tileCoord[1], height - tileCoord[2] - 1, opt_tileCoord);
}
);
}; };
+2 -1
View File
@@ -38,7 +38,8 @@ ol.tilegrid.WMTS = function(options) {
resolutions: options.resolutions, resolutions: options.resolutions,
tileSize: options.tileSize, tileSize: options.tileSize,
tileSizes: options.tileSizes, tileSizes: options.tileSizes,
sizes: options.sizes sizes: options.sizes,
transformTileCoord: ol.tilegrid.originTopLeftTileCoordTransform
}); });
}; };
+40 -51
View File
@@ -2,7 +2,6 @@ goog.provide('ol.tilegrid.Zoomify');
goog.require('goog.math'); goog.require('goog.math');
goog.require('ol.TileCoord'); goog.require('ol.TileCoord');
goog.require('ol.proj');
goog.require('ol.tilecoord'); goog.require('ol.tilecoord');
goog.require('ol.tilegrid.TileGrid'); goog.require('ol.tilegrid.TileGrid');
@@ -20,64 +19,54 @@ goog.require('ol.tilegrid.TileGrid');
ol.tilegrid.Zoomify = function(opt_options) { ol.tilegrid.Zoomify = function(opt_options) {
var options = goog.isDef(opt_options) ? opt_options : options; var options = goog.isDef(opt_options) ? opt_options : options;
/** @type {Array.<ol.TileRange>} */
var tileRangeByZ = goog.isDef(options.extent) ? [] : null;
/** /**
* @param {{extent: (ol.Extent|undefined)}=} opt_options Options. * @param {ol.TileCoord} tileCoord Tile coordinate.
* @return {function(ol.TileCoord, ol.proj.Projection, ol.TileCoord=): * @param {ol.TileCoord=} opt_tileCoord Destination tile coordinate.
* ol.TileCoord} Tile coordinate transform. * @return {ol.TileCoord} Tile coordinate.
* @this {ol.tilegrid.Zoomify}
*/ */
var createTileCoordTransform = function(opt_options) { function transformTileCoord(tileCoord, opt_tileCoord) {
var options = goog.isDef(opt_options) ? opt_options : {}; var z = tileCoord[0];
var minZ = this.minZoom; if (z < minZ || maxZ < z) {
var maxZ = this.maxZoom; return null;
/** @type {Array.<ol.TileRange>} */ }
var tileRangeByZ = null; var n = Math.pow(2, z);
if (goog.isDef(options.extent)) { var x = tileCoord[1];
tileRangeByZ = new Array(maxZ + 1); if (x < 0 || n <= x) {
var z; return null;
for (z = 0; z <= maxZ; ++z) { }
if (z < minZ) { var y = tileCoord[2];
tileRangeByZ[z] = null; if (y < -n || -1 < y) {
} else { return null;
tileRangeByZ[z] = this.getTileRangeForExtentAndZ(options.extent, z); }
} if (!goog.isNull(tileRangeByZ)) {
if (!tileRangeByZ[z].containsXY(x, -y - 1)) {
return null;
} }
} }
return ( return ol.tilecoord.createOrUpdate(z, x, -y - 1, opt_tileCoord);
/** }
* @param {ol.TileCoord} tileCoord Tile coordinate.
* @param {ol.proj.Projection} projection Projection.
* @param {ol.TileCoord=} opt_tileCoord Destination tile coordinate.
* @return {ol.TileCoord} Tile coordinate.
*/
function(tileCoord, projection, opt_tileCoord) {
var z = tileCoord[0];
if (z < minZ || maxZ < z) {
return null;
}
var n = Math.pow(2, z);
var x = tileCoord[1];
if (x < 0 || n <= x) {
return null;
}
var y = tileCoord[2];
if (y < -n || -1 < y) {
return null;
}
if (!goog.isNull(tileRangeByZ)) {
if (!tileRangeByZ[z].containsXY(x, -y - 1)) {
return null;
}
}
return ol.tilecoord.createOrUpdate(z, x, -y - 1, opt_tileCoord);
});
};
goog.base(this, { goog.base(this, {
createTileCoordTransform: createTileCoordTransform,
origin: [0, 0], origin: [0, 0],
resolutions: options.resolutions resolutions: options.resolutions,
transformTileCoord: transformTileCoord
}); });
if (goog.isDef(options.extent)) {
var minZ = this.minZoom;
var maxZ = this.maxZoom;
tileRangeByZ = [];
var z;
for (z = 0; z <= maxZ; ++z) {
if (z < minZ) {
tileRangeByZ[z] = null;
} else {
tileRangeByZ[z] = this.getTileRangeForExtentAndZ(options.extent, z);
}
}
}
}; };
goog.inherits(ol.tilegrid.Zoomify, ol.tilegrid.TileGrid); goog.inherits(ol.tilegrid.Zoomify, ol.tilegrid.TileGrid);
+7 -53
View File
@@ -9,32 +9,14 @@ goog.require('ol.tilecoord');
/** /**
* A function that takes an {@link ol.TileCoord} for the tile coordinate, * {@link ol.source.Tile} sources use a function of this type to get the url
* a `{number}` representing the pixel ratio and an {@link ol.proj.Projection} * that provides a tile for a given tile coordinate.
* for the projection as arguments and returns a `{string}` or
* undefined representing the tile URL.
* *
* The {@link ol.TileCoord}'s `x` value * This function takes an {@link ol.TileCoord} for the tile coordinate, a
* increases from left to right, `y` increases from bottom to top. At the * `{number}` representing the pixel ratio and an {@link ol.proj.Projection} for
* bottom left corner, `x` and `y` are `0`. To convert `y` to increase from * the projection as arguments and returns a `{string}` representing the tile
* top to bottom, use the following code: * URL, or undefined if no tile should be requested for the passed tile
* ```js * coordinate.
* var tileGrid = new ol.tilegrid.TileGrid({
* extent: extent,
* resolutions: resolutions,
* tileSize: tileSize
* });
*
* function calculateY(tileCoord) {
* var z = tileCoord[0];
* var yFromBottom = tileCoord[2];
* var resolution = tileGrid.getResolution(z);
* var tileHeight = ol.size.toSize(tileSize)[1];
* var matrixHeight =
* Math.floor(ol.extent.getHeight(extent) / tileHeight / resolution);
* return matrixHeight - yFromBottom - 1;
* };
* ```
* *
* @typedef {function(ol.TileCoord, number, * @typedef {function(ol.TileCoord, number,
* ol.proj.Projection): (string|undefined)} * ol.proj.Projection): (string|undefined)}
@@ -133,34 +115,6 @@ ol.TileUrlFunction.nullTileUrlFunction =
}; };
/**
* @param {ol.TileCoordTransformType} transformFn Transform function.
* @param {ol.TileUrlFunctionType} tileUrlFunction Tile URL function.
* @return {ol.TileUrlFunctionType} Tile URL function.
*/
ol.TileUrlFunction.withTileCoordTransform =
function(transformFn, tileUrlFunction) {
var tmpTileCoord = [0, 0, 0];
return (
/**
* @param {ol.TileCoord} tileCoord Tile Coordinate.
* @param {number} pixelRatio Pixel ratio.
* @param {ol.proj.Projection} projection Projection.
* @return {string|undefined} Tile URL.
*/
function(tileCoord, pixelRatio, projection) {
if (goog.isNull(tileCoord)) {
return undefined;
} else {
return tileUrlFunction(
transformFn(tileCoord, projection, tmpTileCoord),
pixelRatio,
projection);
}
});
};
/** /**
* @param {string} url URL. * @param {string} url URL.
* @return {Array.<string>} Array of urls. * @return {Array.<string>} Array of urls.
+4 -4
View File
@@ -99,8 +99,8 @@ describe('ol.source.WMTS', function() {
}); });
var projection = ol.proj.get('EPSG:3857'); var projection = ol.proj.get('EPSG:3857');
var url = source.tileUrlFunction.call(source, var url = source.tileUrlFunction(
[1, 1, -2], 1, projection); source.getTileCoordForTileUrlFunction([1, 1, -2]), 1, projection);
expect(url).to.be.eql('http://www.example.com/wmts/coastlines/' + expect(url).to.be.eql('http://www.example.com/wmts/coastlines/' +
'layer/default/EPSG:3857/1/1/1.jpg'); 'layer/default/EPSG:3857/1/1/1.jpg');
@@ -125,8 +125,8 @@ describe('ol.source.WMTS', function() {
}); });
var projection = ol.proj.get('EPSG:3857'); var projection = ol.proj.get('EPSG:3857');
var url = source.tileUrlFunction.call(source, var url = source.tileUrlFunction(
[1, 1, -2], 1, projection); source.getTileCoordForTileUrlFunction([1, 1, -2]), 1, projection);
expect(url).to.be.eql('http://www.example.com/wmts/coastlines/' + expect(url).to.be.eql('http://www.example.com/wmts/coastlines/' +
'layer/default/EPSG:3857/1/1/1.jpg'); 'layer/default/EPSG:3857/1/1/1.jpg');
+1 -1
View File
@@ -26,7 +26,7 @@ describe('ol.source.XYZ', function() {
tileGrid = xyzTileSource.getTileGrid(); tileGrid = xyzTileSource.getTileGrid();
}); });
it('return the expected URL', function() { it('returns the expected URL', function() {
var coordinate = [829330.2064098881, 5933916.615134273]; var coordinate = [829330.2064098881, 5933916.615134273];
var tileUrl; var tileUrl;
+21 -33
View File
@@ -47,7 +47,7 @@ describe('ol.TileCoord', function() {
}); });
}); });
describe('restrictByExtentAndZ', function() { describe('withinExtentAndZ', function() {
it('restricts by z', function() { it('restricts by z', function() {
var tileGrid = new ol.tilegrid.TileGrid({ var tileGrid = new ol.tilegrid.TileGrid({
@@ -56,12 +56,9 @@ describe('ol.TileCoord', function() {
resolutions: [2, 1], resolutions: [2, 1],
minZoom: 1 minZoom: 1
}); });
expect(ol.tilecoord.restrictByExtentAndZ([0, 0, 0], tileGrid)) expect(ol.tilecoord.withinExtentAndZ([0, 0, 0], tileGrid)).to.be(false);
.to.equal(null); expect(ol.tilecoord.withinExtentAndZ([1, 0, 0], tileGrid)).to.be(true);
expect(ol.tilecoord.restrictByExtentAndZ([1, 0, 0], tileGrid)) expect(ol.tilecoord.withinExtentAndZ([2, 0, 0], tileGrid)).to.be(false);
.to.eql([1, 0, 0]);
expect(ol.tilecoord.restrictByExtentAndZ([2, 0, 0], tileGrid))
.to.equal(null);
}); });
it('restricts by extent when extent defines tile ranges', function() { it('restricts by extent when extent defines tile ranges', function() {
@@ -71,12 +68,9 @@ describe('ol.TileCoord', function() {
tileSize: 10, tileSize: 10,
resolutions: [1] resolutions: [1]
}); });
expect(ol.tilecoord.restrictByExtentAndZ([0, 1, 1], tileGrid)) expect(ol.tilecoord.withinExtentAndZ([0, 1, 1], tileGrid)).to.be(true);
.to.eql([0, 1, 1]); expect(ol.tilecoord.withinExtentAndZ([0, 2, 0], tileGrid)).to.be(false);
expect(ol.tilecoord.restrictByExtentAndZ([0, 2, 0], tileGrid)) expect(ol.tilecoord.withinExtentAndZ([0, 0, 2], tileGrid)).to.be(false);
.to.equal(null);
expect(ol.tilecoord.restrictByExtentAndZ([0, 0, 2], tileGrid))
.to.equal(null);
}); });
it('restricts by extent when sizes define tile ranges', function() { it('restricts by extent when sizes define tile ranges', function() {
@@ -86,18 +80,12 @@ describe('ol.TileCoord', function() {
tileSize: 10, tileSize: 10,
resolutions: [1] resolutions: [1]
}); });
expect(ol.tilecoord.restrictByExtentAndZ([0, 0, 0], tileGrid)) expect(ol.tilecoord.withinExtentAndZ([0, 0, 0], tileGrid)).to.be(true);
.to.eql([0, 0, 0]); expect(ol.tilecoord.withinExtentAndZ([0, -1, 0], tileGrid)).to.be(false);
expect(ol.tilecoord.restrictByExtentAndZ([0, -1, 0], tileGrid)) expect(ol.tilecoord.withinExtentAndZ([0, 0, -1], tileGrid)).to.be(false);
.to.equal(null); expect(ol.tilecoord.withinExtentAndZ([0, 2, 2], tileGrid)).to.be(true);
expect(ol.tilecoord.restrictByExtentAndZ([0, 0, -1], tileGrid)) expect(ol.tilecoord.withinExtentAndZ([0, 3, 0], tileGrid)).to.be(false);
.to.equal(null); expect(ol.tilecoord.withinExtentAndZ([0, 0, 3], tileGrid)).to.be(false);
expect(ol.tilecoord.restrictByExtentAndZ([0, 2, 2], tileGrid))
.to.eql([0, 2, 2]);
expect(ol.tilecoord.restrictByExtentAndZ([0, 3, 0], tileGrid))
.to.equal(null);
expect(ol.tilecoord.restrictByExtentAndZ([0, 0, 3], tileGrid))
.to.equal(null);
}); });
it('does not restrict by extent with no extent or sizes', function() { it('does not restrict by extent with no extent or sizes', function() {
@@ -106,14 +94,14 @@ describe('ol.TileCoord', function() {
tileSize: 10, tileSize: 10,
resolutions: [1] resolutions: [1]
}); });
expect(ol.tilecoord.restrictByExtentAndZ([0, Infinity, 0], tileGrid)) expect(ol.tilecoord.withinExtentAndZ([0, Infinity, 0], tileGrid))
.to.eql([0, Infinity, 0]); .to.be(true);
expect(ol.tilecoord.restrictByExtentAndZ([0, 0, Infinity], tileGrid)) expect(ol.tilecoord.withinExtentAndZ([0, 0, Infinity], tileGrid))
.to.eql([0, 0, Infinity]); .to.be(true);
expect(ol.tilecoord.restrictByExtentAndZ([0, -Infinity, 0], tileGrid)) expect(ol.tilecoord.withinExtentAndZ([0, -Infinity, 0], tileGrid))
.to.eql([0, -Infinity, 0]); .to.be(true);
expect(ol.tilecoord.restrictByExtentAndZ([0, 0, Infinity], tileGrid)) expect(ol.tilecoord.withinExtentAndZ([0, 0, Infinity], tileGrid))
.to.eql([0, 0, Infinity]); .to.be(true);
}); });
}); });
+10 -10
View File
@@ -379,8 +379,8 @@ describe('ol.tilegrid.TileGrid', function() {
resolutions: [1, 0.5], resolutions: [1, 0.5],
tileSize: 10 tileSize: 10
}); });
var transformFn = var transformFn = goog.bind(
ol.tilegrid.createOriginTopLeftTileCoordTransform(tileGrid); ol.tilegrid.originTopLeftTileCoordTransform, tileGrid);
expect(transformFn([0, 0, -2])).to.eql([0, 0, 1]); expect(transformFn([0, 0, -2])).to.eql([0, 0, 1]);
expect(transformFn([0, 0, -1])).to.eql([0, 0, 0]); expect(transformFn([0, 0, -1])).to.eql([0, 0, 0]);
expect(transformFn([1, 0, -4])).to.eql([1, 0, 3]); expect(transformFn([1, 0, -4])).to.eql([1, 0, 3]);
@@ -398,10 +398,10 @@ describe('ol.tilegrid.TileGrid', function() {
resolutions: [1, 0.5], resolutions: [1, 0.5],
tileSize: 10 tileSize: 10
}); });
var transformFn1 = var transformFn1 = goog.bind(
ol.tilegrid.createOriginTopLeftTileCoordTransform(tileGrid); ol.tilegrid.originTopLeftTileCoordTransform, tileGrid);
var transformFn2 = var transformFn2 = goog.bind(
ol.tilegrid.createOriginTopLeftTileCoordTransform(tileGrid1); ol.tilegrid.originTopLeftTileCoordTransform, tileGrid1);
expect(transformFn1([0, 0, -2])).to.eql([0, 0, 1]); expect(transformFn1([0, 0, -2])).to.eql([0, 0, 1]);
expect(transformFn2([0, 0, -2])).to.eql([0, 0, 1]); expect(transformFn2([0, 0, -2])).to.eql([0, 0, 1]);
expect(transformFn1([0, 0, -1])).to.eql([0, 0, 0]); expect(transformFn1([0, 0, -1])).to.eql([0, 0, 0]);
@@ -424,10 +424,10 @@ describe('ol.tilegrid.TileGrid', function() {
resolutions: [1, 0.5], resolutions: [1, 0.5],
tileSize: 10 tileSize: 10
}); });
var transformFn1 = var transformFn1 = goog.bind(
ol.tilegrid.createOriginTopLeftTileCoordTransform(tileGrid1); ol.tilegrid.originTopLeftTileCoordTransform, tileGrid1);
var transformFn2 = var transformFn2 = goog.bind(
ol.tilegrid.createOriginTopLeftTileCoordTransform(tileGrid2); ol.tilegrid.originTopLeftTileCoordTransform, tileGrid2);
expect(tileGrid1.getFullTileRange(0).getHeight()).to.equal(2); expect(tileGrid1.getFullTileRange(0).getHeight()).to.equal(2);
expect(transformFn1([0, 0, 0])).to.eql([0, 0, 1]); expect(transformFn1([0, 0, 0])).to.eql([0, 0, 1]);
expect(transformFn2([0, 0, 0])).to.eql([0, 0, 1]); expect(transformFn2([0, 0, 0])).to.eql([0, 0, 1]);
-12
View File
@@ -67,18 +67,6 @@ describe('ol.TileUrlFunction', function() {
}); });
}); });
describe('withTileCoordTransform', function() {
it('creates expected URL', function() {
var tileUrl = ol.TileUrlFunction.withTileCoordTransform(
function(tileCoord) {
return [tileCoord[0], tileCoord[1], -tileCoord[2]];
},
ol.TileUrlFunction.createFromTemplate('{z}/{x}/{y}'));
expect(tileUrl([3, 2, -1])).to.eql('3/2/1');
expect(tileUrl(null)).to.be(undefined);
});
});
describe('createFromTileUrlFunctions', function() { describe('createFromTileUrlFunctions', function() {
it('creates expected URL', function() { it('creates expected URL', function() {
var tileUrl = ol.TileUrlFunction.createFromTileUrlFunctions([ var tileUrl = ol.TileUrlFunction.createFromTileUrlFunctions([