itowns 2.45.1-next.0 → 2.45.1-next.1

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 (185) hide show
  1. package/dist/455.js +2 -0
  2. package/dist/455.js.map +1 -0
  3. package/dist/debug.js +3 -0
  4. package/dist/debug.js.LICENSE.txt +13 -0
  5. package/dist/debug.js.map +1 -0
  6. package/dist/itowns.js +3 -0
  7. package/dist/itowns.js.LICENSE.txt +5 -0
  8. package/dist/itowns.js.map +1 -0
  9. package/dist/itowns_lasparser.js +2 -0
  10. package/dist/itowns_lasparser.js.map +1 -0
  11. package/dist/itowns_lasworker.js +2 -0
  12. package/dist/itowns_lasworker.js.map +1 -0
  13. package/dist/itowns_potree2worker.js +2 -0
  14. package/dist/itowns_potree2worker.js.map +1 -0
  15. package/dist/itowns_widgets.js +2 -0
  16. package/dist/itowns_widgets.js.map +1 -0
  17. package/lib/Controls/FirstPersonControls.js +308 -0
  18. package/lib/Controls/FlyControls.js +175 -0
  19. package/lib/Controls/GlobeControls.js +1178 -0
  20. package/lib/Controls/PlanarControls.js +1025 -0
  21. package/lib/Controls/StateControl.js +432 -0
  22. package/lib/Controls/StreetControls.js +392 -0
  23. package/lib/Converter/Feature2Mesh.js +612 -0
  24. package/lib/Converter/Feature2Texture.js +174 -0
  25. package/lib/Converter/convertToTile.js +70 -0
  26. package/lib/Converter/textureConverter.js +43 -0
  27. package/lib/Core/3DTiles/C3DTBatchTable.js +131 -0
  28. package/lib/Core/3DTiles/C3DTBatchTableHierarchyExtension.js +96 -0
  29. package/lib/Core/3DTiles/C3DTBoundingVolume.js +156 -0
  30. package/lib/Core/3DTiles/C3DTExtensions.js +97 -0
  31. package/lib/Core/3DTiles/C3DTFeature.js +110 -0
  32. package/lib/Core/3DTiles/C3DTilesEnums.js +20 -0
  33. package/lib/Core/3DTiles/C3DTileset.js +99 -0
  34. package/lib/Core/3DTiles/utils/BinaryPropertyAccessor.js +100 -0
  35. package/lib/Core/AnimationPlayer.js +142 -0
  36. package/lib/Core/CopcNode.js +174 -0
  37. package/lib/Core/Deprecated/Undeprecator.js +74 -0
  38. package/lib/Core/EntwinePointTileNode.js +126 -0
  39. package/lib/Core/Feature.js +488 -0
  40. package/lib/Core/Geographic/GeoidGrid.js +108 -0
  41. package/lib/Core/Label.js +222 -0
  42. package/lib/Core/MainLoop.js +209 -0
  43. package/lib/Core/Picking.js +255 -0
  44. package/lib/Core/PointCloudNode.js +42 -0
  45. package/lib/Core/Potree2Node.js +206 -0
  46. package/lib/Core/Potree2PointAttributes.js +139 -0
  47. package/lib/Core/PotreeNode.js +101 -0
  48. package/lib/Core/Prefab/Globe/Atmosphere.js +293 -0
  49. package/lib/Core/Prefab/Globe/GlobeLayer.js +152 -0
  50. package/lib/Core/Prefab/Globe/GlobeTileBuilder.js +110 -0
  51. package/lib/Core/Prefab/Globe/SkyShader.js +78 -0
  52. package/lib/Core/Prefab/GlobeView.js +155 -0
  53. package/lib/Core/Prefab/Planar/PlanarLayer.js +59 -0
  54. package/lib/Core/Prefab/Planar/PlanarTileBuilder.js +71 -0
  55. package/lib/Core/Prefab/PlanarView.js +62 -0
  56. package/lib/Core/Prefab/TileBuilder.js +82 -0
  57. package/lib/Core/Prefab/computeBufferTileGeometry.js +248 -0
  58. package/lib/Core/Scheduler/Cache.js +17 -0
  59. package/lib/Core/Scheduler/CancelledCommandException.js +15 -0
  60. package/lib/Core/Scheduler/Scheduler.js +294 -0
  61. package/lib/Core/Style.js +660 -0
  62. package/lib/Core/StyleOptions.js +486 -0
  63. package/lib/Core/System/Capabilities.js +63 -0
  64. package/lib/Core/Tile/Tile.js +205 -0
  65. package/lib/Core/Tile/TileGrid.js +49 -0
  66. package/lib/Core/TileGeometry.js +124 -0
  67. package/lib/Core/TileMesh.js +108 -0
  68. package/lib/Core/View.js +1115 -0
  69. package/lib/Layer/C3DTilesLayer.js +459 -0
  70. package/lib/Layer/ColorLayer.js +154 -0
  71. package/lib/Layer/CopcLayer.js +63 -0
  72. package/lib/Layer/ElevationLayer.js +139 -0
  73. package/lib/Layer/EntwinePointTileLayer.js +71 -0
  74. package/lib/Layer/FeatureGeometryLayer.js +77 -0
  75. package/lib/Layer/GeoidLayer.js +80 -0
  76. package/lib/Layer/GeometryLayer.js +233 -0
  77. package/lib/Layer/InfoLayer.js +64 -0
  78. package/lib/Layer/LabelLayer.js +469 -0
  79. package/lib/Layer/Layer.js +335 -0
  80. package/lib/Layer/LayerUpdateState.js +89 -0
  81. package/lib/Layer/LayerUpdateStrategy.js +80 -0
  82. package/lib/Layer/OGC3DTilesLayer.js +543 -0
  83. package/lib/Layer/OrientedImageLayer.js +227 -0
  84. package/lib/Layer/PointCloudLayer.js +405 -0
  85. package/lib/Layer/Potree2Layer.js +171 -0
  86. package/lib/Layer/PotreeLayer.js +72 -0
  87. package/lib/Layer/RasterLayer.js +37 -0
  88. package/lib/Layer/ReferencingLayerProperties.js +62 -0
  89. package/lib/Layer/TiledGeometryLayer.js +459 -0
  90. package/lib/Loader/LASLoader.js +193 -0
  91. package/lib/Loader/Potree2BrotliLoader.js +261 -0
  92. package/lib/Loader/Potree2Loader.js +207 -0
  93. package/lib/Main.js +113 -0
  94. package/lib/MainBundle.js +4 -0
  95. package/lib/Parser/B3dmParser.js +174 -0
  96. package/lib/Parser/CameraCalibrationParser.js +94 -0
  97. package/lib/Parser/GDFParser.js +72 -0
  98. package/lib/Parser/GTXParser.js +75 -0
  99. package/lib/Parser/GeoJsonParser.js +212 -0
  100. package/lib/Parser/GpxParser.js +25 -0
  101. package/lib/Parser/ISGParser.js +71 -0
  102. package/lib/Parser/KMLParser.js +25 -0
  103. package/lib/Parser/LASParser.js +137 -0
  104. package/lib/Parser/MapBoxUrlParser.js +83 -0
  105. package/lib/Parser/PntsParser.js +131 -0
  106. package/lib/Parser/Potree2BinParser.js +92 -0
  107. package/lib/Parser/PotreeBinParser.js +106 -0
  108. package/lib/Parser/PotreeCinParser.js +29 -0
  109. package/lib/Parser/ShapefileParser.js +78 -0
  110. package/lib/Parser/VectorTileParser.js +215 -0
  111. package/lib/Parser/XbilParser.js +120 -0
  112. package/lib/Parser/deprecated/LegacyGLTFLoader.js +1386 -0
  113. package/lib/Parser/iGLTFLoader.js +168 -0
  114. package/lib/Process/3dTilesProcessing.js +304 -0
  115. package/lib/Process/FeatureProcessing.js +76 -0
  116. package/lib/Process/LayeredMaterialNodeProcessing.js +229 -0
  117. package/lib/Process/ObjectRemovalHelper.js +97 -0
  118. package/lib/Process/handlerNodeError.js +23 -0
  119. package/lib/Provider/3dTilesProvider.js +149 -0
  120. package/lib/Provider/DataSourceProvider.js +24 -0
  121. package/lib/Provider/Fetcher.js +233 -0
  122. package/lib/Provider/PointCloudProvider.js +45 -0
  123. package/lib/Provider/TileProvider.js +16 -0
  124. package/lib/Provider/URLBuilder.js +116 -0
  125. package/lib/Renderer/Camera.js +281 -0
  126. package/lib/Renderer/Color.js +56 -0
  127. package/lib/Renderer/ColorLayersOrdering.js +115 -0
  128. package/lib/Renderer/CommonMaterial.js +31 -0
  129. package/lib/Renderer/Label2DRenderer.js +192 -0
  130. package/lib/Renderer/LayeredMaterial.js +243 -0
  131. package/lib/Renderer/OBB.js +150 -0
  132. package/lib/Renderer/OrientedImageCamera.js +118 -0
  133. package/lib/Renderer/OrientedImageMaterial.js +167 -0
  134. package/lib/Renderer/PointsMaterial.js +485 -0
  135. package/lib/Renderer/RasterTile.js +243 -0
  136. package/lib/Renderer/RenderMode.js +31 -0
  137. package/lib/Renderer/Shader/ShaderChunk.js +160 -0
  138. package/lib/Renderer/Shader/ShaderUtils.js +47 -0
  139. package/lib/Renderer/SphereHelper.js +17 -0
  140. package/lib/Renderer/WebXR.js +51 -0
  141. package/lib/Renderer/c3DEngine.js +214 -0
  142. package/lib/Source/C3DTilesGoogleSource.js +74 -0
  143. package/lib/Source/C3DTilesIonSource.js +54 -0
  144. package/lib/Source/C3DTilesSource.js +30 -0
  145. package/lib/Source/CopcSource.js +126 -0
  146. package/lib/Source/EntwinePointTileSource.js +72 -0
  147. package/lib/Source/FileSource.js +188 -0
  148. package/lib/Source/OGC3DTilesGoogleSource.js +29 -0
  149. package/lib/Source/OGC3DTilesIonSource.js +34 -0
  150. package/lib/Source/OGC3DTilesSource.js +21 -0
  151. package/lib/Source/OrientedImageSource.js +59 -0
  152. package/lib/Source/Potree2Source.js +167 -0
  153. package/lib/Source/PotreeSource.js +82 -0
  154. package/lib/Source/Source.js +202 -0
  155. package/lib/Source/TMSSource.js +144 -0
  156. package/lib/Source/VectorTilesSource.js +182 -0
  157. package/lib/Source/WFSSource.js +170 -0
  158. package/lib/Source/WMSSource.js +167 -0
  159. package/lib/Source/WMTSSource.js +92 -0
  160. package/lib/ThreeExtended/capabilities/WebGL.js +69 -0
  161. package/lib/ThreeExtended/libs/ktx-parse.module.js +506 -0
  162. package/lib/ThreeExtended/libs/zstddec.module.js +29 -0
  163. package/lib/ThreeExtended/loaders/DDSLoader.js +200 -0
  164. package/lib/ThreeExtended/loaders/DRACOLoader.js +400 -0
  165. package/lib/ThreeExtended/loaders/GLTFLoader.js +2879 -0
  166. package/lib/ThreeExtended/loaders/KTX2Loader.js +709 -0
  167. package/lib/ThreeExtended/math/ColorSpaces.js +59 -0
  168. package/lib/ThreeExtended/utils/BufferGeometryUtils.js +846 -0
  169. package/lib/ThreeExtended/utils/WorkerPool.js +70 -0
  170. package/lib/Utils/CameraUtils.js +554 -0
  171. package/lib/Utils/DEMUtils.js +350 -0
  172. package/lib/Utils/FeaturesUtils.js +156 -0
  173. package/lib/Utils/Gradients.js +16 -0
  174. package/lib/Utils/ThreeUtils.js +115 -0
  175. package/lib/Utils/gui/C3DTilesStyle.js +218 -0
  176. package/lib/Utils/gui/Main.js +7 -0
  177. package/lib/Utils/gui/Minimap.js +152 -0
  178. package/lib/Utils/gui/Navigation.js +245 -0
  179. package/lib/Utils/gui/Scale.js +104 -0
  180. package/lib/Utils/gui/Searchbar.js +234 -0
  181. package/lib/Utils/gui/Widget.js +80 -0
  182. package/lib/Utils/placeObjectOnGround.js +136 -0
  183. package/lib/Worker/LASLoaderWorker.js +19 -0
  184. package/lib/Worker/Potree2Worker.js +21 -0
  185. package/package.json +2 -2
