@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.
@@ -1,5 +1,9 @@
1
+ import type { VcsMap } from '@vcmap/core';
1
2
  import { CesiumMap, moduleIdSymbol } from '@vcmap/core';
3
+ import type { PluginConfigEditor, VcsPlugin, VcsUiApp } from '@vcmap/ui';
4
+ import type { ColorOptions, ViewshedOptions } from './viewshed.js';
2
5
  import Viewshed, { ViewshedTypes } from './viewshed.js';
6
+ import type { ViewshedManager } from './viewshedManager.js';
3
7
  import createViewshedManager, {
4
8
  ViewshedPluginModes,
5
9
  } from './viewshedManager.js';
@@ -7,46 +11,55 @@ import { setupViewshedWindow } from './util/windowHelper.js';
7
11
  import addViewshedToolButtons from './util/toolboxHelper.js';
8
12
  import { name, version, mapVersion } from '../package.json';
9
13
  import ViewshedCategory, { createCategory } from './viewshedCategory.js';
10
- import ViewshedConfigEditor, {
11
- getDefaultOptions,
12
- } from './ViewshedConfigEditor.vue';
14
+ import type { ViewshedConfig } from './ViewshedConfigEditor.vue';
15
+ import ViewshedConfigEditor from './ViewshedConfigEditor.vue';
13
16
 
14
- /**
15
- * @typedef {Object} ViewshedPluginState
16
- * @property {import("./viewshedManager.js").ViewshedPluginModes | null} mode Which mode the plugin is currently in.
17
- * @property {import("./viewshed.js").ViewshedOptions | null} currentViewshed The currents viewshed options.
18
- */
17
+ type ViewshedPluginState = {
18
+ /** Which mode the plugin is currently in. */
19
+ m?: ViewshedPluginModes | null;
20
+ /** The currents viewshed options. */
21
+ cv?: ViewshedOptions | null;
22
+ };
19
23
 
20
- /**
21
- * @typedef {import("./viewshed.js").ColorOptions & {tools?: Array<ViewshedTypes>}} ViewshedPluginOptions
22
- */
24
+ export type ViewshedPluginOptions = ColorOptions & {
25
+ tools?: ViewshedTypes[];
26
+ };
23
27
 
