@vcmap/viewshed 4.0.0 → 4.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vcmap/viewshed",
3
- "version": "4.0.0",
3
+ "version": "4.1.0",
4
4
  "description": "Tool to simulate a \"viewer\" and their field of vision from a certain standpoint in the map. It allows the user to see which areas and buildings can or can't be seen from a specific standpoint, regarding different viewing distances, viewers' sizes and orientations.",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -8,6 +8,7 @@
8
8
  "prepublishOnly": "vcmplugin build",
9
9
  "build": "vcmplugin build",
10
10
  "bundle": "vcmplugin bundle",
11
+ "audit": "npm audit --omit=peer --omit=dev --omit=optional",
11
12
  "start": "vcmplugin serve",
12
13
  "preview": "vcmplugin preview",
13
14
  "buildStagingApp": "vcmplugin buildStagingApp",
@@ -40,20 +41,18 @@
40
41
  },
41
42
  "prettier": "@vcsuite/eslint-config/prettier.js",
42
43
  "peerDependencies": {
43
- "@vcmap-cesium/engine": "^11.0.4",
44
- "@vcmap/core": "^6.3.0",
45
- "@vcmap/ui": "^6.3.0-rc.6",
44
+ "@vcmap-cesium/engine": "^11.0.5",
45
+ "@vcmap/core": "^6.3.5",
46
+ "@vcmap/ui": "^6.3.6",
46
47
  "ol": "^10.4.0",
47
48
  "vue": "~3.4.38",
48
49
  "vuetify": "~3.7.14"
49
50
  },
50
51
  "overrides": {
51
- "@vcmap/core": "^6.3.0",
52
- "@vcmap/ui": "^6.3.0-rc.6",
53
52
  "esbuild": "^0.25.0"
54
53
  },
