drone_view 3.0.19 → 3.0.20

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/src/utility.ts ADDED
@@ -0,0 +1,802 @@
1
+ import {
2
+ BoundingSphere,
3
+ Cartesian2,
4
+ Cartesian3,
5
+ Color,
6
+ VerticalOrigin,
7
+ Viewer,
8
+ CallbackProperty,
9
+ defined,
10
+ Entity,
11
+ HorizontalOrigin,
12
+ Math as cMath,
13
+ PolylineDashMaterialProperty,
14
+ HeightReference,
15
+ Ellipsoid,
16
+ LabelStyle,
17
+ DistanceDisplayCondition,
18
+ HeadingPitchRoll,
19
+ Transforms,
20
+ Quaternion, Matrix3
21
+ } from "cesium";
22
+ // @ts-ignore
23
+ import * as Normalize from "normalize-value";
24
+ import * as Cesium from "cesium";
25
+ import type {
26
+ DrawingConfig,
27
+ Point,
28
+ LabelConfigByCartesian,
29
+ } from "./app.interface";
30
+
31
+ // Min map scale wrt google map
32
+ export const mapScale = 591657550.5;
33
+ // Map Maximum zoom level
34
+ export const mapMaxZoom = 23;
35
+ // Map min zoom level
36
+ export const mapMinZoom = 0;
37
+
38
+ /**
39
+ * To check object exist in cesium viewer
40
+ * @param obj Cesium object
41
+ * @returns boolean
42
+ */
43
+ export const isCesiumObject = (obj: any) => defined(obj);
44
+
45
+ /**
46
+ * Convert camera distance to zoom level
47
+ * @param height number distance between camera position and map earth surface
48
+ * @returns number zoom level between 0-23
49
+ */
50
+ export const cameraHeightToZoomLevel = (height: number): number => {
51
+ for (let i = mapMinZoom; i <= mapMaxZoom; i += 1) {
52
+ // To check camera distance from earth lies between which zoom levels
53
+ if (height >= mapScale / 2 ** +(i + 1) && height < mapScale / 2 ** +i) {
54
+ const afterDecimal = Normalize.default(height, [
55
+ { value: mapScale / 2 ** +(i + 1), norm: 0 },
56
+ { value: mapScale / 2 ** +i, norm: 1 },
57
+ ]);
58
+ return i + afterDecimal;
59
+ }
60
+ }
61
+
62
+ throw new Error("Something went wrong");
63
+ };
64
+
65
+ /**
66
+ * Covert zoom level to camera distance
67
+ * @param zoom Zoom level
68
+ * @returns Distance between camera and earth surface
69
+ */
70
+ export const zoomLevelToCameraHeight = (zoom: number): number =>
71
+ Normalize.default(
72
+ zoom.toString().split(".")[1] ? +zoom.toString().split(".")[1] : 0,
73
+ [
74
+ {
75
+ value: 0,
76
+ norm: mapScale / 2 ** +(zoom + 1).toString().split(".")[0],
77
+ },
78
+ { value: 1, norm: mapScale / 2 ** +zoom.toString().split(".")[0] },
79
+ ]
80
+ );
81
+
82
+ /**
83
+ * This method allows user to convert position from Latitude,
84
+ * Longitude & altitude to Cesium Cartesian3 format
85
+ * @param position - Json object contains Latitude, Longitude & Altitude
86
+ * @returns - Cesium Cartesian3 Position
87
+ */
88
+ export const PointToCartesian = (position: Point): Cartesian3 => {
89
+ const cartesian = Cartesian3.fromDegrees(
90
+ +position.long,
91
+ +position.lat,
92
+ +(position.height || 0)
93
+ );
94
+ return cartesian;
95
+ };
96
+
97
+ /**
98
+ * To convert Cartesian3 to Point
99
+ * @param position Cartesian3 position
100
+ * @returns Point
101
+ */
102
+ export const cartesianToPoint = (position: Cartesian3): Point => {
103
+ const cartographic = Ellipsoid.WGS84.cartesianToCartographic(position);
104
+ return {
105
+ long: cMath.toDegrees(cartographic.longitude),
106
+ lat: cMath.toDegrees(cartographic.latitude),
107
+ height: cartographic.height,
108
+ };
109
+ };
110
+
111
+ /**
112
+ * This Function is for converting array of Cartesian to lat lng
113
+ * @param { Cartesian3[] } positions - Array of Cesium Cartesian3 Position
114
+ * @returns Array of longitude, latitude & height
115
+ */
116
+ export const cartesianArrayToPointArray = (positions: Cartesian3[]) => {
117
+ const langLats: any = [];
118
+ positions.forEach((position) => {
119
+ const cartographic = Ellipsoid.WGS84.cartesianToCartographic(position);
120
+ langLats.push([
121
+ cMath.toDegrees(cartographic.longitude),
122
+ cMath.toDegrees(cartographic.latitude),
123
+ cartographic.height,
124
+ ]);
125
+ });
126
+ return langLats;
127
+ };
128
+
129
+ /**
130
+ * To
131
+ * @param { Point[] } positions
132
+ * @returns { Cartesian3[] }
133
+ */
134
+ export const pointArrayToCartesianArray = (positions: Array<Array<number>>) => {
135
+ const cartesians: Cartesian3[] = [];
136
+ positions.forEach((position) => {
137
+ cartesians.push(
138
+ PointToCartesian({
139
+ lat: +position[1],
140
+ long: +position[0],
141
+ height: +(position[2] || 0),
142
+ })
143
+ );
144
+ });
145
+ return cartesians;
146
+ };
147
+
148
+ /**
149
+ * Covert cesium coordinates to geojson feature collection
150
+ * @param positions Array<Cartesian3>
151
+ * @param type DrawingConfig['type']
152
+ * @returns any
153
+ */
154
+ export const cartesianToGeojson = (
155
+ positions: Array<Cartesian3>,
156
+ type: DrawingConfig["type"],
157
+ properties?: any
158
+ ) => {
159
+ const features: any = [];
160
+ if (type === "Polygon") {
161
+ const feature = {
162
+ type: "Feature",
163
+ geometry: {
164
+ type: "Polygon",
165
+ coordinates: [cartesianArrayToPointArray(positions)],
166
+ },
167
+ };
168
+ features.push(feature);
169
+ } else if (type === "Point") {
170
+ positions.forEach((position) => {
171
+ const feature = {
172
+ type: "Feature",
173
+ geometry: {
174
+ type: "Point",
175
+ coordinates: [
176
+ cartesianToPoint(position).long,
177
+ cartesianToPoint(position).lat,
178
+ cartesianToPoint(position).height,
179
+ ],
180
+ },
181
+ };
182
+ features.push(feature);
183
+ });
184
+ } else {
185
+ const feature = {
186
+ type: "Feature",
187
+ geometry: {
188
+ type: "LineString",
189
+ coordinates: cartesianArrayToPointArray(positions),
190
+ },
191
+ };
192
+ features.push(feature);
193
+ }
194
+
195
+ const geojson = {
196
+ type: "FeatureCollection",
197
+ features,
198
+ properties,
199
+ };
200
+
201
+ return geojson;
202
+ };
203
+
204
+ // eslint-disable-next-line consistent-return
205
+ export const getEntityById = (viewer: Viewer, windowPosition: Cartesian2) => {
206
+ let object;
207
+ if (viewer.scene.pickPositionSupported) {
208
+ const pickedObject = viewer.scene.pick(windowPosition);
209
+
210
+ if (pickedObject?.id instanceof Entity) {
211
+ object = pickedObject.id;
212
+ }
213
+ return object;
214
+ }
215
+ };
216
+
217
+ /**
218
+ * Get global position from mouse screen position
219
+ * @param viewer Viewer
220
+ * @param windowPosition Mouse window position object
221
+ * @returns Object with feature details and position
222
+ */
223
+ export const screenToWorldPosition = (
224
+ viewer: Viewer,
225
+ windowPosition: Cartesian2
226
+ ):
227
+ | {
228
+ data?: { [key: string]: string };
229
+ position: Cartesian3;
230
+ id?: string;
231
+ layerId?: string;
232
+ }
233
+ | any => {
234
+ const entity = getEntityById(viewer, windowPosition);
235
+ const position = viewer.scene.pickPosition(windowPosition);
236
+ if (position) {
237
+ return {
238
+ position,
239
+ data: entity?.data,
240
+ id: entity ? entity : undefined,
241
+ layerId: entity?.layerId,
242
+ };
243
+ }
244
+
245
+ const ray = viewer.scene.camera.getPickRay(windowPosition)!;
246
+ return { position: viewer.scene.globe.pick(ray, viewer.scene)! };
247
+ };
248
+
249
+ /**
250
+ * This function allows user to get distance between two points
251
+ * @param left - Position first
252
+ * @param right - Position second
253
+ * @returns Distance between first and second position in meter
254
+ */
255
+ export const distance2D = (left: Cartesian2, right: Cartesian2): number => {
256
+ const distance = Cartesian2.distance(left, right);
257
+ return distance;
258
+ };
259
+
260
+ /**
261
+ * This function allows user to compute sum of distances between the positions
262
+ * @param position - Array of positions
263
+ * @returns Sum of distances between the positions in meter
264
+ */
265
+ export const distance3D = (positions: Array<Cartesian3>): number => {
266
+ let length = 0;
267
+ for (let i = 0; i < positions.length - 1; i += 1) {
268
+ length += Cartesian3.distance(positions[i], positions[i + 1]);
269
+ }
270
+ return length;
271
+ };
272
+
273
+ /**
274
+ * This function allows user to get mid point between two position
275
+ * @param left - first position
276
+ * @param right - second position
277
+ * @returns Mid Point in Cartesian3 format
278
+ */
279
+ export const getMidPoint = (
280
+ left: Cartesian3,
281
+ right: Cartesian3
282
+ ): Cartesian3 => {
283
+ const midPoint = Cartesian3.add(left, right, new Cartesian3());
284
+ Cartesian3.multiplyByScalar(midPoint, 0.5, midPoint);
285
+ return midPoint;
286
+ };
287
+
288
+ export const getPolygonCenter = (positions: Array<Cartesian3>): Cartesian3 => {
289
+ const { center } = BoundingSphere.fromPoints(positions);
290
+ return center;
291
+ };
292
+
293
+ /**
294
+ * This function allows user to get area of 3D Polygon
295
+ * @param polygonEntity : Cesium Polygon entity/geometry
296
+ * @returns Area in square meter
297
+ */
298
+ export const calculateArea = (pointData: Array<Point>): number => {
299
+ let area = 0;
300
+ const positions: any = [];
301
+ pointData.forEach((point) => {
302
+ positions.push(PointToCartesian(point));
303
+ });
304
+
305
+ for (let i = 0; i < positions.length - 2; i += 1) {
306
+ const vector1 = positions[0];
307
+ const vector2 = positions[i + 1];
308
+ const vector3 = positions[i + 2];
309
+ const vectorC = Cartesian3.subtract(vector2, vector1, new Cartesian3());
310
+ const vectorD = Cartesian3.subtract(vector3, vector1, new Cartesian3());
311
+ const areaVector = Cartesian3.cross(vectorC, vectorD, new Cartesian3());
312
+ area += Cartesian3.magnitude(areaVector) / 2.0;
313
+ }
314
+ return area;
315
+ };
316
+
317
+ export const calculate3DArea = (geoPoints: Point[]): number => {
318
+ const points: Cartesian3[] = geoPoints.map((p) =>
319
+ Cartesian3.fromDegrees(Number(p.long), Number(p.lat), Number(p.height) || 0)
320
+ );
321
+ console.log('dddddd',points)
322
+ if (points.length < 3) return 0; // Not enough points to form an area
323
+
324
+ let area = 0;
325
+ const origin = points[0];
326
+
327
+ for (let i = 1; i < points.length - 1; i++) {
328
+ const vec1 = Cartesian3.subtract(points[i], origin, new Cartesian3());
329
+ const vec2 = Cartesian3.subtract(points[i + 1], origin, new Cartesian3());
330
+ const cross = Cartesian3.cross(vec1, vec2, new Cartesian3());
331
+ const triangleArea = Cartesian3.magnitude(cross) / 2.0;
332
+ area += triangleArea;
333
+ }
334
+
335
+ return area;
336
+ };
337
+
338
+ export const calculate3DPerimeter = (points: Point[]): number => {
339
+ const cartesianPoints = points.map(p =>
340
+ Cartesian3.fromDegrees(Number(p.long), Number(p.lat), Number(p.height) || 0)
341
+ );
342
+
343
+ let length = 0;
344
+ for (let i = 0; i < cartesianPoints.length; i++) {
345
+ const current = cartesianPoints[i];
346
+ const next = cartesianPoints[(i + 1) % cartesianPoints.length]; // loop back to start
347
+ length += Cartesian3.distance(current, next);
348
+ }
349
+
350
+ return length; // in meters
351
+ };
352
+
353
+ /**
354
+ * This method allows user to add a point on map on a position
355
+ * @param viewer - Cesium Viewer object
356
+ * @param position - Cesium Cartesian3 position
357
+ * @param id - Id thats user want to assign point entity
358
+ * @param id - Id thats user want to assign point entity
359
+ * @returns - Point type Entity
360
+ */
361
+ export const addPoint = (
362
+ viewer: Viewer,
363
+ position: Cartesian3,
364
+ id?: string,
365
+ size?: number,
366
+ color?: CallbackProperty,
367
+ noOutline?: boolean
368
+ ): Entity => {
369
+ if (id && viewer.entities.getById(id))
370
+ viewer.entities.remove(viewer.entities.getById(id)!);
371
+
372
+ const svg = `<svg height="20" width="20" xmlns="http://www.w3.org/2000/svg">
373
+ <circle cx="10" cy="10" r="8.5" stroke="red" stroke-width="1.5" fill="whiteSmoke" />
374
+ </svg>`;
375
+
376
+ const point = viewer.entities.add({
377
+ id,
378
+ position,
379
+ // point: {
380
+ // pixelSize: size || 10,
381
+ // color: color || Color.WHITE,
382
+ // heightReference: HeightReference.RELATIVE_TO_GROUND,
383
+ // outlineColor: Color.BLACK,
384
+ // outlineWidth: noOutline ? 0 : 3,
385
+ // // disableDepthTestDistance: 10
386
+ // },
387
+ billboard: {
388
+ image: `data:image/svg+xml;base64,${window.btoa(svg)}`,
389
+ verticalOrigin: VerticalOrigin.CENTER,
390
+ eyeOffset: new Cartesian3(0, 0, -1),
391
+ },
392
+ });
393
+ return point;
394
+ };
395
+
396
+ /**
397
+ * This method allows user to add a polyline on map using set of user provided position
398
+ * @param viewer - Cesium Viewer object
399
+ * @param positions - Array of position in Cesium cartesian3
400
+ * @param config - Configuration object to control color & width of line
401
+ * @returns - Cesium Polyline entity
402
+ */
403
+ export const addPolyLineFilled = (
404
+ viewer: Viewer,
405
+ positions: Array<Cartesian3>,
406
+ config?: DrawingConfig,
407
+ layerId?: string,
408
+ properties?: any
409
+ ): any => {
410
+ if (config?.id && viewer.entities.getById(config.id)) {
411
+ viewer.entities.remove(viewer.entities.getById(config.id)!);
412
+ }
413
+
414
+ return {
415
+ id: config?.id,
416
+ polyline: {
417
+ // classificationType: Cesium.ClassificationType.CESIUM_3D_TILE,
418
+ depthFailMaterial: config?.lineColor
419
+ ? Color.fromCssColorString(config.lineColor)
420
+ : Color.fromCssColorString("#FF0000"),
421
+ positions,
422
+ width: config?.lineWidth ? config?.lineWidth : 3,
423
+
424
+ material: config?.lineColor
425
+ ? Color.fromCssColorString(config.lineColor).withAlpha(
426
+ config.opacity ? config.opacity : 1
427
+ )
428
+ : Color.fromCssColorString("#FFC72C").withAlpha(
429
+ config?.opacity ? config.opacity : 1
430
+ ),
431
+ clampToGround: properties?.clamp,
432
+ },
433
+ layerId,
434
+ heightReference: HeightReference.CLAMP_TO_GROUND,
435
+ data: properties,
436
+ };
437
+ };
438
+
439
+ /**
440
+ * Get pyramid cone for camera position
441
+ * @param position - position in Cesium cartesian3
442
+ * @param layerId - layer Id
443
+ * @param url - image url
444
+ * @returns - Cesium Polyline entity
445
+ */
446
+ export const getPyramid = (
447
+ position: Cartesian3,
448
+ layerId?: string,
449
+ url?: string,
450
+ angle?: number,
451
+ z_angle?: number,
452
+ flightpitchdegree?: number,
453
+ flightrolldegree?: number,
454
+ flightyawdegree?: number,
455
+ directionVector?: [number, number, number]
456
+ ): any => {
457
+
458
+ let orientation: Quaternion;
459
+
460
+ // Check if direction vector is provided, otherwise calculate from yaw and pitch
461
+ if (directionVector) {
462
+ const direction = new Cartesian3(directionVector[0], directionVector[1], directionVector[2]);
463
+ // Calculate orientation using the direction vector
464
+ orientation = getOrientationFromDirectionVector(position, direction);
465
+ } else {
466
+ // If no direction vector, use yaw, pitch, and roll
467
+ const heading = cMath.toRadians(angle || 0);
468
+ const pitch = cMath.toRadians(z_angle || 0);
469
+ const roll = cMath.toRadians(flightrolldegree || 0);
470
+ const hpr = new HeadingPitchRoll(heading, pitch, roll);
471
+ orientation = Transforms.headingPitchRollQuaternion(position, hpr);
472
+ }
473
+
474
+ return {
475
+ position: position,
476
+ orientation: orientation,
477
+ cylinder: {
478
+ topRadius: 0,
479
+ bottomRadius: 1.5,
480
+ length: 1.5,
481
+ slices: 4,
482
+ material: Color.WHITE.withAlpha(0.01),
483
+ outline: true,
484
+ outlineColor: Color.WHITE,
485
+ outlineWidth: 5,
486
+ },
487
+ layerId,
488
+ data: { url },
489
+ };
490
+ };
491
+
492
+ function getOrientationFromDirectionVector(position: Cartesian3, direction: Cartesian3): Quaternion {
493
+ // Compute the rotation matrix from the direction vector
494
+ const up = Cartesian3.UNIT_Z; // Up direction
495
+ const right = Cartesian3.cross(up, direction, new Cartesian3()); // Right direction (cross product)
496
+ const finalUp = Cartesian3.cross(direction, right, new Cartesian3()); // Final Up vector (cross product)
497
+
498
+ const rotationMatrix = new Matrix3(
499
+ right.x, right.y, right.z,
500
+ finalUp.x, finalUp.y, finalUp.z,
501
+ -direction.x, -direction.y, -direction.z
502
+ );
503
+
504
+ // Convert the rotation matrix to a quaternion for orientation
505
+ return Quaternion.fromRotationMatrix(rotationMatrix);
506
+ }
507
+
508
+ /**
509
+ * Get pyramid cone for camera position
510
+ * @param position - position in Cesium cartesian3
511
+ * @param layerId - layer Id
512
+ * @param url - image url
513
+ * @returns - Cesium Polyline entity
514
+ */
515
+ export const getTriangle = (
516
+ position: Cartesian3,
517
+ layerId?: string,
518
+ url?: string,
519
+ angle?: number,
520
+ z_angle?: number,
521
+ flightpitchdegree?: number,
522
+ flightrolldegree?: number,
523
+ flightyawdegree?: number
524
+ ): any => {
525
+ const heading = cMath.toRadians(flightyawdegree || 0);
526
+ const pitch = cMath.toRadians(flightpitchdegree || 0);
527
+ const roll = cMath.toRadians(flightrolldegree || 0);
528
+
529
+ const hpr: any = new HeadingPitchRoll(heading, pitch, roll);
530
+ const orientation: any = Transforms.headingPitchRollQuaternion(position, hpr);
531
+
532
+
533
+ return {
534
+ position: Cesium.Matrix4.multiplyByPoint(
535
+ Cesium.Transforms.eastNorthUpToFixedFrame(position),
536
+ new Cesium.Cartesian3(0, 1.5, 0),
537
+ new Cesium.Cartesian3()
538
+ ),
539
+ orientation: orientation,
540
+ cylinder: {
541
+ topRadius: 0.5,
542
+ bottomRadius: 0.5,
543
+ length: 0.001,
544
+ slices: 3,
545
+ material: Color.WHITE.withAlpha(0.01),
546
+ outline: true,
547
+ outlineColor: Color.WHITE,
548
+ outlineWidth: 5,
549
+ },
550
+ layerId,
551
+ data: { url },
552
+ };
553
+ };
554
+
555
+ /**
556
+ * This function allows user to add polygon on map
557
+ * @param viewer - Cesium Viewer object
558
+ * @param positions - Cesium Polygon Hierarchy
559
+ * @param config - Configuration Object to control fill color
560
+ * @returns Cesium Polygon entity
561
+ */
562
+ export const getPolygonEntity = (
563
+ positions: any,
564
+ layerId: string,
565
+ opacity: number,
566
+ properties?: any,
567
+ outline?: boolean,
568
+ clampToGround?: boolean,
569
+ near?: number,
570
+ far?: number
571
+ ): any => ({
572
+ polygon: {
573
+ hierarchy: positions,
574
+ // perPositionHeight: true,
575
+ // heightReference: HeightReference.CLAMP_TO_GROUND,
576
+ outline: true,
577
+ fill: true,
578
+ outlineWidth: 5,
579
+ outlineColor: properties.color
580
+ ? Color.fromCssColorString(properties.color).withAlpha(1)
581
+ : Color.fromCssColorString("#FFC72C").withAlpha(1),
582
+ material: properties.color
583
+ ? Color.fromCssColorString(properties.color).withAlpha(opacity || 0.0)
584
+ : Color.fromCssColorString("#FFC72C").withAlpha(opacity || 0.0),
585
+
586
+ clampToGround: !!clampToGround,
587
+ // distanceDisplayCondition: new DistanceDisplayCondition(near, far),
588
+ },
589
+ layerId,
590
+ data: properties,
591
+ });
592
+
593
+ /**
594
+ * this function will add a label on map and return label entity
595
+ * @param viewer - Cesium viewer object
596
+ * @param config - LabelConfigByCartesian
597
+ * @returns - Cesium label entity
598
+ */
599
+ export const getLabelEntity = (
600
+ text: string,
601
+ position: Cartesian3,
602
+ near?: number,
603
+ far?: number
604
+ ): any => ({
605
+ position,
606
+ label: {
607
+ text,
608
+ font: `14px Roboto Condensed`,
609
+ fillColor: Color.BLACK,
610
+ showBackground: true,
611
+ backgroundColor: Color.WHITESMOKE,
612
+ horizontalOrigin: HorizontalOrigin.CENTER,
613
+ verticalOrigin: VerticalOrigin.CENTER,
614
+ style: LabelStyle.FILL,
615
+ // heightReference: HeightReference.CLAMP_TO_GROUND,
616
+ eyeOffset: new Cartesian3(0, 0, 10),
617
+ distanceDisplayCondition: new DistanceDisplayCondition(near, far),
618
+ },
619
+ });
620
+
621
+ /**
622
+ * This method allows user to add a dashed polyline on map using set of user provided position
623
+ * @param viewer - Cesium Viewer object
624
+ * @param positions - Array of position in Cesium cartesian3
625
+ * @param config - Configuration object to control color & width of line
626
+ * @returns - Cesium Polyline entity
627
+ */
628
+ export const addPolyLine = (
629
+ viewer: Viewer,
630
+ positions: Array<Cartesian3>,
631
+ config?: DrawingConfig,
632
+ isDashed: boolean = true
633
+ ): Entity => {
634
+ if (config?.id && viewer.entities.getById(config.id)) {
635
+ viewer.entities.remove(viewer.entities.getById(config.id)!);
636
+ }
637
+
638
+ console.log(config?.clamp);
639
+
640
+ const polyline = viewer.entities.add({
641
+ id: config?.id,
642
+ polyline: {
643
+ // classificationType: Cesium.ClassificationType.CESIUM_3D_TILE,
644
+ depthFailMaterial: isDashed
645
+ ? new PolylineDashMaterialProperty({
646
+ color: config?.lineColor
647
+ ? Color.fromCssColorString(config.lineColor)
648
+ : Color.fromCssColorString("#FF0000"),
649
+ dashLength: 10,
650
+ })
651
+ : config?.lineColor
652
+ ? Color.fromCssColorString(config.lineColor)
653
+ : Color.fromCssColorString("#FF0000"),
654
+ positions,
655
+ width: config?.lineWidth ? config?.lineWidth : 3,
656
+
657
+ material: isDashed
658
+ ? new PolylineDashMaterialProperty({
659
+ color: config?.lineColor
660
+ ? Color.fromCssColorString(config.lineColor)
661
+ : Color.fromCssColorString("#FF0000"),
662
+ dashLength: 10,
663
+ })
664
+ : config?.lineColor
665
+ ? Color.fromCssColorString(config.lineColor)
666
+ : Color.fromCssColorString("#FF0000"),
667
+ clampToGround: !!config?.clamp,
668
+ },
669
+ });
670
+
671
+ (polyline as any).config = config;
672
+ return polyline;
673
+ };
674
+
675
+ /**
676
+ * This function allows user to add polygon on map
677
+ * @param viewer - Cesium Viewer object
678
+ * @param positions - Cesium Polygon Hierarchy
679
+ * @param config - Configuration Object to control fill color
680
+ * @returns Cesium Polygon entity
681
+ */
682
+ export const addPolygon = (
683
+ viewer: Viewer,
684
+ positions: any,
685
+ config?: DrawingConfig
686
+ ): Entity => {
687
+ if (config?.id && viewer.entities.getById(config?.id)) {
688
+ viewer.entities.remove(viewer.entities.getById(config?.id)!);
689
+ }
690
+
691
+ const polygon = viewer.entities.add({
692
+ id: config?.id,
693
+ polygon: {
694
+ hierarchy: positions,
695
+ perPositionHeight: !config?.clamp,
696
+ heightReference: config?.clamp
697
+ ? HeightReference.RELATIVE_TO_GROUND
698
+ : HeightReference.NONE,
699
+ outline: false,
700
+ fill: true,
701
+ outlineWidth: 15,
702
+ outlineColor: config?.strokeColor
703
+ ? Color.fromCssColorString(config.strokeColor)
704
+ : Color.BLACK,
705
+ material: config?.fillColor
706
+ ? Color.fromCssColorString(config.fillColor).withAlpha(
707
+ config.opacity ? config.opacity : 0.5
708
+ )
709
+ : Color.fromCssColorString("#FFC72C").withAlpha(
710
+ config?.opacity ? config.opacity : 0.5
711
+ ),
712
+ },
713
+ });
714
+
715
+ (polygon as any).config = config;
716
+
717
+ return polygon;
718
+ };
719
+
720
+ /**
721
+ * this function will add a label on map and return label entity
722
+ * @param viewer - Cesium viewer object
723
+ * @param config - LabelConfigByCartesian
724
+ * @returns - Cesium label entity
725
+ */
726
+ export const addLabel = (
727
+ viewer: Viewer,
728
+ config: LabelConfigByCartesian
729
+ ): Entity => {
730
+ if (config.id && viewer.entities.getById(config.id)) {
731
+ viewer.entities.remove(viewer.entities.getById(config.id)!);
732
+ }
733
+ const label = viewer.entities.add({
734
+ id: config.id,
735
+ position: config.position,
736
+ billboard: {
737
+ sizeInMeters: true,
738
+ },
739
+ label: {
740
+ show: true,
741
+ text: config.text,
742
+ font: `${config.size ? config.size : 12}px Roboto Condensed`,
743
+ fillColor: config.fillColor
744
+ ? Color.fromCssColorString(config.fillColor)
745
+ : Color.WHITE,
746
+ showBackground: config.isBackground !== false,
747
+ backgroundColor: config.backgroundColor
748
+ ? Color.fromCssColorString(config.backgroundColor).withAlpha(
749
+ config.opacity ? config.opacity : 0.5
750
+ )
751
+ : Color.BLACK,
752
+ backgroundPadding: new Cartesian2(7, 7),
753
+ horizontalOrigin: HorizontalOrigin.CENTER,
754
+ verticalOrigin: VerticalOrigin.BOTTOM,
755
+ outlineWidth: 10,
756
+ outlineColor: Color.BLACK,
757
+ style: LabelStyle.FILL,
758
+ disableDepthTestDistance: Number.POSITIVE_INFINITY,
759
+ },
760
+ });
761
+ return label;
762
+ };
763
+
764
+ /**
765
+ * This function allows user to get direction from one point to another point
766
+ * @param start - Start cartesian position
767
+ * @param end - End Cartesian position
768
+ * @returns - return cartesian of direction
769
+ */
770
+ export function getDirBetweenTwoCartesians(
771
+ start: Cartesian3,
772
+ end: Cartesian3
773
+ ): Cartesian3 | undefined {
774
+ const res = Cartesian3.subtract(end, start, new Cartesian3());
775
+ Cartesian3.normalize(res, res);
776
+ return res;
777
+ }
778
+
779
+ /**
780
+ * This Function allows user to get position after every half meter
781
+ * @param start - First cartesian
782
+ * @param end - Second Cartesian
783
+ * @returns - Array of cartesian after every 0.5 meter
784
+ */
785
+ export const getPositionsByFixDistance = (
786
+ start: Cartesian3,
787
+ end: Cartesian3
788
+ ): Array<Cartesian3> => {
789
+ const dir = getDirBetweenTwoCartesians(start, end)!;
790
+ const dist = Cartesian3.distance(start, end);
791
+ const interval = dist / 200;
792
+ const result: any = [];
793
+
794
+ for (let i = 0; dist - i >= interval; i += interval) {
795
+ const res = new Cartesian3();
796
+ Cartesian3.multiplyByScalar(dir, i, res);
797
+ Cartesian3.add(start, res, res);
798
+ result.push(res);
799
+ }
800
+ result.push(end);
801
+ return result;
802
+ };