@gisatcz/deckgl-geolib 1.12.0-dev.13 → 1.12.0-dev.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cjs/index.js CHANGED
@@ -9,38 +9,6 @@ var schema = require('@loaders.gl/schema');
9
9
  var loaderUtils = require('@loaders.gl/loader-utils');
10
10
  var meshLayers = require('@deck.gl/mesh-layers');
11
11
 
12
- /******************************************************************************
13
- Copyright (c) Microsoft Corporation.
14
-
15
- Permission to use, copy, modify, and/or distribute this software for any
16
- purpose with or without fee is hereby granted.
17
-
18
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
19
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
20
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
21
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
22
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
23
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
24
- PERFORMANCE OF THIS SOFTWARE.
25
- ***************************************************************************** */
26
- /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
27
-
28
-
29
- function __awaiter(thisArg, _arguments, P, generator) {
30
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
31
- return new (P || (P = Promise))(function (resolve, reject) {
32
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
33
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
34
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
35
- step((generator = generator.apply(thisArg, _arguments || [])).next());
36
- });
37
- }
38
-
39
- typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
40
- var e = new Error(message);
41
- return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
42
- };
43
-
44
12
  /* eslint-disable no-restricted-globals, no-restricted-syntax */
45
13
  /* global SharedArrayBuffer */
46
14
 
