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/.vscode/settings.json +3 -0
- package/dist/514.droneView.js +1 -1
- package/dist/800.droneView.js +1 -1
- package/dist/droneView.js +1 -1
- package/package.json +1 -1
- package/src/app.interface.ts +684 -0
- package/src/droneView.ts +1070 -0
- package/src/event.ts +359 -0
- package/src/layers/annotation.ts +175 -0
- package/src/layers/droneImages.ts +199 -0
- package/src/layers/editLine.ts +521 -0
- package/src/layers/editPoint.ts +345 -0
- package/src/layers/editPolygon.ts +511 -0
- package/src/layers/line.ts +210 -0
- package/src/layers/marker.ts +333 -0
- package/src/layers/marker3d.ts +326 -0
- package/src/layers/model.ts +253 -0
- package/src/layers/note.ts +333 -0
- package/src/layers/ortho.ts +76 -0
- package/src/layers/polygon.ts +218 -0
- package/src/measurement.ts +374 -0
- package/src/utility.ts +802 -0
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
|
+
}
|