Calculate tile grid extent from extent of bottom-level tile matrix

Prefers extent derived from the tile matrix set in the capabilities
over default projection extent.
This commit is contained in:
Mateusz Łoskot
2019-01-21 15:21:39 +01:00
parent 8f46bb563b
commit 98e8bec370
4 changed files with 77 additions and 20 deletions

View File

@@ -4,9 +4,8 @@
import {expandUrl, createFromTileUrlFunctions, nullTileUrlFunction} from '../tileurlfunction.js'; import {expandUrl, createFromTileUrlFunctions, nullTileUrlFunction} from '../tileurlfunction.js';
import {find, findIndex, includes} from '../array.js'; import {find, findIndex, includes} from '../array.js';
import {containsExtent} from '../extent.js';
import {assign} from '../obj.js'; import {assign} from '../obj.js';
import {get as getProjection, equivalent, transformExtent} from '../proj.js'; import {get as getProjection, equivalent} from '../proj.js';
import TileImage from './TileImage.js'; import TileImage from './TileImage.js';
import WMTSRequestEncoding from './WMTSRequestEncoding.js'; import WMTSRequestEncoding from './WMTSRequestEncoding.js';
import {createFromCapabilitiesMatrixSet} from '../tilegrid/WMTS.js'; import {createFromCapabilitiesMatrixSet} from '../tilegrid/WMTS.js';
@@ -377,22 +376,25 @@ export function optionsFromCapabilities(wmtsCap, config) {
} }
} }
const wgs84BoundingBox = l['WGS84BoundingBox']; const wrapX = false;
let extent, wrapX;
if (wgs84BoundingBox !== undefined) { const matrix0 = matrixSetObj.TileMatrix[0];
const wgs84ProjectionExtent = getProjection('EPSG:4326').getExtent(); const resolution = matrix0.ScaleDenominator * 0.00028; // WMTS 1.0.0: standardized rendering pixel size
wrapX = (wgs84BoundingBox[0] == wgs84ProjectionExtent[0] && const origin = projection === getProjection('EPSG:4326')
wgs84BoundingBox[2] == wgs84ProjectionExtent[2]); ? [matrix0.TopLeftCorner[1], matrix0.TopLeftCorner[0]]
extent = transformExtent( : matrix0.TopLeftCorner;
wgs84BoundingBox, 'EPSG:4326', projection); const tileSpanX = matrix0.TileWidth * resolution;
const projectionExtent = projection.getExtent(); const tileSpanY = matrix0.TileHeight * resolution;
if (projectionExtent) {
// If possible, do a sanity check on the extent - it should never be const extent = [
// bigger than the validity extent of the projection of a matrix set. origin[0],
if (!containsExtent(projectionExtent, extent)) { origin[1] - tileSpanY * matrix0.MatrixHeight,
extent = undefined; origin[0] + tileSpanX * matrix0.MatrixWidth,
} origin[1]
} ];
if (projection.getExtent() === null) {
projection.setExtent(extent);
} }
const tileGrid = createFromCapabilitiesMatrixSet(matrixSetObj, extent, matrixLimits); const tileGrid = createFromCapabilitiesMatrixSet(matrixSetObj, extent, matrixLimits);

View File

@@ -92,6 +92,9 @@ access interface to some TileMatrixSets</ows:Abstract>
<TileMatrixSetLink> <TileMatrixSetLink>
<TileMatrixSet>google3857</TileMatrixSet> <TileMatrixSet>google3857</TileMatrixSet>
</TileMatrixSetLink> </TileMatrixSetLink>
<TileMatrixSetLink>
<TileMatrixSet>google3857subset</TileMatrixSet>
</TileMatrixSetLink>
<ResourceURL format="image/png" resourceType="tile" template="http://www.example.com/wmts/coastlines/{TileMatrix}/{TileRow}/{TileCol}.png"/> <ResourceURL format="image/png" resourceType="tile" template="http://www.example.com/wmts/coastlines/{TileMatrix}/{TileRow}/{TileCol}.png"/>
<ResourceURL format="application/gml+xml; version=3.1" resourceType="FeatureInfo" template="http://www.example.com/wmts/coastlines/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}/{J}/{I}.xml"/> <ResourceURL format="application/gml+xml; version=3.1" resourceType="FeatureInfo" template="http://www.example.com/wmts/coastlines/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}/{J}/{I}.xml"/>
<Dimension> <Dimension>
@@ -372,6 +375,29 @@ access interface to some TileMatrixSets</ows:Abstract>
<MatrixHeight>7000</MatrixHeight> <MatrixHeight>7000</MatrixHeight>
</TileMatrix> </TileMatrix>
</TileMatrixSet> </TileMatrixSet>
</Contents> <TileMatrixSet>
<!-- A custom tile matrix set based on google3857 with tiles at each level covering only part of projection space (extent) -->
<ows:Identifier>google3857subset</ows:Identifier>
<ows:SupportedCRS>urn:ogc:def:crs:EPSG:6.18:3:3857</ows:SupportedCRS>
<TileMatrix>
<ows:Identifier>18</ows:Identifier>
<ScaleDenominator>2132.72958385</ScaleDenominator>
<TopLeftCorner>-10000000 10000000</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>1</MatrixWidth>
<MatrixHeight>1</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>18</ows:Identifier>
<ScaleDenominator>1066.36479193</ScaleDenominator>
<TopLeftCorner>-10000000 10000000</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>2</MatrixWidth>
<MatrixHeight>2</MatrixHeight>
</TileMatrix>
</TileMatrixSet>
</Contents>
<ServiceMetadataURL xlink:href="http://www.maps.bob/wmts/1.0.0/WMTSCapabilities.xml"/> <ServiceMetadataURL xlink:href="http://www.maps.bob/wmts/1.0.0/WMTSCapabilities.xml"/>
</Capabilities> </Capabilities>

