@gisatcz/deckgl-geolib 1.12.0-dev.4 → 2.0.0

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.
Files changed (48) hide show
  1. package/README.md +67 -64
  2. package/dist/cjs/index.js +631 -641
  3. package/dist/cjs/index.js.map +1 -1
  4. package/dist/cjs/index.min.js +3 -3
  5. package/dist/cjs/index.min.js.map +1 -1
  6. package/dist/{esm/types/cogtiles/cogtiles.d.ts → cjs/types/core/CogTiles.d.ts} +12 -9
  7. package/dist/cjs/types/{geoimage/geoimage.d.ts → core/GeoImage.d.ts} +6 -6
  8. package/dist/cjs/types/core/index.d.ts +2 -0
  9. package/dist/cjs/types/index.d.ts +2 -11
  10. package/dist/{esm/types/cogbitmaplayer → cjs/types/layers}/CogBitmapLayer.d.ts +3 -5
  11. package/dist/cjs/types/{cogterrainlayer → layers}/CogTerrainLayer.d.ts +13 -8
  12. package/dist/cjs/types/layers/index.d.ts +2 -0
  13. package/dist/esm/index.js +628 -641
  14. package/dist/esm/index.js.map +1 -1
  15. package/dist/esm/index.min.js +3 -3
  16. package/dist/esm/index.min.js.map +1 -1
  17. package/dist/{cjs/types/cogtiles/cogtiles.d.ts → esm/types/core/CogTiles.d.ts} +12 -9
  18. package/dist/esm/types/{geoimage/geoimage.d.ts → core/GeoImage.d.ts} +6 -6
  19. package/dist/esm/types/core/index.d.ts +2 -0
  20. package/dist/esm/types/index.d.ts +2 -11
  21. package/dist/{cjs/types/cogbitmaplayer → esm/types/layers}/CogBitmapLayer.d.ts +3 -5
  22. package/dist/esm/types/{cogterrainlayer → layers}/CogTerrainLayer.d.ts +13 -8
  23. package/dist/esm/types/layers/index.d.ts +2 -0
  24. package/package.json +40 -4
  25. package/.eslintignore +0 -2
  26. package/.eslintrc.cjs +0 -3
  27. package/CHANGELOG.md +0 -166
  28. package/rollup.config.mjs +0 -77
  29. package/src/cogbitmaplayer/CogBitmapLayer.ts +0 -337
  30. package/src/cogbitmaplayer/README.md +0 -113
  31. package/src/cogterrainlayer/CogTerrainLayer.ts +0 -445
  32. package/src/cogterrainlayer/README.md +0 -118
  33. package/src/cogtiles/README.md +0 -72
  34. package/src/cogtiles/cogtiles.ts +0 -420
  35. package/src/cogtiles/lzw.js +0 -256
  36. package/src/geoimage/README.md +0 -129
  37. package/src/geoimage/delatin/index.ts +0 -495
  38. package/src/geoimage/geoimage.ts +0 -599
  39. package/src/geoimage/helpers/skirt.ts +0 -171
  40. package/src/index.ts +0 -11
  41. package/src/utilities/tileurls.ts +0 -21
  42. package/tsconfig.json +0 -6
  43. /package/dist/cjs/types/{geoimage → core}/delatin/index.d.ts +0 -0
  44. /package/dist/cjs/types/{geoimage → core}/helpers/skirt.d.ts +0 -0
  45. /package/dist/cjs/types/{utilities → utils}/tileurls.d.ts +0 -0
  46. /package/dist/esm/types/{geoimage → core}/delatin/index.d.ts +0 -0
  47. /package/dist/esm/types/{geoimage → core}/helpers/skirt.d.ts +0 -0
  48. /package/dist/esm/types/{utilities → utils}/tileurls.d.ts +0 -0
package/dist/cjs/index.js CHANGED
@@ -9,33 +9,6 @@ var schema = require('@loaders.gl/schema');
9
9
  var loaderUtils = require('@loaders.gl/loader-utils');
10
10
  var meshLayers = require('@deck.gl/mesh-layers');
11
11
 
12
- /******************************************************************************
13
- Copyright (c) Microsoft Corporation.
14
-
15
- Permission to use, copy, modify, and/or distribute this software for any
16
- purpose with or without fee is hereby granted.
17
-
18
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
19
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
20
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
21
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
22
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
23
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
24
- PERFORMANCE OF THIS SOFTWARE.
25
- ***************************************************************************** */
26
- /* global Reflect, Promise */
27
-
28
-
29
- function __awaiter(thisArg, _arguments, P, generator) {
30
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
31
- return new (P || (P = Promise))(function (resolve, reject) {
32
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
33
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
34
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
35
- step((generator = generator.apply(thisArg, _arguments || [])).next());
36
- });
37
- }
38
-
39
12
  /* eslint-disable no-restricted-globals, no-restricted-syntax */
40
13
  /* global SharedArrayBuffer */
41
14
 
@@ -165,6 +138,12 @@ uncurryThisGetter(
165
138
  SymbolToStringTag
166
139
  );
167
140
 
141
+ // Uint8Array
142
+ const NativeUint8Array = Uint8Array;
143
+
144
+ // Uint16Array
145
+ const NativeUint16Array = Uint16Array;
146
+
168
147
  // Uint32Array
169
148
  const NativeUint32Array = Uint32Array;
170
149
 
