@gisatcz/deckgl-geolib 1.12.0-dev.5 → 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 +609 -672
  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} +10 -26
  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 +606 -672
  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} +10 -26
  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 -483
  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 -602
  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();
5045
- }
5046
- else {
5047
- rasters = input.rasters;
5048
- width = input.width;
5049
- height = input.height;
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];
5050
5026
  }
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
- }
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;
5058
5036
  }
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
- }
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];
5068
5042
  }
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
- }
5043
+ // backfill right border
5044
+ for (let i = height, y = 0; y < height + 1; y++, i += height + 1) {
5045
+ terrain[i] = terrain[i - 1];
5078
5046
  }
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;
@@ -5353,7 +5314,7 @@ class GeoImage {
5353
5314
  }
5354
5315
  // FIXME
5355
5316
  // eslint-disable-next-line
5356
- [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);
5357
5318
  pixel += numOfChannels;
5358
5319
  }
5359
5320
  return colorsArray;
@@ -5443,7 +5404,7 @@ function getMeshAttributes(vertices, terrain, width, height, bounds) {
5443
5404
  function getDelatinTileMesh(meshMaxError, width, height, terrain) {
5444
5405
  const tin = new Delatin(terrain, width + 1, height + 1);
5445
5406
  tin.run(meshMaxError);
5446
- // @ts-expect-error
5407
+ // @ts-expect-error: Delatin instance properties 'coords' and 'triangles' are not explicitly typed in the library port
5447
5408
  const { coords, triangles } = tin;
5448
5409
  const vertices = coords;
5449
5410
  return { vertices, triangles };
@@ -5457,31 +5418,30 @@ const CogTilesGeoImageOptionsDefaults = {
5457
5418
  blurredTexture: true,
5458
5419
  };
5459
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;
5460
5430
  constructor(options) {
5461
- this.cogZoomLookup = [0];
5462
- this.cogResolutionLookup = [0];
5463
- this.cogOrigin = [0, 0];
5464
- this.zoomRange = [0, 0];
5465
- this.loaded = false;
5466
- this.geo = new GeoImage();
5467
- this.options = Object.assign(Object.assign({}, CogTilesGeoImageOptionsDefaults), options);
5468
- }
5469
- initializeCog(url) {
5470
- var _a, _b;
5471
- var _c, _d;
5472
- return __awaiter(this, void 0, void 0, function* () {
5473
- this.cog = yield fromUrl(url);
5474
- const image = yield this.cog.getImage(); // by default, the first image is read.
5475
- this.cogOrigin = image.getOrigin();
5476
- (_a = (_c = this.options).noDataValue) !== null && _a !== void 0 ? _a : (_c.noDataValue = this.getNoDataValue(image));
5477
- (_b = (_d = this.options).format) !== null && _b !== void 0 ? _b : (_d.format = this.getDataTypeFromTags(image));
5478
- this.options.numOfChannels = this.getNumberOfChannels(image);
5479
- this.options.planarConfig = this.getPlanarConfiguration(image);
5480
- [this.cogZoomLookup, this.cogResolutionLookup] = yield this.buildCogZoomResolutionLookup(this.cog);
5481
- this.tileSize = image.getTileWidth();
5482
- this.zoomRange = this.calculateZoomRange(image, yield this.cog.getImageCount());
5483
- this.bounds = this.calculateBoundsAsLatLon(image);
5484
- });
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);
5485
5445
  }
5486
5446
  getZoomRange() {
5487
5447
  return this.zoomRange;
@@ -5533,33 +5493,31 @@ class CogTiles {
5533
5493
  * - The first array (`zoomLookup`) maps each image index to its computed zoom level.
5534
5494
  * - The second array (`resolutionLookup`) maps each image index to its estimated resolution (m/pixel).
5535
5495
  */
5536
- buildCogZoomResolutionLookup(cog) {
5537
- return __awaiter(this, void 0, void 0, function* () {
5538
- // Retrieve the total number of images (overviews) in the COG.
5539
- const imageCount = yield cog.getImageCount();
5540
- // Use the first image as the base reference.
5541
- const baseImage = yield cog.getImage(0);
5542
- const baseResolution = baseImage.getResolution()[0]; // Resolution (m/pixel) of the base image.
5543
- const baseWidth = baseImage.getWidth();
5544
- // Initialize arrays to store the zoom level and resolution for each image.
5545
- const zoomLookup = [];
5546
- const resolutionLookup = [];
5547
- // Iterate over each image (overview) in the COG.
5548
- for (let idx = 0; idx < imageCount; idx++) {
5549
- const image = yield cog.getImage(idx);
5550
- const width = image.getWidth();
5551
- // Calculate the scale factor relative to the base image.
5552
- const scaleFactor = baseWidth / width;
5553
- const estimatedResolution = baseResolution * scaleFactor;
5554
- // Calculate the zoom level using the Web Mercator resolution standard:
5555
- // webMercatorRes0 is the resolution at zoom level 0; each zoom level halves the resolution.
5556
- const zoomLevel = Math.round(Math.log2(webMercatorRes0 / estimatedResolution));
5557
- // console.log(`buildCogZoomResolutionLookup: Image index ${idx}: Estimated Resolution = ${estimatedResolution} m/pixel, Zoom Level = ${zoomLevel}`);
5558
- zoomLookup[idx] = zoomLevel;
5559
- resolutionLookup[idx] = estimatedResolution;
5560
- }
5561
- return [zoomLookup, resolutionLookup];
5562
- });
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];
5563
5521
  }
5564
5522
  /**
5565
5523
  * Determines the appropriate image index from the Cloud Optimized GeoTIFF (COG)
@@ -5588,93 +5546,138 @@ class CogTiles {
5588
5546
  }
5589
5547
  return exactMatchIndex;
5590
5548
  }
5591
- getTileFromImage(tileX, tileY, zoom) {
5592
- return __awaiter(this, void 0, void 0, function* () {
5593
- const imageIndex = this.getImageIndexForZoomLevel(zoom);
5594
- const targetImage = yield this.cog.getImage(imageIndex);
5595
- // Ensure the image is tiled
5596
- const tileWidth = targetImage.getTileWidth();
5597
- const tileHeight = targetImage.getTileHeight();
5598
- if (!tileWidth || !tileHeight) {
5599
- throw new Error('The image is not tiled.');
5600
- }
5601
- // Calculate the map offset between the global Web Mercator origin and the COG's origin.
5602
- // (Difference in map units.)
5603
- // if X offset is large and positive (COG is far to the right of global origin)
5604
- // if Y offset is large and positive (COG is far below global origin — expected)
5605
- const offsetXMap = this.cogOrigin[0] - webMercatorOrigin[0];
5606
- const offsetYMap = webMercatorOrigin[1] - this.cogOrigin[1];
5607
- const tileResolution = (EARTH_CIRCUMFERENCE / tileWidth) / Math.pow(2, zoom);
5608
- this.cogResolutionLookup[imageIndex];
5609
- // Convert map offsets into pixel offsets.
5610
- const offsetXPixel = Math.floor(offsetXMap / tileResolution);
5611
- const offsetYPixel = Math.floor(offsetYMap / tileResolution);
5612
- const imageHeight = targetImage.getHeight();
5613
- const imageWidth = targetImage.getWidth();
5614
- // approach by comparing bboxes of tile and cog image
5615
- const tilePixelBbox = [
5616
- tileX * tileWidth,
5617
- tileY * tileHeight,
5618
- (tileX + 1) * tileWidth,
5619
- (tileY + 1) * tileHeight,
5620
- ];
5621
- const cogPixelBBox = [
5622
- offsetXPixel,
5623
- offsetYPixel,
5624
- offsetXPixel + imageWidth,
5625
- offsetYPixel + imageHeight,
5626
- ];
5627
- const intersecion = this.getIntersectionBBox(tilePixelBbox, cogPixelBBox, offsetXPixel, offsetYPixel, tileWidth);
5628
- const [validWidth, validHeight, window, missingLeft, missingTop] = intersecion;
5629
- // Read the raster data for the tile window with shifted origin.
5630
- if (missingLeft > 0 || missingTop > 0 || validWidth < tileWidth || validHeight < tileHeight) {
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
- // 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
5635
- const validRasterData = yield targetImage.readRasters({ window });
5636
- // FOR MULTI-BAND - the result is one array with sequentially typed bands, firstly all data for the band 0, then for band 1
5637
- // 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.
5638
- const validImageData = Array(validRasterData.length * validRasterData[0].length);
5639
- validImageData.fill(this.options.noDataValue);
5640
- // Place the valid pixel data into the tile buffer.
5641
- for (let band = 0; band < validRasterData.length; band++) {
5642
- for (let row = 0; row < validHeight; row++) {
5643
- for (let col = 0; col < validWidth; col++) {
5644
- // Compute the destination position in the tile buffer.
5645
- // We shift by the number of missing pixels (if any) at the top/left.
5646
- const destRow = missingTop + row;
5647
- const destCol = missingLeft + col;
5648
- if (destRow < tileWidth && destCol < tileHeight) {
5649
- tileBuffer[destRow * tileWidth + destCol] = validRasterData[band][row * validRasterData.width + col];
5650
- }
5651
- else {
5652
- console.log('error in assigning data to tile buffer');
5653
- }
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');
5654
5639
  }
5655
5640
  }
5656
- tileBuffer.forEach((rasterValue, index) => {
5657
- validImageData[index * this.options.numOfChannels + band] = rasterValue;
5658
- });
5659
5641
  }
5660
- return [validImageData];
5642
+ for (let i = 0; i < tileBuffer.length; i += 1) {
5643
+ validImageData[i * this.options.numOfChannels + band] = tileBuffer[i];
5644
+ }
5661
5645
  }
5662
- // Read the raster data for the non shifted tile window.
5663
- const tileData = yield targetImage.readRasters({ window, interleave: true });
5664
- // console.log(`data that starts at the left top corner of the tile ${tileX}, ${tileY}`);
5665
- return [tileData];
5666
- });
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];
5667
5654
  }
5668
- getTile(x, y, z, bounds, meshMaxError) {
5669
- return __awaiter(this, void 0, void 0, function* () {
5670
- const tileData = yield this.getTileFromImage(x, y, z);
5671
- return this.geo.getMap({
5672
- rasters: [tileData[0]],
5673
- width: this.tileSize,
5674
- height: this.tileSize,
5675
- bounds,
5676
- }, this.options, meshMaxError);
5677
- });
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);
5678
5681
  }
5679
5682
  /**
5680
5683
  * Determines the data type (e.g., "Int32", "Float64") of a GeoTIFF image
@@ -5757,53 +5760,6 @@ class CogTiles {
5757
5760
  getNumberOfChannels(image) {
5758
5761
  return image.getSamplesPerPixel();
5759
5762
  }
5760
- /**
5761
- * Calculates the intersection between a tile bounding box and a COG bounding box,
5762
- * returning the intersection window in image pixel space (relative to COG offsets),
5763
- * along with how much blank space (nodata) appears on the left and top of the tile.
5764
- *
5765
- * @param {number[]} tileBbox - Tile bounding box: [minX, minY, maxX, maxY]
5766
- * @param {number[]} cogBbox - COG bounding box: [minX, minY, maxX, maxY]
5767
- * @param {number} offsetXPixel - X offset of the COG origin in pixel space
5768
- * @param {number} offsetYPixel - Y offset of the COG origin in pixel space
5769
- * @param {number} tileSize - Size of the tile in pixels (default: 256)
5770
- * @returns {[number, number, number[] | null, number, number]}
5771
- * An array containing:
5772
- * - width of the intersection
5773
- * - height of the intersection
5774
- * - pixel-space window: [startX, startY, endX, endY] or null if no overlap
5775
- * - missingLeft: padding pixels on the left
5776
- * - missingTop: padding pixels on the top
5777
- */
5778
- getIntersectionBBox(tileBbox, cogBbox, offsetXPixel = 0, offsetYPixel = 0, tileSize = 256) {
5779
- const interLeft = Math.max(tileBbox[0], cogBbox[0]);
5780
- const interTop = Math.max(tileBbox[1], cogBbox[1]);
5781
- const interRight = Math.min(tileBbox[2], cogBbox[2]);
5782
- const interBottom = Math.min(tileBbox[3], cogBbox[3]);
5783
- const width = Math.max(0, interRight - interLeft);
5784
- const height = Math.max(0, interBottom - interTop);
5785
- let window = null;
5786
- let missingLeft = 0;
5787
- let missingTop = 0;
5788
- if (width > 0 && height > 0) {
5789
- window = [
5790
- interLeft - offsetXPixel,
5791
- interTop - offsetYPixel,
5792
- interRight - offsetXPixel,
5793
- interBottom - offsetYPixel,
5794
- ];
5795
- // Padding from the tile origin to valid data start
5796
- missingLeft = interLeft - tileBbox[0];
5797
- missingTop = interTop - tileBbox[1];
5798
- }
5799
- return [
5800
- width,
5801
- height,
5802
- window,
5803
- missingLeft,
5804
- missingTop,
5805
- ];
5806
- }
5807
5763
  /**
5808
5764
  * Retrieves the PlanarConfiguration value from a GeoTIFF image.
5809
5765
  *
@@ -5876,7 +5832,8 @@ const urlType$1 = {
5876
5832
  return true;
5877
5833
  },
5878
5834
  };
5879
- const defaultProps$1 = Object.assign(Object.assign({}, TileLayer.defaultProps), {
5835
+ const defaultProps$1 = {
5836
+ ...TileLayer.defaultProps,
5880
5837
  // Image url that encodes height data
5881
5838
  // elevationData: urlType,
5882
5839
  // Image url to use as texture
@@ -5886,10 +5843,9 @@ const defaultProps$1 = Object.assign(Object.assign({}, TileLayer.defaultProps),
5886
5843
  // Bounding box of the terrain image, [minX, minY, maxX, maxY] in world coordinates
5887
5844
  bounds: {
5888
5845
  type: 'array', value: null, optional: true, compare: true,
5889
- }, rasterData: urlType$1,
5890
- // Color to use if texture is unavailable
5891
- // color: { type: 'color', value: [255, 255, 255] },
5892
- blurredTexture: true, opacity: 1, clampToTerrain: false,
5846
+ },
5847
+ rasterData: urlType$1,
5848
+ clampToTerrain: false,
5893
5849
  // Object to decode height data, from (r, g, b) to height in meters
5894
5850
  // elevationDecoder: {
5895
5851
  // type: 'object',
@@ -5901,40 +5857,31 @@ const defaultProps$1 = Object.assign(Object.assign({}, TileLayer.defaultProps),
5901
5857
  // },
5902
5858
  // },
5903
5859
  // Supply url to local terrain worker bundle. Only required if running offline and cannot access CDN.
5904
- workerUrl: '' });
5860
+ workerUrl: '',
5861
+ // Same as SimpleMeshLayer wireframe
5862
+ // wireframe: false,
5863
+ // material: true,
5864
+ // loaders: [TerrainLoader],
5865
+ };
5905
5866
  /** Render bitmap texture from cog raster images. */
5906
5867
  class CogBitmapLayer extends CompositeLayer {
5907
- // private _isLoaded: boolean;
5908
- // id = '';
5909
- // url: string;
5910
- // static displayName: string;
5911
- // cogTiles: CogTiles;
5912
- //
5913
- // tileSize: number;
5914
- //
5915
- initializeState(context) {
5916
- const _super = Object.create(null, {
5917
- initializeState: { get: () => super.initializeState }
5918
- });
5919
- return __awaiter(this, void 0, void 0, function* () {
5920
- _super.initializeState.call(this, context);
5921
- this.setState({
5922
- bitmapCogTiles: new CogTiles(this.props.cogBitmapOptions),
5923
- initialized: false,
5924
- });
5925
- 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,
5926
5875
  });
5876
+ await this.init();
5927
5877
  }
5928
- init() {
5929
- return __awaiter(this, void 0, void 0, function* () {
5930
- yield this.state.bitmapCogTiles.initializeCog(this.props.rasterData);
5931
- const zoomRange = this.state.bitmapCogTiles.getZoomRange();
5932
- const [minZoom, maxZoom] = zoomRange;
5933
- this.setState({ initialized: true, minZoom, maxZoom });
5934
- });
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 });
5935
5883
  }
5936
5884
  updateState({ props, oldProps }) {
5937
- var _a, _b, _c;
5938
5885
  const rasterDataChanged = props.rasterData !== oldProps.rasterData;
5939
5886
  if (rasterDataChanged) {
5940
5887
  const { rasterData } = props;
@@ -5954,45 +5901,47 @@ class CogBitmapLayer extends CompositeLayer {
5954
5901
  // object in this way is not ideal and may need refactoring in the future to follow a more
5955
5902
  // declarative state management approach. Consider revisiting this if additional properties
5956
5903
  // need to be synchronized or if the state structure changes.
5957
- 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)) {
5958
5905
  this.state.bitmapCogTiles.options.useChannel = props.cogBitmapOptions.useChannel;
5959
5906
  }
5960
- // TODO - remove in v9
5961
- // @ts-ignore
5962
5907
  if (props.workerUrl) {
5963
5908
  log.removed('workerUrl', 'loadOptions.terrain.workerUrl')();
5964
5909
  }
5965
5910
  }
5966
- getTiledBitmapData(tile) {
5967
- return __awaiter(this, void 0, void 0, function* () {
5968
- // TODO - pass signal to getTile
5969
- // abort request if signal is aborted
5970
- const tileData = yield this.state.bitmapCogTiles.getTile(tile.index.x, tile.index.y, tile.index.z);
5971
- return tileData;
5972
- });
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;
5973
5916
  }
5974
5917
  renderSubLayers(props) {
5975
5918
  const SubLayerClass = this.getSubLayerClass('image', BitmapLayer);
5976
5919
  const { blurredTexture } = this.state.bitmapCogTiles.options;
5977
- const { opacity, clampToTerrain } = this.props;
5920
+ const { clampToTerrain } = this.props;
5921
+ const hasDrawMode = typeof clampToTerrain === 'object' && clampToTerrain !== null && 'terrainDrawMode' in clampToTerrain;
5978
5922
  const { data } = props;
5979
5923
  if (!data) {
5980
5924
  return null;
5981
5925
  }
5982
5926
  const { bbox: { west, south, east, north, }, } = props.tile;
5983
- 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: {
5984
5933
  minFilter: blurredTexture ? 'linear' : 'nearest',
5985
5934
  magFilter: blurredTexture ? 'linear' : 'nearest',
5986
- },
5935
+ },
5987
5936
  // TODO check if works!!!
5988
- extensions: clampToTerrain ? [new _TerrainExtension()] : [] }, ((clampToTerrain === null || clampToTerrain === void 0 ? void 0 : clampToTerrain.terrainDrawMode)
5989
- ? { terrainDrawMode: clampToTerrain.terrainDrawMode }
5990
- : {})));
5937
+ extensions: clampToTerrain ? [new _TerrainExtension()] : [],
5938
+ ...(hasDrawMode
5939
+ ? { terrainDrawMode: clampToTerrain.terrainDrawMode }
5940
+ : {}),
5941
+ });
5991
5942
  }
