@vcmap/core 5.0.0-rc.2 → 5.0.0-rc.5

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.
Files changed (51) hide show
  1. package/index.d.ts +287 -95
  2. package/index.js +11 -3
  3. package/package.json +5 -10
  4. package/src/vcs/vcm/category/appBackedCategory.js +41 -0
  5. package/src/vcs/vcm/category/category.js +374 -0
  6. package/src/vcs/vcm/category/categoryCollection.js +145 -0
  7. package/src/vcs/vcm/context.js +73 -0
  8. package/src/vcs/vcm/interaction/coordinateAtPixel.js +1 -1
  9. package/src/vcs/vcm/layer/cesiumTileset.js +1 -1
  10. package/src/vcs/vcm/layer/featureStore.js +3 -3
  11. package/src/vcs/vcm/layer/featureStoreChanges.js +89 -73
  12. package/src/vcs/vcm/layer/geojson.js +3 -5
  13. package/src/vcs/vcm/layer/geojsonHelpers.js +3 -3
  14. package/src/vcs/vcm/layer/oblique/obliqueHelpers.js +2 -2
  15. package/src/vcs/vcm/layer/singleImage.js +2 -1
  16. package/src/vcs/vcm/layer/terrainHelpers.js +4 -8
  17. package/src/vcs/vcm/layer/tileProvider/mvtTileProvider.js +3 -3
  18. package/src/vcs/vcm/layer/tileProvider/staticGeojsonTileProvider.js +3 -3
  19. package/src/vcs/vcm/layer/tileProvider/urlTemplateTileProvider.js +3 -3
  20. package/src/vcs/vcm/layer/vector.js +1 -1
  21. package/src/vcs/vcm/layer/vectorHelpers.js +4 -4
  22. package/src/vcs/vcm/layer/wfs.js +5 -5
  23. package/src/vcs/vcm/maps/cameraLimiter.js +5 -5
  24. package/src/vcs/vcm/maps/map.js +26 -11
  25. package/src/vcs/vcm/maps/oblique.js +8 -8
  26. package/src/vcs/vcm/object.js +1 -1
  27. package/src/vcs/vcm/oblique/ObliqueCollection.js +83 -31
  28. package/src/vcs/vcm/oblique/ObliqueDataSet.js +67 -24
  29. package/src/vcs/vcm/oblique/ObliqueImage.js +1 -1
  30. package/src/vcs/vcm/oblique/ObliqueImageMeta.js +2 -2
  31. package/src/vcs/vcm/oblique/ObliqueProvider.js +10 -7
  32. package/src/vcs/vcm/oblique/helpers.js +12 -40
  33. package/src/vcs/vcm/oblique/parseImageJson.js +17 -9
  34. package/src/vcs/vcm/util/clipping/clippingPlaneHelper.js +4 -4
  35. package/src/vcs/vcm/util/extent.js +16 -9
  36. package/src/vcs/vcm/util/featureProvider/featureProviderHelpers.js +3 -4
  37. package/src/vcs/vcm/util/featureProvider/wmsFeatureProvider.js +11 -6
  38. package/src/vcs/vcm/util/featureconverter/extent3D.js +181 -0
  39. package/src/vcs/vcm/util/fetch.js +32 -0
  40. package/src/vcs/vcm/util/indexedCollection.js +23 -0
  41. package/src/vcs/vcm/util/layerCollection.js +10 -5
  42. package/src/vcs/vcm/util/overrideCollection.js +224 -0
  43. package/src/vcs/vcm/util/projection.js +37 -3
  44. package/src/vcs/vcm/util/style/declarativeStyleItem.js +2 -0
  45. package/src/vcs/vcm/util/style/styleFactory.js +1 -1
  46. package/src/vcs/vcm/util/style/styleItem.js +2 -0
  47. package/src/vcs/vcm/util/style/vectorStyleItem.js +2 -0
  48. package/src/vcs/vcm/util/viewpoint.js +3 -0
  49. package/src/vcs/vcm/vcsApp.js +360 -0
  50. package/src/vcs/vcm/vcsAppContextHelpers.js +108 -0
  51. package/src/vcs/vcm/util/featureconverter/extent3d.js +0 -154
