• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

geosolutions-it / MapStore2 / 16371927321

18 Jul 2025 01:35PM UTC coverage: 76.895% (-0.03%) from 76.924%
16371927321

Pull #11331

github

web-flow
Merge 52e841647 into e75d26e98
Pull Request #11331: Fix #11103 Update cesium to latest stable 1.131.0 , reviewed all the cesium layers and cesium map.

31259 of 48656 branches covered (64.24%)

33 of 43 new or added lines in 8 files covered. (76.74%)

27 existing lines in 6 files now uncovered.

38805 of 50465 relevant lines covered (76.89%)

36.52 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

72.99
/web/client/utils/cesium/DrawGeometryInteraction.js
1
/*
2
 * Copyright 2023, GeoSolutions Sas.
3
 * All rights reserved.
4
 *
5
 * This source code is licensed under the BSD-style license found in the
6
 * LICENSE file in the root directory of this source tree.
7
 */
8

9
import * as Cesium from 'cesium';
10
import throttle from 'lodash/throttle';
11
import { computePositionInfo } from './ClickUtils';
12
import {
13
    getCesiumColor,
14
    createPolylinePrimitive,
15
    createPolygonPrimitive,
16
    clearPrimitivesCollection,
17
    createCircleMarkerImage,
18
    createEllipsePolylinePrimitive,
19
    createCylinderPolylinePrimitive
20
} from './PrimitivesUtils';
21

22
import {
23
    computeArea,
24
    computeDistance,
25
    computeHeightSign,
26
    cartesianToCartographicArray,
27
    computeGeodesicCoordinates
28
} from './MathUtils';
29
import { generateEditingStyle } from '../DrawUtils';
30

31
function defaultGetPositionInfo(map, movement, {
×
32
    getObjectsToExcludeOnPick = () => [],
×
33
    pickObjectsLimit = Number.MAX_VALUE,
×
34
    depthTestAgainstTerrain
35
} = {}) {
36

37
    const objectToExclude = getObjectsToExcludeOnPick();
×
38

39
    let currentDepthTestAgainstTerrain;
40
    if (depthTestAgainstTerrain !== undefined) {
×
41
        // we should enable depth test to correctly compute the drawing on terrain
42
        currentDepthTestAgainstTerrain = map.scene.globe.depthTestAgainstTerrain;
×
43
        map.scene.globe.depthTestAgainstTerrain = depthTestAgainstTerrain;
×
44
    }
45

46
    // pick position works with the all the object in the scene
47
    // to avoid to intercept the geometries we are drawing we need to temporary hide them
48
    objectToExclude.forEach((obj) => {
×
49
        if (obj) {
×
50
            obj.show = false;
×
51
        }
52
    });
53

54
    const scene = map.scene;
×
55
    scene.render();
×
56

57
    const positionInfo = computePositionInfo(map, movement, {
×
58
        pickObjectsLimit
59
    });
60

61
    // restore the initial values
62
    if (depthTestAgainstTerrain !== undefined) {
×
63
        map.scene.globe.depthTestAgainstTerrain = currentDepthTestAgainstTerrain;
×
64
    }
65

66
    objectToExclude.forEach((obj) => {
×
67
        if (obj) {
×
68
            obj.show = true;
×
69
        }
70
    });
71

72
    return positionInfo;
×
73
}
74

