@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
@@ -1,15 +1,17 @@
1
+ import { parseInteger, parseNumber } from '@vcsuite/parsers';
1
2
  import RBush from 'rbush';
2
3
  import knn from 'rbush-knn';
3
- import { v4 as uuidv4 } from 'uuid';
4
4
  import { getTransform } from 'ol/proj.js';
5
5
  import { createXYZ } from 'ol/tilegrid.js';
6
6
  import Feature from 'ol/Feature.js';
7
7
  import Polygon, { fromExtent } from 'ol/geom/Polygon.js';
8
8
  import Vector from 'ol/source/Vector.js';
9
9
  import { boundingExtent, buffer, containsCoordinate, getCenter } from 'ol/extent.js';
10
- import { Event as CesiumEvent } from '@vcmap/cesium';
11
- import { DataState, getStateFromStatesArray } from './ObliqueDataSet.js';
10
+ import VcsEvent from '../event/vcsEvent.js';
11
+ import ObliqueDataSet, { DataState, getStateFromStatesArray } from './ObliqueDataSet.js';
12
12
  import { ObliqueViewDirection } from './ObliqueViewDirection.js';
13
+ import { mercatorProjection } from '../util/projection.js';
14
+ import VcsObject from '../object.js';
13
15
 
14
16
  /**
15
17
  * @typedef {Object} ObliqueCameraOptions
@@ -52,13 +54,19 @@ import { ObliqueViewDirection } from './ObliqueViewDirection.js';
52
54
  */
53
55
 
54
56
  /**
55
- * @typedef {Object} ObliqueCollectionOptions
56
- * @property {string|undefined} name
57
- * @property {Array<import("@vcmap/core").ObliqueDataSet>} dataSets
58
- * @property {number|undefined} maxZoom
59
- * @property {number|undefined} minZoom
57
+ * @typedef {Object} ObliqueDataSetOptions
58
+ * @property {string} url
59
+ * @property {ProjectionOptions} [projection]
60
+ * @property {TerrainProviderOptions} [terrainProvider]
61
+ */
62
+
63
+ /**
64
+ * @typedef {VcsObjectOptions} ObliqueCollectionOptions
65
+ * @property {Array<import("@vcmap/core").ObliqueDataSet|ObliqueDataSetOptions>} [dataSets]
66
+ * @property {number|undefined} [maxZoom]
67
+ * @property {number|undefined} [minZoom]
60
68
  * @property {number|undefined} [scaleFactor=4]
61
- * @property {number|undefined} hideLevels
69
+ * @property {number|undefined} [hideLevels]
62
70
  * @api
63
71
  */
64
72
 
@@ -68,7 +76,7 @@ import { ObliqueViewDirection } from './ObliqueViewDirection.js';
68
76
  */
