Allow extents to restrict tile ranges requested from the server

The addition of full extent tile ranges also allows us to simplify wrapX
handling for tile layers. By limiting wrapX to true and false as possible
values, we can remove a lot of guessing logic.
This commit is contained in:
Andreas Hocevar
2015-04-28 23:14:08 +02:00
parent 700903ca5c
commit a116878a57
17 changed files with 535 additions and 199 deletions

View File

@@ -115,22 +115,7 @@ describe('ol.source.Tile', function() {
});
describe('#getWrapXTileCoord()', function() {
it('returns the expected tile coordinate - {wrapX: undefined}', function() {
var tileSource = new ol.source.Tile({
projection: 'EPSG:3857'
});
var tileCoord = tileSource.getWrapXTileCoord([6, -31, 22]);
expect(tileCoord).to.eql([6, -31, 22]);
tileCoord = tileSource.getWrapXTileCoord([6, 33, 22]);
expect(tileCoord).to.eql([6, 33, 22]);
tileCoord = tileSource.getWrapXTileCoord([6, 97, 22]);
expect(tileCoord).to.eql([6, 97, 22]);
});
describe('#getTileCoordForTileUrlFunction()', function() {
it('returns the expected tile coordinate - {wrapX: true}', function() {
var tileSource = new ol.source.Tile({
@@ -138,13 +123,13 @@ describe('ol.source.Tile', function() {
wrapX: true
});
var tileCoord = tileSource.getWrapXTileCoord([6, -31, 22]);
var tileCoord = tileSource.getTileCoordForTileUrlFunction([6, -31, 22]);
expect(tileCoord).to.eql([6, 33, 22]);
tileCoord = tileSource.getWrapXTileCoord([6, 33, 22]);
tileCoord = tileSource.getTileCoordForTileUrlFunction([6, 33, 22]);
expect(tileCoord).to.eql([6, 33, 22]);
tileCoord = tileSource.getWrapXTileCoord([6, 97, 22]);
tileCoord = tileSource.getTileCoordForTileUrlFunction([6, 97, 22]);
expect(tileCoord).to.eql([6, 33, 22]);
});
@@ -154,13 +139,13 @@ describe('ol.source.Tile', function() {
wrapX: false
});
var tileCoord = tileSource.getWrapXTileCoord([6, -31, 22]);
var tileCoord = tileSource.getTileCoordForTileUrlFunction([6, -31, 22]);
expect(tileCoord).to.eql(null);
tileCoord = tileSource.getWrapXTileCoord([6, 33, 22]);
tileCoord = tileSource.getTileCoordForTileUrlFunction([6, 33, 22]);
expect(tileCoord).to.eql([6, 33, 22]);
tileCoord = tileSource.getWrapXTileCoord([6, 97, 22]);
tileCoord = tileSource.getTileCoordForTileUrlFunction([6, 97, 22]);
expect(tileCoord).to.eql(null);
});
});

View File

@@ -66,15 +66,18 @@ describe('ol.source.XYZ', function() {
it('returns the expected URL', function() {
var projection = xyzTileSource.getProjection();
var tileUrl = xyzTileSource.tileUrlFunction(
xyzTileSource.getWrapXTileCoord([6, -31, -23], projection));
xyzTileSource.getTileCoordForTileUrlFunction(
[6, -31, 41], projection));
expect(tileUrl).to.eql('6/33/22');
tileUrl = xyzTileSource.tileUrlFunction(
xyzTileSource.getWrapXTileCoord([6, 33, -23], projection));
xyzTileSource.getTileCoordForTileUrlFunction(
[6, 33, 41], projection));
expect(tileUrl).to.eql('6/33/22');
tileUrl = xyzTileSource.tileUrlFunction(
xyzTileSource.getWrapXTileCoord([6, 97, -23], projection));
xyzTileSource.getTileCoordForTileUrlFunction(
[6, 97, 41], projection));
expect(tileUrl).to.eql('6/33/22');
});
@@ -83,14 +86,20 @@ describe('ol.source.XYZ', function() {
describe('crop y', function() {
it('returns the expected URL', function() {
var projection = xyzTileSource.getProjection();
var tileUrl = xyzTileSource.tileUrlFunction(
[6, 33, -87]);
xyzTileSource.getTileCoordForTileUrlFunction(
[6, 33, 150], projection));
expect(tileUrl).to.be(undefined);
tileUrl = xyzTileSource.tileUrlFunction([6, 33, -23]);
tileUrl = xyzTileSource.tileUrlFunction(
xyzTileSource.getTileCoordForTileUrlFunction(
[6, 33, 41], projection));
expect(tileUrl).to.eql('6/33/22');
tileUrl = xyzTileSource.tileUrlFunction([6, 33, 41]);
tileUrl = xyzTileSource.tileUrlFunction(
xyzTileSource.getTileCoordForTileUrlFunction(
[6, 33, -23], projection));
expect(tileUrl).to.be(undefined);
});

View File

@@ -46,7 +46,79 @@ describe('ol.TileCoord', function() {
ol.tilecoord.hash(tileCoord2));
});
});
describe('restrictByExtentAndZ', function() {
it('restricts by z', function() {
var tileGrid = new ol.tilegrid.TileGrid({
extent: [10, 20, 30, 40],
tileSize: 10,
resolutions: [2, 1],
minZoom: 1
});
expect(ol.tilecoord.restrictByExtentAndZ([0, 0, 0], tileGrid))
.to.equal(null);
expect(ol.tilecoord.restrictByExtentAndZ([1, 0, 0], tileGrid))
.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() {
var tileGrid = new ol.tilegrid.TileGrid({
extent: [10, 20, 30, 40],
sizes: [[3, 3]],
tileSize: 10,
resolutions: [1]
});
expect(ol.tilecoord.restrictByExtentAndZ([0, 1, 1], tileGrid))
.to.eql([0, 1, 1]);
expect(ol.tilecoord.restrictByExtentAndZ([0, 2, 0], tileGrid))
.to.equal(null);
expect(ol.tilecoord.restrictByExtentAndZ([0, 0, 2], tileGrid))
.to.equal(null);
});
it('restricts by extent when sizes define tile ranges', function() {
var tileGrid = new ol.tilegrid.TileGrid({
origin: [10, 20],
sizes: [[3, 3]],
tileSize: 10,
resolutions: [1]
});
expect(ol.tilecoord.restrictByExtentAndZ([0, 0, 0], tileGrid))
.to.eql([0, 0, 0]);
expect(ol.tilecoord.restrictByExtentAndZ([0, -1, 0], tileGrid))
.to.equal(null);
expect(ol.tilecoord.restrictByExtentAndZ([0, 0, -1], tileGrid))
.to.equal(null);
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() {
var tileGrid = new ol.tilegrid.TileGrid({
origin: [10, 20],
tileSize: 10,
resolutions: [1]
});
expect(ol.tilecoord.restrictByExtentAndZ([0, Infinity, 0], tileGrid))
.to.eql([0, Infinity, 0]);
expect(ol.tilecoord.restrictByExtentAndZ([0, 0, Infinity], tileGrid))
.to.eql([0, 0, Infinity]);
expect(ol.tilecoord.restrictByExtentAndZ([0, -Infinity, 0], tileGrid))
.to.eql([0, -Infinity, 0]);
expect(ol.tilecoord.restrictByExtentAndZ([0, 0, Infinity], tileGrid))
.to.eql([0, 0, Infinity]);
});
});
});
goog.require('ol.TileCoord');
goog.require('ol.tilecoord');
goog.require('ol.tilegrid.TileGrid');

View File

@@ -150,6 +150,129 @@ describe('ol.tilegrid.TileGrid', function() {
});
});
describe('create with extent exceeding tile ranges', function() {
it('throws an exception', function() {
expect(function() {
return new ol.tilegrid.TileGrid({
extent: [10, 20, 30, 40],
sizes: [[1, 1]],
tileSize: 10,
resolutions: [1]
});
}).to.throwException();
expect(function() {
return new ol.tilegrid.TileGrid({
extent: [10, 20, 30, 40],
origin: [10, 40], // top-left origin
sizes: [[3, 3]], // would have to be [[3, -3]] for this to not throw
tileSize: 10,
resolutions: [1]
});
}).to.throwException();
});
});
describe('create with origin', function() {
var tileGrid;
beforeEach(function() {
tileGrid = new ol.tilegrid.TileGrid({
origin: [10, 20],
tileSize: 10,
resolutions: [1]
});
});
it('returns the configured origin', function() {
expect(tileGrid.getOrigin()).to.eql([10, 20]);
});
it('returns null for an unknown extent', function() {
expect(tileGrid.getExtent()).to.equal(null);
});
it('returns null for an unknown full tile range', function() {
expect(tileGrid.getFullTileRange(0)).to.equal(null);
});
});
describe('create with extent', function() {
var tileGrid;
beforeEach(function() {
tileGrid = new ol.tilegrid.TileGrid({
extent: [10, 20, 30, 40],
tileSize: 10,
resolutions: [1]
});
});
it('assumes bottom left corner of extent as origin', function() {
expect(tileGrid.getOrigin()).to.eql([10, 20]);
});
it('calculates full tile ranges from extent', function() {
var fullTileRange = tileGrid.getFullTileRange(0);
expect(fullTileRange.minX).to.equal(0);
expect(fullTileRange.maxX).to.equal(1);
expect(fullTileRange.minY).to.equal(0);
expect(fullTileRange.maxY).to.equal(1);
});
});
describe('create with extent and sizes', function() {
var tileGrid;
beforeEach(function() {
tileGrid = new ol.tilegrid.TileGrid({
extent: [10, 20, 30, 40],
sizes: [[3, 3]],
tileSize: 10,
resolutions: [1]
});
});
it('returns the configured extent', function() {
expect(tileGrid.getExtent()).to.eql([10, 20, 30, 40]);
});
it('calculates full tile ranges from sizes', function() {
var fullTileRange = tileGrid.getFullTileRange(0);
expect(fullTileRange.minX).to.equal(0);
expect(fullTileRange.maxX).to.equal(2);
expect(fullTileRange.minY).to.equal(0);
expect(fullTileRange.maxY).to.equal(2);
});
});
describe('create with top-left origin and sizes', function() {
var tileGrid;
beforeEach(function() {
tileGrid = new ol.tilegrid.TileGrid({
origin: [10, 40],
sizes: [[3, -3]],
tileSize: 10,
resolutions: [1]
});
});
it('calculates correct minX and maxX for negative heights', function() {
var fullTileRange = tileGrid.getFullTileRange(0);
expect(fullTileRange.minY).to.equal(-3);
expect(fullTileRange.maxY).to.equal(-1);
});
});
describe('create with extent and origin', function() {
it('uses both origin and extent', function() {
var tileGrid = new ol.tilegrid.TileGrid({
origin: [0, 0],
extent: [10, 20, 30, 40],
tileSize: 10,
resolutions: [1]
});
expect(tileGrid.getOrigin()).to.eql([0, 0]);
expect(tileGrid.getExtent()).to.eql([10, 20, 30, 40]);
});
});
describe('createForExtent', function() {
it('allows creation of tile grid from extent', function() {
var extent = ol.extent.createOrUpdate(-100, -100, 100, 100);
@@ -247,6 +370,78 @@ describe('ol.tilegrid.TileGrid', function() {
});
describe('createOriginTopLeftTileCoordTransform', function() {
it('transforms y to -y-1 for top-left origins', function() {
var tileGrid = new ol.tilegrid.TileGrid({
origin: [10, 40],
sizes: [[2, -2], [4, -4]],
resolutions: [1, 0.5],
tileSize: 10
});
var transformFn =
ol.tilegrid.createOriginTopLeftTileCoordTransform(tileGrid);
expect(transformFn([0, 0, -2])).to.eql([0, 0, 1]);
expect(transformFn([0, 0, -1])).to.eql([0, 0, 0]);
expect(transformFn([1, 0, -4])).to.eql([1, 0, 3]);
expect(transformFn([1, 0, -1])).to.eql([1, 0, 0]);
});
it('transforms y to -y-1 when origin corner is not specified', function() {
var tileGrid1 = new ol.tilegrid.TileGrid({
origin: [10, 20],
resolutions: [1, 0.5],
tileSize: 10
});
var tileGrid = new ol.tilegrid.TileGrid({
origin: [10, 40],
resolutions: [1, 0.5],
tileSize: 10
});
var transformFn1 =
ol.tilegrid.createOriginTopLeftTileCoordTransform(tileGrid);
var transformFn2 =
ol.tilegrid.createOriginTopLeftTileCoordTransform(tileGrid1);
expect(transformFn1([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(transformFn2([0, 0, -1])).to.eql([0, 0, 0]);
expect(transformFn1([1, 0, -4])).to.eql([1, 0, 3]);
expect(transformFn2([1, 0, -4])).to.eql([1, 0, 3]);
expect(transformFn1([1, 0, -1])).to.eql([1, 0, 0]);
expect(transformFn2([1, 0, -1])).to.eql([1, 0, 0]);
});
it('transforms y to height-y-1 for bottom-left origins', function() {
var tileGrid1 = new ol.tilegrid.TileGrid({
extent: [10, 20, 30, 40],
resolutions: [1, 0.5],
tileSize: 10
});
var tileGrid2 = new ol.tilegrid.TileGrid({
origin: [10, 20],
sizes: [[2, 2], [4, 4]],
resolutions: [1, 0.5],
tileSize: 10
});
var transformFn1 =
ol.tilegrid.createOriginTopLeftTileCoordTransform(tileGrid1);
var transformFn2 =
ol.tilegrid.createOriginTopLeftTileCoordTransform(tileGrid2);
expect(tileGrid1.getFullTileRange(0).getHeight()).to.equal(2);
expect(transformFn1([0, 0, 0])).to.eql([0, 0, 1]);
expect(transformFn2([0, 0, 0])).to.eql([0, 0, 1]);
expect(transformFn1([0, 0, 1])).to.eql([0, 0, 0]);
expect(transformFn2([0, 0, 1])).to.eql([0, 0, 0]);
expect(tileGrid1.getFullTileRange(1).getHeight()).to.equal(4);
expect(transformFn1([1, 0, 0])).to.eql([1, 0, 3]);
expect(transformFn2([1, 0, 0])).to.eql([1, 0, 3]);
expect(transformFn1([1, 0, 3])).to.eql([1, 0, 0]);
expect(transformFn2([1, 0, 3])).to.eql([1, 0, 0]);
});
});
describe('getForProjection', function() {
it('gets the default tile grid for a projection', function() {
@@ -839,7 +1034,7 @@ describe('ol.tilegrid.TileGrid', function() {
});
});
describe('getZForResolution (approcimate)', function() {
describe('getZForResolution (approximate)', function() {
it('returns the expected z value', function() {
var tileGrid = new ol.tilegrid.TileGrid({
resolutions: resolutions,
@@ -874,4 +1069,5 @@ goog.require('ol.proj');
goog.require('ol.proj.EPSG3857');
goog.require('ol.proj.Projection');
goog.require('ol.proj.Units');
goog.require('ol.TileRange');
goog.require('ol.tilegrid.TileGrid');

View File

@@ -42,27 +42,17 @@ describe('ol.tilegrid.WMTS', function() {
expect(tileGrid.origins_).to.be.an('array');
expect(tileGrid.origins_).to.have.length(20);
expect(tileGrid.origins_).to.eql(
[[-20037508.3428, 20037508.3428], [-20037508.3428, 20037508.3428],
[-20037508.3428, 20037508.3428], [-20037508.3428, 20037508.3428],
[-20037508.3428, 20037508.3428], [-20037508.3428, 20037508.3428],
[-20037508.3428, 20037508.3428], [-20037508.3428, 20037508.3428],
[-20037508.3428, 20037508.3428], [-20037508.3428, 20037508.3428],
[-20037508.3428, 20037508.3428], [-20037508.3428, 20037508.3428],
[-20037508.3428, 20037508.3428], [-20037508.3428, 20037508.3428],
[-20037508.3428, 20037508.3428], [-20037508.3428, 20037508.3428],
[-20037508.3428, 20037508.3428], [-20037508.3428, 20037508.3428],
[-20037508.3428, 20037508.3428], [-20037508.3428, 20037508.3428]
]);
goog.array.repeat([-20037508.3428, 20037508.3428], 20));
expect(tileGrid.tileSizes_).to.be.an('array');
expect(tileGrid.tileSizes_).to.have.length(20);
expect(tileGrid.tileSizes_).to.eql(
[256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
256, 256, 256, 256, 256, 256, 256, 256, 256, 256]);
goog.array.repeat(256, 20));
});
});
});
goog.require('goog.array');
goog.require('ol.format.WMTSCapabilities');
goog.require('ol.tilegrid.WMTS');