@gisatcz/deckgl-geolib 1.12.0-dev.3 → 1.12.0-dev.5
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 +87 -34
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/index.min.js +1 -1
- package/dist/cjs/index.min.js.map +1 -1
- package/dist/cjs/types/cogbitmaplayer/CogBitmapLayer.d.ts +1 -1
- package/dist/cjs/types/cogtiles/cogtiles.d.ts +21 -2
- package/dist/esm/index.js +87 -34
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.min.js +1 -1
- package/dist/esm/index.min.js.map +1 -1
- package/dist/esm/types/cogbitmaplayer/CogBitmapLayer.d.ts +1 -1
- package/dist/esm/types/cogtiles/cogtiles.d.ts +21 -2
- package/package.json +1 -1
- package/src/cogbitmaplayer/CogBitmapLayer.ts +1 -1
- package/src/cogtiles/cogtiles.ts +99 -36
- package/src/geoimage/geoimage.ts +3 -0
|
@@ -65,7 +65,7 @@ export default class CogBitmapLayer<ExtraPropsT extends {} = {}> extends Composi
|
|
|
65
65
|
getTileData: any;
|
|
66
66
|
renderSubLayers: any;
|
|
67
67
|
updateTriggers: {
|
|
68
|
-
getTileData: (
|
|
68
|
+
getTileData: (number | boolean | ClampToTerrainOptions)[];
|
|
69
69
|
};
|
|
70
70
|
extent: any;
|
|
71
71
|
tileSize: any;
|
|
@@ -83,10 +83,10 @@ declare class CogTiles {
|
|
|
83
83
|
getDataTypeFromTags(image: any): string;
|
|
84
84
|
/**
|
|
85
85
|
* Extracts the noData value from a GeoTIFF.js image.
|
|
86
|
-
* Returns the noData value as a number if available, otherwise undefined.
|
|
86
|
+
* Returns the noData value as a number (including NaN) if available, otherwise undefined.
|
|
87
87
|
*
|
|
88
88
|
* @param {GeoTIFFImage} image - The GeoTIFF.js image.
|
|
89
|
-
* @returns {number|undefined} The noData value
|
|
89
|
+
* @returns {number|undefined} The noData value, possibly NaN, or undefined if not set or invalid.
|
|
90
90
|
*/
|
|
91
91
|
getNoDataValue(image: any): number;
|
|
92
92
|
/**
|
|
@@ -96,6 +96,25 @@ declare class CogTiles {
|
|
|
96
96
|
* @returns {number} The number of channels in the image.
|
|
97
97
|
*/
|
|
98
98
|
getNumberOfChannels(image: any): any;
|
|
99
|
+
/**
|
|
100
|
+
* Calculates the intersection between a tile bounding box and a COG bounding box,
|
|
101
|
+
* returning the intersection window in image pixel space (relative to COG offsets),
|
|
102
|
+
* along with how much blank space (nodata) appears on the left and top of the tile.
|
|
103
|
+
*
|
|
104
|
+
* @param {number[]} tileBbox - Tile bounding box: [minX, minY, maxX, maxY]
|
|
105
|
+
* @param {number[]} cogBbox - COG bounding box: [minX, minY, maxX, maxY]
|
|
106
|
+
* @param {number} offsetXPixel - X offset of the COG origin in pixel space
|
|
107
|
+
* @param {number} offsetYPixel - Y offset of the COG origin in pixel space
|
|
108
|
+
* @param {number} tileSize - Size of the tile in pixels (default: 256)
|
|
109
|
+
* @returns {[number, number, number[] | null, number, number]}
|
|
110
|
+
* An array containing:
|
|
111
|
+
* - width of the intersection
|
|
112
|
+
* - height of the intersection
|
|
113
|
+
* - pixel-space window: [startX, startY, endX, endY] or null if no overlap
|
|
114
|
+
* - missingLeft: padding pixels on the left
|
|
115
|
+
* - missingTop: padding pixels on the top
|
|
116
|
+
*/
|
|
117
|
+
getIntersectionBBox(tileBbox: any, cogBbox: any, offsetXPixel?: number, offsetYPixel?: number, tileSize?: number): any[];
|
|
99
118
|
/**
|
|
100
119
|
* Retrieves the PlanarConfiguration value from a GeoTIFF image.
|
|
101
120
|
*
|
package/package.json
CHANGED
|
@@ -315,7 +315,7 @@ export default class CogBitmapLayer<ExtraPropsT extends {} = {}> extends Composi
|
|
|
315
315
|
// opacity,
|
|
316
316
|
// cogBitmapOptions,
|
|
317
317
|
clampToTerrain,
|
|
318
|
-
cogBitmapOptions,
|
|
318
|
+
cogBitmapOptions.useChannel,
|
|
319
319
|
],
|
|
320
320
|
// renderSubLayers: [cogBitmapOptions],
|
|
321
321
|
},
|
package/src/cogtiles/cogtiles.ts
CHANGED
|
@@ -206,44 +206,37 @@ class CogTiles {
|
|
|
206
206
|
const offsetXPixel = Math.floor(offsetXMap / tileResolution);
|
|
207
207
|
const offsetYPixel = Math.floor(offsetYMap / tileResolution);
|
|
208
208
|
|
|
209
|
-
// Calculate the pixel boundaries for the tile.
|
|
210
|
-
const window = [
|
|
211
|
-
tileX * tileWidth - offsetXPixel, // startX
|
|
212
|
-
tileY * tileHeight - offsetYPixel, // startY
|
|
213
|
-
(tileX + 1) * tileWidth - offsetXPixel, // endX (exclusive)
|
|
214
|
-
(tileY + 1) * tileHeight - offsetYPixel, // endY (exclusive)
|
|
215
|
-
];
|
|
216
|
-
|
|
217
|
-
const [windowStartX, windowStartY, windowEndX, windowEndY] = window;
|
|
218
|
-
|
|
219
209
|
const imageHeight = targetImage.getHeight();
|
|
220
210
|
const imageWidth = targetImage.getWidth();
|
|
221
211
|
|
|
222
|
-
//
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
212
|
+
// approach by comparing bboxes of tile and cog image
|
|
213
|
+
const tilePixelBbox = [
|
|
214
|
+
tileX * tileWidth,
|
|
215
|
+
tileY * tileHeight,
|
|
216
|
+
(tileX + 1) * tileWidth,
|
|
217
|
+
(tileY + 1) * tileHeight,
|
|
218
|
+
];
|
|
219
|
+
|
|
220
|
+
const cogPixelBBox = [
|
|
221
|
+
offsetXPixel,
|
|
222
|
+
offsetYPixel,
|
|
223
|
+
offsetXPixel + imageWidth,
|
|
224
|
+
offsetYPixel + imageHeight,
|
|
225
|
+
];
|
|
226
|
+
|
|
227
|
+
const intersecion = this.getIntersectionBBox(tilePixelBbox, cogPixelBBox, offsetXPixel, offsetYPixel, tileWidth);
|
|
228
|
+
const [validWidth, validHeight, window, missingLeft, missingTop] = intersecion;
|
|
227
229
|
|
|
228
|
-
// Calculate how many pixels are missing from the left and top due to negative windowStart.
|
|
229
|
-
const missingLeft = Math.max(0, 0 - windowStartX);
|
|
230
|
-
const missingTop = Math.max(0, 0 - windowStartY);
|
|
231
230
|
|
|
232
|
-
// Read only the valid window from the image.
|
|
233
|
-
const validWindow = [effectiveStartX, effectiveStartY, effectiveEndX, effectiveEndY];
|
|
234
231
|
|
|
235
232
|
// Read the raster data for the tile window with shifted origin.
|
|
236
|
-
if (missingLeft > 0 || missingTop > 0) {
|
|
233
|
+
if (missingLeft > 0 || missingTop > 0 || validWidth < tileWidth || validHeight < tileHeight) {
|
|
237
234
|
// Prepare the final tile buffer and fill it with noDataValue.
|
|
238
235
|
const tileBuffer = this.createTileBuffer(this.options.format, tileWidth);
|
|
239
236
|
tileBuffer.fill(this.options.noDataValue);
|
|
240
237
|
|
|
241
|
-
// Calculate the width of the valid window.
|
|
242
|
-
const validWidth = Math.min(imageWidth, effectiveEndX - effectiveStartX);
|
|
243
|
-
const validHeight = Math.min(imageHeight, effectiveEndY - effectiveStartY);
|
|
244
|
-
|
|
245
238
|
// if the valid window is smaller than tile size, it gets the image size width and height, thus validRasterData.width must be used as below
|
|
246
|
-
const validRasterData = await targetImage.readRasters({ window
|
|
239
|
+
const validRasterData = await targetImage.readRasters({ window });
|
|
247
240
|
|
|
248
241
|
// FOR MULTI-BAND - the result is one array with sequentially typed bands, firstly all data for the band 0, then for band 1
|
|
249
242
|
// I think this is less practical then the commented solution above, but I do it so it works with the code in geoimage.ts in deck.gl-geoimage in function getColorValue.
|
|
@@ -335,29 +328,43 @@ class CogTiles {
|
|
|
335
328
|
|
|
336
329
|
/**
|
|
337
330
|
* Extracts the noData value from a GeoTIFF.js image.
|
|
338
|
-
* Returns the noData value as a number if available, otherwise undefined.
|
|
331
|
+
* Returns the noData value as a number (including NaN) if available, otherwise undefined.
|
|
339
332
|
*
|
|
340
333
|
* @param {GeoTIFFImage} image - The GeoTIFF.js image.
|
|
341
|
-
* @returns {number|undefined} The noData value
|
|
334
|
+
* @returns {number|undefined} The noData value, possibly NaN, or undefined if not set or invalid.
|
|
342
335
|
*/
|
|
343
336
|
getNoDataValue(image) {
|
|
344
|
-
// Attempt to retrieve the noData value via the GDAL method.
|
|
345
337
|
const noDataRaw = image.getGDALNoData();
|
|
346
338
|
|
|
347
339
|
if (noDataRaw === undefined || noDataRaw === null) {
|
|
348
|
-
console.
|
|
349
|
-
// No noData value is defined
|
|
340
|
+
console.warn('No noData value defined — raster might be rendered incorrectly.');
|
|
350
341
|
return undefined;
|
|
351
342
|
}
|
|
352
343
|
|
|
353
|
-
|
|
354
|
-
// Clean up the string by removing any null characters or extra whitespace.
|
|
355
|
-
const cleanedValue = String(noDataRaw).replace(/\0/g, '').trim();
|
|
344
|
+
const cleaned = String(noDataRaw).replace(/\0/g, '').trim();
|
|
356
345
|
|
|
357
|
-
|
|
358
|
-
|
|
346
|
+
if (cleaned === '') {
|
|
347
|
+
console.warn('noData value is an empty string after cleanup.');
|
|
348
|
+
return undefined;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
const parsed = Number(cleaned);
|
|
352
|
+
|
|
353
|
+
// Allow NaN if explicitly declared
|
|
354
|
+
if (cleaned.toLowerCase() === 'nan') {
|
|
355
|
+
return NaN;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// If not declared as "nan" and still parsed to NaN, it's an error
|
|
359
|
+
if (Number.isNaN(parsed)) {
|
|
360
|
+
console.warn(`Failed to parse numeric noData value: '${cleaned}'`);
|
|
361
|
+
return undefined;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
return parsed;
|
|
359
365
|
}
|
|
360
366
|
|
|
367
|
+
|
|
361
368
|
/**
|
|
362
369
|
* Retrieves the number of channels (samples per pixel) in a GeoTIFF image.
|
|
363
370
|
*
|
|
@@ -368,6 +375,62 @@ class CogTiles {
|
|
|
368
375
|
return image.getSamplesPerPixel();
|
|
369
376
|
}
|
|
370
377
|
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Calculates the intersection between a tile bounding box and a COG bounding box,
|
|
381
|
+
* returning the intersection window in image pixel space (relative to COG offsets),
|
|
382
|
+
* along with how much blank space (nodata) appears on the left and top of the tile.
|
|
383
|
+
*
|
|
384
|
+
* @param {number[]} tileBbox - Tile bounding box: [minX, minY, maxX, maxY]
|
|
385
|
+
* @param {number[]} cogBbox - COG bounding box: [minX, minY, maxX, maxY]
|
|
386
|
+
* @param {number} offsetXPixel - X offset of the COG origin in pixel space
|
|
387
|
+
* @param {number} offsetYPixel - Y offset of the COG origin in pixel space
|
|
388
|
+
* @param {number} tileSize - Size of the tile in pixels (default: 256)
|
|
389
|
+
* @returns {[number, number, number[] | null, number, number]}
|
|
390
|
+
* An array containing:
|
|
391
|
+
* - width of the intersection
|
|
392
|
+
* - height of the intersection
|
|
393
|
+
* - pixel-space window: [startX, startY, endX, endY] or null if no overlap
|
|
394
|
+
* - missingLeft: padding pixels on the left
|
|
395
|
+
* - missingTop: padding pixels on the top
|
|
396
|
+
*/
|
|
397
|
+
getIntersectionBBox(tileBbox, cogBbox, offsetXPixel = 0, offsetYPixel = 0, tileSize = 256) {
|
|
398
|
+
const interLeft = Math.max(tileBbox[0], cogBbox[0]);
|
|
399
|
+
const interTop = Math.max(tileBbox[1], cogBbox[1]);
|
|
400
|
+
const interRight = Math.min(tileBbox[2], cogBbox[2]);
|
|
401
|
+
const interBottom = Math.min(tileBbox[3], cogBbox[3]);
|
|
402
|
+
|
|
403
|
+
const width = Math.max(0, interRight - interLeft);
|
|
404
|
+
const height = Math.max(0, interBottom - interTop);
|
|
405
|
+
|
|
406
|
+
let window = null;
|
|
407
|
+
let missingLeft = 0;
|
|
408
|
+
let missingTop = 0;
|
|
409
|
+
|
|
410
|
+
if (width > 0 && height > 0) {
|
|
411
|
+
window = [
|
|
412
|
+
interLeft - offsetXPixel,
|
|
413
|
+
interTop - offsetYPixel,
|
|
414
|
+
interRight - offsetXPixel,
|
|
415
|
+
interBottom - offsetYPixel,
|
|
416
|
+
];
|
|
417
|
+
|
|
418
|
+
// Padding from the tile origin to valid data start
|
|
419
|
+
missingLeft = interLeft - tileBbox[0];
|
|
420
|
+
missingTop = interTop - tileBbox[1];
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
return [
|
|
424
|
+
width,
|
|
425
|
+
height,
|
|
426
|
+
window,
|
|
427
|
+
missingLeft,
|
|
428
|
+
missingTop,
|
|
429
|
+
];
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
|
|
371
434
|
/**
|
|
372
435
|
* Retrieves the PlanarConfiguration value from a GeoTIFF image.
|
|
373
436
|
*
|
package/src/geoimage/geoimage.ts
CHANGED
|
@@ -423,6 +423,8 @@ export default class GeoImage {
|
|
|
423
423
|
}
|
|
424
424
|
|
|
425
425
|
getColorValue(dataArray:[], options:GeoImageOptions, arrayLength:number, numOfChannels = 1) {
|
|
426
|
+
// const rgb = chroma.random().rgb(); // [R, G, B]
|
|
427
|
+
// const randomColor = [...rgb, 120];
|
|
426
428
|
const colorScale = chroma.scale(options.colorScale).domain(options.colorScaleValueRange);
|
|
427
429
|
// channel index is equal to channel number - 1
|
|
428
430
|
let pixel:number = options.useChannelIndex === null ? 0 : options.useChannelIndex;
|
|
@@ -443,6 +445,7 @@ export default class GeoImage {
|
|
|
443
445
|
|
|
444
446
|
for (let i = 0; i < arrayLength; i += 4) {
|
|
445
447
|
let pixelColor = options.nullColor;
|
|
448
|
+
// let pixelColor = randomColor;
|
|
446
449
|
// FIXME
|
|
447
450
|
// eslint-disable-next-line max-len
|
|
448
451
|
if ((!Number.isNaN(dataArray[pixel])) && (options.noDataValue === undefined || dataArray[pixel] !== options.noDataValue)) {
|