diff --git a/examples/cog-basic/package.json b/examples/cog-basic/package.json index 04a378d..10fb0ab 100644 --- a/examples/cog-basic/package.json +++ b/examples/cog-basic/package.json @@ -17,6 +17,7 @@ "@developmentseed/deck.gl-geotiff": "workspace:^", "@developmentseed/deck.gl-raster": "workspace:^", "geotiff": "^2.1.3", + "geotiff-geokeys-to-proj4": "^2024.4.13", "maplibre-gl": "^5.0.0", "proj4": "^2.20.2", "react": "^19.2.3", diff --git a/examples/cog-basic/src/App.tsx b/examples/cog-basic/src/App.tsx index 858d0f5..394ee31 100644 --- a/examples/cog-basic/src/App.tsx +++ b/examples/cog-basic/src/App.tsx @@ -1,12 +1,15 @@ -import { useEffect, useState, useRef } from "react"; -import { Map, useControl, type MapRef } from "react-map-gl/maplibre"; -import { MapboxOverlay } from "@deck.gl/mapbox"; import type { DeckProps } from "@deck.gl/core"; -import { fromUrl, Pool } from "geotiff"; +import { MapboxOverlay } from "@deck.gl/mapbox"; +import { COGLayer, proj } from "@developmentseed/deck.gl-geotiff"; import type { GeoTIFF } from "geotiff"; -import { COGLayer, GeoTIFFLayer } from "@developmentseed/deck.gl-geotiff"; -import proj4 from "proj4"; +import { fromUrl, Pool } from "geotiff"; +import { toProj4 } from "geotiff-geokeys-to-proj4"; import "maplibre-gl/dist/maplibre-gl.css"; +import proj4 from "proj4"; +import { useEffect, useRef, useState } from "react"; +import { Map, useControl, type MapRef } from "react-map-gl/maplibre"; + +window.proj4 = proj4; function DeckGLOverlay(props: DeckProps) { const overlay = useControl(() => new MapboxOverlay(props)); @@ -14,6 +17,20 @@ function DeckGLOverlay(props: DeckProps) { return null; } +async function geoKeysParser( + geoKeys: Record, +): Promise { + const projDefinition = toProj4(geoKeys as any); + console.log("projDefinition", projDefinition); + (window as any).projDefinition = projDefinition; + + return { + def: projDefinition.proj4, + parsed: proj.parseCrs(projDefinition.proj4), + coordinatesUnits: projDefinition.coordinatesUnits as proj.SupportedCrsUnit, + }; +} + /** * Calculate the WGS84 bounding box of a GeoTIFF image */ @@ -22,26 +39,10 @@ async function getCogBounds( ): Promise<[[number, number], [number, number]]> { const image = await tiff.getImage(); const projectedBbox = image.getBoundingBox(); - const geoKeys = image.getGeoKeys(); - - // Get the projection code - const projectionCode = - geoKeys.ProjectedCSTypeGeoKey || geoKeys.GeographicTypeGeoKey || null; - - if (!projectionCode) { - throw new Error("Could not determine projection from GeoTIFF"); - } - - // Fetch projection definition - const url = `https://epsg.io/${projectionCode}.json`; - const response = await fetch(url); - if (!response.ok) { - throw new Error(`Failed to fetch projection data from ${url}`); - } - const projDef = await response.json(); + const projDefinition = await geoKeysParser(image.getGeoKeys()); // Reproject to WGS84 (EPSG:4326) - const converter = proj4(projDef, "EPSG:4326"); + const converter = proj4(projDefinition.def, "EPSG:4326"); // Reproject all four corners to handle rotation/skew const [minX, minY, maxX, maxY] = projectedBbox; @@ -71,8 +72,12 @@ async function getCogBounds( // const COG_URL = // "https://nz-imagery.s3-ap-southeast-2.amazonaws.com/new-zealand/new-zealand_2024-2025_10m/rgb/2193/CC11.tiff"; +// const COG_URL = +// "https://ds-wheels.s3.us-east-1.amazonaws.com/m_4007307_sw_18_060_20220803.tif"; + +// const COG_URL = "http://127.0.0.1:8080/Annual_NLCD_LndCov_2023_CU_C1V0.tif"; const COG_URL = - "https://ds-wheels.s3.us-east-1.amazonaws.com/m_4007307_sw_18_060_20220803.tif"; + "https://ds-wheels.s3.us-east-1.amazonaws.com/Annual_NLCD_LndCov_2023_CU_C1V0.tif"; export default function App() { const mapRef = useRef(null); @@ -128,25 +133,16 @@ export default function App() { const layers = geotiff ? [ - renderAsTiled - ? new COGLayer({ - id: "cog-layer", - geotiff, - maxError: 0.125, - debug, - debugOpacity, - visible: renderAsTiled, - pool, - }) - : new GeoTIFFLayer({ - id: "geotiff-layer", - geotiff, - maxError: 0.125, - debug, - debugOpacity, - visible: !renderAsTiled, - pool, - }), + new COGLayer({ + id: "cog-layer", + geotiff, + maxError: 0.125, + debug, + debugOpacity, + geoKeysParser, + pool, + beforeId: "aeroway-runway", // In interleaved mode render the layer under map labels. Replace with `slot: 'bottom'` if using Mapbox v3 Standard Style. + }), ] : []; @@ -161,9 +157,9 @@ export default function App() { pitch: 0, bearing: 0, }} - mapStyle="https://basemaps.cartocdn.com/gl/positron-gl-style/style.json" + mapStyle="https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json" > - + {/* UI Overlay Container */} @@ -231,9 +227,9 @@ export default function App() {

COGLayer Example

-

+ {/*

Displaying RGB imagery from New Zealand (NZTM2000 projection) -

+

*/} {/* Debug Controls */}
- + */}
*/} diff --git a/package.json b/package.json index 792f997..e3c3ee9 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "typecheck": "pnpm -r typecheck" }, "devDependencies": { + "@typescript-eslint/eslint-plugin": "^8.49.0", "publint": "^0.3.16", "tsup": "^8.3.5", "typescript": "^5.7.2" diff --git a/packages/deck.gl-geotiff/src/cog-layer.ts b/packages/deck.gl-geotiff/src/cog-layer.ts index 0763c6e..15852a9 100644 --- a/packages/deck.gl-geotiff/src/cog-layer.ts +++ b/packages/deck.gl-geotiff/src/cog-layer.ts @@ -15,11 +15,10 @@ import type { ReprojectionFns } from "@developmentseed/raster-reproject"; import type { GeoTIFF, GeoTIFFImage, Pool } from "geotiff"; import proj4 from "proj4"; import { parseCOGTileMatrixSet } from "./cog-tile-matrix-set.js"; -import { - fromGeoTransform, - getGeoTIFFProjection, -} from "./geotiff-reprojection.js"; +import { fromGeoTransform } from "./geotiff-reprojection.js"; import { defaultPool, loadRgbImage } from "./geotiff.js"; +import type { GeoKeysParser } from "./proj.js"; +import { epsgIoGeoKeyParser } from "./proj.js"; // Workaround until upstream exposes props // https://github.com/visgl/deck.gl/pull/9917 @@ -30,6 +29,16 @@ const DEFAULT_MAX_ERROR = 0.125; export interface COGLayerProps extends CompositeLayerProps { geotiff: GeoTIFF; + /** + * A function callback for parsing GeoTIFF geo keys to a Proj4 compatible + * definition. + * + * By default, uses epsg.io to resolve EPSG codes found in the GeoTIFF. + * Alternatively, you may want to use `geotiff-geokeys-to-proj4`, which is + * more extensive but adds 1.5MB to your bundle size. + */ + geoKeysParser?: GeoKeysParser; + /** * GeoTIFF.js Pool for decoding image chunks. * @@ -58,8 +67,9 @@ export interface COGLayerProps extends CompositeLayerProps { debugOpacity?: number; } -const defaultProps = { +const defaultProps: Partial = { maxError: DEFAULT_MAX_ERROR, + geoKeysParser: epsgIoGeoKeyParser, }; /** @@ -96,7 +106,8 @@ export class COGLayer extends CompositeLayer { async _parseGeoTIFF(): Promise { const { geotiff } = this.props; - const metadata = await parseCOGTileMatrixSet(geotiff); + const geoKeysParser = this.props.geoKeysParser!; + const metadata = await parseCOGTileMatrixSet(geotiff, geoKeysParser); const image = await geotiff.getImage(); const imageCount = await geotiff.getImageCount(); @@ -105,14 +116,14 @@ export class COGLayer extends CompositeLayer { images.push(await geotiff.getImage(imageIdx)); } - const sourceProjection = await getGeoTIFFProjection(image); + const sourceProjection = await geoKeysParser(image.getGeoKeys()); if (!sourceProjection) { throw new Error( "Could not determine source projection from GeoTIFF geo keys", ); } - const converter = proj4(sourceProjection, "EPSG:4326"); + const converter = proj4(sourceProjection.def, "EPSG:4326"); const forwardReproject = (x: number, y: number) => converter.forward<[number, number]>([x, y], false); const inverseReproject = (x: number, y: number) => diff --git a/packages/deck.gl-geotiff/src/cog-tile-matrix-set.ts b/packages/deck.gl-geotiff/src/cog-tile-matrix-set.ts index cd1582a..dcfc88a 100644 --- a/packages/deck.gl-geotiff/src/cog-tile-matrix-set.ts +++ b/packages/deck.gl-geotiff/src/cog-tile-matrix-set.ts @@ -4,13 +4,10 @@ import type { TileMatrixSetBoundingBox, } from "@developmentseed/deck.gl-raster"; import type { GeoTIFF, GeoTIFFImage } from "geotiff"; -import { - extractGeotransform, - getGeoTIFFProjection, -} from "./geotiff-reprojection"; +import { extractGeotransform } from "./geotiff-reprojection"; import proj4, { ProjectionDefinition } from "proj4"; import Ellipsoid from "./ellipsoids.js"; -import type { PROJJSONDefinition } from "proj4/dist/lib/core"; +import { GeoKeysParser, ProjectionInfo, SupportedCrsUnit } from "./proj"; // 0.28 mm per pixel // https://docs.ogc.org/is/17-083r4/17-083r4.html#toc15 @@ -25,6 +22,7 @@ const SCREEN_PIXEL_SIZE = 0.00028; */ export async function parseCOGTileMatrixSet( tiff: GeoTIFF, + geoKeysParser: GeoKeysParser, ): Promise { const fullResImage = await tiff.getImage(); @@ -37,7 +35,7 @@ export async function parseCOGTileMatrixSet( const fullImageWidth = fullResImage.getWidth(); const fullImageHeight = fullResImage.getHeight(); - const crs = await getGeoTIFFProjection(fullResImage); + const crs = await geoKeysParser(fullResImage.getGeoKeys()); if (crs === null) { throw new Error( @@ -45,10 +43,8 @@ export async function parseCOGTileMatrixSet( ); } - const parsedCrs = parseCrs(crs); - - const projectToWgs84 = proj4(crs, "EPSG:4326").forward; - const projectTo3857 = proj4(crs, "EPSG:3857").forward; + const projectToWgs84 = proj4(crs.def, "EPSG:4326").forward; + const projectTo3857 = proj4(crs.def, "EPSG:3857").forward; const boundingBox: TileMatrixSet["boundingBox"] = { lowerLeft: [bbox[0]!, bbox[1]!], @@ -74,7 +70,8 @@ export async function parseCOGTileMatrixSet( // Set as highest resolution / finest level id: String(imageCount - 1), scaleDenominator: - (cellSize * metersPerUnit(parsedCrs)) / SCREEN_PIXEL_SIZE, + (cellSize * metersPerUnit(crs.parsed, crs.coordinatesUnits)) / + SCREEN_PIXEL_SIZE, cellSize, pointOfOrigin: [transform[2], transform[5]], tileWidth: fullResImage.getTileWidth(), @@ -99,7 +96,7 @@ export async function parseCOGTileMatrixSet( fullWidth: fullImageWidth, fullHeight: fullImageHeight, baseTransform: transform, - parsedCrs, + crs, }); tileMatrices.push(tileMatrix); } @@ -126,10 +123,18 @@ export async function parseCOGTileMatrixSet( * > If the CRS uses meters as units of measure for the horizontal dimensions, * > then metersPerUnit=1; if it has degrees, then metersPerUnit=2pa/360 * > (a is the Earth maximum radius of the ellipsoid). + * + * If `crsUnit` is provided, it takes precedence over the unit defined in the + * CRS. This exists because sometimes the parsed CRS from + * `geotiff-geokeys-to-proj4` doesn't have a unit defined. */ // https://github.com/developmentseed/morecantile/blob/7c95a11c491303700d6e33e9c1607f2719584dec/morecantile/utils.py#L67-L90 -function metersPerUnit(parsedCrs: ProjectionDefinition): number { - switch (parsedCrs.units) { +function metersPerUnit( + parsedCrs: ProjectionDefinition, + crsUnit?: SupportedCrsUnit, +): number { + const unit = crsUnit || parsedCrs.units; + switch (unit) { case "metre": case "meter": case "meters": @@ -140,13 +145,13 @@ function metersPerUnit(parsedCrs: ProjectionDefinition): number { return 1200 / 3937; } - if (parsedCrs.units === "degree") { + if (unit === "degree") { // 2 * π * ellipsoid semi-major-axis / 360 const { a } = Ellipsoid[parsedCrs.ellps as keyof typeof Ellipsoid]; return (2 * Math.PI * a) / 360; } - throw new Error(`Unsupported CRS units: ${parsedCrs.units}`); + throw new Error(`Unsupported CRS units: ${unit}`); } /** @@ -157,14 +162,14 @@ function createOverviewTileMatrix({ image, fullWidth, baseTransform, - parsedCrs, + crs, }: { id: string; image: GeoTIFFImage; fullWidth: number; fullHeight: number; baseTransform: [number, number, number, number, number, number]; - parsedCrs: ProjectionDefinition; + crs: ProjectionInfo; }): TileMatrix { const width = image.getWidth(); const height = image.getHeight(); @@ -195,7 +200,9 @@ function createOverviewTileMatrix({ return { id, - scaleDenominator: (cellSize * metersPerUnit(parsedCrs)) / SCREEN_PIXEL_SIZE, + scaleDenominator: + (cellSize * metersPerUnit(crs.parsed, crs.coordinatesUnits)) / + SCREEN_PIXEL_SIZE, cellSize, pointOfOrigin: [geotransform[2], geotransform[5]], tileWidth, @@ -206,17 +213,6 @@ function createOverviewTileMatrix({ }; } -function parseCrs(crs: PROJJSONDefinition): ProjectionDefinition { - // If you pass proj4.defs a projjson, it doesn't parse it; it just returns the - // input. - // - // Instead, you need to assign it to an alias and then retrieve it. - - const key = "__deck.gl-geotiff-internal__"; - proj4.defs(key, crs); - return proj4.defs(key); -} - function computeWgs84BoundingBox( boundingBox: TileMatrixSetBoundingBox, projectToWgs84: (point: [number, number]) => [number, number], diff --git a/packages/deck.gl-geotiff/src/geotiff-layer.ts b/packages/deck.gl-geotiff/src/geotiff-layer.ts index c8fc1ae..6c8c75c 100644 --- a/packages/deck.gl-geotiff/src/geotiff-layer.ts +++ b/packages/deck.gl-geotiff/src/geotiff-layer.ts @@ -5,12 +5,24 @@ import type { ReprojectionFns } from "@developmentseed/raster-reproject"; import type { GeoTIFF, Pool } from "geotiff"; import { extractGeotiffReprojectors } from "./geotiff-reprojection.js"; import { defaultPool, loadRgbImage } from "./geotiff.js"; +import type { GeoKeysParser } from "./proj.js"; +import { epsgIoGeoKeyParser } from "./proj.js"; const DEFAULT_MAX_ERROR = 0.125; export interface GeoTIFFLayerProps extends CompositeLayerProps { geotiff: GeoTIFF; + /** + * A function callback for parsing GeoTIFF geo keys to a Proj4 compatible + * definition. + * + * By default, uses epsg.io to resolve EPSG codes found in the GeoTIFF. + * Alternatively, you may want to use `geotiff-geokeys-to-proj4`, which is + * more extensive but adds 1.5MB to your bundle size. + */ + geoKeysParser?: GeoKeysParser; + /** * GeoTIFF.js Pool for decoding image chunks. * @@ -41,6 +53,7 @@ export interface GeoTIFFLayerProps extends CompositeLayerProps { const defaultProps = { maxError: DEFAULT_MAX_ERROR, + geoKeysParser: epsgIoGeoKeyParser, }; /** @@ -83,7 +96,10 @@ export class GeoTIFFLayer extends CompositeLayer { async _parseGeoTIFF(): Promise { const { geotiff } = this.props; - const reprojectionFns = await extractGeotiffReprojectors(geotiff); + const reprojectionFns = await extractGeotiffReprojectors( + geotiff, + this.props.geoKeysParser!, + ); const image = await geotiff.getImage(); const { imageData, height, width } = await loadRgbImage(image, { pool: this.props.pool || defaultPool(), diff --git a/packages/deck.gl-geotiff/src/geotiff-reprojection.ts b/packages/deck.gl-geotiff/src/geotiff-reprojection.ts index d6ac123..24153dc 100644 --- a/packages/deck.gl-geotiff/src/geotiff-reprojection.ts +++ b/packages/deck.gl-geotiff/src/geotiff-reprojection.ts @@ -9,8 +9,9 @@ import { import proj4 from "proj4"; import type { PROJJSONDefinition } from "proj4/dist/lib/core"; import type Projection from "proj4/dist/lib/Proj"; +import type { GeoKeysParser } from "./proj"; -const OGC_84: PROJJSONDefinition = { +export const OGC_84: PROJJSONDefinition = { $schema: "https://proj.org/schemas/v0.7/projjson.schema.json", type: "GeographicCRS", name: "WGS 84 (CRS84)", @@ -89,6 +90,7 @@ const OGC_84: PROJJSONDefinition = { // TODO: return a RasterReprojector instance, given the IFD and tile of interest? export async function extractGeotiffReprojectors( tiff: GeoTIFF, + geoKeysParser: GeoKeysParser, outputCrs: string | PROJJSONDefinition | Projection = OGC_84, ): Promise { const image = await tiff.getImage(); @@ -97,13 +99,13 @@ export async function extractGeotiffReprojectors( // Only the top-level IFD has geo keys, so we'll derive overviews from this const baseGeotransform = extractGeotransform(image); - const sourceProjection = await getGeoTIFFProjection(image); + const sourceProjection = await geoKeysParser(image.getGeoKeys()); if (sourceProjection === null) { throw new Error( "Could not determine source projection from GeoTIFF geo keys", ); } - const converter = proj4(sourceProjection, outputCrs); + const converter = proj4(sourceProjection.def, outputCrs); const { pixelToInputCRS, inputCRSToPixel } = fromGeoTransform(baseGeotransform); @@ -131,38 +133,6 @@ export function fromGeoTransform( }; } -/** - * Get the Projection of a GeoTIFF - * - * The first `image` must be passed in, as only the top-level IFD contains geo - * keys. - */ -export async function getGeoTIFFProjection( - image: GeoTIFFImage, -): Promise { - const geoKeys = image.getGeoKeys(); - const projectionCode: number | null = - geoKeys.ProjectedCSTypeGeoKey || geoKeys.GeographicTypeGeoKey || null; - - const sourceProjection = await getProjjson(projectionCode); - return sourceProjection; -} - -/** Query epsg.io for the PROJJSON corresponding to the given EPSG code. */ -async function getProjjson(projectionCode: number | null) { - if (projectionCode === null) { - return null; - } - - const url = `https://epsg.io/${projectionCode}.json`; - const response = await fetch(url); - if (!response.ok) { - throw new Error(`Failed to fetch projection data from ${url}`); - } - const data = await response.json(); - return data; -} - /** * Extract affine geotransform from a GeoTIFF image. * diff --git a/packages/deck.gl-geotiff/src/index.ts b/packages/deck.gl-geotiff/src/index.ts index 25f87da..bc211bb 100644 --- a/packages/deck.gl-geotiff/src/index.ts +++ b/packages/deck.gl-geotiff/src/index.ts @@ -6,6 +6,7 @@ export type { GeoTIFFLayerProps } from "./geotiff-layer.js"; export { extractGeotiffReprojectors, fromGeoTransform, - getGeoTIFFProjection, } from "./geotiff-reprojection.js"; export { loadRgbImage } from "./geotiff.js"; + +export * as proj from "./proj.js"; diff --git a/packages/deck.gl-geotiff/src/proj.ts b/packages/deck.gl-geotiff/src/proj.ts new file mode 100644 index 0000000..6bbd423 --- /dev/null +++ b/packages/deck.gl-geotiff/src/proj.ts @@ -0,0 +1,81 @@ +import type { ProjectionDefinition } from "proj4"; +import proj4 from "proj4"; +import type { PROJJSONDefinition } from "proj4/dist/lib/core"; + +export type SupportedCrsUnit = + | "metre" + | "meter" + | "meters" + | "foot" + | "US survey foot" + | "degree"; + +export interface ProjectionInfo { + /** Proj4-compatible projection definition (PROJJSON or proj4 string) */ + def: string | PROJJSONDefinition; + /** A parsed projection definition */ + parsed: ProjectionDefinition; + /** Units of the coordinate system */ + coordinatesUnits: SupportedCrsUnit; +} + +export type GeoKeysParser = ( + geoKeys: Record, +) => Promise; + +/** + * Get the Projection of a GeoTIFF + * + * The first `image` must be passed in, as only the top-level IFD contains geo + * keys. + */ +export async function epsgIoGeoKeyParser( + geoKeys: Record, +): Promise { + const projectionCode: number | null = + geoKeys.ProjectedCSTypeGeoKey || geoKeys.GeographicTypeGeoKey || null; + + const sourceProjection = await getProjjson(projectionCode); + + if (!sourceProjection) { + return null; + } + + const parsed = parseCrs(sourceProjection); + return { + def: sourceProjection, + parsed, + coordinatesUnits: parsed.units as SupportedCrsUnit, + }; +} + +/** Query epsg.io for the PROJJSON corresponding to the given EPSG code. */ +async function getProjjson(projectionCode: number | null) { + if (projectionCode === null) { + return null; + } + + const url = `https://epsg.io/${projectionCode}.json`; + const response = await fetch(url); + if (!response.ok) { + throw new Error(`Failed to fetch projection data from ${url}`); + } + const data = await response.json(); + return data; +} + +/** + * Parse a proj4-accepted input into a ProjectionDefinition + */ +export function parseCrs( + crs: string | PROJJSONDefinition, +): ProjectionDefinition { + // If you pass proj4.defs a projjson, it doesn't parse it; it just returns the + // input. + // + // Instead, you need to assign it to an alias and then retrieve it. + + const key = "__deck.gl-geotiff-internal__"; + proj4.defs(key, crs); + return proj4.defs(key); +} diff --git a/packages/deck.gl-geotiff/tests/cog-tms.test.ts b/packages/deck.gl-geotiff/tests/cog-tms.test.ts index c26e45d..991873e 100644 --- a/packages/deck.gl-geotiff/tests/cog-tms.test.ts +++ b/packages/deck.gl-geotiff/tests/cog-tms.test.ts @@ -1,6 +1,7 @@ import { describe, it, expect } from "vitest"; import { parseCOGTileMatrixSet } from "../src"; import { fromUrl } from "geotiff"; +import { epsgIoGeoKeyParser } from "../src/proj"; describe("create TileMatrixSet from COG", () => { it("creates TMS", async () => { @@ -8,7 +9,7 @@ describe("create TileMatrixSet from COG", () => { "https://ds-wheels.s3.us-east-1.amazonaws.com/m_4007307_sw_18_060_20220803.tif"; const tiff = await fromUrl(url); - const tms = await parseCOGTileMatrixSet(tiff); + const tms = await parseCOGTileMatrixSet(tiff, epsgIoGeoKeyParser); const expectedTileMatrices = [ { diff --git a/packages/deck.gl-raster/src/raster-tileset/raster-tile-traversal.ts b/packages/deck.gl-raster/src/raster-tileset/raster-tile-traversal.ts index 46e35e8..04e9588 100644 --- a/packages/deck.gl-raster/src/raster-tileset/raster-tile-traversal.ts +++ b/packages/deck.gl-raster/src/raster-tileset/raster-tile-traversal.ts @@ -275,12 +275,12 @@ export class RasterTileNode { boundingVolume, viewport.zoom, ); - console.log("metersPerScreenPixel", metersPerScreenPixel); + // console.log("metersPerScreenPixel", metersPerScreenPixel); const tileMetersPerPixel = this.tileMatrix.scaleDenominator * SCREEN_PIXEL_SIZE; - console.log("tileMetersPerPixel", tileMetersPerPixel); + // console.log("tileMetersPerPixel", tileMetersPerPixel); // const screenScaleDenominator = metersPerScreenPixel / SCREEN_PIXEL_SIZE; @@ -295,10 +295,10 @@ export class RasterTileNode { // this.tileMatrix.scaleDenominator, // ); - console.log( - "tileMetersPerPixel <= metersPerScreenPixel", - tileMetersPerPixel <= metersPerScreenPixel, - ); + // console.log( + // "tileMetersPerPixel <= metersPerScreenPixel", + // tileMetersPerPixel <= metersPerScreenPixel, + // ); if ( tileMetersPerPixel <= metersPerScreenPixel || diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ea8581f..f7eaf38 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: devDependencies: + '@typescript-eslint/eslint-plugin': + specifier: ^8.49.0 + version: 8.49.0(@typescript-eslint/parser@8.49.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3) publint: specifier: ^0.3.16 version: 0.3.16 @@ -44,6 +47,9 @@ importers: geotiff: specifier: ^2.1.3 version: 2.1.3 + geotiff-geokeys-to-proj4: + specifier: ^2024.4.13 + version: 2024.4.13 maplibre-gl: specifier: ^5.0.0 version: 5.14.0 @@ -1572,6 +1578,9 @@ packages: geojson-vt@4.0.2: resolution: {integrity: sha512-AV9ROqlNqoZEIJGfm1ncNjEXfkz2hdFlZf0qkVfmkwdKa8vj7H16YUOT81rJw1rdFhyEDlN2Tds91p/glzbl5A==} + geotiff-geokeys-to-proj4@2024.4.13: + resolution: {integrity: sha512-Jgtm/lcPkgB44wCqQHaVQx5/fyhmiVDRUKQcI/vMolsED8/GRWBnn5qkQo/CgutQg9xkGzig21DY9Px9mFRdvg==} + geotiff@2.1.3: resolution: {integrity: sha512-PT6uoF5a1+kbC3tHmZSUsLHBp2QJlHasxxxxPW47QIY1VBKpFB+FcDvX+MxER6UzgLQZ0xDzJ9s48B9JbOCTqA==} engines: {node: '>=10.19'} @@ -3971,6 +3980,8 @@ snapshots: geojson-vt@4.0.2: {} + geotiff-geokeys-to-proj4@2024.4.13: {} + geotiff@2.1.3: dependencies: '@petamoriken/float16': 3.9.3