@vcmap/viewshed 2.0.10 → 3.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vcmap/viewshed",
3
- "version": "2.0.10",
3
+ "version": "3.0.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.Th",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -47,25 +47,25 @@
47
47
  },
48
48
  "prettier": "@vcsuite/eslint-config/prettier.js",
49
49
  "peerDependencies": {
50
- "@vcmap-cesium/engine": "^4.0.3",
51
- "@vcmap/core": "^5.1.4",
52
- "@vcmap/ui": "^5.1.5",
53
- "ol": "^7.5.2",
54
- "vue": "~2.7.3",
55
- "vuetify": "~2.6.7"
50
+ "@vcmap-cesium/engine": "^11.0.2",
51
+ "@vcmap/core": "^6.0.0",
52
+ "@vcmap/ui": "^6.0.1",
53
+ "ol": "^10.2.1",
54
+ "vue": "~3.4.38",
55
+ "vuetify": "^3.7.3"
56
56
  },
57
57
  "devDependencies": {
58
- "@vcmap/plugin-cli": "^3.0.0",
59
- "@vcsuite/eslint-config": "^3.0.5",
60
- "@vitest/coverage-v8": "^0.34.6",
58
+ "@vcmap/plugin-cli": "^4.0.0",
59
+ "@vcsuite/eslint-config": "^3.0.8",
60
+ "@vitest/coverage-v8": "^2.0.1",
61
61
  "jest-canvas-mock": "^2.5.2",
62
62
  "jsdom": "^22.1.0",
63
63
  "resize-observer-polyfill": "^1.5.1",
64
- "vitest": "^0.34.6"
64
+ "vitest": "^2.0.1"
65
65
  },
66
66
  "dependencies": {
67
- "@vcsuite/check": "^1.1.2",
67
+ "@vcsuite/check": "^2.1.0",
68
68
  "@vcsuite/parsers": "^1.0.3"
69
69
  },
70
- "mapVersion": "^5.1"
70
+ "mapVersion": "^6.0"
71
71
  }
@@ -44,7 +44,7 @@
44
44
 
45
45
  <script>
46
46
  import { ref } from 'vue';