5992
5943
  renderLayers() {
5993
- const { rasterData, blurredTexture, opacity, clampToTerrain,
5994
- // tileSize,
5995
- maxRequests, onTileLoad, onTileUnload, onTileError, maxCacheSize, maxCacheByteSize, refinementStrategy, cogBitmapOptions, } = this.props;
5944
+ const { clampToTerrain, maxRequests, onTileLoad, onTileUnload, onTileError, maxCacheSize, maxCacheByteSize, refinementStrategy, cogBitmapOptions, } = this.props;
5996
5945
  if (this.state.isTiled && this.state.initialized) {
5997
5946
  const { tileSize } = this.state.bitmapCogTiles;
5998
5947
  return new TileLayer(this.getSubLayerProps({
@@ -6027,28 +5976,7 @@ class CogBitmapLayer extends CompositeLayer {
6027
5976
  return null;
6028
5977
  }
6029
5978
  }
6030
- CogBitmapLayer.defaultProps = defaultProps$1;
6031
- CogBitmapLayer.layerName = 'CogBitmapLayer';
6032
5979
 
6033
- // Copyright (c) 2015 - 2017 Uber Technologies, Inc.
6034
- //
6035
- // Permission is hereby granted, free of charge, to any person obtaining a copy
6036
- // of this software and associated documentation files (the "Software"), to deal
6037
- // in the Software without restriction, including without limitation the rights
6038
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
6039
- // copies of the Software, and to permit persons to whom the Software is
6040
- // furnished to do so, subject to the following conditions:
6041
- //
6042
- // The above copyright notice and this permission notice shall be included in
6043
- // all copies or substantial portions of the Software.
6044
- //
6045
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6046
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6047
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
6048
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
6049
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
6050
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
6051
- // THE SOFTWARE.
6052
5980
  const urlType = {
6053
5981
  type: 'object',
6054
5982
  value: null,
@@ -6075,19 +6003,20 @@ const urlType = {
6075
6003
  },
6076
6004
  };
6077
6005
  const DUMMY_DATA = [1];
6078
- const defaultProps = Object.assign(Object.assign({}, TileLayer.defaultProps), {
6006
+ const defaultProps = {
6007
+ ...TileLayer.defaultProps,
6079
6008
  // Image url that encodes height data
6080
- elevationData: urlType,
6009
+ elevationData: urlType,
6081
6010
  // Image url to use as texture
6082
- texture: Object.assign(Object.assign({}, urlType), { optional: true }),
6011
+ texture: { ...urlType, optional: true },
6083
6012
  // Martini error tolerance in meters, smaller number -> more detailed mesh
6084
- meshMaxError: { type: 'number', value: 4.0 },
6013
+ meshMaxError: { type: 'number', value: 4.0 },
6085
6014
  // Bounding box of the terrain image, [minX, minY, maxX, maxY] in world coordinates
6086
6015
  bounds: {
6087
6016
  type: 'array', value: null, optional: true, compare: true,
6088
- },
6017
+ },
6089
6018
  // Color to use if texture is unavailable
6090
- color: { type: 'color', value: [255, 255, 255] },
6019
+ color: { type: 'color', value: [255, 255, 255] },
6091
6020
  // Object to decode height data, from (r, g, b) to height in meters
6092
6021
  elevationDecoder: {
6093
6022
  type: 'object',
@@ -6097,11 +6026,14 @@ const defaultProps = Object.assign(Object.assign({}, TileLayer.defaultProps), {
6097
6026
  bScaler: 0,
6098
6027
  offset: 0,
6099
6028
  },
6100
- },
6029
+ },
6101
6030
  // Supply url to local terrain worker bundle. Only required if running offline and cannot access CDN.
6102
- workerUrl: '',
6031
+ workerUrl: '',
6103
6032
  // Same as SimpleMeshLayer wireframe
6104
- wireframe: false, material: true });
6033
+ wireframe: false,
6034
+ material: true,
6035
+ // loaders: [TerrainLoader],
6036
+ };
6105
6037
  // Turns array of templates into a single string to work around shallow change
6106
6038
  function urlTemplateToUpdateTrigger(template) {
6107
6039
  if (Array.isArray(template)) {
@@ -6113,28 +6045,25 @@ function urlTemplateToUpdateTrigger(template) {
6113
6045
  // TODO use meshMaxError
6114
6046
  // TODO - pass signal to getTile
6115
6047
  /** Render mesh surfaces from height map images. */
6116
- class TerrainLayer extends CompositeLayer {
6117
- initializeState(context) {
6118
- const _super = Object.create(null, {
6119
- initializeState: { get: () => super.initializeState }
6120
- });
6121
- return __awaiter(this, void 0, void 0, function* () {
6122
- _super.initializeState.call(this, context);
6123
- this.setState({
6124
- terrainCogTiles: new CogTiles(this.props.terrainOptions),
6125
- initialized: false,
6126
- });
6127
- 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,
6128
6058
  });
6059
+ await this.init(this.terrainUrl);
6129
6060
  }
6130
- init(terrainUrl) {
6131
- return __awaiter(this, void 0, void 0, function* () {
6132
- yield this.state.terrainCogTiles.initializeCog(this.props.elevationData);
6133
- // this.tileSize = this.terrainCogTiles.getTileSize(cog);
6134
- const zoomRange = this.state.terrainCogTiles.getZoomRange();
6135
- const [minZoom, maxZoom] = zoomRange;
6136
- this.setState({ initialized: true, minZoom, maxZoom });
6137
- });
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 });
6138
6067
  }
6139
6068
  updateState({ props, oldProps }) {
6140
6069
  const elevationDataChanged = props.elevationData !== oldProps.elevationData;
@@ -6151,8 +6080,6 @@ class TerrainLayer extends CompositeLayer {
6151
6080
  || props.elevationDecoder !== oldProps.elevationDecoder
6152
6081
  || props.bounds !== oldProps.bounds;
6153
6082
  if (!this.state.isTiled && shouldReload) ;
6154
- // TODO - remove in v9
6155
- // @ts-ignore
6156
6083
  if (props.workerUrl) {
6157
6084
  log.removed('workerUrl', 'loadOptions.terrain.workerUrl')();
6158
6085
  }
@@ -6162,36 +6089,47 @@ class TerrainLayer extends CompositeLayer {
6162
6089
  return null;
6163
6090
  }
6164
6091
  let loadOptions = this.getLoadOptions();
6165
- 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,
6166
6099
  meshMaxError,
6167
- elevationDecoder }) });
6100
+ elevationDecoder,
6101
+ },
6102
+ };
6168
6103
  const { fetch } = this.props;
6169
6104
  return fetch(elevationData, {
6170
6105
  propName: 'elevationData', layer: this, loadOptions, signal, loaders: [],
6171
6106
  });
6172
6107
  }
