itowns 2.43.2-next.0 → 2.43.2-next.10

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 (67) hide show
  1. package/README.md +2 -0
  2. package/dist/debug.js +1 -1
  3. package/dist/debug.js.map +1 -1
  4. package/dist/itowns.js +1 -1
  5. package/dist/itowns.js.map +1 -1
  6. package/dist/itowns_widgets.js +1 -1
  7. package/dist/itowns_widgets.js.map +1 -1
  8. package/examples/3dtiles_25d.html +1 -1
  9. package/examples/3dtiles_basic.html +2 -2
  10. package/examples/3dtiles_batch_table.html +1 -3
  11. package/examples/3dtiles_pointcloud.html +9 -15
  12. package/examples/config.json +2 -1
  13. package/examples/copc_simple_loader.html +128 -0
  14. package/examples/entwine_3d_loader.html +1 -1
  15. package/examples/entwine_simple_loader.html +1 -1
  16. package/examples/js/plugins/COGParser.js +84 -50
  17. package/examples/js/plugins/COGSource.js +7 -4
  18. package/examples/layers/JSONLayers/OPENSM.json +1 -1
  19. package/examples/potree_25d_map.html +1 -1
  20. package/examples/potree_3d_map.html +1 -1
  21. package/examples/source_file_cog.html +22 -5
  22. package/lib/Controls/FirstPersonControls.js +0 -1
  23. package/lib/Controls/FlyControls.js +0 -1
  24. package/lib/Converter/Feature2Mesh.js +2 -4
  25. package/lib/Converter/textureConverter.js +1 -1
  26. package/lib/Core/3DTiles/C3DTBatchTable.js +1 -1
  27. package/lib/Core/3DTiles/C3DTFeature.js +0 -1
  28. package/lib/Core/CopcNode.js +174 -0
  29. package/lib/Core/Feature.js +1 -2
  30. package/lib/Core/Geographic/CoordStars.js +0 -1
  31. package/lib/Core/Label.js +0 -1
  32. package/lib/Core/MainLoop.js +0 -1
  33. package/lib/Core/Prefab/Globe/Atmosphere.js +0 -4
  34. package/lib/Core/Prefab/Globe/GlobeLayer.js +3 -3
  35. package/lib/Core/Style.js +2 -4
  36. package/lib/Core/View.js +2 -4
  37. package/lib/Layer/C3DTilesLayer.js +3 -1
  38. package/lib/Layer/CopcLayer.js +59 -0
  39. package/lib/Layer/ElevationLayer.js +2 -3
  40. package/lib/Layer/GeoidLayer.js +1 -2
  41. package/lib/Layer/LabelLayer.js +8 -17
  42. package/lib/Layer/Layer.js +4 -2
  43. package/lib/Layer/PointCloudLayer.js +4 -7
  44. package/lib/Layer/ReferencingLayerProperties.js +3 -3
  45. package/lib/Layer/TiledGeometryLayer.js +2 -3
  46. package/lib/Main.js +2 -0
  47. package/lib/Parser/GeoJsonParser.js +2 -3
  48. package/lib/Parser/LASLoader.js +45 -1
  49. package/lib/Parser/LASParser.js +57 -25
  50. package/lib/Parser/deprecated/LegacyGLTFLoader.js +1 -2
  51. package/lib/Process/FeatureProcessing.js +1 -2
  52. package/lib/Process/LayeredMaterialNodeProcessing.js +3 -9
  53. package/lib/Process/ObjectRemovalHelper.js +1 -2
  54. package/lib/Provider/3dTilesProvider.js +1 -0
  55. package/lib/Renderer/ColorLayersOrdering.js +1 -2
  56. package/lib/Renderer/Label2DRenderer.js +1 -4
  57. package/lib/Renderer/PointsMaterial.js +14 -9
  58. package/lib/Renderer/RenderMode.js +0 -1
  59. package/lib/Source/CopcSource.js +118 -0
  60. package/lib/Source/Source.js +3 -1
  61. package/lib/ThreeExtended/loaders/DDSLoader.js +11 -1
  62. package/lib/ThreeExtended/loaders/DRACOLoader.js +0 -1
  63. package/lib/ThreeExtended/loaders/GLTFLoader.js +1 -0
  64. package/lib/Utils/DEMUtils.js +2 -2
  65. package/lib/Utils/OrientationUtils.js +0 -1
  66. package/lib/Utils/gui/Searchbar.js +1 -2
  67. package/package.json +8 -7