47
- import { VCol, VColorPicker, VContainer, VRow } from 'vuetify/lib';
47
+ import { VCol, VColorPicker, VContainer, VRow } from 'vuetify/components';
48
48
  import {
49
49
  AbstractConfigEditor,
50
50
  VcsFormSection,
@@ -74,7 +74,6 @@
74
74
 
75
75
  export default {
76
76
  name: 'ViewshedConfigEditor',
77
- title: 'Viewshed Editor',
78
77
  components: {
79
78
  AbstractConfigEditor,
80
79
  VcsFormSection,
@@ -97,14 +96,12 @@
97
96
  },
98
97
  setup(props) {
99
98
  /** @type {import("vue").Ref<import("./index.js").ViewshedPluginOptions>} */
100
- const localConfig = ref({});
99
+ const config = props.getConfig();
101
100
  /** @type {import("vue").Ref<import("./index.js").ViewshedPluginOptions>} */
102
- props.getConfig().then((config) => {
103
- localConfig.value = Object.assign(getDefaultOptions(), config);
104
- });
101
+ const localConfig = ref({ ...getDefaultOptions(), ...config });
105
102
 
106
- async function apply() {
107
- await props.setConfig(localConfig.value);
103
+ function apply() {
104
+ props.setConfig(localConfig.value);
108
105
  }
109
106
 
110
107
  return {
@@ -113,7 +110,7 @@
113
110
  apply,
114
111
  toolItems: Object.values(ViewshedTypes).map((type) => ({
115
112
  value: type,
116
- text: `viewshed.${type}`,
113
+ title: `viewshed.${type}`,
117
114
  })),
118
115
  };
119
116
  },
@@ -1,12 +1,12 @@
1
1
  <template>
2
2
  <div>
3
- <div v-if="viewshedMode === ViewshedPluginModes.CREATE" class="px-2 py-1">
4
- <template v-if="viewshedType === ViewshedTypes.CONE">
3
+ <div v-if="viewshedMode === ViewshedPluginModes.CREATE">
4
+ <VcsHelp v-if="viewshedType === ViewshedTypes.CONE">
5
5
  {{ $t('viewshed.createDescription') }}
6
- </template>
7
- <template v-else-if="viewshedType === ViewshedTypes.THREESIXTY">
6
+ </VcsHelp>
7
+ <VcsHelp v-else-if="viewshedType === ViewshedTypes.THREESIXTY">
8
8
  {{ $t('viewshed.createThreeSixtyDescription') }}
9
- </template>
9
+ </VcsHelp>
10
10
  </div>
11
11
  <VcsFormSection
12
12
  v-else-if="
@@ -32,6 +32,7 @@
32
32
  :transformation-mode="TransformationMode.TRANSLATE"
33
33
  :feature-properties="{ altitudeMode: 'absolute' }"
34
34
  :allow-z-input="true"
35
+ class="w-100"
35
36
  />
36
37
  </v-row>
37
38
  <v-row v-else no-gutters>
@@ -41,11 +42,10 @@
41
42
  class="pb-1"
42
43
  >
43
44
  <VcsTextField
44
- :value="value"
45
- @input="(v) => setPosition(v, key, index)"
45
+ :model-value="value"
46
+ @update:model-value="(v) => setPosition(v, key, index)"
46
47
  type="number"
47
48
  :prefix="key"
48
- :show-spin-buttons="true"
49
49
  :step="key === 'Z' ? 1 : 0.0001"
50
50
  :unit="key === 'Z' ? 'm' : '°'"
51
51
  :decimals="key === 'Z' ? 2 : 8"
@@ -53,6 +53,7 @@
53
53
  viewshedMode === ViewshedPluginModes.MOVE &&
54
54
  !(key === 'Z' && heightMode === HeightModes.RELATIVE)
55
55
  "
56
+ :hide-spin-buttons="true"
56
57
  />
57
58
  </v-col>
58
59
  </v-row>
@@ -62,21 +63,22 @@
62
63
  <v-container class="px-1 py-0">
63
64
  <v-row no-gutters>
64
65
  <v-col>
65
- <VcsLabel>
66
+ <VcsLabel html-for="heightMode">
66
67
  {{ $t('viewshed.heightMode') }}
67
68
  </VcsLabel>
68
69
  </v-col>
69
70
  <v-col>
70
71
  <VcsSelect
72
+ id="heightMode"
71
73
  :items="
72
74
  Object.values(HeightModes).map((item) => ({
73
75
  value: item,
74
- text: `viewshed.${item}`,
76
+ title: `viewshed.${item}`,
75
77
  }))
76
78
  "
77
- :value="heightMode"
78
- @input="changeHeightMode"
79
- ></VcsSelect>
79
+ :model-value="heightMode"
80
+ @update:model-value="changeHeightMode"
81
+ />
80
82
  </v-col>
81
83
  </v-row>
82
84
  </v-container>
@@ -94,28 +96,30 @@
94
96
  (viewshedType === ViewshedTypes.CONE && key !== 'showPrimitive')
95
97
  "
96
98
  >
97
- <v-row no-gutters class="pr-1">
99
+ <v-row no-gutters class="px-1">
98
100
  <v-col>
99
- <VcsLabel :html-for="key">
101
+ <VcsLabel :html-for="key" class="py-0">
100
102
  {{ $t(`viewshed.${key}`) }}
101
103
  </VcsLabel>
102
104
  </v-col>
103
105
  <v-col class="d-flex justify-end align-center">
104
- <span v-if="key === 'distance'">{{ `${value} m` }}</span>
105
- <span v-else>{{ `${value} °` }}</span>
106
+ <span v-if="key === 'distance'">{{
107
+ `${Math.round(value)} m`
108
+ }}</span>
109
+ <span v-else>{{ `${Math.round(value)} °` }}</span>
106
110
  </v-col>
107
111
  </v-row>
108
112
  <v-row no-gutters>
109
113
  <v-col>
110
114
  <VcsSlider
111
115
  :id="key"
112
- :value="value"
113
- @input="(v) => setParameter(key, v)"
116
+ class="pa-0"
117
+ :model-value="value"
118
+ @update:model-value="(v) => setParameter(key, v)"
114
119
  type="number"
115
120
  step="1"
116
121
  :min="parameterRanges[key][0]"
117
122
  :max="parameterRanges[key][1]"
118
- height="15"
119
123
  />
120
124
  </v-col>
121
125
  </v-row>
@@ -144,7 +148,7 @@
144
148
  v-else-if="viewshedMode === ViewshedPluginModes.CREATE"
145
149
  class="d-flex w-full justify-end px-2 pt-2 pb-1"
146
150
  >
147
- <VcsFormButton @click="cancel()" variant="filled">
151
+ <VcsFormButton @click="cancel()" variant="outlined">
148
152
  {{ $t('viewshed.cancel') }}
149
153
  </VcsFormButton>
150
154
  </div>
@@ -163,7 +167,7 @@
163
167
  watch,
164
168
  watchEffect,
165
169
  } from 'vue';
166
- import { VCol, VContainer, VDivider, VRow } from 'vuetify/lib';
170
+ import { VCol, VContainer, VDivider, VRow } from 'vuetify/components';
167
171
  import { TransformationMode, Viewpoint } from '@vcmap/core';
168
172
  import {
169
173
  VcsFormButton,
@@ -173,6 +177,7 @@
173
177
  VcsSlider,
174
178
  VcsTextField,
175
179
  VcsFeatureTransforms,
180
+ VcsHelp,
176
181
  } from '@vcmap/ui';
177
182
  import { ViewshedPluginModes, HeightModes } from './viewshedManager.js';
178
183
  import Viewshed, { ViewshedTypes } from './viewshed.js';
@@ -197,6 +202,7 @@
197
202
  VcsSelect,
198
203
  VcsFormButton,
199
204
  VcsFeatureTransforms,
205
+ VcsHelp,
200
206
  },
201
207
  name: 'ViewshedWindow',
202
208
  props: {
@@ -225,6 +231,12 @@
225
231
  currentIsPersisted,
226
232
  } = viewshedManager;
227
233
 
234
+ /** Whether movement is disabled for the current map */
235
+ const movementDisabled = ref(
236
+ app.maps.activeMap?.movementApiCallsDisabled ?? false,
237
+ );
238
+ let movementDisabledListener = () => {};
239
+
228
240
  const selection = computed(() => props.selection);
229
241
 
230
242
  let removePositionChangedListener = () => {};
@@ -330,11 +342,18 @@
330
342
  // only the case for collection component editor
331
343
  viewshedManager.editViewshed(viewshed);
332
344
  }
