Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(lambda-tiler): ensure wmts limits extent to the bounding box of the tile matrix extent BM-1012 #3235

Merged
merged 5 commits into from
Apr 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 83 additions & 2 deletions packages/lambda-tiler/src/__tests__/wmts.capability.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,86 @@ describe('WmtsCapabilities', () => {
);
});

it('should limit a bounding box to the tileMatrix extent WebMercatorQuad', () => {
const wmts = new WmtsCapabilities({ httpBase: 'https://basemaps.test', apiKey });

const bigImagery = new Map();
bigImagery.set(Imagery3857.id, {
...Imagery3857,
bounds: {
// These bounds are slightly outside the extent bounds of 3857 (approx 0.3m offset)
// expected bounds: {x: -20037508.34 y:-20037508.34, width: 40075016.6855784 , height: 40075016.6855784 }
x: -20037508.6276,
y: -20037508.6276,
width: 40075016.9626,
height: 40075014.197799996,
},
});

wmts.fromParams({
provider: Provider,
tileMatrix: [GoogleTms],
tileSet: TileSetAerial,
imagery: bigImagery,
formats: ['png'],
});
const raw = wmts.toVNode();

const wgs84 = raw.find('Contents', 'Layer', 'ows:WGS84BoundingBox');
const epsg3857 = raw.find('Contents', 'Layer', 'ows:BoundingBox');

assert.equal(
epsg3857?.find('ows:LowerCorner')?.toString(),
`<ows:LowerCorner>-20037508.3428 -20037508.3428</ows:LowerCorner>`,
);
assert.equal(
epsg3857?.find('ows:UpperCorner')?.toString(),
`<ows:UpperCorner>20037508.3428 20037508.3428</ows:UpperCorner>`,
);

assert.equal(wgs84?.find('ows:LowerCorner')?.toString(), '<ows:LowerCorner>-180 -85.051129</ows:LowerCorner>');
assert.equal(wgs84?.find('ows:UpperCorner')?.toString(), '<ows:UpperCorner>180 85.051129</ows:UpperCorner>');
});

it('should limit a bounding box to the tileMatrix extent NZTM2000Quad', () => {
const wmts = new WmtsCapabilities({ httpBase: 'https://basemaps.test', apiKey });
const bigImagery = new Map();

bigImagery.set(Imagery2193.id, {
...Imagery2193,
bounds: {
// These bounds are slightly outside the extent bounds of NZTM2000Quad (approx 0.3m offset)
x: -3260586.9214,
y: 419435.7552,
width: 10018754.086099999,
height: 10018754.086099999,
},
});

wmts.fromParams({
provider: Provider,
tileMatrix: [Nztm2000QuadTms],
tileSet: TileSetAerial,
imagery: bigImagery,
formats: ['png'],
});
const raw = wmts.toVNode();

const wgs84 = raw.find('Contents', 'Layer', 'ows:WGS84BoundingBox');
const crsBounds = raw.find('Contents', 'Layer', 'ows:BoundingBox');
assert.equal(
crsBounds?.find('ows:LowerCorner')?.toString(),
`<ows:LowerCorner>419435.9938 -3260586.7284</ows:LowerCorner>`,
);
assert.equal(
crsBounds?.find('ows:UpperCorner')?.toString(),
`<ows:UpperCorner>10438190.1652 6758167.443</ows:UpperCorner>`,
);

assert.equal(wgs84?.find('ows:LowerCorner')?.toString(), '<ows:LowerCorner>-180 -49.929855</ows:LowerCorner>');
assert.equal(wgs84?.find('ows:UpperCorner')?.toString(), '<ows:UpperCorner>180 2.938603</ows:UpperCorner>');
});

