diff --git a/packages/lambda-tiler/src/__tests__/wmts.capability.test.ts b/packages/lambda-tiler/src/__tests__/wmts.capability.test.ts
index e597a2073..872f14d7f 100644
--- a/packages/lambda-tiler/src/__tests__/wmts.capability.test.ts
+++ b/packages/lambda-tiler/src/__tests__/wmts.capability.test.ts
@@ -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(),
+ `-20037508.3428 -20037508.3428`,
+ );
+ assert.equal(
+ epsg3857?.find('ows:UpperCorner')?.toString(),
+ `20037508.3428 20037508.3428`,
+ );
+
+ assert.equal(wgs84?.find('ows:LowerCorner')?.toString(), '-180 -85.051129');
+ assert.equal(wgs84?.find('ows:UpperCorner')?.toString(), '180 85.051129');
+ });
+
+ 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(),
+ `419435.9938 -3260586.7284`,
+ );
+ assert.equal(
+ crsBounds?.find('ows:UpperCorner')?.toString(),
+ `10438190.1652 6758167.443`,
+ );
+
+ assert.equal(wgs84?.find('ows:LowerCorner')?.toString(), '-180 -49.929855');
+ assert.equal(wgs84?.find('ows:UpperCorner')?.toString(), '180 2.938603');
+ });
+
it('should include output the correct TileMatrix', () => {
const wmts = new WmtsCapabilities({
httpBase: 'https://basemaps.test',
@@ -512,11 +592,12 @@ describe('WmtsCapabilities', () => {
.split('\n')
.map((c) => c.trim()),
);
+
assert.deepEqual(boundingBox[0][1], '-180 -85.0511');
- assert.equal(boundingBox[0][2], '180 0');
+ assert.equal(boundingBox[0][2], '180 85.0511');
assert.deepEqual(boundingBox[1][1], '-180 -85.0511');
- assert.equal(boundingBox[1][2], '180 0');
+ assert.equal(boundingBox[1][2], '180 85.0511');
});
it('should work with NZTM2000Quad', () => {
diff --git a/packages/lambda-tiler/src/wmts.capability.ts b/packages/lambda-tiler/src/wmts.capability.ts
index 3e782c99b..7b69da04e 100644
--- a/packages/lambda-tiler/src/wmts.capability.ts
+++ b/packages/lambda-tiler/src/wmts.capability.ts
@@ -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;
@@ -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;
@@ -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)),
diff --git a/packages/smoke/src/base.ts b/packages/smoke/src/base.ts
index 84bc6903b..c5d3d466b 100644
--- a/packages/smoke/src/base.ts
+++ b/packages/smoke/src/base.ts
@@ -30,7 +30,19 @@ async function req(path: string, opts?: RequestInit): Promise {
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;
}
diff --git a/packages/smoke/src/wmts.test.ts b/packages/smoke/src/wmts.test.ts
index 99ba56c43..6eae1e994 100644
--- a/packages/smoke/src/wmts.test.ts
+++ b/packages/smoke/src/wmts.test.ts
@@ -28,13 +28,23 @@ test(`GET /v1/tiles/aerial/WebMercatorQuad/WMTSCapabilities.xml`, async () => {
assert.ok(
xml.includes(
- `-20037508.3428 -20037508.342820037508.3428 20037508.3428`,
+ [
+ ``,
+ `-20037508.3428 -20037508.3428`,
+ `20037508.3428 20037508.3428`,
+ ``,
+ ].join(''),
),
);
assert.ok(
xml.includes(
- `-180 -85.051129180 85.051129`,
+ [
+ ``,
+ `-180 -85.051129`,
+ `180 85.051129`,
+ ``,
+ ].join(''),
),
);