75
function cesiumCoordinatesToGeoJSONFeature(geometryType, coordinates, {
76
    area,
77
    areaUom,
78
    length,
79
    lengthUom,
80
    height,
81
    heightUom,
82
    terrainCoordinates,
83
    geodesic
84
}) {
85
    const geodesicHeight = geodesic && coordinates?.[coordinates.length - 1] ? Cesium.Cartographic.fromCartesian(coordinates[coordinates.length - 1]).height : undefined;
16✔
86
    switch (geometryType) {
16!
87
    case 'Point':
88
        return {
4✔
89
            type: 'Feature',
90
            properties: terrainCoordinates
4✔
91
                ? {
92
                    height,
93
                    heightUom,
94
                    terrainCoordinates
95
                }
96
                : { geodesic },
97
            geometry: {
98
                type: 'Point',
99
                coordinates: cartesianToCartographicArray(coordinates[coordinates.length - 1], geodesicHeight)
100
            }
101
        };
102
    case 'LineString':
103
        return {
5✔
104
            type: 'Feature',
105
            properties: { length, lengthUom, geodesic },
106
            geometry: {
107
                type: 'LineString',
108
                coordinates: coordinates.map((cartesian) => cartesianToCartographicArray(cartesian, geodesicHeight))
12✔
109
            }
110
        };
111
    case 'Polygon':
112
        return {
5✔
113
            type: 'Feature',
114
            properties: { area, areaUom, length, lengthUom, geodesic },
115
            geometry: {
116
                type: 'Polygon',
117
                coordinates: [
118
                    coordinates.map((cartesian) => cartesianToCartographicArray(cartesian, geodesicHeight))
20✔
119
                ]
120
            }
121
        };
122
    case 'Circle':
123
        const radius = computeDistance([coordinates[0], coordinates[1]], geodesic);
2✔
124
        return {
2✔
125
            type: 'Feature',
126
            properties: { radius, radiusUom: 'm', geodesic },
127
            geometry: {
128
                type: 'Point',
129
                coordinates: cartesianToCartographicArray(coordinates[0], geodesicHeight)
130
            }
131
        };
132
    default:
133
        return null;
×
134
    }
135
}
136

137
function validateDrawnGeometry(geometryType, coordinates, coordinatesLength) {
138
    if (coordinatesLength && coordinatesLength !== coordinates.length) {
14✔
139
        return false;
2✔
140
    }
141
    switch (geometryType) {
12!
142
    case 'Point':
143
        return true;
×
144
    case 'LineString':
145
        return true;
5✔
146
    case 'Polygon':
147
        return coordinates.length > 2;
5✔
148
    default:
149
        return true;
2✔
150
    }
151
}
152

153
function getSampledTerrainPositions(terrainProvider, level = 18, positions) {
×
154
    return new Promise((resolve) => {
1✔
155
        const cartographicHeightZero = positions
1✔
156
            .map(cartesian => Cesium.Cartographic.fromCartesian(cartesian))
1✔
157
            .map(cartographic => new Cesium.Cartographic(cartographic.longitude, cartographic.latitude, 0));
1✔
158

159
        const promise = terrainProvider?.availability
1!
160
            ? Cesium.sampleTerrainMostDetailed(
161
                terrainProvider,
162
                cartographicHeightZero
163
            )
164
            : Cesium.sampleTerrain(
165
                terrainProvider,
166
                level,
167
                cartographicHeightZero
168
            );
169
        if (Cesium.defined(promise)) {
1!
170
            promise
1✔
171
                .then((updatedPositions) => {
172
                    resolve(updatedPositions);
1✔
173
                })
174
                // the sampleTerrainMostDetailed from the Cesium Terrain is still using .otherwise
175
                // and it resolve everything in the .then
176
                // while the sampleTerrain uses .catch
177
                // the optional chain help us to avoid error if catch is not exposed by the promise
178
                ?.catch?.(() => {
NEW
179
                    resolve();
×
180
                });
181
        } else {
NEW
182
            resolve();
×
183
        }
184
    });
185
}
186

187
/**
188
 * Class to manage all the drawing interaction of Cesium library
189
 * @param {string} options.type type of drawing, one of: `Point`, `LineString`, `Polygon` or `Circle`
190
 * @param {object} options.map a Cesium map instance
191
 * @param {number} options.coordinatesLength maximum count of drawing coordinates
192
 * @param {function} options.getPositionInfo custom function to return info given a position
193
 * @param {function} options.getObjectsToExcludeOnPick function that returns a list of primitives to exclude when computing the position with the default `getPositionInfo` function
194
 * @param {boolean} options.depthTestAgainstTerrain apply `depthTestAgainstTerrain` while drawing inside the default `getPositionInfo` function
195
 * @param {object} options.style style for drawing geometries, see the `web/client/DrawUtils.js` file
196
 * @param {boolean} options.geodesic if true the geometries height will be forced to the ellipsoid at 0 height
197
 * @param {boolean} options.sampleTerrain enable the possibility to get the point on terrain, it works only with `Point` type
198
 * @param {number} options.mouseMoveThrottleTime change the throttle time in milliseconds to get feedback on mouse move event, default 100ms
199
 * @param {function} options.onDrawStart triggered on draw start
200
 * @param {function} options.onDrawing triggered while drawing
201
 * @param {function} options.onMouseMove triggered while moving the mouse over the globe
202
 * @param {function} options.onDrawEnd triggered when the drawing event is completed (double click)
203
 */