@@ -3,12 +3,15 @@ import { register } from 'ol/proj/proj4.js';
3
3
  import proj4 from 'proj4';
4
4
  import { getLogger as getLoggerByName } from '@vcsuite/logger';
5
5
  import { check } from '@vcsuite/check';
6
+ import { VcsClassRegistry } from '../classRegistry.js';
6
7
 
7
8
  /**
8
9
  * @typedef {Object} ProjectionOptions
10
+ * @property {string} [type]
9
11
  * @property {string|number} [epsg] - EPSG of the projection, for example: "EPSG:4326" if not specified, uses the framework projection
10
12
  * @property {string|undefined|null} [proj4] - definition of the projection. See for example: {@link http://spatialreference.org/ref/epsg/4326/proj4/} proj4
11
13
  * @property {Array<string>|undefined|null} [alias] - aliases to define
14
+ * @property {string|undefined} [prefix='EPSG:'] - an alternate prefix to use for custom projection
12
15
  * @api stable
13
16
  */
14
17
 
@@ -36,7 +39,8 @@ let defaultProjectionOption = {
36
39
  * @returns {string}
37
40
  */
38
41
  function parseEPSGCode(value, prefix = 'EPSG:') {
39
- const matches = `${value}`.match(/^(?:epsg:)?(\d+)/i);
42
+ const regex = new RegExp(`^(?:${prefix})?(\\d+)`, 'i');
43
+ const matches = `${value}`.match(regex);
40
44
  if (matches && matches[1]) {
41
45
  return `${prefix}${matches[1]}`;
42
46
  }
@@ -73,9 +77,11 @@ function validateProjectionOptions(options) {
73
77
  * @returns {ProjectionOptions} valid options
74
78
  */
75
79
  function registerProjection(options) {
76
- const saneOptions = {};
80
+ const saneOptions = {
81
+ prefix: options.prefix,
82
+ };
77
83
  if (options.epsg) {
78
- saneOptions.epsg = parseEPSGCode(options.epsg);
84
+ saneOptions.epsg = parseEPSGCode(options.epsg, options.prefix);
79
85
  if (saneOptions.epsg) {
80
86
  if (options.proj4) {
81
87
  saneOptions.proj4 = options.proj4;
@@ -123,6 +129,11 @@ export function setDefaultProjectionOptions(options) {
123
129
  * @api stable
124
130
  */
125
131
  class Projection {
132
+ /**
133
+ * @returns {string}
134
+ */
135
+ static get className() { return 'vcs.vcm.util.Projection'; }
136
+
126
137
  /**
127
138
  * @param {ProjectionOptions} options
128
139
  */
@@ -143,6 +154,20 @@ class Projection {
143
154
  if (!this.proj) {
144
155
  this._epsg = Projection.parseEPSGCode(defaultProjectionOption.epsg);
145
156
  }
157
+
158
+ /**
159
+ * Cached for toJSON
160
+ * @type {Array<string>}
161
+ * @private
162
+ */
163
+ this._alias = saneOptions.alias;
164
+
165
+ /**
166
+ * Cached for toJSON
167
+ * @type {string}
168
+ * @private
169
+ */
170
+ this._prefix = saneOptions.prefix;
146
171
  }
147
172
 
148
173
  /**
@@ -264,11 +289,18 @@ class Projection {
264
289
  */
265
290
  toJSON() {
266
291
  const configObject = {
292
+ type: Projection.className,
267
293
  epsg: this.epsg,
268
294
  };
269
295
  if (this.proj4) {
270
296
  configObject.proj4 = this.proj4;
271
297
  }
298
+ if (Array.isArray(this._alias) && this._alias.length > 0) {
299
+ configObject.alias = this._alias.slice();
300
+ }
301
+ if (this._prefix) {
302
+ configObject.prefix = this._prefix;
303
+ }
272
304
  return configObject;
273
305
  }
274
306
 
@@ -346,3 +378,5 @@ export const wgs84Projection = new Projection({ epsg: 4326 });
346
378
  * @export
347
379
  */
348
380
  export const mercatorProjection = new Projection({ epsg: 3857 });
381
+
382
+ VcsClassRegistry.registerClass(Projection.className, Projection);
@@ -14,6 +14,7 @@ import {
14
14
  whiteColor,
15
15
  } from './styleHelpers.js';
16
16
  import { originalFeatureSymbol } from '../../layer/vectorSymbols.js';
17
+ import { VcsClassRegistry } from '../../classRegistry.js';
17
18
 
18
19
  /**
19
20
  * @typedef {Object} DeclarativeStyleItemConditions
@@ -558,6 +559,7 @@ class DeclarativeStyleItem extends StyleItem {
558
559
  }
559
560
 
560
561
  export default DeclarativeStyleItem;
562
+ VcsClassRegistry.registerClass(DeclarativeStyleItem.className, DeclarativeStyleItem);
561
563
 
562
564
  /**
563
565
  * @type {DeclarativeStyleItem}
@@ -13,7 +13,7 @@ function getLogger() {
13
13
 
14
14
  /**
15
15
  * @param {(Reference|DeclarativeStyleItemOptions|VectorStyleItemOptions|StyleItem|string)=} styleOptions
16
- * @param {(VectorStyleItem|DeclarativeStyleItem)=} defaultStyle
16
+ * @param {StyleItem=} defaultStyle
17
17
  * @returns {StyleItem}
18
18
  */
19
19
  // eslint-disable-next-line import/prefer-default-export
@@ -4,6 +4,7 @@ import deepEqual from 'fast-deep-equal';
4
4
  import { parseEnumValue } from '@vcsuite/parsers';
5
5
  import VcsObject from '../../object.js';
6
6
  import VcsEvent from '../../event/vcsEvent.js';
7
+ import { VcsClassRegistry } from '../../classRegistry.js';
7
8
 
8
9
  /**
9
10
  * @namespace style
@@ -241,3 +242,4 @@ class StyleItem extends VcsObject {
241
242
  }
242
243
 
243
244
  export default StyleItem;
245
+ VcsClassRegistry.registerClass(StyleItem.className, StyleItem);
@@ -24,6 +24,7 @@ import {
24
24
  getDefaultVectorStyleItemOptions,
25
25
  } from './styleHelpers.js';
26
26
  import { getShapeFromOptions } from './shapesCategory.js';
27
+ import { VcsClassRegistry } from '../../classRegistry.js';
27
28
 
28
29
  /**
29
30
  * @typedef {Object} VectorStyleItemPattern
@@ -907,6 +908,7 @@ export default VectorStyleItem;
907
908
  * @export
908
909
  */
909
910
  export const defaultVectorStyle = new VectorStyleItem(getDefaultVectorStyleItemOptions());
911
+ VcsClassRegistry.registerClass(VectorStyleItem.className, VectorStyleItem);
910
912
 
911
913
  /**
912
914
  * @param {import("@vcmap/cesium").Color} cesiumColor
@@ -3,6 +3,7 @@ import { parseBoolean, parseNumber } from '@vcsuite/parsers';
3
3
  import Projection, { wgs84Projection } from './projection.js';
4
4
  import VcsObject from '../object.js';
5
5
  import Extent from './extent.js';
6
+ import { VcsClassRegistry } from '../classRegistry.js';
6
7
 
7
8
  /**
8
9
  * compares two numeric properties
@@ -331,3 +332,5 @@ class ViewPoint extends VcsObject {
331
332
  }
332
333
 
333
334
  export default ViewPoint;
335
+
336
+ VcsClassRegistry.registerClass(ViewPoint.className, ViewPoint);
@@ -0,0 +1,360 @@
1
+ import { getLogger as getLoggerByName } from '@vcsuite/logger';
2
+ import { v4 as uuidv4 } from 'uuid';
3
+ import { check } from '@vcsuite/check';
4
+ import Context from './context.js';
5
+ import {
6
+ contextIdSymbol,
7
+ destroyCollection,
8
+ getObjectFromOptions,
9
+ deserializeViewPoint,
10
+ deserializeMap,
11
+ getLayerIndex,
12
+ serializeLayer,
13
+ } from './vcsAppContextHelpers.js';
14
+ import makeOverrideCollection from './util/overrideCollection.js';
15
+ import CategoryCollection from './category/categoryCollection.js';
16
+ import MapCollection from './util/mapCollection.js';
17
+ import VcsMap from './maps/map.js';
18
+ import Layer from './layer/layer.js';
19
+ import Collection from './util/collection.js';
20
+ import ObliqueCollection from './oblique/ObliqueCollection.js';
21
+ import ViewPoint from './util/viewpoint.js';
22
+ import StyleItem from './util/style/styleItem.js';
23
+ import IndexedCollection from './util/indexedCollection.js';
24
+ import VcsEvent from './event/vcsEvent.js';
25
+ import { setDefaultProjectionOptions } from './util/projection.js';
26
+
27
+ /**
28
+ * @returns {import("@vcsuite/logger").Logger}
29
+ */
30
+ function getLogger() {
31
+ return getLoggerByName('init');
32
+ }
33
+
34
+ /**
35
+ * @type {Map<string, VcsApp>}
36
+ */
37
+ const vcsApps = new Map();
38
+
39
+ /**
40
+ * @class
41
+ */
42
+ class VcsApp {
43
+ constructor() {
44
+ /**
45
+ * @type {string}
46
+ * @private
47
+ */
48
+ this._id = uuidv4();
49
+ /**
50
+ * @type {Context}
51
+ * @private
52
+ */
53
+ this._defaultDynamicContext = new Context({ id: '_defaultDynamicContext' });
54
+ /**
55
+ * @type {Context}
56
+ * @private
57
+ */
58
+ this._dynamicContext = this._defaultDynamicContext;
59
+
60
+ const getDynamicContextId = () => this._dynamicContext.id;
61
+ /**
62
+ * @type {OverrideMapCollection}
63
+ * @private
64
+ */
65
+ // @ts-ignore
66
+ this._maps = makeOverrideCollection(
67
+ new MapCollection(),
68
+ getDynamicContextId,
69
+ null,
70
+ deserializeMap.bind(null, this),
71
+ VcsMap,
72
+ );
73
+ /**
74
+ * @type {OverrideLayerCollection}
75
+ * @private
76
+ */
77
+ // @ts-ignore
78
+ this._layers = makeOverrideCollection(
79
+ this._maps.layerCollection,
80
+ getDynamicContextId,
81
+ serializeLayer.bind(null, this),
82
+ getObjectFromOptions,
83
+ Layer,
84
+ getLayerIndex,
85
+ );
86
+ /**
87
+ * @type {OverrideCollection<import("@vcmap/core").ObliqueCollection>}
88
+ * @private
89
+ */
90
+ this._obliqueCollections = makeOverrideCollection(
91
+ new Collection(),
92
+ getDynamicContextId,
93
+ null,
94
+ getObjectFromOptions,
95
+ ObliqueCollection,
96
+ ); // XXX there is a global for this collection in core.
97
+ /**
98
+ * @type {OverrideCollection<import("@vcmap/core").ViewPoint>}
99
+ * @private
100
+ */
101
+ this._viewPoints = makeOverrideCollection(
102
+ new Collection(),
103
+ getDynamicContextId,
104
+ null,
105
+ deserializeViewPoint,
106
+ ViewPoint,
107
+ );
108
+ /**
109
+ * @type {OverrideCollection<import("@vcmap/core").StyleItem>}
110
+ * @private
111
+ */
112
+ this._styles = makeOverrideCollection(
113
+ new Collection(),
114
+ getDynamicContextId,
115
+ null,
116
+ getObjectFromOptions,
117
+ StyleItem,
118
+ ); // XXX there is a global for this collection in core.
119
+
120
+ /**
121
+ * @type {IndexedCollection<Context>}
122
+ * @private
123
+ */
124
+ this._contexts = new IndexedCollection('id');
125
+ this._contexts.add(this._dynamicContext);
126
+ /**
127
+ * @type {CategoryCollection}
128
+ * @private
129
+ */
130
+ this._categories = new CategoryCollection(this);
131
+ /**
132
+ * @type {import("@vcmap/core").VcsEvent<void>}
133
+ * @private
134
+ */
135
+ this._destroyed = new VcsEvent();
136
+ /**
137
+ * @type {Promise<void>}
138
+ * @private
139
+ */
140
+ this._contextMutationPromise = Promise.resolve();
141
+ vcsApps.set(this._id, this);
142
+ }
143
+
144
+ /**
145
+ * @type {string}
146
+ * @readonly
147
+ */
148
+ get id() { return this._id; }
149
+
150
+ /**
151
+ * @type {OverrideMapCollection}
152
+ * @readonly
153
+ */
154
+ get maps() { return this._maps; }
155
+
156
+ /**
157
+ * @type {OverrideLayerCollection}
158
+ * @readonly
159
+ */
160
+ get layers() { return this._layers; }
161
+
162
+ /**
163
+ * @type {OverrideCollection<import("@vcmap/core").ObliqueCollection>}
164
+ * @readonly
165
+ */
166
+ get obliqueCollections() { return this._obliqueCollections; }
167
+
168
+ /**
169
+ * @type {OverrideCollection<import("@vcmap/core").ViewPoint>}
170
+ * @readonly
171
+ */
172
+ get viewPoints() { return this._viewPoints; }
173
+
174
+ /**
175
+ * @type {OverrideCollection<import("@vcmap/core").StyleItem>}
176
+ * @readonly
177
+ */
178
+ get styles() { return this._styles; }
179
+
180
+ /**
181
+ * @type {CategoryCollection}
182
+ * @readonly
183
+ */
184
+ get categories() { return this._categories; }
185
+
186
+ /**
187
+ * @type {VcsEvent<void>}
188
+ * @readonly
189
+ */
190
+ get destroyed() { return this._destroyed; }
191
+
192
+ /**
193
+ * @returns {VcsEvent<Context>}
194
+ * @readonly
195
+ */
196
+ get contextAdded() { return this._contexts.added; }
197
+
198
+ /**
199
+ * @returns {VcsEvent<Context>}
200
+ * @readonly
201
+ */
202
+ get contextRemoved() { return this._contexts.removed; }
203
+
204
+ get dynamicContextId() { return this._dynamicContext.id; }
205
+
206
+ /**
207
+ * @param {string} id
208
+ * @returns {Context}
209
+ */
210
+ getContextById(id) {
211
+ return this._contexts.getByKey(id);
212
+ }
213
+
214
+ /**
215
+ * @param {Context} context
216
+ * @returns {Promise<void>}
217
+ * @protected
218
+ */
219
+ async _parseContext(context) {
220
+ const { config } = context;
221
+ if (config.projection) { // XXX this needs fixing. this should be _projections_ and there should be a `defaultProjection`
222
+ setDefaultProjectionOptions(config.projection);
223
+ }
224
+
225
+ await this._styles.parseItems(config.styles, context.id);
226
+ await this._layers.parseItems(config.layers, context.id);
227
+ // TODO add flights & ade here
228
+
229
+ await this._obliqueCollections.parseItems(config.obliqueCollections, context.id);
230
+ await this._viewPoints.parseItems(config.viewpoints, context.id);
231
+ await this._maps.parseItems(config.maps, context.id);
232
+
233
+ if (Array.isArray(config.categories)) {
234
+ await Promise.all((config.categories).map(async ({ name, items }) => {
235
+ await this._categories.parseCategoryItems(name, items, context.id);
236
+ }));
237
+ }
238
+ }
239
+
240
+ /**
241
+ * @param {Context} context
242
+ * @returns {Promise<void>}
243
+ * @protected
244
+ */
245
+ async _setContextState(context) {
246
+ const { config } = context;
247
+ [...this._layers]
248
+ .filter(l => l[contextIdSymbol] === context.id)
249
+ .forEach((l) => {
250
+ if (l.activeOnStartup) {
251
+ l.activate()
252
+ .catch((err) => {
253
+ getLogger().error(`Failed to activate active on startup layer ${l.name}`);
254
+ getLogger().error(err);
255
+ this._layers.remove(l);
256
+ l.destroy();
257
+ });
258
+ }
259
+ });
260
+
261
+ if (config.startingMapName) {
262
+ await this._maps.setActiveMap(config.startingMapName);
263
+ } else if (!this._maps.activeMap && this._maps.size > 0) {
264
+ await this._maps.setActiveMap([...this._maps][0].name);
265
+ }
266
+
267
+ if (config.startingViewPointName && this._maps.activeMap) {
268
+ const startViewPoint = this._viewPoints.getByKey(config.startingViewPointName);
269
+ if (startViewPoint) {
270
+ await this._maps.activeMap.gotoViewPoint(startViewPoint);
271
+ }
272
+ }
273
+ }
274
+
275
+ /**
276
+ * @param {Context} context
277
+ * @returns {Promise<void>}
278
+ */
279
+ addContext(context) {
280
+ check(context, Context);
281
+
282
+ this._contextMutationPromise = this._contextMutationPromise
283
+ .then(async () => {
284
+ if (this._contexts.has(context)) {
285
+ getLogger().info(`context with id ${context.id} already loaded`);
286
+ return;
287
+ }
288
+
289
+ await this._parseContext(context);
290
+ await this._setContextState(context);
291
+ this._contexts.add(context);
292
+ });
293
+ return this._contextMutationPromise;
294
+ }
295
+
296
+ /**
297
+ * @param {string} contextId
298
+ * @returns {Promise<void>}
299
+ * @protected
300
+ */
301
+ async _removeContext(contextId) {
302
+ await Promise.all([
303
+ this._maps.removeContext(contextId),
304
+ this._layers.removeContext(contextId),
305
+ this._viewPoints.removeContext(contextId),
306
+ this._styles.removeContext(contextId),
307
+ this._obliqueCollections.removeContext(contextId),
308
+ ]);
309
+ }
310
+
311
+ /**
312
+ * @param {string} contextId
313
+ * @returns {Promise<void>}
314
+ */
315
+ removeContext(contextId) {
316
+ this._contextMutationPromise = this._contextMutationPromise
317
+ .then(async () => {
318
+ const context = this._contexts.getByKey(contextId);
319
+ if (!context) {
320
+ getLogger().info(`context with id ${contextId} has alread been removed`);
321
+ return;
322
+ }
323
+ await this._removeContext(contextId);
324
+ this._contexts.remove(context);
325
+ });
326
+
327
+ return this._contextMutationPromise;
328
+ }
329
+
330
+ destroy() {
331
+ Object.defineProperty(this, '_contextMutationPromise', {
332
+ get() {
333
+ throw new Error('VcsApp was destroyed');
334
+ },
335
+ });
336
+ vcsApps.delete(this._id);
337
+ destroyCollection(this._maps);
338
+ destroyCollection(this._layers);
339
+ destroyCollection(this._obliqueCollections);
340
+ destroyCollection(this._viewPoints);
341
+ destroyCollection(this._styles);
342
+ destroyCollection(this._contexts);
343
+ destroyCollection(this._categories);
344
+ this.destroyed.raiseEvent();
345
+ this.destroyed.destroy();
346
+ }
347
+ }
348
+
349
+ /**
350
+ * @param {string} id
351
+ * @returns {VcsApp}
352
+ */
353
+ export function getVcsAppById(id) {
354
+ return vcsApps.get(id);
355
+ }
356
+
357
+ window.vcs = window.vcs || {};
358
+ window.vcs.apps = vcsApps;
359
+
360
+ export default VcsApp;
@@ -0,0 +1,108 @@
1
+ import { getLogger as getLoggerByName } from '@vcsuite/logger';
2
+ import { VcsClassRegistry } from './classRegistry.js';
3
+
4
+ /**
5
+ * @returns {import("@vcsuite/logger").Logger}
6
+ */
7
+ function getLogger() {
8
+ return getLoggerByName('init');
9
+ }
10
+
11
+ /**
12
+ * @type {symbol}
13
+ */
14
+ export const contextIdSymbol = Symbol('contextId');
15
+
16
+ /**
17
+ * returns a constructor of a type.
18
+ * @api stable
19
+ * @export
20
+ * @param {Object} options
21
+ * @param {...*} args
22
+ * @returns {Promise<Object|null>}
23
+ */
24
+ export async function getObjectFromOptions(options, ...args) {
25
+ if (!options.type) {
26
+ getLogger().warning(`ObjectCreation failed: could not find type in options ${options}`);
27
+ return null;
28
+ }
29
+ const ObjectConstructor = await VcsClassRegistry.getClass(options.type);
30
+ if (!ObjectConstructor) {
31
+ getLogger().warning(`ObjectCreation failed: could not find javascript class of type ${options.type}`);
32
+ return null;
33
+ }
34
+ let object;
35
+ try {
36
+ object = new ObjectConstructor(options, ...args);
37
+ } catch (ex) {
38
+ getLogger().warning(`Error: ${ex}`);
39
+ }
40
+
41
+ if (!object) {
42
+ getLogger().warning('ObjectCreation failed: could not create new Object');
43
+ return null;
44
+ }
45
+ return object;
46
+ }
47
+
48
+ /**
49
+ * @param {import("@vcmap/core").VcsApp} vcsApp
50
+ * @param {VcsMapOptions} mapConfig
51
+ * @returns {Promise<import("@vcmap/core").VcsMap|null>}
52
+ */
53
+ export async function deserializeMap(vcsApp, mapConfig) {
54
+ const map = await getObjectFromOptions(mapConfig);
55
+ if (map) {
56
+ map.layerCollection = vcsApp.layers;
57
+ }
58
+ return map;
59
+ }
60
+
61
+ /**
62
+ * @param {ViewPointOptions} viewPointObject
63
+ * @returns {Promise<null|import("@vcmap/core").ViewPoint>}
64
+ */
65
+ export async function deserializeViewPoint(viewPointObject) {
66
+ const viewpoint = /** @type {import("@vcmap/core").ViewPoint} */ (await getObjectFromOptions(viewPointObject));
67
+ if (viewpoint && viewpoint.isValid()) {
68
+ return viewpoint;
69
+ }
70
+ getLogger().warning(`Viewpoint ${viewPointObject.name} is not valid`);
71
+ return null;
72
+ }
73
+
74
+ /**
75
+ * @param {import("@vcmap/core").VcsApp} vcsApp
76
+ * @param {import("@vcmap/core").Layer} layer
77
+ * @returns {Promise<LayerOptions|null>}
78
+ */
79
+ export async function serializeLayer(vcsApp, layer) {
80
+ const serializedLayer = layer.toJSON();
81
+ serializedLayer.zIndex = layer[vcsApp.layers.zIndexSymbol];
82
+ return serializedLayer;
83
+ }
84
+
85
+ /**
86
+ * @param {import("@vcmap/core").Layer} current
87
+ * @param {import("@vcmap/core").Layer} previous
88
+ * @param {number} currentIndex
89
+ * @returns {number|null}
90
+ */
91
+ export function getLayerIndex(current, previous, currentIndex) {
92
+ if (current.zIndex !== previous.zIndex) {
93
+ return null;
94
+ }
95
+ return currentIndex;
96
+ }
97
+
98
+ /**
99
+ * @param {import("@vcmap/core").Collection<*>} collection
100
+ */
101
+ export function destroyCollection(collection) {
102
+ [...collection].forEach((i) => {
103
+ if (i.destroy && !i.isDestroyed) {
104
+ i.destroy();
105
+ }
106
+ });
107
+ collection.destroy();
108
+ }