6173
- getTiledTerrainData(tile) {
6174
- return __awaiter(this, void 0, void 0, function* () {
6175
- this.props;
6176
- const { viewport } = this.context;
6177
- let bottomLeft = [0, 0];
6178
- let topRight = [0, 0];
6179
- if (viewport.isGeospatial) {
6180
- const bbox = tile.bbox;
6181
- bottomLeft = viewport.projectFlat([bbox.west, bbox.south]);
6182
- topRight = viewport.projectFlat([bbox.east, bbox.north]);
6183
- }
6184
- else {
6185
- const bbox = tile.bbox;
6186
- bottomLeft = [bbox.left, bbox.bottom];
6187
- topRight = [bbox.right, bbox.top];
6188
- }
6189
- const bounds = [bottomLeft[0], bottomLeft[1], topRight[0], topRight[1]];
6190
- // TODO - pass signal to getTile
6191
- // abort request if signal is aborted
6192
- const terrain = yield this.state.terrainCogTiles.getTile(tile.index.x, tile.index.y, tile.index.z, bounds, this.props.meshMaxError);
6193
- return Promise.all([terrain]);
6194
- });
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]);
6195
6133
  }
6196
6134
  renderSubLayers(props) {
6197
6135
  const SubLayerClass = this.getSubLayerClass('mesh', SimpleMeshLayer);
@@ -6202,13 +6140,13 @@ class TerrainLayer extends CompositeLayer {
6202
6140
  }
6203
6141
  // const [mesh, texture] = data;
6204
6142
  const [mesh] = data;
6205
- return new SubLayerClass(Object.assign(Object.assign({}, props), { tileSize: 256 }), {
6143
+ return new SubLayerClass({ ...props, tileSize: 256 }, {
6206
6144
  data: DUMMY_DATA,
6207
6145
  mesh,
6208
6146
  // texture,
6209
6147
  _instanced: false,
6210
6148
  coordinateSystem: COORDINATE_SYSTEM.CARTESIAN,
6211
- getPosition: (d) => [0, 0, 0],
6149
+ // getPosition: (d) => [0, 0, 0],
6212
6150
  getColor: color,
6213
6151
  wireframe,
6214
6152
  material,
@@ -6224,10 +6162,9 @@ class TerrainLayer extends CompositeLayer {
6224
6162
  .map((tile) => tile.content)
6225
6163
  .filter((x) => x && x[0])
6226
6164
  .map((arr) => {
6227
- var _a, _b;
6228
- // @ts-ignore
6229
- const bounds = (_b = (_a = arr[0]) === null || _a === void 0 ? void 0 : _a.header) === null || _b === void 0 ? void 0 : _b.boundingBox;
6230
- 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]);
6231
6168
  });
6232
6169
  if (ranges.length === 0) {
6233
6170
  return;
@@ -6239,7 +6176,13 @@ class TerrainLayer extends CompositeLayer {
6239
6176
  }
6240
6177
  }
6241
6178
  renderLayers() {
6242
- 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;
6243
6186
  if (this.state.isTiled && this.state.initialized) {
6244
6187
  return new TileLayer(this.getSubLayerProps({
6245
6188
  id: 'tiles',
@@ -6290,15 +6233,6 @@ class TerrainLayer extends CompositeLayer {
6290
6233
  // );
6291
6234
  }
6292
6235
  }
6293
- TerrainLayer.defaultProps = defaultProps;
6294
- TerrainLayer.layerName = 'TerrainLayer';
6295
-
6296
- var index = {
6297
- CogBitmapLayer,
6298
- CogTerrainLayer: TerrainLayer,
6299
- cogtiles: CogTiles,
6300
- GeoImage,
6301
- };
6302
6236
 
6303
6237
  class RawDecoder extends BaseDecoder {
6304
6238
  decodeBlock(buffer) {
@@ -6307,8 +6241,8 @@ class RawDecoder extends BaseDecoder {
6307
6241
  }
6308
6242
 
6309
6243
  var raw = /*#__PURE__*/Object.freeze({
6310
- __proto__: null,
6311
- default: RawDecoder
6244
+ __proto__: null,
6245
+ default: RawDecoder
6312
6246
  });
6313
6247
 
6314
6248
  const MIN_BITS = 9;
@@ -6442,8 +6376,8 @@ class LZWDecoder extends BaseDecoder {
6442
6376
  }
6443
6377
 
6444
6378
  var lzw = /*#__PURE__*/Object.freeze({
6445
- __proto__: null,
6446
- default: LZWDecoder
6379
+ __proto__: null,
6380
+ default: LZWDecoder
6447
6381
  });
6448
6382
 
6449
6383
  /* -*- tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
@@ -7341,8 +7275,8 @@ class JpegDecoder extends BaseDecoder {
7341
7275
  }
7342
7276
 
7343
7277
  var jpeg = /*#__PURE__*/Object.freeze({
7344
- __proto__: null,
7345
- default: JpegDecoder
7278
+ __proto__: null,
7279
+ default: JpegDecoder
7346
7280
  });
7347
7281
 
7348
7282
  /*! pako 2.1.0 https://github.com/nodeca/pako @license (MIT AND Zlib) */
@@ -14113,8 +14047,8 @@ class DeflateDecoder extends BaseDecoder {
14113
14047
  }
14114
14048
 
14115
14049
  var deflate = /*#__PURE__*/Object.freeze({
14116
- __proto__: null,
14117
- default: DeflateDecoder
14050
+ __proto__: null,
14051
+ default: DeflateDecoder
14118
14052
  });
14119
14053
 
14120
14054
  class PackbitsDecoder extends BaseDecoder {
@@ -14143,8 +14077,8 @@ class PackbitsDecoder extends BaseDecoder {
14143
14077
  }
14144
14078
 
14145
14079
  var packbits = /*#__PURE__*/Object.freeze({
14146
- __proto__: null,
14147
- default: PackbitsDecoder
14080
+ __proto__: null,
14081
+ default: PackbitsDecoder
14148
14082
  });
14149
14083
 
14150
14084
  var LercDecode = {exports: {}};
@@ -16587,9 +16521,9 @@ class LercDecoder extends BaseDecoder {
16587
16521
  }
16588
16522
 
16589
16523
  var lerc = /*#__PURE__*/Object.freeze({
16590
- __proto__: null,
16591
- default: LercDecoder,
16592
- zstd: zstd
16524
+ __proto__: null,
16525
+ default: LercDecoder,
16526
+ zstd: zstd
16593
16527
  });
16594
16528
 
16595
16529
  /**
@@ -16632,9 +16566,9 @@ class WebImageDecoder extends BaseDecoder {
16632
16566
  }
16633
16567
 
16634
16568
  var webimage = /*#__PURE__*/Object.freeze({
16635
- __proto__: null,
16636
- default: WebImageDecoder
16569
+ __proto__: null,
16570
+ default: WebImageDecoder
16637
16571
  });
16638
16572
 
16639
- export { index as default };
16573
+ export { CogBitmapLayer, CogTerrainLayer, CogTiles, GeoImage };
16640
16574
  //# sourceMappingURL=index.js.map