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.
- package/dist/455.js +2 -0
- package/dist/455.js.map +1 -0
- package/dist/debug.js +3 -0
- package/dist/debug.js.LICENSE.txt +13 -0
- package/dist/debug.js.map +1 -0
- package/dist/itowns.js +3 -0
- package/dist/itowns.js.LICENSE.txt +5 -0
- package/dist/itowns.js.map +1 -0
- package/dist/itowns_lasparser.js +2 -0
- package/dist/itowns_lasparser.js.map +1 -0
- package/dist/itowns_lasworker.js +2 -0
- package/dist/itowns_lasworker.js.map +1 -0
- package/dist/itowns_potree2worker.js +2 -0
- package/dist/itowns_potree2worker.js.map +1 -0
- package/dist/itowns_widgets.js +2 -0
- package/dist/itowns_widgets.js.map +1 -0
- package/lib/Controls/FirstPersonControls.js +308 -0
- package/lib/Controls/FlyControls.js +175 -0
- package/lib/Controls/GlobeControls.js +1178 -0
- package/lib/Controls/PlanarControls.js +1025 -0
- package/lib/Controls/StateControl.js +432 -0
- package/lib/Controls/StreetControls.js +392 -0
- package/lib/Converter/Feature2Mesh.js +612 -0
- package/lib/Converter/Feature2Texture.js +174 -0
- package/lib/Converter/convertToTile.js +70 -0
- package/lib/Converter/textureConverter.js +43 -0
- package/lib/Core/3DTiles/C3DTBatchTable.js +131 -0
- package/lib/Core/3DTiles/C3DTBatchTableHierarchyExtension.js +96 -0
- package/lib/Core/3DTiles/C3DTBoundingVolume.js +156 -0
- package/lib/Core/3DTiles/C3DTExtensions.js +97 -0
- package/lib/Core/3DTiles/C3DTFeature.js +110 -0
- package/lib/Core/3DTiles/C3DTilesEnums.js +20 -0
- package/lib/Core/3DTiles/C3DTileset.js +99 -0
- package/lib/Core/3DTiles/utils/BinaryPropertyAccessor.js +100 -0
- package/lib/Core/AnimationPlayer.js +142 -0
- package/lib/Core/CopcNode.js +174 -0
- package/lib/Core/Deprecated/Undeprecator.js +74 -0
- package/lib/Core/EntwinePointTileNode.js +126 -0
- package/lib/Core/Feature.js +488 -0
- package/lib/Core/Geographic/GeoidGrid.js +108 -0
- package/lib/Core/Label.js +222 -0
- package/lib/Core/MainLoop.js +209 -0
- package/lib/Core/Picking.js +255 -0
- package/lib/Core/PointCloudNode.js +42 -0
- package/lib/Core/Potree2Node.js +206 -0
- package/lib/Core/Potree2PointAttributes.js +139 -0
- package/lib/Core/PotreeNode.js +101 -0
- package/lib/Core/Prefab/Globe/Atmosphere.js +293 -0
- package/lib/Core/Prefab/Globe/GlobeLayer.js +152 -0
- package/lib/Core/Prefab/Globe/GlobeTileBuilder.js +110 -0
- package/lib/Core/Prefab/Globe/SkyShader.js +78 -0
- package/lib/Core/Prefab/GlobeView.js +155 -0
- package/lib/Core/Prefab/Planar/PlanarLayer.js +59 -0
- package/lib/Core/Prefab/Planar/PlanarTileBuilder.js +71 -0
- package/lib/Core/Prefab/PlanarView.js +62 -0
- package/lib/Core/Prefab/TileBuilder.js +82 -0
- package/lib/Core/Prefab/computeBufferTileGeometry.js +248 -0
- package/lib/Core/Scheduler/Cache.js +17 -0
- package/lib/Core/Scheduler/CancelledCommandException.js +15 -0
- package/lib/Core/Scheduler/Scheduler.js +294 -0
- package/lib/Core/Style.js +660 -0
- package/lib/Core/StyleOptions.js +486 -0
- package/lib/Core/System/Capabilities.js +63 -0
- package/lib/Core/Tile/Tile.js +205 -0
- package/lib/Core/Tile/TileGrid.js +49 -0
- package/lib/Core/TileGeometry.js +124 -0
- package/lib/Core/TileMesh.js +108 -0
- package/lib/Core/View.js +1115 -0
- package/lib/Layer/C3DTilesLayer.js +459 -0
- package/lib/Layer/ColorLayer.js +154 -0
- package/lib/Layer/CopcLayer.js +63 -0
- package/lib/Layer/ElevationLayer.js +139 -0
- package/lib/Layer/EntwinePointTileLayer.js +71 -0
- package/lib/Layer/FeatureGeometryLayer.js +77 -0
- package/lib/Layer/GeoidLayer.js +80 -0
- package/lib/Layer/GeometryLayer.js +233 -0
- package/lib/Layer/InfoLayer.js +64 -0
- package/lib/Layer/LabelLayer.js +469 -0
- package/lib/Layer/Layer.js +335 -0
- package/lib/Layer/LayerUpdateState.js +89 -0
- package/lib/Layer/LayerUpdateStrategy.js +80 -0
- package/lib/Layer/OGC3DTilesLayer.js +543 -0
- package/lib/Layer/OrientedImageLayer.js +227 -0
- package/lib/Layer/PointCloudLayer.js +405 -0
- package/lib/Layer/Potree2Layer.js +171 -0
- package/lib/Layer/PotreeLayer.js +72 -0
- package/lib/Layer/RasterLayer.js +37 -0
- package/lib/Layer/ReferencingLayerProperties.js +62 -0
- package/lib/Layer/TiledGeometryLayer.js +459 -0
- package/lib/Loader/LASLoader.js +193 -0
- package/lib/Loader/Potree2BrotliLoader.js +261 -0
- package/lib/Loader/Potree2Loader.js +207 -0
- package/lib/Main.js +113 -0
- package/lib/MainBundle.js +4 -0
- package/lib/Parser/B3dmParser.js +174 -0
- package/lib/Parser/CameraCalibrationParser.js +94 -0
- package/lib/Parser/GDFParser.js +72 -0
- package/lib/Parser/GTXParser.js +75 -0
- package/lib/Parser/GeoJsonParser.js +212 -0
- package/lib/Parser/GpxParser.js +25 -0
- package/lib/Parser/ISGParser.js +71 -0
- package/lib/Parser/KMLParser.js +25 -0
- package/lib/Parser/LASParser.js +137 -0
- package/lib/Parser/MapBoxUrlParser.js +83 -0
- package/lib/Parser/PntsParser.js +131 -0
- package/lib/Parser/Potree2BinParser.js +92 -0
- package/lib/Parser/PotreeBinParser.js +106 -0
- package/lib/Parser/PotreeCinParser.js +29 -0
- package/lib/Parser/ShapefileParser.js +78 -0
- package/lib/Parser/VectorTileParser.js +215 -0
- package/lib/Parser/XbilParser.js +120 -0
- package/lib/Parser/deprecated/LegacyGLTFLoader.js +1386 -0
- package/lib/Parser/iGLTFLoader.js +168 -0
- package/lib/Process/3dTilesProcessing.js +304 -0
- package/lib/Process/FeatureProcessing.js +76 -0
- package/lib/Process/LayeredMaterialNodeProcessing.js +229 -0
- package/lib/Process/ObjectRemovalHelper.js +97 -0
- package/lib/Process/handlerNodeError.js +23 -0
- package/lib/Provider/3dTilesProvider.js +149 -0
- package/lib/Provider/DataSourceProvider.js +24 -0
- package/lib/Provider/Fetcher.js +233 -0
- package/lib/Provider/PointCloudProvider.js +45 -0
- package/lib/Provider/TileProvider.js +16 -0
- package/lib/Provider/URLBuilder.js +116 -0
- package/lib/Renderer/Camera.js +281 -0
- package/lib/Renderer/Color.js +56 -0
- package/lib/Renderer/ColorLayersOrdering.js +115 -0
- package/lib/Renderer/CommonMaterial.js +31 -0
- package/lib/Renderer/Label2DRenderer.js +192 -0
- package/lib/Renderer/LayeredMaterial.js +243 -0
- package/lib/Renderer/OBB.js +150 -0
- package/lib/Renderer/OrientedImageCamera.js +118 -0
- package/lib/Renderer/OrientedImageMaterial.js +167 -0
- package/lib/Renderer/PointsMaterial.js +485 -0
- package/lib/Renderer/RasterTile.js +243 -0
- package/lib/Renderer/RenderMode.js +31 -0
- package/lib/Renderer/Shader/ShaderChunk.js +160 -0
- package/lib/Renderer/Shader/ShaderUtils.js +47 -0
- package/lib/Renderer/SphereHelper.js +17 -0
- package/lib/Renderer/WebXR.js +51 -0
- package/lib/Renderer/c3DEngine.js +214 -0
- package/lib/Source/C3DTilesGoogleSource.js +74 -0
- package/lib/Source/C3DTilesIonSource.js +54 -0
- package/lib/Source/C3DTilesSource.js +30 -0
- package/lib/Source/CopcSource.js +126 -0
- package/lib/Source/EntwinePointTileSource.js +72 -0
- package/lib/Source/FileSource.js +188 -0
- package/lib/Source/OGC3DTilesGoogleSource.js +29 -0
- package/lib/Source/OGC3DTilesIonSource.js +34 -0
- package/lib/Source/OGC3DTilesSource.js +21 -0
- package/lib/Source/OrientedImageSource.js +59 -0
- package/lib/Source/Potree2Source.js +167 -0
- package/lib/Source/PotreeSource.js +82 -0
- package/lib/Source/Source.js +202 -0
- package/lib/Source/TMSSource.js +144 -0
- package/lib/Source/VectorTilesSource.js +182 -0
- package/lib/Source/WFSSource.js +170 -0
- package/lib/Source/WMSSource.js +167 -0
- package/lib/Source/WMTSSource.js +92 -0
- package/lib/ThreeExtended/capabilities/WebGL.js +69 -0
- package/lib/ThreeExtended/libs/ktx-parse.module.js +506 -0
- package/lib/ThreeExtended/libs/zstddec.module.js +29 -0
- package/lib/ThreeExtended/loaders/DDSLoader.js +200 -0
- package/lib/ThreeExtended/loaders/DRACOLoader.js +400 -0
- package/lib/ThreeExtended/loaders/GLTFLoader.js +2879 -0
- package/lib/ThreeExtended/loaders/KTX2Loader.js +709 -0
- package/lib/ThreeExtended/math/ColorSpaces.js +59 -0
- package/lib/ThreeExtended/utils/BufferGeometryUtils.js +846 -0
- package/lib/ThreeExtended/utils/WorkerPool.js +70 -0
- package/lib/Utils/CameraUtils.js +554 -0
- package/lib/Utils/DEMUtils.js +350 -0
- package/lib/Utils/FeaturesUtils.js +156 -0
- package/lib/Utils/Gradients.js +16 -0
- package/lib/Utils/ThreeUtils.js +115 -0
- package/lib/Utils/gui/C3DTilesStyle.js +218 -0
- package/lib/Utils/gui/Main.js +7 -0
- package/lib/Utils/gui/Minimap.js +152 -0
- package/lib/Utils/gui/Navigation.js +245 -0
- package/lib/Utils/gui/Scale.js +104 -0
- package/lib/Utils/gui/Searchbar.js +234 -0
- package/lib/Utils/gui/Widget.js +80 -0
- package/lib/Utils/placeObjectOnGround.js +136 -0
- package/lib/Worker/LASLoaderWorker.js +19 -0
- package/lib/Worker/Potree2Worker.js +21 -0
- 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;
|