@vcmap/core 6.0.0-rc.6 → 6.0.0-rc.7

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 (45) hide show
  1. package/dist/cesium.d.ts +1 -0
  2. package/dist/index.d.ts +1 -1
  3. package/dist/index.js +1 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/src/layer/cesium/clusterContext.d.ts +4 -2
  6. package/dist/src/layer/cesium/clusterContext.js +14 -3
  7. package/dist/src/layer/cesium/clusterContext.js.map +1 -1
  8. package/dist/src/layer/cesium/vectorContext.d.ts +2 -2
  9. package/dist/src/layer/cesium/vectorContext.js +7 -5
  10. package/dist/src/layer/cesium/vectorContext.js.map +1 -1
  11. package/dist/src/layer/oblique/obliqueHelpers.js +3 -3
  12. package/dist/src/layer/oblique/obliqueHelpers.js.map +1 -1
  13. package/dist/src/layer/vectorProperties.d.ts +2 -2
  14. package/dist/src/layer/vectorProperties.js +6 -4
  15. package/dist/src/layer/vectorProperties.js.map +1 -1
  16. package/dist/src/ol/geom/geometryCollection.js +1 -1
  17. package/dist/src/ol/geom/geometryCollection.js.map +1 -1
  18. package/dist/src/util/clipping/clippingPlaneHelper.js +2 -2
  19. package/dist/src/util/clipping/clippingPlaneHelper.js.map +1 -1
  20. package/dist/src/util/editor/editorHelpers.js +3 -3
  21. package/dist/src/util/editor/editorHelpers.js.map +1 -1
  22. package/dist/src/util/featureconverter/convert.d.ts +4 -0
  23. package/dist/src/util/featureconverter/convert.js +1 -1
  24. package/dist/src/util/featureconverter/convert.js.map +1 -1
  25. package/dist/src/util/featureconverter/pointHelpers.js +9 -3
  26. package/dist/src/util/featureconverter/pointHelpers.js.map +1 -1
  27. package/dist/src/util/geometryHelpers.d.ts +12 -1
  28. package/dist/src/util/geometryHelpers.js +89 -12
  29. package/dist/src/util/geometryHelpers.js.map +1 -1
  30. package/dist/tests/unit/helpers/helpers.d.ts +1 -1
  31. package/dist/tests/unit/helpers/helpers.js +2 -2
  32. package/dist/tests/unit/helpers/helpers.js.map +1 -1
  33. package/index.ts +3 -1
  34. package/package.json +1 -1
  35. package/src/cesium/cesium.d.ts +1 -0
  36. package/src/layer/cesium/clusterContext.ts +16 -3
  37. package/src/layer/cesium/vectorContext.ts +13 -10
  38. package/src/layer/oblique/obliqueHelpers.ts +3 -3
  39. package/src/layer/vectorProperties.ts +7 -5
  40. package/src/ol/geom/geometryCollection.js +3 -1
  41. package/src/util/clipping/clippingPlaneHelper.ts +3 -4
  42. package/src/util/editor/editorHelpers.ts +3 -3
  43. package/src/util/featureconverter/convert.ts +3 -1
  44. package/src/util/featureconverter/pointHelpers.ts +9 -4
  45. package/src/util/geometryHelpers.ts +145 -14
@@ -4,6 +4,7 @@ import {
4
4
  Entity,
5
5
  SplitDirection,
6
6
  Scene,
7
+ ConstantProperty,
7
8
  } from '@vcmap-cesium/engine';
8
9
  import { StyleLike } from 'ol/style/Style.js';
9
10
  import type { Feature } from 'ol/index.js';
