@vcmap/core 5.0.0-rc.0

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 (146) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +44 -0
  3. package/build/postinstall.js +44 -0
  4. package/index.js +139 -0
  5. package/package.json +92 -0
  6. package/src/cesium/cesium3DTileFeature.js +9 -0
  7. package/src/cesium/cesium3DTilePointFeature.js +9 -0
  8. package/src/cesium/cesiumVcsCameraPrimitive.js +146 -0
  9. package/src/cesium/wallpaperMaterial.js +64 -0
  10. package/src/ol/feature.js +47 -0
  11. package/src/ol/geom/circle.js +24 -0
  12. package/src/ol/geom/geometryCollection.js +33 -0
  13. package/src/ol/render/canvas/canvasTileRenderer.js +179 -0
  14. package/src/ol/source/ClusterEnhancedVectorSource.js +39 -0
  15. package/src/ol/source/VcsCluster.js +37 -0
  16. package/src/vcs/vcm/classRegistry.js +106 -0
  17. package/src/vcs/vcm/event/vcsEvent.js +89 -0
  18. package/src/vcs/vcm/globalCollections.js +11 -0
  19. package/src/vcs/vcm/interaction/abstractInteraction.js +149 -0
  20. package/src/vcs/vcm/interaction/coordinateAtPixel.js +102 -0
  21. package/src/vcs/vcm/interaction/eventHandler.js +425 -0
  22. package/src/vcs/vcm/interaction/featureAtPixelInteraction.js +286 -0
  23. package/src/vcs/vcm/interaction/featureProviderInteraction.js +54 -0
  24. package/src/vcs/vcm/interaction/interactionChain.js +124 -0
  25. package/src/vcs/vcm/interaction/interactionType.js +114 -0
  26. package/src/vcs/vcm/layer/buildings.js +17 -0
  27. package/src/vcs/vcm/layer/cesium/cesiumTilesetCesium.js +359 -0
  28. package/src/vcs/vcm/layer/cesium/clusterContext.js +95 -0
  29. package/src/vcs/vcm/layer/cesium/dataSourceCesium.js +171 -0
  30. package/src/vcs/vcm/layer/cesium/openStreetMapCesium.js +29 -0
  31. package/src/vcs/vcm/layer/cesium/pointCloudCesium.js +58 -0
  32. package/src/vcs/vcm/layer/cesium/rasterLayerCesium.js +110 -0
  33. package/src/vcs/vcm/layer/cesium/singleImageCesium.js +49 -0
  34. package/src/vcs/vcm/layer/cesium/terrainCesium.js +80 -0
  35. package/src/vcs/vcm/layer/cesium/tmsCesium.js +54 -0
  36. package/src/vcs/vcm/layer/cesium/vectorCesium.js +255 -0
  37. package/src/vcs/vcm/layer/cesium/vectorContext.js +167 -0
  38. package/src/vcs/vcm/layer/cesium/vectorRasterTileCesium.js +116 -0
  39. package/src/vcs/vcm/layer/cesium/vectorTileImageryProvider.js +246 -0
  40. package/src/vcs/vcm/layer/cesium/wmsCesium.js +71 -0
  41. package/src/vcs/vcm/layer/cesium/wmtsCesium.js +101 -0
  42. package/src/vcs/vcm/layer/cesium/x3dmHelper.js +22 -0
  43. package/src/vcs/vcm/layer/cesiumTileset.js +376 -0
  44. package/src/vcs/vcm/layer/czml.js +141 -0
  45. package/src/vcs/vcm/layer/dataSource.js +259 -0
  46. package/src/vcs/vcm/layer/featureLayer.js +261 -0
  47. package/src/vcs/vcm/layer/featureStore.js +647 -0
  48. package/src/vcs/vcm/layer/featureStoreChanges.js +360 -0
  49. package/src/vcs/vcm/layer/featureStoreState.js +19 -0
  50. package/src/vcs/vcm/layer/featureVisibility.js +435 -0
  51. package/src/vcs/vcm/layer/geojson.js +185 -0
  52. package/src/vcs/vcm/layer/geojsonHelpers.js +450 -0
  53. package/src/vcs/vcm/layer/globalHider.js +157 -0
  54. package/src/vcs/vcm/layer/layer.js +752 -0
  55. package/src/vcs/vcm/layer/layerImplementation.js +102 -0
  56. package/src/vcs/vcm/layer/layerState.js +17 -0
  57. package/src/vcs/vcm/layer/layerSymbols.js +6 -0
  58. package/src/vcs/vcm/layer/oblique/layerOblique.js +76 -0
  59. package/src/vcs/vcm/layer/oblique/obliqueHelpers.js +175 -0
  60. package/src/vcs/vcm/layer/oblique/vectorOblique.js +469 -0
  61. package/src/vcs/vcm/layer/openStreetMap.js +194 -0
  62. package/src/vcs/vcm/layer/openlayers/layerOpenlayers.js +79 -0
  63. package/src/vcs/vcm/layer/openlayers/openStreetMapOpenlayers.js +27 -0
  64. package/src/vcs/vcm/layer/openlayers/rasterLayerOpenlayers.js +121 -0
  65. package/src/vcs/vcm/layer/openlayers/singleImageOpenlayers.js +49 -0
  66. package/src/vcs/vcm/layer/openlayers/tileDebugOpenlayers.js +39 -0
  67. package/src/vcs/vcm/layer/openlayers/tmsOpenlayers.js +62 -0
  68. package/src/vcs/vcm/layer/openlayers/vectorOpenlayers.js +118 -0
  69. package/src/vcs/vcm/layer/openlayers/vectorTileOpenlayers.js +177 -0
  70. package/src/vcs/vcm/layer/openlayers/wmsOpenlayers.js +55 -0
  71. package/src/vcs/vcm/layer/openlayers/wmtsOpenlayers.js +141 -0
  72. package/src/vcs/vcm/layer/pointCloud.js +162 -0
  73. package/src/vcs/vcm/layer/rasterLayer.js +294 -0
  74. package/src/vcs/vcm/layer/singleImage.js +119 -0
  75. package/src/vcs/vcm/layer/terrain.js +122 -0
  76. package/src/vcs/vcm/layer/terrainHelpers.js +123 -0
  77. package/src/vcs/vcm/layer/tileLoadedHelper.js +72 -0
  78. package/src/vcs/vcm/layer/tileProvider/mvtTileProvider.js +104 -0
  79. package/src/vcs/vcm/layer/tileProvider/staticGeojsonTileProvider.js +67 -0
  80. package/src/vcs/vcm/layer/tileProvider/tileProvider.js +584 -0
  81. package/src/vcs/vcm/layer/tileProvider/tileProviderFactory.js +28 -0
  82. package/src/vcs/vcm/layer/tileProvider/urlTemplateTileProvider.js +106 -0
  83. package/src/vcs/vcm/layer/tms.js +121 -0
  84. package/src/vcs/vcm/layer/vector.js +632 -0
  85. package/src/vcs/vcm/layer/vectorHelpers.js +206 -0
  86. package/src/vcs/vcm/layer/vectorProperties.js +1391 -0
  87. package/src/vcs/vcm/layer/vectorSymbols.js +40 -0
  88. package/src/vcs/vcm/layer/vectorTile.js +480 -0
  89. package/src/vcs/vcm/layer/wfs.js +165 -0
  90. package/src/vcs/vcm/layer/wms.js +270 -0
  91. package/src/vcs/vcm/layer/wmsHelpers.js +65 -0
  92. package/src/vcs/vcm/layer/wmts.js +235 -0
  93. package/src/vcs/vcm/maps/baseOLMap.js +257 -0
  94. package/src/vcs/vcm/maps/cameraLimiter.js +219 -0
  95. package/src/vcs/vcm/maps/cesium.js +1192 -0
  96. package/src/vcs/vcm/maps/map.js +511 -0
  97. package/src/vcs/vcm/maps/mapState.js +17 -0
  98. package/src/vcs/vcm/maps/oblique.js +536 -0
  99. package/src/vcs/vcm/maps/openlayers.js +205 -0
  100. package/src/vcs/vcm/object.js +92 -0
  101. package/src/vcs/vcm/oblique/ObliqueCollection.js +572 -0
  102. package/src/vcs/vcm/oblique/ObliqueDataSet.js +357 -0
  103. package/src/vcs/vcm/oblique/ObliqueImage.js +247 -0
  104. package/src/vcs/vcm/oblique/ObliqueImageMeta.js +126 -0
  105. package/src/vcs/vcm/oblique/ObliqueProvider.js +433 -0
  106. package/src/vcs/vcm/oblique/ObliqueView.js +130 -0
  107. package/src/vcs/vcm/oblique/ObliqueViewDirection.js +40 -0
  108. package/src/vcs/vcm/oblique/helpers.js +483 -0
  109. package/src/vcs/vcm/oblique/parseImageJson.js +248 -0
  110. package/src/vcs/vcm/util/clipping/clippingObject.js +386 -0
  111. package/src/vcs/vcm/util/clipping/clippingObjectManager.js +312 -0
  112. package/src/vcs/vcm/util/clipping/clippingPlaneHelper.js +413 -0
  113. package/src/vcs/vcm/util/collection.js +193 -0
  114. package/src/vcs/vcm/util/dateTime.js +60 -0
  115. package/src/vcs/vcm/util/exclusiveManager.js +135 -0
  116. package/src/vcs/vcm/util/extent.js +124 -0
  117. package/src/vcs/vcm/util/featureProvider/abstractFeatureProvider.js +196 -0
  118. package/src/vcs/vcm/util/featureProvider/featureProviderHelpers.js +51 -0
  119. package/src/vcs/vcm/util/featureProvider/featureProviderSymbols.js +11 -0
  120. package/src/vcs/vcm/util/featureProvider/tileProviderFeatureProvider.js +62 -0
  121. package/src/vcs/vcm/util/featureProvider/wmsFeatureProvider.js +280 -0
  122. package/src/vcs/vcm/util/featureconverter/circleToCesium.js +215 -0
  123. package/src/vcs/vcm/util/featureconverter/convert.js +83 -0
  124. package/src/vcs/vcm/util/featureconverter/extent3d.js +154 -0
  125. package/src/vcs/vcm/util/featureconverter/featureconverterHelper.js +591 -0
  126. package/src/vcs/vcm/util/featureconverter/lineStringToCesium.js +171 -0
  127. package/src/vcs/vcm/util/featureconverter/pointToCesium.js +359 -0
  128. package/src/vcs/vcm/util/featureconverter/polygonToCesium.js +229 -0
  129. package/src/vcs/vcm/util/geometryHelpers.js +172 -0
  130. package/src/vcs/vcm/util/indexedCollection.js +158 -0
  131. package/src/vcs/vcm/util/isMobile.js +12 -0
  132. package/src/vcs/vcm/util/layerCollection.js +216 -0
  133. package/src/vcs/vcm/util/locale.js +53 -0
  134. package/src/vcs/vcm/util/mapCollection.js +363 -0
  135. package/src/vcs/vcm/util/math.js +71 -0
  136. package/src/vcs/vcm/util/projection.js +348 -0
  137. package/src/vcs/vcm/util/splitScreen.js +233 -0
  138. package/src/vcs/vcm/util/style/declarativeStyleItem.js +631 -0
  139. package/src/vcs/vcm/util/style/shapesCategory.js +67 -0
  140. package/src/vcs/vcm/util/style/styleFactory.js +48 -0
  141. package/src/vcs/vcm/util/style/styleHelpers.js +555 -0
  142. package/src/vcs/vcm/util/style/styleItem.js +226 -0
  143. package/src/vcs/vcm/util/style/vectorStyleItem.js +927 -0
  144. package/src/vcs/vcm/util/style/writeStyle.js +48 -0
  145. package/src/vcs/vcm/util/urlHelpers.js +16 -0
  146. package/src/vcs/vcm/util/viewpoint.js +333 -0
