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