diff --git a/src/initialize-store.js b/src/initialize-store.js index e251533..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': @@ -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..03c8e24 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 = {} @@ -57,8 +57,6 @@ export const createTiles = (regl, opts) => { this.selector = selector 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 +115,7 @@ export const createTiles = (regl, opts) => { levels, maxZoom, tileSize, + crs, }) => { if (setMetadata) setMetadata(metadata) this.maxZoom = maxZoom @@ -124,6 +123,23 @@ 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) + this.projection = ['mercator', 'equirectangular'][ + this.projectionIndex + ] + + 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'.` + ) + } + if (mode === 'grid' || mode === 'dotgrid') { this.count = position.length } @@ -291,6 +307,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 cb35f99..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 @@ -41,7 +40,7 @@ export const pointToTile = (lon, lat, z, projection, order) => { y = Math.max(Math.min(y, z2), 0) tile = [x, y, z] default: - break + return } tile[0] = Math.floor(tile[0]) tile[1] = Math.min(Math.floor(tile[1]), z2 - 1) @@ -349,13 +348,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 } } /**