View File

@@ -54,11 +54,13 @@ describe('ol.format.WMTSCapabilities', function() {
expect(layer.Style[0].LegendURL[0].format).to.be.eql('image/png'); expect(layer.Style[0].LegendURL[0].format).to.be.eql('image/png');
expect(layer.TileMatrixSetLink).to.be.an('array'); expect(layer.TileMatrixSetLink).to.be.an('array');
expect(layer.TileMatrixSetLink).to.have.length(2); expect(layer.TileMatrixSetLink).to.have.length(3);
expect(layer.TileMatrixSetLink[0].TileMatrixSet).to.be expect(layer.TileMatrixSetLink[0].TileMatrixSet).to.be
.eql('BigWorldPixel'); .eql('BigWorldPixel');
expect(layer.TileMatrixSetLink[1].TileMatrixSet).to.be expect(layer.TileMatrixSetLink[1].TileMatrixSet).to.be
.eql('google3857'); .eql('google3857');
expect(layer.TileMatrixSetLink[2].TileMatrixSet).to.be
.eql('google3857subset');
const wgs84Bbox = layer.WGS84BoundingBox; const wgs84Bbox = layer.WGS84BoundingBox;
expect(wgs84Bbox).to.be.an('array'); expect(wgs84Bbox).to.be.an('array');

View File

@@ -1,4 +1,5 @@
import WMTSCapabilities from '../../../../src/ol/format/WMTSCapabilities.js'; import WMTSCapabilities from '../../../../src/ol/format/WMTSCapabilities.js';
import {getBottomLeft, getTopRight} from '../../../../src/ol/extent.js';
import {get as getProjection} from '../../../../src/ol/proj.js'; import {get as getProjection} from '../../../../src/ol/proj.js';
import Projection from '../../../../src/ol/proj/Projection.js'; import Projection from '../../../../src/ol/proj/Projection.js';
import WMTSTileGrid from '../../../../src/ol/tilegrid/WMTS.js'; import WMTSTileGrid from '../../../../src/ol/tilegrid/WMTS.js';
@@ -149,6 +150,32 @@ describe('ol.source.WMTS', function() {
expect(options.projection.getCode()).to.be.eql('urn:ogc:def:crs:OGC:1.3:CRS84'); expect(options.projection.getCode()).to.be.eql('urn:ogc:def:crs:OGC:1.3:CRS84');
}); });
it('uses extent of tile matrix instead of projection extent', function() {
const options = optionsFromCapabilities(capabilities,
{layer: 'BlueMarbleNextGeneration', matrixSet: 'google3857subset'});
// Since google3857subset defines subset of space defined by the google3857 matrix set:
// - top left corner: -10000000, 10000000
// - calculated grid extent: [-10000000, 9999694.25188686, -9999694.25188686, 10000000]
// then the tile grid extent is only a part of the full projection extent.
const gridExtent = options.tileGrid.getExtent();
const gridBottomLeft = getBottomLeft(gridExtent);
const gridTopRight = getTopRight(gridExtent);
expect(Math.round(gridBottomLeft[0])).to.be.eql(-10000000);
expect(Math.round(gridBottomLeft[1])).to.be.eql(9999847);
expect(Math.round(gridTopRight[0])).to.be.eql(-9999847);
expect(Math.round(gridTopRight[1])).to.be.eql(10000000);
const projExtent = options.projection.getExtent();
const projBottomLeft = getBottomLeft(projExtent);
const projTopRight = getTopRight(projExtent);
expect(Math.round(projBottomLeft[0])).to.be.eql(-20037508);
expect(Math.round(projBottomLeft[1])).to.be.eql(-20037508);
expect(Math.round(projTopRight[0])).to.be.eql(20037508);
expect(Math.round(projTopRight[1])).to.be.eql(20037508);
});
it('doesn\'t fail if the GetCap doesn\'t contains Constraint tags', function() { it('doesn\'t fail if the GetCap doesn\'t contains Constraint tags', function() {
const tmpXml = content.replace(/<ows:Constraint[\s\S]*?<\/ows:Constraint>/g, ''); const tmpXml = content.replace(/<ows:Constraint[\s\S]*?<\/ows:Constraint>/g, '');
const tmpCapabilities = parser.read(tmpXml); const tmpCapabilities = parser.read(tmpXml);