@@ -0,0 +1,174 @@
1
+ import * as THREE from 'three';
2
+ import { Hierarchy } from 'copc';
3
+ import PointCloudNode from "./PointCloudNode.js";
4
+ const size = new THREE.Vector3();
5
+ const position = new THREE.Vector3();
6
+ const translation = new THREE.Vector3();
7
+ function buildId(depth, x, y, z) {
8
+ return `${depth}-${x}-${y}-${z}`;
9
+ }
10
+ class CopcNode extends PointCloudNode {
11
+ /**
12
+ * Constructs a new instance of a COPC Octree node
13
+ *
14
+ * @param {number} depth - Depth within the octree
15
+ * @param {number} x - X position within the octree
16
+ * @param {number} y - Y position within the octree
17
+ * @param {number} z - Z position with the octree
18
+ * @param {number} entryOffset - Offset from the beginning of the file of
19
+ * the node entry
20
+ * @param {number} entryLength - Size of the node entry
21
+ * @param {CopcLayer} layer - Parent COPC layer
22
+ * @param {number} [numPoints=0] - Number of points given by this entry
23
+ */
24
+ constructor(depth, x, y, z, entryOffset, entryLength, layer) {
25
+ let numPoints = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : 0;
26
+ super(numPoints, layer);
27
+ this.isCopcNode = true;
28
+ this.entryOffset = entryOffset;
29
+ this.entryLength = entryLength;
30
+ this.layer = layer;
31
+ this.depth = depth;
32
+ this.x = x;
33
+ this.y = y;
34
+ this.z = z;
35
+ }
36
+ get id() {
37
+ return buildId(this.depth, this.x, this.y, this.z);
38
+ }
39
+ get octreeIsLoaded() {
40
+ return this.numPoints >= 0;
41
+ }
42
+
43
+ /**
44
+ * @param {number} offset
45
+ * @param {number} size
46
+ */
47
+ async _fetch(offset, size) {
48
+ return this.layer.source.fetcher(this.layer.source.url, {
49
+ ...this.layer.source.networkOptions,
50
+ headers: {
51
+ ...this.layer.source.networkOptions.headers,
52
+ range: `bytes=${offset}-${offset + size - 1}`
53
+ }
54
+ });
55
+ }
56
+
57
+ /**
58
+ * Create an (A)xis (A)ligned (B)ounding (B)ox for the given node given
59
+ * `this` is its parent.
60
+ * @param {CopcNode} node - The child node
61
+ */
62
+ createChildAABB(node) {
63
+ // factor to apply, based on the depth difference (can be > 1)
64
+ const f = 2 ** (node.depth - this.depth);
65
+
66
+ // size of the child node bbox (Vector3), based on the size of the
67
+ // parent node, and divided by the factor
68
+ this.bbox.getSize(size).divideScalar(f);
69
+
70
+ // initialize the child node bbox at the location of the parent node bbox
71
+ node.bbox.min.copy(this.bbox.min);
72
+
73
+ // position of the parent node, if it was at the same depth as the
74
+ // child, found by multiplying the tree position by the factor
75
+ position.copy(this).multiplyScalar(f);
76
+
77
+ // difference in position between the two nodes, at child depth, and
78
+ // scale it using the size
79
+ translation.subVectors(node, position).multiply(size);
80
+
81
+ // apply the translation to the child node bbox
82
+ node.bbox.min.add(translation);
83
+
84
+ // use the size computed above to set the max
85
+ node.bbox.max.copy(node.bbox.min).add(size);
86
+ }
87
+
88
+ /**
89
+ * Create a CopcNode from the provided subtree and add it as child
90
+ * of the current node.
91
+ * @param {number} depth - Child node depth in the octree
92
+ * @param {number} x - Child node x position in the octree
93
+ * @param {number} y - Child node y position in the octree
94
+ * @param {number} z - Child node z position in the octree
95
+ * @param {Hierarchy.Subtree} hierarchy - Octree's subtree
96
+ * @param {CopcNode[]} stack - Stack of node candidates for traversal
97
+ */
98
+ findAndCreateChild(depth, x, y, z, hierarchy, stack) {
99
+ const id = buildId(depth, x, y, z);
100
+ let pointCount;
101
+ let offset;
102
+ let byteSize;
103
+ const node = hierarchy.nodes[id];
104
+ if (node) {
105
+ pointCount = node.pointCount;
106
+ offset = node.pointDataOffset;
107
+ byteSize = node.pointDataLength;
108
+ } else {
109
+ const page = hierarchy.pages[id];
110
+ if (!page) {
111
+ return;
112
+ }
113
+ pointCount = -1;
114
+ offset = page.pageOffset;
115
+ byteSize = page.pageLength;
116
+ }
117
+ const child = new CopcNode(depth, x, y, z, offset, byteSize, this.layer, pointCount);
118
+ this.add(child);
119
+ stack.push(child);
120
+ }
121
+ async loadOctree() {
122
+ // Load hierarchy
123
+ const buffer = await this._fetch(this.entryOffset, this.entryLength);
124
+ const hierarchy = await Hierarchy.parse(new Uint8Array(buffer));
125
+
126
+ // Update current node entry from loaded subtree
127
+ const node = hierarchy.nodes[this.id];
128
+ if (!node) {
129
+ return Promise.reject('[CopcNode]: Ill-formed data, entry not found in hierarchy.');
130
+ }
131
+ this.numPoints = node.pointCount;
132
+ this.entryOffset = node.pointDataOffset;
133
+ this.entryLength = node.pointDataLength;
134
+
135
+ // Load subtree entries
136
+ const stack = [];
137
+ stack.push(this);
138
+ while (stack.length) {
139
+ const node = stack.shift();
140
+ const depth = node.depth + 1;
141
+ const x = node.x * 2;
142
+ const y = node.y * 2;
143
+ const z = node.z * 2;
144
+ node.findAndCreateChild(depth, x, y, z, hierarchy, stack);
145
+ node.findAndCreateChild(depth, x + 1, y, z, hierarchy, stack);
146
+ node.findAndCreateChild(depth, x, y + 1, z, hierarchy, stack);
147
+ node.findAndCreateChild(depth, x + 1, y + 1, z, hierarchy, stack);
148
+ node.findAndCreateChild(depth, x, y, z + 1, hierarchy, stack);
149
+ node.findAndCreateChild(depth, x + 1, y, z + 1, hierarchy, stack);
150
+ node.findAndCreateChild(depth, x, y + 1, z + 1, hierarchy, stack);
151
+ node.findAndCreateChild(depth, x + 1, y + 1, z + 1, hierarchy, stack);
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Load the COPC Buffer geometry for this node.
157
+ * @returns {Promise<THREE.BufferGeometry>}
158
+ */
159
+ async load() {
160
+ if (!this.octreeIsLoaded) {
161
+ await this.loadOctree();
162
+ }
163
+ const buffer = await this._fetch(this.entryOffset, this.entryLength);
164
+ const geometry = await this.layer.source.parser(buffer, {
165
+ in: {
166
+ ...this.layer.source,
167
+ pointCount: this.numPoints
168
+ },
169
+ out: this.layer
170
+ });
171
+ return geometry;
172
+ }
173
+ }
174
+ export default CopcNode;
@@ -338,10 +338,9 @@ export class FeatureCollection extends THREE.Object3D {
338
338
  * @param {FeatureBuildingOptions|Layer} options The building options .
339
339
  */
340
340
  constructor(options) {
341
- var _options$source;
342
341
  super();
343
342
  this.isFeatureCollection = true;
344
- this.crs = CRS.formatToEPSG(options.accurate || !((_options$source = options.source) !== null && _options$source !== void 0 && _options$source.crs) ? options.crs : options.source.crs);
343
+ this.crs = CRS.formatToEPSG(options.accurate || !options.source?.crs ? options.crs : options.source.crs);
345
344
  this.features = [];
346
345
  this.mergeFeatures = options.mergeFeatures === undefined ? true : options.mergeFeatures;
347
346
  this.size = options.structure == '3d' ? 3 : 2;
@@ -68,7 +68,6 @@ const CoordStars = {
68
68
  };
69
69
  };
70
70
  },
71
-
72
71
  // Return scene coordinate ({x,y,z}) of sun
73
72
  getSunPositionInScene(date, lat, lon) {
74
73
  const sun = CoordStars.getSunPosition()(date, lat, lon);
package/lib/Core/Label.js CHANGED
@@ -71,7 +71,6 @@ class Label extends THREE.Object3D {
71
71
  // TODO: add smooth transition for fade in/out
72
72
  }
73
73
  },
74
-
75
74
  get() {
76
75
  return _visible;
77
76
  }
@@ -88,7 +88,6 @@ class MainLoop extends EventDispatcher {
88
88
  this.scheduler = scheduler;
89
89
  this.gfxEngine = engine; // TODO: remove me
90
90
  }
91
-
92
91
  scheduleViewUpdate(view, forceRedraw) {
93
92
  this.#needsRedraw |= forceRedraw;
94
93
  if (this.renderingState !== RENDERING_SCHEDULED) {
@@ -72,7 +72,6 @@ class Atmosphere extends GeometryLayer {
72
72
  value: new THREE.Vector2(window.innerWidth, window.innerHeight)
73
73
  } // Should be updated on screen resize...
74
74
  },
75
-
76
75
  vertexShader: GlowVS,
77
76
  fragmentShader: GlowFS,
78
77
  side: THREE.BackSide,
@@ -100,7 +99,6 @@ class Atmosphere extends GeometryLayer {
100
99
  value: new THREE.Vector2(window.innerWidth, window.innerHeight)
101
100
  } // Should be updated on screen resize...
102
101
  },
103
-
104
102
  vertexShader: GlowVS,
105
103
  fragmentShader: GlowFS,
106
104
  side: THREE.FrontSide,
@@ -135,7 +133,6 @@ class Atmosphere extends GeometryLayer {
135
133
  scaleDepth: 0.25
136
134
  // mieScaleDepth: 0.1,
137
135
  };
138
-
139
136
  this.object3d.updateMatrixWorld();
140
137
  }
141
138
  update(context, layer, node) {
@@ -288,7 +285,6 @@ class Atmosphere extends GeometryLayer {
288
285
  skyDome.material.uniforms.mieDirectionalG.value = effectController.mieDirectionalG;
289
286
  skyDome.material.uniforms.up.value = new THREE.Vector3(); // no more necessary, estimate normal from cam..
290
287
  }
291
-
292
288
  setRealisticOn(bool) {
293
289
  if (bool) {
294
290
  if (!this.realisticAtmosphere.children.length) {
@@ -3,7 +3,6 @@ import TiledGeometryLayer from "../../../Layer/TiledGeometryLayer.js";
3
3
  import { ellipsoidSizes } from "../../Math/Ellipsoid.js";
4
4
  import { globalExtentTMS, schemeTiles } from "../../Geographic/Extent.js";
5
5
  import BuilderEllipsoidTile from "./BuilderEllipsoidTile.js";
6
- import { SIZE_DIAGONAL_TEXTURE } from "../../../Process/LayeredMaterialNodeProcessing.js";
7
6
  import CRS from "../../Geographic/Crs.js";
8
7
 
9
8
  // matrix to convert sphere to ellipsoid
@@ -129,7 +128,7 @@ class GlobeLayer extends TiledGeometryLayer {
129
128
  return isOccluded;
130
129
  }
131
130
  computeTileZoomFromDistanceCamera(distance, camera) {
132
- const preSinus = SIZE_DIAGONAL_TEXTURE * (this.sseSubdivisionThreshold * 0.5) / camera._preSSE / ellipsoidSizes.x;
131
+ const preSinus = this.sizeDiagonalTexture * (this.sseSubdivisionThreshold * 0.5) / camera._preSSE / ellipsoidSizes.x;
133
132
  let sinus = distance * preSinus;
134
133
  let zoom = Math.log(Math.PI / (2.0 * Math.asin(sinus))) / Math.log(2);
135
134
  const delta = Math.PI / 2 ** zoom;
@@ -143,7 +142,8 @@ class GlobeLayer extends TiledGeometryLayer {
143
142
  const delta = Math.PI / 2 ** zoom;
144
143
  const circleChord = 2.0 * ellipsoidSizes.x * Math.sin(delta * 0.5);
145
144
  const radius = circleChord * 0.5;
146
- return camera._preSSE * (radius / SIZE_DIAGONAL_TEXTURE) / (this.sseSubdivisionThreshold * 0.5) + radius;
145
+ const error = radius / this.sizeDiagonalTexture;
146
+ return camera._preSSE * error / (this.sseSubdivisionThreshold * 0.5) + radius;
147
147
  }
148
148
  }
149
149
  export default GlobeLayer;
package/lib/Core/Style.js CHANGED
@@ -12,8 +12,7 @@ const matrix = document.createElementNS('http://www.w3.org/2000/svg', 'svg').cre
12
12
  const canvas = document.createElement('canvas');
13
13
  const inv255 = 1 / 255;
14
14
  function baseAltitudeDefault(properties, ctx) {
15
- var _ctx$coordinates;
16
- return (ctx === null || ctx === void 0 ? void 0 : (_ctx$coordinates = ctx.coordinates) === null || _ctx$coordinates === void 0 ? void 0 : _ctx$coordinates.z) || 0;
15
+ return ctx?.coordinates?.z || 0;
17
16
  }
18
17
  export function readExpression(property, ctx) {
19
18
  if (property != undefined) {
@@ -154,7 +153,6 @@ function defineStyleProperty(style, category, parameter, userValue, defaultValue
154
153
  Object.defineProperty(style[category], parameter, {
155
154
  enumerable: true,
156
155
  get: () => {
157
- var _style$context$featur, _style$context$featur2;
158
156
  // != to check for 'undefined' and 'null' value)
159
157
  if (property != undefined) {
160
158
  return property;
@@ -162,7 +160,7 @@ function defineStyleProperty(style, category, parameter, userValue, defaultValue
162
160
  if (userValue != undefined) {
163
161
  return readExpression(userValue, style.context);
164
162
  }
165
- const dataValue = (_style$context$featur = style.context.featureStyle) === null || _style$context$featur === void 0 ? void 0 : (_style$context$featur2 = _style$context$featur[category]) === null || _style$context$featur2 === void 0 ? void 0 : _style$context$featur2[parameter];
163
+ const dataValue = style.context.featureStyle?.[category]?.[parameter];
166
164
  if (dataValue != undefined) {
167
165
  return readExpression(dataValue, style.context);
168
166
  }
package/lib/Core/View.js CHANGED
@@ -232,8 +232,7 @@ class View extends THREE.EventDispatcher {
232
232
  * @returns {THREE.WebGLRenderer} the WebGLRenderer used to render this view.
233
233
  */
234
234
  get renderer() {
235
- var _this$mainLoop, _this$mainLoop$gfxEng;
236
- return (_this$mainLoop = this.mainLoop) === null || _this$mainLoop === void 0 ? void 0 : (_this$mainLoop$gfxEng = _this$mainLoop.gfxEngine) === null || _this$mainLoop$gfxEng === void 0 ? void 0 : _this$mainLoop$gfxEng.getRenderer();
235
+ return this.mainLoop?.gfxEngine?.getRenderer();
237
236
  }
238
237
 
239
238
  /**
@@ -241,8 +240,7 @@ class View extends THREE.EventDispatcher {
241
240
  * @returns {THREE.Camera} the threejs camera of this view
242
241
  */
243
242
  get camera3D() {
244
- var _this$camera;
245
- return (_this$camera = this.camera) === null || _this$camera === void 0 ? void 0 : _this$camera.camera3D;
243
+ return this.camera?.camera3D;
246
244
  }
247
245
 
248
246
  /**
@@ -92,7 +92,9 @@ class C3DTilesLayer extends GeometryLayer {
92
92
  * @param {Number} [config.cleanupDelay=1000] The time (in ms) after which a tile content (and its children) are
93
93
  * removed from the scene.
94
94
  * @param {C3DTExtensions} [config.registeredExtensions] 3D Tiles extensions managers registered for this tileset.
95
- * @param {String} [config.pntsMode= PNTS_MODE.COLOR] {@link PointsMaterials} Point cloud coloring mode. Only 'COLOR' or 'CLASSIFICATION' are possible. COLOR uses RGB colors of the points, CLASSIFICATION uses a classification property of the batch table to color points.
95
+ * @param {String} [config.pntsMode= PNTS_MODE.COLOR] {@link PointsMaterials} Point cloud coloring mode.
96
+ * Only 'COLOR' or 'CLASSIFICATION' are possible. COLOR uses RGB colors of the points,
97
+ * CLASSIFICATION uses a classification property of the batch table to color points.
96
98
  * @param {String} [config.pntsShape= PNTS_SHAPE.CIRCLE] Point cloud point shape. Only 'CIRCLE' or 'SQUARE' are possible.
97
99
  * @param {String} [config.pntsSizeMode= PNTS_SIZE_MODE.VALUE] {@link PointsMaterials} Point cloud size mode. Only 'VALUE' or 'ATTENUATED' are possible. VALUE use constant size, ATTENUATED compute size depending on distance from point to camera.
98
100
  * @param {Number} [config.pntsMinAttenuatedSize=3] Minimum scale used by 'ATTENUATED' size mode
@@ -0,0 +1,59 @@
1
+ import * as THREE from 'three';
2
+ import CopcNode from "../Core/CopcNode.js";
3
+ import PointCloudLayer from "./PointCloudLayer.js";
4
+
5
+ /**
6
+ * @classdesc
7
+ * A layer for [Cloud Optimised Point Cloud](https://copc.io) (COPC) datasets.
8
+ * See {@link PointCloudLayer} class for documentation on base properties.
9
+ *
10
+ * @extends {PointCloudLayer}
11
+ *
12
+ * @example
13
+ * // Create a new COPC layer
14
+ * const copcSource = new CopcSource({
15
+ * url: 'https://s3.amazonaws.com/hobu-lidar/autzen-classified.copc.laz',
16
+ * crs: 'EPSG:4978',
17
+ * colorDepth: 16, // bit-depth of 'color' attribute (either 8 or 16 bits)
18
+ * });
19
+ *
20
+ * const copcLayer = new CopcLayer('COPC', {
21
+ * source: copcSource,
22
+ * });
23
+ *
24
+ * View.prototype.addLayer.call(view, copcLayer);
25
+ */
26
+ class CopcLayer extends PointCloudLayer {
27
+ /**
28
+ * @param {string} id - Unique id of the layer.
29
+ * @param {Object} config - See {@link PointCloudLayer} for base pointcloud
30
+ * options.
31
+ */
32
+ constructor(id, config) {
33
+ super(id, config);
34
+ this.isCopcLayer = true;
35
+ const resolve = () => this;
36
+ this.whenReady = this.source.whenReady.then(( /** @type {CopcSource} */source) => {
37
+ const {
38
+ cube,
39
+ rootHierarchyPage
40
+ } = source.info;
41
+ const {
42
+ pageOffset,
43
+ pageLength
44
+ } = rootHierarchyPage;
45
+ this.root = new CopcNode(0, 0, 0, 0, pageOffset, pageLength, this, -1);
46
+ this.root.bbox.min.fromArray(cube, 0);
47
+ this.root.bbox.max.fromArray(cube, 3);
48
+ this.minElevationRange = source.header.min[2];
49
+ this.maxElevationRange = source.header.max[2];
50
+ this.scale = new THREE.Vector3(1.0, 1.0, 1.0);
51
+ this.offset = new THREE.Vector3(0.0, 0.0, 0.0);
52
+ return this.root.loadOctree().then(resolve);
53
+ });
54
+ }
55
+ get spacing() {
56
+ return this.source.info.spacing;
57
+ }
58
+ }
59
+ export default CopcLayer;
@@ -60,14 +60,13 @@ class ElevationLayer extends RasterLayer {
60
60
  * view.addLayer(elevation);
61
61
  */
62
62
  constructor(id) {
63
- var _config$clampValues, _config$clampValues2;
64
63
  let config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
65
64
  super(id, config);
66
65
  if (config.zmin || config.zmax) {
67
66
  console.warn('Config using zmin and zmax are deprecated, use {clampValues: {min, max}} structure.');
68
67
  }
69
- this.zmin = ((_config$clampValues = config.clampValues) === null || _config$clampValues === void 0 ? void 0 : _config$clampValues.min) ?? config.zmin;
70
- this.zmax = ((_config$clampValues2 = config.clampValues) === null || _config$clampValues2 === void 0 ? void 0 : _config$clampValues2.max) ?? config.zmax;
68
+ this.zmin = config.clampValues?.min ?? config.zmin;
69
+ this.zmax = config.clampValues?.max ?? config.zmax;
71
70
  this.isElevationLayer = true;
72
71
  this.defineLayerProperty('scale', this.scale || 1.0);
73
72
  }
@@ -1,8 +1,7 @@
1
1
  import Layer from "./Layer.js";
2
2
  import LayerUpdateState from "./LayerUpdateState.js";
3
3
  export function geoidLayerIsVisible(tilelayer) {
4
- var _tilelayer$attachedLa;
5
- return tilelayer === null || tilelayer === void 0 ? void 0 : (_tilelayer$attachedLa = tilelayer.attachedLayers.filter(l => l.isGeoidLayer)[0]) === null || _tilelayer$attachedLa === void 0 ? void 0 : _tilelayer$attachedLa.visible;
4
+ return tilelayer?.attachedLayers.filter(l => l.isGeoidLayer)[0]?.visible;
6
5
  }
7
6
 
8
7
  /**
@@ -195,11 +195,9 @@ class LabelLayer extends GeometryLayer {
195
195
  set visible(value) {
196
196
  super.visible = value;
197
197
  if (value) {
198
- var _this$domElement;
199
- (_this$domElement = this.domElement) === null || _this$domElement === void 0 ? void 0 : _this$domElement.show();
198
+ this.domElement?.show();
200
199
  } else {
201
- var _this$domElement2;
202
- (_this$domElement2 = this.domElement) === null || _this$domElement2 === void 0 ? void 0 : _this$domElement2.hide();
200
+ this.domElement?.hide();
203
201
  }
204
202
  }
205
203
  get submittedLabelNodes() {
@@ -231,16 +229,15 @@ class LabelLayer extends GeometryLayer {
231
229
  coord.crs = data.crs;
232
230
  context.setZoom(extent.zoom);
233
231
  data.features.forEach(f => {
234
- var _f$style, _f$style$text, _f$style2, _f$style2$point;
235
232
  // TODO: add support for LINE and POLYGON
236
233
  if (f.type !== FEATURE_TYPES.POINT) {
237
234
  return;
238
235
  }
239
236
  context.setFeature(f);
240
- const featureField = (_f$style = f.style) === null || _f$style === void 0 ? void 0 : (_f$style$text = _f$style.text) === null || _f$style$text === void 0 ? void 0 : _f$style$text.field;
237
+ const featureField = f.style?.text?.field;
241
238
 
242
239
  // determine if altitude style is specified by the user
243
- const altitudeStyle = (_f$style2 = f.style) === null || _f$style2 === void 0 ? void 0 : (_f$style2$point = _f$style2.point) === null || _f$style2$point === void 0 ? void 0 : _f$style2$point.base_altitude;
240
+ const altitudeStyle = f.style?.point?.base_altitude;
244
241
  const isDefaultElevationStyle = altitudeStyle instanceof Function && altitudeStyle.name == 'baseAltitudeDefault';
245
242
 
246
243
  // determine if the altitude needs update with ElevationLayer
@@ -292,19 +289,14 @@ class LabelLayer extends GeometryLayer {
292
289
  this.toHide.add(labelsNode);
293
290
  }
294
291
  #findClosestDomElement(node) {
295
- var _node$parent;
296
- if ((_node$parent = node.parent) !== null && _node$parent !== void 0 && _node$parent.isTileMesh) {
297
- var _node$parent$link$thi;
298
- return ((_node$parent$link$thi = node.parent.link[this.id]) === null || _node$parent$link$thi === void 0 ? void 0 : _node$parent$link$thi.domElements) || this.#findClosestDomElement(node.parent);
292
+ if (node.parent?.isTileMesh) {
293
+ return node.parent.link[this.id]?.domElements || this.#findClosestDomElement(node.parent);
299
294
  } else {
300
295
  return this.domElement;
301
296
  }
302
297
  }
303
298
  #hasLabelChildren(object) {
304
- return object.children.every(c => {
305
- var _c$layerUpdateState$t;
306
- return c.layerUpdateState && ((_c$layerUpdateState$t = c.layerUpdateState[this.id]) === null || _c$layerUpdateState$t === void 0 ? void 0 : _c$layerUpdateState$t.hasFinished());
307
- });
299
+ return object.children.every(c => c.layerUpdateState && c.layerUpdateState[this.id]?.hasFinished());
308
300
  }
309
301
 
310
302
  // Remove all labels invisible with pre-culling with screen grid
@@ -439,8 +431,7 @@ class LabelLayer extends GeometryLayer {
439
431
  this.removeNodeDomElement(node);
440
432
  }
441
433
  removeNodeDomElement(node) {
442
- var _node$link$this$id;
443
- if ((_node$link$this$id = node.link[this.id]) !== null && _node$link$this$id !== void 0 && _node$link$this$id.domElements) {
434
+ if (node.link[this.id]?.domElements) {
444
435
  const child = node.link[this.id].domElements.dom;
445
436
  child.parentElement.removeChild(child);
446
437
  delete node.link[this.id].domElements;
@@ -66,6 +66,7 @@ class Layer extends THREE.EventDispatcher {
66
66
  * @param {boolean} [config.addLabelLayer.performance=false] - In case label layer adding, so remove labels that have no chance of being visible.
67
67
  * Indeed, even in the best case, labels will never be displayed. By example, if there's many labels.
68
68
  * @param {boolean} [config.addLabelLayer.forceClampToTerrain=false] - use elevation layer to clamp label on terrain.
69
+ * @param {number} [config.subdivisionThreshold=256] - set the texture size and, if applied to the globe, affects the tile subdivision.
69
70
  *
70
71
  * @example
71
72
  * // Add and create a new Layer
@@ -100,8 +101,7 @@ class Layer extends THREE.EventDispatcher {
100
101
  super();
101
102
  this.isLayer = true;
102
103
  if (config.style && !(config.style instanceof Style)) {
103
- var _config$style$fill;
104
- if (typeof ((_config$style$fill = config.style.fill) === null || _config$style$fill === void 0 ? void 0 : _config$style$fill.pattern) === 'string') {
104
+ if (typeof config.style.fill?.pattern === 'string') {
105
105
  console.warn('Using style.fill.pattern = { source: Img|url } is adviced');
106
106
  config.style.fill.pattern = {
107
107
  source: config.style.fill.pattern
@@ -110,6 +110,8 @@ class Layer extends THREE.EventDispatcher {
110
110
  config.style = new Style(config.style);
111
111
  }
112
112
  this.style = config.style || new Style();
113
+ this.subdivisionThreshold = config.subdivisionThreshold || 256;
114
+ this.sizeDiagonalTexture = (2 * (this.subdivisionThreshold * this.subdivisionThreshold)) ** 0.5;
113
115
  Object.assign(this, config);
114
116
  Object.defineProperty(this, 'id', {
115
117
  value: id,
@@ -73,16 +73,13 @@ function markForDeletion(elt) {
73
73
  }
74
74
  }
75
75
  function changeIntensityRange(layer) {
76
- var _layer$material$inten;
77
- (_layer$material$inten = layer.material.intensityRange) === null || _layer$material$inten === void 0 ? void 0 : _layer$material$inten.set(layer.minIntensityRange, layer.maxIntensityRange);
76
+ layer.material.intensityRange?.set(layer.minIntensityRange, layer.maxIntensityRange);
78
77
  }
79
78
  function changeElevationRange(layer) {
80
- var _layer$material$eleva;
81
- (_layer$material$eleva = layer.material.elevationRange) === null || _layer$material$eleva === void 0 ? void 0 : _layer$material$eleva.set(layer.minElevationRange, layer.maxElevationRange);
79
+ layer.material.elevationRange?.set(layer.minElevationRange, layer.maxElevationRange);
82
80
  }
83
81
  function changeAngleRange(layer) {
84
- var _layer$material$angle;
85
- (_layer$material$angle = layer.material.angleRange) === null || _layer$material$angle === void 0 ? void 0 : _layer$material$angle.set(layer.minAngleRange, layer.maxAngleRange);
82
+ layer.material.angleRange?.set(layer.minAngleRange, layer.maxAngleRange);
86
83
  }
87
84
 
88
85
  /**
@@ -176,7 +173,7 @@ class PointCloudLayer extends GeometryLayer {
176
173
  if (this.material) {
177
174
  this.material.visible = this.visible;
178
175
  this.material.opacity = this.opacity;
179
- this.material.transparent = this.opacity < 1;
176
+ this.material.transparent = this.opacity < 1 || this.material.userData.needTransparency[this.material.mode];
180
177
  this.material.size = this.pointSize;
181
178
  this.material.scale = context.camera.preSSE;
182
179
  if (this.material.updateUniforms) {
@@ -1,6 +1,5 @@
1
1
  // next step is move these properties to Style class
2
2
  // and hide transparent mechanism
3
-
4
3
  function ReferLayerProperties(material, layer) {
5
4
  if (layer && layer.isGeometryLayer) {
6
5
  let transparent = material.transparent;
@@ -44,9 +43,10 @@ function ReferLayerProperties(material, layer) {
44
43
  });
45
44
  Object.defineProperty(material, 'transparent', {
46
45
  get: () => {
47
- if (transparent != material.layer.opacity < 1.0) {
46
+ const needTransparency = material.userData.needTransparency?.[material.mode] || material.layer.opacity < 1.0;
47
+ if (transparent != needTransparency) {
48
48
  material.needsUpdate = true;
49
- transparent = material.layer.opacity < 1.0;
49
+ transparent = needTransparency;
50
50
  }
51
51
  return transparent;
52
52
  }
@@ -4,7 +4,6 @@ import { InfoTiledGeometryLayer } from "./InfoLayer.js";
4
4
  import Picking from "../Core/Picking.js";
5
5
  import convertToTile from "../Converter/convertToTile.js";
6
6
  import ObjectRemovalHelper from "../Process/ObjectRemovalHelper.js";
7
- import { SIZE_DIAGONAL_TEXTURE } from "../Process/LayeredMaterialNodeProcessing.js";
8
7
  import { ImageryLayers } from "./Layer.js";
9
8
  import { CACHE_POLICIES } from "../Core/Scheduler/Cache.js";
10
9
  const subdivisionVector = new THREE.Vector3();
@@ -89,7 +88,7 @@ class TiledGeometryLayer extends GeometryLayer {
89
88
  this.object3d.add(...level0s);
90
89
  this.object3d.updateMatrixWorld();
91
90
  }));
92
- this.maxScreenSizeNode = this.sseSubdivisionThreshold * (SIZE_DIAGONAL_TEXTURE * 2);
91
+ this.maxScreenSizeNode = this.sseSubdivisionThreshold * (this.sizeDiagonalTexture * 2);
93
92
  }
94
93
  get hideSkirt() {
95
94
  return this._hideSkirt;
@@ -408,7 +407,7 @@ class TiledGeometryLayer extends GeometryLayer {
408
407
 
409
408
  // The screen space error is calculated to have a correct texture display.
410
409
  // For the projection of a texture's texel to be less than or equal to one pixel
411
- const sse = node.screenSize / (SIZE_DIAGONAL_TEXTURE * 2);
410
+ const sse = node.screenSize / (this.sizeDiagonalTexture * 2);
412
411
  return this.sseSubdivisionThreshold < sse;
413
412
  }
414
413
  }
package/lib/Main.js CHANGED
@@ -60,6 +60,7 @@ export { default as GlobeLayer } from "./Core/Prefab/Globe/GlobeLayer.js";
60
60
  export { default as PlanarLayer } from "./Core/Prefab/Planar/PlanarLayer.js";
61
61
  export { default as LabelLayer } from "./Layer/LabelLayer.js";
62
62
  export { default as EntwinePointTileLayer } from "./Layer/EntwinePointTileLayer.js";
63
+ export { default as CopcLayer } from "./Layer/CopcLayer.js";
63
64
  export { default as GeoidLayer } from "./Layer/GeoidLayer.js";
64
65
 
65
66
  // Sources provided by default in iTowns
@@ -78,6 +79,7 @@ export { default as C3DTilesSource } from "./Source/C3DTilesSource.js";
78
79
  export { default as C3DTilesIonSource } from "./Source/C3DTilesIonSource.js";
79
80
  export { default as C3DTilesGoogleSource } from "./Source/C3DTilesGoogleSource.js";
80
81
  export { default as EntwinePointTileSource } from "./Source/EntwinePointTileSource.js";
82
+ export { default as CopcSource } from "./Source/CopcSource.js";
81
83
 
82
84
  // Parsers provided by default in iTowns
83
85
  // Custom parser can be implemented as wanted, as long as the main function
@@ -132,8 +132,7 @@ function toFeatureType(jsonType) {
132
132
  const keyProperties = ['type', 'geometry', 'properties'];
133
133
  const firstCoordinates = a => a === undefined || Array.isArray(a) && !isNaN(a[0]) ? a : firstCoordinates(a[0]);
134
134
  function jsonFeatureToFeature(crsIn, json, collection) {
135
- var _json$geometry, _firstCoordinates;
136
- if (!((_json$geometry = json.geometry) !== null && _json$geometry !== void 0 && _json$geometry.type)) {
135
+ if (!json.geometry?.type) {
137
136
  console.warn('No geometry provided');
138
137
  return null;
139
138
  }
@@ -142,7 +141,7 @@ function jsonFeatureToFeature(crsIn, json, collection) {
142
141
  const feature = collection.requestFeatureByType(featureType);
143
142
  const coordinates = jsonType != 'point' ? json.geometry.coordinates : [json.geometry.coordinates];
144
143
  const properties = json.properties || {};
145
- feature.hasRawElevationData = ((_firstCoordinates = firstCoordinates(coordinates)) === null || _firstCoordinates === void 0 ? void 0 : _firstCoordinates.length) === 3;
144
+ feature.hasRawElevationData = firstCoordinates(coordinates)?.length === 3;
146
145
 
147
146
  // copy other properties
148
147
  for (const key of Object.keys(json)) {