@vcmap/viewshed 3.0.3 → 4.0.0
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/CHANGELOG.md +10 -0
- package/dist/index.js +1076 -1078
- package/package.json +25 -24
- package/src/ViewshedConfigEditor.vue +32 -34
- package/src/ViewshedWindow.vue +152 -160
- package/src/{index.js → index.ts} +63 -68
- package/src/util/toolboxHelper.ts +183 -0
- package/src/util/{windowHelper.js → windowHelper.ts} +28 -27
- package/src/{viewshed.js → viewshed.ts} +159 -202
- package/src/{viewshedCategory.js → viewshedCategory.ts} +67 -60
- package/src/{viewshedInteraction.js → viewshedInteraction.ts} +20 -14
- package/src/{viewshedManager.js → viewshedManager.ts} +130 -97
- package/src/{viewshedPrimitive.js → viewshedPrimitive.ts} +34 -19
- package/src/util/toolboxHelper.js +0 -132
|
@@ -1,4 +1,10 @@
|
|
|
1
|
+
import type { Ref, ShallowRef } from 'vue';
|
|
1
2
|
import { nextTick, ref, shallowRef } from 'vue';
|
|
3
|
+
import type {
|
|
4
|
+
EditFeaturesSession,
|
|
5
|
+
EditGeometrySession,
|
|
6
|
+
FeatureAtPixelInteraction,
|
|
7
|
+
} from '@vcmap/core';
|
|
2
8
|
import {
|
|
3
9
|
CesiumMap,
|
|
4
10
|
EventType,
|
|
@@ -12,73 +18,96 @@ import {
|
|
|
12
18
|
wgs84Projection,
|
|
13
19
|
} from '@vcmap/core';
|
|
14
20
|
import { HeightReference } from '@vcmap-cesium/engine';
|
|
21
|
+
import { getLogger } from '@vcsuite/logger';
|
|
15
22
|
import { Feature } from 'ol';
|
|
16
23
|
import { Point } from 'ol/geom';
|
|
17
24
|
import { Style } from 'ol/style.js';
|
|
18
25
|
import { unByKey } from 'ol/Observable.js';
|
|
26
|
+
import type { Coordinate } from 'ol/coordinate.js';
|
|
27
|
+
import type { VcsUiApp } from '@vcmap/ui';
|
|
28
|
+
import { name } from '../package.json';
|
|
29
|
+
import type { ViewshedTypes } from './viewshed.js';
|
|
19
30
|
import Viewshed from './viewshed.js';
|
|
20
31
|
import ViewshedInteraction from './viewshedInteraction.js';
|
|
32
|
+
import type { ViewshedPluginOptions } from './index.js';
|
|
33
|
+
import type { ViewshedCategoryHelper } from './viewshedCategory.js';
|
|
21
34
|
|
|
22
35
|
/**
|
|
23
|
-
*
|
|
24
|
-
* @property {import("vue").ShallowRef<import("./viewshed.js").default | null>} currentViewshed The current viewshed, that is displayed in the map.
|
|
25
|
-
* @property {import("vue").Ref<null | boolean>} currentIsPersisted Whether current viewshed is persisted or not.
|
|
26
|
-
* @property {import("vue").Ref<import("@vcmap/core").EditFeaturesSession | import("@vcmap/core").EditGeometrySession | null>} currentEditSession The current edit session, when in MOVE mode. Read only.
|
|
27
|
-
* @property {import("vue").ShallowRef<import("ol").Feature[]>} currentFeatures The feature that is created for feature/geometry editing in {@link moveCurrentViewshed}. Needed to match the EditorManager API from the UI.
|
|
28
|
-
* @property {function(import("./viewshed.js").ViewshedTypes): void} createViewshed Creates a new viewshed and stops a running create process.
|
|
29
|
-
* @property {function(import("./viewshed.js").default):void} viewViewshed Changes mode to VIEW for passed Viewshed.
|
|
30
|
-
* @property {function(import("./viewshed.js").default):void} editViewshed Changes mode to EDIT for passed Viewshed.
|
|
31
|
-
* @property {function(boolean):void} moveCurrentViewshed Changes mode to MOVE. If heightMode is ABSOLUTE a translate EditFeatureSession is started, if RELATIVE a EditGeometrySession is started.
|
|
32
|
-
* @property {function():void} setupMultiSelect Changes mode to MULTI_SELECT.
|
|
33
|
-
* @property {function():void} persistCurrent Adds current viewshed to the category collection.
|
|
34
|
-
* @property {import("vue").Ref<ViewshedPluginModes | null>} mode Viewshed mode. Should only be used to watch and get the mode, not to set the mode.
|
|
35
|
-
* @property {import("vue").Ref<HeightModes>} heightMode The height mode the viewshed plugin is currently in. Use changeHeightMode to change height mode when there is a currentViewshed.
|
|
36
|
-
* @property {function():void} changeHeightMode Sets heightMode and calculates the Z value according to the input heightMode.
|
|
37
|
-
* @property {function():void} placeCurrentFeaturesOnTerrain Places viewshed on terrain. Only available when in 'move' mode and height mode 'absolute'.
|
|
38
|
-
* @property {function(boolean=):void} stop Stops the creation and removes current viewshed.
|
|
39
|
-
* @property {function():void} destroy Destroys the viewshed manager.
|
|
40
|
-
*/
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* @enum {string}
|
|
44
|
-
* @property {string} ABSOLUTE Absolute
|
|
45
|
-
* @property {string} RELATIVE Relative to ground
|
|
36
|
+
* ViewshedManager interface for managing viewsheds
|
|
46
37
|
*/
|
|
47
|
-
export
|
|
48
|
-
|
|
49
|
-
|
|
38
|
+
export type ViewshedManager = {
|
|
39
|
+
/** The current viewshed, that is displayed in the map. */
|
|
40
|
+
currentViewshed: ShallowRef<Viewshed | null>;
|
|
41
|
+
/** Whether current viewshed is persisted or not. */
|
|
42
|
+
currentIsPersisted: Ref<null | boolean>;
|
|
43
|
+
/** The current edit session, when in MOVE mode. Read only. */
|
|
44
|
+
currentEditSession: Ref<EditFeaturesSession | EditGeometrySession | null>;
|
|
45
|
+
/** The feature that is created for feature/geometry editing in moveCurrentViewshed. Needed to match the EditorManager API from the UI. */
|
|
46
|
+
currentFeatures: ShallowRef<Feature[]>;
|
|
47
|
+
/** Creates a new viewshed and stops a running create process. */
|
|
48
|
+
createViewshed(viewshedType: ViewshedTypes): Promise<void>;
|
|
49
|
+
/** Changes mode to VIEW for passed Viewshed. */
|
|
50
|
+
viewViewshed(viewshed: Viewshed): void;
|
|
51
|
+
/** Changes mode to EDIT for passed Viewshed. */
|
|
52
|
+
editViewshed(viewshed: Viewshed): void;
|
|
53
|
+
/** Changes mode to MOVE. If heightMode is ABSOLUTE a translate EditFeatureSession is started, if RELATIVE a EditGeometrySession is started. */
|
|
54
|
+
moveCurrentViewshed(activate: boolean): void;
|
|
55
|
+
/** Changes mode to MULTI_SELECT. */
|
|
56
|
+
setupMultiSelect(): void;
|
|
57
|
+
/** Adds current viewshed to the category collection. */
|
|
58
|
+
persistCurrent(): void;
|
|
59
|
+
/** Viewshed mode. Should only be used to watch and get the mode, not to set the mode. */
|
|
60
|
+
mode: Ref<ViewshedPluginModes | null>;
|
|
61
|
+
/** The height mode the viewshed plugin is currently in. Use changeHeightMode to change height mode when there is a currentViewshed. */
|
|
62
|
+
heightMode: Ref<HeightModes>;
|
|
63
|
+
/** Sets heightMode and calculates the Z value according to the input heightMode. */
|
|
64
|
+
changeHeightMode(newHeightMode: HeightModes): void;
|
|
65
|
+
/** Places viewshed on terrain. Only available when in 'move' mode and height mode 'absolute'. */
|
|
66
|
+
placeCurrentFeaturesOnTerrain(): Promise<void>;
|
|
67
|
+
/** Stops the creation and removes current viewshed. */
|
|
68
|
+
stop(clear?: boolean): void;
|
|
69
|
+
/** Destroys the viewshed manager. */
|
|
70
|
+
destroy(): void;
|
|
50
71
|
};
|
|
51
72
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
*/
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
VIEW
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
73
|
+
export enum HeightModes {
|
|
74
|
+
ABSOLUTE = 'absolute',
|
|
75
|
+
RELATIVE = 'relative',
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export enum ViewshedPluginModes {
|
|
79
|
+
/** Window with instructions is open, map interaction for setting viewshed is active */
|
|
80
|
+
CREATE = 'create',
|
|
81
|
+
/** Viewshed is visible in map, window is closed */
|
|
82
|
+
VIEW = 'view',
|
|
83
|
+
/** Viewshed is visible in map, window is open */
|
|
84
|
+
EDIT = 'edit',
|
|
85
|
+
/** Viewshed is visible in map, window is open, move interaction is active */
|
|
86
|
+
MOVE = 'move',
|
|
87
|
+
MULTI_SELECT = 'multiSelect',
|
|
88
|
+
}
|
|
66
89
|
|
|
67
90
|
/** The default height offset of a viewshed. */
|
|
68
91
|
export const defaultHeightOffset = 1.8;
|
|
69
92
|
|
|
70
93
|
/**
|
|
71
94
|
* Creates layer with feature at a specified position.
|
|
72
|
-
* @param
|
|
73
|
-
* @returns
|
|
95
|
+
* @param Position for feature.
|
|
96
|
+
* @returns A layer and the added feature at the passed position.
|
|
74
97
|
*/
|
|
75
|
-
function createLayerWithFeature(position) {
|
|
98
|
+
function createLayerWithFeature(position: Coordinate): {
|
|
99
|
+
layer: VectorLayer;
|
|
100
|
+
feature: Feature;
|
|
101
|
+
destroy: () => void;
|
|
102
|
+
} {
|
|
76
103
|
const layer = new VectorLayer({
|
|
77
104
|
projection: wgs84Projection.toJSON(),
|
|
78
105
|
zIndex: maxZIndex - 1,
|
|
79
106
|
});
|
|
80
107
|
markVolatile(layer);
|
|
81
|
-
layer.activate()
|
|
108
|
+
layer.activate().catch((e: unknown) => {
|
|
109
|
+
getLogger(name).error('Failed to activate layer', String(e));
|
|
110
|
+
});
|
|
82
111
|
|
|
83
112
|
const feature = new Feature(new Point(position));
|
|
84
113
|
// hide feature
|
|
@@ -89,7 +118,7 @@ function createLayerWithFeature(position) {
|
|
|
89
118
|
return {
|
|
90
119
|
layer,
|
|
91
120
|
feature,
|
|
92
|
-
destroy() {
|
|
121
|
+
destroy(): void {
|
|
93
122
|
feature.dispose();
|
|
94
123
|
layer.destroy();
|
|
95
124
|
},
|
|
@@ -101,10 +130,13 @@ function createLayerWithFeature(position) {
|
|
|
101
130
|
* In case of heightMode ABSOLUTE the eventType is CLICKMOVE, and therefore sets the viewshed on top of terrain AND buildings.
|
|
102
131
|
* In case of heightMode RELATIVE the eventType is NONE which means viewshed is only set on top of terrain.
|
|
103
132
|
* Run featureInteraction.setActive() to reset eventType, pickPosition and pullPickedPosition.
|
|
104
|
-
* @param
|
|
105
|
-
* @param
|
|
133
|
+
* @param featureInteraction The featureInteraction of the maps eventHandler
|
|
134
|
+
* @param heightMode The current height mode of the viewshed plugin
|
|
106
135
|
*/
|
|
107
|
-
function updateFeatureInteraction(
|
|
136
|
+
function updateFeatureInteraction(
|
|
137
|
+
featureInteraction: FeatureAtPixelInteraction,
|
|
138
|
+
heightMode: HeightModes,
|
|
139
|
+
): void {
|
|
108
140
|
const eventType =
|
|
109
141
|
heightMode === HeightModes.ABSOLUTE ? EventType.CLICKMOVE : EventType.NONE;
|
|
110
142
|
featureInteraction.setActive(eventType);
|
|
@@ -112,33 +144,27 @@ function updateFeatureInteraction(featureInteraction, heightMode) {
|
|
|
112
144
|
featureInteraction.pullPickedPosition = 1.8;
|
|
113
145
|
}
|
|
114
146
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
/** @type {import("vue").ShallowRef<import("./viewshed.js").default | null>} */
|
|
124
|
-
const currentViewshed = shallowRef(null);
|
|
125
|
-
/** @type {import("vue").Ref<boolean | null>} */
|
|
126
|
-
const currentIsPersisted = ref(null);
|
|
127
|
-
/** @type {import("vue").Ref<ViewshedPluginModes | null>} */
|
|
128
|
-
const mode = ref(null);
|
|
147
|
+
export default function createViewshedManager(
|
|
148
|
+
app: VcsUiApp,
|
|
149
|
+
config: ViewshedPluginOptions,
|
|
150
|
+
categoryHelper: ViewshedCategoryHelper,
|
|
151
|
+
): ViewshedManager {
|
|
152
|
+
const currentViewshed = shallowRef<Viewshed | null>(null);
|
|
153
|
+
const currentIsPersisted = ref<boolean | null>(null);
|
|
154
|
+
const mode = ref<ViewshedPluginModes | null>(null);
|
|
129
155
|
const heightMode = ref(HeightModes.ABSOLUTE);
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
156
|
+
const currentEditSession = shallowRef<
|
|
157
|
+
EditFeaturesSession | EditGeometrySession | null
|
|
158
|
+
>(null);
|
|
159
|
+
let removeInteraction = (): void => {};
|
|
133
160
|
/**
|
|
134
161
|
* The feature that is created for feature/geometry editing in {@link moveCurrentViewshed}. Needed to match the EditorManager API from the UI.
|
|
135
|
-
* @type {import("vue").ShallowRef<import("ol").Feature[]>}
|
|
136
162
|
*/
|
|
137
|
-
const currentFeatures = shallowRef([]);
|
|
163
|
+
const currentFeatures = shallowRef<Feature[]>([]);
|
|
138
164
|
|
|
139
|
-
let shadowMapChangedListener = () => {};
|
|
165
|
+
let shadowMapChangedListener = (): void => {};
|
|
140
166
|
|
|
141
|
-
function deactivateCurrentViewshed() {
|
|
167
|
+
function deactivateCurrentViewshed(): void {
|
|
142
168
|
if (currentIsPersisted.value && currentViewshed.value) {
|
|
143
169
|
currentViewshed.value.deactivate();
|
|
144
170
|
categoryHelper.setVisibility(currentViewshed.value.name, false);
|
|
@@ -149,9 +175,9 @@ export default function createViewshedManager(app, config, categoryHelper) {
|
|
|
149
175
|
|
|
150
176
|
/**
|
|
151
177
|
* Stops the viewshed operation.
|
|
152
|
-
*
|
|
178
|
+
* Indicates whether to clear the selection.
|
|
153
179
|
*/
|
|
154
|
-
function stop(clear = true) {
|
|
180
|
+
function stop(clear = true): void {
|
|
155
181
|
shadowMapChangedListener();
|
|
156
182
|
removeInteraction();
|
|
157
183
|
deactivateCurrentViewshed();
|
|
@@ -165,9 +191,8 @@ export default function createViewshedManager(app, config, categoryHelper) {
|
|
|
165
191
|
|
|
166
192
|
/**
|
|
167
193
|
* activates a viewshed, and adds a Listener to the shadowMapChangedEvent to deactivate the viewshed plugin.
|
|
168
|
-
* @param {Viewshed} viewshed
|
|
169
194
|
*/
|
|
170
|
-
function activateViewshed(viewshed) {
|
|
195
|
+
function activateViewshed(viewshed: Viewshed): void {
|
|
171
196
|
shadowMapChangedListener();
|
|
172
197
|
// deactivate existing Viewsheds
|
|
173
198
|
deactivateCurrentViewshed();
|
|
@@ -183,7 +208,7 @@ export default function createViewshedManager(app, config, categoryHelper) {
|
|
|
183
208
|
}
|
|
184
209
|
}
|
|
185
210
|
|
|
186
|
-
async function createViewshed(viewshedType) {
|
|
211
|
+
async function createViewshed(viewshedType: ViewshedTypes): Promise<void> {
|
|
187
212
|
stop();
|
|
188
213
|
await nextTick(); // so the viewshedWindow is closed with mode === null and not CREATE
|
|
189
214
|
|
|
@@ -202,7 +227,7 @@ export default function createViewshedManager(app, config, categoryHelper) {
|
|
|
202
227
|
});
|
|
203
228
|
activateViewshed(viewshed);
|
|
204
229
|
// setup viewshed create interaction
|
|
205
|
-
const interaction = new ViewshedInteraction(currentViewshed.value);
|
|
230
|
+
const interaction = new ViewshedInteraction(currentViewshed.value!);
|
|
206
231
|
|
|
207
232
|
interaction.finished.addEventListener(() => {
|
|
208
233
|
removeInteraction();
|
|
@@ -226,18 +251,18 @@ export default function createViewshedManager(app, config, categoryHelper) {
|
|
|
226
251
|
updateFeatureInteraction(featureInteraction, HeightModes.ABSOLUTE); // always set second click (lookAt) absolute
|
|
227
252
|
});
|
|
228
253
|
|
|
229
|
-
removeInteraction = () => {
|
|
254
|
+
removeInteraction = (): void => {
|
|
230
255
|
removeExclusiveInteraction();
|
|
231
256
|
interaction.destroy();
|
|
232
257
|
featureInteraction.setActive(); // resets featureInteractions eventType, pickPosition and pullPickedPosition
|
|
233
258
|
|
|
234
|
-
removeInteraction = () => {};
|
|
259
|
+
removeInteraction = (): void => {};
|
|
235
260
|
};
|
|
236
261
|
|
|
237
262
|
mode.value = ViewshedPluginModes.CREATE;
|
|
238
263
|
}
|
|
239
264
|
|
|
240
|
-
function moveCurrentViewshed(activate) {
|
|
265
|
+
function moveCurrentViewshed(activate: boolean): void {
|
|
241
266
|
if (currentViewshed.value && activate) {
|
|
242
267
|
removeInteraction();
|
|
243
268
|
|
|
@@ -265,9 +290,7 @@ export default function createViewshedManager(app, config, categoryHelper) {
|
|
|
265
290
|
const geometryListenerKey = feature.getGeometry()?.on('change', () => {
|
|
266
291
|
if (currentViewshed.value) {
|
|
267
292
|
currentViewshed.value.position = Projection.mercatorToWgs84(
|
|
268
|
-
|
|
269
|
-
feature.getGeometry()
|
|
270
|
-
).getCoordinates(),
|
|
293
|
+
(feature as Feature<Point>).getGeometry()!.getCoordinates(),
|
|
271
294
|
);
|
|
272
295
|
} else {
|
|
273
296
|
stop();
|
|
@@ -276,8 +299,8 @@ export default function createViewshedManager(app, config, categoryHelper) {
|
|
|
276
299
|
|
|
277
300
|
mode.value = ViewshedPluginModes.MOVE;
|
|
278
301
|
|
|
279
|
-
removeInteraction = () => {
|
|
280
|
-
removeInteraction = () => {}; // needs to be before currentEditSession.value.stop(), otherwise recursion
|
|
302
|
+
removeInteraction = (): void => {
|
|
303
|
+
removeInteraction = (): void => {}; // needs to be before currentEditSession.value.stop(), otherwise recursion
|
|
281
304
|
|
|
282
305
|
if (geometryListenerKey) {
|
|
283
306
|
unByKey(geometryListenerKey);
|
|
@@ -296,10 +319,11 @@ export default function createViewshedManager(app, config, categoryHelper) {
|
|
|
296
319
|
|
|
297
320
|
/**
|
|
298
321
|
* Changes the mode and the current viewshed. Only works with viewshedMode EDIT and VIEW.
|
|
299
|
-
* @param {ViewshedPluginModes} viewshedMode
|
|
300
|
-
* @param {import("./viewshed.js").default} viewshed
|
|
301
322
|
*/
|
|
302
|
-
function changeMode(
|
|
323
|
+
function changeMode(
|
|
324
|
+
viewshedMode: ViewshedPluginModes,
|
|
325
|
+
viewshed: Viewshed,
|
|
326
|
+
): void {
|
|
303
327
|
removeInteraction();
|
|
304
328
|
if (currentViewshed.value !== viewshed) {
|
|
305
329
|
activateViewshed(viewshed);
|
|
@@ -331,7 +355,7 @@ export default function createViewshedManager(app, config, categoryHelper) {
|
|
|
331
355
|
viewshedWindow.state.headerTitle = title;
|
|
332
356
|
}
|
|
333
357
|
}),
|
|
334
|
-
categoryHelper.visibilityChanged.addEventListener((item) => {
|
|
358
|
+
categoryHelper.visibilityChanged.addEventListener(({ item }) => {
|
|
335
359
|
const isCurrentlyVisible = currentViewshed.value?.name === item.name;
|
|
336
360
|
if (isCurrentlyVisible) {
|
|
337
361
|
stop();
|
|
@@ -343,7 +367,7 @@ export default function createViewshedManager(app, config, categoryHelper) {
|
|
|
343
367
|
}),
|
|
344
368
|
];
|
|
345
369
|
|
|
346
|
-
function changeHeightMode(newHeightMode) {
|
|
370
|
+
function changeHeightMode(newHeightMode: HeightModes): void {
|
|
347
371
|
if (newHeightMode === heightMode.value || !currentViewshed.value) {
|
|
348
372
|
return;
|
|
349
373
|
}
|
|
@@ -365,7 +389,7 @@ export default function createViewshedManager(app, config, categoryHelper) {
|
|
|
365
389
|
const { position: currentPosition, heightOffset: currentHeightOffset } =
|
|
366
390
|
currentViewshed.value;
|
|
367
391
|
if (newHeightMode === HeightModes.RELATIVE) {
|
|
368
|
-
|
|
392
|
+
(app.maps.activeMap as CesiumMap)
|
|
369
393
|
.getHeightFromTerrain([Projection.wgs84ToMercator(currentPosition)])
|
|
370
394
|
.then((value) => {
|
|
371
395
|
const newPosition = Projection.mercatorToWgs84(value[0]);
|
|
@@ -375,6 +399,12 @@ export default function createViewshedManager(app, config, categoryHelper) {
|
|
|
375
399
|
currentPosition[2] - newPosition[2];
|
|
376
400
|
currentViewshed.value.position = newPosition;
|
|
377
401
|
}
|
|
402
|
+
})
|
|
403
|
+
.catch((e: unknown) => {
|
|
404
|
+
getLogger(name).error(
|
|
405
|
+
'Failed to get height from terrain',
|
|
406
|
+
String(e),
|
|
407
|
+
);
|
|
378
408
|
});
|
|
379
409
|
} else {
|
|
380
410
|
currentViewshed.value.position = [
|
|
@@ -393,18 +423,19 @@ export default function createViewshedManager(app, config, categoryHelper) {
|
|
|
393
423
|
currentEditSession,
|
|
394
424
|
currentFeatures,
|
|
395
425
|
createViewshed,
|
|
396
|
-
viewViewshed(viewshed) {
|
|
426
|
+
viewViewshed(viewshed): void {
|
|
397
427
|
changeMode(ViewshedPluginModes.VIEW, viewshed);
|
|
398
428
|
},
|
|
399
|
-
editViewshed(viewshed) {
|
|
429
|
+
editViewshed(viewshed): void {
|
|
400
430
|
changeMode(ViewshedPluginModes.EDIT, viewshed);
|
|
401
431
|
if (currentIsPersisted.value) {
|
|
402
432
|
// makes sure the editor window is open, if it is not triggered by a new selection but e.g. the tristate button
|
|
403
433
|
categoryHelper.setSelection(viewshed.name);
|
|
404
|
-
|
|
434
|
+
// FIXME does not exist
|
|
435
|
+
// categoryHelper.collectionComponent.openEditorWindow(viewshed);
|
|
405
436
|
}
|
|
406
437
|
},
|
|
407
|
-
persistCurrent() {
|
|
438
|
+
persistCurrent(): void {
|
|
408
439
|
if (currentViewshed.value) {
|
|
409
440
|
categoryHelper.add(currentViewshed.value);
|
|
410
441
|
currentIsPersisted.value = true;
|
|
@@ -413,7 +444,7 @@ export default function createViewshedManager(app, config, categoryHelper) {
|
|
|
413
444
|
}
|
|
414
445
|
},
|
|
415
446
|
moveCurrentViewshed,
|
|
416
|
-
setupMultiSelect() {
|
|
447
|
+
setupMultiSelect(): void {
|
|
417
448
|
removeInteraction();
|
|
418
449
|
mode.value = ViewshedPluginModes.MULTI_SELECT;
|
|
419
450
|
deactivateCurrentViewshed();
|
|
@@ -422,7 +453,7 @@ export default function createViewshedManager(app, config, categoryHelper) {
|
|
|
422
453
|
mode,
|
|
423
454
|
heightMode,
|
|
424
455
|
changeHeightMode,
|
|
425
|
-
async placeCurrentFeaturesOnTerrain() {
|
|
456
|
+
async placeCurrentFeaturesOnTerrain(): Promise<void> {
|
|
426
457
|
if (
|
|
427
458
|
currentViewshed.value &&
|
|
428
459
|
currentEditSession.value?.type === SessionType.EDIT_FEATURES &&
|
|
@@ -438,9 +469,11 @@ export default function createViewshedManager(app, config, categoryHelper) {
|
|
|
438
469
|
}
|
|
439
470
|
},
|
|
440
471
|
stop,
|
|
441
|
-
destroy() {
|
|
472
|
+
destroy(): void {
|
|
442
473
|
stop();
|
|
443
|
-
categoryListener.forEach((l) =>
|
|
474
|
+
categoryListener.forEach((l) => {
|
|
475
|
+
l();
|
|
476
|
+
});
|
|
444
477
|
},
|
|
445
478
|
};
|
|
446
479
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Camera } from '@vcmap-cesium/engine';
|
|
1
2
|
import {
|
|
2
3
|
Color,
|
|
3
4
|
ColorGeometryInstanceAttribute,
|
|
@@ -9,33 +10,45 @@ import {
|
|
|
9
10
|
SphereOutlineGeometry,
|
|
10
11
|
Transforms,
|
|
11
12
|
} from '@vcmap-cesium/engine';
|
|
13
|
+
import type { VcsCameraPrimitiveOptions } from '@vcmap/core';
|
|
12
14
|
import { VcsCameraPrimitive } from '@vcmap/core';
|
|
13
15
|
|
|
14
|
-
/**
|
|
15
|
-
* @type {import("@vcmap-cesium/engine").Color}
|
|
16
|
-
*/
|
|
17
16
|
const scratchColor = new Color();
|
|
18
|
-
/**
|
|
19
|
-
* @type {import("@vcmap-cesium/engine").Matrix4}
|
|
20
|
-
*/
|
|
21
17
|
const scratchMatrix = new Matrix4();
|
|
22
18
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
* @extends VcsCameraPrimitive
|
|
26
|
-
*/
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
20
|
+
// @ts-ignore
|
|
27
21
|
class ViewshedCameraPrimitive extends VcsCameraPrimitive {
|
|
28
|
-
|
|
22
|
+
static get className(): string {
|
|
23
|
+
return 'ViewshedCameraPrimitive';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
spot: boolean;
|
|
27
|
+
|
|
28
|
+
private _allowPicking: boolean;
|
|
29
|
+
|
|
30
|
+
private _color: Color = Color.WHITE;
|
|
31
|
+
|
|
32
|
+
private _camera: Camera;
|
|
33
|
+
|
|
34
|
+
private _planesPrimitives: Primitive[] = [];
|
|
35
|
+
|
|
36
|
+
private _outlinePrimitives: Primitive[] = [];
|
|
37
|
+
|
|
38
|
+
constructor(
|
|
39
|
+
options: VcsCameraPrimitiveOptions & {
|
|
40
|
+
spot: boolean;
|
|
41
|
+
camera: Camera;
|
|
42
|
+
allowPicking: boolean;
|
|
43
|
+
},
|
|
44
|
+
) {
|
|
29
45
|
super(options);
|
|
30
|
-
/** @type {boolean} */
|
|
31
46
|
this.spot = options.spot;
|
|
47
|
+
this._camera = options.camera;
|
|
48
|
+
this._allowPicking = options.allowPicking;
|
|
32
49
|
}
|
|
33
50
|
|
|
34
|
-
|
|
35
|
-
* Updates the camera primitive.
|
|
36
|
-
* @param {unknown} frameState
|
|
37
|
-
*/
|
|
38
|
-
update(frameState) {
|
|
51
|
+
update(frameState: unknown): void {
|
|
39
52
|
if (!this.show) {
|
|
40
53
|
return;
|
|
41
54
|
}
|
|
@@ -50,7 +63,7 @@ class ViewshedCameraPrimitive extends VcsCameraPrimitive {
|
|
|
50
63
|
scratchMatrix,
|
|
51
64
|
);
|
|
52
65
|
planesPrimitives[0] = new Primitive({
|
|
53
|
-
allowPicking: this.
|
|
66
|
+
allowPicking: this._allowPicking,
|
|
54
67
|
geometryInstances: new GeometryInstance({
|
|
55
68
|
geometry: new SphereGeometry({
|
|
56
69
|
radius: 2,
|
|
@@ -70,7 +83,7 @@ class ViewshedCameraPrimitive extends VcsCameraPrimitive {
|
|
|
70
83
|
});
|
|
71
84
|
|
|
72
85
|
outlinePrimitives[0] = new Primitive({
|
|
73
|
-
allowPicking: this.
|
|
86
|
+
allowPicking: this._allowPicking,
|
|
74
87
|
geometryInstances: new GeometryInstance({
|
|
75
88
|
geometry: new SphereOutlineGeometry({
|
|
76
89
|
radius: 2,
|
|
@@ -89,7 +102,9 @@ class ViewshedCameraPrimitive extends VcsCameraPrimitive {
|
|
|
89
102
|
}
|
|
90
103
|
const { length } = planesPrimitives;
|
|
91
104
|
for (let i = 0; i < length; ++i) {
|
|
105
|
+
// @ts-expect-error update
|
|
92
106
|
outlinePrimitives[i].update(frameState);
|
|
107
|
+
// @ts-expect-error update
|
|
93
108
|
planesPrimitives[i].update(frameState);
|
|
94
109
|
}
|
|
95
110
|
} else {
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import { CesiumMap } from '@vcmap/core';
|
|
2
|
-
import { ToolboxType } from '@vcmap/ui';
|
|
3
|
-
import { check, ofEnum } from '@vcsuite/check';
|
|
4
|
-
import { reactive, watch } from 'vue';
|
|
5
|
-
import { ViewshedTypes } from '../viewshed.js';
|
|
6
|
-
import { ViewshedIcons } from './windowHelper.js';
|
|
7
|
-
import { ViewshedPluginModes } from '../viewshedManager.js';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* @typedef {Object} ViewshedToolbox
|
|
11
|
-
* @property {import("@vcmap/ui/src/manager/toolbox/toolboxManager").SelectToolboxComponentOptions} toolbox
|
|
12
|
-
* @property {function():void} destroy
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
*
|
|
17
|
-
* @param {import("@vcmap/ui").VcsUiApp} app The VcsUiApp instance
|
|
18
|
-
* @param {import("../viewshedManager.js").ViewshedManager} manager The viewshed manager.
|
|
19
|
-
* @param {string} name Name of toolbox.
|
|
20
|
-
* @param {Array<string>} tools The tools to be available in the toolbox
|
|
21
|
-
* @returns {ViewshedToolbox} A select toolbox with buttons to create 360 and cone viewshed.
|
|
22
|
-
*/
|
|
23
|
-
function createViewshedToolbox(app, manager, name, tools) {
|
|
24
|
-
const toolbox = {
|
|
25
|
-
type: ToolboxType.SELECT,
|
|
26
|
-
action: reactive({
|
|
27
|
-
name,
|
|
28
|
-
currentIndex: 0,
|
|
29
|
-
active: false,
|
|
30
|
-
background: false,
|
|
31
|
-
disabled: !(app.maps.activeMap instanceof CesiumMap),
|
|
32
|
-
callback() {
|
|
33
|
-
if (this.active) {
|
|
34
|
-
if (this.background && manager.currentViewshed.value) {
|
|
35
|
-
manager.editViewshed(manager.currentViewshed.value);
|
|
36
|
-
} else {
|
|
37
|
-
manager.stop();
|
|
38
|
-
}
|
|
39
|
-
} else {
|
|
40
|
-
const toolName = this.tools[this.currentIndex].name;
|
|
41
|
-
manager.createViewshed(toolName);
|
|
42
|
-
}
|
|
43
|
-
},
|
|
44
|
-
selected(newIndex) {
|
|
45
|
-
if (newIndex !== this.currentIndex) {
|
|
46
|
-
this.currentIndex = newIndex;
|
|
47
|
-
}
|
|
48
|
-
const toolName = this.tools[this.currentIndex].name;
|
|
49
|
-
manager.createViewshed(toolName);
|
|
50
|
-
},
|
|
51
|
-
tools: tools.flatMap((tool) => {
|
|
52
|
-
if (tool === ViewshedTypes.CONE) {
|
|
53
|
-
return {
|
|
54
|
-
name: ViewshedTypes.CONE,
|
|
55
|
-
icon: ViewshedIcons[ViewshedTypes.CONE],
|
|
56
|
-
title: `viewshed.create.${ViewshedTypes.CONE}`,
|
|
57
|
-
};
|
|
58
|
-
} else if (tool === ViewshedTypes.THREESIXTY) {
|
|
59
|
-
return {
|
|
60
|
-
name: ViewshedTypes.THREESIXTY,
|
|
61
|
-
icon: ViewshedIcons[ViewshedTypes.THREESIXTY],
|
|
62
|
-
title: `viewshed.create.${ViewshedTypes.THREESIXTY}`,
|
|
63
|
-
};
|
|
64
|
-
} else {
|
|
65
|
-
return [];
|
|
66
|
-
}
|
|
67
|
-
}),
|
|
68
|
-
}),
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
const viewshedModeWatcher = watch(manager.mode, (mode) => {
|
|
72
|
-
if (mode === ViewshedPluginModes.VIEW) {
|
|
73
|
-
toolbox.action.background = true;
|
|
74
|
-
toolbox.action.active = true;
|
|
75
|
-
} else if (mode) {
|
|
76
|
-
toolbox.action.background = false;
|
|
77
|
-
toolbox.action.active = true;
|
|
78
|
-
} else {
|
|
79
|
-
toolbox.action.background = false;
|
|
80
|
-
toolbox.action.active = false;
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
const currentViewshedWatcher = watch(
|
|
85
|
-
manager.currentViewshed,
|
|
86
|
-
(currentViewshed) => {
|
|
87
|
-
if (currentViewshed) {
|
|
88
|
-
toolbox.action.currentIndex = toolbox.action.tools.findIndex(
|
|
89
|
-
(tool) => tool.name === currentViewshed.type,
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
},
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
const mapChangedListener = app.maps.mapActivated.addEventListener((map) => {
|
|
96
|
-
if (map instanceof CesiumMap) {
|
|
97
|
-
toolbox.action.disabled = false;
|
|
98
|
-
} else {
|
|
99
|
-
toolbox.action.disabled = true;
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
return {
|
|
104
|
-
destroy() {
|
|
105
|
-
viewshedModeWatcher();
|
|
106
|
-
currentViewshedWatcher();
|
|
107
|
-
mapChangedListener();
|
|
108
|
-
},
|
|
109
|
-
toolbox,
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
*
|
|
115
|
-
* @param {import("@vcmap/ui").VcsUiApp} app The VcsUiApp instance
|
|
116
|
-
* @param {import("../viewshedManager.js").ViewshedManager} manager The viewshed manager.
|
|
117
|
-
* @param {string} name Name of toolbox action and owner of toolbox component
|
|
118
|
-
* @param {Array<string>} tools The tools to be available in the toolbox
|
|
119
|
-
* @returns {function():void} Function to remove toolbox component.
|
|
120
|
-
*/
|
|
121
|
-
export default function addToolButtons(app, manager, name, tools) {
|
|
122
|
-
check(tools, [ofEnum(ViewshedTypes)]);
|
|
123
|
-
|
|
124
|
-
const { toolbox: createToolbox, destroy: destroyCreateToolbox } =
|
|
125
|
-
createViewshedToolbox(app, manager, name, tools);
|
|
126
|
-
const createId = app.toolboxManager.add(createToolbox, name).id;
|
|
127
|
-
|
|
128
|
-
return () => {
|
|
129
|
-
app.toolboxManager.remove(createId);
|
|
130
|
-
destroyCreateToolbox();
|
|
131
|
-
};
|
|
132
|
-
}
|