204
class CesiumDrawGeometryInteraction {
205

206
    constructor(options) {
207

208
        this._type = options?.type;
16✔
209
        this._map = options?.map;
16✔
210
        this._coordinatesLength = options?.coordinatesLength;
16✔
211
        this._geodesic = options?.geodesic;
16✔
212
        this._sampleTerrain = options?.sampleTerrain;
16✔
213
        this._getObjectsToExcludeOnPick = () => [
16✔
214
            ...(options?.getObjectsToExcludeOnPick ? options.getObjectsToExcludeOnPick() : []),
×
215
            this._dynamicPrimitivesCollection,
216
            this._dynamicBillboardCollection
217
        ];
218
        this._depthTestAgainstTerrain = options?.depthTestAgainstTerrain;
16✔
219
        this._getPositionInfo =  options?.getPositionInfo || defaultGetPositionInfo;
16!
220

221
        this._handler = new Cesium.ScreenSpaceEventHandler(this._map.canvas);
16✔
222
        this._handler.setInputAction((movement) => {
16✔
223
            this._handleDrawEnd(movement, true);
8✔
224
        }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
225
        this._handler.setInputAction((movement) => {
16✔
226
            this._handleDrawing(movement);
43✔
227
            this._handleDrawStart(movement);
43✔
228
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
229
        this._handler.setInputAction(throttle((movement) => {
16✔
230
            this._handleMouseMove(movement);
×
231
        }, options.mouseMoveThrottleTime ?? 100), Cesium.ScreenSpaceEventType.MOUSE_MOVE);
32✔
232

233
        this._drawing = false;
16✔
234
        this._forcedDrawEnd = false;
16✔
235
        this._coordinates = [];
16✔
236

237
        this._style = generateEditingStyle(options?.style);
16✔
238

239
        this._dynamicPrimitivesCollection = new Cesium.PrimitiveCollection({ destroyPrimitives: true });
16✔
240
        this._map.scene.primitives.add(this._dynamicPrimitivesCollection);
16✔
241

242
        this._dynamicBillboardCollection = new Cesium.BillboardCollection({ scene: this._map.scene });
16✔
243
        this._map.scene.primitives.add(this._dynamicBillboardCollection);
16✔
244

245
        this._cursorImage = createCircleMarkerImage(this._style?.cursor?.radius * 2, { stroke: '#ffffff', strokeWidth: this._style?.cursor?.width, fill: 'rgba(0, 0, 0, 0)' });
16✔
246
        this._coordinateNodeImage = createCircleMarkerImage(this._style?.coordinatesNode?.radius * 2, { stroke: '#ffffff', strokeWidth: this._style?.coordinatesNode?.width, fill: 'rgba(0, 0, 0, 0.1)' });
16✔
247

248
        this._onMouseMove = options?.onMouseMove ? options.onMouseMove : () => {};
16!
249
        this._onDrawStart = options?.onDrawStart ? options.onDrawStart : () => {};
16!
250
        this._onDrawing = options?.onDrawing ? options.onDrawing : () => {};
16!
251
        this._onDrawEnd = options?.onDrawEnd ? options.onDrawEnd : () => {};
16!
252
    }
253
    getCoordinates() {
254
        return this._coordinates;
16✔
255
    }
256
    remove() {
257
        if (this._handler) {
16!
258
            this._handler.destroy();
16✔
259
            this._handler = null;
16✔
260
        }
261
        this._coordinates = [];
16✔
262
        this._drawing = false;
16✔
263
        if (this._map?.isDestroyed && !this._map.isDestroyed()) {
16!
264
            clearPrimitivesCollection(this._map, this._dynamicPrimitivesCollection);
×
265
            this._dynamicPrimitivesCollection = null;
×
266
            clearPrimitivesCollection(this._map, this._dynamicBillboardCollection);
×
267
            this._dynamicBillboardCollection = null;
×
268
        }
269
    }
270
    _getCoordinatesLength() {
271
        return this._type === 'Circle' ? 2 : this._coordinatesLength;
39✔
272
    }
273
    _handleMouseMove(movement) {
274
        const { cartesian } = this._getPositionInfo(this._map, movement, {
×
275
            getObjectsToExcludeOnPick: this._getObjectsToExcludeOnPick,
276
            depthTestAgainstTerrain: this._depthTestAgainstTerrain
277
        });
278
        if (cartesian) {
×
279
            if (this._type === 'Point' && this._sampleTerrain) {
×
280
                getSampledTerrainPositions(
×
281
                    this._map?.terrainProvider,
282
                    this._map?.terrainProvider?.sampleTerrainZoomLevel ?? 18,
×
283
                    [cartesian]
284
                )
285
                    .then((updatedPositions) => {
286
                        let distance;
287
                        if (updatedPositions) {
×
288
                            const [updatedPosition] = updatedPositions;
×
289
                            const cartesianTerrain = Cesium.Cartographic.toCartesian(updatedPosition);
×
290
                            const heightCoordinates = [cartesianTerrain, cartesian];
×
291
                            distance = computeHeightSign(heightCoordinates) * computeDistance(heightCoordinates);
×
292
                            this._coordinates = heightCoordinates;
×
293
                        } else {
294
                            this._coordinates = [cartesian];
×
295
                        }
296
                        this._onMouseMove(this._drawPrimitives({
×
297
                            distance,
298
                            cartesian,
299
                            coordinates: [...this._coordinates]
300
                        }));
301
                    });
302
            } else {
303
                const previousCartesian = this._coordinates[this._coordinates.length - 1];
×
304
                const currentCoordinates = [...this._coordinates, cartesian];
×
305
                const area = computeArea(currentCoordinates, undefined);
×
306
                const distance = computeDistance(currentCoordinates, this._geodesic);
×
307
                this._onMouseMove(this._drawPrimitives({
×
308
                    area,
309
                    distance,
310
                    previousCartesian,
311
                    cartesian,
312
                    coordinates: currentCoordinates
313
                }));
314
            }
315
        }
316
    }
317
    _handleDrawStart(movement) {
318
        if (!this._drawing && !this._forcedDrawEnd && !this._handler?.isDestroyed?.()) {
43✔
319
            const initialCoordinates = [...this._coordinates];
18✔
320
            this._coordinates = [];
18✔
321
            const { cartesian } = this._getPositionInfo(this._map, movement, {
18✔
322
                getObjectsToExcludeOnPick: this._getObjectsToExcludeOnPick,
323
                depthTestAgainstTerrain: this._depthTestAgainstTerrain
324
            });
325
            if (cartesian) {
18!
326
                this._coordinates.push(cartesian);
18✔
327
                if (this._type === 'Point') {
18✔
328

329
                    const requestSampleTerrain = this._sampleTerrain && initialCoordinates.length !== 2
4✔
330
                        ? () => getSampledTerrainPositions(
1✔
331
                            this._map?.terrainProvider,
332
                            this._map?.terrainProvider?.sampleTerrainZoomLevel ?? 18,
2✔
333
                            [cartesian]
334
                        )
335
                            .then((updatedPositions) => {
336
                                if (updatedPositions) {
1!
337
                                    const [updatedPosition] = updatedPositions;
1✔
338
                                    const cartesianTerrain = Cesium.Cartographic.toCartesian(updatedPosition);
1✔
339
                                    const heightCoordinates = [cartesianTerrain, cartesian];
1✔
340
                                    return heightCoordinates;
1✔
341
                                }
342
                                return [cartesian];
×
343
                            })
344
                        : () => Promise.resolve(initialCoordinates.length === 2 ? initialCoordinates : [cartesian]);
3!
345

346
                    requestSampleTerrain()
4✔
347
                        .then((currentCoordinates) => {
348
                            this._onDrawStart(this._drawPrimitives({
4✔
349
                                cartesian: currentCoordinates[currentCoordinates.length - 1],
350
                                coordinates: currentCoordinates,
351
                                geodesicCoordinates: computeGeodesicCoordinates(currentCoordinates)
352
                            }));
353
                            this._onDrawEnd(this._clearPrimitive({
4✔
354
                                coordinates: currentCoordinates,
355
                                geodesicCoordinates: computeGeodesicCoordinates(currentCoordinates),
356
                                feature: this._sampleTerrain && currentCoordinates.length === 2
9✔
357
                                    ? cesiumCoordinatesToGeoJSONFeature(this._type, currentCoordinates, {
358
                                        height: computeHeightSign(currentCoordinates) * computeDistance(currentCoordinates),
359
                                        heightUom: 'm',
360
                                        terrainCoordinates: cartesianToCartographicArray(currentCoordinates[0]),
361
                                        geodesic: this._geodesic
362
                                    })
363
                                    : cesiumCoordinatesToGeoJSONFeature(this._type, currentCoordinates, { geodesic: this._geodesic })
364
                            }));
365
                        });
366
                    this._coordinates = [];
4✔
367
                } else {
368
                    this._onDrawStart(this._drawPrimitives({
14✔
369
                        cartesian,
370
                        coordinates: [...this._coordinates],
371
                        geodesicCoordinates: computeGeodesicCoordinates(this._coordinates)
372
                    }));
373
                    this._drawing = true;
14✔
374
                }
375
            }
376
        }
377
        if (this._forcedDrawEnd) {
43✔
378
            this._forcedDrawEnd = false;
6✔
379
        }
380
    }
381
    _handleDrawing(movement) {
382
        if (this._drawing) {
43✔
383
            if ((this._coordinates.length + 1) === this._getCoordinatesLength()) {
25✔
384
                this._forcedDrawEnd = true;
6✔
385
                return this._handleDrawEnd(movement);
6✔
386
            }
387
            const { cartesian } = this._getPositionInfo(this._map, movement, {
19✔
388
                getObjectsToExcludeOnPick: this._getObjectsToExcludeOnPick,
389
                depthTestAgainstTerrain: this._depthTestAgainstTerrain
390
            });
391
            if (cartesian) {
19!
392
                const previousCartesian = this._coordinates[this._coordinates.length - 1];
19✔
393
                this._coordinates.push(cartesian);
19✔
394
                const currentCoordinates = [...this._coordinates];
19✔
395
                const area = computeArea(currentCoordinates, undefined);
19✔
396
                const distance = computeDistance(currentCoordinates, this._geodesic);
19✔
397
                this._onDrawing(this._drawPrimitives({
19✔
398
                    area,
399
                    distance,
400
                    previousCartesian,
401
                    cartesian,
402
                    coordinates: [...this._coordinates],
403
                    geodesicCoordinates: computeGeodesicCoordinates(this._coordinates)
404
                }));
405
            }
406
        }
407
        return null;
37✔
408
    }
409
    _handleDrawEnd(movement, isDoubleClick) {
410
        if (this._drawing) {
14!
411
            const { cartesian } = this._getPositionInfo(this._map, movement, {
14✔
412
                getObjectsToExcludeOnPick: this._getObjectsToExcludeOnPick,
413
                depthTestAgainstTerrain: this._depthTestAgainstTerrain
414
            });
415

416
            if (isDoubleClick) {
14✔
417
                // remove last two elements added with the double click event
418
                this._coordinates.splice(this._coordinates.length - 2, 2);
8✔
419
            }
420

421
            this._coordinates.push(cartesian);
14✔
422

423
            if (!validateDrawnGeometry(this._type, [...this._coordinates], this._getCoordinatesLength())) {
14✔
424
                this._onDrawEnd(this._clearPrimitive({}));
2✔
425
                this._coordinates = [];
2✔
426
                this._drawing = false;
2✔
427
                return null;
2✔
428
            }
429

430
            const currentCoordinates = this._type === 'Polygon'
12✔
431
                ? [...this._coordinates, this._coordinates[0]]
432
                : [...this._coordinates];
433
            const area = computeArea(currentCoordinates, undefined);
12✔
434
            const distance = computeDistance(currentCoordinates, this._geodesic);
12✔
435

436
            this._onDrawEnd(this._clearPrimitive({
12✔
437
                area,
438
                distance,
439
                coordinates: currentCoordinates,
440
                geodesicCoordinates: computeGeodesicCoordinates(currentCoordinates),
441
                feature: cesiumCoordinatesToGeoJSONFeature(this._type, currentCoordinates, {
442
                    area,
443
                    areaUom: 'sqm',
444
                    length: distance,
445
                    lengthUom: 'm',
446
                    geodesic: this._geodesic
447
                })
448
            }));
449
            this._coordinates = [];
12✔
450
            this._drawing = false;
12✔
451
        }
452
        return null;
12✔
453
    }
454
    _drawPrimitives(options) {
455
        if (this._style) {
37!
456
            this._updateDynamicCoordinates(options.coordinates);
37✔
457
        }
458
        return options;
37✔
459
    }
460

461
    _clearPrimitive(options) {
462
        this._dynamicPrimitivesCollection.removeAll();
18✔
463
        this._dynamicBillboardCollection.removeAll();
18✔
464
        return options;
18✔
465
    }
466

467
    _updateDynamicCoordinates(updatedCoordinates) {
468

469
        this._dynamicPrimitivesCollection.removeAll();
37✔
470
        this._dynamicBillboardCollection.removeAll();
37✔
471

472
        switch (this._type) {
37!
473
        case 'Point':
474
            if (this._geodesic) {
4✔
475
                const geodesicCoordinatesZero = computeGeodesicCoordinates(updatedCoordinates);
1✔
476
                this._dynamicPrimitivesCollection.add(createPolylinePrimitive({ ...this._style?.wireframe, coordinates: [geodesicCoordinatesZero[0], updatedCoordinates[0]] }));
1✔
477
                this._dynamicBillboardCollection.add({
1✔
478
                    position: geodesicCoordinatesZero[0],
479
                    image: this._coordinateNodeImage,
480
                    color: getCesiumColor({
481
                        ...this._style?.coordinatesNode
482
                    }),
483
                    disableDepthTestDistance: Number.POSITIVE_INFINITY
484
                });
485
            }
486
            break;
4✔
487
        case 'Circle':
488
            if (updatedCoordinates.length > 1) {
4!
489
                const radius = computeDistance(updatedCoordinates, this._geodesic);
×
490
                if (this._geodesic) {
×
491
                    const geodesicCoordinates = computeGeodesicCoordinates(updatedCoordinates, cartographic => cartographic[cartographic.length - 1]?.height);
×
492
                    const geodesicCoordinatesZero = computeGeodesicCoordinates(updatedCoordinates);
×
493
                    this._dynamicPrimitivesCollection.add(createEllipsePolylinePrimitive({
×
494
                        ...this._style?.wireframe,
495
                        coordinates: geodesicCoordinates[0],
496
                        radius,
497
                        geodesic: true
498
                    }));
499
                    this._dynamicPrimitivesCollection.add(createEllipsePolylinePrimitive({
×
500
                        ...this._style?.lineDrawing,
501
                        coordinates: geodesicCoordinatesZero[0],
502
                        radius,
503
                        geodesic: true
504
                    }));
505
                    this._dynamicBillboardCollection.add({
×
506
                        position: updatedCoordinates[0],
507
                        image: this._coordinateNodeImage,
508
                        color: getCesiumColor({
509
                            ...this._style?.coordinatesNode
510
                        }),
511
                        disableDepthTestDistance: Number.POSITIVE_INFINITY
512
                    });
513
                    this._dynamicBillboardCollection.add({
×
514
                        position: geodesicCoordinates[0],
515
                        image: this._coordinateNodeImage,
516
                        color: getCesiumColor({
517
                            ...this._style?.coordinatesNode
518
                        }),
519
                        disableDepthTestDistance: Number.POSITIVE_INFINITY
520
                    });
521
                    this._dynamicBillboardCollection.add({
×
522
                        position: geodesicCoordinatesZero[0],
523
                        image: this._coordinateNodeImage,
524
                        color: getCesiumColor({
525
                            ...this._style?.coordinatesNode
526
                        }),
527
                        disableDepthTestDistance: Number.POSITIVE_INFINITY
528
                    });
529
                    this._dynamicPrimitivesCollection.add(createPolylinePrimitive({
×
530
                        ...this._style?.wireframe,
531
                        geodesic: true,
532
                        coordinates: [
533
                            updatedCoordinates[0],
534
                            geodesicCoordinatesZero[0],
535
                            geodesicCoordinatesZero[1],
536
                            geodesicCoordinates[1],
537
                            geodesicCoordinates[0]
538
                        ]
539
                    }));
540
                } else {
541
                    this._dynamicPrimitivesCollection.add(createCylinderPolylinePrimitive({
×
542
                        ...this._style?.lineDrawing,
543
                        coordinates: updatedCoordinates[0],
544
                        radius
545
                    }));
546
                    this._dynamicPrimitivesCollection.add(createPolylinePrimitive({
×
547
                        ...this._style?.wireframe,
548
                        coordinates: [...updatedCoordinates]
549
                    }));
550
                }
551
            }
552
            break;
4✔
553
        case 'LineString':
554
            if (updatedCoordinates.length > 1) {
13✔
555
                if (this._geodesic) {
8✔
556
                    const geodesicCoordinates = computeGeodesicCoordinates(updatedCoordinates, cartographic => cartographic[cartographic.length - 1]?.height);
2✔
557
                    const geodesicCoordinatesZero = computeGeodesicCoordinates(updatedCoordinates);
2✔
558
                    this._dynamicPrimitivesCollection.add(createPolylinePrimitive({ ...this._style?.wireframe, geodesic: this._geodesic, coordinates: [...geodesicCoordinates] }));
2✔
559
                    this._dynamicPrimitivesCollection.add(createPolylinePrimitive({ ...this._style?.lineDrawing, geodesic: this._geodesic, coordinates: [...geodesicCoordinatesZero] }));
2✔
560
                    geodesicCoordinates.forEach((coord, idx) => {
2✔
561
                        this._dynamicPrimitivesCollection.add(createPolylinePrimitive({ ...this._style?.wireframe, geodesic: this._geodesic, coordinates: [geodesicCoordinatesZero[idx], geodesicCoordinates[idx]] }));
5✔
562
                    });
563
                } else {
564
                    this._dynamicPrimitivesCollection.add(createPolylinePrimitive({ ...this._style?.lineDrawing, coordinates: [...updatedCoordinates] }));
6✔
565
                }
566
            }
567
            break;
13✔
568
        case 'Polygon':
569
            if (updatedCoordinates.length > 1) {
16✔
570
                if (this._geodesic) {
11✔
571
                    const geodesicCoordinates = computeGeodesicCoordinates(updatedCoordinates, cartographic => cartographic[cartographic.length - 1]?.height);
3✔
572
                    const geodesicCoordinatesZero = computeGeodesicCoordinates(updatedCoordinates);
3✔
573
                    this._dynamicPrimitivesCollection.add(createPolygonPrimitive({ ...this._style?.areaDrawing, geodesic: this._geodesic, coordinates: [...geodesicCoordinatesZero, geodesicCoordinatesZero[0]] }));
3✔
574
                    this._dynamicPrimitivesCollection.add(createPolylinePrimitive({ ...this._style?.wireframe, geodesic: this._geodesic, coordinates: [...geodesicCoordinates, geodesicCoordinates[0]] }));
3✔
575
                    this._dynamicPrimitivesCollection.add(createPolylinePrimitive({ ...this._style?.lineDrawing, geodesic: this._geodesic, coordinates: [...geodesicCoordinatesZero, geodesicCoordinatesZero[0]] }));
3✔
576
                    geodesicCoordinates.forEach((coord, idx) => {
3✔
577
                        this._dynamicPrimitivesCollection.add(createPolylinePrimitive({ ...this._style?.wireframe, geodesic: this._geodesic, coordinates: [geodesicCoordinatesZero[idx], geodesicCoordinates[idx]] }));
9✔
578
                    });
579
                } else {
580
                    this._dynamicPrimitivesCollection.add(createPolygonPrimitive({ ...this._style?.areaDrawing, coordinates: [...updatedCoordinates] }));
8✔
581
                    this._dynamicPrimitivesCollection.add(createPolylinePrimitive({ ...this._style?.lineDrawing, coordinates: [...updatedCoordinates] }));
8✔
582
                }
583
            }
584
            break;
16✔
585
        default:
586
            break;
×
587
        }
588
        if (updatedCoordinates.length > 0) {
37!
589
            this._dynamicBillboardCollection.add({
37✔
590
                position: updatedCoordinates[updatedCoordinates.length - 1],
591
                image: this._cursorImage,
592
                color: getCesiumColor({
593
                    ...this._style?.cursor
594
                }),
595
                disableDepthTestDistance: Number.POSITIVE_INFINITY
596
            });
597
        }
598
        this._map.scene.requestRender();
37✔
599
    }
600
}
601

602
export default CesiumDrawGeometryInteraction;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc