From 1b2762a4b91dc62df1e3e12f53d73a3fd6d73954 Mon Sep 17 00:00:00 2001 From: katamartin Date: Tue, 26 Mar 2024 10:06:35 -0400 Subject: [PATCH 1/8] Read attribute from metadata --- src/initialize-store.js | 5 +++-- src/tiles.js | 6 +++++- src/utils.js | 10 +++++++++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/initialize-store.js b/src/initialize-store.js index e251533..f266d87 100644 --- a/src/initialize-store.js +++ b/src/initialize-store.js @@ -21,7 +21,7 @@ const initializeStore = async (source, version, variable, coordinateKeys) => { resolve() }) ) - ;({ levels, maxZoom, tileSize } = getPyramidMetadata( + ;({ levels, maxZoom, tileSize, crs } = getPyramidMetadata( metadata.metadata['.zattrs'].multiscales )) @@ -48,7 +48,7 @@ const initializeStore = async (source, version, variable, coordinateKeys) => { break case 'v3': metadata = await fetch(`${source}/zarr.json`).then((res) => res.json()) - ;({ levels, maxZoom, tileSize } = getPyramidMetadata( + ;({ levels, maxZoom, tileSize, crs } = getPyramidMetadata( metadata.attributes.multiscales )) @@ -114,6 +114,7 @@ const initializeStore = async (source, version, variable, coordinateKeys) => { levels, maxZoom, tileSize, + crs, } } diff --git a/src/tiles.js b/src/tiles.js index 7b283fc..7064533 100644 --- a/src/tiles.js +++ b/src/tiles.js @@ -58,7 +58,6 @@ export const createTiles = (regl, opts) => { this.variable = variable this.fillValue = fillValue this.projection = projection - this.projectionIndex = ['mercator', 'equirectangular'].indexOf(projection) this.order = order ?? [1, 1] this.invalidate = invalidate this.viewport = { viewportHeight: 0, viewportWidth: 0 } @@ -117,6 +116,7 @@ export const createTiles = (regl, opts) => { levels, maxZoom, tileSize, + crs, }) => { if (setMetadata) setMetadata(metadata) this.maxZoom = maxZoom @@ -124,6 +124,10 @@ export const createTiles = (regl, opts) => { const position = getPositions(tileSize, mode) this.position = regl.buffer(position) this.size = tileSize + // Respect `projection` prop when provided, otherwise rely on `crs` value from metadata + this.projectionIndex = projection + ? ['mercator', 'equirectangular'].indexOf(projection) + : ['EPSG:3857', 'EPSG:4326'].indexOf(crs) if (mode === 'grid' || mode === 'dotgrid') { this.count = position.length } diff --git a/src/utils.js b/src/utils.js index cb35f99..64e8191 100644 --- a/src/utils.js +++ b/src/utils.js @@ -349,13 +349,21 @@ export const getPyramidMetadata = (multiscales) => { const levels = datasets.map((dataset) => Number(dataset.path)) const maxZoom = Math.max(...levels) const tileSize = datasets[0].pixels_per_tile + let crs = datasets[0].crs if (!tileSize) { throw new Error( 'Missing required `pixels_per_tile` value in `multiscales` metadata. Please check your pyramid generation code.' ) } - return { levels, maxZoom, tileSize } + + if (!crs) { + console.warn( + 'Missing `crs` value in `multiscales` metadata. Please check your pyramid generation code. Falling back to `crs=EPSG:3857` (Web Mercator)' + ) + crs = 'EPSG:3857' + } + return { levels, maxZoom, tileSize, crs } } /** From 870475be6da94f7961b8522aeef1553520196936 Mon Sep 17 00:00:00 2001 From: katamartin Date: Tue, 26 Mar 2024 10:19:03 -0400 Subject: [PATCH 2/8] Add missing definition --- src/initialize-store.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/initialize-store.js b/src/initialize-store.js index f266d87..c9d56c7 100644 --- a/src/initialize-store.js +++ b/src/initialize-store.js @@ -10,7 +10,7 @@ const initializeStore = async (source, version, variable, coordinateKeys) => { let chunks let fill_value let dtype - let levels, maxZoom, tileSize + let levels, maxZoom, tileSize, crs const coordinates = {} switch (version) { case 'v2': From e8af016bf403da287bac3a1d882e93acac63b019 Mon Sep 17 00:00:00 2001 From: katamartin Date: Tue, 26 Mar 2024 10:19:43 -0400 Subject: [PATCH 3/8] Remove prop default --- src/tiles.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tiles.js b/src/tiles.js index 7064533..f0480bf 100644 --- a/src/tiles.js +++ b/src/tiles.js @@ -46,7 +46,7 @@ export const createTiles = (regl, opts) => { setMetadata, order, version = 'v2', - projection = 'mercator', + projection, }) { this.tiles = {} this.loaders = {} From 6868c9f1ce9e449bfdcd90b05f4dc23e4ba8d050 Mon Sep 17 00:00:00 2001 From: katamartin Date: Tue, 26 Mar 2024 10:44:14 -0400 Subject: [PATCH 4/8] Avoid errors before metadata initialized --- src/tiles.js | 9 +++++++++ src/utils.js | 1 + 2 files changed, 10 insertions(+) diff --git a/src/tiles.js b/src/tiles.js index f0480bf..45ea158 100644 --- a/src/tiles.js +++ b/src/tiles.js @@ -128,6 +128,10 @@ export const createTiles = (regl, opts) => { this.projectionIndex = projection ? ['mercator', 'equirectangular'].indexOf(projection) : ['EPSG:3857', 'EPSG:4326'].indexOf(crs) + this.projection = ['mercator', 'equirectangular'][ + this.projectionIndex + ] + if (mode === 'grid' || mode === 'dotgrid') { this.count = position.length } @@ -295,6 +299,11 @@ export const createTiles = (regl, opts) => { } this.updateCamera = ({ center, zoom }) => { + // Return early if projection not yet initialized + if (!this.projection) { + return + } + const level = zoomToLevel(zoom, this.maxZoom) const tile = pointToTile( center.lng, diff --git a/src/utils.js b/src/utils.js index 64e8191..398c9df 100644 --- a/src/utils.js +++ b/src/utils.js @@ -41,6 +41,7 @@ export const pointToTile = (lon, lat, z, projection, order) => { y = Math.max(Math.min(y, z2), 0) tile = [x, y, z] default: + return break } tile[0] = Math.floor(tile[0]) From 405ea05fd157183a53cdbee9444ff845d944f3a9 Mon Sep 17 00:00:00 2001 From: katamartin Date: Tue, 26 Mar 2024 11:55:47 -0400 Subject: [PATCH 5/8] Remove unused break --- src/utils.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/utils.js b/src/utils.js index 398c9df..9cb0463 100644 --- a/src/utils.js +++ b/src/utils.js @@ -42,7 +42,6 @@ export const pointToTile = (lon, lat, z, projection, order) => { tile = [x, y, z] default: return - break } tile[0] = Math.floor(tile[0]) tile[1] = Math.min(Math.floor(tile[1]), z2 - 1) From 79e536603bdce32d7ea6d9abaaeec1f93d4a7a07 Mon Sep 17 00:00:00 2001 From: katamartin Date: Tue, 26 Mar 2024 11:56:04 -0400 Subject: [PATCH 6/8] Remove unused import --- src/utils.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/utils.js b/src/utils.js index 9cb0463..07cabb6 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,5 +1,4 @@ import { point, rhumbBearing, rhumbDestination } from '@turf/turf' -import { select } from 'd3-selection' const d2r = Math.PI / 180 From 7a3823c9eeca3f9b5acff67c65954df2e937887e Mon Sep 17 00:00:00 2001 From: katamartin Date: Tue, 26 Mar 2024 11:59:53 -0400 Subject: [PATCH 7/8] Throw error when unexpected projection is encountered --- src/tiles.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/tiles.js b/src/tiles.js index 45ea158..74e4218 100644 --- a/src/tiles.js +++ b/src/tiles.js @@ -132,6 +132,14 @@ export const createTiles = (regl, opts) => { this.projectionIndex ] + if (!this.projection) { + throw new Error( + projection + ? `Unexpected \`projection\` prop provided: ${projection}. Must be one of 'mercator', 'equirectangular'.` + : `Unexpected \`crs\` found in metadata: ${crs}. Must be one of 'EPSG:3857', 'EPSG:4326'.` + ) + } + if (mode === 'grid' || mode === 'dotgrid') { this.count = position.length } From 6842eb7e8612f73e8bbaaa92af0c594b1f2c5018 Mon Sep 17 00:00:00 2001 From: katamartin Date: Tue, 26 Mar 2024 12:05:13 -0400 Subject: [PATCH 8/8] Throw an error on initialization when unexpected projection found --- src/tiles.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tiles.js b/src/tiles.js index 74e4218..03c8e24 100644 --- a/src/tiles.js +++ b/src/tiles.js @@ -57,7 +57,6 @@ export const createTiles = (regl, opts) => { this.selector = selector this.variable = variable this.fillValue = fillValue - this.projection = projection this.order = order ?? [1, 1] this.invalidate = invalidate this.viewport = { viewportHeight: 0, viewportWidth: 0 } @@ -133,10 +132,11 @@ export const createTiles = (regl, opts) => { ] if (!this.projection) { + this.projection = null throw new Error( projection - ? `Unexpected \`projection\` prop provided: ${projection}. Must be one of 'mercator', 'equirectangular'.` - : `Unexpected \`crs\` found in metadata: ${crs}. Must be one of 'EPSG:3857', 'EPSG:4326'.` + ? `Unexpected \`projection\` prop provided: '${projection}'. Must be one of 'mercator', 'equirectangular'.` + : `Unexpected \`crs\` found in metadata: '${crs}'. Must be one of 'EPSG:3857', 'EPSG:4326'.` ) }