@@ -4443,6 +4411,29 @@ class Tile {
4443
4411
  // loaders.gl
4444
4412
  // SPDX-License-Identifier: MIT
4445
4413
  // Copyright (c) vis.gl contributors
4414
+ /**
4415
+ * Get geometry edges that located on a border of the mesh
4416
+ * @param {object} indices - edge indices from quantized mesh data
4417
+ * @param {TypedArray} position - position attribute geometry data
4418
+ * @returns {number[][]} - outside edges data
4419
+ */
4420
+ function getOutsideEdgesFromIndices(indices, position) {
4421
+ // Sort skirt indices to create adjacent triangles
4422
+ indices.westIndices.sort((a, b) => position[3 * a + 1] - position[3 * b + 1]);
4423
+ // Reverse (b - a) to match triangle winding
4424
+ indices.eastIndices.sort((a, b) => position[3 * b + 1] - position[3 * a + 1]);
4425
+ indices.southIndices.sort((a, b) => position[3 * b] - position[3 * a]);
4426
+ // Reverse (b - a) to match triangle winding
4427
+ indices.northIndices.sort((a, b) => position[3 * a] - position[3 * b]);
4428
+ const edges = [];
4429
+ for (const index in indices) {
4430
+ const indexGroup = indices[index];
4431
+ for (let i = 0; i < indexGroup.length - 1; i++) {
4432
+ edges.push([indexGroup[i], indexGroup[i + 1]]);
4433
+ }
4434
+ }
4435
+ return edges;
4436
+ }
4446
4437
  /**
4447
4438
  * Add skirt to existing mesh
4448
4439
  * @param {object} attributes - POSITION and TEXCOOD_0 attributes data
@@ -4488,7 +4479,6 @@ function addSkirt(attributes, triangles, skirtHeight, outsideIndices) {
4488
4479
  * @returns {number[][]} - outside edges data
4489
4480
  */
4490
4481
  function getOutsideEdgesFromTriangles(triangles) {
4491
- var _a, _b;
4492
4482
  const edges = [];
4493
4483
  for (let i = 0; i < triangles.length; i += 3) {
4494
4484
  edges.push([triangles[i], triangles[i + 1]]);
@@ -4499,7 +4489,7 @@ function getOutsideEdgesFromTriangles(triangles) {
4499
4489
  const outsideEdges = [];
4500
4490
  let index = 0;
4501
4491
  while (index < edges.length) {
4502
- if (edges[index][0] === ((_a = edges[index + 1]) === null || _a === void 0 ? void 0 : _a[1]) && edges[index][1] === ((_b = edges[index + 1]) === null || _b === void 0 ? void 0 : _b[0])) {
4492
+ if (edges[index][0] === edges[index + 1]?.[1] && edges[index][1] === edges[index + 1]?.[0]) {
4503
4493
  index += 2;
4504
4494
  }
4505
4495
  else {
@@ -4509,29 +4499,6 @@ function getOutsideEdgesFromTriangles(triangles) {
4509
4499
  }
4510
4500
  return outsideEdges;
4511
4501
  }
4512
- /**
4513
- * Get geometry edges that located on a border of the mesh
4514
- * @param {object} indices - edge indices from quantized mesh data
4515
- * @param {TypedArray} position - position attribute geometry data
4516
- * @returns {number[][]} - outside edges data
4517
- */
4518
- function getOutsideEdgesFromIndices(indices, position) {
4519
- // Sort skirt indices to create adjacent triangles
4520
- indices.westIndices.sort((a, b) => position[3 * a + 1] - position[3 * b + 1]);
4521
- // Reverse (b - a) to match triangle winding
4522
- indices.eastIndices.sort((a, b) => position[3 * b + 1] - position[3 * a + 1]);
4523
- indices.southIndices.sort((a, b) => position[3 * b] - position[3 * a]);
4524
- // Reverse (b - a) to match triangle winding
4525
- indices.northIndices.sort((a, b) => position[3 * a] - position[3 * b]);
4526
- const edges = [];
4527
- for (const index in indices) {
4528
- const indexGroup = indices[index];
4529
- for (let i = 0; i < indexGroup.length - 1; i++) {
4530
- edges.push([indexGroup[i], indexGroup[i + 1]]);
4531
- }
4532
- }
4533
- return edges;
4534
- }
4535
4502
  /**
4536
4503
  * Get geometry edges that located on a border of the mesh
4537
4504
  * @param {object} args
@@ -4572,7 +4539,12 @@ function updateAttributesForNewEdge({ edge, edgeIndex, attributes, skirtHeight,
4572
4539
  // Copyright (c) vis.gl contributors
4573
4540
  // ISC License
4574
4541
  // Copyright(c) 2019, Michael Fogleman, Vladimir Agafonkin
4542
+ /* eslint-disable @typescript-eslint/ban-ts-comment */
4575
4543
  // @ts-nocheck
4544
+ /* eslint-enable @typescript-eslint/ban-ts-comment */
4545
+ function orient(ax, ay, bx, by, cx, cy) {
4546
+ return (bx - cx) * (ay - cy) - (by - cy) * (ax - cx);
4547
+ }
4576
4548
  /* eslint-disable complexity, max-params, max-statements, max-depth, no-constant-condition */
4577
4549
  class Delatin {
4578
4550
  constructor(data, width, height = width) {
@@ -4960,9 +4932,6 @@ class Delatin {
4960
4932
  return i > i0;
4961
4933
  }
4962
4934
  }
4963
- function orient(ax, ay, bx, by, cx, cy) {
4964
- return (bx - cx) * (ay - cy) - (by - cy) * (ax - cx);
4965
- }
4966
4935
  function inCircle(ax, ay, bx, by, cx, cy, px, py) {
4967
4936
  const dx = ax - px;
4968
4937
  const dy = ay - py;
@@ -4976,7 +4945,7 @@ function inCircle(ax, ay, bx, by, cx, cy, px, py) {
4976
4945
  return dx * (ey * cp - bp * fy) - dy * (ex * cp - bp * fx) + ap * (ex * fy - ey * fx) < 0;
4977
4946
  }
4978
4947
 
4979
- /* eslint 'max-len': [1, { code: 105, comments: 999, ignoreStrings: true, ignoreUrls: true }] */
4948
+ // import { ExtentsLeftBottomRightTop } from '@deck.gl/core/utils/positions';
4980
4949
  // FIXME - tesselator as a parameter
4981
4950
  const tesselator = 'martini';
4982
4951
  const DefaultGeoImageOptions = {
@@ -5011,279 +4980,264 @@ const DefaultGeoImageOptions = {
5011
4980
  planarConfig: undefined,
5012
4981
  };
5013
4982
  class GeoImage {
5014
- constructor() {
5015
- this.scale = (num, inMin, inMax, outMin, outMax) => ((num - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin;
5016
- }
5017
- setUrl(url) {
5018
- return __awaiter(this, void 0, void 0, function* () {
5019
- // TODO - not tested
5020
- const response = yield fetch(url);
5021
- const arrayBuffer = yield response.arrayBuffer();
5022
- const tiff = yield fromArrayBuffer(arrayBuffer);
5023
- const data = yield tiff.getImage(0);
5024
- this.data = data;
5025
- });
5026
- }
5027
- getMap(input, options, meshMaxError) {
5028
- return __awaiter(this, void 0, void 0, function* () {
5029
- const mergedOptions = Object.assign(Object.assign({}, DefaultGeoImageOptions), options);
5030
- switch (mergedOptions.type) {
5031
- case 'image':
5032
- return this.getBitmap(input, mergedOptions);
5033
- case 'terrain':
5034
- return this.getHeightmap(input, mergedOptions, meshMaxError);
5035
- default:
5036
- return null;
5037
- }
5038
- });
4983
+ data;
4984
+ scale = (num, inMin, inMax, outMin, outMax) => ((num - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin;
4985
+ async setUrl(url) {
4986
+ // TODO - not tested
4987
+ const response = await fetch(url);
4988
+ const arrayBuffer = await response.arrayBuffer();
4989
+ const tiff = await fromArrayBuffer(arrayBuffer);
4990
+ const data = await tiff.getImage(0);
4991
+ this.data = data;
4992
+ }
4993
+ async getMap(input, options, meshMaxError) {
4994
+ const mergedOptions = { ...DefaultGeoImageOptions, ...options };
4995
+ switch (mergedOptions.type) {
4996
+ case 'image':
4997
+ return this.getBitmap(input, mergedOptions);
4998
+ case 'terrain':
4999
+ return this.getHeightmap(input, mergedOptions, meshMaxError);
5000
+ default:
5001
+ return null;
5002
+ }
5039
5003
  }
5040
5004
  // GetHeightmap uses only "useChannel" and "multiplier" options
5041
- getHeightmap(input, options, meshMaxError) {
5042
- return __awaiter(this, void 0, void 0, function* () {
5043
- var _a;
5044
- let rasters = [];
5045
- let width;
5046
- let height;
5047
- if (typeof (input) === 'string') {
5048
- // TODO not tested
5049
- // input is type of object
5050
- yield this.setUrl(input);
5051
- rasters = (yield this.data.readRasters());
5052
- width = this.data.getWidth();
5053
- height = this.data.getHeight();
5054
- }
5055
- else {
5056
- rasters = input.rasters;
5057
- width = input.width;
5058
- height = input.height;
5005
+ async getHeightmap(input, options, meshMaxError) {
5006
+ let rasters = [];
5007
+ let width;
5008
+ let height;
5009
+ if (typeof (input) === 'string') {
5010
+ // TODO not tested
5011
+ // input is type of object
5012
+ await this.setUrl(input);
5013
+ rasters = (await this.data.readRasters());
5014
+ width = this.data.getWidth();
5015
+ height = this.data.getHeight();
5016
+ }
5017
+ else {
5018
+ rasters = input.rasters;
5019
+ width = input.width;
5020
+ height = input.height;
5021
+ }
5022
+ const optionsLocal = { ...options };
5023
+ let channel = rasters[0];
5024
+ optionsLocal.useChannelIndex ??= optionsLocal.useChannel == null ? null : optionsLocal.useChannel - 1;
5025
+ if (options.useChannelIndex != null) {
5026
+ if (rasters[optionsLocal.useChannelIndex]) {
5027
+ channel = rasters[optionsLocal.useChannelIndex];
5059
5028
  }
5060
- const optionsLocal = Object.assign({}, options);
5061
- let channel = rasters[0];
5062
- (_a = optionsLocal.useChannelIndex) !== null && _a !== void 0 ? _a : (optionsLocal.useChannelIndex = optionsLocal.useChannel == null ? null : optionsLocal.useChannel - 1);
5063
- if (options.useChannelIndex != null) {
5064
- if (rasters[optionsLocal.useChannelIndex]) {
5065
- channel = rasters[optionsLocal.useChannelIndex];
5066
- }
5029
+ }
5030
+ const terrain = new Float32Array((width + 1) * (height + 1));
5031
+ const numOfChannels = channel.length / (width * height);
5032
+ let pixel = options.useChannelIndex === null ? 0 : options.useChannelIndex;
5033
+ for (let i = 0, y = 0; y < height; y++) {
5034
+ for (let x = 0; x < width; x++, i++) {
5035
+ const elevationValue = (options.noDataValue && channel[pixel] === options.noDataValue) ? options.terrainMinValue : channel[pixel] * options.multiplier;
5036
+ terrain[i + y] = elevationValue;
5037
+ pixel += numOfChannels;
5067
5038
  }
5068
- const terrain = new Float32Array((width + 1) * (height + 1));
5069
- const numOfChannels = channel.length / (width * height);
5070
- let pixel = options.useChannelIndex === null ? 0 : options.useChannelIndex;
5071
- for (let i = 0, y = 0; y < height; y++) {
5072
- for (let x = 0; x < width; x++, i++) {
5073
- const elevationValue = (options.noDataValue && channel[pixel] === options.noDataValue) ? options.terrainMinValue : channel[pixel] * options.multiplier;
5074
- terrain[i + y] = elevationValue;
5075
- pixel += numOfChannels;
5076
- }
5039
+ }
5040
+ {
5041
+ // backfill bottom border
5042
+ for (let i = (width + 1) * width, x = 0; x < width; x++, i++) {
5043
+ terrain[i] = terrain[i - width - 1];
5077
5044
  }
5078
- {
5079
- // backfill bottom border
5080
- for (let i = (width + 1) * width, x = 0; x < width; x++, i++) {
5081
- terrain[i] = terrain[i - width - 1];
5082
- }
5083
- // backfill right border
5084
- for (let i = height, y = 0; y < height + 1; y++, i += height + 1) {
5085
- terrain[i] = terrain[i - 1];
5086
- }
5045
+ // backfill right border
5046
+ for (let i = height, y = 0; y < height + 1; y++, i += height + 1) {
5047
+ terrain[i] = terrain[i - 1];
5087
5048
  }
5088
- // getMesh
5089
- const { terrainSkirtHeight } = options;
5090
- let mesh;
5091
- switch (tesselator) {
5092
- case 'martini':
5049
+ }
5050
+ // getMesh
5051
+ const { terrainSkirtHeight } = options;
5052
+ let mesh;
5053
+ switch (tesselator) {
5054
+ case 'martini':
5055
+ mesh = getMartiniTileMesh(meshMaxError, width, terrain);
5056
+ break;
5057
+ case 'delatin':
5058
+ mesh = getDelatinTileMesh(meshMaxError, width, height, terrain);
5059
+ break;
5060
+ default:
5061
+ if (width === height && !(height && (width - 1))) {
5062
+ // fixme get terrain to separate method
5063
+ // terrain = getTerrain(data, width, height, elevationDecoder, 'martini');
5093
5064
  mesh = getMartiniTileMesh(meshMaxError, width, terrain);
5094
- break;
5095
- case 'delatin':
5065
+ }
5066
+ else {
5067
+ // fixme get terrain to separate method
5068
+ // terrain = getTerrain(data, width, height, elevationDecoder, 'delatin');
5096
5069
  mesh = getDelatinTileMesh(meshMaxError, width, height, terrain);
5097
- break;
5098
- default:
5099
- if (width === height && !(height && (width - 1))) {
5100
- // fixme get terrain to separate method
5101
- // terrain = getTerrain(data, width, height, elevationDecoder, 'martini');
5102
- mesh = getMartiniTileMesh(meshMaxError, width, terrain);
5103
- }
5104
- else {
5105
- // fixme get terrain to separate method
5106
- // terrain = getTerrain(data, width, height, elevationDecoder, 'delatin');
5107
- mesh = getDelatinTileMesh(meshMaxError, width, height, terrain);
5108
- }
5109
- break;
5110
- }
5111
- // Martini
5112
- // Martini
5113
- // Delatin
5114
- // Delatin
5115
- const { vertices } = mesh;
5116
- let { triangles } = mesh;
5117
- let attributes = getMeshAttributes(vertices, terrain, width, height, input.bounds);
5118
- // Compute bounding box before adding skirt so that z values are not skewed
5119
- const boundingBox = schema.getMeshBoundingBox(attributes);
5120
- if (terrainSkirtHeight) {
5121
- const { attributes: newAttributes, triangles: newTriangles } = addSkirt(attributes, triangles, terrainSkirtHeight);
5122
- attributes = newAttributes;
5123
- triangles = newTriangles;
5124
- }
5125
- return {
5126
- // Data return by this loader implementation
5127
- loaderData: {
5128
- header: {},
5129
- },
5130
- header: {
5131
- vertexCount: triangles.length,
5132
- boundingBox,
5133
- },
5134
- mode: 4, // TRIANGLES
5135
- indices: { value: Uint32Array.from(triangles), size: 1 },
5136
- attributes,
5137
- };
5138
- });
5139
- }
5140
- getBitmap(input, options) {
5141
- return __awaiter(this, void 0, void 0, function* () {
5142
- var _a;
5143
- // console.time('bitmap-generated-in');
5144
- // const optionsLocal = { ...options };
5145
- const optionsLocal = Object.assign({}, options);
5146
- let rasters = [];
5147
- let channels;
5148
- let width;
5149
- let height;
5150
- if (typeof (input) === 'string') {
5151
- // TODO not tested
5152
- // input is type of object
5153
- yield this.setUrl(input);
5154
- rasters = (yield this.data.readRasters());
5155
- channels = rasters.length;
5156
- width = this.data.getWidth();
5157
- height = this.data.getHeight();
5158
- }
5159
- else {
5160
- rasters = input.rasters;
5161
- channels = rasters.length;
5162
- width = input.width;
5163
- height = input.height;
5164
- }
5165
- const canvas = document.createElement('canvas');
5166
- canvas.width = width;
5167
- canvas.height = height;
5168
- const c = canvas.getContext('2d');
5169
- const imageData = c.createImageData(width, height);
5170
- let r;
5171
- let g;
5172
- let b;
5173
- let a;
5174
- const size = width * height * 4;
5175
- // const size = width * height;
5176
- // if (!options.noDataValue) {
5177
- // console.log('Missing noData value. Raster might be displayed incorrectly.');
5178
- // }
5179
- optionsLocal.unidentifiedColor = this.getColorFromChromaType(optionsLocal.unidentifiedColor);
5180
- optionsLocal.nullColor = this.getColorFromChromaType(optionsLocal.nullColor);
5181
- optionsLocal.clippedColor = this.getColorFromChromaType(optionsLocal.clippedColor);
5182
- optionsLocal.color = this.getColorFromChromaType(optionsLocal.color);
5183
- (_a = optionsLocal.useChannelIndex) !== null && _a !== void 0 ? _a : (optionsLocal.useChannelIndex = options.useChannel === null ? null : options.useChannel - 1);
5184
- // console.log(rasters[0])
5185
- /* console.log("raster 0 length: " + rasters[0].length)
5186
- console.log("image width: " + width)
5187
- console.log("channels: " + channels)
5188
- console.log("format: " + rasters[0].length / (width * height))
5189
- */
5190
- if (optionsLocal.useChannelIndex == null) {
5191
- if (channels === 1) {
5192
- if (rasters[0].length / (width * height) === 1) {
5193
- const channel = rasters[0];
5194
- // AUTO RANGE
5195
- if (optionsLocal.useAutoRange) {
5196
- optionsLocal.colorScaleValueRange = this.getMinMax(channel, optionsLocal);
5197
- // console.log('data min: ' + optionsLocal.rangeMin + ', max: ' + optionsLocal.rangeMax);
5198
- }
5199
- // SINGLE CHANNEL
5200
- const colorData = this.getColorValue(channel, optionsLocal, size);
5201
- colorData.forEach((value, index) => {
5202
- imageData.data[index] = value;
5203
- });
5204
- }
5205
- // RGB values in one channel
5206
- if (rasters[0].length / (width * height) === 3) {
5207
- // console.log("geoImage: " + "RGB 1 array of length: " + rasters[0].length);
5208
- let pixel = 0;
5209
- for (let idx = 0; idx < size; idx += 4) {
5210
- const rgbColor = [rasters[0][pixel], rasters[0][pixel + 1], rasters[0][pixel + 2]];
5211
- const rgbaColor = this.hasPixelsNoData(rgbColor, optionsLocal.noDataValue)
5212
- ? optionsLocal.nullColor
5213
- : [...rgbColor, Math.floor(optionsLocal.alpha * 2.55)];
5214
- // eslint-disable-next-line max-len
5215
- [imageData.data[idx], imageData.data[idx + 1], imageData.data[idx + 2], imageData.data[idx + 3]] = rgbaColor;
5216
- pixel += 3;
5217
- }
5218
- }
5219
- if (rasters[0].length / (width * height) === 4) {
5220
- // console.log("geoImage: " + "RGBA 1 array");
5221
- rasters[0].forEach((value, index) => {
5222
- imageData.data[index] = value;
5223
- });
5224
- }
5225
5070
  }
5226
- if (channels === 3) {
5227
- // RGB
5228
- let pixel = 0;
5229
- for (let i = 0; i < size; i += 4) {
5230
- r = rasters[0][pixel];
5231
- g = rasters[1][pixel];
5232
- b = rasters[2][pixel];
5233
- a = Math.floor(optionsLocal.alpha * 2.55);
5234
- imageData.data[i] = r;
5235
- imageData.data[i + 1] = g;
5236
- imageData.data[i + 2] = b;
5237
- imageData.data[i + 3] = a;
5238
- pixel += 1;
5071
+ break;
5072
+ }
5073
+ const { vertices } = mesh;
5074
+ let { triangles } = mesh;
5075
+ let attributes = getMeshAttributes(vertices, terrain, width, height, input.bounds);
5076
+ // Compute bounding box before adding skirt so that z values are not skewed
5077
+ const boundingBox = schema.getMeshBoundingBox(attributes);
5078
+ if (terrainSkirtHeight) {
5079
+ const { attributes: newAttributes, triangles: newTriangles } = addSkirt(attributes, triangles, terrainSkirtHeight);
5080
+ attributes = newAttributes;
5081
+ triangles = newTriangles;
5082
+ }
5083
+ return {
5084
+ // Data return by this loader implementation
5085
+ loaderData: {
5086
+ header: {},
5087
+ },
5088
+ header: {
5089
+ vertexCount: triangles.length,
5090
+ boundingBox,
5091
+ },
5092
+ mode: 4, // TRIANGLES
5093
+ indices: { value: Uint32Array.from(triangles), size: 1 },
5094
+ attributes,
5095
+ };
5096
+ }
5097
+ async getBitmap(input, options) {
5098
+ // console.time('bitmap-generated-in');
5099
+ // const optionsLocal = { ...options };
5100
+ const optionsLocal = { ...options };
5101
+ let rasters = [];
5102
+ let channels;
5103
+ let width;
5104
+ let height;
5105
+ if (typeof (input) === 'string') {
5106
+ // TODO not tested
5107
+ // input is type of object
5108
+ await this.setUrl(input);
5109
+ rasters = (await this.data.readRasters());
5110
+ channels = rasters.length;
5111
+ width = this.data.getWidth();
5112
+ height = this.data.getHeight();
5113
+ }
5114
+ else {
5115
+ rasters = input.rasters;
5116
+ channels = rasters.length;
5117
+ width = input.width;
5118
+ height = input.height;
5119
+ }
5120
+ const canvas = document.createElement('canvas');
5121
+ canvas.width = width;
5122
+ canvas.height = height;
5123
+ const c = canvas.getContext('2d');
5124
+ const imageData = c.createImageData(width, height);
5125
+ let r;
5126
+ let g;
5127
+ let b;
5128
+ let a;
5129
+ const size = width * height * 4;
5130
+ // const size = width * height;
5131
+ // if (!options.noDataValue) {
5132
+ // console.log('Missing noData value. Raster might be displayed incorrectly.');
5133
+ // }
5134
+ optionsLocal.unidentifiedColor = this.getColorFromChromaType(optionsLocal.unidentifiedColor);
5135
+ optionsLocal.nullColor = this.getColorFromChromaType(optionsLocal.nullColor);
5136
+ optionsLocal.clippedColor = this.getColorFromChromaType(optionsLocal.clippedColor);
5137
+ optionsLocal.color = this.getColorFromChromaType(optionsLocal.color);
5138
+ optionsLocal.useChannelIndex ??= options.useChannel === null ? null : options.useChannel - 1;
5139
+ // console.log(rasters[0])
5140
+ /* console.log("raster 0 length: " + rasters[0].length)
5141
+ console.log("image width: " + width)
5142
+ console.log("channels: " + channels)
5143
+ console.log("format: " + rasters[0].length / (width * height))
5144
+ */
5145
+ if (optionsLocal.useChannelIndex == null) {
5146
+ if (channels === 1) {
5147
+ if (rasters[0].length / (width * height) === 1) {
5148
+ const channel = rasters[0];
5149
+ // AUTO RANGE
5150
+ if (optionsLocal.useAutoRange) {
5151
+ optionsLocal.colorScaleValueRange = this.getMinMax(channel, optionsLocal);
5152
+ // console.log('data min: ' + optionsLocal.rangeMin + ', max: ' + optionsLocal.rangeMax);
5239
5153
  }
5154
+ // SINGLE CHANNEL
5155
+ const colorData = this.getColorValue(channel, optionsLocal, size);
5156
+ colorData.forEach((value, index) => {
5157
+ imageData.data[index] = value;
5158
+ });
5240
5159
  }
5241
- if (channels === 4) {
5242
- // RGBA
5160
+ // RGB values in one channel
5161
+ if (rasters[0].length / (width * height) === 3) {
5162
+ // console.log("geoImage: " + "RGB 1 array of length: " + rasters[0].length);
5243
5163
  let pixel = 0;
5244
- for (let i = 0; i < size; i += 4) {
5245
- r = rasters[0][pixel];
5246
- g = rasters[1][pixel];
5247
- b = rasters[2][pixel];
5248
- a = Math.floor(optionsLocal.alpha * 2.55);
5249
- imageData.data[i] = r;
5250
- imageData.data[i + 1] = g;
5251
- imageData.data[i + 2] = b;
5252
- imageData.data[i + 3] = a;
5253
- pixel += 1;
5164
+ for (let idx = 0; idx < size; idx += 4) {
5165
+ const rgbColor = [rasters[0][pixel], rasters[0][pixel + 1], rasters[0][pixel + 2]];
5166
+ const rgbaColor = this.hasPixelsNoData(rgbColor, optionsLocal.noDataValue)
5167
+ ? optionsLocal.nullColor
5168
+ : [...rgbColor, Math.floor(optionsLocal.alpha * 2.55)];
5169
+ // eslint-disable-next-line max-len
5170
+ [imageData.data[idx], imageData.data[idx + 1], imageData.data[idx + 2], imageData.data[idx + 3]] = rgbaColor;
5171
+ pixel += 3;
5254
5172
  }
5255
5173
  }
5174
+ if (rasters[0].length / (width * height) === 4) {
5175
+ // console.log("geoImage: " + "RGBA 1 array");
5176
+ rasters[0].forEach((value, index) => {
5177
+ imageData.data[index] = value;
5178
+ });
5179
+ }
5256
5180
  }
5257
- else if (optionsLocal.useChannelIndex < optionsLocal.numOfChannels && optionsLocal.useChannelIndex >= 0) {
5258
- let channel = rasters[0];
5259
- if (rasters[optionsLocal.useChannelIndex]) {
5260
- channel = rasters[optionsLocal.useChannelIndex];
5181
+ if (channels === 3) {
5182
+ // RGB
5183
+ let pixel = 0;
5184
+ for (let i = 0; i < size; i += 4) {
5185
+ r = rasters[0][pixel];
5186
+ g = rasters[1][pixel];
5187
+ b = rasters[2][pixel];
5188
+ a = Math.floor(optionsLocal.alpha * 2.55);
5189
+ imageData.data[i] = r;
5190
+ imageData.data[i + 1] = g;
5191
+ imageData.data[i + 2] = b;
5192
+ imageData.data[i + 3] = a;
5193
+ pixel += 1;
5261
5194
  }
5262
- // AUTO RANGE
5263
- if (optionsLocal.useAutoRange) {
5264
- optionsLocal.colorScaleValueRange = this.getMinMax(channel, optionsLocal);
5265
- // console.log('data min: ' + optionsLocal.rangeMin + ', max: ' + optionsLocal.rangeMax);
5195
+ }
5196
+ if (channels === 4) {
5197
+ // RGBA
5198
+ let pixel = 0;
5199
+ for (let i = 0; i < size; i += 4) {
5200
+ r = rasters[0][pixel];
5201
+ g = rasters[1][pixel];
5202
+ b = rasters[2][pixel];
5203
+ a = Math.floor(optionsLocal.alpha * 2.55);
5204
+ imageData.data[i] = r;
5205
+ imageData.data[i + 1] = g;
5206
+ imageData.data[i + 2] = b;
5207
+ imageData.data[i + 3] = a;
5208
+ pixel += 1;
5266
5209
  }
5267
- // const numOfChannels = channel.length / (width * height);
5268
- const colorData = this.getColorValue(channel, optionsLocal, size, optionsLocal.numOfChannels);
5269
- colorData.forEach((value, index) => {
5270
- imageData.data[index] = value;
5271
- });
5272
5210
  }
5273
- else {
5274
- // if user defined channel does not exist
5275
- 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`);
5276
- const defaultColorData = this.getDefaultColor(size, optionsLocal.nullColor);
5277
- defaultColorData.forEach((value, index) => {
5278
- imageData.data[index] = value;
5279
- });
5211
+ }
5212
+ else if (optionsLocal.useChannelIndex < optionsLocal.numOfChannels && optionsLocal.useChannelIndex >= 0) {
5213
+ let channel = rasters[0];
5214
+ if (rasters[optionsLocal.useChannelIndex]) {
5215
+ channel = rasters[optionsLocal.useChannelIndex];
5280
5216
  }
5281
- // console.timeEnd('bitmap-generated-in');
5282
- c.putImageData(imageData, 0, 0);
5283
- const imageUrl = canvas.toDataURL('image/png');
5284
- // console.log('Bitmap generated.');
5285
- return imageUrl;
5286
- });
5217
+ // AUTO RANGE
5218
+ if (optionsLocal.useAutoRange) {
5219
+ optionsLocal.colorScaleValueRange = this.getMinMax(channel, optionsLocal);
5220
+ // console.log('data min: ' + optionsLocal.rangeMin + ', max: ' + optionsLocal.rangeMax);
5221
+ }
5222
+ // const numOfChannels = channel.length / (width * height);
5223
+ const colorData = this.getColorValue(channel, optionsLocal, size, optionsLocal.numOfChannels);
5224
+ colorData.forEach((value, index) => {
5225
+ imageData.data[index] = value;
5226
+ });
5227
+ }
5228
+ else {
5229
+ // if user defined channel does not exist
5230
+ console.log(`Defined channel(${options.useChannel}) or channel index(${options.useChannelIndex}) does not exist, choose a different channel or set the useChannel property to null if you want to visualize RGB(A) imagery`);
5231
+ const defaultColorData = this.getDefaultColor(size, optionsLocal.nullColor);
5232
+ defaultColorData.forEach((value, index) => {
5233
+ imageData.data[index] = value;
5234
+ });
5235
+ }
5236
+ // console.timeEnd('bitmap-generated-in');
5237
+ c.putImageData(imageData, 0, 0);
5238
+ const imageUrl = canvas.toDataURL('image/png');
5239
+ // console.log('Bitmap generated.');
5240
+ return imageUrl;
5287
5241
  }
5288
5242
  getMinMax(array, options) {
5289
5243
  let maxValue = options.maxValue ? options.maxValue : Number.MIN_VALUE;
@@ -5362,7 +5316,7 @@ class GeoImage {
5362
5316
  }
5363
5317
  // FIXME
5364
5318
  // eslint-disable-next-line
5365
- [colorsArray[i], colorsArray[i + 1], colorsArray[i + 2], colorsArray[i + 3]] = pixelColor;
5319
+ ([colorsArray[i], colorsArray[i + 1], colorsArray[i + 2], colorsArray[i + 3]] = pixelColor);
5366
5320
  pixel += numOfChannels;
5367
5321
  }
5368
5322
  return colorsArray;
@@ -5452,7 +5406,7 @@ function getMeshAttributes(vertices, terrain, width, height, bounds) {
5452
5406
  function getDelatinTileMesh(meshMaxError, width, height, terrain) {
5453
5407
  const tin = new Delatin(terrain, width + 1, height + 1);
5454
5408
  tin.run(meshMaxError);
5455
- // @ts-expect-error
5409
+ // @ts-expect-error: Delatin instance properties 'coords' and 'triangles' are not explicitly typed in the library port
5456
5410
  const { coords, triangles } = tin;
5457
5411
  const vertices = coords;
5458
5412
  return { vertices, triangles };
@@ -5466,31 +5420,30 @@ const CogTilesGeoImageOptionsDefaults = {
5466
5420
  blurredTexture: true,
5467
5421
  };
5468
5422
  class CogTiles {
5423
+ cog;
5424
+ cogZoomLookup = [0];
5425
+ cogResolutionLookup = [0];
5426
+ cogOrigin = [0, 0];
5427
+ zoomRange = [0, 0];
5428
+ tileSize;
5429
+ bounds;
5430
+ geo = new GeoImage();
5431
+ options;
5469
5432
  constructor(options) {
5470
- this.cogZoomLookup = [0];
5471
- this.cogResolutionLookup = [0];
5472
- this.cogOrigin = [0, 0];
5473
- this.zoomRange = [0, 0];
5474
- this.loaded = false;
5475
- this.geo = new GeoImage();
5476
- this.options = Object.assign(Object.assign({}, CogTilesGeoImageOptionsDefaults), options);
5477
- }
5478
- initializeCog(url) {
5479
- return __awaiter(this, void 0, void 0, function* () {
5480
- var _a, _b;
5481
- var _c, _d;
5482
- this.cog = yield fromUrl(url);
5483
- const image = yield this.cog.getImage(); // by default, the first image is read.
5484
- this.cogOrigin = image.getOrigin();
5485
- (_a = (_c = this.options).noDataValue) !== null && _a !== void 0 ? _a : (_c.noDataValue = this.getNoDataValue(image));
5486
- (_b = (_d = this.options).format) !== null && _b !== void 0 ? _b : (_d.format = this.getDataTypeFromTags(image));
5487
- this.options.numOfChannels = this.getNumberOfChannels(image);
5488
- this.options.planarConfig = this.getPlanarConfiguration(image);
5489
- [this.cogZoomLookup, this.cogResolutionLookup] = yield this.buildCogZoomResolutionLookup(this.cog);
5490
- this.tileSize = image.getTileWidth();
5491
- this.zoomRange = this.calculateZoomRange(image, yield this.cog.getImageCount());
5492
- this.bounds = this.calculateBoundsAsLatLon(image);
5493
- });
5433
+ this.options = { ...CogTilesGeoImageOptionsDefaults, ...options };
5434
+ }
5435
+ async initializeCog(url) {
5436
+ this.cog = await fromUrl(url);
5437
+ const image = await this.cog.getImage(); // by default, the first image is read.
5438
+ this.cogOrigin = image.getOrigin();
5439
+ this.options.noDataValue ??= this.getNoDataValue(image);
5440
+ this.options.format ??= this.getDataTypeFromTags(image);
5441
+ this.options.numOfChannels = this.getNumberOfChannels(image);
5442
+ this.options.planarConfig = this.getPlanarConfiguration(image);
5443
+ [this.cogZoomLookup, this.cogResolutionLookup] = await this.buildCogZoomResolutionLookup(this.cog);
5444
+ this.tileSize = image.getTileWidth();
5445
+ this.zoomRange = this.calculateZoomRange(image, await this.cog.getImageCount());
5446
+ this.bounds = this.calculateBoundsAsLatLon(image);
5494
5447
  }
5495
5448
  getZoomRange() {
5496
5449
  return this.zoomRange;
@@ -5542,33 +5495,31 @@ class CogTiles {
5542
5495
  * - The first array (`zoomLookup`) maps each image index to its computed zoom level.
5543
5496
  * - The second array (`resolutionLookup`) maps each image index to its estimated resolution (m/pixel).
5544
5497
  */
5545
- buildCogZoomResolutionLookup(cog) {
5546
- return __awaiter(this, void 0, void 0, function* () {
5547
- // Retrieve the total number of images (overviews) in the COG.
5548
- const imageCount = yield cog.getImageCount();
5549
- // Use the first image as the base reference.
5550
- const baseImage = yield cog.getImage(0);
5551
- const baseResolution = baseImage.getResolution()[0]; // Resolution (m/pixel) of the base image.
5552
- const baseWidth = baseImage.getWidth();
5553
- // Initialize arrays to store the zoom level and resolution for each image.
5554
- const zoomLookup = [];
5555
- const resolutionLookup = [];
5556
- // Iterate over each image (overview) in the COG.
5557
- for (let idx = 0; idx < imageCount; idx++) {
5558
- const image = yield cog.getImage(idx);
5559
- const width = image.getWidth();
5560
- // Calculate the scale factor relative to the base image.
5561
- const scaleFactor = baseWidth / width;
5562
- const estimatedResolution = baseResolution * scaleFactor;
5563
- // Calculate the zoom level using the Web Mercator resolution standard:
5564
- // webMercatorRes0 is the resolution at zoom level 0; each zoom level halves the resolution.
5565
- const zoomLevel = Math.round(Math.log2(webMercatorRes0 / estimatedResolution));
5566
- // console.log(`buildCogZoomResolutionLookup: Image index ${idx}: Estimated Resolution = ${estimatedResolution} m/pixel, Zoom Level = ${zoomLevel}`);
5567
- zoomLookup[idx] = zoomLevel;
5568
- resolutionLookup[idx] = estimatedResolution;
5569
- }
5570
- return [zoomLookup, resolutionLookup];
5571
- });
5498
+ async buildCogZoomResolutionLookup(cog) {
5499
+ // Retrieve the total number of images (overviews) in the COG.
5500
+ const imageCount = await cog.getImageCount();
5501
+ // Use the first image as the base reference.
5502
+ const baseImage = await cog.getImage(0);
5503
+ const baseResolution = baseImage.getResolution()[0]; // Resolution (m/pixel) of the base image.
5504
+ const baseWidth = baseImage.getWidth();
5505
+ // Initialize arrays to store the zoom level and resolution for each image.
5506
+ const zoomLookup = [];
5507
+ const resolutionLookup = [];
5508
+ // Iterate over each image (overview) in the COG.
5509
+ for (let idx = 0; idx < imageCount; idx++) {
5510
+ const image = await cog.getImage(idx);
5511
+ const width = image.getWidth();
5512
+ // Calculate the scale factor relative to the base image.
5513
+ const scaleFactor = baseWidth / width;
5514
+ const estimatedResolution = baseResolution * scaleFactor;
5515
+ // Calculate the zoom level using the Web Mercator resolution standard:
5516
+ // webMercatorRes0 is the resolution at zoom level 0; each zoom level halves the resolution.
5517
+ const zoomLevel = Math.round(Math.log2(webMercatorRes0 / estimatedResolution));
5518
+ // console.log(`buildCogZoomResolutionLookup: Image index ${idx}: Estimated Resolution = ${estimatedResolution} m/pixel, Zoom Level = ${zoomLevel}`);
5519
+ zoomLookup[idx] = zoomLevel;
5520
+ resolutionLookup[idx] = estimatedResolution;
5521
+ }
5522
+ return [zoomLookup, resolutionLookup];
5572
5523
  }
5573
5524
  /**
5574
5525
  * Determines the appropriate image index from the Cloud Optimized GeoTIFF (COG)
@@ -5597,93 +5548,138 @@ class CogTiles {
5597
5548
  }
5598
5549
  return exactMatchIndex;
5599
5550
  }
5600
- getTileFromImage(tileX, tileY, zoom) {
5601
- return __awaiter(this, void 0, void 0, function* () {
5602
- const imageIndex = this.getImageIndexForZoomLevel(zoom);
5603
- const targetImage = yield this.cog.getImage(imageIndex);
5604
- // Ensure the image is tiled
5605
- const tileWidth = targetImage.getTileWidth();
5606
- const tileHeight = targetImage.getTileHeight();
5607
- if (!tileWidth || !tileHeight) {
5608
- throw new Error('The image is not tiled.');
5609
- }
5610
- // Calculate the map offset between the global Web Mercator origin and the COG's origin.
5611
- // (Difference in map units.)
5612
- // if X offset is large and positive (COG is far to the right of global origin)
5613
- // if Y offset is large and positive (COG is far below global origin — expected)
5614
- const offsetXMap = this.cogOrigin[0] - webMercatorOrigin[0];
5615
- const offsetYMap = webMercatorOrigin[1] - this.cogOrigin[1];
5616
- const tileResolution = (EARTH_CIRCUMFERENCE / tileWidth) / Math.pow(2, zoom);
5617
- this.cogResolutionLookup[imageIndex];
5618
- // Convert map offsets into pixel offsets.
5619
- const offsetXPixel = Math.floor(offsetXMap / tileResolution);
5620
- const offsetYPixel = Math.floor(offsetYMap / tileResolution);
5621
- const imageHeight = targetImage.getHeight();
5622
- const imageWidth = targetImage.getWidth();
5623
- // approach by comparing bboxes of tile and cog image
5624
- const tilePixelBbox = [
5625
- tileX * tileWidth,
5626
- tileY * tileHeight,
5627
- (tileX + 1) * tileWidth,
5628
- (tileY + 1) * tileHeight,
5629
- ];
5630
- const cogPixelBBox = [
5631
- offsetXPixel,
5632
- offsetYPixel,
5633
- offsetXPixel + imageWidth,
5634
- offsetYPixel + imageHeight,
5635
- ];
5636
- const intersecion = this.getIntersectionBBox(tilePixelBbox, cogPixelBBox, offsetXPixel, offsetYPixel, tileWidth);
5637
- const [validWidth, validHeight, window, missingLeft, missingTop] = intersecion;
5638
- // Read the raster data for the tile window with shifted origin.
5639
- if (missingLeft > 0 || missingTop > 0 || validWidth < tileWidth || validHeight < tileHeight) {
5640
- // Prepare the final tile buffer and fill it with noDataValue.
5641
- const tileBuffer = this.createTileBuffer(this.options.format, tileWidth);
5642
- tileBuffer.fill(this.options.noDataValue);
5643
- // 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
5644
- const validRasterData = yield targetImage.readRasters({ window });
5645
- // FOR MULTI-BAND - the result is one array with sequentially typed bands, firstly all data for the band 0, then for band 1
5646
- // 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.
5647
- const validImageData = Array(validRasterData.length * validRasterData[0].length);
5648
- validImageData.fill(this.options.noDataValue);
5649
- // Place the valid pixel data into the tile buffer.
5650
- for (let band = 0; band < validRasterData.length; band++) {
5651
- for (let row = 0; row < validHeight; row++) {
5652
- for (let col = 0; col < validWidth; col++) {
5653
- // Compute the destination position in the tile buffer.
5654
- // We shift by the number of missing pixels (if any) at the top/left.
5655
- const destRow = missingTop + row;
5656
- const destCol = missingLeft + col;
5657
- if (destRow < tileWidth && destCol < tileHeight) {
5658
- tileBuffer[destRow * tileWidth + destCol] = validRasterData[band][row * validRasterData.width + col];
5659
- }
5660
- else {
5661
- console.log('error in assigning data to tile buffer');
5662
- }
5551
+ async getTileFromImage(tileX, tileY, zoom) {
5552
+ const imageIndex = this.getImageIndexForZoomLevel(zoom);
5553
+ const targetImage = await this.cog.getImage(imageIndex);
5554
+ // 1. Validation: Ensure the image is tiled
5555
+ const tileWidth = targetImage.getTileWidth();
5556
+ const tileHeight = targetImage.getTileHeight();
5557
+ if (!tileWidth || !tileHeight) {
5558
+ throw new Error('GeoTIFF Error: The provided image is not tiled. '
5559
+ + 'Please use "rio cogeo create --web-optimized" to fix this.');
5560
+ }
5561
+ // --- STEP 1: CALCULATE BOUNDS IN METERS ---
5562
+ // 2. Get COG Metadata (image = COG)
5563
+ const imageResolution = this.cogResolutionLookup[imageIndex];
5564
+ const imageHeight = targetImage.getHeight();
5565
+ const imageWidth = targetImage.getWidth();
5566
+ const [imgOriginX, imgOriginY] = this.cogOrigin;
5567
+ // 3. Define Web Mercator Constants
5568
+ // We use the class property tileSize (usually 256) as the ground truth for grid calculations
5569
+ const TILE_SIZE = this.tileSize;
5570
+ const ORIGIN_X = webMercatorOrigin[0];
5571
+ const ORIGIN_Y = webMercatorOrigin[1];
5572
+ // 4. Calculate Tile BBox in World Meters
5573
+ // This defines where the map expects the tile to be physically located
5574
+ const tileGridResolution = (EARTH_CIRCUMFERENCE / TILE_SIZE) / (2 ** zoom);
5575
+ const tileMinXMeters = ORIGIN_X + (tileX * TILE_SIZE * tileGridResolution);
5576
+ const tileMaxYMeters = ORIGIN_Y - (tileY * TILE_SIZE * tileGridResolution);
5577
+ // Note: We don't strictly need MaxX/MinY meters for the start calculation,
5578
+ // but they are useful if debugging the full meter footprint.
5579
+ // --- STEP 2: CONVERT TO PIXEL COORDINATES ---
5580
+ // 5. Calculate precise floating-point start position relative to the image
5581
+ const windowMinX = (tileMinXMeters - imgOriginX) / imageResolution;
5582
+ const windowMinY = (imgOriginY - tileMaxYMeters) / imageResolution;
5583
+ // 6. Snap to Integer Grid (The "Force 256" Fix)
5584
+ // We round the start position to align with the nearest pixel.
5585
+ // Crucially, we calculate endX/endY by adding tileSize to startX/startY.
5586
+ // This guarantees the window is exactly 256x256, preventing "off-by-one" (257px) errors.
5587
+ const startX = Math.round(windowMinX);
5588
+ const startY = Math.round(windowMinY);
5589
+ const endX = startX + TILE_SIZE;
5590
+ const endY = startY + TILE_SIZE;
5591
+ // --- STEP 3: CALCULATE INTERSECTION ---
5592
+ // 7. Clamp the read window to the actual image dimensions
5593
+ // This defines the "Safe" area we can actually read from the file.
5594
+ const validReadX = Math.max(0, startX);
5595
+ const validReadY = Math.max(0, startY);
5596
+ const validReadMaxX = Math.min(imageWidth, endX);
5597
+ const validReadMaxY = Math.min(imageHeight, endY);
5598
+ const readWidth = validReadMaxX - validReadX;
5599
+ const readHeight = validReadMaxY - validReadY;
5600
+ // CHECK: If no overlap, return empty
5601
+ if (readWidth <= 0 || readHeight <= 0) {
5602
+ return [this.createEmptyTile()];
5603
+ }
5604
+ // 8. Calculate Offsets (Padding)
5605
+ // "missingLeft" is how many blank pixels we need to insert before the image data starts.
5606
+ // Logic: If we wanted to read from -50 (startX), but clamped to 0 (validReadX),
5607
+ // we are missing the first 50 pixels.
5608
+ const missingLeft = validReadX - startX;
5609
+ const missingTop = validReadY - startY;
5610
+ const window = [validReadX, validReadY, validReadMaxX, validReadMaxY];
5611
+ // --- STEP 4: READ AND COMPOSITE ---
5612
+ // Case A: Partial Overlap (Padding or Cropping required)
5613
+ // If the tile is hanging off the edge, we need to manually reconstruct it.
5614
+ if (missingLeft > 0 || missingTop > 0 || readWidth < tileWidth || readHeight < tileHeight) {
5615
+ /// Initialize a temporary buffer for a single band (filled with NoData)
5616
+ // We will reuse this buffer for each band to save memory allocations.
5617
+ const tileBuffer = this.createTileBuffer(this.options.format, tileWidth);
5618
+ tileBuffer.fill(this.options.noDataValue);
5619
+ // if the valid window is smaller than the tile size, it gets the image size width and height, thus validRasterData.width must be used as below
5620
+ const validRasterData = await targetImage.readRasters({ window });
5621
+ // FOR MULTI-BAND - the result is one array with sequentially typed bands, firstly all data for the band 0, then for band 1
5622
+ // I think this is less practical then the commented solution above, but I do it so it works with the code in GeoImage.ts in deck.gl-geoimage in function getColorValue.
5623
+ const validImageData = Array(validRasterData.length * validRasterData[0].length);
5624
+ validImageData.fill(this.options.noDataValue);
5625
+ // Place the valid pixel data into the tile buffer.
5626
+ for (let band = 0; band < validRasterData.length; band += 1) {
5627
+ for (let row = 0; row < readHeight; row += 1) {
5628
+ const destRow = missingTop + row;
5629
+ const destRowOffset = destRow * TILE_SIZE;
5630
+ const srcRowOffset = row * validRasterData.width;
5631
+ for (let col = 0; col < readWidth; col += 1) {
5632
+ // Compute the destination position in the tile buffer.
5633
+ // We shift by the number of missing pixels (if any) at the top/left.
5634
+ const destCol = missingLeft + col;
5635
+ // Bounds Check: Ensure we don't write outside the 256x256 buffer
5636
+ if (destRow < tileWidth && destCol < tileHeight) {
5637
+ tileBuffer[destRowOffset + destCol] = validRasterData[band][srcRowOffset + col];
5638
+ }
5639
+ else {
5640
+ console.log('error in assigning data to tile buffer');
5663
5641
  }
5664
5642
  }
5665
- tileBuffer.forEach((rasterValue, index) => {
5666
- validImageData[index * this.options.numOfChannels + band] = rasterValue;
5667
- });
5668
5643
  }
5669
- return [validImageData];
5644
+ for (let i = 0; i < tileBuffer.length; i += 1) {
5645
+ validImageData[i * this.options.numOfChannels + band] = tileBuffer[i];
5646
+ }
5670
5647
  }
5671
- // Read the raster data for the non shifted tile window.
5672
- const tileData = yield targetImage.readRasters({ window, interleave: true });
5673
- // console.log(`data that starts at the left top corner of the tile ${tileX}, ${tileY}`);
5674
- return [tileData];
5675
- });
5648
+ return [validImageData];
5649
+ }
5650
+ // Case B: Perfect Match (Optimization)
5651
+ // If the read window is exactly 256x256 and aligned, we can read directly interleaved.
5652
+ // console.log("Perfect aligned read");
5653
+ const tileData = await targetImage.readRasters({ window, interleave: true });
5654
+ // console.log(`data that starts at the left top corner of the tile ${tileX}, ${tileY}`);
5655
+ return [tileData];
5676
5656
  }
5677
- getTile(x, y, z, bounds, meshMaxError) {
5678
- return __awaiter(this, void 0, void 0, function* () {
5679
- const tileData = yield this.getTileFromImage(x, y, z);
5680
- return this.geo.getMap({
5681
- rasters: [tileData[0]],
5682
- width: this.tileSize,
5683
- height: this.tileSize,
5684
- bounds,
5685
- }, this.options, meshMaxError);
5686
- });
5657
+ /**
5658
+ * Creates a blank tile buffer filled with the "No Data" value.
5659
+ */
5660
+ createEmptyTile() {
5661
+ // 1. Determine the size
5662
+ // Default to 1 channel (grayscale) if not specified
5663
+ const channels = this.options.numOfChannels || 1;
5664
+ const size = this.tileSize * this.tileSize * channels;
5665
+ // 2. Create the array
5666
+ // Float32 is standard for GeoTIFF data handling in browsers
5667
+ const tileData = new Float32Array(size);
5668
+ // 3. Fill with "No Data" value
5669
+ // If noDataValue is undefined, it defaults to 0
5670
+ if (this.options.noDataValue !== undefined) {
5671
+ tileData.fill(this.options.noDataValue);
5672
+ }
5673
+ return tileData;
5674
+ }
5675
+ async getTile(x, y, z, bounds, meshMaxError) {
5676
+ const tileData = await this.getTileFromImage(x, y, z);
5677
+ return this.geo.getMap({
5678
+ rasters: [tileData[0]],
5679
+ width: this.tileSize,
5680
+ height: this.tileSize,
5681
+ bounds,
5682
+ }, this.options, meshMaxError);
5687
5683
  }
5688
5684
  /**
5689
5685
  * Determines the data type (e.g., "Int32", "Float64") of a GeoTIFF image
@@ -5766,53 +5762,6 @@ class CogTiles {
5766
5762
  getNumberOfChannels(image) {
5767
5763
  return image.getSamplesPerPixel();
5768
5764
  }
5769
- /**
5770
- * Calculates the intersection between a tile bounding box and a COG bounding box,
5771
- * returning the intersection window in image pixel space (relative to COG offsets),
5772
- * along with how much blank space (nodata) appears on the left and top of the tile.
5773
- *
5774
- * @param {number[]} tileBbox - Tile bounding box: [minX, minY, maxX, maxY]
5775
- * @param {number[]} cogBbox - COG bounding box: [minX, minY, maxX, maxY]
5776
- * @param {number} offsetXPixel - X offset of the COG origin in pixel space
5777
- * @param {number} offsetYPixel - Y offset of the COG origin in pixel space
5778
- * @param {number} tileSize - Size of the tile in pixels (default: 256)
5779
- * @returns {[number, number, number[] | null, number, number]}
5780
- * An array containing:
5781
- * - width of the intersection
5782
- * - height of the intersection
5783
- * - pixel-space window: [startX, startY, endX, endY] or null if no overlap
5784
- * - missingLeft: padding pixels on the left
5785
- * - missingTop: padding pixels on the top
5786
- */
5787
- getIntersectionBBox(tileBbox, cogBbox, offsetXPixel = 0, offsetYPixel = 0, tileSize = 256) {
5788
- const interLeft = Math.max(tileBbox[0], cogBbox[0]);
5789
- const interTop = Math.max(tileBbox[1], cogBbox[1]);
5790
- const interRight = Math.min(tileBbox[2], cogBbox[2]);
5791
- const interBottom = Math.min(tileBbox[3], cogBbox[3]);
5792
- const width = Math.max(0, interRight - interLeft);
5793
- const height = Math.max(0, interBottom - interTop);
5794
- let window = null;
5795
- let missingLeft = 0;
5796
- let missingTop = 0;
5797
- if (width > 0 && height > 0) {
5798
- window = [
5799
- interLeft - offsetXPixel,
5800
- interTop - offsetYPixel,
5801
- interRight - offsetXPixel,
5802
- interBottom - offsetYPixel,
5803
- ];
5804
- // Padding from the tile origin to valid data start
5805
- missingLeft = interLeft - tileBbox[0];
5806
- missingTop = interTop - tileBbox[1];
5807
- }
5808
- return [
5809
- width,
5810
- height,
5811
- window,
5812
- missingLeft,
5813
- missingTop,
5814
- ];
5815
- }
5816
5765
  /**
5817
5766
  * Retrieves the PlanarConfiguration value from a GeoTIFF image.
5818
5767
  *
@@ -5885,7 +5834,8 @@ const urlType$1 = {
5885
5834
  return true;
5886
5835
  },
5887
5836
  };
5888
- const defaultProps$1 = Object.assign(Object.assign({}, geoLayers.TileLayer.defaultProps), {
5837
+ const defaultProps$1 = {
5838
+ ...geoLayers.TileLayer.defaultProps,
5889
5839
  // Image url that encodes height data
5890
5840
  // elevationData: urlType,
5891
5841
  // Image url to use as texture
@@ -5895,10 +5845,9 @@ const defaultProps$1 = Object.assign(Object.assign({}, geoLayers.TileLayer.defau
5895
5845
  // Bounding box of the terrain image, [minX, minY, maxX, maxY] in world coordinates
5896
5846
  bounds: {
5897
5847
  type: 'array', value: null, optional: true, compare: true,
5898
- }, rasterData: urlType$1,
5899
- // Color to use if texture is unavailable
5900
- // color: { type: 'color', value: [255, 255, 255] },
5901
- blurredTexture: true, opacity: 1, clampToTerrain: false,
5848
+ },
5849
+ rasterData: urlType$1,
5850
+ clampToTerrain: false,
5902
5851
  // Object to decode height data, from (r, g, b) to height in meters
5903
5852
  // elevationDecoder: {
5904
5853
  // type: 'object',
@@ -5910,40 +5859,31 @@ const defaultProps$1 = Object.assign(Object.assign({}, geoLayers.TileLayer.defau
5910
5859
  // },
5911
5860
  // },
5912
5861
  // Supply url to local terrain worker bundle. Only required if running offline and cannot access CDN.
5913
- workerUrl: '' });
5862
+ workerUrl: '',
5863
+ // Same as SimpleMeshLayer wireframe
5864
+ // wireframe: false,
5865
+ // material: true,
5866
+ // loaders: [TerrainLoader],
5867
+ };
5914
5868
  /** Render bitmap texture from cog raster images. */
5915
5869
  class CogBitmapLayer extends core.CompositeLayer {
5916
- // private _isLoaded: boolean;
5917
- // id = '';
5918
- // url: string;
5919
- // static displayName: string;
5920
- // cogTiles: CogTiles;
5921
- //
5922
- // tileSize: number;
5923
- //
5924
- initializeState(context) {
5925
- const _super = Object.create(null, {
5926
- initializeState: { get: () => super.initializeState }
5927
- });
5928
- return __awaiter(this, void 0, void 0, function* () {
5929
- _super.initializeState.call(this, context);
5930
- this.setState({
5931
- bitmapCogTiles: new CogTiles(this.props.cogBitmapOptions),
5932
- initialized: false,
5933
- });
5934
- yield this.init();
5870
+ static defaultProps = defaultProps$1;
5871
+ static layerName = 'CogBitmapLayer';
5872
+ async initializeState(context) {
5873
+ super.initializeState(context);
5874
+ this.setState({
5875
+ bitmapCogTiles: new CogTiles(this.props.cogBitmapOptions),
5876
+ initialized: false,
5935
5877
  });
5878
+ await this.init();
5936
5879
  }
5937
- init() {
5938
- return __awaiter(this, void 0, void 0, function* () {
5939
- yield this.state.bitmapCogTiles.initializeCog(this.props.rasterData);
5940
- const zoomRange = this.state.bitmapCogTiles.getZoomRange();
5941
- const [minZoom, maxZoom] = zoomRange;
5942
- this.setState({ initialized: true, minZoom, maxZoom });
5943
- });
5880
+ async init() {
5881
+ await this.state.bitmapCogTiles.initializeCog(this.props.rasterData);
5882
+ const zoomRange = this.state.bitmapCogTiles.getZoomRange();
5883
+ const [minZoom, maxZoom] = zoomRange;
5884
+ this.setState({ initialized: true, minZoom, maxZoom });
5944
5885
  }
5945
5886
  updateState({ props, oldProps }) {
5946
- var _a, _b, _c;
5947
5887
  const rasterDataChanged = props.rasterData !== oldProps.rasterData;
5948
5888
  if (rasterDataChanged) {
5949
5889
  const { rasterData } = props;
@@ -5963,45 +5903,47 @@ class CogBitmapLayer extends core.CompositeLayer {
5963
5903
  // object in this way is not ideal and may need refactoring in the future to follow a more
5964
5904
  // declarative state management approach. Consider revisiting this if additional properties
5965
5905
  // need to be synchronized or if the state structure changes.
5966
- if (((_a = props === null || props === void 0 ? void 0 : props.cogBitmapOptions) === null || _a === void 0 ? void 0 : _a.useChannel) && (((_b = props.cogBitmapOptions) === null || _b === void 0 ? void 0 : _b.useChannel) !== ((_c = oldProps.cogBitmapOptions) === null || _c === void 0 ? void 0 : _c.useChannel))) {
5906
+ if (props?.cogBitmapOptions?.useChannel && (props.cogBitmapOptions?.useChannel !== oldProps.cogBitmapOptions?.useChannel)) {
5967
5907
  this.state.bitmapCogTiles.options.useChannel = props.cogBitmapOptions.useChannel;
5968
5908
  }
5969
- // TODO - remove in v9
5970
- // @ts-ignore
5971
5909
  if (props.workerUrl) {
5972
5910
  core.log.removed('workerUrl', 'loadOptions.terrain.workerUrl')();
5973
5911
  }
5974
5912
  }
5975
- getTiledBitmapData(tile) {
5976
- return __awaiter(this, void 0, void 0, function* () {
5977
- // TODO - pass signal to getTile
5978
- // abort request if signal is aborted
5979
- const tileData = yield this.state.bitmapCogTiles.getTile(tile.index.x, tile.index.y, tile.index.z);
5980
- return tileData;
5981
- });
5913
+ async getTiledBitmapData(tile) {
5914
+ // TODO - pass signal to getTile
5915
+ // abort request if signal is aborted
5916
+ const tileData = await this.state.bitmapCogTiles.getTile(tile.index.x, tile.index.y, tile.index.z);
5917
+ return tileData;
5982
5918
  }
5983
5919
  renderSubLayers(props) {
5984
5920
  const SubLayerClass = this.getSubLayerClass('image', layers.BitmapLayer);
5985
5921
  const { blurredTexture } = this.state.bitmapCogTiles.options;
5986
- const { opacity, clampToTerrain } = this.props;
5922
+ const { clampToTerrain } = this.props;
5923
+ const hasDrawMode = typeof clampToTerrain === 'object' && clampToTerrain !== null && 'terrainDrawMode' in clampToTerrain;
5987
5924
  const { data } = props;
5988
5925
  if (!data) {
5989
5926
  return null;
5990
5927
  }
5991
5928
  const { bbox: { west, south, east, north, }, } = props.tile;
5992
- return new SubLayerClass(Object.assign(Object.assign({}, props), { tileSize: this.state.bitmapCogTiles.tileSize }), Object.assign({ data: null, image: data, _instanced: false, bounds: [west, south, east, north], opacity, textureParameters: {
5929
+ return new SubLayerClass({ ...props, tileSize: this.state.bitmapCogTiles.tileSize }, {
5930
+ data: null,
5931
+ image: data,
5932
+ _instanced: false,
5933
+ bounds: [west, south, east, north],
5934
+ textureParameters: {
5993
5935
  minFilter: blurredTexture ? 'linear' : 'nearest',
5994
5936
  magFilter: blurredTexture ? 'linear' : 'nearest',
5995
- },
5937
+ },
5996
5938
  // TODO check if works!!!
5997
- extensions: clampToTerrain ? [new extensions._TerrainExtension()] : [] }, ((clampToTerrain === null || clampToTerrain === void 0 ? void 0 : clampToTerrain.terrainDrawMode)
5998
- ? { terrainDrawMode: clampToTerrain.terrainDrawMode }
5999
- : {})));
5939
+ extensions: clampToTerrain ? [new extensions._TerrainExtension()] : [],
5940
+ ...(hasDrawMode
5941
+ ? { terrainDrawMode: clampToTerrain.terrainDrawMode }
5942
+ : {}),
5943
+ });
6000
5944
  }
6001
5945
  renderLayers() {
6002
- const { rasterData, blurredTexture, opacity, clampToTerrain,
6003
- // tileSize,
6004
- maxRequests, onTileLoad, onTileUnload, onTileError, maxCacheSize, maxCacheByteSize, refinementStrategy, cogBitmapOptions, } = this.props;
5946
+ const { clampToTerrain, maxRequests, onTileLoad, onTileUnload, onTileError, maxCacheSize, maxCacheByteSize, refinementStrategy, cogBitmapOptions, } = this.props;
6005
5947
  if (this.state.isTiled && this.state.initialized) {
6006
5948
  const { tileSize } = this.state.bitmapCogTiles;
6007
5949
  return new geoLayers.TileLayer(this.getSubLayerProps({
@@ -6036,28 +5978,7 @@ class CogBitmapLayer extends core.CompositeLayer {
6036
5978
  return null;
6037
5979
  }
6038
5980
  }
6039
- CogBitmapLayer.defaultProps = defaultProps$1;
6040
- CogBitmapLayer.layerName = 'CogBitmapLayer';
6041
5981
 
6042
- // Copyright (c) 2015 - 2017 Uber Technologies, Inc.
6043
- //
6044
- // Permission is hereby granted, free of charge, to any person obtaining a copy
6045
- // of this software and associated documentation files (the "Software"), to deal
6046
- // in the Software without restriction, including without limitation the rights
6047
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
6048
- // copies of the Software, and to permit persons to whom the Software is
6049
- // furnished to do so, subject to the following conditions:
6050
- //
6051
- // The above copyright notice and this permission notice shall be included in
6052
- // all copies or substantial portions of the Software.
6053
- //
6054
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6055
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6056
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
6057
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
6058
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
6059
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
6060
- // THE SOFTWARE.
6061
5982
  const urlType = {
6062
5983
  type: 'object',
6063
5984
  value: null,
@@ -6084,19 +6005,20 @@ const urlType = {
6084
6005
  },
6085
6006
  };
6086
6007
  const DUMMY_DATA = [1];
6087
- const defaultProps = Object.assign(Object.assign({}, geoLayers.TileLayer.defaultProps), {
6008
+ const defaultProps = {
6009
+ ...geoLayers.TileLayer.defaultProps,
6088
6010
  // Image url that encodes height data
6089
- elevationData: urlType,
6011
+ elevationData: urlType,
6090
6012
  // Image url to use as texture
6091
- texture: Object.assign(Object.assign({}, urlType), { optional: true }),
6013
+ texture: { ...urlType, optional: true },
6092
6014
  // Martini error tolerance in meters, smaller number -> more detailed mesh
6093
- meshMaxError: { type: 'number', value: 4.0 },
6015
+ meshMaxError: { type: 'number', value: 4.0 },
6094
6016
  // Bounding box of the terrain image, [minX, minY, maxX, maxY] in world coordinates
6095
6017
  bounds: {
6096
6018
  type: 'array', value: null, optional: true, compare: true,
6097
- },
6019
+ },
6098
6020
  // Color to use if texture is unavailable
6099
- color: { type: 'color', value: [255, 255, 255] },
6021
+ color: { type: 'color', value: [255, 255, 255] },
6100
6022
  // Object to decode height data, from (r, g, b) to height in meters
6101
6023
  elevationDecoder: {
6102
6024
  type: 'object',
@@ -6106,11 +6028,14 @@ const defaultProps = Object.assign(Object.assign({}, geoLayers.TileLayer.default
6106
6028
  bScaler: 0,
6107
6029
  offset: 0,
6108
6030
  },
6109
- },
6031
+ },
6110
6032
  // Supply url to local terrain worker bundle. Only required if running offline and cannot access CDN.
6111
- workerUrl: '',
6033
+ workerUrl: '',
6112
6034
  // Same as SimpleMeshLayer wireframe
6113
- wireframe: false, material: true });
6035
+ wireframe: false,
6036
+ material: true,
6037
+ // loaders: [TerrainLoader],
6038
+ };
6114
6039
  // Turns array of templates into a single string to work around shallow change
6115
6040
  function urlTemplateToUpdateTrigger(template) {
6116
6041
  if (Array.isArray(template)) {
@@ -6122,28 +6047,25 @@ function urlTemplateToUpdateTrigger(template) {
6122
6047
  // TODO use meshMaxError
6123
6048
  // TODO - pass signal to getTile
6124
6049
  /** Render mesh surfaces from height map images. */
6125
- class TerrainLayer extends core.CompositeLayer {
6126
- initializeState(context) {
6127
- const _super = Object.create(null, {
6128
- initializeState: { get: () => super.initializeState }
6129
- });
6130
- return __awaiter(this, void 0, void 0, function* () {
6131
- _super.initializeState.call(this, context);
6132
- this.setState({
6133
- terrainCogTiles: new CogTiles(this.props.terrainOptions),
6134
- initialized: false,
6135
- });
6136
- yield this.init(this.terrainUrl);
6050
+ class CogTerrainLayer extends core.CompositeLayer {
6051
+ static defaultProps = defaultProps;
6052
+ static layerName = 'CogTerrainLayer';
6053
+ // terrainCogTiles: CogTiles;
6054
+ terrainUrl;
6055
+ async initializeState(context) {
6056
+ super.initializeState(context);
6057
+ this.setState({
6058
+ terrainCogTiles: new CogTiles(this.props.terrainOptions),
6059
+ initialized: false,
6137
6060
  });
6061
+ await this.init(this.terrainUrl);
6138
6062
  }
6139
- init(terrainUrl) {
6140
- return __awaiter(this, void 0, void 0, function* () {
6141
- yield this.state.terrainCogTiles.initializeCog(this.props.elevationData);
6142
- // this.tileSize = this.terrainCogTiles.getTileSize(cog);
6143
- const zoomRange = this.state.terrainCogTiles.getZoomRange();
6144
- const [minZoom, maxZoom] = zoomRange;
6145
- this.setState({ initialized: true, minZoom, maxZoom });
6146
- });
6063
+ async init() {
6064
+ await this.state.terrainCogTiles.initializeCog(this.props.elevationData);
6065
+ // this.tileSize = this.terrainCogTiles.getTileSize(cog);
6066
+ const zoomRange = this.state.terrainCogTiles.getZoomRange();
6067
+ const [minZoom, maxZoom] = zoomRange;
6068
+ this.setState({ initialized: true, minZoom, maxZoom });
6147
6069
  }
6148
6070
  updateState({ props, oldProps }) {
6149
6071
  const elevationDataChanged = props.elevationData !== oldProps.elevationData;
@@ -6160,8 +6082,6 @@ class TerrainLayer extends core.CompositeLayer {
6160
6082
  || props.elevationDecoder !== oldProps.elevationDecoder
6161
6083
  || props.bounds !== oldProps.bounds;
6162
6084
  if (!this.state.isTiled && shouldReload) ;
6163
- // TODO - remove in v9
6164
- // @ts-ignore
6165
6085
  if (props.workerUrl) {
6166
6086
  core.log.removed('workerUrl', 'loadOptions.terrain.workerUrl')();
6167
6087
  }
@@ -6171,36 +6091,47 @@ class TerrainLayer extends core.CompositeLayer {
6171
6091
  return null;
6172
6092
  }
6173
6093
  let loadOptions = this.getLoadOptions();
6174
- loadOptions = Object.assign(Object.assign({}, loadOptions), { _workerType: 'test', terrain: Object.assign(Object.assign({ skirtHeight: this.state.isTiled ? meshMaxError * 2 : 0 }, loadOptions === null || loadOptions === void 0 ? void 0 : loadOptions.terrain), { bounds,
6094
+ loadOptions = {
6095
+ ...loadOptions,
6096
+ _workerType: 'test',
6097
+ terrain: {
6098
+ skirtHeight: this.state.isTiled ? meshMaxError * 2 : 0,
6099
+ ...loadOptions?.terrain,
6100
+ bounds,
6175
6101
  meshMaxError,
6176
- elevationDecoder }) });
6102
+ elevationDecoder,
6103
+ },
6104
+ };
6177
6105
  const { fetch } = this.props;
6178
6106
  return fetch(elevationData, {
6179
6107
  propName: 'elevationData', layer: this, loadOptions, signal, loaders: [],
6180
6108
  });
6181
6109
  }
6182
- getTiledTerrainData(tile) {
6183
- return __awaiter(this, void 0, void 0, function* () {
6184
- this.props;
6185
- const { viewport } = this.context;
6186
- let bottomLeft = [0, 0];
6187
- let topRight = [0, 0];
6188
- if (viewport.isGeospatial) {
6189
- const bbox = tile.bbox;
6190
- bottomLeft = viewport.projectFlat([bbox.west, bbox.south]);
6191
- topRight = viewport.projectFlat([bbox.east, bbox.north]);
6192
- }
6193
- else {
6194
- const bbox = tile.bbox;
6195
- bottomLeft = [bbox.left, bbox.bottom];
6196
- topRight = [bbox.right, bbox.top];
6197
- }
6198
- const bounds = [bottomLeft[0], bottomLeft[1], topRight[0], topRight[1]];
6199
- // TODO - pass signal to getTile
6200
- // abort request if signal is aborted
6201
- const terrain = yield this.state.terrainCogTiles.getTile(tile.index.x, tile.index.y, tile.index.z, bounds, this.props.meshMaxError);
6202
- return Promise.all([terrain]);
6203
- });
6110
+ async getTiledTerrainData(tile) {
6111
+ // const {
6112
+ // elevationData, fetch, texture, elevationDecoder, meshMaxError,
6113
+ // } = this.props;
6114
+ const { viewport } = this.context;
6115
+ // const dataUrl = getURLFromTemplate(elevationData, tile);
6116
+ // const textureUrl = texture && getURLFromTemplate(texture, tile);
6117
+ // const { signal } = tile;
6118
+ let bottomLeft = [0, 0];
6119
+ let topRight = [0, 0];
6120
+ if (viewport.isGeospatial) {
6121
+ const bbox = tile.bbox;
6122
+ bottomLeft = viewport.projectFlat([bbox.west, bbox.south]);
6123
+ topRight = viewport.projectFlat([bbox.east, bbox.north]);
6124
+ }
6125
+ else {
6126
+ const bbox = tile.bbox;
6127
+ bottomLeft = [bbox.left, bbox.bottom];
6128
+ topRight = [bbox.right, bbox.top];
6129
+ }
6130
+ const bounds = [bottomLeft[0], bottomLeft[1], topRight[0], topRight[1]];
6131
+ // TODO - pass signal to getTile
6132
+ // abort request if signal is aborted
6133
+ const terrain = await this.state.terrainCogTiles.getTile(tile.index.x, tile.index.y, tile.index.z, bounds, this.props.meshMaxError);
6134
+ return Promise.all([terrain, null]);
6204
6135
  }
6205
6136
  renderSubLayers(props) {
6206
6137
  const SubLayerClass = this.getSubLayerClass('mesh', meshLayers.SimpleMeshLayer);
@@ -6211,13 +6142,13 @@ class TerrainLayer extends core.CompositeLayer {
6211
6142
  }
6212
6143
  // const [mesh, texture] = data;
6213
6144
  const [mesh] = data;
6214
- return new SubLayerClass(Object.assign(Object.assign({}, props), { tileSize: 256 }), {
6145
+ return new SubLayerClass({ ...props, tileSize: 256 }, {
6215
6146
  data: DUMMY_DATA,
6216
6147
  mesh,
6217
6148
  // texture,
6218
6149
  _instanced: false,
6219
6150
  coordinateSystem: core.COORDINATE_SYSTEM.CARTESIAN,
6220
- getPosition: (d) => [0, 0, 0],
6151
+ // getPosition: (d) => [0, 0, 0],
6221
6152
  getColor: color,
6222
6153
  wireframe,
6223
6154
  material,
@@ -6233,10 +6164,9 @@ class TerrainLayer extends core.CompositeLayer {
6233
6164
  .map((tile) => tile.content)
6234
6165
  .filter((x) => x && x[0])
6235
6166
  .map((arr) => {
6236
- var _a, _b;
6237
- // @ts-ignore
6238
- const bounds = (_b = (_a = arr[0]) === null || _a === void 0 ? void 0 : _a.header) === null || _b === void 0 ? void 0 : _b.boundingBox;
6239
- return bounds === null || bounds === void 0 ? void 0 : bounds.map((bound) => bound[2]);
6167
+ // @ts-expect-error: Tile content structure is not fully typed in the source layer
6168
+ const bounds = arr[0]?.header?.boundingBox;
6169
+ return bounds?.map((bound) => bound[2]);
6240
6170
  });
6241
6171
  if (ranges.length === 0) {
6242
6172
  return;
@@ -6248,7 +6178,13 @@ class TerrainLayer extends core.CompositeLayer {
6248
6178
  }
6249
6179
  }
6250
6180
  renderLayers() {
6251
- const { color, material, elevationData, texture, wireframe, meshMaxError, elevationDecoder, tileSize, extent, maxRequests, onTileLoad, onTileUnload, onTileError, maxCacheSize, maxCacheByteSize, refinementStrategy, } = this.props;
6181
+ const {
6182
+ // color,
6183
+ // material,
6184
+ elevationData,
6185
+ // texture,
6186
+ // wireframe,
6187
+ meshMaxError, elevationDecoder, tileSize, extent, maxRequests, onTileLoad, onTileUnload, onTileError, maxCacheSize, maxCacheByteSize, refinementStrategy, } = this.props;
6252
6188
  if (this.state.isTiled && this.state.initialized) {
6253
6189
  return new geoLayers.TileLayer(this.getSubLayerProps({
6254
6190
  id: 'tiles',
@@ -6299,8 +6235,6 @@ class TerrainLayer extends core.CompositeLayer {
6299
6235
  // );
6300
6236
  }
6301
6237
  }
6302
- TerrainLayer.defaultProps = defaultProps;
6303
- TerrainLayer.layerName = 'TerrainLayer';
6304
6238
 
6305
6239
  class RawDecoder extends BaseDecoder {
6306
6240
  decodeBlock(buffer) {
@@ -6309,8 +6243,8 @@ class RawDecoder extends BaseDecoder {
6309
6243
  }
6310
6244
 
6311
6245
  var raw = /*#__PURE__*/Object.freeze({
6312
- __proto__: null,
6313
- default: RawDecoder
6246
+ __proto__: null,
6247
+ default: RawDecoder
6314
6248
  });
6315
6249
 
6316
6250
  const MIN_BITS = 9;
@@ -6444,8 +6378,8 @@ class LZWDecoder extends BaseDecoder {
6444
6378
  }
6445
6379
 
6446
6380
  var lzw = /*#__PURE__*/Object.freeze({
6447
- __proto__: null,
6448
- default: LZWDecoder
6381
+ __proto__: null,
6382
+ default: LZWDecoder
6449
6383
  });
6450
6384
 
6451
6385
  /* -*- tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
@@ -7343,8 +7277,8 @@ class JpegDecoder extends BaseDecoder {
7343
7277
  }
7344
7278
 
7345
7279
  var jpeg = /*#__PURE__*/Object.freeze({
7346
- __proto__: null,
7347
- default: JpegDecoder
7280
+ __proto__: null,
7281
+ default: JpegDecoder
7348
7282
  });
7349
7283
 
7350
7284
  /*! pako 2.1.0 https://github.com/nodeca/pako @license (MIT AND Zlib) */
@@ -14115,8 +14049,8 @@ class DeflateDecoder extends BaseDecoder {
14115
14049
  }
14116
14050
 
14117
14051
  var deflate = /*#__PURE__*/Object.freeze({
14118
- __proto__: null,
14119
- default: DeflateDecoder
14052
+ __proto__: null,
14053
+ default: DeflateDecoder
14120
14054
  });
14121
14055
 
14122
14056
  class PackbitsDecoder extends BaseDecoder {
@@ -14145,8 +14079,8 @@ class PackbitsDecoder extends BaseDecoder {
14145
14079
  }
14146
14080
 
14147
14081
  var packbits = /*#__PURE__*/Object.freeze({
14148
- __proto__: null,
14149
- default: PackbitsDecoder
14082
+ __proto__: null,
14083
+ default: PackbitsDecoder
14150
14084
  });
14151
14085
 
14152
14086
  var LercDecode = {exports: {}};
@@ -16589,9 +16523,9 @@ class LercDecoder extends BaseDecoder {
16589
16523
  }
16590
16524
 
16591
16525
  var lerc = /*#__PURE__*/Object.freeze({
16592
- __proto__: null,
16593
- default: LercDecoder,
16594
- zstd: zstd
16526
+ __proto__: null,
16527
+ default: LercDecoder,
16528
+ zstd: zstd
16595
16529
  });
16596
16530
 
16597
16531
  /**
@@ -16634,12 +16568,12 @@ class WebImageDecoder extends BaseDecoder {
16634
16568
  }
16635
16569
 
16636
16570
  var webimage = /*#__PURE__*/Object.freeze({
16637
- __proto__: null,
16638
- default: WebImageDecoder
16571
+ __proto__: null,
16572
+ default: WebImageDecoder
16639
16573
  });
16640
16574
 
16641
16575
  exports.CogBitmapLayer = CogBitmapLayer;
16642
- exports.CogTerrainLayer = TerrainLayer;
16576
+ exports.CogTerrainLayer = CogTerrainLayer;
16643
16577
  exports.CogTiles = CogTiles;
16644
16578
  exports.GeoImage = GeoImage;
16645
16579
  //# sourceMappingURL=index.js.map