@gisatcz/deckgl-geolib 2.6.0-dev.1 → 2.6.0-dev.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +150 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/index.min.js +2 -2
- package/dist/cjs/index.min.js.map +1 -1
- package/dist/cjs/react/index.js +39 -0
- package/dist/cjs/react/index.js.map +1 -0
- package/dist/cjs/react/index.min.js +2 -0
- package/dist/cjs/react/index.min.js.map +1 -0
- package/dist/esm/index.js +149 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.min.js +2 -2
- package/dist/esm/index.min.js.map +1 -1
- package/dist/esm/react/index.js +37 -0
- package/dist/esm/react/index.js.map +1 -0
- package/dist/esm/react/index.min.js +2 -0
- package/dist/esm/react/index.min.js.map +1 -0
- package/dist/esm/types/hooks/index.d.ts +1 -0
- package/dist/esm/types/hooks/useTerrainZRange.d.ts +30 -0
- package/dist/esm/types/index.d.ts +2 -0
- package/dist/esm/types/layers/CogTerrainLayer.d.ts +5 -0
- package/dist/esm/types/react/index.d.ts +1 -0
- package/dist/esm/types/utils/terrainPickingUtils.d.ts +61 -0
- package/package.json +24 -13
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var react = require('react');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* React hook for syncing terrain elevation bounds to overlay TileLayer for 3D frustum culling.
|
|
7
|
+
*
|
|
8
|
+
* Manages the zRange state needed to prevent foreground tile clipping when viewport is tilted in 3D.
|
|
9
|
+
*
|
|
10
|
+
* @returns Object with zRange state and onZRangeUpdate callback
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const { zRange, onZRangeUpdate } = useTerrainZRange();
|
|
15
|
+
*
|
|
16
|
+
* const layers = useMemo(() => [
|
|
17
|
+
* new TileLayer({
|
|
18
|
+
* id: 'osm',
|
|
19
|
+
* zRange: zRange, // Pass elevation bounds to overlay
|
|
20
|
+
* // ... other props
|
|
21
|
+
* }),
|
|
22
|
+
* new CogTerrainLayer({
|
|
23
|
+
* id: 'terrain',
|
|
24
|
+
* onZRangeUpdate: onZRangeUpdate, // Sync elevation bounds from terrain
|
|
25
|
+
* // ... other props
|
|
26
|
+
* }),
|
|
27
|
+
* ], [zRange]);
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
function useTerrainZRange() {
|
|
31
|
+
const [zRange, setZRange] = react.useState(null);
|
|
32
|
+
return {
|
|
33
|
+
zRange,
|
|
34
|
+
onZRangeUpdate: setZRange,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
exports.useTerrainZRange = useTerrainZRange;
|
|
39
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/hooks/useTerrainZRange.ts"],"sourcesContent":["import { useState } from 'react';\nimport type { ZRange } from '../layers/CogTerrainLayer';\n\n/**\n * React hook for syncing terrain elevation bounds to overlay TileLayer for 3D frustum culling.\n *\n * Manages the zRange state needed to prevent foreground tile clipping when viewport is tilted in 3D.\n *\n * @returns Object with zRange state and onZRangeUpdate callback\n *\n * @example\n * ```typescript\n * const { zRange, onZRangeUpdate } = useTerrainZRange();\n *\n * const layers = useMemo(() => [\n * new TileLayer({\n * id: 'osm',\n * zRange: zRange, // Pass elevation bounds to overlay\n * // ... other props\n * }),\n * new CogTerrainLayer({\n * id: 'terrain',\n * onZRangeUpdate: onZRangeUpdate, // Sync elevation bounds from terrain\n * // ... other props\n * }),\n * ], [zRange]);\n * ```\n */\nexport function useTerrainZRange() {\n const [zRange, setZRange] = useState<ZRange | null>(null);\n\n return {\n zRange,\n onZRangeUpdate: setZRange,\n };\n}\n"],"names":["useState"],"mappings":";;;;AAGA;;;;;;;;;;;;;;;;;;;;;;;;AAwBG;SACa,gBAAgB,GAAA;IAC9B,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAGA,cAAQ,CAAgB,IAAI,CAAC;IAEzD,OAAO;QACL,MAAM;AACN,QAAA,cAAc,EAAE,SAAS;KAC1B;AACH;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.min.js","sources":["../../../src/hooks/useTerrainZRange.ts"],"sourcesContent":["import { useState } from 'react';\nimport type { ZRange } from '../layers/CogTerrainLayer';\n\n/**\n * React hook for syncing terrain elevation bounds to overlay TileLayer for 3D frustum culling.\n *\n * Manages the zRange state needed to prevent foreground tile clipping when viewport is tilted in 3D.\n *\n * @returns Object with zRange state and onZRangeUpdate callback\n *\n * @example\n * ```typescript\n * const { zRange, onZRangeUpdate } = useTerrainZRange();\n *\n * const layers = useMemo(() => [\n * new TileLayer({\n * id: 'osm',\n * zRange: zRange, // Pass elevation bounds to overlay\n * // ... other props\n * }),\n * new CogTerrainLayer({\n * id: 'terrain',\n * onZRangeUpdate: onZRangeUpdate, // Sync elevation bounds from terrain\n * // ... other props\n * }),\n * ], [zRange]);\n * ```\n */\nexport function useTerrainZRange() {\n const [zRange, setZRange] = useState<ZRange | null>(null);\n\n return {\n zRange,\n onZRangeUpdate: setZRange,\n };\n}\n"],"names":["zRange","setZRange","useState","onZRangeUpdate"],"mappings":"wEA6BE,MAAOA,EAAQC,GAAaC,EAAAA,SAAwB,MAEpD,MAAO,CACLF,SACAG,eAAgBF,EAEpB"}
|
package/dist/esm/index.js
CHANGED
|
@@ -8258,7 +8258,9 @@ class CogTerrainLayer extends CompositeLayer {
|
|
|
8258
8258
|
const minZ = Math.min(...ranges.map((x) => x?.[0] ?? 0).filter((n) => Number.isFinite(n)));
|
|
8259
8259
|
const maxZ = Math.max(...ranges.map((x) => x?.[1] ?? 0).filter((n) => Number.isFinite(n)));
|
|
8260
8260
|
if (!zRange || minZ < zRange[0] || maxZ > zRange[1]) {
|
|
8261
|
-
|
|
8261
|
+
const newZRange = [Number.isFinite(minZ) ? minZ : 0, Number.isFinite(maxZ) ? maxZ : 0];
|
|
8262
|
+
this.setState({ zRange: newZRange });
|
|
8263
|
+
this.props.onZRangeUpdate?.(newZRange);
|
|
8262
8264
|
}
|
|
8263
8265
|
}
|
|
8264
8266
|
renderLayers() {
|
|
@@ -8310,6 +8312,151 @@ class CogTerrainLayer extends CompositeLayer {
|
|
|
8310
8312
|
}
|
|
8311
8313
|
}
|
|
8312
8314
|
|
|
8315
|
+
/**
|
|
8316
|
+
* Terrain coordinate extraction utility for CogTerrainLayer
|
|
8317
|
+
* Enables precise lat/lon/elevation extraction from 3D terrain picks
|
|
8318
|
+
*/
|
|
8319
|
+
/**
|
|
8320
|
+
* Extracts precise geographic coordinates and elevation from a CogTerrainLayer pick result
|
|
8321
|
+
*
|
|
8322
|
+
* @param pickResult - DeckGL pickObject result from terrain-layer pick
|
|
8323
|
+
* @returns TerrainCoordinate with lon/lat/elevation, or null if extraction fails
|
|
8324
|
+
*
|
|
8325
|
+
* @requires deck.gl >=9.3.0 (for `pickable: '3d'` support)
|
|
8326
|
+
* @note Requires `pickable: '3d'` on CogTerrainLayer. With 3D picking enabled,
|
|
8327
|
+
* deck.gl's terrain layer provides info.coordinate as a 3-element array [lon, lat, elevation]
|
|
8328
|
+
* where elevation is read directly from the terrain mesh at the picked point.
|
|
8329
|
+
* This gives accurate 3D coordinates regardless of camera pitch or bearing.
|
|
8330
|
+
*
|
|
8331
|
+
* @example
|
|
8332
|
+
* ```ts
|
|
8333
|
+
* const cogLayer = new CogTerrainLayer({
|
|
8334
|
+
* // ...
|
|
8335
|
+
* pickable: '3d', // Requires deck.gl >=9.3.0
|
|
8336
|
+
* onClick: (info) => {
|
|
8337
|
+
* const coord = extractTerrainCoordinate(info);
|
|
8338
|
+
* if (coord) {
|
|
8339
|
+
* console.log(`Clicked at ${coord.latitude}, ${coord.longitude}, elevation: ${coord.elevation}m`);
|
|
8340
|
+
* }
|
|
8341
|
+
* }
|
|
8342
|
+
* });
|
|
8343
|
+
* ```
|
|
8344
|
+
*/
|
|
8345
|
+
function extractTerrainCoordinate(pickResult) {
|
|
8346
|
+
try {
|
|
8347
|
+
// With pickable: '3d', info.coordinate is a 3-element array [lon, lat, elevation]
|
|
8348
|
+
if (!pickResult?.coordinate || pickResult.coordinate.length < 3) {
|
|
8349
|
+
return null;
|
|
8350
|
+
}
|
|
8351
|
+
const [longitude, latitude, elevation] = pickResult.coordinate;
|
|
8352
|
+
if (longitude === undefined || latitude === undefined || elevation === undefined) {
|
|
8353
|
+
return null;
|
|
8354
|
+
}
|
|
8355
|
+
return {
|
|
8356
|
+
longitude,
|
|
8357
|
+
latitude,
|
|
8358
|
+
elevation,
|
|
8359
|
+
};
|
|
8360
|
+
}
|
|
8361
|
+
catch {
|
|
8362
|
+
// Silently return null on any error
|
|
8363
|
+
return null;
|
|
8364
|
+
}
|
|
8365
|
+
}
|
|
8366
|
+
/**
|
|
8367
|
+
* Samples terrain coordinates in a grid around a pick point for debugging
|
|
8368
|
+
* Useful for understanding terrain data layout and accuracy
|
|
8369
|
+
*
|
|
8370
|
+
* @param pickResult - DeckGL pickObject result from terrain-layer pick
|
|
8371
|
+
* @param gridSize - Odd number for grid dimensions (default: 3 for 3x3 grid).
|
|
8372
|
+
* gridSize=3 → 3×3 grid (offset±1), gridSize=5 → 5×5 grid (offset±2).
|
|
8373
|
+
* Uses WebMercator projection for accurate latitude mapping.
|
|
8374
|
+
* @returns Array of TerrainCoordinate samples, or empty array if extraction fails
|
|
8375
|
+
*
|
|
8376
|
+
* @example
|
|
8377
|
+
* ```ts
|
|
8378
|
+
* const samples = sampleTerrainTileCoordinates(info, 5); // 5x5 grid around click
|
|
8379
|
+
* samples.forEach(coord => {
|
|
8380
|
+
* console.log(`Sample: ${coord.latitude}, ${coord.longitude}, elev: ${coord.elevation}m`);
|
|
8381
|
+
* });
|
|
8382
|
+
* ```
|
|
8383
|
+
*/
|
|
8384
|
+
function sampleTerrainTileCoordinates(pickResult, gridSize = 3) {
|
|
8385
|
+
try {
|
|
8386
|
+
// Validate input has required structure
|
|
8387
|
+
if (!pickResult?.tile?.content) {
|
|
8388
|
+
return [];
|
|
8389
|
+
}
|
|
8390
|
+
const tileResult = pickResult.tile.content[0];
|
|
8391
|
+
if (!tileResult?.raw) {
|
|
8392
|
+
return [];
|
|
8393
|
+
}
|
|
8394
|
+
const { raw, width, height } = tileResult;
|
|
8395
|
+
const bbox = pickResult.tile.bbox;
|
|
8396
|
+
if (!bbox) {
|
|
8397
|
+
return [];
|
|
8398
|
+
}
|
|
8399
|
+
const west = bbox.west ?? bbox[0];
|
|
8400
|
+
const south = bbox.south ?? bbox[1];
|
|
8401
|
+
const east = bbox.east ?? bbox[2];
|
|
8402
|
+
const north = bbox.north ?? bbox[3];
|
|
8403
|
+
if (west === undefined || south === undefined || east === undefined || north === undefined) {
|
|
8404
|
+
return [];
|
|
8405
|
+
}
|
|
8406
|
+
const coordinate = pickResult.coordinate;
|
|
8407
|
+
if (!coordinate || coordinate.length < 2) {
|
|
8408
|
+
return [];
|
|
8409
|
+
}
|
|
8410
|
+
const [centerLon, centerLat] = coordinate;
|
|
8411
|
+
// Calculate grid offset (in pixels): gridSize must be odd; gridSize=3 → offset=1, gridSize=5 → offset=2
|
|
8412
|
+
const offset = Math.floor(gridSize / 2);
|
|
8413
|
+
// Get center pixel from clicked coordinate using WebMercator projection
|
|
8414
|
+
const centerNormX = (centerLon - west) / (east - west);
|
|
8415
|
+
// WebMercator non-linear latitude projection
|
|
8416
|
+
const centerLatRad = centerLat * Math.PI / 180;
|
|
8417
|
+
const northRad = north * Math.PI / 180;
|
|
8418
|
+
const southRad = south * Math.PI / 180;
|
|
8419
|
+
const mercatorCenterY = Math.log(Math.tan(Math.PI / 4 + centerLatRad / 2));
|
|
8420
|
+
const mercatorNorth = Math.log(Math.tan(Math.PI / 4 + northRad / 2));
|
|
8421
|
+
const mercatorSouth = Math.log(Math.tan(Math.PI / 4 + southRad / 2));
|
|
8422
|
+
const centerNormY = (mercatorNorth - mercatorCenterY) / (mercatorNorth - mercatorSouth);
|
|
8423
|
+
const centerPixelX = Math.floor(centerNormX * (width - 1));
|
|
8424
|
+
const centerPixelY = Math.floor(centerNormY * (height - 1));
|
|
8425
|
+
const samples = [];
|
|
8426
|
+
// Sample grid around clicked point
|
|
8427
|
+
for (let dy = -offset; dy <= offset; dy++) {
|
|
8428
|
+
for (let dx = -offset; dx <= offset; dx++) {
|
|
8429
|
+
const pixelX = centerPixelX + dx;
|
|
8430
|
+
const pixelY = centerPixelY + dy;
|
|
8431
|
+
// Stay within tile bounds
|
|
8432
|
+
if (pixelX < 0 || pixelX >= width || pixelY < 0 || pixelY >= height) {
|
|
8433
|
+
continue;
|
|
8434
|
+
}
|
|
8435
|
+
const pixelIndex = pixelY * width + pixelX;
|
|
8436
|
+
const elevation = raw[pixelIndex];
|
|
8437
|
+
if (elevation === undefined || elevation === null) {
|
|
8438
|
+
continue;
|
|
8439
|
+
}
|
|
8440
|
+
// Convert pixel to geographic coordinates using WebMercator projection
|
|
8441
|
+
const lon = west + (pixelX / (width - 1)) * (east - west);
|
|
8442
|
+
// Inverse WebMercator transform for latitude
|
|
8443
|
+
const normV = pixelY / (height - 1);
|
|
8444
|
+
const mercatorY = mercatorNorth - normV * (mercatorNorth - mercatorSouth);
|
|
8445
|
+
const lat = (2 * Math.atan(Math.exp(mercatorY)) - Math.PI / 2) * 180 / Math.PI;
|
|
8446
|
+
samples.push({
|
|
8447
|
+
longitude: lon,
|
|
8448
|
+
latitude: lat,
|
|
8449
|
+
elevation,
|
|
8450
|
+
});
|
|
8451
|
+
}
|
|
8452
|
+
}
|
|
8453
|
+
return samples;
|
|
8454
|
+
}
|
|
8455
|
+
catch {
|
|
8456
|
+
return [];
|
|
8457
|
+
}
|
|
8458
|
+
}
|
|
8459
|
+
|
|
8313
8460
|
// src/index.ts
|
|
8314
8461
|
// Initialize global error suppression for deck.gl AbortErrors
|
|
8315
8462
|
suppressGlobalAbortErrors();
|
|
@@ -15523,5 +15670,5 @@ var webimage = /*#__PURE__*/Object.freeze({
|
|
|
15523
15670
|
default: WebImageDecoder
|
|
15524
15671
|
});
|
|
15525
15672
|
|
|
15526
|
-
export { CogBitmapLayer, CogTerrainLayer, CogTiles, GeoImage, suppressGlobalAbortErrors };
|
|
15673
|
+
export { CogBitmapLayer, CogTerrainLayer, CogTiles, GeoImage, extractTerrainCoordinate, sampleTerrainTileCoordinates, suppressGlobalAbortErrors };
|
|
15527
15674
|
//# sourceMappingURL=index.js.map
|