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/event.ts ADDED
@@ -0,0 +1,359 @@
1
+ import { Cesium3DTileset, Entity, ScreenSpaceEventHandler, ScreenSpaceEventType } from 'cesium';
2
+ import CenterOfMasss from '@turf/center-of-mass';
3
+ import type { Point, SingleLocationFeature } from './app.interface';
4
+ import { cartesianToGeojson, cartesianToPoint } from './utility';
5
+ import type CesiumView from './droneView';
6
+
7
+ export default class EventManager {
8
+ mapObject: CesiumView;
9
+
10
+ handler: ScreenSpaceEventHandler;
11
+
12
+ layerEvents: any = [];
13
+
14
+ mouseGlobalPostion: Point;
15
+
16
+ mouseOverEntity: Entity | null;
17
+
18
+ isMouseOver: boolean = false;
19
+
20
+ constructor(mapObject: CesiumView) {
21
+ this.mapObject = mapObject;
22
+ this.handler = new ScreenSpaceEventHandler(
23
+ this.mapObject.viewer.scene.canvas
24
+ );
25
+ this.handler.setInputAction(
26
+ this.click.bind(this),
27
+ ScreenSpaceEventType.LEFT_CLICK
28
+ );
29
+ this.handler.setInputAction(
30
+ this.mouseMove.bind(this),
31
+ ScreenSpaceEventType.MOUSE_MOVE
32
+ );
33
+ }
34
+
35
+ addListener(event: string, layerId: string, callback: Function) {
36
+ if (this.layerEvents[event] === undefined) {
37
+ this.layerEvents[event] = [];
38
+ }
39
+
40
+ this.layerEvents[event][layerId] = callback;
41
+ }
42
+
43
+ /** Handle click event for all the layer */
44
+ click(event: any) {
45
+ if (this.layerEvents.click === undefined) {
46
+ return;
47
+ }
48
+
49
+ if (this.layerEvents.click !== undefined) {
50
+ if (this.mapObject.viewer.scene.pickPositionSupported) {
51
+ let result: any;
52
+
53
+ const position = this.mapObject.viewer.camera.pickEllipsoid(
54
+ event.position
55
+ );
56
+ let point: any;
57
+ if (position) {
58
+ point = cartesianToPoint(position);
59
+ } else {
60
+ const ray = this.mapObject.viewer.scene.camera.getPickRay(
61
+ event.position
62
+ )!;
63
+ const position2D = this.mapObject.viewer.scene.globe.pick(
64
+ ray,
65
+ this.mapObject.viewer.scene
66
+ )!;
67
+ point = cartesianToPoint(position2D);
68
+ }
69
+
70
+ const pickedObject = this.mapObject.viewer.scene.drillPick(
71
+ event.position
72
+ );
73
+ if (pickedObject.length > 0) {
74
+ const entity = pickedObject[0].id;
75
+
76
+ if (entity && entity instanceof Entity) {
77
+ this.mouseGlobalPostion = point;
78
+ result = {
79
+ id: pickedObject[0].id || entity.id,
80
+ lngLat: {
81
+ lat: point.lat,
82
+ lng: point.long,
83
+ height: point.height,
84
+ },
85
+ point: event.position,
86
+ target: this.mapObject.viewer,
87
+ type: 'click',
88
+ features: [
89
+ this.entityToSingleLocationFeature(entity),
90
+ ],
91
+ };
92
+ }
93
+
94
+ Object.keys(this.layerEvents.click).forEach(
95
+ (layerId: string) => {
96
+ if (entity && layerId === (entity as any).layerId) {
97
+ this.layerEvents.click[layerId](result);
98
+ }
99
+ }
100
+ );
101
+ } else {
102
+ result = {
103
+ lngLat: {
104
+ lat: point.lat,
105
+ lng: point.long,
106
+ height: point.height,
107
+ },
108
+ point: event.position,
109
+ target: this.mapObject.viewer,
110
+ type: 'click',
111
+ features: [],
112
+ };
113
+
114
+ Object.keys(this.layerEvents.click).forEach(
115
+ (layerId: string) => {
116
+ this.layerEvents.click[layerId](result);
117
+ }
118
+ );
119
+ }
120
+ }
121
+ }
122
+ }
123
+
124
+ mouseMove(event: any) {
125
+ if (!event.endPosition) {
126
+ return;
127
+ }
128
+
129
+ if (
130
+ !(
131
+ this.layerEvents.mousemove !== undefined ||
132
+ this.layerEvents.mouseenter !== undefined ||
133
+ this.layerEvents.mouseout !== undefined
134
+ )
135
+ ) {
136
+ return;
137
+ }
138
+
139
+ if (this.mapObject.viewer.scene.pickPositionSupported) {
140
+ let result: any;
141
+
142
+ const position = this.mapObject.viewer.camera.pickEllipsoid(
143
+ event.endPosition
144
+ );
145
+ let point: any;
146
+ if (position) {
147
+ point = cartesianToPoint(position);
148
+ } else {
149
+ const ray = this.mapObject.viewer.scene.camera.getPickRay(
150
+ event.endPosition
151
+ )!;
152
+ const position2D = this.mapObject.viewer.scene.globe.pick(
153
+ ray,
154
+ this.mapObject.viewer.scene
155
+ );
156
+
157
+ if (!position2D) {
158
+ return;
159
+ }
160
+
161
+ point = cartesianToPoint(position2D);
162
+ }
163
+
164
+ let pickedObject = this.mapObject.viewer.scene.drillPick(
165
+ event.endPosition
166
+ );
167
+
168
+ // console.log(pickedObject);
169
+
170
+ pickedObject = pickedObject.filter(object=> !(object?.primitive instanceof Cesium3DTileset));
171
+
172
+
173
+ if (pickedObject.length > 0) {
174
+ const entity: any = pickedObject[0].id;
175
+
176
+ if (entity && entity instanceof Entity) {
177
+ this.mouseGlobalPostion = point;
178
+ result = {
179
+ id:
180
+ ((entity as any).data && (entity as any).data.id) ||
181
+ entity.id,
182
+ lngLat: {
183
+ lat: point.lat,
184
+ lng: point.long,
185
+ height: point.height,
186
+ },
187
+ point: event.position,
188
+ target: this.mapObject.viewer,
189
+ type: 'mousemove',
190
+ features: [this.entityToSingleLocationFeature(entity)],
191
+ };
192
+
193
+ this.mouseOver(entity, result);
194
+
195
+ if (
196
+ this.layerEvents.mousemove !== undefined &&
197
+ this.isMouseOver &&
198
+ this.mouseOverEntity
199
+ ) {
200
+ Object.keys(this.layerEvents.mousemove).forEach(
201
+ (layerId: string) => {
202
+ if (layerId === (entity as any).layerId) {
203
+ if (
204
+ layerId ===
205
+ (this.mouseOverEntity as any).layerId
206
+ ) {
207
+ this.layerEvents.mousemove[layerId](
208
+ result
209
+ );
210
+ } else {
211
+ this.mouseOut();
212
+ this.mouseOver(entity, result);
213
+ }
214
+ }
215
+ }
216
+ );
217
+ }
218
+ }
219
+ } else {
220
+ this.mouseOut();
221
+ }
222
+ }
223
+ }
224
+
225
+ mouseOver(entity: any, event: any) {
226
+ if (
227
+ this.layerEvents.mouseenter !== undefined &&
228
+ !this.isMouseOver &&
229
+ !this.mouseOverEntity
230
+ ) {
231
+ Object.keys(this.layerEvents.mouseenter).forEach(
232
+ (layerId: string) => {
233
+ if (layerId === (entity as any).layerId) {
234
+ this.mouseOverEntity = entity;
235
+ this.isMouseOver = true;
236
+ this.layerEvents.mouseenter[layerId](event);
237
+ }
238
+ }
239
+ );
240
+ }
241
+ }
242
+
243
+ mouseOut() {
244
+ const self = this;
245
+ if (
246
+ self.layerEvents.mouseout !== undefined &&
247
+ self.isMouseOver &&
248
+ self.mouseOverEntity
249
+ ) {
250
+ Object.keys(self.layerEvents.mouseout).forEach(
251
+ (layerId: string) => {
252
+ if (
253
+ self.mouseOverEntity &&
254
+ self.isMouseOver &&
255
+ layerId === (self.mouseOverEntity as any).layerId
256
+ ) {
257
+ self.mouseOverEntity = null;
258
+ self.isMouseOver = false;
259
+ self.layerEvents.mouseout[layerId]();
260
+ }
261
+ }
262
+ );
263
+ }
264
+ }
265
+
266
+ // eslint-disable-next-line class-methods-use-this
267
+ private entityToSingleLocationFeature(
268
+ entity: Entity
269
+ ): SingleLocationFeature | undefined {
270
+ if (entity.billboard || entity.ellipse) {
271
+ const position: any = entity.position!.valueOf();
272
+ // eslint-disable-next-line no-underscore-dangle
273
+ const point = cartesianToPoint(position._value);
274
+ return {
275
+ geometry: 'Point',
276
+ lat: point.lat,
277
+ long: point.long,
278
+ height: point.height || 0,
279
+ properties: (entity as any).data,
280
+ };
281
+ }
282
+ if (entity.plane) {
283
+ const position: any = entity.position!.valueOf();
284
+ // eslint-disable-next-line no-underscore-dangle
285
+ const point = cartesianToPoint(position._value);
286
+ return {
287
+ geometry: 'Point',
288
+ lat: point.lat,
289
+ long: point.long,
290
+ height: point.height || 0,
291
+ properties: (entity as any).data,
292
+ };
293
+ }
294
+ if (entity.polyline) {
295
+ return {
296
+ geometry: 'Point',
297
+ lat: this.mouseGlobalPostion.lat,
298
+ long: this.mouseGlobalPostion.long,
299
+ height: this.mouseGlobalPostion.height || 0,
300
+ properties: (entity as any).data,
301
+ };
302
+ }
303
+ if (entity.polygon) {
304
+ const { positions } = (entity.polygon.hierarchy as any).valueOf();
305
+
306
+ if(!positions){
307
+ return undefined;
308
+ }
309
+
310
+ const center = CenterOfMasss(
311
+ cartesianToGeojson(positions, 'Polygon')
312
+ );
313
+
314
+ return {
315
+ geometry: 'Point',
316
+ lat: center.geometry.coordinates[1],
317
+ long: center.geometry.coordinates[0],
318
+ height: 0,
319
+ properties: (entity as any).data,
320
+ };
321
+ }
322
+
323
+ if (entity.cylinder) {
324
+ const position: any = entity.position!.valueOf();
325
+ if(!position){
326
+ return undefined;
327
+ }
328
+ // eslint-disable-next-line no-underscore-dangle
329
+ const point = cartesianToPoint(position._value);
330
+
331
+ return {
332
+ geometry: 'Point',
333
+ lat: point.lat,
334
+ long: point.long,
335
+ height: point.height || 0,
336
+ properties: (entity as any).data,
337
+ };
338
+ }
339
+
340
+ return undefined;
341
+ }
342
+
343
+ removeLayerListner(event: string, layerId: string) {
344
+ if (this.layerEvents[event] && this.layerEvents[event][layerId]) {
345
+ delete this.layerEvents[event][layerId];
346
+ }
347
+ }
348
+
349
+ removeLayerListners(layerId: string) {
350
+ Object.values(this.layerEvents).forEach((eventType: any) => {
351
+ Object.keys(eventType).forEach((layerid: string) => {
352
+ if (layerid === layerId) {
353
+ // eslint-disable-next-line no-param-reassign
354
+ delete eventType[layerid];
355
+ }
356
+ });
357
+ });
358
+ }
359
+ }
@@ -0,0 +1,175 @@
1
+ import {
2
+ CustomDataSource,
3
+ HeadingPitchRange,
4
+ Math as cMath,
5
+ Cartesian3,
6
+ Cartesian2,
7
+ } from "cesium";
8
+
9
+ import type CesiumView from "../droneView";
10
+
11
+ import { addPolyLineFilled, getPolygonEntity } from "../utility";
12
+
13
+ import {
14
+ AnnotationData,
15
+ Options,
16
+ PolygonData,
17
+ PolygonOptions,
18
+ } from "../app.interface";
19
+
20
+ /**
21
+ * Use this class to create a marker layer
22
+ * @extends {GenericLayer}
23
+ * @param {MapBox} mapObject - The mapbox map object
24
+ * @param {string} uniqueName - The unique name of the layer
25
+ * @param {PolygonData[]} data - The data to be used in the layer
26
+ * @param {PolygonOptions} options - The options for the layer (see {@link PolygonOptions})
27
+ */
28
+ export default class Annotation {
29
+ annotationLayerId: string;
30
+
31
+ uniqueName: string;
32
+
33
+ mapObject: CesiumView;
34
+
35
+ options: PolygonOptions;
36
+
37
+ layer: CustomDataSource;
38
+
39
+ data: AnnotationData[];
40
+
41
+ /**
42
+ * @param { CesiumView } mapObject map object
43
+ * @param { string }uniqueName string unique name for the layer
44
+ * @param { AnnotationData[] } data
45
+ * @param { Options } options
46
+ */
47
+ constructor(
48
+ mapObject: CesiumView,
49
+ uniqueName: string,
50
+ data: AnnotationData[],
51
+ options: Options
52
+ ) {
53
+ this.annotationLayerId = `annotation-${this.uniqueName}`;
54
+ this.data = data;
55
+ this.mapObject = mapObject;
56
+ this.uniqueName = uniqueName;
57
+ this.options = options;
58
+
59
+ this.buildLayer();
60
+ this.add(this.data).then(() => {
61
+ if (this.options.setBounds === undefined || this.options.setBounds) {
62
+ this.setBounds();
63
+ }
64
+ });
65
+ }
66
+
67
+ /** To initialize layer */
68
+ public buildLayer(): void {
69
+ if (
70
+ this.mapObject.viewer.dataSources.getByName(
71
+ "annotation-" + this.uniqueName
72
+ )
73
+ ) {
74
+ this.mapObject.viewer.dataSources.remove(
75
+ this.mapObject.viewer.dataSources.getByName(
76
+ "annotation-" + this.uniqueName
77
+ )[0],
78
+ true
79
+ );
80
+ }
81
+ this.layer = new CustomDataSource("annotation-" + this.uniqueName);
82
+
83
+ this.mapObject.viewer.dataSources.add(this.layer);
84
+ }
85
+
86
+ /** To add layer on map */
87
+ public add(data: AnnotationData[]) {
88
+ const self = this;
89
+
90
+ return new Promise<void>((resolve) => {
91
+ self.addToMap(data).then(() => {
92
+ this.mapObject.viewer.dataSources.add(this.layer);
93
+
94
+ this.mapObject.viewer.scene.requestRender();
95
+ resolve();
96
+ });
97
+ });
98
+ }
99
+
100
+ /**
101
+ * Add data on map
102
+ * @param { AnnotationData } data
103
+ */
104
+ public addToMap(data: AnnotationData[]) {
105
+ return new Promise<void>((resolve) => {
106
+ const cartesians: any = [];
107
+
108
+ data.forEach((point: any) => {
109
+ cartesians.push(Cartesian3.fromDegrees(point.point[0], point.point[1]));
110
+ });
111
+
112
+ this.mapObject.viewer.scene
113
+ .clampToHeightMostDetailed(cartesians)
114
+ .then((pos) => {
115
+ pos.forEach((position: Cartesian3, i: number) => {
116
+
117
+ const svg = `
118
+ <svg width="200" height="150" xmlns="http://www.w3.org/2000/svg">
119
+ <!-- Rectangle -->
120
+ <rect x="50" y="30" width="100" height="60" fill="#000000" rx="5" opacity="0.85" stroke="${data[i].properties.color}" stroke-width="2" />
121
+
122
+ <!-- Text -->
123
+ <text x="100" y="65" text-anchor="middle" font-size="13" fill="#ffffff">${data[i].properties.name}</text>
124
+
125
+ <!-- Vertical Line -->
126
+ <line x1="100" y1="90" x2="100" y2="140" stroke="${data[i].properties.color}" stroke-width="2" />
127
+
128
+ <!-- Arrowhead -->
129
+ <polygon points="95,135 100,145 105,135" fill="${data[i].properties.color}" />
130
+ </svg>
131
+ `;
132
+
133
+ const point = {
134
+ position: position,
135
+ billboard: {
136
+ image: `data:image/svg+xml;base64,${window.btoa(svg)}`,
137
+ pixelOffset : new Cartesian2(0,-90),
138
+ },
139
+ };
140
+
141
+ this.layer.entities.add(point);
142
+ });
143
+ });
144
+ });
145
+ }
146
+
147
+ /** to set map bouds fit with layer data */
148
+ public setBounds(): void {
149
+ const time = this.options.setBoundsInstant ? 0 : undefined;
150
+ this.mapObject.viewer.flyTo(this.layer.entities, {
151
+ duration: time,
152
+ offset: new HeadingPitchRange(
153
+ cMath.toRadians(this.mapObject.viewer.camera.heading),
154
+ -Math.PI / 2,
155
+ 0
156
+ ),
157
+ });
158
+ }
159
+
160
+ /** Remove layer from map and destroy layer */
161
+ public remove(): void {
162
+ this.mapObject.viewer.dataSources.remove(this.layer, true);
163
+ this.mapObject.viewer.scene.requestRender();
164
+ }
165
+
166
+ show() {
167
+ this.layer.entities.show = true;
168
+ this.mapObject.viewer.scene.requestRender();
169
+ }
170
+
171
+ hide() {
172
+ this.layer.entities.show = false;
173
+ this.mapObject.viewer.scene.requestRender();
174
+ }
175
+ }