@@ -0,0 +1,469 @@
1
+ import * as THREE from 'three';
2
+ import LayerUpdateState from "./LayerUpdateState.js";
3
+ import ObjectRemovalHelper from "../Process/ObjectRemovalHelper.js";
4
+ import GeometryLayer from "./GeometryLayer.js";
5
+ import { Coordinates, Extent } from '@itowns/geographic';
6
+ import Label from "../Core/Label.js";
7
+ import { readExpression, StyleContext } from "../Core/Style.js";
8
+ import { ScreenGrid } from "../Renderer/Label2DRenderer.js";
9
+ const context = new StyleContext();
10
+ const coord = new Coordinates('EPSG:4326', 0, 0, 0);
11
+ const _extent = new Extent('EPSG:4326', 0, 0, 0, 0);
12
+ const nodeDimensions = new THREE.Vector2();
13
+ const westNorthNode = new THREE.Vector2();
14
+ const labelPosition = new THREE.Vector2();
15
+
16
+ /**
17
+ * DomNode is a node in the tree data structure of labels divs.
18
+ *
19
+ * @class DomNode
20
+ */
21
+ class DomNode {
22
+ #domVisibility = false;
23
+ constructor() {
24
+ this.dom = document.createElement('div');
25
+ this.dom.style.display = 'none';
26
+ this.visible = true;
27
+ }
28
+ get visible() {
29
+ return this.#domVisibility;
30
+ }
31
+ set visible(v) {
32
+ if (v !== this.#domVisibility) {
33
+ this.#domVisibility = v;
34
+ this.dom.style.display = v ? 'block' : 'none';
35
+ }
36
+ }
37
+ hide() {
38
+ this.visible = false;
39
+ }
40
+ show() {
41
+ this.visible = true;
42
+ }
43
+ add(node) {
44
+ this.dom.append(node.dom);
45
+ }
46
+ }
47
+
48
+ /**
49
+ * LabelsNode is node of tree data structure for LabelLayer.
50
+ * the node is made of dom elements and 3D labels.
51
+ *
52
+ * @class LabelsNode
53
+ */
54
+ class LabelsNode extends THREE.Group {
55
+ constructor(node) {
56
+ super();
57
+ // attached node parent
58
+ this.nodeParent = node;
59
+ // When this is set, it calculates the position in that frame and resets this property to false.
60
+ this.needsUpdate = true;
61
+ }
62
+
63
+ // instanciate dom elements
64
+ initializeDom() {
65
+ // create root dom
66
+ this.domElements = new DomNode();
67
+ // create labels container dom
68
+ this.domElements.labels = new DomNode();
69
+ this.domElements.add(this.domElements.labels);
70
+ this.domElements.labels.dom.style.opacity = '0';
71
+ }
72
+
73
+ // add node label
74
+ // add label 3d and dom label
75
+ addLabel(label) {
76
+ // add 3d object
77
+ this.add(label);
78
+
79
+ // add dom label
80
+ this.domElements.labels.dom.append(label.content);
81
+
82
+ // Batch update the dimensions of labels all at once to avoid
83
+ // redraw for at least this tile.
84
+ label.initDimensions();
85
+
86
+ // add horizon culling point if it's necessary
87
+ // the horizon culling is applied to nodes that trace the horizon which
88
+ // corresponds to the low zoom node, that's why the culling is done for a zoom lower than 4.
89
+ if (this.nodeParent.layer.isGlobeLayer && this.nodeParent.level < 4) {
90
+ label.horizonCullingPoint = new THREE.Vector3();
91
+ }
92
+ }
93
+
94
+ // remove node label
95
+ // remove label 3d and dom label
96
+ removeLabel(label) {
97
+ // remove 3d object
98
+ this.remove(label);
99
+
100
+ // remove dom label
101
+ this.domElements.labels.dom.removeChild(label.content);
102
+ }
103
+
104
+ // update position if it's necessary
105
+ updatePosition(label) {
106
+ if (this.needsUpdate) {
107
+ // update elevation from elevation layer.
108
+ if (this.needsAltitude) {
109
+ label.updateElevationFromLayer(this.nodeParent.layer, [this.nodeParent]);
110
+ }
111
+
112
+ // update elevation label
113
+ label.update3dPosition(this.nodeParent.layer.crs);
114
+
115
+ // update horizon culling
116
+ label.updateHorizonCullingPoint();
117
+ }
118
+ }
119
+
120
+ // return labels count
121
+ count() {
122
+ return this.children.length;
123
+ }
124
+ get labels() {
125
+ return this.children;
126
+ }
127
+ }
128
+
129
+ /**
130
+ * A layer to handle a bunch of `Label`. This layer can be created on its own,
131
+ * but it is better to use the option `addLabelLayer` on another `Layer` to let
132
+ * it work with it (see the `vector_tile_raster_2d` example). Supported for Points features, not yet
133
+ * for Lines and Polygons features.
134
+ *
135
+ * @property {boolean} isLabelLayer - Used to checkout whether this layer is a
136
+ * LabelLayer. Default is true. You should not change this, as it is used
137
+ * internally for optimisation.
138
+ */
139
+ class LabelLayer extends GeometryLayer {
140
+ #filterGrid = (() => new ScreenGrid())();
141
+ /**
142
+ * @extends Layer
143
+ *
144
+ * @param {string} id - The id of the layer, that should be unique. It is
145
+ * not mandatory, but an error will be emitted if this layer is added a
146
+ * {@link View} that already has a layer going by that id.
147
+ * @param {Object} [config] - Optional configuration, all elements in it
148
+ * will be merged as is in the layer. For example, if the configuration
149
+ * contains three elements `name, protocol, extent`, these elements will be
150
+ * available using `layer.name` or something else depending on the property
151
+ * name.
152
+ * @param {boolean} [config.performance=true] - remove labels that have no chance of being visible.
153
+ * if the `config.performance` is set to true then the performance is improved
154
+ * proportional to the amount of unnecessary labels that are removed.
155
+ * Indeed, even in the best case, labels will never be displayed. By example, if there's many labels.
156
+ * We advise you to not use this option if your data is optimized.
157
+ * @param {domElement|function} config.domElement - An HTML domElement.
158
+ * If set, all `Label` displayed within the current instance `LabelLayer`
159
+ * will be this domElement.
160
+ *
161
+ * It can be set to a method. The single parameter of this method gives the
162
+ * properties of each feature on which a `Label` is created.
163
+ *
164
+ * If set, all the parameters set in the `LabelLayer` `Style.text` will be overridden,
165
+ * except for the `Style.text.anchor` parameter which can help place the label.
166
+ */
167
+ constructor(id) {
168
+ let config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
169
+ const {
170
+ domElement,
171
+ performance = true,
172
+ forceClampToTerrain = false,
173
+ margin,
174
+ ...geometryConfig
175
+ } = config;
176
+ super(id, config.object3d || new THREE.Group(), geometryConfig);
177
+ this.isLabelLayer = true;
178
+ this.domElement = new DomNode();
179
+ this.domElement.show();
180
+ this.domElement.dom.id = `itowns-label-${this.id}`;
181
+ this.buildExtent = true;
182
+ this.crs = config.source.crs;
183
+ this.performance = performance;
184
+ this.forceClampToTerrain = forceClampToTerrain;
185
+ this.margin = margin;
186
+ this.toHide = new THREE.Group();
187
+ this.labelDomelement = domElement;
188
+
189
+ // The margin property defines a space around each label that cannot be occupied by another label.
190
+ // For example, if some labelLayer has a margin value of 5, there will be at least 10 pixels
191
+ // between each labels of the layer
192
+ // TODO : this property should be moved to Style after refactoring style properties structure
193
+ this.margin = config.margin;
194
+ }
195
+ get visible() {
196
+ return super.visible;
197
+ }
198
+ set visible(value) {
199
+ super.visible = value;
200
+ if (value) {
201
+ this.domElement?.show();
202
+ } else {
203
+ this.domElement?.hide();
204
+ }
205
+ }
206
+ get submittedLabelNodes() {
207
+ return this.object3d.children;
208
+ }
209
+
210
+ /**
211
+ * Reads each {@link FeatureGeometry} that contains label configuration, and
212
+ * creates the corresponding {@link Label}. To create a `Label`, a geometry
213
+ * needs to have a `label` object with at least a few properties:
214
+ * - `content`, which refers to `Label#content`
215
+ * - `position`, which refers to `Label#position`
216
+ * - (optional) `config`, containing miscellaneous configuration for the
217
+ * label
218
+ *
219
+ * The geometry (or its parent Feature) needs to have a Style set.
220
+ *
221
+ * @param {FeatureCollection} data - The FeatureCollection to read the
222
+ * labels from.
223
+ * @param {Extent|Tile} extentOrTile
224
+ *
225
+ * @return {Label[]} An array containing all the created labels.
226
+ */
227
+ convert(data, extentOrTile) {
228
+ const labels = [];
229
+
230
+ // Converting the extent now is faster for further operation
231
+ if (extentOrTile.isExtent) {
232
+ extentOrTile.as(data.crs, _extent);
233
+ } else {
234
+ extentOrTile.toExtent(data.crs, _extent);
235
+ }
236
+ coord.crs = data.crs;
237
+ context.setZoom(extentOrTile.zoom);
238
+ data.features.forEach(f => {
239
+ if (f.style.text) {
240
+ if (Object.keys(f.style.text).length === 0) {
241
+ return;
242
+ }
243
+ }
244
+ context.setFeature(f);
245
+ const featureField = f.style?.text?.field;
246
+
247
+ // determine if altitude style is specified by the user
248
+ const altitudeStyle = f.style?.point?.base_altitude;
249
+ const isDefaultElevationStyle = altitudeStyle instanceof Function && altitudeStyle.name == 'baseAltitudeDefault';
250
+
251
+ // determine if the altitude needs update with ElevationLayer
252
+ labels.needsAltitude = labels.needsAltitude || this.forceClampToTerrain === true || isDefaultElevationStyle && !f.hasRawElevationData;
253
+ f.geometries.forEach(g => {
254
+ context.setGeometry(g);
255
+ this.style.setContext(context);
256
+ const layerField = this.style.text && this.style.text.field;
257
+ const geometryField = g.properties.style && g.properties.style.text && g.properties.style.text.field;
258
+ let content;
259
+ if (this.labelDomelement) {
260
+ content = readExpression(this.labelDomelement, context);
261
+ } else if (!geometryField && !featureField && !layerField) {
262
+ // Check if there is an icon, with no text
263
+ if (!(g.properties.style && (g.properties.style.icon.source || g.properties.style.icon.key)) && !(f.style && f.style.icon && (f.style.icon.source || f.style.icon.key)) && !(this.style.icon && (this.style.icon.source || this.style.icon.key))) {
264
+ return;
265
+ }
266
+ }
267
+ if (this.style.zoom.min > this.style.context.zoom || this.style.zoom.max <= this.style.context.zoom) {
268
+ return;
269
+ }
270
+
271
+ // NOTE: this only works fine for POINT.
272
+ // It needs more work for LINE and POLYGON as we currently only use the first point of the entity
273
+
274
+ g.indices.forEach(i => {
275
+ coord.setFromArray(f.vertices, g.size * i.offset);
276
+ // Transform coordinate to data.crs projection
277
+ coord.applyMatrix4(data.matrixWorld);
278
+ if (!_extent.isPointInside(coord)) {
279
+ return;
280
+ }
281
+ const label = new Label(content, coord.clone(), this.style);
282
+ label.layerId = this.id;
283
+ label.order = f.order;
284
+ label.padding = this.margin || label.padding;
285
+ labels.push(label);
286
+ });
287
+ });
288
+ });
289
+ return labels;
290
+ }
291
+
292
+ // placeholder
293
+ preUpdate(context, sources) {
294
+ if (sources.has(this.parent)) {
295
+ this.object3d.clear();
296
+ this.#filterGrid.width = this.parent.maxScreenSizeNode * 0.5;
297
+ this.#filterGrid.height = this.parent.maxScreenSizeNode * 0.5;
298
+ this.#filterGrid.resize();
299
+ }
300
+ }
301
+ #submitToRendering(labelsNode) {
302
+ this.object3d.add(labelsNode);
303
+ }
304
+ #disallowToRendering(labelsNode) {
305
+ this.toHide.add(labelsNode);
306
+ }
307
+ #findClosestDomElement(node) {
308
+ if (node.parent?.isTileMesh) {
309
+ return node.parent.link[this.id]?.domElements || this.#findClosestDomElement(node.parent);
310
+ } else {
311
+ return this.domElement;
312
+ }
313
+ }
314
+ #hasLabelChildren(object) {
315
+ return object.children.every(c => c.layerUpdateState && c.layerUpdateState[this.id]?.hasFinished());
316
+ }
317
+
318
+ // Remove all labels invisible with pre-culling with screen grid
319
+ // We use the screen grid with maximum size of node on screen
320
+ #removeCulledLabels(node) {
321
+ // copy labels array
322
+ const labels = node.children.slice();
323
+
324
+ // reset filter
325
+ this.#filterGrid.reset();
326
+
327
+ // sort labels by order
328
+ labels.sort((a, b) => b.order - a.order);
329
+ labels.forEach(label => {
330
+ // get node dimensions
331
+ node.nodeParent.extent.planarDimensions(nodeDimensions);
332
+ coord.crs = node.nodeParent.extent.crs;
333
+
334
+ // get west/north node coordinates
335
+ coord.setFromValues(node.nodeParent.extent.west, node.nodeParent.extent.north, 0).toVector3(westNorthNode);
336
+
337
+ // get label position
338
+ coord.copy(label.coordinates).as(node.nodeParent.extent.crs, coord).toVector3(labelPosition);
339
+
340
+ // transform label position to local node system
341
+ labelPosition.sub(westNorthNode);
342
+ labelPosition.y += nodeDimensions.y;
343
+ labelPosition.divide(nodeDimensions).multiplyScalar(this.#filterGrid.width);
344
+
345
+ // update the projected position to transform to local filter grid sytem
346
+ label.updateProjectedPosition(labelPosition.x, labelPosition.y);
347
+
348
+ // use screen grid to remove all culled labels
349
+ if (!this.#filterGrid.insert(label)) {
350
+ node.removeLabel(label);
351
+ }
352
+ });
353
+ }
354
+ update(context, layer, node, parent) {
355
+ if (!parent && node.link[layer.id]) {
356
+ // if node has been removed dispose three.js resource
357
+ ObjectRemovalHelper.removeChildrenAndCleanupRecursively(this, node);
358
+ return;
359
+ }
360
+ const labelsNode = node.link[layer.id] || new LabelsNode(node);
361
+ node.link[layer.id] = labelsNode;
362
+ if (this.frozen || !node.visible || !this.visible) {
363
+ return;
364
+ }
365
+ if (!node.material.visible && this.#hasLabelChildren(node)) {
366
+ return this.#disallowToRendering(labelsNode);
367
+ }
368
+ const extentsDestination = node.getExtentsByProjection(this.source.crs) || [node.extent];
369
+ const zoomDest = extentsDestination[0].zoom;
370
+ if (zoomDest < layer.zoom.min || zoomDest > layer.zoom.max) {
371
+ return this.#disallowToRendering(labelsNode);
372
+ }
373
+ if (node.layerUpdateState[this.id] === undefined) {
374
+ node.layerUpdateState[this.id] = new LayerUpdateState();
375
+ }
376
+ if (!this.source.extentInsideLimit(node.extent, zoomDest)) {
377
+ node.layerUpdateState[this.id].noMoreUpdatePossible();
378
+ return;
379
+ } else if (this.#hasLabelChildren(node.parent)) {
380
+ if (!node.material.visible) {
381
+ labelsNode.needsUpdate = true;
382
+ }
383
+ this.#submitToRendering(labelsNode);
384
+ return;
385
+ } else if (!node.layerUpdateState[this.id].canTryUpdate()) {
386
+ return;
387
+ }
388
+ node.layerUpdateState[this.id].newTry();
389
+ const command = {
390
+ layer: this,
391
+ extentsSource: extentsDestination,
392
+ view: context.view,
393
+ requester: node
394
+ };
395
+ return context.scheduler.execute(command).then(result => {
396
+ if (!result) {
397
+ return;
398
+ }
399
+ const renderer = context.view.mainLoop.gfxEngine.label2dRenderer;
400
+ labelsNode.initializeDom();
401
+ this.#findClosestDomElement(node).add(labelsNode.domElements);
402
+ result.forEach(labels => {
403
+ // Clean if there isnt' parent
404
+ if (!node.parent) {
405
+ labels.forEach(l => {
406
+ ObjectRemovalHelper.removeChildrenAndCleanupRecursively(this, l);
407
+ renderer.removeLabelDOM(l);
408
+ });
409
+ return;
410
+ }
411
+ labelsNode.needsAltitude = labelsNode.needsAltitude || labels.needsAltitude;
412
+
413
+ // Add all labels for this tile at once to batch it
414
+ labels.forEach(label => {
415
+ if (node.extent.isPointInside(label.coordinates)) {
416
+ labelsNode.addLabel(label);
417
+ }
418
+ });
419
+ });
420
+ if (labelsNode.count()) {
421
+ labelsNode.domElements.labels.hide();
422
+ labelsNode.domElements.labels.dom.style.opacity = '1.0';
423
+ node.addEventListener('show', () => labelsNode.domElements.labels.show());
424
+ node.addEventListener('hidden', () => this.#disallowToRendering(labelsNode));
425
+
426
+ // Necessary event listener, to remove any Label attached to
427
+ node.addEventListener('removed', () => this.removeNodeDomElement(node));
428
+ if (labelsNode.needsAltitude && node.material.getElevationLayer()) {
429
+ node.material.getElevationLayer().addEventListener('rasterElevationLevelChanged', () => {
430
+ labelsNode.needsUpdate = true;
431
+ });
432
+ }
433
+ if (this.performance) {
434
+ this.#removeCulledLabels(labelsNode);
435
+ }
436
+ }
437
+ node.layerUpdateState[this.id].noMoreUpdatePossible();
438
+ });
439
+ }
440
+ removeLabelsFromNodeRecursive(node) {
441
+ node.children.forEach(c => {
442
+ if (c.link[this.id]) {
443
+ delete c.link[this.id];
444
+ }
445
+ this.removeLabelsFromNodeRecursive(c);
446
+ });
447
+ this.removeNodeDomElement(node);
448
+ }
449
+ removeNodeDomElement(node) {
450
+ if (node.link[this.id]?.domElements) {
451
+ const child = node.link[this.id].domElements.dom;
452
+ child.parentElement.removeChild(child);
453
+ delete node.link[this.id].domElements;
454
+ }
455
+ }
456
+
457
+ /**
458
+ * All layer's objects and domElements are removed.
459
+ * @param {boolean} [clearCache=false] Whether to clear the layer cache or not
460
+ */
461
+ delete(clearCache) {
462
+ if (clearCache) {
463
+ this.cache.clear();
464
+ }
465
+ this.domElement.dom.parentElement.removeChild(this.domElement.dom);
466
+ this.parent.level0Nodes.forEach(obj => this.removeLabelsFromNodeRecursive(obj));
467
+ }
468
+ }
469
+ export default LabelLayer;