@@ -194,7 +173,6 @@ const DataViewPrototypeGetUint16 = uncurryThis(
194
173
  // WeakMap
195
174
  /**
196
175
  * Do not construct with arguments to avoid calling the "set" method
197
- *
198
176
  * @type {{new <K extends {}, V>(): WeakMap<K, V>}}
199
177
  */
200
178
  const NativeWeakMap = WeakMap;
@@ -224,7 +202,6 @@ const SafeIteratorPrototype = ObjectCreate(null, {
224
202
 
225
203
  /**
226
204
  * Wrap the Array around the SafeIterator If Array.prototype [@@iterator] has been modified
227
- *
228
205
  * @type {<T>(array: T[]) => Iterable<T>}
229
206
  */
230
207
  function safeIfNeeded(array) {
@@ -265,21 +242,20 @@ for (const key of ReflectOwnKeys(ArrayIteratorPrototype)) {
265
242
  ObjectDefineProperty(DummyArrayIteratorPrototype, key, ReflectGetOwnPropertyDescriptor(ArrayIteratorPrototype, key));
266
243
  }
267
244
 
268
- // algorithm: http://fox-toolkit.org/ftp/fasthalffloatconversion.pdf
269
-
245
+ // base algorithm: http://fox-toolkit.org/ftp/fasthalffloatconversion.pdf
270
246
 
271
247
  const buffer = new NativeArrayBuffer(4);
272
248
  const floatView = new NativeFloat32Array(buffer);
273
249
  const uint32View = new NativeUint32Array(buffer);
274
250
 
275
- const baseTable = new NativeUint32Array(512);
276
- const shiftTable = new NativeUint32Array(512);
251
+ const baseTable = new NativeUint16Array(512);
252
+ const shiftTable = new NativeUint8Array(512);
277
253
 
278
254
  for (let i = 0; i < 256; ++i) {
279
255
  const e = i - 127;
280
256
 
281
257
  // very small number (0, -0)
282
- if (e < -27) {
258
+ if (e < -24) {
283
259
  baseTable[i] = 0x0000;
284
260
  baseTable[i | 0x100] = 0x8000;
285
261
  shiftTable[i] = 24;
@@ -316,21 +292,18 @@ for (let i = 0; i < 256; ++i) {
316
292
  }
317
293
 
318
294
  const mantissaTable = new NativeUint32Array(2048);
319
- const exponentTable = new NativeUint32Array(64);
320
- const offsetTable = new NativeUint32Array(64);
321
-
322
295
  for (let i = 1; i < 1024; ++i) {
323
- let m = i << 13; // zero pad mantissa bits
324
- let e = 0; // zero exponent
296
+ let m = i << 13; // zero pad mantissa bits
297
+ let e = 0; // zero exponent
325
298
 
326
299
  // normalized
327
- while((m & 0x00800000) === 0) {
300
+ while ((m & 0x00800000) === 0) {
328
301
  m <<= 1;
329
- e -= 0x00800000; // decrement exponent
302
+ e -= 0x00800000; // decrement exponent
330
303
  }
331
304
 
332
- m &= ~0x00800000; // clear leading 1 bit
333
- e += 0x38800000; // adjust bias
305
+ m &= ~0x00800000; // clear leading 1 bit
306
+ e += 0x38800000; // adjust bias
334
307
 
335
308
  mantissaTable[i] = m | e;
336
309
  }
@@ -338,6 +311,7 @@ for (let i = 1024; i < 2048; ++i) {
338
311
  mantissaTable[i] = 0x38000000 + ((i - 1024) << 13);
339
312
  }
340
313
 
314
+ const exponentTable = new NativeUint32Array(64);
341
315
  for (let i = 1; i < 31; ++i) {
342
316
  exponentTable[i] = i << 23;
343
317
  }
@@ -348,6 +322,7 @@ for (let i = 33; i < 63; ++i) {
348
322
  }
349
323
  exponentTable[63] = 0xc7800000;
350
324
 
325
+ const offsetTable = new NativeUint16Array(64);
351
326
  for (let i = 1; i < 64; ++i) {
352
327
  if (i !== 32) {
353
328
  offsetTable[i] = 1024;
@@ -356,19 +331,17 @@ for (let i = 1; i < 64; ++i) {
356
331
 
357
332
  /**
358
333
  * convert a half float number bits to a number
359
- *
360
334
  * @param {number} float16bits - half float number bits
361
335
  * @returns {number} double float
362
336
  */
363
337
  function convertToNumber(float16bits) {
364
- const m = float16bits >> 10;
365
- uint32View[0] = mantissaTable[offsetTable[m] + (float16bits & 0x3ff)] + exponentTable[m];
338
+ const i = float16bits >> 10;
339
+ uint32View[0] = mantissaTable[offsetTable[i] + (float16bits & 0x3ff)] + exponentTable[i];
366
340
  return floatView[0];
367
341
  }
368
342
 
369
343
  /**
370
344
  * returns an unsigned 16-bit float at the specified byte offset from the start of the DataView
371
- *
372
345
  * @param {DataView} dataView
373
346
  * @param {number} byteOffset
374
347
  * @param {[boolean]} opts
@@ -2638,6 +2611,8 @@ class QuickLRU extends Map {
2638
2611
  } else {
2639
2612
  this._set(key, {value, expiry});
2640
2613
  }
2614
+
2615
+ return this;
2641
2616
  }
2642
2617
 
2643
2618
  has(key) {
@@ -4436,6 +4411,29 @@ class Tile {
4436
4411
  // loaders.gl
4437
4412
  // SPDX-License-Identifier: MIT
4438
4413
  // Copyright (c) vis.gl contributors
4414
+ /**
4415
+ * Get geometry edges that located on a border of the mesh
4416
+ * @param {object} indices - edge indices from quantized mesh data
4417
+ * @param {TypedArray} position - position attribute geometry data
4418
+ * @returns {number[][]} - outside edges data
4419
+ */
4420
+ function getOutsideEdgesFromIndices(indices, position) {
4421
+ // Sort skirt indices to create adjacent triangles
4422
+ indices.westIndices.sort((a, b) => position[3 * a + 1] - position[3 * b + 1]);
4423
+ // Reverse (b - a) to match triangle winding
4424
+ indices.eastIndices.sort((a, b) => position[3 * b + 1] - position[3 * a + 1]);
4425
+ indices.southIndices.sort((a, b) => position[3 * b] - position[3 * a]);
4426
+ // Reverse (b - a) to match triangle winding
4427
+ indices.northIndices.sort((a, b) => position[3 * a] - position[3 * b]);
4428
+ const edges = [];
4429
+ for (const index in indices) {
4430
+ const indexGroup = indices[index];
4431
+ for (let i = 0; i < indexGroup.length - 1; i++) {
4432
+ edges.push([indexGroup[i], indexGroup[i + 1]]);
4433
+ }
4434
+ }
4435
+ return edges;
4436
+ }
4439
4437
  /**
4440
4438
  * Add skirt to existing mesh
4441
4439
  * @param {object} attributes - POSITION and TEXCOOD_0 attributes data
@@ -4481,7 +4479,6 @@ function addSkirt(attributes, triangles, skirtHeight, outsideIndices) {
4481
4479
  * @returns {number[][]} - outside edges data
4482
4480
  */
4483
4481
  function getOutsideEdgesFromTriangles(triangles) {
4484
- var _a, _b;
4485
4482
  const edges = [];
4486
4483
  for (let i = 0; i < triangles.length; i += 3) {
4487
4484
  edges.push([triangles[i], triangles[i + 1]]);
@@ -4492,7 +4489,7 @@ function getOutsideEdgesFromTriangles(triangles) {
4492
4489
  const outsideEdges = [];
4493
4490
  let index = 0;
4494
4491
  while (index < edges.length) {
4495
- if (edges[index][0] === ((_a = edges[index + 1]) === null || _a === void 0 ? void 0 : _a[1]) && edges[index][1] === ((_b = edges[index + 1]) === null || _b === void 0 ? void 0 : _b[0])) {
4492
+ if (edges[index][0] === edges[index + 1]?.[1] && edges[index][1] === edges[index + 1]?.[0]) {
4496
4493
  index += 2;
4497
4494
  }
4498
4495
  else {
@@ -4502,29 +4499,6 @@ function getOutsideEdgesFromTriangles(triangles) {
4502
4499
  }
4503
4500
  return outsideEdges;
4504
4501
  }
4505
- /**
4506
- * Get geometry edges that located on a border of the mesh
4507
- * @param {object} indices - edge indices from quantized mesh data
4508
- * @param {TypedArray} position - position attribute geometry data
4509
- * @returns {number[][]} - outside edges data
4510
- */
4511
- function getOutsideEdgesFromIndices(indices, position) {
4512
- // Sort skirt indices to create adjacent triangles
4513
- indices.westIndices.sort((a, b) => position[3 * a + 1] - position[3 * b + 1]);
4514
- // Reverse (b - a) to match triangle winding
4515
- indices.eastIndices.sort((a, b) => position[3 * b + 1] - position[3 * a + 1]);
4516
- indices.southIndices.sort((a, b) => position[3 * b] - position[3 * a]);
4517
- // Reverse (b - a) to match triangle winding
4518
- indices.northIndices.sort((a, b) => position[3 * a] - position[3 * b]);
4519
- const edges = [];
4520
- for (const index in indices) {
4521
- const indexGroup = indices[index];
4522
- for (let i = 0; i < indexGroup.length - 1; i++) {
4523
- edges.push([indexGroup[i], indexGroup[i + 1]]);
4524
- }
4525
- }
4526
- return edges;
4527
- }
4528
4502
  /**
4529
4503
  * Get geometry edges that located on a border of the mesh
4530
4504
  * @param {object} args
@@ -4565,7 +4539,12 @@ function updateAttributesForNewEdge({ edge, edgeIndex, attributes, skirtHeight,
4565
4539
  // Copyright (c) vis.gl contributors
4566
4540
  // ISC License
4567
4541
  // Copyright(c) 2019, Michael Fogleman, Vladimir Agafonkin
4542
+ /* eslint-disable @typescript-eslint/ban-ts-comment */
4568
4543
  // @ts-nocheck
4544
+ /* eslint-enable @typescript-eslint/ban-ts-comment */
4545
+ function orient(ax, ay, bx, by, cx, cy) {
4546
+ return (bx - cx) * (ay - cy) - (by - cy) * (ax - cx);
4547
+ }
4569
4548
  /* eslint-disable complexity, max-params, max-statements, max-depth, no-constant-condition */
4570
4549
  class Delatin {
4571
4550
  constructor(data, width, height = width) {
@@ -4953,9 +4932,6 @@ class Delatin {
4953
4932
  return i > i0;
4954
4933
  }
4955
4934
  }
4956
- function orient(ax, ay, bx, by, cx, cy) {
4957
- return (bx - cx) * (ay - cy) - (by - cy) * (ax - cx);
4958
- }
4959
4935
  function inCircle(ax, ay, bx, by, cx, cy, px, py) {
4960
4936
  const dx = ax - px;
4961
4937
  const dy = ay - py;
@@ -4969,7 +4945,7 @@ function inCircle(ax, ay, bx, by, cx, cy, px, py) {
4969
4945
  return dx * (ey * cp - bp * fy) - dy * (ex * cp - bp * fx) + ap * (ex * fy - ey * fx) < 0;
4970
4946
  }
4971
4947
 
4972
- /* eslint 'max-len': [1, { code: 105, comments: 999, ignoreStrings: true, ignoreUrls: true }] */
4948
+ // import { ExtentsLeftBottomRightTop } from '@deck.gl/core/utils/positions';
4973
4949
  // FIXME - tesselator as a parameter
4974
4950
  const tesselator = 'martini';
4975
4951
  const DefaultGeoImageOptions = {
@@ -5004,279 +4980,264 @@ const DefaultGeoImageOptions = {
5004
4980
  planarConfig: undefined,
5005
4981
  };
5006
4982
  class GeoImage {
5007
- constructor() {
5008
- this.scale = (num, inMin, inMax, outMin, outMax) => ((num - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin;
5009
- }
5010
- setUrl(url) {
5011
- return __awaiter(this, void 0, void 0, function* () {
5012
- // TODO - not tested
5013
- const response = yield fetch(url);
5014
- const arrayBuffer = yield response.arrayBuffer();
5015
- const tiff = yield fromArrayBuffer(arrayBuffer);
5016
- const data = yield tiff.getImage(0);
5017
- this.data = data;
5018
- });
5019
- }
5020
- getMap(input, options, meshMaxError) {
5021
- return __awaiter(this, void 0, void 0, function* () {
5022
- const mergedOptions = Object.assign(Object.assign({}, DefaultGeoImageOptions), options);
5023
- switch (mergedOptions.type) {
5024
- case 'image':
5025
- return this.getBitmap(input, mergedOptions);
5026
- case 'terrain':
5027
- return this.getHeightmap(input, mergedOptions, meshMaxError);
5028
- default:
5029
- return null;
5030
- }
5031
- });
4983
+ data;
4984
+ scale = (num, inMin, inMax, outMin, outMax) => ((num - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin;
4985
+ async setUrl(url) {
4986
+ // TODO - not tested
4987
+ const response = await fetch(url);
4988
+ const arrayBuffer = await response.arrayBuffer();
4989
+ const tiff = await fromArrayBuffer(arrayBuffer);
4990
+ const data = await tiff.getImage(0);
4991
+ this.data = data;
4992
+ }
4993
+ async getMap(input, options, meshMaxError) {
4994
+ const mergedOptions = { ...DefaultGeoImageOptions, ...options };
4995
+ switch (mergedOptions.type) {
4996
+ case 'image':
4997
+ return this.getBitmap(input, mergedOptions);
4998
+ case 'terrain':
4999
+ return this.getHeightmap(input, mergedOptions, meshMaxError);
5000
+ default:
5001
+ return null;
5002
+ }
5032
5003
  }
5033
5004
  // GetHeightmap uses only "useChannel" and "multiplier" options
5034
- getHeightmap(input, options, meshMaxError) {
5035
- var _a;
5036
- return __awaiter(this, void 0, void 0, function* () {
5037
- let rasters = [];
5038
- let width;
5039
- let height;
5040
- if (typeof (input) === 'string') {
5041
- // TODO not tested
5042
- // input is type of object
5043
- yield this.setUrl(input);
5044
- rasters = (yield this.data.readRasters());
5045
- width = this.data.getWidth();
5046
- height = this.data.getHeight();
5005
+ async getHeightmap(input, options, meshMaxError) {
5006
+ let rasters = [];
5007
+ let width;
5008
+ let height;
5009
+ if (typeof (input) === 'string') {
5010
+ // TODO not tested
5011
+ // input is type of object
5012
+ await this.setUrl(input);
5013
+ rasters = (await this.data.readRasters());
5014
+ width = this.data.getWidth();
5015
+ height = this.data.getHeight();
5016
+ }
5017
+ else {
5018
+ rasters = input.rasters;
5019
+ width = input.width;
5020
+ height = input.height;
5021
+ }
5022
+ const optionsLocal = { ...options };
5023
+ let channel = rasters[0];
5024
+ optionsLocal.useChannelIndex ??= optionsLocal.useChannel == null ? null : optionsLocal.useChannel - 1;
5025
+ if (options.useChannelIndex != null) {
5026
+ if (rasters[optionsLocal.useChannelIndex]) {
5027
+ channel = rasters[optionsLocal.useChannelIndex];
5047
5028
  }
5048
- else {
5049
- rasters = input.rasters;
5050
- width = input.width;
5051
- height = input.height;
5029
+ }
5030
+ const terrain = new Float32Array((width + 1) * (height + 1));
5031
+ const numOfChannels = channel.length / (width * height);
5032
+ let pixel = options.useChannelIndex === null ? 0 : options.useChannelIndex;
5033
+ for (let i = 0, y = 0; y < height; y++) {
5034
+ for (let x = 0; x < width; x++, i++) {
5035
+ const elevationValue = (options.noDataValue && channel[pixel] === options.noDataValue) ? options.terrainMinValue : channel[pixel] * options.multiplier;
5036
+ terrain[i + y] = elevationValue;
5037
+ pixel += numOfChannels;
5052
5038
  }
5053
- const optionsLocal = Object.assign({}, options);
5054
- let channel = rasters[0];
5055
- (_a = optionsLocal.useChannelIndex) !== null && _a !== void 0 ? _a : (optionsLocal.useChannelIndex = optionsLocal.useChannel == null ? null : optionsLocal.useChannel - 1);
5056
- if (options.useChannelIndex != null) {
5057
- if (rasters[optionsLocal.useChannelIndex]) {
5058
- channel = rasters[optionsLocal.useChannelIndex];
5059
- }
5039
+ }
5040
+ {
5041
+ // backfill bottom border
5042
+ for (let i = (width + 1) * width, x = 0; x < width; x++, i++) {
5043
+ terrain[i] = terrain[i - width - 1];
5060
5044
  }
5061
- const terrain = new Float32Array((width + 1) * (height + 1));
5062
- const numOfChannels = channel.length / (width * height);
5063
- let pixel = options.useChannelIndex === null ? 0 : options.useChannelIndex;
5064
- for (let i = 0, y = 0; y < height; y++) {
5065
- for (let x = 0; x < width; x++, i++) {
5066
- const elevationValue = (options.noDataValue && channel[pixel] === options.noDataValue) ? options.terrainMinValue : channel[pixel] * options.multiplier;
5067
- terrain[i + y] = elevationValue;
5068
- pixel += numOfChannels;
5069
- }
5045
+ // backfill right border
5046
+ for (let i = height, y = 0; y < height + 1; y++, i += height + 1) {
5047
+ terrain[i] = terrain[i - 1];
5070
5048
  }
5071
- {
5072
- // backfill bottom border
5073
- for (let i = (width + 1) * width, x = 0; x < width; x++, i++) {
5074
- terrain[i] = terrain[i - width - 1];
5075
- }
5076
- // backfill right border
5077
- for (let i = height, y = 0; y < height + 1; y++, i += height + 1) {
5078
- terrain[i] = terrain[i - 1];
5079
- }
5080
- }
5081
- // getMesh
5082
- const { terrainSkirtHeight } = options;
5083
- let mesh;
5084
- switch (tesselator) {
5085
- case 'martini':
5049
+ }
5050
+ // getMesh
5051
+ const { terrainSkirtHeight } = options;
5052
+ let mesh;
5053
+ switch (tesselator) {
5054
+ case 'martini':
5055
+ mesh = getMartiniTileMesh(meshMaxError, width, terrain);
5056
+ break;
5057
+ case 'delatin':
5058
+ mesh = getDelatinTileMesh(meshMaxError, width, height, terrain);
5059
+ break;
5060
+ default:
5061
+ if (width === height && !(height && (width - 1))) {
5062
+ // fixme get terrain to separate method
5063
+ // terrain = getTerrain(data, width, height, elevationDecoder, 'martini');
5086
5064
  mesh = getMartiniTileMesh(meshMaxError, width, terrain);
5087
- break;
5088
- case 'delatin':
5065
+ }
5066
+ else {
5067
+ // fixme get terrain to separate method
5068
+ // terrain = getTerrain(data, width, height, elevationDecoder, 'delatin');
5089
5069
  mesh = getDelatinTileMesh(meshMaxError, width, height, terrain);
5090
- break;
5091
- default:
5092
- if (width === height && !(height && (width - 1))) {
5093
- // fixme get terrain to separate method
5094
- // terrain = getTerrain(data, width, height, elevationDecoder, 'martini');
5095
- mesh = getMartiniTileMesh(meshMaxError, width, terrain);
5096
- }
5097
- else {
5098
- // fixme get terrain to separate method
5099
- // terrain = getTerrain(data, width, height, elevationDecoder, 'delatin');
5100
- mesh = getDelatinTileMesh(meshMaxError, width, height, terrain);
5101
- }
5102
- break;
5103
- }
5104
- // Martini
5105
- // Martini
5106
- // Delatin
5107
- // Delatin
5108
- const { vertices } = mesh;
5109
- let { triangles } = mesh;
5110
- let attributes = getMeshAttributes(vertices, terrain, width, height, input.bounds);
5111
- // Compute bounding box before adding skirt so that z values are not skewed
5112
- const boundingBox = schema.getMeshBoundingBox(attributes);
5113
- if (terrainSkirtHeight) {
5114
- const { attributes: newAttributes, triangles: newTriangles } = addSkirt(attributes, triangles, terrainSkirtHeight);
5115
- attributes = newAttributes;
5116
- triangles = newTriangles;
5117
- }
5118
- return {
5119
- // Data return by this loader implementation
5120
- loaderData: {
5121
- header: {},
5122
- },
5123
- header: {
5124
- vertexCount: triangles.length,
5125
- boundingBox,
5126
- },
5127
- mode: 4,
5128
- indices: { value: Uint32Array.from(triangles), size: 1 },
5129
- attributes,
5130
- };
5131
- });
5132
- }
5133
- getBitmap(input, options) {
5134
- var _a;
5135
- return __awaiter(this, void 0, void 0, function* () {
5136
- // console.time('bitmap-generated-in');
5137
- // const optionsLocal = { ...options };
5138
- const optionsLocal = Object.assign({}, options);
5139
- let rasters = [];
5140
- let channels;
5141
- let width;
5142
- let height;
5143
- if (typeof (input) === 'string') {
5144
- // TODO not tested
5145
- // input is type of object
5146
- yield this.setUrl(input);
5147
- rasters = (yield this.data.readRasters());
5148
- channels = rasters.length;
5149
- width = this.data.getWidth();
5150
- height = this.data.getHeight();
5151
- }
5152
- else {
5153
- rasters = input.rasters;
5154
- channels = rasters.length;
5155
- width = input.width;
5156
- height = input.height;
5157
- }
5158
- const canvas = document.createElement('canvas');
5159
- canvas.width = width;
5160
- canvas.height = height;
5161
- const c = canvas.getContext('2d');
5162
- const imageData = c.createImageData(width, height);
5163
- let r;
5164
- let g;
5165
- let b;
5166
- let a;
5167
- const size = width * height * 4;
5168
- // const size = width * height;
5169
- // if (!options.noDataValue) {
5170
- // console.log('Missing noData value. Raster might be displayed incorrectly.');
5171
- // }
5172
- optionsLocal.unidentifiedColor = this.getColorFromChromaType(optionsLocal.unidentifiedColor);
5173
- optionsLocal.nullColor = this.getColorFromChromaType(optionsLocal.nullColor);
5174
- optionsLocal.clippedColor = this.getColorFromChromaType(optionsLocal.clippedColor);
5175
- optionsLocal.color = this.getColorFromChromaType(optionsLocal.color);
5176
- (_a = optionsLocal.useChannelIndex) !== null && _a !== void 0 ? _a : (optionsLocal.useChannelIndex = options.useChannel === null ? null : options.useChannel - 1);
5177
- // console.log(rasters[0])
5178
- /* console.log("raster 0 length: " + rasters[0].length)
5179
- console.log("image width: " + width)
5180
- console.log("channels: " + channels)
5181
- console.log("format: " + rasters[0].length / (width * height))
5182
- */
5183
- if (optionsLocal.useChannelIndex == null) {
5184
- if (channels === 1) {
5185
- if (rasters[0].length / (width * height) === 1) {
5186
- const channel = rasters[0];
5187
- // AUTO RANGE
5188
- if (optionsLocal.useAutoRange) {
5189
- optionsLocal.colorScaleValueRange = this.getMinMax(channel, optionsLocal);
5190
- // console.log('data min: ' + optionsLocal.rangeMin + ', max: ' + optionsLocal.rangeMax);
5191
- }
5192
- // SINGLE CHANNEL
5193
- const colorData = this.getColorValue(channel, optionsLocal, size);
5194
- colorData.forEach((value, index) => {
5195
- imageData.data[index] = value;
5196
- });
5197
- }
5198
- // RGB values in one channel
5199
- if (rasters[0].length / (width * height) === 3) {
5200
- // console.log("geoImage: " + "RGB 1 array of length: " + rasters[0].length);
5201
- let pixel = 0;
5202
- for (let idx = 0; idx < size; idx += 4) {
5203
- const rgbColor = [rasters[0][pixel], rasters[0][pixel + 1], rasters[0][pixel + 2]];
5204
- const rgbaColor = this.hasPixelsNoData(rgbColor, optionsLocal.noDataValue)
5205
- ? optionsLocal.nullColor
5206
- : [...rgbColor, Math.floor(optionsLocal.alpha * 2.55)];
5207
- // eslint-disable-next-line max-len
5208
- [imageData.data[idx], imageData.data[idx + 1], imageData.data[idx + 2], imageData.data[idx + 3]] = rgbaColor;
5209
- pixel += 3;
5210
- }
5211
- }
5212
- if (rasters[0].length / (width * height) === 4) {
5213
- // console.log("geoImage: " + "RGBA 1 array");
5214
- rasters[0].forEach((value, index) => {
5215
- imageData.data[index] = value;
5216
- });
5217
- }
5218
5070
  }
5219
- if (channels === 3) {
5220
- // RGB
5221
- let pixel = 0;
5222
- for (let i = 0; i < size; i += 4) {
5223
- r = rasters[0][pixel];
5224
- g = rasters[1][pixel];
5225
- b = rasters[2][pixel];
5226
- a = Math.floor(optionsLocal.alpha * 2.55);
5227
- imageData.data[i] = r;
5228
- imageData.data[i + 1] = g;
5229
- imageData.data[i + 2] = b;
5230
- imageData.data[i + 3] = a;
5231
- pixel += 1;
5071
+ break;
5072
+ }
5073
+ const { vertices } = mesh;
5074
+ let { triangles } = mesh;
5075
+ let attributes = getMeshAttributes(vertices, terrain, width, height, input.bounds);
5076
+ // Compute bounding box before adding skirt so that z values are not skewed
5077
+ const boundingBox = schema.getMeshBoundingBox(attributes);
5078
+ if (terrainSkirtHeight) {
5079
+ const { attributes: newAttributes, triangles: newTriangles } = addSkirt(attributes, triangles, terrainSkirtHeight);
5080
+ attributes = newAttributes;
5081
+ triangles = newTriangles;
5082
+ }
5083
+ return {
5084
+ // Data return by this loader implementation
5085
+ loaderData: {
5086
+ header: {},
5087
+ },
5088
+ header: {
5089
+ vertexCount: triangles.length,
5090
+ boundingBox,
5091
+ },
5092
+ mode: 4, // TRIANGLES
5093
+ indices: { value: Uint32Array.from(triangles), size: 1 },
5094
+ attributes,
5095
+ };
5096
+ }
5097
+ async getBitmap(input, options) {
5098
+ // console.time('bitmap-generated-in');
5099
+ // const optionsLocal = { ...options };
5100
+ const optionsLocal = { ...options };
5101
+ let rasters = [];
5102
+ let channels;
5103
+ let width;
5104
+ let height;
5105
+ if (typeof (input) === 'string') {
5106
+ // TODO not tested
5107
+ // input is type of object
5108
+ await this.setUrl(input);
5109
+ rasters = (await this.data.readRasters());
5110
+ channels = rasters.length;
5111
+ width = this.data.getWidth();
5112
+ height = this.data.getHeight();
5113
+ }
5114
+ else {
5115
+ rasters = input.rasters;
5116
+ channels = rasters.length;
5117
+ width = input.width;
5118
+ height = input.height;
5119
+ }
5120
+ const canvas = document.createElement('canvas');
5121
+ canvas.width = width;
5122
+ canvas.height = height;
5123
+ const c = canvas.getContext('2d');
5124
+ const imageData = c.createImageData(width, height);
5125
+ let r;
5126
+ let g;
5127
+ let b;
5128
+ let a;
5129
+ const size = width * height * 4;
5130
+ // const size = width * height;
5131
+ // if (!options.noDataValue) {
5132
+ // console.log('Missing noData value. Raster might be displayed incorrectly.');
5133
+ // }
5134
+ optionsLocal.unidentifiedColor = this.getColorFromChromaType(optionsLocal.unidentifiedColor);
5135
+ optionsLocal.nullColor = this.getColorFromChromaType(optionsLocal.nullColor);
5136
+ optionsLocal.clippedColor = this.getColorFromChromaType(optionsLocal.clippedColor);
5137
+ optionsLocal.color = this.getColorFromChromaType(optionsLocal.color);
5138
+ optionsLocal.useChannelIndex ??= options.useChannel === null ? null : options.useChannel - 1;
5139
+ // console.log(rasters[0])
5140
+ /* console.log("raster 0 length: " + rasters[0].length)
5141
+ console.log("image width: " + width)
5142
+ console.log("channels: " + channels)
5143
+ console.log("format: " + rasters[0].length / (width * height))
5144
+ */
5145
+ if (optionsLocal.useChannelIndex == null) {
5146
+ if (channels === 1) {
5147
+ if (rasters[0].length / (width * height) === 1) {
5148
+ const channel = rasters[0];
5149
+ // AUTO RANGE
5150
+ if (optionsLocal.useAutoRange) {
5151
+ optionsLocal.colorScaleValueRange = this.getMinMax(channel, optionsLocal);
5152
+ // console.log('data min: ' + optionsLocal.rangeMin + ', max: ' + optionsLocal.rangeMax);
5232
5153
  }
5154
+ // SINGLE CHANNEL
5155
+ const colorData = this.getColorValue(channel, optionsLocal, size);
5156
+ colorData.forEach((value, index) => {
5157
+ imageData.data[index] = value;
5158
+ });
5233
5159
  }
5234
- if (channels === 4) {
5235
- // RGBA
5160
+ // RGB values in one channel
5161
+ if (rasters[0].length / (width * height) === 3) {
5162
+ // console.log("geoImage: " + "RGB 1 array of length: " + rasters[0].length);
5236
5163
  let pixel = 0;
5237
- for (let i = 0; i < size; i += 4) {
5238
- r = rasters[0][pixel];
5239
- g = rasters[1][pixel];
5240
- b = rasters[2][pixel];
5241
- a = Math.floor(optionsLocal.alpha * 2.55);
5242
- imageData.data[i] = r;
5243
- imageData.data[i + 1] = g;
5244
- imageData.data[i + 2] = b;
5245
- imageData.data[i + 3] = a;
5246
- pixel += 1;
5164
+ for (let idx = 0; idx < size; idx += 4) {
5165
+ const rgbColor = [rasters[0][pixel], rasters[0][pixel + 1], rasters[0][pixel + 2]];
5166
+ const rgbaColor = this.hasPixelsNoData(rgbColor, optionsLocal.noDataValue)
5167
+ ? optionsLocal.nullColor
5168
+ : [...rgbColor, Math.floor(optionsLocal.alpha * 2.55)];
5169
+ // eslint-disable-next-line max-len
5170
+ [imageData.data[idx], imageData.data[idx + 1], imageData.data[idx + 2], imageData.data[idx + 3]] = rgbaColor;
5171
+ pixel += 3;
5247
5172
  }
5248
5173
  }
5174
+ if (rasters[0].length / (width * height) === 4) {
5175
+ // console.log("geoImage: " + "RGBA 1 array");
5176
+ rasters[0].forEach((value, index) => {
5177
+ imageData.data[index] = value;
5178
+ });
5179
+ }
5249
5180
  }
5250
- else if (optionsLocal.useChannelIndex < optionsLocal.numOfChannels && optionsLocal.useChannelIndex >= 0) {
5251
- let channel = rasters[0];
5252
- if (rasters[optionsLocal.useChannelIndex]) {
5253
- channel = rasters[optionsLocal.useChannelIndex];
5181
+ if (channels === 3) {
5182
+ // RGB
5183
+ let pixel = 0;
5184
+ for (let i = 0; i < size; i += 4) {
5185
+ r = rasters[0][pixel];
5186
+ g = rasters[1][pixel];
5187
+ b = rasters[2][pixel];
5188
+ a = Math.floor(optionsLocal.alpha * 2.55);
5189
+ imageData.data[i] = r;
5190
+ imageData.data[i + 1] = g;
5191
+ imageData.data[i + 2] = b;
5192
+ imageData.data[i + 3] = a;
5193
+ pixel += 1;
5254
5194
  }
5255
- // AUTO RANGE
5256
- if (optionsLocal.useAutoRange) {
5257
- optionsLocal.colorScaleValueRange = this.getMinMax(channel, optionsLocal);
5258
- // console.log('data min: ' + optionsLocal.rangeMin + ', max: ' + optionsLocal.rangeMax);
5195
+ }
5196
+ if (channels === 4) {
5197
+ // RGBA
5198
+ let pixel = 0;
5199
+ for (let i = 0; i < size; i += 4) {
5200
+ r = rasters[0][pixel];
5201
+ g = rasters[1][pixel];
5202
+ b = rasters[2][pixel];
5203
+ a = Math.floor(optionsLocal.alpha * 2.55);
5204
+ imageData.data[i] = r;
5205
+ imageData.data[i + 1] = g;
5206
+ imageData.data[i + 2] = b;
5207
+ imageData.data[i + 3] = a;
5208
+ pixel += 1;
5259
5209
  }
5260
- // const numOfChannels = channel.length / (width * height);
5261
- const colorData = this.getColorValue(channel, optionsLocal, size, optionsLocal.numOfChannels);
5262
- colorData.forEach((value, index) => {
5263
- imageData.data[index] = value;
5264
- });
5265
5210
  }
5266
- else {
5267
- // if user defined channel does not exist
5268
- console.log(`Defined channel(${options.useChannel}) or channel index(${options.useChannelIndex}) does not exist, choose a different channel or set the useChannel property to null if you want to visualize RGB(A) imagery`);
5269
- const defaultColorData = this.getDefaultColor(size, optionsLocal.nullColor);
5270
- defaultColorData.forEach((value, index) => {
5271
- imageData.data[index] = value;
5272
- });
5211
+ }
5212
+ else if (optionsLocal.useChannelIndex < optionsLocal.numOfChannels && optionsLocal.useChannelIndex >= 0) {
5213
+ let channel = rasters[0];
5214
+ if (rasters[optionsLocal.useChannelIndex]) {
5215
+ channel = rasters[optionsLocal.useChannelIndex];
5273
5216
  }
5274
- // console.timeEnd('bitmap-generated-in');
5275
- c.putImageData(imageData, 0, 0);
5276
- const imageUrl = canvas.toDataURL('image/png');
5277
- // console.log('Bitmap generated.');
5278
- return imageUrl;
5279
- });
5217
+ // AUTO RANGE
5218
+ if (optionsLocal.useAutoRange) {
5219
+ optionsLocal.colorScaleValueRange = this.getMinMax(channel, optionsLocal);
5220
+ // console.log('data min: ' + optionsLocal.rangeMin + ', max: ' + optionsLocal.rangeMax);
5221
+ }
5222
+ // const numOfChannels = channel.length / (width * height);
5223
+ const colorData = this.getColorValue(channel, optionsLocal, size, optionsLocal.numOfChannels);
5224
+ colorData.forEach((value, index) => {
5225
+ imageData.data[index] = value;
5226
+ });
5227
+ }
5228
+ else {
5229
+ // if user defined channel does not exist
5230
+ console.log(`Defined channel(${options.useChannel}) or channel index(${options.useChannelIndex}) does not exist, choose a different channel or set the useChannel property to null if you want to visualize RGB(A) imagery`);
5231
+ const defaultColorData = this.getDefaultColor(size, optionsLocal.nullColor);
5232
+ defaultColorData.forEach((value, index) => {
5233
+ imageData.data[index] = value;
5234
+ });
5235
+ }
5236
+ // console.timeEnd('bitmap-generated-in');
5237
+ c.putImageData(imageData, 0, 0);
5238
+ const imageUrl = canvas.toDataURL('image/png');
5239
+ // console.log('Bitmap generated.');
5240
+ return imageUrl;
5280
5241
  }
5281
5242
  getMinMax(array, options) {
5282
5243
  let maxValue = options.maxValue ? options.maxValue : Number.MIN_VALUE;
@@ -5292,6 +5253,8 @@ class GeoImage {
5292
5253
  return [minValue, maxValue];
5293
5254
  }
5294
5255
  getColorValue(dataArray, options, arrayLength, numOfChannels = 1) {
5256
+ // const rgb = chroma.random().rgb(); // [R, G, B]
5257
+ // const randomColor = [...rgb, 120];
5295
5258
  const colorScale = chroma.scale(options.colorScale).domain(options.colorScaleValueRange);
5296
5259
  // channel index is equal to channel number - 1
5297
5260
  let pixel = options.useChannelIndex === null ? 0 : options.useChannelIndex;
@@ -5311,6 +5274,7 @@ class GeoImage {
5311
5274
  }) : undefined;
5312
5275
  for (let i = 0; i < arrayLength; i += 4) {
5313
5276
  let pixelColor = options.nullColor;
5277
+ // let pixelColor = randomColor;
5314
5278
  // FIXME
5315
5279
  // eslint-disable-next-line max-len
5316
5280
  if ((!Number.isNaN(dataArray[pixel])) && (options.noDataValue === undefined || dataArray[pixel] !== options.noDataValue)) {
@@ -5352,7 +5316,7 @@ class GeoImage {
5352
5316
  }
5353
5317
  // FIXME
5354
5318
  // eslint-disable-next-line
5355
- [colorsArray[i], colorsArray[i + 1], colorsArray[i + 2], colorsArray[i + 3]] = pixelColor;
5319
+ ([colorsArray[i], colorsArray[i + 1], colorsArray[i + 2], colorsArray[i + 3]] = pixelColor);
5356
5320
  pixel += numOfChannels;
5357
5321
  }
5358
5322
  return colorsArray;
@@ -5442,7 +5406,7 @@ function getMeshAttributes(vertices, terrain, width, height, bounds) {
5442
5406
  function getDelatinTileMesh(meshMaxError, width, height, terrain) {
5443
5407
  const tin = new Delatin(terrain, width + 1, height + 1);
5444
5408
  tin.run(meshMaxError);
5445
- // @ts-expect-error
5409
+ // @ts-expect-error: Delatin instance properties 'coords' and 'triangles' are not explicitly typed in the library port
5446
5410
  const { coords, triangles } = tin;
5447
5411
  const vertices = coords;
5448
5412
  return { vertices, triangles };
@@ -5456,31 +5420,30 @@ const CogTilesGeoImageOptionsDefaults = {
5456
5420
  blurredTexture: true,
5457
5421
  };
5458
5422
  class CogTiles {
5423
+ cog;
5424
+ cogZoomLookup = [0];
5425
+ cogResolutionLookup = [0];
5426
+ cogOrigin = [0, 0];
5427
+ zoomRange = [0, 0];
5428
+ tileSize;
5429
+ bounds;
5430
+ geo = new GeoImage();
5431
+ options;
5459
5432
  constructor(options) {
5460
- this.cogZoomLookup = [0];
5461
- this.cogResolutionLookup = [0];
5462
- this.cogOrigin = [0, 0];
5463
- this.zoomRange = [0, 0];
5464
- this.loaded = false;
5465
- this.geo = new GeoImage();
5466
- this.options = Object.assign(Object.assign({}, CogTilesGeoImageOptionsDefaults), options);
5467
- }
5468
- initializeCog(url) {
5469
- var _a, _b;
5470
- var _c, _d;
5471
- return __awaiter(this, void 0, void 0, function* () {
5472
- this.cog = yield fromUrl(url);
5473
- const image = yield this.cog.getImage(); // by default, the first image is read.
5474
- this.cogOrigin = image.getOrigin();
5475
- (_a = (_c = this.options).noDataValue) !== null && _a !== void 0 ? _a : (_c.noDataValue = this.getNoDataValue(image));
5476
- (_b = (_d = this.options).format) !== null && _b !== void 0 ? _b : (_d.format = this.getDataTypeFromTags(image));
5477
- this.options.numOfChannels = this.getNumberOfChannels(image);
5478
- this.options.planarConfig = this.getPlanarConfiguration(image);
5479
- [this.cogZoomLookup, this.cogResolutionLookup] = yield this.buildCogZoomResolutionLookup(this.cog);
5480
- this.tileSize = image.getTileWidth();
5481
- this.zoomRange = this.calculateZoomRange(image, yield this.cog.getImageCount());
5482
- this.bounds = this.calculateBoundsAsLatLon(image);
5483
- });
5433
+ this.options = { ...CogTilesGeoImageOptionsDefaults, ...options };
5434
+ }
5435
+ async initializeCog(url) {
5436
+ this.cog = await fromUrl(url);
5437
+ const image = await this.cog.getImage(); // by default, the first image is read.
5438
+ this.cogOrigin = image.getOrigin();
5439
+ this.options.noDataValue ??= this.getNoDataValue(image);
5440
+ this.options.format ??= this.getDataTypeFromTags(image);
5441
+ this.options.numOfChannels = this.getNumberOfChannels(image);
5442
+ this.options.planarConfig = this.getPlanarConfiguration(image);
5443
+ [this.cogZoomLookup, this.cogResolutionLookup] = await this.buildCogZoomResolutionLookup(this.cog);
5444
+ this.tileSize = image.getTileWidth();
5445
+ this.zoomRange = this.calculateZoomRange(image, await this.cog.getImageCount());
5446
+ this.bounds = this.calculateBoundsAsLatLon(image);
5484
5447
  }
5485
5448
  getZoomRange() {
5486
5449
  return this.zoomRange;
@@ -5532,33 +5495,31 @@ class CogTiles {
5532
5495
  * - The first array (`zoomLookup`) maps each image index to its computed zoom level.
5533
5496
  * - The second array (`resolutionLookup`) maps each image index to its estimated resolution (m/pixel).
5534
5497
  */
5535
- buildCogZoomResolutionLookup(cog) {
5536
- return __awaiter(this, void 0, void 0, function* () {
5537
- // Retrieve the total number of images (overviews) in the COG.
5538
- const imageCount = yield cog.getImageCount();
5539
- // Use the first image as the base reference.
5540
- const baseImage = yield cog.getImage(0);
5541
- const baseResolution = baseImage.getResolution()[0]; // Resolution (m/pixel) of the base image.
5542
- const baseWidth = baseImage.getWidth();
5543
- // Initialize arrays to store the zoom level and resolution for each image.
5544
- const zoomLookup = [];
5545
- const resolutionLookup = [];
5546
- // Iterate over each image (overview) in the COG.
5547
- for (let idx = 0; idx < imageCount; idx++) {
5548
- const image = yield cog.getImage(idx);
5549
- const width = image.getWidth();
5550
- // Calculate the scale factor relative to the base image.
5551
- const scaleFactor = baseWidth / width;
5552
- const estimatedResolution = baseResolution * scaleFactor;
5553
- // Calculate the zoom level using the Web Mercator resolution standard:
5554
- // webMercatorRes0 is the resolution at zoom level 0; each zoom level halves the resolution.
5555
- const zoomLevel = Math.round(Math.log2(webMercatorRes0 / estimatedResolution));
5556
- // console.log(`buildCogZoomResolutionLookup: Image index ${idx}: Estimated Resolution = ${estimatedResolution} m/pixel, Zoom Level = ${zoomLevel}`);
5557
- zoomLookup[idx] = zoomLevel;
5558
- resolutionLookup[idx] = estimatedResolution;
5559
- }
5560
- return [zoomLookup, resolutionLookup];
5561
- });
5498
+ async buildCogZoomResolutionLookup(cog) {
5499
+ // Retrieve the total number of images (overviews) in the COG.
5500
+ const imageCount = await cog.getImageCount();
5501
+ // Use the first image as the base reference.
5502
+ const baseImage = await cog.getImage(0);
5503
+ const baseResolution = baseImage.getResolution()[0]; // Resolution (m/pixel) of the base image.
5504
+ const baseWidth = baseImage.getWidth();
5505
+ // Initialize arrays to store the zoom level and resolution for each image.
5506
+ const zoomLookup = [];
5507
+ const resolutionLookup = [];
5508
+ // Iterate over each image (overview) in the COG.
5509
+ for (let idx = 0; idx < imageCount; idx++) {
5510
+ const image = await cog.getImage(idx);
5511
+ const width = image.getWidth();
5512
+ // Calculate the scale factor relative to the base image.
5513
+ const scaleFactor = baseWidth / width;
5514
+ const estimatedResolution = baseResolution * scaleFactor;
5515
+ // Calculate the zoom level using the Web Mercator resolution standard:
5516
+ // webMercatorRes0 is the resolution at zoom level 0; each zoom level halves the resolution.
5517
+ const zoomLevel = Math.round(Math.log2(webMercatorRes0 / estimatedResolution));
5518
+ // console.log(`buildCogZoomResolutionLookup: Image index ${idx}: Estimated Resolution = ${estimatedResolution} m/pixel, Zoom Level = ${zoomLevel}`);
5519
+ zoomLookup[idx] = zoomLevel;
5520
+ resolutionLookup[idx] = estimatedResolution;
5521
+ }
5522
+ return [zoomLookup, resolutionLookup];
5562
5523
  }
5563
5524
  /**
5564
5525
  * Determines the appropriate image index from the Cloud Optimized GeoTIFF (COG)
@@ -5587,99 +5548,138 @@ class CogTiles {
5587
5548
  }
5588
5549
  return exactMatchIndex;
5589
5550
  }
5590
- getTileFromImage(tileX, tileY, zoom) {
5591
- return __awaiter(this, void 0, void 0, function* () {
5592
- const imageIndex = this.getImageIndexForZoomLevel(zoom);
5593
- const targetImage = yield this.cog.getImage(imageIndex);
5594
- // Ensure the image is tiled
5595
- const tileWidth = targetImage.getTileWidth();
5596
- const tileHeight = targetImage.getTileHeight();
5597
- if (!tileWidth || !tileHeight) {
5598
- throw new Error('The image is not tiled.');
5599
- }
5600
- // Calculate the map offset between the global Web Mercator origin and the COG's origin.
5601
- // (Difference in map units.)
5602
- // if X offset is large and positive (COG is far to the right of global origin)
5603
- // if Y offset is large and positive (COG is far below global origin — expected)
5604
- const offsetXMap = this.cogOrigin[0] - webMercatorOrigin[0];
5605
- const offsetYMap = webMercatorOrigin[1] - this.cogOrigin[1];
5606
- const tileResolution = (EARTH_CIRCUMFERENCE / tileWidth) / Math.pow(2, zoom);
5607
- this.cogResolutionLookup[imageIndex];
5608
- // Convert map offsets into pixel offsets.
5609
- const offsetXPixel = Math.floor(offsetXMap / tileResolution);
5610
- const offsetYPixel = Math.floor(offsetYMap / tileResolution);
5611
- // Calculate the pixel boundaries for the tile.
5612
- const window = [
5613
- tileX * tileWidth - offsetXPixel,
5614
- tileY * tileHeight - offsetYPixel,
5615
- (tileX + 1) * tileWidth - offsetXPixel,
5616
- (tileY + 1) * tileHeight - offsetYPixel, // endY (exclusive)
5617
- ];
5618
- const [windowStartX, windowStartY, windowEndX, windowEndY] = window;
5619
- const imageHeight = targetImage.getHeight();
5620
- const imageWidth = targetImage.getWidth();
5621
- // Determine the effective (valid) window inside the image:
5622
- const effectiveStartX = Math.max(0, windowStartX);
5623
- const effectiveStartY = Math.max(0, windowStartY);
5624
- const effectiveEndX = windowEndX;
5625
- const effectiveEndY = windowEndY;
5626
- // Calculate how many pixels are missing from the left and top due to negative windowStart.
5627
- const missingLeft = Math.max(0, 0 - windowStartX);
5628
- const missingTop = Math.max(0, 0 - windowStartY);
5629
- // Read only the valid window from the image.
5630
- const validWindow = [effectiveStartX, effectiveStartY, effectiveEndX, effectiveEndY];
5631
- // Read the raster data for the tile window with shifted origin.
5632
- if (missingLeft > 0 || missingTop > 0) {
5633
- // Prepare the final tile buffer and fill it with noDataValue.
5634
- const tileBuffer = this.createTileBuffer(this.options.format, tileWidth);
5635
- tileBuffer.fill(this.options.noDataValue);
5636
- // Calculate the width of the valid window.
5637
- const validWidth = Math.min(imageWidth, effectiveEndX - effectiveStartX);
5638
- const validHeight = Math.min(imageHeight, effectiveEndY - effectiveStartY);
5639
- // 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
5640
- const validRasterData = yield targetImage.readRasters({ window: validWindow });
5641
- // FOR MULTI-BAND - the result is one array with sequentially typed bands, firstly all data for the band 0, then for band 1
5642
- // 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.
5643
- const validImageData = Array(validRasterData.length * validRasterData[0].length);
5644
- validImageData.fill(this.options.noDataValue);
5645
- // Place the valid pixel data into the tile buffer.
5646
- for (let band = 0; band < validRasterData.length; band++) {
5647
- for (let row = 0; row < validHeight; row++) {
5648
- for (let col = 0; col < validWidth; col++) {
5649
- // Compute the destination position in the tile buffer.
5650
- // We shift by the number of missing pixels (if any) at the top/left.
5651
- const destRow = missingTop + row;
5652
- const destCol = missingLeft + col;
5653
- if (destRow < tileWidth && destCol < tileHeight) {
5654
- tileBuffer[destRow * tileWidth + destCol] = validRasterData[band][row * validRasterData.width + col];
5655
- }
5656
- else {
5657
- console.log('error in assigning data to tile buffer');
5658
- }
5551
+ async getTileFromImage(tileX, tileY, zoom) {
5552
+ const imageIndex = this.getImageIndexForZoomLevel(zoom);
5553
+ const targetImage = await this.cog.getImage(imageIndex);
5554
+ // 1. Validation: Ensure the image is tiled
5555
+ const tileWidth = targetImage.getTileWidth();
5556
+ const tileHeight = targetImage.getTileHeight();
5557
+ if (!tileWidth || !tileHeight) {
5558
+ throw new Error('GeoTIFF Error: The provided image is not tiled. '
5559
+ + 'Please use "rio cogeo create --web-optimized" to fix this.');
5560
+ }
5561
+ // --- STEP 1: CALCULATE BOUNDS IN METERS ---
5562
+ // 2. Get COG Metadata (image = COG)
5563
+ const imageResolution = this.cogResolutionLookup[imageIndex];
5564
+ const imageHeight = targetImage.getHeight();
5565
+ const imageWidth = targetImage.getWidth();
5566
+ const [imgOriginX, imgOriginY] = this.cogOrigin;
5567
+ // 3. Define Web Mercator Constants
5568
+ // We use the class property tileSize (usually 256) as the ground truth for grid calculations
5569
+ const TILE_SIZE = this.tileSize;
5570
+ const ORIGIN_X = webMercatorOrigin[0];
5571
+ const ORIGIN_Y = webMercatorOrigin[1];
5572
+ // 4. Calculate Tile BBox in World Meters
5573
+ // This defines where the map expects the tile to be physically located
5574
+ const tileGridResolution = (EARTH_CIRCUMFERENCE / TILE_SIZE) / (2 ** zoom);
5575
+ const tileMinXMeters = ORIGIN_X + (tileX * TILE_SIZE * tileGridResolution);
5576
+ const tileMaxYMeters = ORIGIN_Y - (tileY * TILE_SIZE * tileGridResolution);
5577
+ // Note: We don't strictly need MaxX/MinY meters for the start calculation,
5578
+ // but they are useful if debugging the full meter footprint.
5579
+ // --- STEP 2: CONVERT TO PIXEL COORDINATES ---
5580
+ // 5. Calculate precise floating-point start position relative to the image
5581
+ const windowMinX = (tileMinXMeters - imgOriginX) / imageResolution;
5582
+ const windowMinY = (imgOriginY - tileMaxYMeters) / imageResolution;
5583
+ // 6. Snap to Integer Grid (The "Force 256" Fix)
5584
+ // We round the start position to align with the nearest pixel.
5585
+ // Crucially, we calculate endX/endY by adding tileSize to startX/startY.
5586
+ // This guarantees the window is exactly 256x256, preventing "off-by-one" (257px) errors.
5587
+ const startX = Math.round(windowMinX);
5588
+ const startY = Math.round(windowMinY);
5589
+ const endX = startX + TILE_SIZE;
5590
+ const endY = startY + TILE_SIZE;
5591
+ // --- STEP 3: CALCULATE INTERSECTION ---
5592
+ // 7. Clamp the read window to the actual image dimensions
5593
+ // This defines the "Safe" area we can actually read from the file.
5594
+ const validReadX = Math.max(0, startX);
5595
+ const validReadY = Math.max(0, startY);
5596
+ const validReadMaxX = Math.min(imageWidth, endX);
5597
+ const validReadMaxY = Math.min(imageHeight, endY);
5598
+ const readWidth = validReadMaxX - validReadX;
5599
+ const readHeight = validReadMaxY - validReadY;
5600
+ // CHECK: If no overlap, return empty
5601
+ if (readWidth <= 0 || readHeight <= 0) {
5602
+ return [this.createEmptyTile()];
5603
+ }
5604
+ // 8. Calculate Offsets (Padding)
5605
+ // "missingLeft" is how many blank pixels we need to insert before the image data starts.
5606
+ // Logic: If we wanted to read from -50 (startX), but clamped to 0 (validReadX),
5607
+ // we are missing the first 50 pixels.
5608
+ const missingLeft = validReadX - startX;
5609
+ const missingTop = validReadY - startY;
5610
+ const window = [validReadX, validReadY, validReadMaxX, validReadMaxY];
5611
+ // --- STEP 4: READ AND COMPOSITE ---
5612
+ // Case A: Partial Overlap (Padding or Cropping required)
5613
+ // If the tile is hanging off the edge, we need to manually reconstruct it.
5614
+ if (missingLeft > 0 || missingTop > 0 || readWidth < tileWidth || readHeight < tileHeight) {
5615
+ /// Initialize a temporary buffer for a single band (filled with NoData)
5616
+ // We will reuse this buffer for each band to save memory allocations.
5617
+ const tileBuffer = this.createTileBuffer(this.options.format, tileWidth);
5618
+ tileBuffer.fill(this.options.noDataValue);
5619
+ // if the valid window is smaller than the tile size, it gets the image size width and height, thus validRasterData.width must be used as below
5620
+ const validRasterData = await targetImage.readRasters({ window });
5621
+ // FOR MULTI-BAND - the result is one array with sequentially typed bands, firstly all data for the band 0, then for band 1
5622
+ // 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.
5623
+ const validImageData = Array(validRasterData.length * validRasterData[0].length);
5624
+ validImageData.fill(this.options.noDataValue);
5625
+ // Place the valid pixel data into the tile buffer.
5626
+ for (let band = 0; band < validRasterData.length; band += 1) {
5627
+ for (let row = 0; row < readHeight; row += 1) {
5628
+ const destRow = missingTop + row;
5629
+ const destRowOffset = destRow * TILE_SIZE;
5630
+ const srcRowOffset = row * validRasterData.width;
5631
+ for (let col = 0; col < readWidth; col += 1) {
5632
+ // Compute the destination position in the tile buffer.
5633
+ // We shift by the number of missing pixels (if any) at the top/left.
5634
+ const destCol = missingLeft + col;
5635
+ // Bounds Check: Ensure we don't write outside the 256x256 buffer
5636
+ if (destRow < tileWidth && destCol < tileHeight) {
5637
+ tileBuffer[destRowOffset + destCol] = validRasterData[band][srcRowOffset + col];
5638
+ }
5639
+ else {
5640
+ console.log('error in assigning data to tile buffer');
5659
5641
  }
5660
5642
  }
5661
- tileBuffer.forEach((rasterValue, index) => {
5662
- validImageData[index * this.options.numOfChannels + band] = rasterValue;
5663
- });
5664
5643
  }
5665
- return [validImageData];
5644
+ for (let i = 0; i < tileBuffer.length; i += 1) {
5645
+ validImageData[i * this.options.numOfChannels + band] = tileBuffer[i];
5646
+ }
5666
5647
  }
5667
- // Read the raster data for the non shifted tile window.
5668
- const tileData = yield targetImage.readRasters({ window, interleave: true });
5669
- // console.log(`data that starts at the left top corner of the tile ${tileX}, ${tileY}`);
5670
- return [tileData];
5671
- });
5648
+ return [validImageData];
5649
+ }
5650
+ // Case B: Perfect Match (Optimization)
5651
+ // If the read window is exactly 256x256 and aligned, we can read directly interleaved.
5652
+ // console.log("Perfect aligned read");
5653
+ const tileData = await targetImage.readRasters({ window, interleave: true });
5654
+ // console.log(`data that starts at the left top corner of the tile ${tileX}, ${tileY}`);
5655
+ return [tileData];
5672
5656
  }
5673
- getTile(x, y, z, bounds, meshMaxError) {
5674
- return __awaiter(this, void 0, void 0, function* () {
5675
- const tileData = yield this.getTileFromImage(x, y, z);
5676
- return this.geo.getMap({
5677
- rasters: [tileData[0]],
5678
- width: this.tileSize,
5679
- height: this.tileSize,
5680
- bounds,
5681
- }, this.options, meshMaxError);
5682
- });
5657
+ /**
5658
+ * Creates a blank tile buffer filled with the "No Data" value.
5659
+ */
5660
+ createEmptyTile() {
5661
+ // 1. Determine the size
5662
+ // Default to 1 channel (grayscale) if not specified
5663
+ const channels = this.options.numOfChannels || 1;
5664
+ const size = this.tileSize * this.tileSize * channels;
5665
+ // 2. Create the array
5666
+ // Float32 is standard for GeoTIFF data handling in browsers
5667
+ const tileData = new Float32Array(size);
5668
+ // 3. Fill with "No Data" value
5669
+ // If noDataValue is undefined, it defaults to 0
5670
+ if (this.options.noDataValue !== undefined) {
5671
+ tileData.fill(this.options.noDataValue);
5672
+ }
5673
+ return tileData;
5674
+ }
5675
+ async getTile(x, y, z, bounds, meshMaxError) {
5676
+ const tileData = await this.getTileFromImage(x, y, z);
5677
+ return this.geo.getMap({
5678
+ rasters: [tileData[0]],
5679
+ width: this.tileSize,
5680
+ height: this.tileSize,
5681
+ bounds,
5682
+ }, this.options, meshMaxError);
5683
5683
  }
5684
5684
  /**
5685
5685
  * Determines the data type (e.g., "Int32", "Float64") of a GeoTIFF image
@@ -5725,24 +5725,33 @@ class CogTiles {
5725
5725
  }
5726
5726
  /**
5727
5727
  * Extracts the noData value from a GeoTIFF.js image.
5728
- * Returns the noData value as a number if available, otherwise undefined.
5728
+ * Returns the noData value as a number (including NaN) if available, otherwise undefined.
5729
5729
  *
5730
5730
  * @param {GeoTIFFImage} image - The GeoTIFF.js image.
5731
- * @returns {number|undefined} The noData value as a number, or undefined if not available.
5731
+ * @returns {number|undefined} The noData value, possibly NaN, or undefined if not set or invalid.
5732
5732
  */
5733
5733
  getNoDataValue(image) {
5734
- // Attempt to retrieve the noData value via the GDAL method.
5735
5734
  const noDataRaw = image.getGDALNoData();
5736
5735
  if (noDataRaw === undefined || noDataRaw === null) {
5737
- console.log('noDataValue is undefined or null,raster might be displayed incorrectly.');
5738
- // No noData value is defined
5736
+ console.warn('No noData value defined raster might be rendered incorrectly.');
5739
5737
  return undefined;
5740
5738
  }
5741
- // In geotiff.js, the noData value is typically returned as a string.
5742
- // Clean up the string by removing any null characters or extra whitespace.
5743
- const cleanedValue = String(noDataRaw).replace(/\0/g, '').trim();
5744
- const parsedValue = Number(cleanedValue);
5745
- return Number.isNaN(parsedValue) ? undefined : parsedValue;
5739
+ const cleaned = String(noDataRaw).replace(/\0/g, '').trim();
5740
+ if (cleaned === '') {
5741
+ console.warn('noData value is an empty string after cleanup.');
5742
+ return undefined;
5743
+ }
5744
+ const parsed = Number(cleaned);
5745
+ // Allow NaN if explicitly declared
5746
+ if (cleaned.toLowerCase() === 'nan') {
5747
+ return NaN;
5748
+ }
5749
+ // If not declared as "nan" and still parsed to NaN, it's an error
5750
+ if (Number.isNaN(parsed)) {
5751
+ console.warn(`Failed to parse numeric noData value: '${cleaned}'`);
5752
+ return undefined;
5753
+ }
5754
+ return parsed;
5746
5755
  }
5747
5756
  /**
5748
5757
  * Retrieves the number of channels (samples per pixel) in a GeoTIFF image.
@@ -5825,7 +5834,8 @@ const urlType$1 = {
5825
5834
  return true;
5826
5835
  },
5827
5836
  };
5828
- const defaultProps$1 = Object.assign(Object.assign({}, geoLayers.TileLayer.defaultProps), {
5837
+ const defaultProps$1 = {
5838
+ ...geoLayers.TileLayer.defaultProps,
5829
5839
  // Image url that encodes height data
5830
5840
  // elevationData: urlType,
5831
5841
  // Image url to use as texture
@@ -5835,10 +5845,9 @@ const defaultProps$1 = Object.assign(Object.assign({}, geoLayers.TileLayer.defau
5835
5845
  // Bounding box of the terrain image, [minX, minY, maxX, maxY] in world coordinates
5836
5846
  bounds: {
5837
5847
  type: 'array', value: null, optional: true, compare: true,
5838
- }, rasterData: urlType$1,
5839
- // Color to use if texture is unavailable
5840
- // color: { type: 'color', value: [255, 255, 255] },
5841
- blurredTexture: true, opacity: 1, clampToTerrain: false,
5848
+ },
5849
+ rasterData: urlType$1,
5850
+ clampToTerrain: false,
5842
5851
  // Object to decode height data, from (r, g, b) to height in meters
5843
5852
  // elevationDecoder: {
5844
5853
  // type: 'object',
@@ -5850,40 +5859,31 @@ const defaultProps$1 = Object.assign(Object.assign({}, geoLayers.TileLayer.defau
5850
5859
  // },
5851
5860
  // },
5852
5861
  // Supply url to local terrain worker bundle. Only required if running offline and cannot access CDN.
5853
- workerUrl: '' });
5862
+ workerUrl: '',
5863
+ // Same as SimpleMeshLayer wireframe
5864
+ // wireframe: false,
5865
+ // material: true,
5866
+ // loaders: [TerrainLoader],
5867
+ };
5854
5868
  /** Render bitmap texture from cog raster images. */
5855
5869
  class CogBitmapLayer extends core.CompositeLayer {
5856
- // private _isLoaded: boolean;
5857
- // id = '';
5858
- // url: string;
5859
- // static displayName: string;
5860
- // cogTiles: CogTiles;
5861
- //
5862
- // tileSize: number;
5863
- //
5864
- initializeState(context) {
5865
- const _super = Object.create(null, {
5866
- initializeState: { get: () => super.initializeState }
5867
- });
5868
- return __awaiter(this, void 0, void 0, function* () {
5869
- _super.initializeState.call(this, context);
5870
- this.setState({
5871
- bitmapCogTiles: new CogTiles(this.props.cogBitmapOptions),
5872
- initialized: false,
5873
- });
5874
- yield this.init();
5870
+ static defaultProps = defaultProps$1;
5871
+ static layerName = 'CogBitmapLayer';
5872
+ async initializeState(context) {
5873
+ super.initializeState(context);
5874
+ this.setState({
5875
+ bitmapCogTiles: new CogTiles(this.props.cogBitmapOptions),
5876
+ initialized: false,
5875
5877
  });
5878
+ await this.init();
5876
5879
  }
5877
- init() {
5878
- return __awaiter(this, void 0, void 0, function* () {
5879
- yield this.state.bitmapCogTiles.initializeCog(this.props.rasterData);
5880
- const zoomRange = this.state.bitmapCogTiles.getZoomRange();
5881
- const [minZoom, maxZoom] = zoomRange;
5882
- this.setState({ initialized: true, minZoom, maxZoom });
5883
- });
5880
+ async init() {
5881
+ await this.state.bitmapCogTiles.initializeCog(this.props.rasterData);
5882
+ const zoomRange = this.state.bitmapCogTiles.getZoomRange();
5883
+ const [minZoom, maxZoom] = zoomRange;
5884
+ this.setState({ initialized: true, minZoom, maxZoom });
5884
5885
  }
5885
5886
  updateState({ props, oldProps }) {
5886
- var _a, _b, _c;
5887
5887
  const rasterDataChanged = props.rasterData !== oldProps.rasterData;
5888
5888
  if (rasterDataChanged) {
5889
5889
  const { rasterData } = props;
@@ -5903,45 +5903,47 @@ class CogBitmapLayer extends core.CompositeLayer {
5903
5903
  // object in this way is not ideal and may need refactoring in the future to follow a more
5904
5904
  // declarative state management approach. Consider revisiting this if additional properties
5905
5905
  // need to be synchronized or if the state structure changes.
5906
- if (((_a = props === null || props === void 0 ? void 0 : props.cogBitmapOptions) === null || _a === void 0 ? void 0 : _a.useChannel) && (((_b = props.cogBitmapOptions) === null || _b === void 0 ? void 0 : _b.useChannel) !== ((_c = oldProps.cogBitmapOptions) === null || _c === void 0 ? void 0 : _c.useChannel))) {
5906
+ if (props?.cogBitmapOptions?.useChannel && (props.cogBitmapOptions?.useChannel !== oldProps.cogBitmapOptions?.useChannel)) {
5907
5907
  this.state.bitmapCogTiles.options.useChannel = props.cogBitmapOptions.useChannel;
5908
5908
  }
5909
- // TODO - remove in v9
5910
- // @ts-ignore
5911
5909
  if (props.workerUrl) {
5912
5910
  core.log.removed('workerUrl', 'loadOptions.terrain.workerUrl')();
5913
5911
  }
5914
5912
  }
5915
- getTiledBitmapData(tile) {
5916
- return __awaiter(this, void 0, void 0, function* () {
5917
- // TODO - pass signal to getTile
5918
- // abort request if signal is aborted
5919
- const tileData = yield this.state.bitmapCogTiles.getTile(tile.index.x, tile.index.y, tile.index.z);
5920
- return tileData;
5921
- });
5913
+ async getTiledBitmapData(tile) {
5914
+ // TODO - pass signal to getTile
5915
+ // abort request if signal is aborted
5916
+ const tileData = await this.state.bitmapCogTiles.getTile(tile.index.x, tile.index.y, tile.index.z);
5917
+ return tileData;
5922
5918
  }
5923
5919
  renderSubLayers(props) {
5924
5920
  const SubLayerClass = this.getSubLayerClass('image', layers.BitmapLayer);
5925
5921
  const { blurredTexture } = this.state.bitmapCogTiles.options;
5926
- const { opacity, clampToTerrain } = this.props;
5922
+ const { clampToTerrain } = this.props;
5923
+ const hasDrawMode = typeof clampToTerrain === 'object' && clampToTerrain !== null && 'terrainDrawMode' in clampToTerrain;
5927
5924
  const { data } = props;
5928
5925
  if (!data) {
5929
5926
  return null;
5930
5927
  }
5931
5928
  const { bbox: { west, south, east, north, }, } = props.tile;
5932
- return new SubLayerClass(Object.assign(Object.assign({}, props), { tileSize: this.state.bitmapCogTiles.tileSize }), Object.assign({ data: null, image: data, _instanced: false, bounds: [west, south, east, north], opacity, textureParameters: {
5929
+ return new SubLayerClass({ ...props, tileSize: this.state.bitmapCogTiles.tileSize }, {
5930
+ data: null,
5931
+ image: data,
5932
+ _instanced: false,
5933
+ bounds: [west, south, east, north],
5934
+ textureParameters: {
5933
5935
  minFilter: blurredTexture ? 'linear' : 'nearest',
5934
5936
  magFilter: blurredTexture ? 'linear' : 'nearest',
5935
- },
5937
+ },
5936
5938
  // TODO check if works!!!
5937
- extensions: clampToTerrain ? [new extensions._TerrainExtension()] : [] }, ((clampToTerrain === null || clampToTerrain === void 0 ? void 0 : clampToTerrain.terrainDrawMode)
5938
- ? { terrainDrawMode: clampToTerrain.terrainDrawMode }
5939
- : {})));
5939
+ extensions: clampToTerrain ? [new extensions._TerrainExtension()] : [],
5940
+ ...(hasDrawMode
5941
+ ? { terrainDrawMode: clampToTerrain.terrainDrawMode }
5942
+ : {}),
5943
+ });
5940
5944
  }
5941
5945
  renderLayers() {
5942
- const { rasterData, blurredTexture, opacity, clampToTerrain,
5943
- // tileSize,
5944
- maxRequests, onTileLoad, onTileUnload, onTileError, maxCacheSize, maxCacheByteSize, refinementStrategy, cogBitmapOptions, } = this.props;
5946
+ const { clampToTerrain, maxRequests, onTileLoad, onTileUnload, onTileError, maxCacheSize, maxCacheByteSize, refinementStrategy, cogBitmapOptions, } = this.props;
5945
5947
  if (this.state.isTiled && this.state.initialized) {
5946
5948
  const { tileSize } = this.state.bitmapCogTiles;
5947
5949
  return new geoLayers.TileLayer(this.getSubLayerProps({
@@ -5976,28 +5978,7 @@ class CogBitmapLayer extends core.CompositeLayer {
5976
5978
  return null;
5977
5979
  }
5978
5980
  }
5979
- CogBitmapLayer.defaultProps = defaultProps$1;
5980
- CogBitmapLayer.layerName = 'CogBitmapLayer';
5981
5981
 
5982
- // Copyright (c) 2015 - 2017 Uber Technologies, Inc.
5983
- //
5984
- // Permission is hereby granted, free of charge, to any person obtaining a copy
5985
- // of this software and associated documentation files (the "Software"), to deal
5986
- // in the Software without restriction, including without limitation the rights
5987
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
5988
- // copies of the Software, and to permit persons to whom the Software is
5989
- // furnished to do so, subject to the following conditions:
5990
- //
5991
- // The above copyright notice and this permission notice shall be included in
5992
- // all copies or substantial portions of the Software.
5993
- //
5994
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
5995
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
5996
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
5997
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
5998
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
5999
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
6000
- // THE SOFTWARE.
6001
5982
  const urlType = {
6002
5983
  type: 'object',
6003
5984
  value: null,
@@ -6024,19 +6005,20 @@ const urlType = {
6024
6005
  },
6025
6006
  };
6026
6007
  const DUMMY_DATA = [1];
6027
- const defaultProps = Object.assign(Object.assign({}, geoLayers.TileLayer.defaultProps), {
6008
+ const defaultProps = {
6009
+ ...geoLayers.TileLayer.defaultProps,
6028
6010
  // Image url that encodes height data
6029
- elevationData: urlType,
6011
+ elevationData: urlType,
6030
6012
  // Image url to use as texture
6031
- texture: Object.assign(Object.assign({}, urlType), { optional: true }),
6013
+ texture: { ...urlType, optional: true },
6032
6014
  // Martini error tolerance in meters, smaller number -> more detailed mesh
6033
- meshMaxError: { type: 'number', value: 4.0 },
6015
+ meshMaxError: { type: 'number', value: 4.0 },
6034
6016
  // Bounding box of the terrain image, [minX, minY, maxX, maxY] in world coordinates
6035
6017
  bounds: {
6036
6018
  type: 'array', value: null, optional: true, compare: true,
6037
- },
6019
+ },
6038
6020
  // Color to use if texture is unavailable
6039
- color: { type: 'color', value: [255, 255, 255] },
6021
+ color: { type: 'color', value: [255, 255, 255] },
6040
6022
  // Object to decode height data, from (r, g, b) to height in meters
6041
6023
  elevationDecoder: {
6042
6024
  type: 'object',
@@ -6046,11 +6028,14 @@ const defaultProps = Object.assign(Object.assign({}, geoLayers.TileLayer.default
6046
6028
  bScaler: 0,
6047
6029
  offset: 0,
6048
6030
  },
6049
- },
6031
+ },
6050
6032
  // Supply url to local terrain worker bundle. Only required if running offline and cannot access CDN.
6051
- workerUrl: '',
6033
+ workerUrl: '',
6052
6034
  // Same as SimpleMeshLayer wireframe
6053
- wireframe: false, material: true });
6035
+ wireframe: false,
6036
+ material: true,
6037
+ // loaders: [TerrainLoader],
6038
+ };
6054
6039
  // Turns array of templates into a single string to work around shallow change
6055
6040
  function urlTemplateToUpdateTrigger(template) {
6056
6041
  if (Array.isArray(template)) {
@@ -6062,28 +6047,25 @@ function urlTemplateToUpdateTrigger(template) {
6062
6047
  // TODO use meshMaxError
6063
6048
  // TODO - pass signal to getTile
6064
6049
  /** Render mesh surfaces from height map images. */
6065
- class TerrainLayer extends core.CompositeLayer {
6066
- initializeState(context) {
6067
- const _super = Object.create(null, {
6068
- initializeState: { get: () => super.initializeState }
6069
- });
6070
- return __awaiter(this, void 0, void 0, function* () {
6071
- _super.initializeState.call(this, context);
6072
- this.setState({
6073
- terrainCogTiles: new CogTiles(this.props.terrainOptions),
6074
- initialized: false,
6075
- });
6076
- yield this.init(this.terrainUrl);
6050
+ class CogTerrainLayer extends core.CompositeLayer {
6051
+ static defaultProps = defaultProps;
6052
+ static layerName = 'CogTerrainLayer';
6053
+ // terrainCogTiles: CogTiles;
6054
+ terrainUrl;
6055
+ async initializeState(context) {
6056
+ super.initializeState(context);
6057
+ this.setState({
6058
+ terrainCogTiles: new CogTiles(this.props.terrainOptions),
6059
+ initialized: false,
6077
6060
  });
6061
+ await this.init(this.terrainUrl);
6078
6062
  }
6079
- init(terrainUrl) {
6080
- return __awaiter(this, void 0, void 0, function* () {
6081
- yield this.state.terrainCogTiles.initializeCog(this.props.elevationData);
6082
- // this.tileSize = this.terrainCogTiles.getTileSize(cog);
6083
- const zoomRange = this.state.terrainCogTiles.getZoomRange();
6084
- const [minZoom, maxZoom] = zoomRange;
6085
- this.setState({ initialized: true, minZoom, maxZoom });
6086
- });
6063
+ async init() {
6064
+ await this.state.terrainCogTiles.initializeCog(this.props.elevationData);
6065
+ // this.tileSize = this.terrainCogTiles.getTileSize(cog);
6066
+ const zoomRange = this.state.terrainCogTiles.getZoomRange();
6067
+ const [minZoom, maxZoom] = zoomRange;
6068
+ this.setState({ initialized: true, minZoom, maxZoom });
6087
6069
  }
6088
6070
  updateState({ props, oldProps }) {
6089
6071
  const elevationDataChanged = props.elevationData !== oldProps.elevationData;
@@ -6100,8 +6082,6 @@ class TerrainLayer extends core.CompositeLayer {
6100
6082
  || props.elevationDecoder !== oldProps.elevationDecoder
6101
6083
  || props.bounds !== oldProps.bounds;
6102
6084
  if (!this.state.isTiled && shouldReload) ;
6103
- // TODO - remove in v9
6104
- // @ts-ignore
6105
6085
  if (props.workerUrl) {
6106
6086
  core.log.removed('workerUrl', 'loadOptions.terrain.workerUrl')();
6107
6087
  }
@@ -6111,36 +6091,47 @@ class TerrainLayer extends core.CompositeLayer {
6111
6091
  return null;
6112
6092
  }
6113
6093
  let loadOptions = this.getLoadOptions();
6114
- loadOptions = Object.assign(Object.assign({}, loadOptions), { _workerType: 'test', terrain: Object.assign(Object.assign({ skirtHeight: this.state.isTiled ? meshMaxError * 2 : 0 }, loadOptions === null || loadOptions === void 0 ? void 0 : loadOptions.terrain), { bounds,
6094
+ loadOptions = {
6095
+ ...loadOptions,
6096
+ _workerType: 'test',
6097
+ terrain: {
6098
+ skirtHeight: this.state.isTiled ? meshMaxError * 2 : 0,
6099
+ ...loadOptions?.terrain,
6100
+ bounds,
6115
6101
  meshMaxError,
6116
- elevationDecoder }) });
6102
+ elevationDecoder,
6103
+ },
6104
+ };
6117
6105
  const { fetch } = this.props;
6118
6106
  return fetch(elevationData, {
6119
6107
  propName: 'elevationData', layer: this, loadOptions, signal, loaders: [],
6120
6108
  });
6121
6109
  }
6122
- getTiledTerrainData(tile) {
6123
- return __awaiter(this, void 0, void 0, function* () {
6124
- this.props;
6125
- const { viewport } = this.context;
6126
- let bottomLeft = [0, 0];
6127
- let topRight = [0, 0];
6128
- if (viewport.isGeospatial) {
6129
- const bbox = tile.bbox;
6130
- bottomLeft = viewport.projectFlat([bbox.west, bbox.south]);
6131
- topRight = viewport.projectFlat([bbox.east, bbox.north]);
6132
- }
6133
- else {
6134
- const bbox = tile.bbox;
6135
- bottomLeft = [bbox.left, bbox.bottom];
6136
- topRight = [bbox.right, bbox.top];
6137
- }
6138
- const bounds = [bottomLeft[0], bottomLeft[1], topRight[0], topRight[1]];
6139
- // TODO - pass signal to getTile
6140
- // abort request if signal is aborted
6141
- const terrain = yield this.state.terrainCogTiles.getTile(tile.index.x, tile.index.y, tile.index.z, bounds, this.props.meshMaxError);
6142
- return Promise.all([terrain]);
6143
- });
6110
+ async getTiledTerrainData(tile) {
6111
+ // const {
6112
+ // elevationData, fetch, texture, elevationDecoder, meshMaxError,
6113
+ // } = this.props;
6114
+ const { viewport } = this.context;
6115
+ // const dataUrl = getURLFromTemplate(elevationData, tile);
6116
+ // const textureUrl = texture && getURLFromTemplate(texture, tile);
6117
+ // const { signal } = tile;
6118
+ let bottomLeft = [0, 0];
6119
+ let topRight = [0, 0];
6120
+ if (viewport.isGeospatial) {
6121
+ const bbox = tile.bbox;
6122
+ bottomLeft = viewport.projectFlat([bbox.west, bbox.south]);
6123
+ topRight = viewport.projectFlat([bbox.east, bbox.north]);
6124
+ }
6125
+ else {
6126
+ const bbox = tile.bbox;
6127
+ bottomLeft = [bbox.left, bbox.bottom];
6128
+ topRight = [bbox.right, bbox.top];
6129
+ }
6130
+ const bounds = [bottomLeft[0], bottomLeft[1], topRight[0], topRight[1]];
6131
+ // TODO - pass signal to getTile
6132
+ // abort request if signal is aborted
6133
+ const terrain = await this.state.terrainCogTiles.getTile(tile.index.x, tile.index.y, tile.index.z, bounds, this.props.meshMaxError);
6134
+ return Promise.all([terrain, null]);
6144
6135
  }
6145
6136
  renderSubLayers(props) {
6146
6137
  const SubLayerClass = this.getSubLayerClass('mesh', meshLayers.SimpleMeshLayer);
@@ -6151,13 +6142,13 @@ class TerrainLayer extends core.CompositeLayer {
6151
6142
  }
6152
6143
  // const [mesh, texture] = data;
6153
6144
  const [mesh] = data;
6154
- return new SubLayerClass(Object.assign(Object.assign({}, props), { tileSize: 256 }), {
6145
+ return new SubLayerClass({ ...props, tileSize: 256 }, {
6155
6146
  data: DUMMY_DATA,
6156
6147
  mesh,
6157
6148
  // texture,
6158
6149
  _instanced: false,
6159
6150
  coordinateSystem: core.COORDINATE_SYSTEM.CARTESIAN,
6160
- getPosition: (d) => [0, 0, 0],
6151
+ // getPosition: (d) => [0, 0, 0],
6161
6152
  getColor: color,
6162
6153
  wireframe,
6163
6154
  material,
@@ -6173,10 +6164,9 @@ class TerrainLayer extends core.CompositeLayer {
6173
6164
  .map((tile) => tile.content)
6174
6165
  .filter((x) => x && x[0])
6175
6166
  .map((arr) => {
6176
- var _a, _b;
6177
- // @ts-ignore
6178
- const bounds = (_b = (_a = arr[0]) === null || _a === void 0 ? void 0 : _a.header) === null || _b === void 0 ? void 0 : _b.boundingBox;
6179
- return bounds === null || bounds === void 0 ? void 0 : bounds.map((bound) => bound[2]);
6167
+ // @ts-expect-error: Tile content structure is not fully typed in the source layer
6168
+ const bounds = arr[0]?.header?.boundingBox;
6169
+ return bounds?.map((bound) => bound[2]);
6180
6170
  });
6181
6171
  if (ranges.length === 0) {
6182
6172
  return;
@@ -6188,7 +6178,13 @@ class TerrainLayer extends core.CompositeLayer {
6188
6178
  }
6189
6179
  }
6190
6180
  renderLayers() {
6191
- const { color, material, elevationData, texture, wireframe, meshMaxError, elevationDecoder, tileSize, extent, maxRequests, onTileLoad, onTileUnload, onTileError, maxCacheSize, maxCacheByteSize, refinementStrategy, } = this.props;
6181
+ const {
6182
+ // color,
6183
+ // material,
6184
+ elevationData,
6185
+ // texture,
6186
+ // wireframe,
6187
+ meshMaxError, elevationDecoder, tileSize, extent, maxRequests, onTileLoad, onTileUnload, onTileError, maxCacheSize, maxCacheByteSize, refinementStrategy, } = this.props;
6192
6188
  if (this.state.isTiled && this.state.initialized) {
6193
6189
  return new geoLayers.TileLayer(this.getSubLayerProps({
6194
6190
  id: 'tiles',
@@ -6239,15 +6235,6 @@ class TerrainLayer extends core.CompositeLayer {
6239
6235
  // );
6240
6236
  }
6241
6237
  }
6242
- TerrainLayer.defaultProps = defaultProps;
6243
- TerrainLayer.layerName = 'TerrainLayer';
6244
-
6245
- var index = {
6246
- CogBitmapLayer,
6247
- CogTerrainLayer: TerrainLayer,
6248
- cogtiles: CogTiles,
6249
- GeoImage,
6250
- };
6251
6238
 
6252
6239
  class RawDecoder extends BaseDecoder {
6253
6240
  decodeBlock(buffer) {
@@ -6256,8 +6243,8 @@ class RawDecoder extends BaseDecoder {
6256
6243
  }
6257
6244
 
6258
6245
  var raw = /*#__PURE__*/Object.freeze({
6259
- __proto__: null,
6260
- default: RawDecoder
6246
+ __proto__: null,
6247
+ default: RawDecoder
6261
6248
  });
6262
6249
 
6263
6250
  const MIN_BITS = 9;
@@ -6391,8 +6378,8 @@ class LZWDecoder extends BaseDecoder {
6391
6378
  }
6392
6379
 
6393
6380
  var lzw = /*#__PURE__*/Object.freeze({
6394
- __proto__: null,
6395
- default: LZWDecoder
6381
+ __proto__: null,
6382
+ default: LZWDecoder
6396
6383
  });
6397
6384
 
6398
6385
  /* -*- tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
@@ -7290,8 +7277,8 @@ class JpegDecoder extends BaseDecoder {
7290
7277
  }
7291
7278
 
7292
7279
  var jpeg = /*#__PURE__*/Object.freeze({
7293
- __proto__: null,
7294
- default: JpegDecoder
7280
+ __proto__: null,
7281
+ default: JpegDecoder
7295
7282
  });
7296
7283
 
7297
7284
  /*! pako 2.1.0 https://github.com/nodeca/pako @license (MIT AND Zlib) */
@@ -14062,8 +14049,8 @@ class DeflateDecoder extends BaseDecoder {
14062
14049
  }
14063
14050
 
14064
14051
  var deflate = /*#__PURE__*/Object.freeze({
14065
- __proto__: null,
14066
- default: DeflateDecoder
14052
+ __proto__: null,
14053
+ default: DeflateDecoder
14067
14054
  });
14068
14055
 
14069
14056
  class PackbitsDecoder extends BaseDecoder {
@@ -14092,8 +14079,8 @@ class PackbitsDecoder extends BaseDecoder {
14092
14079
  }
14093
14080
 
14094
14081
  var packbits = /*#__PURE__*/Object.freeze({
14095
- __proto__: null,
14096
- default: PackbitsDecoder
14082
+ __proto__: null,
14083
+ default: PackbitsDecoder
14097
14084
  });
14098
14085
 
14099
14086
  var LercDecode = {exports: {}};
@@ -16536,9 +16523,9 @@ class LercDecoder extends BaseDecoder {
16536
16523
  }
16537
16524
 
16538
16525
  var lerc = /*#__PURE__*/Object.freeze({
16539
- __proto__: null,
16540
- default: LercDecoder,
16541
- zstd: zstd
16526
+ __proto__: null,
16527
+ default: LercDecoder,
16528
+ zstd: zstd
16542
16529
  });
16543
16530
 
16544
16531
  /**
@@ -16581,9 +16568,12 @@ class WebImageDecoder extends BaseDecoder {
16581
16568
  }
16582
16569
 
16583
16570
  var webimage = /*#__PURE__*/Object.freeze({
16584
- __proto__: null,
16585
- default: WebImageDecoder
16571
+ __proto__: null,
16572
+ default: WebImageDecoder
16586
16573
  });
16587
16574
 
16588
- module.exports = index;
16575
+ exports.CogBitmapLayer = CogBitmapLayer;
16576
+ exports.CogTerrainLayer = CogTerrainLayer;
16577
+ exports.CogTiles = CogTiles;
16578
+ exports.GeoImage = GeoImage;
16589
16579
  //# sourceMappingURL=index.js.map