69
77
  function getImageFeatures(images) {
70
78
  return images.map((image) => {
71
- const transform = getTransform(image.meta.projection, 'EPSG:3857');
79
+ const transform = getTransform(image.meta.projection.proj, mercatorProjection.proj);
72
80
  const feature = new Feature({
73
81
  geometry: new Polygon([image.groundCoordinates.map(c => transform(c.slice(0, 2)))]),
74
82
  viewDirection: image.viewDirection,
@@ -103,18 +111,28 @@ function getTileFeatures(tiles) {
103
111
  * @class
104
112
  * @export
105
113
  */
106
- class ObliqueCollection {
114
+ class ObliqueCollection extends VcsObject {
115
+ static get className() { return 'oblique.ObliqueCollection'; }
116
+
117
+ /**
118
+ * @returns {ObliqueCollectionOptions}
119
+ */
120
+ static getDefaultOptions() {
121
+ return {
122
+ maxZoom: 0,
123
+ minZoom: 0,
124
+ scaleFactor: 4,
125
+ dataSets: undefined,
126
+ hideLevels: 0,
127
+ };
128
+ }
129
+
107
130
  /**
108
131
  * @param {ObliqueCollectionOptions} options
109
132
  */
110
133
  constructor(options) {
111
- /**
112
- * The unique name of the collection
113
- * @type {string}
114
- * @api
115
- */
116
- this.name = options.name || uuidv4();
117
-
134
+ super(options);
135
+ const defaultOptions = ObliqueCollection.getDefaultOptions();
118
136
  /**
119
137
  * Maps each direction to an RTree
120
138
  * @type {Map<import("@vcmap/core").ObliqueViewDirection, RBush>}
@@ -136,10 +154,10 @@ class ObliqueCollection {
136
154
 
137
155
  /** @type {ObliqueViewOptions} */
138
156
  this.viewOptions = {
139
- maxZoom: options.maxZoom || 0,
140
- minZoom: options.minZoom || 0,
141
- scaleFactor: options.scaleFactor || 4,
142
- hideLevels: options.hideLevels || 0,
157
+ maxZoom: parseInteger(options.maxZoom, defaultOptions.maxZoom),
158
+ minZoom: parseInteger(options.minZoom, defaultOptions.minZoom),
159
+ scaleFactor: parseNumber(options.scaleFactor, defaultOptions.scaleFactor),
160
+ hideLevels: parseInteger(options.hideLevels, defaultOptions.hideLevels),
143
161
  };
144
162
 
145
163
  /** @type {boolean} */
@@ -147,10 +165,10 @@ class ObliqueCollection {
147
165
 
148
166
  /**
149
167
  * Event raised when images are loaded. Is passed an Array of ObliqueImages as its only argument.
150
- * @type {import("@vcmap/cesium").Event}
168
+ * @type {import("@vcmap/core").VcsEvent<Array<import("@vcmap/core").ObliqueImage>>}
151
169
  * @api
152
170
  */
153
- this.imagesLoaded = new CesiumEvent();
171
+ this.imagesLoaded = new VcsEvent();
154
172
 
155
173
  /**
156
174
  * @type {import("ol/source").Vector<import("ol/geom/Geometry").default>|null}
@@ -262,11 +280,18 @@ class ObliqueCollection {
262
280
 
263
281
  /**
264
282
  * Adds an oblique data set to this collection.
265
- * @param {import("@vcmap/core").ObliqueDataSet} dataSet
283
+ * @param {import("@vcmap/core").ObliqueDataSet|ObliqueDataSetOptions} dataSetOptions
266
284
  * @private
267
285
  */
268
- _addDataSet(dataSet) {
269
- dataSet.imagesLoaded.addEventListener((images, tileCoordinate) => {
286
+ _addDataSet(dataSetOptions) {
287
+ /** @type {import("@vcmap/core").ObliqueDataSet} */
288
+ let dataSet;
289
+ if (dataSetOptions instanceof ObliqueDataSet) {
290
+ dataSet = dataSetOptions;
291
+ } else {
292
+ dataSet = new ObliqueDataSet(dataSetOptions.url, dataSetOptions.projection, dataSetOptions.terrainProvider);
293
+ }
294
+ dataSet.imagesLoaded.addEventListener(({ images, tileCoordinate }) => {
270
295
  this._loadImages(images, tileCoordinate);
271
296
  });
272
297
  this._loadImages(dataSet.images);
@@ -279,7 +304,7 @@ class ObliqueCollection {
279
304
  * @returns {Promise<void>}
280
305
  * @api
281
306
  */
282
- async addDataSet(dataSet) {
307
+ async addDataSet(dataSet) { // XXX check for dataset here?
283
308
  if (this._loadingPromise) {
284
309
  await this._loadingPromise;
285
310
  await this._loadDataSet(dataSet);
@@ -322,7 +347,7 @@ class ObliqueCollection {
322
347
  directions.set(image.viewDirection, []);
323
348
  }
324
349
 
325
- const transform = getTransform(image.meta.projection, 'EPSG:3857');
350
+ const transform = getTransform(image.meta.projection.proj, mercatorProjection.proj);
326
351
  const coord = image.centerPointOnGround.slice(0, 2);
327
352
  transform(coord, coord);
328
353
  directions.get(image.viewDirection).push({
@@ -491,7 +516,7 @@ class ObliqueCollection {
491
516
  async hasImageAtCoordinate(mercatorCoordinate, direction) {
492
517
  const image = await this.loadImageForCoordinate(mercatorCoordinate, direction);
493
518
  if (image) {
494
- const transform = getTransform('EPSG:3857', image.meta.projection);
519
+ const transform = getTransform(mercatorProjection.proj, image.meta.projection.proj);
495
520
  const internalCoordinates = mercatorCoordinate.slice(0, 2);
496
521
  transform(internalCoordinates, internalCoordinates);
497
522
  const extent = boundingExtent(image.groundCoordinates);
@@ -513,7 +538,7 @@ class ObliqueCollection {
513
538
  async loadAdjacentImage(image, heading, deviation = Math.PI / 4) {
514
539
  const tree = this._directionTrees.get(image.viewDirection);
515
540
  if (tree) {
516
- const transform = getTransform(image.meta.projection, 'EPSG:3857');
541
+ const transform = getTransform(image.meta.projection.proj, mercatorProjection.proj);
517
542
  const coords = image.groundCoordinates.map(c => transform(c.slice(0, 2)));
518
543
  const extent = boundingExtent(coords);
519
544
  await this.loadDataForExtent(buffer(extent, 200));
@@ -566,6 +591,33 @@ class ObliqueCollection {
566
591
  this._imageFeatureSource.clear(true);
567
592
  this._imageFeatureSource = null;
568
593
  }
594
+ this.imagesLoaded.destroy();
595
+ }
596
+
597
+ /**
598
+ * @returns {ObliqueCollectionOptions}
599
+ */
600
+ toJSON() {
601
+ /** @type {ObliqueCollectionOptions} */
602
+ const config = super.toJSON();
603
+ const defaultOptions = ObliqueCollection.getDefaultOptions();
604
+ if (this.viewOptions.maxZoom !== defaultOptions.maxZoom) {
605
+ config.maxZoom = this.viewOptions.maxZoom;
606
+ }
607
+ if (this.viewOptions.minZoom !== defaultOptions.minZoom) {
608
+ config.minZoom = this.viewOptions.minZoom;
609
+ }
610
+ if (this.viewOptions.scaleFactor !== defaultOptions.scaleFactor) {
611
+ config.scaleFactor = this.viewOptions.scaleFactor;
612
+ }
613
+ if (this.viewOptions.hideLevels !== defaultOptions.hideLevels) {
614
+ config.hideLevels = this.viewOptions.hideLevels;
615
+ }
616
+
617
+ if (this.dataSets.length > 0) {
618
+ config.dataSets = this.dataSets.map(d => d.toJSON());
619
+ }
620
+ return config;
569
621
  }
570
622
  }
571
623
 
@@ -1,9 +1,16 @@
1
- import { Event as CesiumEvent } from '@vcmap/cesium';
2
- import axios from 'axios';
3
1
  import { createXYZ } from 'ol/tilegrid.js';
4
- import { destroyCesiumEvent } from './helpers.js';
5
2
  import { cartesian2DDistance } from '../util/math.js';
6
3
  import { parseImageData, parseImageMeta, parseLegacyImageData, getVersionFromImageJson } from './parseImageJson.js';
4
+ import VcsEvent from '../event/vcsEvent.js';
5
+ import { getTerrainProviderForUrl } from '../layer/terrainHelpers.js';
6
+ import Projection from '../util/projection.js';
7
+ import { requestJson } from '../util/fetch.js';
8
+
9
+ /**
10
+ * @typedef {Object} ObliqueDataSetImagesLoaded
11
+ * @property {Array<import("@vcmap/core").ObliqueImage>} images - the loaded images
12
+ * @property {string} [tileCoordinate] - an optional tile coordinate
13
+ */
7
14
 
8
15
  /**
9
16
  * Enumeration of data set states
@@ -43,10 +50,10 @@ export function getStateFromStatesArray(states) {
43
50
  class ObliqueDataSet {
44
51
  /**
45
52
  * @param {string} url
46
- * @param {import("ol/proj/Projection").default} projection
47
- * @param {import("@vcmap/cesium").CesiumTerrainProvider=} terrainProvider
53
+ * @param {import("@vcmap/core").Projection|ProjectionOptions=} projection
54
+ * @param {TerrainProviderOptions=} terrainProviderOptions
48
55
  */
49
- constructor(url, projection, terrainProvider) {
56
+ constructor(url, projection, terrainProviderOptions) {
50
57
  /** @type {string} */
51
58
  this.url = url;
52
59
  if (!/\.json$/.test(this.url)) {
@@ -55,22 +62,36 @@ class ObliqueDataSet {
55
62
 
56
63
  /** @type {string} */
57
64
  this.baseUrl = this.url.replace(/\/?([^/]+\.json)?$/, '');
58
- /** @type {import("ol/proj/Projection").default} */
59
- this.projection = projection;
60
- /** @type {import("@vcmap/cesium").CesiumTerrainProvider|undefined} */
61
- this.terrainProvider = terrainProvider;
65
+
66
+ let projectionObject = projection;
67
+ if (projectionObject && !(projectionObject instanceof Projection)) {
68
+ projectionObject = new Projection(projectionObject);
69
+ }
70
+ /** @type {import("@vcmap/core").Projection} */
71
+ this.projection = /** @type {import("@vcmap/core").Projection} */ (projectionObject);
72
+ /**
73
+ * @type {TerrainProviderOptions}
74
+ * @private
75
+ */
76
+ this._terrainProviderOptions = terrainProviderOptions ? { ...terrainProviderOptions } : undefined;
77
+ /**
78
+ * @type {import("@vcmap/cesium").CesiumTerrainProvider|undefined}
79
+ * @private
80
+ */
81
+ this._terrainProvider = this._terrainProviderOptions ?
82
+ getTerrainProviderForUrl(this._terrainProviderOptions) :
83
+ undefined;
62
84
  /**
63
85
  * @type {Array<import("@vcmap/core").ObliqueImageMeta>}
64
86
  * @private
65
87
  */
66
88
  this._imageMetas = [];
67
89
  /**
68
- * Event raised when images are loaded. Is passed an Array of ObliqueImages as the first argument and optionally
69
- * a string representing the tile coordinate ("z/x/y"), if the images where loaded for a tile.
70
- * @type {import("@vcmap/cesium").Event}
90
+ * Event raised when images are loaded.
91
+ * @type {import("@vcmap/core").VcsEvent<ObliqueDataSetImagesLoaded>}
71
92
  * @api
72
93
  */
73
- this.imagesLoaded = new CesiumEvent();
94
+ this.imagesLoaded = new VcsEvent();
74
95
  /** @type {Map<string, DataState>} */
75
96
  this._tiles = new Map();
76
97
  /** @type {Map<string, Promise<void>>} */
@@ -118,6 +139,14 @@ class ObliqueDataSet {
118
139
  return this._state;
119
140
  }
120
141
 
142
+ /**
143
+ * @type {import("@vcmap/cesium").CesiumTerrainProvider|undefined}
144
+ * @readonly
145
+ */
146
+ get terrainProvider() {
147
+ return this._terrainProvider;
148
+ }
149
+
121
150
  /**
122
151
  * Loads the data set.
123
152
  * @returns {Promise<void>}
@@ -127,9 +156,10 @@ class ObliqueDataSet {
127
156
  if (!this._loadingPromise) {
128
157
  this._state = DataState.LOADING;
129
158
 
130
- this._loadingPromise = axios.get(this.url)
131
- .then(({ data }) => {
132
- this._initialize(data);
159
+ this._loadingPromise = requestJson(this.url)
160
+ .then(data => this._initialize(data))
161
+ .catch((err) => {
162
+ return Promise.reject(err);
133
163
  });
134
164
  }
135
165
  return this._loadingPromise;
@@ -194,7 +224,7 @@ class ObliqueDataSet {
194
224
  }
195
225
  if (images.length > 0) {
196
226
  this._images = images;
197
- this.imagesLoaded.raiseEvent(images);
227
+ this.imagesLoaded.raiseEvent({ images });
198
228
  }
199
229
  }
200
230
  }
@@ -297,13 +327,12 @@ class ObliqueDataSet {
297
327
  }
298
328
 
299
329
  this._tiles.set(stringTileCoordinates, DataState.LOADING);
300
- const promise = axios
301
- .get(`${this.baseUrl}/${stringTileCoordinates}.json`)
302
- .then(({ data }) => {
330
+ const promise = requestJson(`${this.baseUrl}/${stringTileCoordinates}.json`)
331
+ .then((data) => {
303
332
  const images = parseImageData(data, this._imageMetas);
304
333
  if (images.length > 0) {
305
334
  this._images = this._images.concat(images);
306
- this.imagesLoaded.raiseEvent(images, stringTileCoordinates);
335
+ this.imagesLoaded.raiseEvent({ images, tileCoordinate: stringTileCoordinates });
307
336
  }
308
337
  })
309
338
  .catch((err) => {
@@ -344,13 +373,27 @@ class ObliqueDataSet {
344
373
  }
345
374
 
346
375
  destroy() {
347
- destroyCesiumEvent(this.imagesLoaded);
376
+ this.imagesLoaded.destroy();
348
377
  this._images = [];
349
378
  this._imageMetas = [];
350
379
  this._tiles.clear();
351
380
  this._loadingPromises.clear();
352
381
  this._tileGrid = null;
353
- this.terrainProvider = null;
382
+ this._terrainProvider = null;
383
+ }
384
+
385
+ /**
386
+ * @returns {ObliqueDataSetOptions}
387
+ */
388
+ toJSON() {
389
+ const config = { url: this.url };
390
+ if (this.projection) {
391
+ config.projection = this.projection.toJSON();
392
+ }
393
+ if (this._terrainProviderOptions) {
394
+ config.terrainProvider = { ...this._terrainProviderOptions };
395
+ }
396
+ return config;
354
397
  }
355
398
  }
356
399
 
@@ -13,7 +13,7 @@ import { getHeightFromTerrainProvider } from '../layer/terrainHelpers.js';
13
13
  * @property {import("@vcmap/cesium").Cartesian3|undefined} projectionCenter
14
14
  * @property {import("@vcmap/cesium").Matrix3|undefined} pToRealworld
15
15
  * @property {import("@vcmap/cesium").Matrix4|undefined} pToImage
16
- * @property {import("ol/proj/Projection").default|undefined} [projection]
16
+ * @property {import("@vcmap/core").Projection|undefined} [projection]
17
17
  * @property {import("@vcmap/cesium").CesiumTerrainProvider|undefined} terrainProvider
18
18
  * @api
19
19
  */
@@ -9,7 +9,7 @@ import { cartesian2DDistance } from '../util/math.js';
9
9
  * @property {import("ol/size").Size} size
10
10
  * @property {import("ol/size").Size} tileSize
11
11
  * @property {Array<number>} tileResolution
12
- * @property {import("ol/proj/Projection").default} projection
12
+ * @property {import("@vcmap/core").Projection} projection
13
13
  * @property {string} url
14
14
  * @property {import("@vcmap/cesium").CesiumTerrainProvider} terrainProvider
15
15
  * @property {string} name
@@ -64,7 +64,7 @@ class ObliqueImageMeta {
64
64
  this.tileResolution = options.tileResolution;
65
65
  /**
66
66
  * The world projection of the images associated with this meta
67
- * @type {import("ol/proj/Projection").default}
67
+ * @type {import("@vcmap/core").Projection}
68
68
  * @api
69
69
  */
70
70
  this.projection = options.projection;
@@ -1,12 +1,12 @@
1
- import { Event as CesiumEvent } from '@vcmap/cesium';
2
1
  import { getTransform } from 'ol/proj.js';
3
2
  import View from 'ol/View.js';
4
3
  import { unByKey } from 'ol/Observable.js';
5
4
  import { DataState } from './ObliqueDataSet.js';
6
5
  import OLView from './ObliqueView.js';
7
- import { destroyCesiumEvent, transformFromImage } from './helpers.js';
6
+ import { transformFromImage } from './helpers.js';
8
7
  import { getHeightFromTerrainProvider } from '../layer/terrainHelpers.js';
9
8
  import { mercatorProjection } from '../util/projection.js';
9
+ import VcsEvent from '../event/vcsEvent.js';
10
10
 
11
11
  /**
12
12
  * @typedef {Object} ObliqueViewPoint
@@ -63,10 +63,10 @@ class ObliqueProvider {
63
63
 
64
64
  /**
65
65
  * Event raised once a new image is set on the provider. Will be passed the new image as the only argument.
66
- * @type {import("@vcmap/cesium").Event}
66
+ * @type {import("@vcmap/core").VcsEvent<import("@vcmap/core").ObliqueImage>}
67
67
  * @api
68
68
  */
69
- this.imageChanged = new CesiumEvent();
69
+ this.imageChanged = new VcsEvent();
70
70
  /**
71
71
  * Whether the post render handler should switch on image edge. Setting
72
72
  * this to false will suspend all post render handler switches.
@@ -232,7 +232,7 @@ class ObliqueProvider {
232
232
  }
233
233
  const pulledCenter = this._pullCoordinateToImageCenter(imageCoordinates.slice());
234
234
  const worldCoords = this._currentImage.transformImage2RealWorld(pulledCenter).slice(0, 2);
235
- const transform = getTransform(this._currentImage.meta.projection, 'EPSG:3857');
235
+ const transform = getTransform(this._currentImage.meta.projection.proj, mercatorProjection.proj);
236
236
  const mercatorCoords = transform(worldCoords);
237
237
  const buffer = 200; // XXX make configurable?
238
238
  const extent = [
@@ -299,7 +299,10 @@ class ObliqueProvider {
299
299
  const [width, height] = this._currentImage.meta.size;
300
300
  let center = [width / 2, height / 2];
301
301
  if (optCenter) {
302
- const worldCenter = getTransform('EPSG:3857', this._currentImage.meta.projection)(optCenter.slice(0, 2));
302
+ const worldCenter = getTransform(
303
+ mercatorProjection.proj,
304
+ this._currentImage.meta.projection.proj,
305
+ )(optCenter.slice(0, 2));
303
306
  const imageCenter = this._currentImage.transformRealWorld2Image(worldCenter, optCenter[2]);
304
307
  imageCenter[0] = withinBounds(imageCenter[0], width);
305
308
  imageCenter[1] = withinBounds(imageCenter[1], height);
@@ -424,7 +427,7 @@ class ObliqueProvider {
424
427
  this._postRenderListener = null;
425
428
  }
426
429
 
427
- destroyCesiumEvent(this.imageChanged);
430
+ this.imageChanged.destroy();
428
431
  this._collection = null;
429
432
  this._olMap = null;
430
433
  }
@@ -1,11 +1,12 @@
1
1
  /* eslint no-underscore-dangle: ["error", { "allow": ["_listeners", "_scopes", "_toRemove"] }] */
2
2
  /* eslint-disable no-continue */
3
3
  import { boundingExtent, getBottomLeft, getBottomRight, getTopLeft, getTopRight } from 'ol/extent.js';
4
- import { get as getProjection, transform } from 'ol/proj.js';
4
+ import { transform } from 'ol/proj.js';
5
5
  import { Cartesian2 } from '@vcmap/cesium';
6
6
  import { ObliqueViewDirection } from './ObliqueViewDirection.js';
7
7
  import { getHeightFromTerrainProvider } from '../layer/terrainHelpers.js';
8
8
  import { cartesian2DDistance } from '../util/math.js';
9
+ import { mercatorProjection, wgs84Projection } from '../util/projection.js';
9
10
 
10
11
  /**
11
12
  * @type {import("@vcmap/cesium").Cartesian2}
@@ -292,7 +293,7 @@ export function transformCWIFC(inputOrigin, inputTarget, originIsImage, coordina
292
293
  /**
293
294
  * @typedef {Object} ImageTransformationOptions
294
295
  * @property {boolean|undefined} [dontUseTerrain]
295
- * @property {import("ol/proj/Projection").default|undefined} [dataProjection] - the projection of the input/output coordinates, assumes image source projection
296
+ * @property {import("@vcmap/core").Projection|undefined} [dataProjection] - the projection of the input/output coordinates, assumes image source projection
296
297
  * @property {number|undefined} [terrainErrorThreshold=1] - the transformToWorld process iterativly calculates a new Height Value from the terrainProvider until the difference to the new height value is smaller
297
298
  * @property {number|undefined} [terrainErrorCountThreshold=3] - how often the transformToWorld process iterativly calculates a new Height Value from the terrainProvider
298
299
  * @api
@@ -313,8 +314,8 @@ export function transformToImage(image, worldCoordinate, options = {}) {
313
314
  gpInternalCoordinates = worldCoordinate;
314
315
  } else {
315
316
  gpInternalCoordinates = options.dataProjection ?
316
- transform(worldCoordinate, options.dataProjection, image.meta.projection) :
317
- transform(worldCoordinate, 'EPSG:3857', image.meta.projection);
317
+ transform(worldCoordinate, options.dataProjection.proj, image.meta.projection.proj) :
318
+ transform(worldCoordinate, mercatorProjection.proj, image.meta.projection.proj);
318
319
  }
319
320
 
320
321
  function useAverageHeight() {
@@ -369,14 +370,14 @@ function pickTerrain(pickTerrainOptions) {
369
370
  count,
370
371
  height,
371
372
  } = pickTerrainOptions;
372
- const wgs84Projection = getProjection('EPSG:4326');
373
+
373
374
  return getHeightFromTerrainProvider(image.meta.terrainProvider, [worldCoordinate])
374
375
  .then(([worldCoordinateWithHeights]) => {
375
376
  if (worldCoordinateWithHeights[2] != null) {
376
377
  const newWorldCoords = transform(
377
378
  image.transformImage2RealWorld(imageCoordinate, worldCoordinateWithHeights[2]),
378
- image.meta.projection,
379
- wgs84Projection,
379
+ image.meta.projection.proj,
380
+ wgs84Projection.proj,
380
381
  );
381
382
  newWorldCoords[2] = worldCoordinateWithHeights[2];
382
383
  if (
@@ -406,11 +407,10 @@ function pickTerrain(pickTerrainOptions) {
406
407
  * @export
407
408
  */
408
409
  export async function transformFromImage(image, imageCoordinate, options = {}) {
409
- const wgs84Projection = getProjection('EPSG:4326');
410
410
  const initialWorldCoords = transform(
411
411
  image.transformImage2RealWorld(imageCoordinate, image.averageHeight),
412
- image.meta.projection,
413
- wgs84Projection,
412
+ image.meta.projection.proj,
413
+ wgs84Projection.proj,
414
414
  );
415
415
 
416
416
  const terrainErrorThreshold = options.terrainErrorThreshold || 1;
@@ -430,8 +430,8 @@ export async function transformFromImage(image, imageCoordinate, options = {}) {
430
430
  }
431
431
 
432
432
  coordsObj.coords = options.dataProjection ?
433
- transform(coordsObj.coords, wgs84Projection, options.dataProjection) :
434
- transform(coordsObj.coords, wgs84Projection, getProjection('EPSG:3857'));
433
+ transform(coordsObj.coords, wgs84Projection.proj, options.dataProjection.proj) :
434
+ transform(coordsObj.coords, wgs84Projection.proj, mercatorProjection.proj);
435
435
  return coordsObj;
436
436
  }
437
437
 
@@ -453,31 +453,3 @@ export function hasSameOrigin(url) {
453
453
  const uri = new URL(url);
454
454
  return currentUri.host.toLowerCase() === uri.host.toLocaleLowerCase();
455
455
  }
456
-
457
- /**
458
- * destroys a cesium Event Emitter, (removes all listeners)
459
- * @param {import("@vcmap/cesium").Event} cesiumEvent
460
- */
461
- export function destroyCesiumEvent(cesiumEvent) {
462
- // @ts-ignore
463
- for (let i = 0; i < cesiumEvent._listeners.length; i++) {
464
- // @ts-ignore
465
- cesiumEvent._listeners[i] = undefined;
466
- }
467
- // @ts-ignore
468
- for (let i = 0; i < cesiumEvent._scopes.length; i++) {
469
- // @ts-ignore
470
- cesiumEvent._scopes[i] = undefined;
471
- }
472
- // @ts-ignore
473
- for (let i = 0; i < cesiumEvent._toRemove.length; i++) {
474
- // @ts-ignore
475
- cesiumEvent._toRemove[i] = undefined;
476
- }
477
- // @ts-ignore
478
- cesiumEvent._listeners.length = 0;
479
- // @ts-ignore
480
- cesiumEvent._scopes.length = 0;
481
- // @ts-ignore
482
- cesiumEvent._toRemove.length = 0;
483
- }
@@ -1,11 +1,18 @@
1
- import { v4 as uuidv4 } from 'uuid';
2
- import proj4 from 'proj4';
3
- import { register } from 'ol/proj/proj4.js';
4
- import { get as getProjection } from 'ol/proj.js';
5
1
  import { Matrix3, Cartesian3, Matrix4 } from '@vcmap/cesium';
6
2
  import ObliqueImage from './ObliqueImage.js';
7
3
  import { obliqueViewDirectionNames } from './ObliqueViewDirection.js';
8
4
  import ImageMeta from './ObliqueImageMeta.js';
5
+ import Projection from '../util/projection.js';
6
+
7
+ let customObliqueProjectionId = 0;
8
+
9
+ /**
10
+ * @returns {number}
11
+ */
12
+ function getNextObliqueProjectionId() {
13
+ customObliqueProjectionId += 1;
14
+ return customObliqueProjectionId;
15
+ }
9
16
 
10
17
  /**
11
18
  * @param {Object} json
@@ -33,7 +40,7 @@ export function getVersionFromImageJson(json) {
33
40
  /**
34
41
  * @param {ObliqueImageJson} json
35
42
  * @param {string} url
36
- * @param {(import("ol/proj/Projection").default|null)=} projection
43
+ * @param {import("@vcmap/core").Projection=} projection
37
44
  * @param {import("@vcmap/cesium").CesiumTerrainProvider=} terrainProvider
38
45
  * @returns {Array<import("@vcmap/core").ObliqueImageMeta>}
39
46
  */
@@ -47,10 +54,11 @@ export function parseImageMeta(json, url, projection, terrainProvider) {
47
54
  let imageProjection = projection;
48
55
  const imageMetas = [];
49
56
  if (!imageProjection && json.generalImageInfo.crs) {
50
- const crsUuid = uuidv4();
51
- proj4.defs(crsUuid, json.generalImageInfo.crs);
52
- register(proj4);
53
- imageProjection = getProjection(crsUuid);
57
+ imageProjection = new Projection({
58
+ epsg: getNextObliqueProjectionId(),
59
+ prefix: 'OBLIQUE:',
60
+ proj4: json.generalImageInfo.crs,
61
+ });
54
62
  }
55
63
 
56
64
  const defaultOptions = {
@@ -19,7 +19,7 @@ import Polygon from 'ol/geom/Polygon.js';
19
19
 
20
20
  import { check, checkMaybe } from '@vcsuite/check';
21
21
  import Projection, { mercatorProjection, wgs84Projection } from '../projection.js';
22
- import { createOrUpdateFromGeometry } from '../featureconverter/extent3d.js';
22
+ import Extent3D from '../featureconverter/extent3D.js';
23
23
  import { enforceEndingVertex, enforceRightHand, getFlatCoordinatesFromGeometry } from '../geometryHelpers.js';
24
24
 
25
25
  /**
@@ -75,9 +75,9 @@ function createVerticalPlanes(coords) {
75
75
  */
76
76
  function createHorizontalPlanes(feature, coords, options) {
77
77
  const clippingPlanes = [];
78
- const extent = createOrUpdateFromGeometry(feature.getGeometry());
79
- let min = Number.isFinite(extent[2]) ? extent[2] : 0;
80
- let max = Number.isFinite(extent[5]) ? extent[5] : 0;
78
+ const extent = Extent3D.fromGeometry(feature.getGeometry());
79
+ let min = Number.isFinite(extent.minZ) ? extent.minZ : 0;
80
+ let max = Number.isFinite(extent.maxZ) ? extent.maxZ : 0;
81
81
  const extruded = feature.get('olcs_extrudedHeight');
82
82
  if (extruded) {
83
83
  max += extruded;