@@ -0,0 +1,591 @@
1
+ import { getBottomLeft } from 'ol/extent.js';
2
+ import {
3
+ Cartesian3,
4
+ HeightReference,
5
+ ColorGeometryInstanceAttribute,
6
+ GeometryInstance,
7
+ Material,
8
+ SceneTransforms,
9
+ MaterialAppearance,
10
+ ClassificationType,
11
+ PerInstanceColorAppearance,
12
+ GroundPrimitive,
13
+ GroundPolylinePrimitive,
14
+ ClassificationPrimitive,
15
+ ShadowMode,
16
+ Primitive,
17
+ Color,
18
+ PolylineMaterialAppearance,
19
+ } from '@vcmap/cesium';
20
+ import { parseInteger, parseNumber } from '@vcsuite/parsers';
21
+ import { getCesiumColor } from '../style/styleHelpers.js';
22
+
23
+ /**
24
+ * @param {import("@vcmap/cesium").Scene} scene
25
+ * @param {import("ol/style/Fill").default} fill
26
+ * @param {import("ol").Feature<import("ol/geom/Geometry").default>} feature
27
+ * @returns {import("@vcmap/cesium").MaterialAppearance}
28
+ */
29
+ export function getMaterialAppearance(scene, fill, feature) {
30
+ const options = {
31
+ flat: true,
32
+ renderState: {
33
+ depthTest: {
34
+ enabled: true,
35
+ },
36
+ },
37
+ };
38
+ const fillColor = fill.getColor();
39
+ if (fillColor instanceof CanvasPattern) {
40
+ const canvas = document.createElement('canvas');
41
+ const ctx = canvas.getContext('2d');
42
+ ctx.fillStyle = fillColor;
43
+ ctx.fillRect(0, 0, 300, 300);
44
+ options.material = Material.fromType('Wallpaper', {
45
+ image: canvas,
46
+ anchor: SceneTransforms.wgs84ToDrawingBufferCoordinates(
47
+ scene,
48
+ Cartesian3.fromDegreesArray(getBottomLeft(feature.getGeometry().getExtent()))[0],
49
+ ),
50
+ });
51
+ } else {
52
+ const color = getCesiumColor(fillColor, [0, 0, 0, 1]);
53
+ options.material = Material.fromType('Color', {
54
+ color,
55
+ });
56
+ options.translucent = color.alpha !== 1;
57
+ }
58
+ return new MaterialAppearance(options);
59
+ }
60
+
61
+ /**
62
+ *
63
+ * @param {Object} options
64
+ * @param {Array<import("@vcmap/cesium").Geometry>} geometries
65
+ * @param {import("@vcmap/cesium").Color} color
66
+ * @param {import("@vcmap/cesium").ClassificationType} classificationType
67
+ * @returns {import("@vcmap/cesium").ClassificationPrimitive}
68
+ */
69
+ export function createClassificationPrimitive(options, geometries, color, classificationType) {
70
+ const instances = geometries.map(geometry => new GeometryInstance({
71
+ geometry,
72
+ attributes: {
73
+ color: ColorGeometryInstanceAttribute.fromColor(color),
74
+ },
75
+ }));
76
+
77
+ const appearance = new PerInstanceColorAppearance({
78
+ flat: false,
79
+ renderState: {
80
+ depthTest: {
81
+ enabled: true,
82
+ },
83
+ lineWidth: 1,
84
+ },
85
+ translucent: color.alpha !== 1,
86
+ });
87
+
88
+ const classificationPrimitiveOptions = {
89
+ ...options,
90
+ geometryInstances: instances,
91
+ appearance,
92
+ shadows: ShadowMode.ENABLED,
93
+ classificationType,
94
+ };
95
+ return new ClassificationPrimitive(classificationPrimitiveOptions);
96
+ }
97
+
98
+ /**
99
+ *
100
+ * @param {import("@vcmap/cesium").Scene} scene
101
+ * @param {import("@vcmap/core").VectorProperties} vectorProperties
102
+ * @param {boolean} allowPicking
103
+ * @param {import("ol").Feature<import("ol/geom/Geometry").default>} feature
104
+ * @param {Array<import("@vcmap/cesium").Geometry>} geometries
105
+ * @param {import("ol/style/Style").default} style
106
+ * @param {boolean} groundPrimitive
107
+ * @returns {import("@vcmap/cesium").Primitive|import("@vcmap/cesium").GroundPrimitive|import("@vcmap/cesium").ClassificationPrimitive|null}
108
+ */
109
+ export function createPrimitive(scene, vectorProperties, allowPicking, feature, geometries, style, groundPrimitive) {
110
+ const classificationType = vectorProperties.getClassificationType(feature);
111
+ const options = {
112
+ shadows: ShadowMode.ENABLED,
113
+ allowPicking,
114
+ };
115
+ let primitive;
116
+ if (classificationType !== undefined && !groundPrimitive) {
117
+ if (!ClassificationPrimitive.isSupported(scene)) {
118
+ return null;
119
+ }
120
+ const color = getCesiumColor(style.getFill().getColor(), [0, 0, 0, 1]);
121
+ primitive = createClassificationPrimitive(options, geometries, color, classificationType);
122
+ } else {
123
+ const instances = geometries.map(geometry => new GeometryInstance({
124
+ geometry,
125
+ }));
126
+ options.geometryInstances = instances;
127
+ const appearance = getMaterialAppearance(scene, style.getFill(), feature);
128
+ options.appearance = appearance;
129
+ if (groundPrimitive) {
130
+ if (!GroundPrimitive.isSupported(scene)) {
131
+ return null;
132
+ }
133
+ options.classificationType = classificationType || ClassificationType.TERRAIN;
134
+ primitive = new GroundPrimitive(options);
135
+ } else {
136
+ primitive = new Primitive(options);
137
+ }
138
+ }
139
+ return primitive;
140
+ }
141
+
142
+ /**
143
+ *
144
+ * @param {import("@vcmap/cesium").Scene} scene
145
+ * @param {import("@vcmap/core").VectorProperties} vectorProperties
146
+ * @param {boolean} allowPicking
147
+ * @param {import("ol").Feature<import("ol/geom/Geometry").default>} feature
148
+ * @param {Array<import("@vcmap/cesium").Geometry>} geometries
149
+ * @param {import("ol/style/Style").default} style
150
+ * @returns {import("@vcmap/cesium").Primitive}
151
+ */
152
+ export function createOutlinePrimitive(scene, vectorProperties, allowPicking, feature, geometries, style) {
153
+ const color = getCesiumColor(style.getStroke().getColor(), [0, 0, 0, 1]);
154
+ const instances = geometries.map(geometry => new GeometryInstance({
155
+ geometry,
156
+ attributes: {
157
+ color: ColorGeometryInstanceAttribute.fromColor(color),
158
+ },
159
+ }));
160
+ const appearance = new PerInstanceColorAppearance({
161
+ flat: true,
162
+ renderState: {
163
+ depthTest: {
164
+ enabled: true,
165
+ },
166
+ lineWidth: 1,
167
+ },
168
+ translucent: color.alpha !== 1,
169
+ });
170
+ const options = {
171
+ geometryInstances: instances,
172
+ appearance,
173
+ shadows: ShadowMode.ENABLED,
174
+ allowPicking,
175
+ };
176
+ const primitive = new Primitive(options);
177
+ return primitive;
178
+ }
179
+
180
+ /**
181
+ *
182
+ * @param {import("@vcmap/cesium").Scene} scene
183
+ * @param {import("@vcmap/core").VectorProperties} vectorProperties
184
+ * @param {boolean} allowPicking
185
+ * @param {import("ol").Feature<import("ol/geom/Geometry").default>} feature
186
+ * @param {Array<import("@vcmap/cesium").PolylineGeometry|import("@vcmap/cesium").GroundPolylineGeometry>} geometries
187
+ * @param {import("ol/style/Style").default} style
188
+ * @param {boolean} groundPrimitive
189
+ * @returns {import("@vcmap/cesium").Primitive|import("@vcmap/cesium").GroundPolylinePrimitive|null}
190
+ */
191
+ export function createLinePrimitive(
192
+ scene, vectorProperties, allowPicking, feature, geometries, style, groundPrimitive,
193
+ ) {
194
+ const classificationType = vectorProperties.getClassificationType(feature);
195
+ const instances = geometries.map(geometry => new GeometryInstance({
196
+ geometry,
197
+ }));
198
+
199
+ const color = getCesiumColor(style.getStroke().getColor(), [0, 0, 0, 1]);
200
+ let material;
201
+ if (style.getStroke().getLineDash()) {
202
+ material = Material.fromType('Stripe', {
203
+ horizontal: false,
204
+ repeat: 500,
205
+ evenColor: color,
206
+ oddColor: new Color(0, 0, 0, 0), // transparent
207
+ });
208
+ } else {
209
+ material = Material.fromType('Color', { color });
210
+ }
211
+
212
+ const appearance = new PolylineMaterialAppearance({
213
+ renderState: {
214
+ depthTest: {
215
+ enabled: true,
216
+ },
217
+ lineWidth: 1,
218
+ },
219
+ translucent: color.alpha !== 1,
220
+ material,
221
+ });
222
+
223
+ const options = {
224
+ geometryInstances: instances,
225
+ appearance,
226
+ shadows: ShadowMode.ENABLED,
227
+ allowPicking,
228
+ };
229
+ let primitive;
230
+ if (groundPrimitive) {
231
+ if (!GroundPolylinePrimitive.isSupported(scene)) {
232
+ return null;
233
+ }
234
+ options.classificationType = classificationType || ClassificationType.TERRAIN;
235
+ primitive = new GroundPolylinePrimitive(options);
236
+ } else {
237
+ primitive = new Primitive(options);
238
+ }
239
+ return primitive;
240
+ }
241
+
242
+ /**
243
+ * returns groundlevel or extracts the minimum height from the coordinates, returns 0 if no z coordinates are set
244
+ * @param {number|null|undefined} groundLevel
245
+ * @param {Array<import("ol/coordinate").Coordinate>=} coordinates
246
+ * @returns {number}
247
+ */
248
+ export function getMinHeightOrGroundLevel(groundLevel, coordinates) {
249
+ if (groundLevel != null && Number.isFinite(Number(groundLevel))) {
250
+ return groundLevel;
251
+ }
252
+ if (coordinates) {
253
+ let minimumHeight = Infinity;
254
+ for (let i = 0; i < coordinates.length; i++) {
255
+ minimumHeight = coordinates[i][2] < minimumHeight ? coordinates[i][2] : minimumHeight;
256
+ }
257
+ if (Number.isFinite(minimumHeight)) {
258
+ return minimumHeight;
259
+ }
260
+ }
261
+ return 0;
262
+ }
263
+
264
+
265
+ /**
266
+ * @param {number} extrudedHeight should be a number > 0
267
+ * @param {Array<number>} storeyHeights
268
+ * @param {number} storeyNumber
269
+ * @returns {Array<number>}
270
+ */
271
+ export function getStoreyHeights(extrudedHeight, storeyHeights, storeyNumber) {
272
+ const positiveExtrudedHeight = Math.abs(extrudedHeight);
273
+ const fittedStoreyHeights = [];
274
+ if (storeyHeights.length) {
275
+ let height = 0;
276
+ for (let i = 0; i < storeyHeights.length; i++) {
277
+ height += storeyHeights[i];
278
+ if (height < positiveExtrudedHeight) {
279
+ fittedStoreyHeights.push(storeyHeights[i]);
280
+ } else {
281
+ fittedStoreyHeights.push(storeyHeights[i] - (height - positiveExtrudedHeight));
282
+ return fittedStoreyHeights;
283
+ }
284
+ }
285
+ const lastStoreyHeight = storeyHeights[storeyHeights.length - 1];
286
+ while (height < positiveExtrudedHeight) {
287
+ height += lastStoreyHeight;
288
+ if (height < positiveExtrudedHeight) {
289
+ fittedStoreyHeights.push(lastStoreyHeight);
290
+ } else {
291
+ fittedStoreyHeights.push(lastStoreyHeight - (height - positiveExtrudedHeight));
292
+ return fittedStoreyHeights;
293
+ }
294
+ }
295
+ } else if (storeyNumber) {
296
+ return new Array(storeyNumber).fill(positiveExtrudedHeight / storeyNumber);
297
+ }
298
+ // case no predefined storeyHeights
299
+ return [positiveExtrudedHeight];
300
+ }
301
+
302
+
303
+ /**
304
+ * @param {number} storeys
305
+ * @param {Array<number>} storeyHeights
306
+ */
307
+ export function validateStoreys(storeys, storeyHeights) {
308
+ if (storeys && storeyHeights.length) {
309
+ const missingStoreyHeights = storeys - storeyHeights.length;
310
+ if (missingStoreyHeights > 0) {
311
+ storeyHeights.push(
312
+ ...new Array(missingStoreyHeights).fill(storeyHeights[storeyHeights.length - 1]),
313
+ );
314
+ } else if (missingStoreyHeights < 0) {
315
+ storeyHeights.splice(storeyHeights.length + missingStoreyHeights);
316
+ }
317
+ if (storeys > 100) {
318
+ storeyHeights.splice(100);
319
+ }
320
+ } else {
321
+ storeyHeights.splice(0);
322
+ }
323
+ }
324
+
325
+ /**
326
+ * @param {import("ol").Feature<import("ol/geom/Geometry").default>} feature
327
+ * @param {import("@vcmap/cesium").HeightReference} heightReference
328
+ * @param {import("@vcmap/core").VectorProperties} vectorProperties
329
+ * @returns {number}
330
+ */
331
+ export function getHeightAboveGround(feature, heightReference, vectorProperties) {
332
+ if (heightReference === HeightReference.RELATIVE_TO_GROUND) {
333
+ return vectorProperties.getHeightAboveGround(feature);
334
+ }
335
+ return 0;
336
+ }
337
+
338
+ /**
339
+ * @param {import("ol").Feature<import("ol/geom/Geometry").default>} feature
340
+ * @param {import("@vcmap/core").VectorProperties} vectorProperties
341
+ * @param {Array<import("ol/coordinate").Coordinate>} coordinates
342
+ * @returns {VectorHeightInfo}
343
+ */
344
+ export function getHeightInfo(feature, vectorProperties, coordinates) {
345
+ const extrudedHeight = vectorProperties.getExtrudedHeight(feature);
346
+ const storeyNumber = Math.abs(parseInteger(feature.get('olcs_storeyNumber'), 0)); // legacy
347
+ const storeyHeight = Math.abs(parseNumber(feature.get('olcs_storeyHeight'), 0)); // legacy
348
+ let storeysAboveGround = 0;
349
+ let storeysBelowGround = 0;
350
+ let storeyHeightsAboveGround = [];
351
+ let storeyHeightsBelowGround = [];
352
+
353
+ // legacy CASE
354
+ if (storeyHeight || storeyNumber) {
355
+ if (extrudedHeight && extrudedHeight > 0 && storeyHeight) {
356
+ storeysAboveGround = Math.ceil(extrudedHeight / storeyHeight);
357
+ storeyHeightsAboveGround = new Array(storeysAboveGround - 1).fill(storeyHeight);
358
+ storeyHeightsAboveGround.push(extrudedHeight - (storeysAboveGround - 1) * storeyHeight);
359
+ } else if (extrudedHeight && extrudedHeight < 0 && storeyHeight) {
360
+ storeysBelowGround = Math.ceil(Math.abs(extrudedHeight / storeyHeight));
361
+ storeyHeightsBelowGround = new Array(storeysBelowGround - 1).fill(storeyHeight);
362
+ storeyHeightsBelowGround.push(Math.abs(extrudedHeight) - (storeysBelowGround - 1) * storeyHeight);
363
+ } else if (extrudedHeight && extrudedHeight > 0 && storeyNumber) {
364
+ storeysAboveGround = storeyNumber;
365
+ const currentStoreyHeight = Math.abs(extrudedHeight / storeyNumber);
366
+ storeyHeightsAboveGround = new Array(storeyNumber).fill(currentStoreyHeight);
367
+ } else if (extrudedHeight && extrudedHeight < 0 && storeyNumber) {
368
+ storeysBelowGround = storeyNumber;
369
+ const currentStoreyHeight = Math.abs(extrudedHeight / storeyNumber);
370
+ storeyHeightsBelowGround = new Array(storeyNumber).fill(currentStoreyHeight);
371
+ } else if (storeyNumber && storeyHeight) {
372
+ storeysAboveGround = storeyNumber;
373
+ storeyHeightsAboveGround = new Array(storeyNumber).fill(storeyHeight);
374
+ } else if (storeyNumber && vectorProperties.storeyHeight) {
375
+ storeysAboveGround = storeyNumber;
376
+ storeyHeightsAboveGround = new Array(storeyNumber).fill(vectorProperties.storeyHeight);
377
+ }
378
+ }
379
+
380
+ // no legacy case // can also be an invalid legacy case
381
+ if (!(storeysAboveGround && storeyHeightsAboveGround.length) &&
382
+ !(storeysBelowGround && storeyHeightsBelowGround.length)) {
383
+ storeysAboveGround = vectorProperties.getStoreysAboveGround(feature);
384
+ storeysBelowGround = vectorProperties.getStoreysBelowGround(feature);
385
+ storeyHeightsAboveGround = vectorProperties.getStoreyHeightsAboveGround(feature);
386
+ storeyHeightsBelowGround = vectorProperties.getStoreyHeightsBelowGround(feature);
387
+ if (extrudedHeight) { // current Case only extrudedHeight
388
+ if (extrudedHeight > 0) {
389
+ storeyHeightsAboveGround = getStoreyHeights(extrudedHeight, storeyHeightsAboveGround, storeysAboveGround);
390
+ storeysAboveGround = storeyHeightsAboveGround.length;
391
+ storeyHeightsBelowGround = [];
392
+ storeysBelowGround = 0;
393
+ } else if (extrudedHeight < 0) {
394
+ storeyHeightsBelowGround = getStoreyHeights(extrudedHeight, storeyHeightsBelowGround, storeysBelowGround);
395
+ storeysBelowGround = storeyHeightsBelowGround.length;
396
+ storeyHeightsAboveGround = [];
397
+ storeysAboveGround = 0;
398
+ }
399
+ }
400
+ }
401
+
402
+ validateStoreys(storeysAboveGround, storeyHeightsAboveGround);
403
+ validateStoreys(storeysBelowGround, storeyHeightsBelowGround);
404
+
405
+ const skirt = vectorProperties.getSkirt(feature);
406
+ const olcsGroundLevel = vectorProperties.getGroundLevel(feature);
407
+
408
+ const heightReference = vectorProperties.getAltitudeMode(feature);
409
+ const heightAboveGroundAdjustment = getHeightAboveGround(feature, heightReference, vectorProperties);
410
+
411
+ const groundLevel = getMinHeightOrGroundLevel(olcsGroundLevel, coordinates) + heightAboveGroundAdjustment;
412
+ const hasZCoordinate = !!coordinates.find(value => value[2]);
413
+
414
+ const extruded = !!(storeyHeightsAboveGround.length || storeyHeightsBelowGround.length || skirt);
415
+ const perPositionHeight = hasZCoordinate && (
416
+ !extruded ||
417
+ (extruded && ((storeyHeightsAboveGround.length + storeyHeightsBelowGround.length) === 1))
418
+ );
419
+
420
+ return {
421
+ extruded,
422
+ storeyHeightsAboveGround,
423
+ storeyHeightsBelowGround,
424
+ skirt,
425
+ groundLevel,
426
+ perPositionHeight,
427
+ heightReference,
428
+ heightAboveGroundAdjustment,
429
+ };
430
+ }
431
+
432
+ /**
433
+ * @param {Array<number>} storeyHeights
434
+ * @param {number} initialHeight
435
+ * @param {boolean} [down=false]
436
+ * @param {Array<{currentHeight:number, extrudedHeight:number}>=} result
437
+ * @returns {Array<{currentHeight:number, extrudedHeight:number}>}
438
+ */
439
+ export function getStoreyOptions(storeyHeights, initialHeight, down, result) {
440
+ const direction = down ? -1 : 1;
441
+ let currentHeight = initialHeight;
442
+ const storeys = storeyHeights.length;
443
+ const options = new Array(storeys);
444
+ for (let i = 0; i < storeys; i++) {
445
+ const extrudedHeight = currentHeight + direction * storeyHeights[i];
446
+ options[i] = {
447
+ currentHeight,
448
+ extrudedHeight,
449
+ };
450
+ currentHeight = extrudedHeight;
451
+ }
452
+
453
+ if (result) {
454
+ result.push(...options);
455
+ return result;
456
+ }
457
+ return options;
458
+ }
459
+
460
+ /**
461
+ *
462
+ * @param {import("ol").Feature<import("ol/geom/Geometry").default>} feature
463
+ * @param {import("ol/style/Style").default} style
464
+ * @param {Array<import("ol/geom/SimpleGeometry").default>} geometries
465
+ * @param {import("@vcmap/core").VectorProperties} vectorProperties
466
+ * @param {import("@vcmap/cesium").Scene} scene
467
+ * @param {VectorGeometryFactoryType} geometryFactory
468
+ * @param {import("@vcmap/core").VectorContext|import("@vcmap/core").ClusterContext} context
469
+ */
470
+ export function addPrimitivesToContext(
471
+ feature, style, geometries, vectorProperties, scene, geometryFactory, context,
472
+ ) {
473
+ // no geometries, so early escape
474
+ if (!geometries.length) {
475
+ return;
476
+ }
477
+
478
+ const fillGeometries = [];
479
+ const outlineGeometries = [];
480
+ const lineGeometries = [];
481
+
482
+ const heightInfo = getHeightInfo(feature, vectorProperties, geometryFactory.getCoordinates(geometries));
483
+
484
+ const hasFill = !!style.getFill();
485
+ const hasStroke = !!style.getStroke();
486
+
487
+ let groundPrimitive = false;
488
+
489
+
490
+ geometries.forEach((geometry) => {
491
+ const geometryOptions = geometryFactory.getGeometryOptions(geometry, heightInfo.heightAboveGroundAdjustment);
492
+ const storeyOptions = getStoreyOptions(heightInfo.storeyHeightsAboveGround, heightInfo.groundLevel);
493
+ getStoreyOptions(heightInfo.storeyHeightsBelowGround, heightInfo.groundLevel, true, storeyOptions);
494
+
495
+ if (hasFill) {
496
+ storeyOptions.forEach((options) => {
497
+ fillGeometries.push(
498
+ ...geometryFactory.createSolidGeometries(
499
+ geometryOptions,
500
+ options.currentHeight,
501
+ heightInfo.perPositionHeight,
502
+ options.extrudedHeight,
503
+ ),
504
+ );
505
+ });
506
+ }
507
+ if (hasStroke) {
508
+ storeyOptions.forEach((options) => {
509
+ outlineGeometries.push(
510
+ ...geometryFactory.createOutlineGeometries(
511
+ geometryOptions,
512
+ options.currentHeight,
513
+ heightInfo.perPositionHeight,
514
+ options.extrudedHeight,
515
+ ),
516
+ );
517
+ });
518
+ }
519
+ if (heightInfo.skirt) {
520
+ const currentHeight = heightInfo.groundLevel - heightInfo.storeyHeightsBelowGround.reduce((a, b) => a + b, 0);
521
+ const extrudedHeight = currentHeight - heightInfo.skirt;
522
+ const skirtPositionHeight = heightInfo.storeyHeightsBelowGround.length ? false : heightInfo.perPositionHeight;
523
+ if (hasFill) {
524
+ fillGeometries.push(
525
+ ...geometryFactory.createSolidGeometries(
526
+ geometryOptions,
527
+ currentHeight,
528
+ skirtPositionHeight,
529
+ extrudedHeight,
530
+ ),
531
+ );
532
+ }
533
+ if (hasStroke) {
534
+ outlineGeometries.push(
535
+ ...geometryFactory.createOutlineGeometries(
536
+ geometryOptions,
537
+ currentHeight,
538
+ skirtPositionHeight,
539
+ extrudedHeight,
540
+ ),
541
+ );
542
+ }
543
+ }
544
+
545
+ if (!heightInfo.extruded) {
546
+ if (heightInfo.heightReference === HeightReference.CLAMP_TO_GROUND) {
547
+ groundPrimitive = true;
548
+ }
549
+ if (hasFill) {
550
+ fillGeometries.push(...geometryFactory.createFillGeometries(
551
+ geometryOptions, heightInfo.groundLevel, heightInfo.perPositionHeight,
552
+ ));
553
+ }
554
+ if (hasStroke) {
555
+ if (heightInfo.heightReference === HeightReference.CLAMP_TO_GROUND) {
556
+ lineGeometries.push(...geometryFactory.createGroundLineGeometries(geometryOptions, style));
557
+ } else {
558
+ lineGeometries.push(...geometryFactory.createLineGeometries(geometryOptions, style));
559
+ }
560
+ }
561
+ }
562
+ });
563
+
564
+ const allowPicking = vectorProperties.getAllowPicking(feature);
565
+ const primitives = [];
566
+ if (lineGeometries.length) {
567
+ const linePrimitive =
568
+ createLinePrimitive(scene, vectorProperties, allowPicking, feature, lineGeometries, style, groundPrimitive);
569
+ if (linePrimitive) {
570
+ primitives.push(linePrimitive);
571
+ }
572
+ }
573
+
574
+ if (fillGeometries.length) {
575
+ const fillPrimitive =
576
+ createPrimitive(scene, vectorProperties, allowPicking, feature, fillGeometries, style, groundPrimitive);
577
+ if (fillPrimitive) {
578
+ primitives.push(fillPrimitive);
579
+ }
580
+ }
581
+
582
+ if (outlineGeometries.length) {
583
+ const outlinePrimitive =
584
+ createOutlinePrimitive(scene, vectorProperties, allowPicking, feature, outlineGeometries, style);
585
+ if (outlinePrimitive) {
586
+ primitives.push(outlinePrimitive);
587
+ }
588
+ }
589
+
590
+ context.addPrimitives(primitives, feature, allowPicking);
591
+ }