345
+ movementDisabledListener =
346
+ app.maps.activeMap?.movementDisabledChanged.addEventListener(
347
+ (options) => {
348
+ movementDisabled.value = options.apiCalls;
349
+ },
350
+ );
333
351
  });
334
352
 
335
353
  onUnmounted(() => {
336
354
  removePositionChangedListener();
337
355
  deleteCachedViewpoint();
356
+ movementDisabledListener();
338
357
 
339
358
  if (!currentIsPersisted.value) {
340
359
  // in case of temp editor
@@ -384,6 +403,7 @@
384
403
  : 'viewshed.jumpToViewpoint',
385
404
  icon: 'mdi-human-male',
386
405
  active: !!cachedViewpoint.value,
406
+ disabled: movementDisabled.value,
387
407
  async callback() {
388
408
  viewshedManager.moveCurrentViewshed(false);
389
409
  if (currentViewshed.value && !cachedViewpoint.value) {
package/src/index.js CHANGED
@@ -28,6 +28,7 @@ import ViewshedConfigEditor, {
28
28
  */
29
29
  export default function plugin(config) {
30
30
  let viewshedManager;
31
+ let app;
31
32
  let destroy = () => {};
32
33
 
33
34
  return {
@@ -46,6 +47,7 @@ export default function plugin(config) {
46
47
  * @returns {Promise<void>}
47
48
  */
48
49
  async initialize(vcsUiApp, state) {
50
+ app = vcsUiApp;
49
51
  vcsUiApp.categoryClassRegistry.registerClass(
50
52
  this[moduleIdSymbol],
51
53
  ViewshedCategory.className,
@@ -71,9 +73,12 @@ export default function plugin(config) {
71
73
 
72
74
  const { activeMap } = vcsUiApp.maps;
73
75
  function activateCachedViewshed(map) {
74
- if (state?.mode && state.currentViewshed && map instanceof CesiumMap) {
75
- const activeViewshed = new Viewshed(state.currentViewshed, activeMap);
76
- if (state.mode === ViewshedPluginModes.VIEW) {
76
+ if (state?.m && state.cv && map instanceof CesiumMap) {
77
+ if (state.cv.properties.title) {
78
+ delete state.cv.properties.title;
79
+ }
80
+ const activeViewshed = new Viewshed(state.cv);
81
+ if (state.m === ViewshedPluginModes.VIEW) {
77
82
  viewshedManager.viewViewshed(activeViewshed);
78
83
  } else {
79
84
  viewshedManager.editViewshed(activeViewshed);
@@ -139,19 +144,33 @@ export default function plugin(config) {
139
144
  * @returns {ViewshedPluginState}
140
145
  */
141
146
  getState() {
142
- return {
143
- mode: viewshedManager.mode.value,
144
- currentViewshed: viewshedManager.currentViewshed.value?.toJSON(),
145
- };
147
+ const state = {};
148
+ const mode = viewshedManager.mode.value;
149
+ const currentViewshed = viewshedManager.currentViewshed.value?.toJSON();
150
+
151
+ if (mode !== null && mode !== 'create' && currentViewshed) {
152
+ state.m = mode;
153
+ state.cv = currentViewshed;
154
+ }
155
+
156
+ return state;
146
157
  },
147
158
  /**
148
159
  * components for configuring the plugin and/ or custom items defined by the plugin
149
160
  * @returns {Array<import("@vcmap/ui").PluginConfigEditor>}
150
161
  */
151
162
  getConfigEditors() {
152
- return [{ component: ViewshedConfigEditor }];
163
+ return [
164
+ {
165
+ component: ViewshedConfigEditor,
166
+ title: 'viewshed.editor.title',
167
+ infoUrlCallback: app?.getHelpUrlCallback(
168
+ '/components/plugins/viewshedToolConfig.html',
169
+ ),
170
+ },
171
+ ];
153
172
  },
154
- destroy,
173
+ destroy: () => destroy(),
155
174
  i18n: {
156
175
  en: {
157
176
  viewshed: {
@@ -162,14 +181,14 @@ export default function plugin(config) {
162
181
  position: 'Position',
163
182
  showPrimitive: 'Show viewpoint',
164
183
  viewpoint: 'Viewpoint',
165
- viewshed: 'Viewshed',
184
+ viewshedCategory: 'Viewsheds',
166
185
  heightMode: 'Height mode',
167
- relative: 'Relativ to ground',
186
+ relative: 'Relative to ground',
168
187
  absolute: 'Absolute',
169
188
  new: 'New',
170
189
  cancel: 'Cancel',
171
- [ViewshedTypes.CONE]: 'Cone Viewshed',
172
- [ViewshedTypes.THREESIXTY]: '360° Viewshed',
190
+ [ViewshedTypes.CONE]: 'Cone viewshed analysis',
191
+ [ViewshedTypes.THREESIXTY]: '360° viewshed analysis',
173
192
  create: 'Create',
174
193
  addToMyWorkspace: 'Add to My Workspace',
175
194
  temporary: 'Temporary',
@@ -182,6 +201,7 @@ export default function plugin(config) {
182
201
  'Click the map twice. First click places the origin, second defines the distance of the viewshed.',
183
202
  remove: 'Remove',
184
203
  editor: {
204
+ title: 'Viewshed Editor',
185
205
  general: 'General Settings',
186
206
  visibleColor: 'Visible color',
187
207
  shadowColor: 'Shadow color',
@@ -196,28 +216,29 @@ export default function plugin(config) {
196
216
  heading: 'Ausrichtung',
197
217
  pitch: 'Neigung',
198
218
  position: 'Position',
199
- showPrimitive: 'Viewpoint zeigen',
200
- viewpoint: 'Viewpoint',
201
- viewshed: 'Viewshed',
219
+ showPrimitive: 'Standpunkt zeigen',
220
+ viewpoint: 'Standpunkt',
221
+ viewshedCategory: 'Sichtbarkeitsanalysen',
202
222
  heightMode: 'Höhenmodus',
203
223
  relative: 'Relativ zum Gelände',
204
224
  absolute: 'Absolut',
205
225
  new: 'Neu',
206
226
  cancel: 'Abbrechen',
207
- [ViewshedTypes.CONE]: 'Kegel Viewshed',
208
- [ViewshedTypes.THREESIXTY]: '360° Viewshed',
227
+ [ViewshedTypes.CONE]: 'Sichtkegelanalyse',
228
+ [ViewshedTypes.THREESIXTY]: '360° Sichtsanalyse',
209
229
  create: 'Erzeuge',
210
230
  addToMyWorkspace: 'Zu Mein Arbeitsbereich hinzufügen',
211
- temporary: 'Temporärer',
212
- jumpToViewpoint: 'Zu Viewpoint springen',
213
- returnToViewpoint: 'Zu vorherigem Viewpoint zurück springen',
214
- move: 'Viewpoint verschieben',
231
+ temporary: 'Temporäre',
232
+ jumpToViewpoint: 'Zu Standpunkt springen',
233
+ returnToViewpoint: 'Zu vorherigem Standpunkt zurück springen',
234
+ move: 'Standpunkt verschieben',
215
235
  createDescription:
216
- 'Klicke zweimal in die Karte. Der erste Klick platziert den Ursprung, der zweite die Distanz und die Richtung des Viewsheds.',
236
+ 'Klicken Sie zweimal in die Karte. Der erste Klick platziert den Ursprung, der zweite die Distanz und die Richtung des Sichtkegels.',
217
237
  createThreeSixtyDescription:
218
- 'Klicke zweimal in die Karte. Der erste Klick platziert den Ursprung, der zweite die Distanz des Viewsheds.',
238
+ 'Klicken Sie zweimal in die Karte. Der erste Klick platziert den Ursprung, der zweite die Distanz der Sichtbarkeitsanalyse.',
219
239
  remove: 'Entfernen',
220
240
  editor: {
241
+ title: 'Viewshed Editor',
221
242
  general: 'Allgemeine Einstellungen',
222
243
  visibleColor: 'Sichtbarer Bereich',
223
244
  shadowColor: 'Nicht sichtbarer Bereich',
@@ -1,6 +1,6 @@
1
1
  import { CesiumMap } from '@vcmap/core';
2
2
  import { ToolboxType } from '@vcmap/ui';
3
- import { check } from '@vcsuite/check';
3
+ import { check, ofEnum } from '@vcsuite/check';
4
4
  import { reactive, watch } from 'vue';
5
5
  import { ViewshedTypes } from '../viewshed.js';
6
6
  import { ViewshedIcons } from './windowHelper.js';
@@ -44,9 +44,9 @@ function createViewshedToolbox(app, manager, name, tools) {
44
44
  selected(newIndex) {
45
45
  if (newIndex !== this.currentIndex) {
46
46
  this.currentIndex = newIndex;
47
- const toolName = this.tools[this.currentIndex].name;
48
- manager.createViewshed(toolName);
49
47
  }
48
+ const toolName = this.tools[this.currentIndex].name;
49
+ manager.createViewshed(toolName);
50
50
  },
51
51
  tools: tools.flatMap((tool) => {
52
52
  if (tool === ViewshedTypes.CONE) {
@@ -119,7 +119,7 @@ function createViewshedToolbox(app, manager, name, tools) {
119
119
  * @returns {function():void} Function to remove toolbox component.
120
120
  */
121
121
  export default function addToolButtons(app, manager, name, tools) {
122
- check(tools, [Object.values(ViewshedTypes)]);
122
+ check(tools, [ofEnum(ViewshedTypes)]);
123
123
 
124
124
  const { toolbox: createToolbox, destroy: destroyCreateToolbox } =
125
125
  createViewshedToolbox(app, manager, name, tools);
package/src/viewshed.js CHANGED
@@ -305,6 +305,7 @@ export default class Viewshed extends VcsObject {
305
305
  this._shadowCamera.frustum
306
306
  ).fov = value * CesiumMath.RADIANS_PER_DEGREE;
307
307
  if (this._viewshedType === ViewshedTypes.CONE) {
308
+ this._updateShadowMap();
308
309
  this._updatePrimitive();
309
310
  }
310
311
  }
@@ -481,7 +482,7 @@ export default class Viewshed extends VcsObject {
481
482
  }
482
483
 
483
484
  _removePrimitive() {
484
- if (this._primitive && !this._primitive.isDestroyed?.()) {
485
+ if (this._primitive && !this._primitive.isDestroyed()) {
485
486
  this._scene?.primitives.remove(this._primitive);
486
487
  this._primitive.destroy();
487
488
  this._primitive = null;
@@ -34,7 +34,7 @@ class ViewshedCategory extends Category {
34
34
  this._app?.maps.getByType(CesiumMap.className)[0]
35
35
  );
36
36
  if (cesiumMap) {
37
- return new Viewshed(item, cesiumMap);
37
+ return new Viewshed(item);
38
38
  } else {
39
39
  throw new Error('No CesiumMap available');
40
40
  }
@@ -83,7 +83,7 @@ export async function createCategory(app) {
83
83
  {
84
84
  type: ViewshedCategory.className,
85
85
  name: 'Viewsheds',
86
- title: 'Viewsheds',
86
+ title: 'viewshed.viewshedCategory',
87
87
  },
88
88
  name,
89
89
  {