it('should include output the correct TileMatrix', () => {
const wmts = new WmtsCapabilities({
httpBase: 'https://basemaps.test',
Expand Down Expand Up @@ -512,11 +592,12 @@ describe('WmtsCapabilities', () => {
.split('\n')
.map((c) => c.trim()),
);

assert.deepEqual(boundingBox[0][1], '<ows:LowerCorner>-180 -85.0511</ows:LowerCorner>');
assert.equal(boundingBox[0][2], '<ows:UpperCorner>180 0</ows:UpperCorner>');
assert.equal(boundingBox[0][2], '<ows:UpperCorner>180 85.0511</ows:UpperCorner>');

assert.deepEqual(boundingBox[1][1], '<ows:LowerCorner>-180 -85.0511</ows:LowerCorner>');
assert.equal(boundingBox[1][2], '<ows:UpperCorner>180 0</ows:UpperCorner>');
assert.equal(boundingBox[1][2], '<ows:UpperCorner>180 85.0511</ows:UpperCorner>');
});

it('should work with NZTM2000Quad', () => {
Expand Down
23 changes: 17 additions & 6 deletions packages/lambda-tiler/src/wmts.capability.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,18 +94,25 @@ export class WmtsBuilder {
}

buildWgs84BoundingBox(tms: TileMatrixSet, layers: Bounds[]): VNodeElement {
let bbox: BBox;
let bbox: BBox | null = null;

if (layers.length > 0) {
let bounds = layers[0];
for (let i = 1; i < layers.length; i++) {
bounds = bounds.union(layers[i]);
}
bbox = wgs84Extent(tms, bounds.toJson());
} else {
// No layers provided assume extent is the size of the tile matrix set :shrug: ?
bbox = wgs84Extent(tms, tms.extent);

// If imagery is outside of the bounds of the tileMatrix, fall back to the tileMatrix extent for the bounds
if (!tms.extent.containsBounds(bounds)) {
bbox = wgs84Extent(tms, tms.extent);
} else {
bbox = wgs84Extent(tms, bounds);
}
}

// No layers provided assume extent is the size of the tile matrix set :shrug: ?
if (bbox == null) bbox = wgs84Extent(tms, tms.extent);

// If east is less than west, then this has crossed the anti meridian, so cover the entire globe
if (bbox[2] < bbox[0]) {
bbox[0] = -180;
Expand All @@ -120,7 +127,7 @@ export class WmtsBuilder {

/** Combine all the bounds of the imagery inside the layers into a extent for the imagery set */
buildBoundingBoxFromImagery(tms: TileMatrixSet, layers: ConfigLayer[]): VNodeElement | null {
let bounds;
let bounds: Bounds | null = null;
for (const layer of layers) {
const imgId = layer[tms.projection.code];
if (imgId == null) continue;
Expand All @@ -131,7 +138,11 @@ export class WmtsBuilder {
}
if (bounds == null) return null;

// If imagery is outside of the bounds of the tileMatrix, fall back to the tileMatrix extent for the bounds
if (!tms.extent.containsBounds(bounds)) bounds = tms.extent;

const bbox = bounds.toBbox();

return V('ows:BoundingBox', { crs: tms.projection.toUrn() }, [
V('ows:LowerCorner', formatBbox(bbox[tms.indexX], bbox[tms.indexY], MeterPrecision)),
V('ows:UpperCorner', formatBbox(bbox[tms.indexX + 2], bbox[tms.indexY + 2], MeterPrecision)),
Expand Down
14 changes: 13 additions & 1 deletion packages/smoke/src/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,19 @@ async function req(path: string, opts?: RequestInit): Promise<Response> {
const res = await fetch(target, opts);

// eslint-disable-next-line no-console
console.log({ url: target.href, status: res.status, ...opts, duration: performance.now() - startTime }, 'Fetch:Done');
console.log(
// Create a fake log line approximating the pino log format
JSON.stringify({
pid: 0,
time: new Date().toISOString(),
level: 30,
msg: 'Fetch:Done',
url: target.href,
status: res.status,
...opts,
duration: performance.now() - startTime,
}),
);
return res;
}

Expand Down
14 changes: 12 additions & 2 deletions packages/smoke/src/wmts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,23 @@ test(`GET /v1/tiles/aerial/WebMercatorQuad/WMTSCapabilities.xml`, async () => {

assert.ok(
xml.includes(
`<ows:BoundingBox crs="urn:ogc:def:crs:EPSG::3857"><ows:LowerCorner>-20037508.3428 -20037508.3428</ows:LowerCorner><ows:UpperCorner>20037508.3428 20037508.3428</ows:UpperCorner></ows:BoundingBox>`,
[
`<ows:BoundingBox crs="urn:ogc:def:crs:EPSG::3857">`,
`<ows:LowerCorner>-20037508.3428 -20037508.3428</ows:LowerCorner>`,
`<ows:UpperCorner>20037508.3428 20037508.3428</ows:UpperCorner>`,
`</ows:BoundingBox>`,
].join(''),
),
);

assert.ok(
xml.includes(
`<ows:WGS84BoundingBox crs="urn:ogc:def:crs:OGC:2:84"><ows:LowerCorner>-180 -85.051129</ows:LowerCorner><ows:UpperCorner>180 85.051129</ows:UpperCorner></ows:WGS84BoundingBox>`,
[
`<ows:WGS84BoundingBox crs="urn:ogc:def:crs:OGC:2:84">`,
`<ows:LowerCorner>-180 -85.051129</ows:LowerCorner>`,
`<ows:UpperCorner>180 85.051129</ows:UpperCorner>`,
`</ows:WGS84BoundingBox>`,
].join(''),
),
);

Expand Down
Loading