@gisatcz/deckgl-geolib 2.5.0-dev.2 → 2.5.0-dev.3

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/esm/index.js CHANGED
@@ -4872,6 +4872,7 @@ const DefaultGeoImageOptions = {
4872
4872
  useChannelIndex: null,
4873
4873
  noDataValue: undefined,
4874
4874
  multiplier: 1.0,
4875
+ verticalExaggeration: 1.0,
4875
4876
  numOfChannels: undefined,
4876
4877
  planarConfig: undefined,
4877
4878
  // --- Mesh generation (terrain only) ---
@@ -5546,25 +5547,31 @@ function addSkirt(attributes, triangles, skirtHeight, outsideIndices) {
5546
5547
  * @returns {number[][]} - outside edges data
5547
5548
  */
5548
5549
  function getOutsideEdgesFromTriangles(triangles) {
5549
- const edges = [];
5550
- for (let i = 0; i < triangles.length; i += 3) {
5551
- edges.push([triangles[i], triangles[i + 1]]);
5552
- edges.push([triangles[i + 1], triangles[i + 2]]);
5553
- edges.push([triangles[i + 2], triangles[i]]);
5554
- }
5555
- edges.sort((a, b) => Math.min(...a) - Math.min(...b) || Math.max(...a) - Math.max(...b));
5556
- const outsideEdges = [];
5557
- let index = 0;
5558
- while (index < edges.length) {
5559
- if (edges[index][0] === edges[index + 1]?.[1] && edges[index][1] === edges[index + 1]?.[0]) {
5560
- index += 2;
5550
+ // Use integer keys instead of strings: min * 70000 + max is collision-free
5551
+ // for any grid 257×257 (66,049 vertices < 70,000)
5552
+ const edgeMap = new Map();
5553
+ const processEdge = (a, b) => {
5554
+ const min = Math.min(a, b);
5555
+ const max = Math.max(a, b);
5556
+ // Integer key: no string allocation per edge
5557
+ const key = min * 70000 + max;
5558
+ if (edgeMap.has(key)) {
5559
+ edgeMap.delete(key); // Interior edge, remove
5561
5560
  }
5562
5561
  else {
5563
- outsideEdges.push(edges[index]);
5564
- index++;
5562
+ edgeMap.set(key, [a, b]);
5565
5563
  }
5564
+ };
5565
+ for (let i = 0; i < triangles.length; i += 3) {
5566
+ const v0 = triangles[i];
5567
+ const v1 = triangles[i + 1];
5568
+ const v2 = triangles[i + 2];
5569
+ // Process each edge inline — no temporary array allocation per triangle
5570
+ processEdge(v0, v1);
5571
+ processEdge(v1, v2);
5572
+ processEdge(v2, v0);
5566
5573
  }
5567
- return outsideEdges;
5574
+ return Array.from(edgeMap.values());
5568
5575
  }
5569
5576
  /**
5570
5577
  * Get geometry edges that located on a border of the mesh
@@ -6282,7 +6289,7 @@ class TerrainGenerator {
6282
6289
  const meshWidth = isKernel ? 257 : width;
6283
6290
  const meshHeight = isKernel ? 257 : height;
6284
6291
  // 2. Tesselate (Generate Mesh)
6285
- const { terrainSkirtHeight } = options;
6292
+ const { terrainSkirtHeight, verticalExaggeration = 1.0 } = options;
6286
6293
  let mesh;
6287
6294
  switch (options.tesselator) {
6288
6295
  case 'martini':
@@ -6298,13 +6305,17 @@ class TerrainGenerator {
6298
6305
  }
6299
6306
  const { vertices } = mesh;
6300
6307
  let { triangles } = mesh;
6301
- let attributes = this.getMeshAttributes(vertices, meshTerrain, meshWidth, meshHeight, input.bounds);
6308
+ let attributes = this.getMeshAttributes(vertices, meshTerrain, meshWidth, meshHeight, input.bounds, verticalExaggeration);
6302
6309
  // Compute bounding box before adding skirt so that z values are not skewed
6303
6310
  const boundingBox = getMeshBoundingBox(attributes);
6304
6311
  if (terrainSkirtHeight) {
6305
- const { attributes: newAttributes, triangles: newTriangles } = addSkirt(attributes, triangles, terrainSkirtHeight);
6306
- attributes = newAttributes;
6307
- triangles = newTriangles;
6312
+ const scaledSkirtHeight = terrainSkirtHeight * verticalExaggeration;
6313
+ // Skip skirt generation if scaled height is zero (e.g., verticalExaggeration = 0)
6314
+ if (scaledSkirtHeight > 0) {
6315
+ const { attributes: newAttributes, triangles: newTriangles } = addSkirt(attributes, triangles, scaledSkirtHeight);
6316
+ attributes = newAttributes;
6317
+ triangles = newTriangles;
6318
+ }
6308
6319
  }
6309
6320
  const map = {
6310
6321
  // Data return by this loader implementation
@@ -6500,10 +6511,10 @@ class TerrainGenerator {
6500
6511
  const vertices = coords;
6501
6512
  return { vertices, triangles };
6502
6513
  }
6503
- static getMeshAttributes(vertices, terrain, width, height, bounds) {
6514
+ static getMeshAttributes(vertices, terrain, width, height, bounds, verticalExaggeration = 1.0) {
6504
6515
  const gridSize = width === 257 ? 257 : width + 1;
6505
6516
  const numOfVerticies = vertices.length / 2;
6506
- // vec3. x, y in pixels, z in meters
6517
+ // vec3. x, y in pixels, z in meters (scaled by verticalExaggeration)
6507
6518
  const positions = new Float32Array(numOfVerticies * 3);
6508
6519
  // vec2. 1 to 1 relationship with position. represents the uv on the texture image. 0,0 to 1,1.
6509
6520
  const texCoords = new Float32Array(numOfVerticies * 2);
@@ -6520,7 +6531,7 @@ class TerrainGenerator {
6520
6531
  const pixelIdx = y * gridSize + x;
6521
6532
  positions[3 * i] = x * xScale + minX;
6522
6533
  positions[3 * i + 1] = -y * yScale + maxY;
6523
- positions[3 * i + 2] = terrain[pixelIdx];
6534
+ positions[3 * i + 2] = terrain[pixelIdx] * verticalExaggeration;
6524
6535
  texCoords[2 * i] = x / effectiveWidth;
6525
6536
  texCoords[2 * i + 1] = y / effectiveHeight;
6526
6537
  }