55
54
  "devDependencies": {
56
- "@vcmap/plugin-cli": "^4.1.6",
55
+ "@vcmap/plugin-cli": "^4.2.0",
57
56
  "@vcsuite/eslint-config": "^4.1.0",
58
57
  "@vitest/coverage-v8": "^2.1.9",
59
58
  "jest-canvas-mock": "^2.5.2",
@@ -0,0 +1,57 @@
1
+ import { getLogger } from '@vcsuite/logger';
2
+ import { parseEnumValue } from '@vcsuite/parsers';
3
+ import { VcsCallback } from '@vcmap/ui';
4
+ import type { VcsCallbackOptions, VcsUiApp } from '@vcmap/ui';
5
+ import type { ViewshedPlugin, ViewshedPluginState } from '../index.js';
6
+ import { name as pluginName } from '../../package.json';
7
+ import { ViewshedPluginModes } from '../viewshedManager.js';
8
+ import type { ViewshedOptions } from '../viewshed.js';
9
+
10
+ export type ActivateViewshedCallbackOptions = VcsCallbackOptions &
11
+ ViewshedPluginState;
12
+
13
+ class ActivateViewshedCallback extends VcsCallback {
14
+ static get className(): string {
15
+ return 'ActivateViewshedCallback';
16
+ }
17
+
18
+ private _mode: ViewshedPluginModes | null;
19
+ private _viewshedOptions: ViewshedOptions | null;
20
+ constructor(options: ActivateViewshedCallbackOptions, app: VcsUiApp) {
21
+ super(options, app);
22
+ this._mode = parseEnumValue<ViewshedPluginModes>(
23
+ options.m,
24
+ ViewshedPluginModes,
25
+ ViewshedPluginModes.CREATE,
26
+ );
27
+ this._viewshedOptions = options.cv || null;
28
+ }
29
+
30
+ callback(): void {
31
+ const plugin = (this._app as VcsUiApp).plugins.getByKey(pluginName) as
32
+ | ViewshedPlugin
33
+ | undefined;
34
+ if (!plugin) {
35
+ getLogger('ActivateViewshedCallback').warning(
36
+ `Plugin ${pluginName} not found`,
37
+ );
38
+ return;
39
+ }
40
+ plugin.state.m = this._mode;
41
+ plugin.state.cv = this._viewshedOptions;
42
+ plugin.activate();
43
+ }
44
+
45
+ toJSON(): ActivateViewshedCallbackOptions {
46
+ const config: ActivateViewshedCallbackOptions = super.toJSON();
47
+ if (this._mode) {
48
+ config.m = this._mode;
49
+ }
50
+ if (this._viewshedOptions) {
51
+ config.cv = structuredClone(this._viewshedOptions);
52
+ }
53
+ return config;
54
+ }
55
+ }
56
+
57
+ export default ActivateViewshedCallback;
@@ -0,0 +1,26 @@
1
+ import { VcsCallback } from '@vcmap/ui';
2
+ import type { VcsUiApp } from '@vcmap/ui';
3
+ import { getLogger } from '@vcsuite/logger';
4
+ import { name as pluginName } from '../../package.json';
5
+ import type { ViewshedPlugin } from '../index.js';
6
+
7
+ class DeactivateViewshedCallback extends VcsCallback {
8
+ static get className(): string {
9
+ return 'DeactivateViewshedCallback';
10
+ }
11
+
12
+ callback(): void {
13
+ const plugin = (this._app as VcsUiApp).plugins.getByKey(pluginName) as
14
+ | ViewshedPlugin
15
+ | undefined;
16
+ if (!plugin) {
17
+ getLogger('DeactivateShadowCallback').warning(
18
+ `Plugin ${pluginName} not found`,
19
+ );
20
+ return;
21
+ }
22
+ plugin.deactivate();
23
+ }
24
+ }
25
+
26
+ export default DeactivateViewshedCallback;
package/src/index.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import type { VcsMap } from '@vcmap/core';
2
2
  import { CesiumMap, moduleIdSymbol } from '@vcmap/core';
3
3
  import type { PluginConfigEditor, VcsPlugin, VcsUiApp } from '@vcmap/ui';
4
+ import { getLogger } from '@vcsuite/logger';
5
+ import { reactive } from 'vue';
4
6
  import type { ColorOptions, ViewshedOptions } from './viewshed.js';
5
7
  import Viewshed, { ViewshedTypes } from './viewshed.js';
6
8
  import type { ViewshedManager } from './viewshedManager.js';
@@ -13,8 +15,10 @@ import { name, version, mapVersion } from '../package.json';
13
15
  import ViewshedCategory, { createCategory } from './viewshedCategory.js';
14
16
  import type { ViewshedConfig } from './ViewshedConfigEditor.vue';
15
17
  import ViewshedConfigEditor from './ViewshedConfigEditor.vue';
18
+ import ActivateViewshedCallback from './callbacks/activateViewshedCallback.js';
19
+ import DeactivateViewshedCallback from './callbacks/deactivateViewshedCallback.js';
16
20
 
17
- type ViewshedPluginState = {
21
+ export type ViewshedPluginState = {
18
22
  /** Which mode the plugin is currently in. */
19
23
  m?: ViewshedPluginModes | null;
20
24
  /** The currents viewshed options. */
@@ -36,15 +40,43 @@ export function getDefaultOptions(): ViewshedConfig {
36
40
  export type ViewshedPlugin = VcsPlugin<
37
41
  ViewshedPluginOptions,
38
42
  ViewshedPluginState
39
- >;
43
+ > & {
44
+ readonly state: ViewshedPluginState;
45
+ activate: () => void;
46
+ deactivate: () => void;
47
+ };
48
+
49
+ function activateCachedViewshed(
50
+ map: VcsMap,
51
+ viewshedManager?: ViewshedManager,
52
+ state?: ViewshedPluginState,
53
+ ): void {
54
+ if (!state?.m || !(map instanceof CesiumMap)) {
55
+ return;
56
+ }
57
+ if (state.m === ViewshedPluginModes.CREATE) {
58
+ const viewshedType = state.cv?.viewshedType ?? ViewshedTypes.CONE;
59
+ viewshedManager?.createViewshed(viewshedType).catch((e: unknown) => {
60
+ getLogger(name).error('Failed to create viewshed', String(e));
61
+ });
62
+ } else if (state.cv) {
63
+ const activeViewshed = new Viewshed(state.cv);
64
+ if (state.m === ViewshedPluginModes.VIEW) {
65
+ viewshedManager?.viewViewshed(activeViewshed);
66
+ } else {
67
+ viewshedManager?.editViewshed(activeViewshed);
68
+ }
69
+ }
70
+ }
40
71
 
41
72
  export default function plugin(options: ViewshedPluginOptions): ViewshedPlugin {
42
- let app: VcsUiApp;
43
- let viewshedManager: ViewshedManager;
73
+ let app: VcsUiApp | undefined;
74
+ let viewshedManager: ViewshedManager | undefined;
44
75
  let destroy = (): void => {};
45
76
 
46
77
  const defaultOptions = getDefaultOptions();
47
78
  const config = { ...defaultOptions, ...options };
79
+ const defaultState: ViewshedPluginState = reactive({});
48
80
 
49
81
  return {
50
82
  get name(): string {
@@ -56,16 +88,29 @@ export default function plugin(options: ViewshedPluginOptions): ViewshedPlugin {
56
88
  get mapVersion(): string {
57
89
  return mapVersion;
58
90
  },
91
+ getDefaultOptions,
92
+ state: defaultState,
59
93
  async initialize(
60
94
  vcsUiApp: VcsUiApp,
61
95
  state?: ViewshedPluginState,
62
96
  ): Promise<void> {
63
97
  app = vcsUiApp;
98
+ app.callbackClassRegistry.registerClass(
99
+ this[moduleIdSymbol],
100
+ ActivateViewshedCallback.className,
101
+ ActivateViewshedCallback,
102
+ );
103
+ app.callbackClassRegistry.registerClass(
104
+ this[moduleIdSymbol],
105
+ DeactivateViewshedCallback.className,
106
+ DeactivateViewshedCallback,
107
+ );
64
108
  vcsUiApp.categoryClassRegistry.registerClass(
65
109
  this[moduleIdSymbol],
66
110
  ViewshedCategory.className,
67
111
  ViewshedCategory,
68
112
  );
113
+
69
114
  const viewshedCategoryHelper = await createCategory(vcsUiApp);
70
115
  viewshedManager = createViewshedManager(
71
116
  vcsUiApp,
@@ -85,26 +130,17 @@ export default function plugin(options: ViewshedPluginOptions): ViewshedPlugin {
85
130
  );
86
131
 
87
132
  const { activeMap } = vcsUiApp.maps;
88
- function activateCachedViewshed(map: VcsMap): void {
89
- if (state?.m && state.cv && map instanceof CesiumMap) {
90
- const activeViewshed = new Viewshed(state.cv);
91
- if (state.m === ViewshedPluginModes.VIEW) {
92
- viewshedManager.viewViewshed(activeViewshed);
93
- } else {
94
- viewshedManager.editViewshed(activeViewshed);
95
- }
96
- }
97
- }
133
+
98
134
  let appliedCachedViewshed = false;
99
135
  if (activeMap) {
100
136
  appliedCachedViewshed = true;
101
- activateCachedViewshed(activeMap);
137
+ activateCachedViewshed(activeMap, viewshedManager, state);
102
138
  }
103
139
  const mapActivatedListener = vcsUiApp.maps.mapActivated.addEventListener(
104
140
  (map) => {
105
- viewshedManager.stop();
141
+ viewshedManager?.stop();
106
142
  if (!appliedCachedViewshed) {
107
- activateCachedViewshed(map);
143
+ activateCachedViewshed(map, viewshedManager, state);
108
144
  appliedCachedViewshed = true;
109
145
  }
110
146
  },
@@ -114,11 +150,24 @@ export default function plugin(options: ViewshedPluginOptions): ViewshedPlugin {
114
150
  mapActivatedListener();
115
151
  destroyButtons();
116
152
  destroyViewshedWindow();
117
- viewshedCategoryHelper.destroy();
118
- viewshedManager.destroy();
153
+ viewshedCategoryHelper?.destroy();
154
+ viewshedManager?.destroy();
119
155
  };
120
156
  },
121
- getDefaultOptions,
157
+ activate(): void {
158
+ if (!viewshedManager || !app) {
159
+ getLogger(name).error('Cannot activate plugin before initialization');
160
+ return;
161
+ }
162
+ if (!app.maps.activeMap) {
163
+ getLogger(name).error('Cannot activate plugin without an active map');
164
+ return;
165
+ }
166
+ activateCachedViewshed(app.maps.activeMap, viewshedManager, this.state);
167
+ },
168
+ deactivate(): void {
169
+ viewshedManager?.stop();
170
+ },
122
171
  toJSON(): ViewshedPluginOptions {
123
172
  const serial: ViewshedPluginOptions = {};
124
173
  if (config.tools && defaultOptions.tools.length !== config.tools.length) {
@@ -140,8 +189,8 @@ export default function plugin(options: ViewshedPluginOptions): ViewshedPlugin {
140
189
  },
141
190
  getState(forUrl?: boolean): ViewshedPluginState {
142
191
  const state: ViewshedPluginState = {};
143
- const mode = viewshedManager.mode.value;
144
- const currentViewshed = viewshedManager.currentViewshed.value?.toJSON();
192
+ const mode = viewshedManager?.mode.value;
193
+ const currentViewshed = viewshedManager?.currentViewshed.value?.toJSON();
145
194
 
146
195
  if (
147
196
  mode !== null &&
@@ -173,9 +222,6 @@ export default function plugin(options: ViewshedPluginOptions): ViewshedPlugin {
173
222
  },
174
223
  ];
175
224
  },
176
- destroy: (): void => {
177
- destroy();
178
- },
179
225
  i18n: {
180
226
  en: {
181
227
  viewshed: {
@@ -254,5 +300,18 @@ export default function plugin(options: ViewshedPluginOptions): ViewshedPlugin {
254
300
  },
255
301
  },
256
302
  },
303
+ destroy(): void {
304
+ if (app) {
305
+ app.callbackClassRegistry.unregisterClass(
306
+ this[moduleIdSymbol],
307
+ ActivateViewshedCallback.className,
308
+ );
309
+ app.callbackClassRegistry.unregisterClass(
310
+ this[moduleIdSymbol],
311
+ DeactivateViewshedCallback.className,
312
+ );
313
+ }
314
+ destroy();
315
+ },
257
316
  };
258
317
  }