24
- /**
25
- * Implementation of VcsPlugin interface. This function should not throw! Put exceptions in initialize instead.
26
- * @param {ViewshedPluginOptions} config - the configuration of this plugin instance, passed in from the app.
27
- * @returns {import("@vcmap/ui/src/vcsUiApp").VcsPlugin<T, ViewshedPluginState>}
28
- */
29
- export default function plugin(config) {
30
- let viewshedManager;
31
- let app;
32
- let destroy = () => {};
28
+ export function getDefaultOptions(): ViewshedConfig {
29
+ return {
30
+ visibleColor: Viewshed.getDefaultOptions().colorOptions.visibleColor,
31
+ shadowColor: Viewshed.getDefaultOptions().colorOptions.shadowColor,
32
+ tools: [...Object.values(ViewshedTypes)],
33
+ };
34
+ }
35
+
36
+ export type ViewshedPlugin = VcsPlugin<
37
+ ViewshedPluginOptions,
38
+ ViewshedPluginState
39
+ >;
40
+
41
+ export default function plugin(options: ViewshedPluginOptions): ViewshedPlugin {
42
+ let app: VcsUiApp;
43
+ let viewshedManager: ViewshedManager;
44
+ let destroy = (): void => {};
45
+
46
+ const defaultOptions = getDefaultOptions();
47
+ const config = { ...defaultOptions, ...options };
33
48
 
34
49
  return {
35
- get name() {
50
+ get name(): string {
36
51
  return name;
37
52
  },
38
- get version() {
53
+ get version(): string {
39
54
  return version;
40
55
  },
41
- get mapVersion() {
56
+ get mapVersion(): string {
42
57
  return mapVersion;
43
58
  },
44
- /**
45
- * @param {import("@vcmap/ui").VcsUiApp} vcsUiApp
46
- * @param {ViewshedPluginState=} state
47
- * @returns {Promise<void>}
48
- */
49
- async initialize(vcsUiApp, state) {
59
+ async initialize(
60
+ vcsUiApp: VcsUiApp,
61
+ state?: ViewshedPluginState,
62
+ ): Promise<void> {
50
63
  app = vcsUiApp;
51
64
  vcsUiApp.categoryClassRegistry.registerClass(
52
65
  this[moduleIdSymbol],
@@ -63,7 +76,7 @@ export default function plugin(config) {
63
76
  vcsUiApp,
64
77
  viewshedManager,
65
78
  name,
66
- config.tools || getDefaultOptions().tools,
79
+ config.tools || defaultOptions.tools,
67
80
  );
68
81
  const { destroy: destroyViewshedWindow } = setupViewshedWindow(
69
82
  viewshedManager,
@@ -72,7 +85,7 @@ export default function plugin(config) {
72
85
  );
73
86
 
74
87
  const { activeMap } = vcsUiApp.maps;
75
- function activateCachedViewshed(map) {
88
+ function activateCachedViewshed(map: VcsMap): void {
76
89
  if (state?.m && state.cv && map instanceof CesiumMap) {
77
90
  const activeViewshed = new Viewshed(state.cv);
78
91
  if (state.m === ViewshedPluginModes.VIEW) {
@@ -97,7 +110,7 @@ export default function plugin(config) {
97
110
  },
98
111
  );
99
112
 
100
- destroy = () => {
113
+ destroy = (): void => {
101
114
  mapActivatedListener();
102
115
  destroyButtons();
103
116
  destroyViewshedWindow();
@@ -105,52 +118,40 @@ export default function plugin(config) {
105
118
  viewshedManager.destroy();
106
119
  };
107
120
  },
108
- /**
109
- * should return all default values of the configuration
110
- * @returns {ViewshedPluginOptions}
111
- */
112
121
  getDefaultOptions,
113
- /**
114
- * should return the plugin's serialization excluding all default values
115
- * @returns {ViewshedPluginOptions}
116
- */
117
- toJSON() {
118
- const serial = {};
119
- if (
120
- config.tools &&
121
- getDefaultOptions().tools.length !== config.tools.length
122
- ) {
122
+ toJSON(): ViewshedPluginOptions {
123
+ const serial: ViewshedPluginOptions = {};
124
+ if (config.tools && defaultOptions.tools.length !== config.tools.length) {
123
125
  serial.tools = [...config.tools];
124
126
  }
125
127
  if (
126
128
  config.shadowColor &&
127
- config.shadowColor !== Viewshed.getDefaultOptions().shadowColor
129
+ config.shadowColor !== defaultOptions.shadowColor
128
130
  ) {
129
131
  serial.shadowColor = config.shadowColor;
130
132
  }
131
133
  if (
132
134
  config.visibleColor &&
133
- config.visibleColor !== Viewshed.getDefaultOptions().visibleColor
135
+ config.visibleColor !== defaultOptions.visibleColor
134
136
  ) {
135
137
  serial.visibleColor = config.visibleColor;
136
138
  }
137
139
  return serial;
138
140
  },
139
- /**
140
- * should return the plugins state
141
- * @param {boolean} forUrl
142
- * @returns {ViewshedPluginState}
143
- */
144
- getState(forUrl) {
145
- const state = {};
141
+ getState(forUrl?: boolean): ViewshedPluginState {
142
+ const state: ViewshedPluginState = {};
146
143
  const mode = viewshedManager.mode.value;
147
144
  const currentViewshed = viewshedManager.currentViewshed.value?.toJSON();
148
145
 
149
- if (mode !== null && mode !== 'create' && currentViewshed) {
146
+ if (
147
+ mode !== null &&
148
+ mode !== ViewshedPluginModes.CREATE &&
149
+ currentViewshed
150
+ ) {
150
151
  state.m = mode;
151
152
  state.cv = currentViewshed;
152
- if (forUrl && state.cv.properties?.title) {
153
- if (Object.keys(state.properties).length === 1) {
153
+ if (forUrl && state.cv?.properties?.title) {
154
+ if (Object.keys(state.cv?.properties).length === 1) {
154
155
  delete state.cv.properties;
155
156
  } else {
156
157
  delete state.cv.properties.title;
@@ -160,11 +161,7 @@ export default function plugin(config) {
160
161
 
161
162
  return state;
162
163
  },
163
- /**
164
- * components for configuring the plugin and/ or custom items defined by the plugin
165
- * @returns {Array<import("@vcmap/ui").PluginConfigEditor>}
166
- */
167
- getConfigEditors() {
164
+ getConfigEditors(): PluginConfigEditor<object>[] {
168
165
  return [
169
166
  {
170
167
  component: ViewshedConfigEditor,
@@ -176,7 +173,9 @@ export default function plugin(config) {
176
173
  },
177
174
  ];
178
175
  },
179
- destroy: () => destroy(),
176
+ destroy: (): void => {
177
+ destroy();
178
+ },
180
179
  i18n: {
181
180
  en: {
182
181
  viewshed: {
@@ -191,7 +190,6 @@ export default function plugin(config) {
191
190
  heightMode: 'Height mode',
192
191
  relative: 'Relative to ground',
193
192
  absolute: 'Absolute',
194
- new: 'New',
195
193
  cancel: 'Cancel',
196
194
  [ViewshedTypes.CONE]: 'Cone viewshed analysis',
197
195
  [ViewshedTypes.THREESIXTY]: '360° viewshed analysis',
@@ -199,7 +197,6 @@ export default function plugin(config) {
199
197
  [ViewshedTypes.CONE]: 'Create cone viewshed analysis',
200
198
  [ViewshedTypes.THREESIXTY]: 'Create 360° viewshed analysis',
201
199
  },
202
- addToMyWorkspace: 'Add to My Workspace',
203
200
  temporary: 'Temporary',
204
201
  jumpToViewpoint: 'Jump to viewpoint',
205
202
  returnToViewpoint: 'Return to previous viewpoint',
@@ -231,7 +228,6 @@ export default function plugin(config) {
231
228
  heightMode: 'Höhenmodus',
232
229
  relative: 'Relativ zum Gelände',
233
230
  absolute: 'Absolut',
234
- new: 'Neu',
235
231
  cancel: 'Abbrechen',
236
232
  [ViewshedTypes.CONE]: 'Sichtkegelanalyse',
237
233
  [ViewshedTypes.THREESIXTY]: '360° Sichtsanalyse',
@@ -239,7 +235,6 @@ export default function plugin(config) {
239
235
  [ViewshedTypes.CONE]: 'Sichtkegelanalyse erstellen',
240
236
  [ViewshedTypes.THREESIXTY]: '360° Sichtanalyse erstellen',
241
237
  },
242
- addToMyWorkspace: 'Zu Mein Arbeitsbereich hinzufügen',
243
238
  temporary: 'Temporäre',
244
239
  jumpToViewpoint: 'Zu Standpunkt springen',
245
240
  returnToViewpoint: 'Zu vorherigem Standpunkt zurück springen',
@@ -0,0 +1,183 @@
1
+ import { CesiumMap } from '@vcmap/core';
2
+ import type {
3
+ SelectToolboxComponentOptions,
4
+ SingleToolboxComponentOptions,
5
+ VcsUiApp,
6
+ } from '@vcmap/ui';
7
+ import { ToolboxType } from '@vcmap/ui';
8
+ import { check, ofEnum } from '@vcsuite/check';
9
+ import { reactive, watch } from 'vue';
10
+ import { ViewshedTypes } from '../viewshed.js';
11
+ import { viewshedIcons } from './windowHelper.js';
12
+ import type { ViewshedManager } from '../viewshedManager.js';
13
+ import { ViewshedPluginModes } from '../viewshedManager.js';
14
+
15
+ type ViewshedToolbox = {
16
+ toolbox: SingleToolboxComponentOptions | SelectToolboxComponentOptions;
17
+ destroy: () => void;
18
+ };
19
+
20
+ /**
21
+ *
22
+ * @param app The VcsUiApp instance
23
+ * @param manager The viewshed manager.
24
+ * @param name Name of toolbox.
25
+ * @param tools The tools to be available in the toolbox
26
+ * @returns A select toolbox with buttons to create 360 and cone viewshed.
27
+ */
28
+ function createViewshedToolbox(
29
+ app: VcsUiApp,
30
+ manager: ViewshedManager,
31
+ name: string,
32
+ tools: string[],
33
+ ): ViewshedToolbox {
34
+ /**
35
+ * @param tool The tool to create.
36
+ * @returns A tool object.
37
+ */
38
+ function parseTool(
39
+ tool: ViewshedTypes,
40
+ ): { name: ViewshedTypes; icon: string; title: string } | undefined {
41
+ if (tool === ViewshedTypes.CONE) {
42
+ return {
43
+ name: ViewshedTypes.CONE,
44
+ icon: viewshedIcons[ViewshedTypes.CONE],
45
+ title: `viewshed.create.${ViewshedTypes.CONE}`,
46
+ };
47
+ } else if (tool === ViewshedTypes.THREESIXTY) {
48
+ return {
49
+ name: ViewshedTypes.THREESIXTY,
50
+ icon: viewshedIcons[ViewshedTypes.THREESIXTY],
51
+ title: `viewshed.create.${ViewshedTypes.THREESIXTY}`,
52
+ };
53
+ } else {
54
+ return undefined;
55
+ }
56
+ }
57
+
58
+ let toolbox: SingleToolboxComponentOptions | SelectToolboxComponentOptions;
59
+ let currentViewshedWatcher: () => void;
60
+ if (tools.length === 1) {
61
+ const tool = parseTool(tools[0] as ViewshedTypes)!;
62
+ toolbox = {
63
+ type: ToolboxType.SINGLE,
64
+ action: reactive({
65
+ ...tool,
66
+ active: false,
67
+ background: false,
68
+ disabled: !(app.maps.activeMap instanceof CesiumMap),
69
+ async callback() {
70
+ if (this.active) {
71
+ if (this.background && manager.currentViewshed.value) {
72
+ manager.editViewshed(manager.currentViewshed.value);
73
+ } else {
74
+ manager.stop();
75
+ }
76
+ } else if (tool) {
77
+ await manager.createViewshed(tool.name);
78
+ }
79
+ },
80
+ }),
81
+ };
82
+ } else {
83
+ toolbox = {
84
+ type: ToolboxType.SELECT,
85
+ action: reactive({
86
+ name,
87
+ currentIndex: 0,
88
+ active: false,
89
+ background: false,
90
+ disabled: !(app.maps.activeMap instanceof CesiumMap),
91
+ async callback() {
92
+ if (this.active) {
93
+ if (this.background && manager.currentViewshed.value) {
94
+ manager.editViewshed(manager.currentViewshed.value);
95
+ } else {
96
+ manager.stop();
97
+ }
98
+ } else {
99
+ const toolName = this.tools[this.currentIndex].name;
100
+ await manager.createViewshed(toolName);
101
+ }
102
+ },
103
+ async selected(newIndex: number) {
104
+ if (newIndex !== this.currentIndex) {
105
+ this.currentIndex = newIndex;
106
+ }
107
+ const toolName = this.tools[this.currentIndex].name;
108
+ await manager.createViewshed(toolName);
109
+ },
110
+ tools: tools.flatMap((t) => parseTool(t as ViewshedTypes)),
111
+ }),
112
+ };
113
+
114
+ currentViewshedWatcher = watch(
115
+ manager.currentViewshed,
116
+ (currentViewshed) => {
117
+ if (currentViewshed) {
118
+ (toolbox as SelectToolboxComponentOptions).action.currentIndex = (
119
+ toolbox as SelectToolboxComponentOptions
120
+ ).action.tools.findIndex(
121
+ (tool) => (tool.name as ViewshedTypes) === currentViewshed.type,
122
+ );
123
+ }
124
+ },
125
+ );
126
+ }
127
+
128
+ const viewshedModeWatcher = watch(manager.mode, (mode) => {
129
+ if (mode === ViewshedPluginModes.VIEW) {
130
+ toolbox.action.background = true;
131
+ toolbox.action.active = true;
132
+ } else if (mode) {
133
+ toolbox.action.background = false;
134
+ toolbox.action.active = true;
135
+ } else {
136
+ toolbox.action.background = false;
137
+ toolbox.action.active = false;
138
+ }
139
+ });
140
+
141
+ const mapChangedListener = app.maps.mapActivated.addEventListener((map) => {
142
+ if (map instanceof CesiumMap) {
143
+ toolbox.action.disabled = false;
144
+ } else {
145
+ toolbox.action.disabled = true;
146
+ }
147
+ });
148
+
149
+ return {
150
+ toolbox,
151
+ destroy(): void {
152
+ viewshedModeWatcher();
153
+ currentViewshedWatcher?.();
154
+ mapChangedListener();
155
+ },
156
+ };
157
+ }
158
+
159
+ /**
160
+ *
161
+ * @param app The VcsUiApp instance
162
+ * @param manager The viewshed manager.
163
+ * @param name Name of toolbox action and owner of toolbox component
164
+ * @param tools The tools to be available in the toolbox
165
+ * @returns Function to remove toolbox component.
166
+ */
167
+ export default function addToolButtons(
168
+ app: VcsUiApp,
169
+ manager: ViewshedManager,
170
+ name: string,
171
+ tools: string[],
172
+ ): () => void {
173
+ check(tools, [ofEnum(ViewshedTypes)]);
174
+
175
+ const { toolbox: createToolbox, destroy: destroyCreateToolbox } =
176
+ createViewshedToolbox(app, manager, name, tools);
177
+ const createId = app.toolboxManager.add(createToolbox, name).id;
178
+
179
+ return () => {
180
+ app.toolboxManager.remove(createId);
181
+ destroyCreateToolbox();
182
+ };
183
+ }
@@ -1,41 +1,40 @@
1
1
  import { ref, watch } from 'vue';
2
+ import type {
3
+ CollectionComponentClass,
4
+ WindowComponentOptions,
5
+ VcsUiApp,
6
+ } from '@vcmap/ui';
2
7
  import { WindowSlot, makeEditorCollectionComponentClass } from '@vcmap/ui';
3
8
  import ViewshedWindow from '../ViewshedWindow.vue';
4
9
  import { name } from '../../package.json';
10
+ import type Viewshed from '../viewshed.js';
5
11
  import { ViewshedTypes } from '../viewshed.js';
12
+ import type { ViewshedManager } from '../viewshedManager.js';
6
13
  import { ViewshedPluginModes } from '../viewshedManager.js';
7
14
 
8
- export const ViewshedIcons = {
15
+ export const viewshedIcons = {
9
16
  [ViewshedTypes.CONE]: '$vcsViewshed',
10
17
  [ViewshedTypes.THREESIXTY]: '$vcsViewshedCone',
11
18
  };
12
19
 
13
20
  /**
14
- * @typedef {Object} ViewshedWindow
15
- * @property {function():void} destroy Destroys watchers and removes window.
16
- * @property {function():void} toggleWindow Toggles window. Only opens window when manager has current viewshed.
21
+ * @param manager The viewshed manager.
22
+ * @param app The VcsUiApp instance
23
+ * @param collectionComponent The collection component of the category.
24
+ * @returns The destroy function.
17
25
  */
18
-
19
- /**
20
- *
21
- * @param {import("../viewshedManager.js").ViewshedManager} manager The viewshed manager.
22
- * @param {import("@vcmap/ui").VcsUiApp} app The VcsUiApp instance
23
- * @param {import("@vcmap/ui").CollectionComponent} collectionComponent The collection component of the category.
24
- * @returns {ViewshedWindow} Viewshed window api.
25
- */
26
- export function setupViewshedWindow(manager, app, collectionComponent) {
27
- /**
28
- * @type {import("vue").Ref<undefined | string | string[]>}
29
- */
30
- const headerTitle = ref();
26
+ export function setupViewshedWindow(
27
+ manager: ViewshedManager,
28
+ app: VcsUiApp,
29
+ collectionComponent: CollectionComponentClass<Viewshed>,
30
+ ): { destroy: () => void } {
31
+ const headerTitle = ref<string | string[]>('');
31
32
  const headerIcon = ref();
32
33
  const windowId = `${collectionComponent.id}-editor`;
33
34
 
34
- const editor = {
35
+ const editor: WindowComponentOptions = {
35
36
  component: ViewshedWindow,
36
- provides: {
37
- manager,
38
- },
37
+ provides: { manager },
39
38
  state: {
40
39
  headerTitle,
41
40
  headerIcon,
@@ -49,17 +48,19 @@ export function setupViewshedWindow(manager, app, collectionComponent) {
49
48
  ...editor,
50
49
  props: {
51
50
  selection: collectionComponent.selection,
52
- getViewshed: () => collectionComponent.collection.getByKey(item.name),
51
+ getViewshed: (): Viewshed | undefined =>
52
+ collectionComponent.collection.getByKey(item.name),
53
53
  },
54
54
  }),
55
55
  });
56
56
 
57
- function updateHeader() {
57
+ function updateHeader(): void {
58
58
  if (manager.currentViewshed.value) {
59
- headerIcon.value = ViewshedIcons[manager.currentViewshed.value.type];
59
+ headerIcon.value = viewshedIcons[manager.currentViewshed.value.type];
60
60
 
61
61
  if (manager.currentIsPersisted.value) {
62
- headerTitle.value = manager.currentViewshed.value.properties.title;
62
+ headerTitle.value = manager.currentViewshed.value.properties
63
+ .title as string;
63
64
  } else if (manager.mode.value === ViewshedPluginModes.CREATE) {
64
65
  headerTitle.value = `viewshed.create.${manager.currentViewshed.value.type}`;
65
66
  } else {
@@ -71,7 +72,7 @@ export function setupViewshedWindow(manager, app, collectionComponent) {
71
72
  }
72
73
  }
73
74
 
74
- function updateWindow() {
75
+ function updateWindow(): void {
75
76
  updateHeader();
76
77
  if (
77
78
  manager.currentViewshed.value &&
@@ -115,7 +116,7 @@ export function setupViewshedWindow(manager, app, collectionComponent) {
115
116
  });
116
117
 
117
118
  return {
118
- destroy() {
119
+ destroy(): void {
119
120
  app.windowManager.remove(windowId);
120
121
  viewshedListener();
121
122
  viewshedModeListener();