@vcmap/viewshed 2.0.1

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/dist/index.js ADDED
@@ -0,0 +1,1423 @@
1
+ var ue = Object.defineProperty;
2
+ var fe = (s, e, t) => e in s ? ue(s, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : s[e] = t;
3
+ var Z = (s, e, t) => (fe(s, typeof e != "symbol" ? e + "" : e, t), t);
4
+ import { VcsCameraPrimitive as ve, VcsObject as pe, VcsEvent as L, AbstractInteraction as we, EventType as D, Projection as I, SessionType as me, CesiumMap as B, startEditFeaturesSession as ge, startEditGeometrySession as _e, VectorLayer as Ce, wgs84Projection as Ee, maxZIndex as Ve, markVolatile as ye, Viewpoint as be, TransformationMode as Me, Category as Te, moduleIdSymbol as Oe } from "../../../assets/core.js";
5
+ import { Color as k, Matrix4 as Se, Transforms as Pe, Primitive as q, GeometryInstance as Q, SphereGeometry as Ae, ColorGeometryInstanceAttribute as ee, PerInstanceColorAppearance as te, SphereOutlineGeometry as Ie, Math as O, Cartesian3 as S, ShadowMap as Re, Camera as $e, HeightReference as Ne } from "../../../assets/cesium.js";
6
+ import { shallowRef as H, ref as A, nextTick as xe, inject as ie, reactive as j, watchEffect as De, watch as R, onMounted as Le, onUnmounted as Fe, computed as ke } from "../../../assets/vue.js";
7
+ import { ol$Observable$unByKey as je, Feature as We, ol$geom$Point as Be, ol$style$Style as ze } from "../../../assets/ol.js";
8
+ import { VcsTextField as Ge, VcsSlider as Ue, VcsLabel as oe, VcsFormSection as ne, VcsSelect as re, VcsFormButton as He, VcsFeatureTransforms as Xe, makeEditorCollectionComponentClass as Ke, WindowSlot as Ye, ToolboxType as Je, createListExportAction as Ze, downloadText as qe, createListImportAction as Qe, AbstractConfigEditor as et } from "../../../assets/ui.js";
9
+ import { VContainer as ae, VRow as le, VCol as ce, VDivider as tt, VColorPicker as it } from "../../../assets/vuetify.js";
10
+ const x = [
11
+ [String, "string"],
12
+ [Number, "number"],
13
+ [Boolean, "boolean"],
14
+ [Function, "function"],
15
+ [void 0, "undefined"],
16
+ [Symbol, "symbol"]
17
+ ];
18
+ function W(s) {
19
+ const e = {};
20
+ if (!s || e.toString(s) !== "[object Object]")
21
+ return !1;
22
+ const t = Object.getPrototypeOf(s);
23
+ if (!t)
24
+ return !0;
25
+ const i = e.hasOwnProperty, o = i.call(t, "constructor") && t.constructor;
26
+ return typeof o == "function" && i.toString.call(o) === i.toString.call(Object);
27
+ }
28
+ function M(s, e) {
29
+ if (s === null)
30
+ return "null";
31
+ if (typeof s > "u")
32
+ return "undefined";
33
+ if (e)
34
+ return typeof s;
35
+ let t;
36
+ if (Array.isArray(s))
37
+ t = `[${s.map((o) => M(o, e)).join(",")}]`;
38
+ else
39
+ try {
40
+ t = JSON.stringify(s);
41
+ } catch {
42
+ t = typeof s;
43
+ }
44
+ return t = t || typeof s, t.length > 20 ? `${t.substr(0, 20)}...` : t;
45
+ }
46
+ function st(s, e) {
47
+ return typeof e == "string" || typeof e == "number" || typeof e == "boolean" || typeof e == "symbol" ? s === e ? !1 : `Expected ${M(s)} to equal ${e.toString()}` : null;
48
+ }
49
+ function ot(s, e, t) {
50
+ if (Array.isArray(e)) {
51
+ if (e.length !== 1)
52
+ throw new Error("Array patterns may only have on type");
53
+ if (Array.isArray(s)) {
54
+ let i = !1;
55
+ return s.findIndex((r) => {
56
+ try {
57
+ z(r, e[0], t);
58
+ } catch (a) {
59
+ i = a.message.replace(/Match failed:\s/, "");
60
+ }
61
+ return i;
62
+ }) > -1 ? `${i} in ${M(s)}` : !1;
63
+ }
64
+ return `Expected ${M(s)} to be an Array`;
65
+ }
66
+ return null;
67
+ }
68
+ function X(s, e, t) {
69
+ const i = t ? `${t}.` : "";
70
+ if (!W(s))
71
+ return `Expected ${M(s)} to be a plain Object`;
72
+ let r = !1;
73
+ const a = Object.keys(e).find((l) => {
74
+ const n = s[l];
75
+ if (W(e[l]))
76
+ r = X(n, e[l], i + l);
77
+ else
78
+ try {
79
+ z(n, e[l]);
80
+ } catch (u) {
81
+ r = u.message.replace(/Match failed:\s/, "");
82
+ }
83
+ return r;
84
+ });
85
+ return a ? `${r} in object.${i}${a}` : !1;
86
+ }
87
+ function nt(s, e) {
88
+ if (e === Number)
89
+ return Number.isFinite(s) ? !1 : `expected ${M(s)} to be a number, excluding NaN`;
90
+ for (let t = x.length; t--; )
91
+ if (e === x[t][0])
92
+ return typeof s === x[t][1] ? !1 : `expected ${M(s)} to be a ${x[t][1]}`;
93
+ return null;
94
+ }
95
+ function K(s) {
96
+ if (s === null)
97
+ return "null";
98
+ const e = x.find((o) => o[0] === s);
99
+ if (e)
100
+ return e[1];
101
+ let t = s.toString();
102
+ if (s.className)
103
+ return s.className;
104
+ const i = t.match(/function (.*)\(/);
105
+ if (i && i.length > 1)
106
+ return i[1];
107
+ if (W(s)) {
108
+ const o = {};
109
+ Object.keys(s).forEach((r) => {
110
+ o[r] = K(s[r]);
111
+ });
112
+ try {
113
+ t = `Object of ${JSON.stringify(o)}`;
114
+ } catch {
115
+ t = "Object";
116
+ }
117
+ }
118
+ return t;
119
+ }
120
+ function de(s, e, t) {
121
+ const i = t ? `${t}.` : "";
122
+ let o = !1;
123
+ return Object.keys(s).find((a) => {
124
+ if (W(e[a])) {
125
+ const l = s[a];
126
+ o = de(l, e[a], i + a);
127
+ } else
128
+ e[a] || (o = `Found additional key ${i}${a}`);
129
+ return o = o ? o.replace(/\sin.*/, "") : !1, o;
130
+ }) ? `${o} in ${M(s)}` : !1;
131
+ }
132
+ function rt(s, e, t) {
133
+ const i = function(a, l) {
134
+ if (l == null)
135
+ return a === l ? !1 : `Expected ${M(a)} to be ${l}`;
136
+ const n = nt(a, l);
137
+ if (n !== null)
138
+ return n;
139
+ const u = st(a, l);
140
+ if (u !== null)
141
+ return u;
142
+ if (Array.isArray(l))
143
+ return ot(a, l, t);
144
+ if (l instanceof Function)
145
+ return a instanceof l ? !1 : `Expected ${M(a, !0)} to be of Type ${K(l)}`;
146
+ if (l === Object)
147
+ return X(a, {});
148
+ if (typeof l != "object")
149
+ throw new Error(`Cannot handler pattern ${l}`);
150
+ const c = X(a, l);
151
+ return c || (t ? de(a, l) : !1);
152
+ };
153
+ let o;
154
+ return Array.isArray(e) && e.length > 1 ? e.every((a) => i(s, a)) && (o = `Expected ${M(s)} to be a ${e.map((a) => K(a)).join(" or ")}`) : o = i(s, e), o;
155
+ }
156
+ function z(s, e, t) {
157
+ const i = rt(s, e, t);
158
+ if (i)
159
+ throw new Error(`Match failed: ${i}`);
160
+ return !1;
161
+ }
162
+ function at(s, e, t) {
163
+ if (s != null) {
164
+ const i = Object.values(e).find((o) => o == s);
165
+ if (i != null)
166
+ return i;
167
+ }
168
+ return t;
169
+ }
170
+ const lt = new k(), G = new Se();
171
+ class ct extends ve {
172
+ constructor(e) {
173
+ super(e), this.spot = e.spot;
174
+ }
175
+ /**
176
+ * Updates the camera primitive.
177
+ * @param {unknown} frameState
178
+ */
179
+ update(e) {
180
+ if (this.show)
181
+ if (this.spot)
182
+ super.update(e);
183
+ else {
184
+ const t = this._planesPrimitives, i = this._outlinePrimitives;
185
+ t.length === 0 && (Pe.eastNorthUpToFixedFrame(
186
+ this._camera.positionWC,
187
+ void 0,
188
+ G
189
+ ), t[0] = new q({
190
+ allowPicking: this.allowPicking,
191
+ geometryInstances: new Q({
192
+ geometry: new Ae({
193
+ radius: 2
194
+ }),
195
+ attributes: {
196
+ color: ee.fromColor(
197
+ k.fromAlpha(this._color, 0.1, lt)
198
+ )
199
+ },
200
+ modelMatrix: G
201
+ }),
202
+ appearance: new te({
203
+ translucent: !0,
204
+ flat: !0
205
+ }),
206
+ asynchronous: !1
207
+ }), i[0] = new q({
208
+ allowPicking: this.allowPicking,
209
+ geometryInstances: new Q({
210
+ geometry: new Ie({
211
+ radius: 2
212
+ }),
213
+ attributes: {
214
+ color: ee.fromColor(this._color)
215
+ },
216
+ modelMatrix: G
217
+ }),
218
+ appearance: new te({
219
+ translucent: !1,
220
+ flat: !0
221
+ }),
222
+ asynchronous: !1
223
+ }));
224
+ const { length: o } = t;
225
+ for (let r = 0; r < o; ++r)
226
+ i[r].update(e), t[r].update(e);
227
+ }
228
+ }
229
+ }
230
+ const w = {
231
+ CONE: "cone",
232
+ THREESIXTY: "360"
233
+ };
234
+ function dt(s, e) {
235
+ const t = new $e(s), i = (
236
+ /** @type {import("@vcmap-cesium/engine").PerspectiveFrustum} */
237
+ t.frustum
238
+ );
239
+ return i.fov = e.fov, i.near = e.near, i.aspectRatio = e.aspectRatio, i.far = e.far, t;
240
+ }
241
+ const E = class E extends pe {
242
+ static get className() {
243
+ return "Viewshed";
244
+ }
245
+ /**
246
+ * Returns the default viewshed options.
247
+ * @returns {{frustum: ShadowFrustumOptions, shadowColor: string, visibleColor: string, orientation: import("@vcmap-cesium/engine").HeadingPitchRollValues, position: import("ol/coordinate").Coordinate}}
248
+ */
249
+ static getDefaultOptions() {
250
+ return {
251
+ frustum: {
252
+ fov: O.PI / 3,
253
+ near: 1,
254
+ aspectRatio: 1,
255
+ far: 300
256
+ },
257
+ shadowColor: "#3333331A",
258
+ visibleColor: "#FF990080",
259
+ orientation: {
260
+ heading: 0,
261
+ pitch: 0,
262
+ roll: 0
263
+ },
264
+ position: [0, 0, 0]
265
+ };
266
+ }
267
+ /**
268
+ * @param {ViewshedOptions} options The options for the viewshed.
269
+ * @param {import("@vcmap/core").CesiumMap} [cesiumMap] The cesiumMap the viewshed should be applied to. If this parameter is passed, the viewshed is activated and all other viewsheds are deactivated.
270
+ */
271
+ constructor(e, t) {
272
+ var i, o, r, a, l, n;
273
+ super(e), this._cesiumMap = null, this._shadowCamera = null, this._scene = null, this._frustumOptions = {
274
+ fov: ((i = e.frustumOptions) == null ? void 0 : i.fov) || E.getDefaultOptions().frustum.fov,
275
+ far: ((o = e.frustumOptions) == null ? void 0 : o.far) || E.getDefaultOptions().frustum.far,
276
+ near: ((r = e.frustumOptions) == null ? void 0 : r.near) || E.getDefaultOptions().frustum.near,
277
+ aspectRatio: ((a = e.frustumOptions) == null ? void 0 : a.aspectRatio) || E.getDefaultOptions().frustum.aspectRatio
278
+ }, this._headingPitchRollValues = e.orientation || {
279
+ ...E.getDefaultOptions().orientation
280
+ }, this._position = e.position || E.getDefaultOptions().position, this._viewshedType = at(e.viewshedType, w), this._colors = {
281
+ visibleColor: k.fromCssColorString(
282
+ ((l = e.colorOptions) == null ? void 0 : l.visibleColor) || E.getDefaultOptions().visibleColor
283
+ ),
284
+ shadowColor: k.fromCssColorString(
285
+ ((n = e.colorOptions) == null ? void 0 : n.shadowColor) || E.getDefaultOptions().shadowColor
286
+ )
287
+ }, this._heightOffset = e.heightOffset || 0, this._shadowMap = null, this._primitive = null, this._showPrimitive = !!e.showPrimitive, this._shadowMapChangedListener = null, this._positionChanged = new L(), t ? this.activate(t) : this._active = !1;
288
+ }
289
+ /**
290
+ * Sets a new position for the shadow map. If no shadow map was created yet, due to missing position, this method triggers the creation of a shadow map.
291
+ * @param {import("ol/coordinate").Coordinate} coords The new positions coordinates in degrees
292
+ */
293
+ set position(e) {
294
+ z(e, [Number]), this._position = e, this._shadowCamera && (this._shadowCamera.position = S.fromDegrees(
295
+ e[0],
296
+ e[1],
297
+ e[2] + this._heightOffset
298
+ ), this._shadowCamera.setView({ orientation: this._headingPitchRollValues }), this._updatePrimitive()), this._positionChanged.raiseEvent(e);
299
+ }
300
+ /**
301
+ * @returns {import("ol/coordinate").Coordinate} The current position of the viewshed source.
302
+ */
303
+ get position() {
304
+ return [...this._position];
305
+ }
306
+ /**
307
+ * Getter for Event that is triggered each time the position is changed.
308
+ * @returns {import("@vcmap/core").VcsEvent<number[]>} The new position
309
+ */
310
+ get positionChanged() {
311
+ return this._positionChanged;
312
+ }
313
+ /**
314
+ * Sets the height offset of the viewshed.
315
+ * @param {number} value the offset that is added to the position height.
316
+ */
317
+ set heightOffset(e) {
318
+ this._heightOffset = e, this._shadowCamera && (this._shadowCamera.position = S.fromDegrees(
319
+ this.position[0],
320
+ this.position[1],
321
+ this.position[2] + e
322
+ ), this._updateShadowMap(), this._updatePrimitive());
323
+ }
324
+ /**
325
+ * Getter for height offset.
326
+ * @returns {number}
327
+ */
328
+ get heightOffset() {
329
+ return this._heightOffset;
330
+ }
331
+ /**
332
+ * Sets the reach of the viewshed.
333
+ * @param {number} value The distance in meters.
334
+ */
335
+ set distance(e) {
336
+ this._frustumOptions.far = e > E.MIN_DISTANCE ? e : E.MIN_DISTANCE, this._shadowCamera && (this._shadowCamera.frustum.far = this._frustumOptions.far, this._updateShadowMap(), this._viewshedType === w.CONE && this._updatePrimitive());
337
+ }
338
+ /**
339
+ * Returns the reach of the viewshed.
340
+ * @returns {number} The distance in meters.
341
+ */
342
+ get distance() {
343
+ return this._frustumOptions.far;
344
+ }
345
+ /**
346
+ * Sets the field of view of a cone viewshed. Does not have a impact on 360 viewshed.
347
+ * @param {number} value The field of view in degrees.
348
+ */
349
+ set fov(e) {
350
+ this._frustumOptions.fov = e * O.RADIANS_PER_DEGREE, this._shadowCamera && (this._shadowCamera.frustum.fov = e * O.RADIANS_PER_DEGREE, this._updateShadowMap(), this._viewshedType === w.CONE && this._updatePrimitive());
351
+ }
352
+ /**
353
+ * Returns the field of view.
354
+ * @returns {number} The field of view in degrees.
355
+ */
356
+ get fov() {
357
+ return this._frustumOptions.fov * O.DEGREES_PER_RADIAN;
358
+ }
359
+ /**
360
+ * Sets the heading of a cone viewshed. Does not have impact on 360 viewshed.
361
+ * @param {number} value Heading in degrees.
362
+ */
363
+ set heading(e) {
364
+ this._headingPitchRollValues.heading = e * O.RADIANS_PER_DEGREE, this._shadowCamera && (this._shadowCamera.setView({
365
+ orientation: {
366
+ heading: e * O.RADIANS_PER_DEGREE,
367
+ pitch: this._shadowCamera.pitch,
368
+ roll: 0
369
+ }
370
+ }), this._viewshedType === w.CONE && this._updatePrimitive());
371
+ }
372
+ /**
373
+ * Getter for the heading of a cone viewshed.
374
+ * @returns {number} The heading in degress.
375
+ */
376
+ get heading() {
377
+ return this._headingPitchRollValues.heading * O.DEGREES_PER_RADIAN;
378
+ }
379
+ /**
380
+ * Sets the pitch of a cone viewshed. 0 is horizontal. Does not have impact on 360 viewshed.
381
+ * @param {number} value The pitch in degrees.
382
+ */
383
+ set pitch(e) {
384
+ if (this._headingPitchRollValues.pitch = e * O.RADIANS_PER_DEGREE, this._shadowCamera) {
385
+ const t = e * O.RADIANS_PER_DEGREE - this._shadowCamera.pitch;
386
+ this._shadowCamera.lookUp(t), this._viewshedType === w.CONE && this._updatePrimitive();
387
+ }
388
+ }
389
+ /**
390
+ * Getter for the pitch of a cone viewshed.
391
+ * @returns {number} The pitch in degrees.
392
+ */
393
+ get pitch() {
394
+ return this._headingPitchRollValues.pitch * O.DEGREES_PER_RADIAN;
395
+ }
396
+ /**
397
+ * Sets whether the primitive of the viewshed should be shown or not.
398
+ * @param {boolean} value
399
+ */
400
+ set showPrimitive(e) {
401
+ this._showPrimitive = e, this._updatePrimitive();
402
+ }
403
+ /**
404
+ * Gets if the primitive of the viewshed is shown or not.
405
+ * @returns {boolean}
406
+ */
407
+ get showPrimitive() {
408
+ return this._showPrimitive;
409
+ }
410
+ /**
411
+ * Retruns the type of the Viewshed.
412
+ * @returns {ViewshedTypes}
413
+ */
414
+ get type() {
415
+ return this._viewshedType;
416
+ }
417
+ /**
418
+ * Deactivates the viewshed by removing primitve and removing shadowMap.
419
+ */
420
+ deactivate() {
421
+ var e, t, i, o;
422
+ this._active && (this._removePrimitive(), (e = this._shadowMapChangedListener) == null || e.call(this), ((i = (t = this._cesiumMap) == null ? void 0 : t.getScene()) == null ? void 0 : i.shadowMap) === this._shadowMap && this._cesiumMap.setDefaultShadowMap(), (o = this._shadowMap) == null || o.destroy(), this._shadowCamera = null, this._scene = null, this._cesiumMap = null, this._active = !1);
423
+ }
424
+ /**
425
+ * Activates viewshed. Sets the CesiumMap and adds shadowMapChanged listener to CesiumMap. If viewshed is active but
426
+ * @param {import("@vcmap/core").CesiumMap} cesiumMap The cesium map to which the shadow map of the viewshed is applied to.
427
+ */
428
+ activate(e) {
429
+ if (this._active || (this._active = !0), e !== this._cesiumMap) {
430
+ this._cesiumMap = e;
431
+ const t = e.getScene();
432
+ if (t)
433
+ this._shadowCamera = dt(t, this._frustumOptions), this._position && (this.position = this._position), this._scene = t;
434
+ else
435
+ throw new Error("CesiumMap contains no scene");
436
+ this._updateShadowMap(), this._updatePrimitive(), this._shadowMapChangedListener = this._cesiumMap.shadowMapChanged.addEventListener(() => {
437
+ this.deactivate();
438
+ });
439
+ }
440
+ }
441
+ /**
442
+ * Updates the shadow map by creating a new one and applying all the current parameters.
443
+ */
444
+ _updateShadowMap() {
445
+ !this._active || !this._shadowCamera || !this._cesiumMap || !this._scene || (this._shadowMap = new Re({
446
+ // @ts-ignore
447
+ context: this._scene.context,
448
+ lightCamera: this._shadowCamera,
449
+ enabled: !0,
450
+ isPointLight: this._viewshedType === w.THREESIXTY,
451
+ softShadows: !0,
452
+ fromLightSource: !0,
453
+ cascadesEnabled: !1,
454
+ pointLightRadius: this._shadowCamera.frustum.far,
455
+ maximumDistance: 200,
456
+ size: 2048
457
+ }), this._shadowMap.viewshed = this._colors, this._scene.shadowMap = this._shadowMap, this._cesiumMap.setShadowMap(this._shadowMap));
458
+ }
459
+ _removePrimitive() {
460
+ var e;
461
+ this._primitive && ((e = this._scene) == null || e.primitives.remove(this._primitive), this._primitive.destroy(), this._primitive = null);
462
+ }
463
+ _updatePrimitive() {
464
+ this._showPrimitive && this._active && this._scene ? (this._removePrimitive(), this._primitive = new ct({
465
+ camera: this._shadowCamera,
466
+ allowPicking: !1,
467
+ spot: this._viewshedType === w.CONE
468
+ }), this._scene.primitives.add(this._primitive)) : this._removePrimitive();
469
+ }
470
+ /**
471
+ * Sets distance and, in case of cone viewsheds, also heading and pitch. Only works when viewshed is **active**.
472
+ * @param {number[]} target Point to calculate distance, heading and pitch from.
473
+ */
474
+ lookAt(e) {
475
+ if (!this._shadowCamera)
476
+ return;
477
+ const t = S.fromDegrees(e[0], e[1], e[2]);
478
+ if (this.distance = S.distance(this._shadowCamera.position, t), this.type === w.CONE && !t.equals(this._shadowCamera.position)) {
479
+ const i = new S();
480
+ S.subtract(t, this._shadowCamera.position, t), S.normalize(t, t), S.normalize(this._shadowCamera.position, i), this._shadowCamera.setView({
481
+ orientation: {
482
+ direction: t,
483
+ up: i
484
+ }
485
+ }), this._headingPitchRollValues.heading = this._shadowCamera.heading, this._headingPitchRollValues.pitch = this._shadowCamera.pitch;
486
+ }
487
+ this._updatePrimitive();
488
+ }
489
+ /**
490
+ * Returns an object with all the settings of a viewshed instance.
491
+ * @returns {ViewshedOptions}
492
+ */
493
+ toJSON() {
494
+ return {
495
+ ...super.toJSON(),
496
+ viewshedType: this.type,
497
+ position: this.position,
498
+ frustumOptions: { ...this._frustumOptions },
499
+ orientation: { ...this._headingPitchRollValues },
500
+ colorOptions: {
501
+ visibleColor: this._colors.visibleColor.toCssHexString(),
502
+ shadowColor: this._colors.shadowColor.toCssHexString()
503
+ },
504
+ showPrimitive: this.showPrimitive,
505
+ heightOffset: this.heightOffset
506
+ };
507
+ }
508
+ /**
509
+ * Destroys the viewshed.
510
+ */
511
+ destroy() {
512
+ this.deactivate();
513
+ }
514
+ };
515
+ Z(E, "MIN_DISTANCE", 10);
516
+ let T = E;
517
+ class ht extends we {
518
+ /**
519
+ *
520
+ * @param {import("./viewshed").default} viewshed
521
+ */
522
+ constructor(e) {
523
+ super(D.CLICKMOVE), this._viewshed = e, this._positioned = new L(), this._finished = new L(), this._position = !1, this.setActive();
524
+ }
525
+ get finished() {
526
+ return this._finished;
527
+ }
528
+ get positioned() {
529
+ return this._positioned;
530
+ }
531
+ async pipe(e) {
532
+ return e.position && (this._position ? (this._viewshed.lookAt(I.mercatorToWgs84(e.position)), e.type & D.CLICK && (this.setActive(!1), this._finished.raiseEvent(null))) : (this._viewshed.position = I.mercatorToWgs84(e.position), e.type & D.CLICK && (this._position = !0, this._positioned.raiseEvent(null)))), e;
533
+ }
534
+ destroy() {
535
+ super.destroy(), this._finished.destroy(), this._positioned.destroy();
536
+ }
537
+ }
538
+ const V = {
539
+ ABSOLUTE: "absolute",
540
+ RELATIVE: "relative"
541
+ }, g = {
542
+ CREATE: "create",
543
+ VIEW: "view",
544
+ EDIT: "edit",
545
+ MOVE: "move",
546
+ MULTI_SELECT: "multiSelect"
547
+ }, se = 1.8;
548
+ function ut(s) {
549
+ const e = new Ce({
550
+ projection: Ee.toJSON(),
551
+ zIndex: Ve - 1
552
+ });
553
+ ye(e), e.activate();
554
+ const t = new We(new Be(s));
555
+ return t.setStyle(new ze({})), e.addFeatures([t]), e.vectorProperties.altitudeMode = Ne.NONE, {
556
+ layer: e,
557
+ feature: t,
558
+ destroy() {
559
+ t.dispose(), e.destroy();
560
+ }
561
+ };
562
+ }
563
+ function U(s, e) {
564
+ const t = e === V.ABSOLUTE ? D.CLICKMOVE : D.NONE;
565
+ s.setActive(t), s.pickPosition = t, s.pullPickedPosition = 1.8;
566
+ }
567
+ function ft(s, e, t) {
568
+ const i = H(null), o = A(null), r = A(null), a = A(V.ABSOLUTE);
569
+ let l = () => {
570
+ };
571
+ const n = H(null);
572
+ function u(d) {
573
+ var f, h;
574
+ o.value && i.value ? (i.value.deactivate(), t.setVisibility(i.value.name, !1)) : (f = i.value) == null || f.destroy(), i.value = d, (h = i.value) == null || h.activate(s.maps.activeMap);
575
+ }
576
+ function c(d = !0) {
577
+ l(), u(null), d && t.clearSelection(), o.value = null, r.value = null;
578
+ }
579
+ async function m(d) {
580
+ c(), await xe();
581
+ const { eventHandler: f } = s.maps, { featureInteraction: h } = f;
582
+ i.value = new T(
583
+ {
584
+ viewshedType: d,
585
+ colorOptions: {
586
+ visibleColor: e.visibleColor,
587
+ shadowColor: e.shadowColor
588
+ },
589
+ heightOffset: a.value === V.ABSOLUTE ? 0 : se
590
+ },
591
+ /** @type {import("@vcmap/core").CesiumMap} */
592
+ s.maps.activeMap
593
+ );
594
+ const p = new ht(i.value);
595
+ p.finished.addEventListener(() => {
596
+ l(), i.value ? (i.value.showPrimitive = !0, r.value = g.EDIT) : c();
597
+ });
598
+ const C = f.addExclusiveInteraction(
599
+ p,
600
+ () => {
601
+ p.destroy();
602
+ }
603
+ );
604
+ U(h, a.value), p.positioned.addEventListener(() => {
605
+ U(h, V.ABSOLUTE);
606
+ }), l = () => {
607
+ C(), p.destroy(), h.setActive(), l = () => {
608
+ };
609
+ }, r.value = g.CREATE;
610
+ }
611
+ function v(d) {
612
+ var f;
613
+ if (i.value && d) {
614
+ l();
615
+ const {
616
+ layer: h,
617
+ feature: p,
618
+ destroy: C
619
+ } = ut(i.value.position);
620
+ s.layers.add(h), a.value === V.ABSOLUTE ? (n.value = ge(s, h), n.value.setFeatures([p])) : (n.value = _e(s, h), n.value.setFeature(p)), n.value.stopped.addEventListener(() => {
621
+ l();
622
+ });
623
+ const b = (f = p.getGeometry()) == null ? void 0 : f.on("change", () => {
624
+ i.value ? i.value.position = I.mercatorToWgs84(
625
+ /** @type {import("ol/geom").Point} */
626
+ p.getGeometry().getCoordinates()
627
+ ) : c();
628
+ });
629
+ r.value = g.MOVE, l = () => {
630
+ var N;
631
+ l = () => {
632
+ }, b && je(b), (N = n.value) == null || N.stop(), n.value = null, s.layers.remove(h), C(), r.value = g.EDIT;
633
+ };
634
+ } else
635
+ l();
636
+ }
637
+ function _(d, f) {
638
+ l(), i.value !== f && (u(f), a.value = f.heightOffset ? V.RELATIVE : V.ABSOLUTE), o.value = !!f.properties.title, r.value = d, o.value && t.setVisibility(f.name, !0);
639
+ }
640
+ const y = [
641
+ t.collectionComponent.collection.removed.addEventListener(
642
+ (d) => {
643
+ var f;
644
+ t.remove(d.name), ((f = i.value) == null ? void 0 : f.name) === d.name && c();
645
+ }
646
+ ),
647
+ t.renamed.addEventListener(({ item: d, title: f }) => {
648
+ var p;
649
+ const h = s.windowManager.get(
650
+ `${t.collectionComponent.id}-editor`
651
+ );
652
+ h && ((p = i.value) == null ? void 0 : p.name) === d.name && (h.state.headerTitle = f);
653
+ }),
654
+ t.visibilityChanged.addEventListener((d) => {
655
+ var h;
656
+ const f = ((h = i.value) == null ? void 0 : h.name) === d.name;
657
+ f ? c() : (_(g.VIEW, d), t.clearSelection()), t.setVisibility(d.name, !f);
658
+ })
659
+ ];
660
+ function $(d) {
661
+ if (!(d === a.value || !i.value)) {
662
+ if (a.value = d, r.value === g.MOVE && l(), r.value === g.CREATE)
663
+ U(
664
+ s.maps.eventHandler.featureInteraction,
665
+ d
666
+ ), i.value.heightOffset = d === V.ABSOLUTE ? 0 : se;
667
+ else if (r.value === g.EDIT) {
668
+ const { position: f, heightOffset: h } = i.value;
669
+ d === V.RELATIVE ? s.maps.activeMap.getHeightFromTerrain([I.wgs84ToMercator(f)]).then((p) => {
670
+ const C = I.mercatorToWgs84(p[0]);
671
+ i.value && (i.value.heightOffset = f[2] - C[2], i.value.position = C);
672
+ }) : (i.value.position = [
673
+ f[0],
674
+ f[1],
675
+ f[2] + h
676
+ ], i.value.heightOffset = 0);
677
+ }
678
+ }
679
+ }
680
+ return {
681
+ currentViewshed: i,
682
+ currentIsPersisted: o,
683
+ currentEditSession: n,
684
+ createViewshed: m,
685
+ viewViewshed(d) {
686
+ _(g.VIEW, d);
687
+ },
688
+ editViewshed(d) {
689
+ _(g.EDIT, d), o.value && (t.setSelection(d.name), t.collectionComponent.openEditorWindow(d));
690
+ },
691
+ persistCurrent() {
692
+ i.value && (t.add(i.value), o.value = !0, t.setSelection(i.value.name), t.setVisibility(i.value.name, !0));
693
+ },
694
+ moveCurrentViewshed: v,
695
+ setupMultiSelect() {
696
+ l(), r.value = g.MULTI_SELECT, u(null);
697
+ },
698
+ mode: r,
699
+ heightMode: a,
700
+ changeHeightMode: $,
701
+ async placeCurrentFeaturesOnTerrain() {
702
+ var d, f;
703
+ if (i.value && ((d = n.value) == null ? void 0 : d.type) === me.EDIT_FEATURES && s.maps.activeMap instanceof B) {
704
+ const p = (await s.maps.activeMap.getHeightFromTerrain([
705
+ I.wgs84ToMercator((f = i.value) == null ? void 0 : f.position)
706
+ ]))[0][2] - i.value.position[2];
707
+ n.value.translate(0, 0, p);
708
+ }
709
+ },
710
+ stop: c,
711
+ destroy() {
712
+ c(), y.forEach((d) => d());
713
+ }
714
+ };
715
+ }
716
+ function he(s, e, t, i, o, r, a, l) {
717
+ var n = typeof s == "function" ? s.options : s;
718
+ e && (n.render = e, n.staticRenderFns = t, n._compiled = !0), i && (n.functional = !0), r && (n._scopeId = "data-v-" + r);
719
+ var u;
720
+ if (a ? (u = function(v) {
721
+ v = v || // cached call
722
+ this.$vnode && this.$vnode.ssrContext || // stateful
723
+ this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext, !v && typeof __VUE_SSR_CONTEXT__ < "u" && (v = __VUE_SSR_CONTEXT__), o && o.call(this, v), v && v._registeredComponents && v._registeredComponents.add(a);
724
+ }, n._ssrRegister = u) : o && (u = l ? function() {
725
+ o.call(
726
+ this,
727
+ (n.functional ? this.parent : this).$root.$options.shadowRoot
728
+ );
729
+ } : o), u)
730
+ if (n.functional) {
731
+ n._injectStyles = u;
732
+ var c = n.render;
733
+ n.render = function(_, y) {
734
+ return u.call(y), c(_, y);
735
+ };
736
+ } else {
737
+ var m = n.beforeCreate;
738
+ n.beforeCreate = m ? [].concat(m, u) : [u];
739
+ }
740
+ return {
741
+ exports: s,
742
+ options: n
743
+ };
744
+ }
745
+ const vt = {
746
+ distance: [T.MIN_DISTANCE, 2e3],
747
+ fov: [25, 85],
748
+ heading: [0, 360],
749
+ pitch: [-90, 90]
750
+ }, pt = {
751
+ components: {
752
+ VcsTextField: Ge,
753
+ VContainer: ae,
754
+ VRow: le,
755
+ VCol: ce,
756
+ VcsSlider: Ue,
757
+ VcsLabel: oe,
758
+ VcsFormSection: ne,
759
+ VDivider: tt,
760
+ VcsSelect: re,
761
+ VcsFormButton: He,
762
+ VcsFeatureTransforms: Xe
763
+ },
764
+ name: "ViewshedWindow",
765
+ props: {
766
+ getViewshed: {
767
+ type: Function,
768
+ required: !1,
769
+ default: void 0
770
+ },
771
+ selection: {
772
+ type: Object,
773
+ required: !1,
774
+ default: void 0
775
+ }
776
+ },
777
+ setup(s) {
778
+ const e = (
779
+ /** @type {import("./viewshedManager.js").ViewshedManager} */
780
+ ie("manager")
781
+ ), t = (
782
+ /** @type {import("@vcmap/ui").VcsUiApp} */
783
+ ie("vcsApp")
784
+ ), {
785
+ currentViewshed: i,
786
+ mode: o,
787
+ currentIsPersisted: r
788
+ } = e, a = A(s.selection);
789
+ let l = () => {
790
+ };
791
+ const n = j({
792
+ X: void 0,
793
+ Y: void 0,
794
+ Z: void 0
795
+ }), u = H();
796
+ let c = () => {
797
+ };
798
+ const m = j({
799
+ showPrimitive: !1,
800
+ distance: void 0,
801
+ fov: void 0,
802
+ heading: void 0,
803
+ pitch: void 0
804
+ }), v = A();
805
+ function _() {
806
+ i.value && (n.X = i.value.position[0], n.Y = i.value.position[1], n.Z = e.heightMode.value === V.ABSOLUTE ? i.value.position[2] : i.value.heightOffset);
807
+ }
808
+ function y() {
809
+ _(), i.value && (m.distance = i.value.distance, m.fov = i.value.fov, m.heading = i.value.heading, m.pitch = i.value.pitch, m.showPrimitive = i.value.showPrimitive, v.value = i.value.type);
810
+ }
811
+ De(() => {
812
+ i.value && o.value !== g.CREATE && y();
813
+ }), R(
814
+ i,
815
+ () => {
816
+ i.value && (l(), l = i.value.positionChanged.addEventListener(() => {
817
+ _(), c();
818
+ }));
819
+ },
820
+ { immediate: !0 }
821
+ );
822
+ async function $() {
823
+ var C, b;
824
+ (C = i.value) == null || C.deactivate();
825
+ const h = (
826
+ /** @type {import("@vcmap/core").CesiumMap} */
827
+ (b = t.maps.activeMap.getScene()) == null ? void 0 : b.camera
828
+ ), p = h == null ? void 0 : h.changed.addEventListener(() => {
829
+ c();
830
+ });
831
+ c = () => {
832
+ var N;
833
+ p == null || p(), u.value = null, (N = i.value) == null || N.activate(t.maps.activeMap), c = () => {
834
+ };
835
+ };
836
+ }
837
+ Le(() => {
838
+ var p;
839
+ const h = (p = s.getViewshed) == null ? void 0 : p.call(s);
840
+ h && e.editViewshed(h);
841
+ }), Fe(() => {
842
+ l(), c(), r.value || ((o.value === g.EDIT || o.value === g.MOVE) && i.value ? e.viewViewshed(i.value) : o.value === g.CREATE && e.stop()), a.value && (a.value.length > 1 ? e.setupMultiSelect() : a.value.length === 1 && i.value ? e.viewViewshed(i.value) : (
843
+ // when a persited viewshed is deselected, stops plugin
844
+ !a.value.length && o.value === g.EDIT && e.stop(!1)
845
+ ));
846
+ }), y();
847
+ function d(h, p) {
848
+ c(), i.value && (m[h] = p, i.value[h] = p);
849
+ }
850
+ const f = ke(() => {
851
+ const h = [];
852
+ return v.value === w.CONE && h.push({
853
+ name: "jumpToViewpoint",
854
+ title: u.value ? "viewshed.returnToViewpoint" : "viewshed.jumpToViewpoint",
855
+ icon: "mdi-human-male",
856
+ active: !!u.value,
857
+ async callback() {
858
+ var p, C, b;
859
+ e.moveCurrentViewshed(!1), i.value && !u.value ? (u.value = await ((p = t.maps.activeMap) == null ? void 0 : p.getViewpoint()), await ((C = t.maps.activeMap) == null ? void 0 : C.gotoViewpoint(
860
+ new be({
861
+ groundPosition: [
862
+ i.value.position[0],
863
+ i.value.position[1],
864
+ i.value.position[2] + i.value.heightOffset
865
+ ],
866
+ heading: i.value.heading,
867
+ pitch: i.value.pitch,
868
+ distance: 0,
869
+ animate: !0
870
+ // if not animate, async does not work and the cameraChanged listener is triggered immediately. alternatively set timeout
871
+ })
872
+ )), $()) : u.value && ((b = t.maps.activeMap) == null || b.gotoViewpoint(u.value), c());
873
+ }
874
+ }), h.push({
875
+ name: "moveViewshed",
876
+ title: "viewshed.move",
877
+ icon: e.heightMode.value === V.RELATIVE ? "$vcsEditVertices" : "mdi-axis-arrow",
878
+ active: o.value === g.MOVE,
879
+ callback() {
880
+ e.moveCurrentViewshed(
881
+ o.value !== g.MOVE
882
+ );
883
+ }
884
+ }), h.unshift({
885
+ name: "showPrimitive",
886
+ title: "viewshed.showPrimitive",
887
+ icon: "mdi-eye",
888
+ active: m.showPrimitive,
889
+ callback() {
890
+ this.active = !this.active, d("showPrimitive", this.active);
891
+ }
892
+ }), h;
893
+ });
894
+ return {
895
+ position: n,
896
+ setPosition(h, p, C) {
897
+ if (c(), !!i.value) {
898
+ if (C === 2 && e.heightMode.value === V.RELATIVE)
899
+ i.value.heightOffset = Number(h);
900
+ else {
901
+ const b = [...i.value.position];
902
+ b[C] = Number(h), i.value.position = b;
903
+ }
904
+ n[p] = Number(h);
905
+ }
906
+ },
907
+ parameters: m,
908
+ setParameter: d,
909
+ parameterRanges: vt,
910
+ ViewshedPluginModes: g,
911
+ viewshedMode: o,
912
+ currentIsPersisted: r,
913
+ viewshedType: v,
914
+ ViewshedTypes: w,
915
+ HeightModes: V,
916
+ heightMode: e.heightMode,
917
+ TransformationMode: Me,
918
+ changeHeightMode: e.changeHeightMode,
919
+ async createNewViewshed() {
920
+ await e.createViewshed(v.value);
921
+ },
922
+ addToMyWorkspace: () => e.persistCurrent(),
923
+ cancel: () => e.stop(),
924
+ headerActions: f
925
+ };
926
+ }
927
+ };
928
+ var wt = function() {
929
+ var e = this, t = e._self._c;
930
+ return t("div", [e.viewshedMode === e.ViewshedPluginModes.CREATE ? t("div", { staticClass: "px-2 py-1" }, [e._v(" " + e._s(e.$t("viewshed.createDescription")) + " ")]) : e.viewshedMode === e.ViewshedPluginModes.EDIT || e.viewshedMode === e.ViewshedPluginModes.MOVE ? t("VcsFormSection", { attrs: { "header-actions": e.headerActions, heading: "viewshed.viewpoint", "action-button-list-overflow-count": 3 } }, [t("v-container", { staticClass: "px-1 py-0" }, [t("v-row", { attrs: { "no-gutters": "" } }, [t("span", { staticClass: "px-1 py-0" }, [e._v(e._s(e.$t("viewshed.position")))])]), e.viewshedMode === e.ViewshedPluginModes.MOVE && e.heightMode === e.HeightModes.ABSOLUTE ? t("v-row", { attrs: { "no-gutters": "" } }, [t("VcsFeatureTransforms", { attrs: { "transformation-mode": e.TransformationMode.TRANSLATE, "feature-properties": { altitudeMode: "absolute" }, "allow-z-input": !0 } })], 1) : t("v-row", { attrs: { "no-gutters": "" } }, e._l(e.position, function(i, o, r) {
931
+ return t("v-col", { key: r, staticClass: "pb-1" }, [t("VcsTextField", { attrs: { value: i, type: "number", prefix: o, "show-spin-buttons": !0, step: o === "Z" ? 1 : 1e-4, unit: o === "Z" ? "m" : "°", decimals: o === "Z" ? 2 : 8, disabled: e.viewshedMode === e.ViewshedPluginModes.MOVE && !(o === "Z" && e.heightMode === e.HeightModes.RELATIVE) }, on: { input: (a) => e.setPosition(a, o, r) } })], 1);
932
+ }), 1)], 1)], 1) : e._e(), t("v-divider"), t("v-container", { staticClass: "px-1 py-0" }, [t("v-row", { attrs: { "no-gutters": "" } }, [t("v-col", [t("VcsLabel", [e._v(" " + e._s(e.$t("viewshed.heightMode")) + " ")])], 1), t("v-col", [t("VcsSelect", { attrs: { items: Object.values(e.HeightModes).map((i) => ({
933
+ value: i,
934
+ text: `viewshed.${i}`
935
+ })), value: e.heightMode }, on: { input: e.changeHeightMode } })], 1)], 1)], 1), e.viewshedMode === e.ViewshedPluginModes.EDIT || e.viewshedMode === e.ViewshedPluginModes.MOVE ? t("v-container", { staticClass: "px-1 pt-0 pb-2" }, e._l(e.parameters, function(i, o) {
936
+ return t("v-row", { key: o, attrs: { "no-gutters": "" } }, [o === "distance" || e.viewshedType === e.ViewshedTypes.CONE && o !== "showPrimitive" ? t("v-col", [t("v-row", { staticClass: "pr-1", attrs: { "no-gutters": "" } }, [t("v-col", [t("VcsLabel", { attrs: { "html-for": o } }, [e._v(" " + e._s(e.$t(`viewshed.${o}`)) + " ")])], 1), t("v-col", { staticClass: "d-flex justify-end align-center" }, [o === "distance" ? t("span", [e._v(e._s(`${i} m`))]) : t("span", [e._v(e._s(`${i} °`))])])], 1), t("v-row", { attrs: { "no-gutters": "" } }, [t("v-col", [t("VcsSlider", { attrs: { id: o, value: i, type: "number", step: "1", min: e.parameterRanges[o][0], max: e.parameterRanges[o][1], height: "15" }, on: { input: (r) => e.setParameter(o, r) } })], 1)], 1)], 1) : e._e()], 1);
937
+ }), 1) : e._e(), t("v-divider"), e.viewshedMode === e.ViewshedPluginModes.EDIT || e.viewshedMode === e.ViewshedPluginModes.MOVE ? t("div", { staticClass: "d-flex w-full justify-space-between px-2 pt-2 pb-1" }, [t("VcsFormButton", { attrs: { tooltip: "viewshed.addToMyWorkspace", icon: "$vcsComponentsPlus", disabled: e.currentIsPersisted || void 0 }, on: { click: function(i) {
938
+ return e.addToMyWorkspace();
939
+ } } }), t("VcsFormButton", { attrs: { variant: "filled" }, on: { click: function(i) {
940
+ return e.createNewViewshed();
941
+ } } }, [e._v(" " + e._s(e.$t("viewshed.new")) + " ")])], 1) : e.viewshedMode === e.ViewshedPluginModes.CREATE ? t("div", { staticClass: "d-flex w-full justify-end px-2 pt-2 pb-1" }, [t("VcsFormButton", { attrs: { variant: "filled" }, on: { click: function(i) {
942
+ return e.cancel();
943
+ } } }, [e._v(" " + e._s(e.$t("viewshed.cancel")) + " ")])], 1) : e._e()], 1);
944
+ }, mt = [], gt = /* @__PURE__ */ he(
945
+ pt,
946
+ wt,
947
+ mt,
948
+ !1,
949
+ null,
950
+ null,
951
+ null,
952
+ null
953
+ );
954
+ const _t = gt.exports, P = "@vcmap/viewshed", Ct = "2.0.1", Et = "^5.1", Y = {
955
+ [w.CONE]: "$vcsViewshed",
956
+ [w.THREESIXTY]: "$vcsViewshedCone"
957
+ };
958
+ function Vt(s, e, t) {
959
+ const i = A(), o = A(), r = `${t.id}-editor`, a = {
960
+ component: _t,
961
+ provides: {
962
+ manager: s
963
+ },
964
+ state: {
965
+ headerTitle: i,
966
+ headerIcon: o,
967
+ styles: { width: "280px", height: "auto" },
968
+ infoUrlCallback: e.getHelpUrlCallback("tools/viewshedTool.html")
969
+ }
970
+ };
971
+ Ke(e, t, {
972
+ editor: (v) => ({
973
+ ...a,
974
+ props: {
975
+ selection: t.selection,
976
+ getViewshed: () => t.collection.getByKey(v.name)
977
+ }
978
+ })
979
+ });
980
+ function l() {
981
+ s.currentViewshed.value && (o.value = Y[s.currentViewshed.value.type], s.currentIsPersisted.value ? i.value = s.currentViewshed.value.properties.title : s.mode.value === g.CREATE ? i.value = [
982
+ "viewshed.create",
983
+ `viewshed.${s.currentViewshed.value.type}`
984
+ ] : i.value = [
985
+ "viewshed.temporary",
986
+ `viewshed.${s.currentViewshed.value.type}`
987
+ ]);
988
+ }
989
+ function n() {
990
+ l(), s.currentViewshed.value && !s.currentIsPersisted.value && (s.mode.value === g.EDIT || s.mode.value === g.MOVE || s.mode.value === g.CREATE) && (e.windowManager.has(r) || e.windowManager.add(
991
+ {
992
+ ...a,
993
+ id: r,
994
+ parentId: "category-manager",
995
+ slot: Ye.DYNAMIC_LEFT
996
+ },
997
+ P
998
+ ));
999
+ }
1000
+ const u = R(s.currentViewshed, (v) => {
1001
+ v && n();
1002
+ }), c = R(s.currentIsPersisted, (v) => {
1003
+ v && l();
1004
+ }), m = R(s.mode, () => {
1005
+ s.mode.value ? n() : e.windowManager.remove(r);
1006
+ });
1007
+ return {
1008
+ destroy() {
1009
+ e.windowManager.remove(r), u(), m(), c();
1010
+ }
1011
+ };
1012
+ }
1013
+ function yt(s, e, t, i) {
1014
+ const o = {
1015
+ type: Je.SELECT,
1016
+ action: j({
1017
+ name: t,
1018
+ currentIndex: 0,
1019
+ active: !1,
1020
+ background: !1,
1021
+ disabled: !1,
1022
+ callback() {
1023
+ if (this.active)
1024
+ this.background && e.currentViewshed.value ? e.editViewshed(e.currentViewshed.value) : e.stop();
1025
+ else {
1026
+ const n = this.tools[this.currentIndex].name;
1027
+ e.createViewshed(n);
1028
+ }
1029
+ },
1030
+ selected(n) {
1031
+ if (n !== this.currentIndex) {
1032
+ this.currentIndex = n;
1033
+ const u = this.tools[this.currentIndex].name;
1034
+ e.createViewshed(u);
1035
+ }
1036
+ },
1037
+ tools: i.flatMap((n) => n === w.CONE ? {
1038
+ name: w.CONE,
1039
+ icon: Y[w.CONE],
1040
+ title: `viewshed.${w.CONE}`
1041
+ } : n === w.THREESIXTY ? {
1042
+ name: w.THREESIXTY,
1043
+ icon: Y[w.THREESIXTY],
1044
+ title: `viewshed.${w.THREESIXTY}`
1045
+ } : [])
1046
+ })
1047
+ }, r = R(e.mode, (n) => {
1048
+ n === g.VIEW ? (o.action.background = !0, o.action.active = !0) : n ? (o.action.background = !1, o.action.active = !0) : (o.action.background = !1, o.action.active = !1);
1049
+ }), a = R(
1050
+ e.currentViewshed,
1051
+ (n) => {
1052
+ n && (o.action.currentIndex = o.action.tools.findIndex(
1053
+ (u) => u.name === n.type
1054
+ ));
1055
+ }
1056
+ ), l = s.maps.mapActivated.addEventListener((n) => {
1057
+ n instanceof B ? o.action.disabled = !1 : (o.action.disabled = !0, e.stop());
1058
+ });
1059
+ return {
1060
+ destroy() {
1061
+ r(), a(), l();
1062
+ },
1063
+ toolbox: o
1064
+ };
1065
+ }
1066
+ function bt(s, e, t, i) {
1067
+ z(i, [Object.values(w)]);
1068
+ const { toolbox: o, destroy: r } = yt(s, e, t, i), a = s.toolboxManager.add(o, t).id;
1069
+ return () => {
1070
+ s.toolboxManager.remove(a), r();
1071
+ };
1072
+ }
1073
+ class J extends Te {
1074
+ static get className() {
1075
+ return "ViewshedCategory";
1076
+ }
1077
+ async _deserializeItem(e) {
1078
+ var i;
1079
+ const t = (
1080
+ /** @type {import("@vcmap/core").CesiumMap | undefined} */
1081
+ (i = this._app) == null ? void 0 : i.maps.getByType(B.className)[0]
1082
+ );
1083
+ if (t)
1084
+ return new T(e, t);
1085
+ throw new Error("No CesiumMap available");
1086
+ }
1087
+ }
1088
+ function Mt(s, e) {
1089
+ let t, i = 0;
1090
+ const o = new Set(
1091
+ e.filter((r) => r.type === s).map((r) => r.properties.title)
1092
+ );
1093
+ do
1094
+ i += 1, o.has(`${s}-${i}`) || (t = `${s}-${i}`);
1095
+ while (!t);
1096
+ return t;
1097
+ }
1098
+ async function Tt(s) {
1099
+ const e = new L(), t = new L(), { collectionComponent: i, category: o } = await s.categoryManager.requestCategory(
1100
+ {
1101
+ type: J.className,
1102
+ name: "Viewsheds",
1103
+ title: "Viewsheds"
1104
+ },
1105
+ P,
1106
+ {
1107
+ selectable: !0,
1108
+ renamable: !0,
1109
+ removable: !0
1110
+ }
1111
+ ), r = (c, m, v) => {
1112
+ v.title = c.properties.title, v.titleChanged = (_) => {
1113
+ c.properties.title = _, v.title = _, e.raiseEvent({ item: c, title: _ });
1114
+ }, v.actions.push(
1115
+ j({
1116
+ name: "visibilityAction",
1117
+ icon: "$vcsCheckbox",
1118
+ callback() {
1119
+ t.raiseEvent(c);
1120
+ }
1121
+ })
1122
+ );
1123
+ };
1124
+ s.categoryManager.addMappingFunction(
1125
+ () => !0,
1126
+ r,
1127
+ P,
1128
+ [i.id]
1129
+ );
1130
+ const { action: a, destroy: l } = Ze(
1131
+ i.selection,
1132
+ () => {
1133
+ const c = i.selection.value.map(
1134
+ (m) => i.collection.getByKey(m.name)
1135
+ );
1136
+ qe(JSON.stringify(c), "viewsheds.json");
1137
+ },
1138
+ P
1139
+ ), { action: n, destroy: u } = Qe(
1140
+ async (c) => {
1141
+ const m = c.map((v) => {
1142
+ const _ = new FileReader();
1143
+ return new Promise((y, $) => {
1144
+ _.onload = () => {
1145
+ try {
1146
+ JSON.parse(_.result).forEach((f) => {
1147
+ const h = new T(f);
1148
+ o.collection.add(h);
1149
+ }), y();
1150
+ } catch (d) {
1151
+ $(d);
1152
+ }
1153
+ }, _.readAsText(v);
1154
+ });
1155
+ });
1156
+ await Promise.all(m);
1157
+ },
1158
+ s.windowManager,
1159
+ P,
1160
+ "category-manager"
1161
+ );
1162
+ return i.addActions([a, n]), {
1163
+ renamed: e,
1164
+ visibilityChanged: t,
1165
+ setSelection(c) {
1166
+ c && (i.selection.value = i.items.value.filter((m) => c === m.name));
1167
+ },
1168
+ clearSelection() {
1169
+ i.selection.value.length && (i.selection.value = []);
1170
+ },
1171
+ setVisibility(c, m) {
1172
+ const v = i.items.value.find(
1173
+ (_) => c === _.name
1174
+ );
1175
+ if (v) {
1176
+ const _ = v.actions.find(
1177
+ (y) => y.name === "visibilityAction"
1178
+ );
1179
+ _ && (_.icon = m ? "$vcsCheckboxChecked" : "$vcsCheckbox");
1180
+ }
1181
+ },
1182
+ add(c) {
1183
+ c.properties.title = Mt(
1184
+ c.type,
1185
+ /** @type {import("./viewshed.js").default[]} */
1186
+ [
1187
+ ...o.collection
1188
+ ]
1189
+ ), o.collection.add(c);
1190
+ },
1191
+ remove(c) {
1192
+ const m = o.collection.getByKey(c);
1193
+ m && o.collection.remove(m);
1194
+ },
1195
+ collectionComponent: i,
1196
+ destroy() {
1197
+ s.categoryManager.removeOwner(P), e.destroy(), t.destroy(), l(), u();
1198
+ }
1199
+ };
1200
+ }
1201
+ function F() {
1202
+ return {
1203
+ visibleColor: T.getDefaultOptions().visibleColor,
1204
+ shadowColor: T.getDefaultOptions().shadowColor,
1205
+ tools: [...Object.values(w)]
1206
+ };
1207
+ }
1208
+ const Ot = {
1209
+ name: "ViewshedConfigEditor",
1210
+ title: "Viewshed Editor",
1211
+ components: {
1212
+ AbstractConfigEditor: et,
1213
+ VcsFormSection: ne,
1214
+ VContainer: ae,
1215
+ VRow: le,
1216
+ VCol: ce,
1217
+ VcsLabel: oe,
1218
+ VcsSelect: re,
1219
+ VColorPicker: it
1220
+ },
1221
+ props: {
1222
+ getConfig: {
1223
+ type: Function,
1224
+ required: !0
1225
+ },
1226
+ setConfig: {
1227
+ type: Function,
1228
+ required: !0
1229
+ }
1230
+ },
1231
+ setup(s) {
1232
+ const e = A({});
1233
+ s.getConfig().then((i) => {
1234
+ e.value = Object.assign(F(), i);
1235
+ });
1236
+ async function t() {
1237
+ await s.setConfig(e.value);
1238
+ }
1239
+ return {
1240
+ localConfig: e,
1241
+ ViewshedTypes: w,
1242
+ apply: t,
1243
+ toolItems: Object.values(w).map((i) => ({
1244
+ value: i,
1245
+ text: `viewshed.${i}`
1246
+ }))
1247
+ };
1248
+ }
1249
+ };
1250
+ var St = function() {
1251
+ var e = this, t = e._self._c;
1252
+ return t("AbstractConfigEditor", e._b({ on: { submit: e.apply } }, "AbstractConfigEditor", { ...e.$attrs, ...e.$props }, !1), [e.localConfig ? t("VcsFormSection", { attrs: { heading: "viewshed.editor.general" } }, [t("v-container", { staticClass: "px-1 py-0" }, [t("v-row", { attrs: { "no-gutters": "" } }, [t("v-col", [t("VcsLabel", { attrs: { "html-for": "viewshed-editor-tools" } }, [e._v(e._s(e.$t("viewshed.editor.tools")))])], 1), t("v-col", [t("VcsSelect", { attrs: { id: "viewshed-tools", items: e.toolItems, multiple: !0 }, model: { value: e.localConfig.tools, callback: function(i) {
1253
+ e.$set(e.localConfig, "tools", i);
1254
+ }, expression: "localConfig.tools" } })], 1)], 1), t("v-row", { attrs: { "no-gutters": "" } }, [t("v-col", [t("VcsLabel", { attrs: { "html-for": "viewshed-editor-visible-color" } }, [e._v(e._s(e.$t("viewshed.editor.visibleColor")))])], 1), t("v-col", [t("VColorPicker", { attrs: { mode: "rgba" }, model: { value: e.localConfig.visibleColor, callback: function(i) {
1255
+ e.$set(e.localConfig, "visibleColor", i);
1256
+ }, expression: "localConfig.visibleColor" } })], 1)], 1), t("v-row", { attrs: { "no-gutters": "" } }, [t("v-col", [t("VcsLabel", { attrs: { "html-for": "viewshed-editor-shadow-color" } }, [e._v(e._s(e.$t("viewshed.editor.shadowColor")))])], 1), t("v-col", [t("VColorPicker", { attrs: { mode: "rgba" }, model: { value: e.localConfig.shadowColor, callback: function(i) {
1257
+ e.$set(e.localConfig, "shadowColor", i);
1258
+ }, expression: "localConfig.shadowColor" } })], 1)], 1)], 1)], 1) : e._e()], 1);
1259
+ }, Pt = [], At = /* @__PURE__ */ he(
1260
+ Ot,
1261
+ St,
1262
+ Pt,
1263
+ !1,
1264
+ null,
1265
+ null,
1266
+ null,
1267
+ null
1268
+ );
1269
+ const It = At.exports;
1270
+ function kt(s) {
1271
+ let e, t = () => {
1272
+ };
1273
+ return {
1274
+ get name() {
1275
+ return P;
1276
+ },
1277
+ get version() {
1278
+ return Ct;
1279
+ },
1280
+ get mapVersion() {
1281
+ return Et;
1282
+ },
1283
+ /**
1284
+ * @param {import("@vcmap/ui").VcsUiApp} vcsUiApp
1285
+ * @param {ViewshedPluginState=} state
1286
+ * @returns {Promise<void>}
1287
+ */
1288
+ async initialize(i, o) {
1289
+ i.categoryClassRegistry.registerClass(
1290
+ this[Oe],
1291
+ J.className,
1292
+ J
1293
+ );
1294
+ const r = await Tt(i);
1295
+ e = ft(
1296
+ i,
1297
+ s,
1298
+ r
1299
+ );
1300
+ const a = bt(
1301
+ i,
1302
+ e,
1303
+ P,
1304
+ s.tools || F().tools
1305
+ ), { destroy: l } = Vt(
1306
+ e,
1307
+ i,
1308
+ r.collectionComponent
1309
+ );
1310
+ t = () => {
1311
+ a(), l(), r.destroy();
1312
+ };
1313
+ const { activeMap: n } = i.maps;
1314
+ if (o != null && o.mode && o.currentViewshed && n instanceof B) {
1315
+ const u = new T(o.currentViewshed, n);
1316
+ o.mode === g.VIEW ? e.viewViewshed(u) : e.editViewshed(u);
1317
+ }
1318
+ },
1319
+ /**
1320
+ * should return all default values of the configuration
1321
+ * @returns {ViewshedPluginOptions}
1322
+ */
1323
+ getDefaultOptions: F,
1324
+ /**
1325
+ * should return the plugin's serialization excluding all default values
1326
+ * @returns {ViewshedPluginOptions}
1327
+ */
1328
+ toJSON() {
1329
+ const i = {};
1330
+ return s.tools && F().tools.length !== s.tools.length && (i.tools = [...s.tools]), s.shadowColor && s.shadowColor !== T.getDefaultOptions().shadowColor && (i.shadowColor = s.shadowColor), s.visibleColor && s.visibleColor !== T.getDefaultOptions().visibleColor && (i.visibleColor = s.visibleColor), i;
1331
+ },
1332
+ /**
1333
+ * should return the plugins state
1334
+ * @returns {ViewshedPluginState}
1335
+ */
1336
+ getState() {
1337
+ var i;
1338
+ return {
1339
+ mode: e.mode.value,
1340
+ currentViewshed: (i = e.currentViewshed.value) == null ? void 0 : i.toJSON()
1341
+ };
1342
+ },
1343
+ /**
1344
+ * components for configuring the plugin and/ or custom items defined by the plugin
1345
+ * @returns {Array<import("@vcmap/ui").PluginConfigEditor>}
1346
+ */
1347
+ getConfigEditors() {
1348
+ return [{ component: It }];
1349
+ },
1350
+ destroy: t,
1351
+ i18n: {
1352
+ en: {
1353
+ viewshed: {
1354
+ distance: "Distance",
1355
+ fov: "Field of view",
1356
+ heading: "Heading",
1357
+ pitch: "Pitch",
1358
+ position: "Position",
1359
+ showPrimitive: "Show viewpoint",
1360
+ viewpoint: "Viewpoint",
1361
+ viewshed: "Viewshed",
1362
+ heightMode: "Height mode",
1363
+ relative: "Relativ to ground",
1364
+ absolute: "Absolute",
1365
+ new: "New",
1366
+ cancel: "Cancel",
1367
+ [w.CONE]: "Cone Viewshed",
1368
+ [w.THREESIXTY]: "360° Viewshed",
1369
+ create: "Create",
1370
+ addToMyWorkspace: "Add to My Workspace",
1371
+ temporary: "Temporary",
1372
+ jumpToViewpoint: "Jump to viewpoint",
1373
+ returnToViewpoint: "Return to previous viewpoint",
1374
+ move: "Move viewpoint",
1375
+ createDescription: "Click the map twice. First click places the origin, second defines the distance and direction of the viewshed.",
1376
+ remove: "Remove",
1377
+ editor: {
1378
+ general: "General",
1379
+ visibleColor: "Visible color",
1380
+ shadowColor: "Shadow color",
1381
+ tools: "Tools"
1382
+ }
1383
+ }
1384
+ },
1385
+ de: {
1386
+ viewshed: {
1387
+ distance: "Distanz",
1388
+ fov: "Sichtfeld",
1389
+ heading: "Ausrichtung",
1390
+ pitch: "Neigung",
1391
+ position: "Position",
1392
+ showPrimitive: "Viewpoint zeigen",
1393
+ viewpoint: "Viewpoint",
1394
+ viewshed: "Viewshed",
1395
+ heightMode: "Höhenmodus",
1396
+ relative: "Relativ zum Gelände",
1397
+ absolute: "Absolut",
1398
+ new: "Neu",
1399
+ cancel: "Abbrechen",
1400
+ [w.CONE]: "Kegel Viewshed",
1401
+ [w.THREESIXTY]: "360° Viewshed",
1402
+ create: "Erzeuge",
1403
+ addToMyWorkspace: "Zu Mein Arbeitsbereich hinzufügen",
1404
+ temporary: "Temporärer",
1405
+ jumpToViewpoint: "Zu Viewpoint springen",
1406
+ returnToViewpoint: "Zu vorherigem Viewpoint zurück springen",
1407
+ move: "Viewpoint verschieben",
1408
+ createDescription: "Klicke zweimal in die Karte. Der erste Klick platziert den Ursprung, der zweite die Distanz und die Richtung des Viewsheds.",
1409
+ remove: "Entfernen",
1410
+ editor: {
1411
+ general: "Generelles",
1412
+ visibleColor: "Sichtbarer Bereich",
1413
+ shadowColor: "Schatten Bereich",
1414
+ tools: "Werkzeuge"
1415
+ }
1416
+ }
1417
+ }
1418
+ }
1419
+ };
1420
+ }
1421
+ export {
1422
+ kt as default
1423
+ };