@@ -17,12 +18,18 @@ import convert, { ConvertedItem } from '../../util/featureconverter/convert.js';
17
18
  class ClusterContext implements CesiumVectorContext {
18
19
  entities: EntityCollection;
19
20
 
21
+ splitDirection: SplitDirection;
22
+
23
+ private _splitDirectionProperty: ConstantProperty;
24
+
20
25
  private _featureItems = new Map<Feature, (() => void)[]>();
21
26
 
22
27
  private _convertingFeatures: Map<Feature, () => void> = new Map();
23
28
 
24
- constructor(dataSource: CustomDataSource) {
29
+ constructor(dataSource: CustomDataSource, splitDirection: SplitDirection) {
25
30
  this.entities = dataSource.entities;
31
+ this.splitDirection = splitDirection;
32
+ this._splitDirectionProperty = new ConstantProperty(splitDirection);
26
33
  }
27
34
 
28
35
  private _addConvertedItems(
@@ -36,7 +43,10 @@ class ClusterContext implements CesiumVectorContext {
36
43
  let removeItem: (() => void) | undefined;
37
44
  if (item.type === 'billboard') {
38
45
  instance = this.entities.add({
39
- billboard: item.item,
46
+ billboard: {
47
+ ...item.item,
48
+ splitDirection: this._splitDirectionProperty,
49
+ },
40
50
  position: item.item.position,
41
51
  });
42
52
  } else if (item.type === 'label') {
@@ -108,7 +118,10 @@ class ClusterContext implements CesiumVectorContext {
108
118
  }
109
119
 
110
120
  // eslint-disable-next-line class-methods-use-this,no-unused-vars
111
- updateSplitDirection(_splitDirection: SplitDirection): void {}
121
+ updateSplitDirection(splitDirection: SplitDirection): void {
122
+ this.splitDirection = splitDirection;
123
+ this._splitDirectionProperty.setValue(this.splitDirection);
124
+ }
112
125
 
113
126
  clear(): void {
114
127
  this.entities.removeAll();
@@ -1,5 +1,5 @@
1
1
  import {
2
- type Billboard,
2
+ Billboard,
3
3
  BillboardCollection,
4
4
  Cartesian3,
5
5
  type Entity,
@@ -34,13 +34,12 @@ export function setReferenceForPicking(
34
34
  /**
35
35
  * Sets splitDirection on primitives. Currently only Model primitives support splitting.
36
36
  */
37
- export function setSplitDirectionOnPrimitives(
38
- splitDirection: SplitDirection,
39
- primitives: PrimitiveCollection,
40
- ): void {
37
+ export function setSplitDirectionOnPrimitives<
38
+ T extends PrimitiveCollection | BillboardCollection,
39
+ >(splitDirection: SplitDirection, primitives: T): void {
41
40
  for (let i = 0; i < primitives.length; i++) {
42
- const p = primitives.get(i) as Primitive | Model;
43
- if (p instanceof Model) {
41
+ const p = primitives.get(i) as Primitive | Model | Billboard;
42
+ if (p instanceof Model || p instanceof Billboard) {
44
43
  p.splitDirection = splitDirection;
45
44
  }
46
45
  }
@@ -84,7 +83,7 @@ export function setupScalingPrimitiveCollection(
84
83
  primitive.modelMatrix = Matrix4.setScale(
85
84
  modelMatrix,
86
85
  new Cartesian3(res, res, res),
87
- new Matrix4(),
86
+ primitive.modelMatrix,
88
87
  );
89
88
  primitive[scaleSymbol] = res;
90
89
  }
@@ -202,8 +201,11 @@ export default class VectorContext implements CesiumVectorContext {
202
201
  setReferenceForPicking(feature, instance);
203
202
  }
204
203
 
205
- if (this.splitDirection && instance instanceof Model) {
206
- // Cesium currently only supports splitDirection on Model primitives // XXX this is no longer TRUE
204
+ if (
205
+ this.splitDirection &&
206
+ (instance instanceof Model || instance instanceof Billboard)
207
+ ) {
208
+ // Cesium currently only supports splitDirection on Model & Billboard Primitives
207
209
  instance.splitDirection = this.splitDirection;
208
210
  }
209
211
  }
@@ -262,6 +264,7 @@ export default class VectorContext implements CesiumVectorContext {
262
264
  this.splitDirection = splitDirection;
263
265
  setSplitDirectionOnPrimitives(splitDirection, this.primitives);
264
266
  setSplitDirectionOnPrimitives(splitDirection, this.scaledPrimitives);
267
+ setSplitDirectionOnPrimitives(splitDirection, this.billboards);
265
268
  }
266
269
 
267
270
  clear(): void {
@@ -19,7 +19,7 @@ import {
19
19
  } from '../vectorSymbols.js';
20
20
  import {
21
21
  convertGeometryToPolygon,
22
- getFlatCoordinatesFromGeometry,
22
+ getFlatCoordinateReferences,
23
23
  } from '../../util/geometryHelpers.js';
24
24
  import { transformFromImage } from '../../oblique/helpers.js';
25
25
  import type ObliqueImage from '../../oblique/obliqueImage.js';
@@ -97,7 +97,7 @@ export async function mercatorGeometryToImageGeometry(
97
97
  ? fromCircle(inputSourceGeometry)
98
98
  : inputSourceGeometry;
99
99
  const coordinates = sourceGeometry.getCoordinates() as any[];
100
- const flattenCoordinates = getFlatCoordinatesFromGeometry(
100
+ const flattenCoordinates = getFlatCoordinateReferences(
101
101
  sourceGeometry,
102
102
  coordinates,
103
103
  );
@@ -151,7 +151,7 @@ export function imageGeometryToMercatorGeometry(
151
151
  image: ObliqueImage,
152
152
  ): Promise<Geometry> {
153
153
  const coordinates = sourceGeometry.getCoordinates() as any[];
154
- const flattenCoordinates = getFlatCoordinatesFromGeometry(
154
+ const flattenCoordinates = getFlatCoordinateReferences(
155
155
  sourceGeometry,
156
156
  coordinates,
157
157
  );
@@ -897,10 +897,10 @@ class VectorProperties {
897
897
  }
898
898
 
899
899
  /**
900
- * Get the features or the properties modelOptions. Returns an empty Object if both are undefined
900
+ * Get the features or the properties modelOptions.
901
901
  * @param feature
902
902
  */
903
- getModelOptions(feature: Feature): Record<string, unknown> {
903
+ getModelOptions(feature: Feature): Record<string, unknown> | undefined {
904
904
  const featureValue = feature.get('olcs_modelOptions') as
905
905
  | Record<string, unknown>
906
906
  | undefined;
@@ -910,7 +910,7 @@ class VectorProperties {
910
910
  if (this.modelOptions) {
911
911
  return this.modelOptions;
912
912
  }
913
- return {};
913
+ return undefined;
914
914
  }
915
915
 
916
916
  get modelAutoScale(): boolean {
@@ -1315,7 +1315,7 @@ class VectorProperties {
1315
1315
  }
1316
1316
 
1317
1317
  getValues(): VectorPropertiesOptions {
1318
- const values = {
1318
+ return {
1319
1319
  altitudeMode: getAltitudeModeOptions(this.altitudeMode),
1320
1320
  allowPicking: this.allowPicking,
1321
1321
  classificationType: getClassificationTypeOptions(this.classificationType),
@@ -1336,9 +1336,11 @@ class VectorProperties {
1336
1336
  modelHeading: this.modelHeading,
1337
1337
  modelPitch: this.modelPitch,
1338
1338
  modelRoll: this.modelRoll,
1339
+ modelAutoScale: this.modelAutoScale,
1340
+ modelOptions: this.modelOptions,
1339
1341
  baseUrl: this.baseUrl,
1342
+ primitiveOptions: this.primitiveOptions,
1340
1343
  };
1341
- return values;
1342
1344
  }
1343
1345
 
1344
1346
  /**
@@ -54,5 +54,7 @@ GeometryCollection.prototype.getStride = function getStride() {
54
54
  */
55
55
  GeometryCollection.prototype.getFlatCoordinates =
56
56
  function getFlatCoordinates() {
57
- return this.getGeometriesArray().flatMap((g) => g.getFlatCoordinates());
57
+ return this.getGeometriesArrayRecursive().flatMap((g) =>
58
+ g.getFlatCoordinates(),
59
+ );
58
60
  };
@@ -13,7 +13,6 @@ import {
13
13
  type Camera,
14
14
  } from '@vcmap-cesium/engine';
15
15
  import type { Coordinate } from 'ol/coordinate.js';
16
- import type { Geometry } from 'ol/geom.js';
17
16
  import Feature from 'ol/Feature.js';
18
17
  import LineString from 'ol/geom/LineString.js';
19
18
  import { offset } from 'ol/sphere.js';
@@ -27,7 +26,7 @@ import Extent3D from '../featureconverter/extent3D.js';
27
26
  import {
28
27
  enforceEndingVertex,
29
28
  enforceRightHand,
30
- getFlatCoordinatesFromGeometry,
29
+ getFlatCoordinateReferences,
31
30
  } from '../geometryHelpers.js';
32
31
  import { mercatorToCartesian } from '../math.js';
33
32
 
@@ -162,7 +161,7 @@ export function createClippingPlaneCollection(
162
161
  check(transformMatrix, optional(Matrix4));
163
162
 
164
163
  const clippingPlanes = [];
165
- const geometry = feature.getGeometry() as Geometry;
164
+ const geometry = feature.getGeometry()!;
166
165
  const geometryType = geometry.getType();
167
166
 
168
167
  if (geometryType === 'Point') {
@@ -174,7 +173,7 @@ export function createClippingPlaneCollection(
174
173
  ),
175
174
  );
176
175
  } else {
177
- const coords = getFlatCoordinatesFromGeometry(geometry);
176
+ const coords = getFlatCoordinateReferences(geometry);
178
177
  if (
179
178
  coords.length < 2 ||
180
179
  (coords[0][0] === coords[1][0] && coords[0][1] === coords[1][1])
@@ -18,7 +18,7 @@ import {
18
18
  } from '@vcmap-cesium/engine';
19
19
 
20
20
  import { mercatorToCartesian } from '../math.js';
21
- import { getFlatCoordinatesFromGeometry } from '../geometryHelpers.js';
21
+ import { getFlatCoordinateReferences } from '../geometryHelpers.js';
22
22
  import CesiumMap from '../../map/cesiumMap.js';
23
23
  import { vertexIndexSymbol, vertexSymbol } from './editorSymbols.js';
24
24
  import {
@@ -365,7 +365,7 @@ export async function drapeGeometryOnTerrain(
365
365
  ): Promise<void> {
366
366
  if (map instanceof CesiumMap) {
367
367
  const coordinates = geometry.getCoordinates() as any[];
368
- const flats = getFlatCoordinatesFromGeometry(geometry, coordinates);
368
+ const flats = getFlatCoordinateReferences(geometry, coordinates);
369
369
  await map.getHeightFromTerrain(flats);
370
370
  geometry.setCoordinates(coordinates, 'XYZ');
371
371
  }
@@ -382,7 +382,7 @@ export async function placeGeometryOnTerrain(
382
382
  ): Promise<void> {
383
383
  if (map instanceof CesiumMap) {
384
384
  const coordinates = geometry.getCoordinates() as any[];
385
- const flats = getFlatCoordinatesFromGeometry(geometry, coordinates);
385
+ const flats = getFlatCoordinateReferences(geometry, coordinates);
386
386
  await map.getHeightFromTerrain(flats);
387
387
  let minHeight = Infinity;
388
388
  flats.forEach((coord) => {
@@ -109,7 +109,9 @@ export function getStylesArray(
109
109
  return styles;
110
110
  }
111
111
 
112
- function getSingleGeometriesFromGeometry(geometry: Geometry): SingleGeometry[] {
112
+ export function getSingleGeometriesFromGeometry(
113
+ geometry: Geometry,
114
+ ): SingleGeometry[] {
113
115
  if (
114
116
  geometry instanceof Point ||
115
117
  geometry instanceof Polygon ||
@@ -44,6 +44,7 @@ import {
44
44
  RelativeHeightReference,
45
45
  VectorHeightInfo,
46
46
  } from './vectorHeightInfo.js';
47
+ import { scaleSymbol } from '../../layer/cesium/vectorContext.js';
47
48
 
48
49
  function makeOffsetAutoScalePrimitive(
49
50
  primitive: Primitive | Model,
@@ -114,12 +115,16 @@ function makeClampedPrimitive(
114
115
  undefined,
115
116
  scratchUpdateHeightCartesian,
116
117
  );
117
-
118
- const geometryModelMatrix = Matrix4.fromScale(scale);
118
+ let usedScale = scale;
119
+ const autoScale = primitive[scaleSymbol];
120
+ if (autoScale != null) {
121
+ usedScale = new Cartesian3(autoScale, autoScale, autoScale);
122
+ }
123
+ const geometryModelMatrix = Matrix4.fromScale(usedScale);
119
124
  if (offset) {
120
125
  Matrix4.setTranslation(
121
126
  geometryModelMatrix,
122
- Cartesian3.multiplyComponents(offset, scale, new Cartesian3()),
127
+ Cartesian3.multiplyComponents(offset, usedScale, new Cartesian3()),
123
128
  geometryModelMatrix,
124
129
  );
125
130
  }
@@ -131,7 +136,7 @@ function makeClampedPrimitive(
131
136
  primitive.modelMatrix = Matrix4.multiply(
132
137
  transform,
133
138
  geometryModelMatrix,
134
- new Matrix4(),
139
+ primitive.modelMatrix,
135
140
  );
136
141
  };
137
142
 
@@ -19,8 +19,18 @@ import {
19
19
  Polygon,
20
20
  SimpleGeometry,
21
21
  } from 'ol/geom.js';
22
+ import { Feature } from 'ol';
22
23
  import Projection from './projection.js';
23
24
  import { mercatorToCartographic } from './math.js';
25
+ import VectorProperties from '../layer/vectorProperties.js';
26
+ import {
27
+ getHeightInfo,
28
+ isClampedHeightReference,
29
+ isRelativeHeightReference,
30
+ RelativeHeightReference,
31
+ VectorHeightInfo,
32
+ } from './featureconverter/vectorHeightInfo.js';
33
+ import { getSingleGeometriesFromGeometry } from './featureconverter/convert.js';
24
34
 
25
35
  export function getFlatCoordinatesFromSimpleGeometry(
26
36
  geometry: SimpleGeometry,
@@ -44,7 +54,7 @@ export function getFlatCoordinatesFromSimpleGeometry(
44
54
  return [];
45
55
  }
46
56
 
47
- export function getFlatCoordinatesFromGeometry(
57
+ export function getFlatCoordinateReferences(
48
58
  geometry: Geometry,
49
59
  inputCoordinates?: any[],
50
60
  ): Coordinate[] {
@@ -78,9 +88,7 @@ export function getFlatCoordinatesFromGeometry(
78
88
  } else if (geometry instanceof GeometryCollection) {
79
89
  flattenCoordinates = geometry
80
90
  .getGeometries()
81
- .map((g, i) =>
82
- getFlatCoordinatesFromGeometry(g, coordinates?.[i] as any[]),
83
- )
91
+ .map((g, i) => getFlatCoordinateReferences(g, coordinates?.[i] as any[]))
84
92
  .reduce((current, next) => current.concat(next));
85
93
  }
86
94
  return flattenCoordinates as Coordinate[];
@@ -195,7 +203,7 @@ export function from3Dto2DLayout(geometry: Geometry): void {
195
203
  return;
196
204
  }
197
205
  const coordinates = geometry.getCoordinates() as any[];
198
- const flatCoordinates = getFlatCoordinatesFromGeometry(geometry, coordinates);
206
+ const flatCoordinates = getFlatCoordinateReferences(geometry, coordinates);
199
207
  flatCoordinates.forEach((coordinate) => {
200
208
  if (layout === 'XYZM') {
201
209
  coordinate[2] = coordinate.pop()!;
@@ -207,13 +215,13 @@ export function from3Dto2DLayout(geometry: Geometry): void {
207
215
  }
208
216
 
209
217
  /**
210
- * Wil transform a 2D geometry (layout XY XYM) in place to 3D (XYZ XYZM) using the provided scene & height reference.
211
- * will no apply anything, if the layout is already 3D
218
+ * Places a geometry on to the ground (or terrain). The geometry is changed in place. This function
219
+ * will set the layout to a respective 3D layout.
212
220
  * @param geometry
213
221
  * @param scene
214
- * @param heightReference
222
+ * @param heightReference - clamp to ground will use `scene.getHeightMostDetailed`, terrain will use `sampleTerrainMostDetailed` using the scenes terrain provider
215
223
  */
216
- export async function from2Dto3DLayout(
224
+ export async function placeGeometryOnGround(
217
225
  geometry: Geometry,
218
226
  scene: Scene,
219
227
  heightReference:
@@ -221,17 +229,15 @@ export async function from2Dto3DLayout(
221
229
  | HeightReference.CLAMP_TO_TERRAIN,
222
230
  ): Promise<void> {
223
231
  const layout = geometry.getLayout();
224
- if (!is2DLayout(layout)) {
225
- return;
226
- }
227
232
  const coordinates = geometry.getCoordinates() as any[];
228
- const flatCoordinates = getFlatCoordinatesFromGeometry(geometry, coordinates);
233
+ const flatCoordinates = getFlatCoordinateReferences(geometry, coordinates);
229
234
  const cartographics = flatCoordinates.map((c) => mercatorToCartographic(c));
230
235
  if (heightReference === HeightReference.CLAMP_TO_GROUND) {
231
236
  await scene.sampleHeightMostDetailed(cartographics);
232
237
  } else {
233
238
  await sampleTerrainMostDetailed(scene.terrainProvider, cartographics);
234
239
  }
240
+
235
241
  cartographics.forEach((c, index) => {
236
242
  if (layout === 'XYM') {
237
243
  flatCoordinates[index][3] = flatCoordinates[index][2];
@@ -240,5 +246,130 @@ export async function from2Dto3DLayout(
240
246
  flatCoordinates[index][2] = c.height;
241
247
  }
242
248
  });
243
- geometry.setCoordinates(coordinates, layout === 'XYM' ? 'XYZM' : 'XYZ');
249
+
250
+ geometry.setCoordinates(
251
+ coordinates,
252
+ layout === 'XYM' || layout === 'XYZM' ? 'XYZM' : 'XYZ',
253
+ );
254
+ }
255
+
256
+ /**
257
+ * Wil transform a 2D geometry (layout XY XYM) in place to 3D (XYZ XYZM) using the provided scene & height reference.
258
+ * will no apply anything, if the layout is already 3D
259
+ * @param geometry
260
+ * @param scene
261
+ * @param heightReference
262
+ */
263
+ export async function from2Dto3DLayout(
264
+ geometry: Geometry,
265
+ scene: Scene,
266
+ heightReference:
267
+ | HeightReference.CLAMP_TO_GROUND
268
+ | HeightReference.CLAMP_TO_TERRAIN,
269
+ ): Promise<void> {
270
+ if (is2DLayout(geometry.getLayout())) {
271
+ await placeGeometryOnGround(geometry, scene, heightReference);
272
+ }
273
+ }
274
+
275
+ export async function createAbsoluteFeatures(
276
+ features: Feature[],
277
+ vectorProperties: VectorProperties,
278
+ scene: Scene,
279
+ ): Promise<Feature[]> {
280
+ const clones = features.map((feature) => feature.clone());
281
+ const absoluteClones = await Promise.all(
282
+ clones.map(async (feature) => {
283
+ const geometry = feature.getGeometry();
284
+ if (!geometry) {
285
+ return null;
286
+ }
287
+
288
+ const altitudeMode = vectorProperties.getAltitudeMode(feature);
289
+ if (altitudeMode === HeightReference.NONE) {
290
+ if (is2DLayout(geometry.getLayout())) {
291
+ await from2Dto3DLayout(
292
+ geometry,
293
+ scene,
294
+ HeightReference.CLAMP_TO_GROUND,
295
+ );
296
+ }
297
+ } else if (isClampedHeightReference(altitudeMode)) {
298
+ await placeGeometryOnGround(
299
+ geometry,
300
+ scene,
301
+ altitudeMode !== HeightReference.CLAMP_TO_TERRAIN
302
+ ? HeightReference.CLAMP_TO_GROUND
303
+ : HeightReference.CLAMP_TO_TERRAIN,
304
+ );
305
+ } else if (isRelativeHeightReference(altitudeMode)) {
306
+ const singleGeometries = getSingleGeometriesFromGeometry(geometry);
307
+ await Promise.all(
308
+ singleGeometries.map(async (singleGeometry) => {
309
+ const heightInfo = getHeightInfo(
310
+ feature,
311
+ singleGeometry,
312
+ vectorProperties,
313
+ ) as VectorHeightInfo<RelativeHeightReference>;
314
+
315
+ let { groundLevel } = heightInfo;
316
+ if (heightInfo.clampOrigin) {
317
+ const cartographics = [
318
+ mercatorToCartographic(heightInfo.clampOrigin),
319
+ ];
320
+ if (
321
+ heightInfo.heightReference ===
322
+ HeightReference.RELATIVE_TO_TERRAIN
323
+ ) {
324
+ await sampleTerrainMostDetailed(
325
+ scene.terrainProvider,
326
+ cartographics,
327
+ );
328
+ } else {
329
+ await scene.sampleHeightMostDetailed(cartographics);
330
+ }
331
+ groundLevel = cartographics[0].height;
332
+ }
333
+
334
+ const coordinates = singleGeometry.getCoordinates() as any[];
335
+ const flatCoordinates = getFlatCoordinateReferences(
336
+ singleGeometry,
337
+ coordinates,
338
+ );
339
+ const { heightAboveGround } = heightInfo;
340
+ const setCoordinate =
341
+ heightAboveGround == null
342
+ ? (c: Coordinate): void => {
343
+ c[2] += groundLevel as number;
344
+ }
345
+ : (c: Coordinate): void => {
346
+ c[2] = (groundLevel as number) + heightAboveGround;
347
+ };
348
+ flatCoordinates.forEach(setCoordinate);
349
+ singleGeometry.setCoordinates(coordinates, 'XYZ');
350
+ }),
351
+ );
352
+
353
+ if (geometry instanceof MultiPoint) {
354
+ geometry.setCoordinates(
355
+ singleGeometries.map((g) => g.getCoordinates() as Coordinate),
356
+ );
357
+ } else if (geometry instanceof MultiPolygon) {
358
+ geometry.setCoordinates(
359
+ singleGeometries.map((g) => g.getCoordinates() as Coordinate[][]),
360
+ );
361
+ } else if (geometry instanceof MultiLineString) {
362
+ geometry.setCoordinates(
363
+ singleGeometries.map((g) => g.getCoordinates() as Coordinate[]),
364
+ );
365
+ } else if (geometry instanceof GeometryCollection) {
366
+ geometry.setGeometries(singleGeometries);
367
+ }
368
+ }
369
+
370
+ return feature;
371
+ }),
372
+ );
373
+
374
+ return absoluteClones.filter((f): f is Feature => !!f);
244
375
  }