@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.
- package/index.d.ts +287 -95
- package/index.js +11 -3
- package/package.json +5 -10
- package/src/vcs/vcm/category/appBackedCategory.js +41 -0
- package/src/vcs/vcm/category/category.js +374 -0
- package/src/vcs/vcm/category/categoryCollection.js +145 -0
- package/src/vcs/vcm/context.js +73 -0
- package/src/vcs/vcm/interaction/coordinateAtPixel.js +1 -1
- package/src/vcs/vcm/layer/cesiumTileset.js +1 -1
- package/src/vcs/vcm/layer/featureStore.js +3 -3
- package/src/vcs/vcm/layer/featureStoreChanges.js +89 -73
- package/src/vcs/vcm/layer/geojson.js +3 -5
- package/src/vcs/vcm/layer/geojsonHelpers.js +3 -3
- package/src/vcs/vcm/layer/oblique/obliqueHelpers.js +2 -2
- package/src/vcs/vcm/layer/singleImage.js +2 -1
- package/src/vcs/vcm/layer/terrainHelpers.js +4 -8
- package/src/vcs/vcm/layer/tileProvider/mvtTileProvider.js +3 -3
- package/src/vcs/vcm/layer/tileProvider/staticGeojsonTileProvider.js +3 -3
- package/src/vcs/vcm/layer/tileProvider/urlTemplateTileProvider.js +3 -3
- package/src/vcs/vcm/layer/vector.js +1 -1
- package/src/vcs/vcm/layer/vectorHelpers.js +4 -4
- package/src/vcs/vcm/layer/wfs.js +5 -5
- package/src/vcs/vcm/maps/cameraLimiter.js +5 -5
- package/src/vcs/vcm/maps/map.js +26 -11
- package/src/vcs/vcm/maps/oblique.js +8 -8
- package/src/vcs/vcm/object.js +1 -1
- package/src/vcs/vcm/oblique/ObliqueCollection.js +83 -31
- package/src/vcs/vcm/oblique/ObliqueDataSet.js +67 -24
- package/src/vcs/vcm/oblique/ObliqueImage.js +1 -1
- package/src/vcs/vcm/oblique/ObliqueImageMeta.js +2 -2
- package/src/vcs/vcm/oblique/ObliqueProvider.js +10 -7
- package/src/vcs/vcm/oblique/helpers.js +12 -40
- package/src/vcs/vcm/oblique/parseImageJson.js +17 -9
- package/src/vcs/vcm/util/clipping/clippingPlaneHelper.js +4 -4
- package/src/vcs/vcm/util/extent.js +16 -9
- package/src/vcs/vcm/util/featureProvider/featureProviderHelpers.js +3 -4
- package/src/vcs/vcm/util/featureProvider/wmsFeatureProvider.js +11 -6
- package/src/vcs/vcm/util/featureconverter/extent3D.js +181 -0
- package/src/vcs/vcm/util/fetch.js +32 -0
- package/src/vcs/vcm/util/indexedCollection.js +23 -0
- package/src/vcs/vcm/util/layerCollection.js +10 -5
- package/src/vcs/vcm/util/overrideCollection.js +224 -0
- package/src/vcs/vcm/util/projection.js +37 -3
- package/src/vcs/vcm/util/style/declarativeStyleItem.js +2 -0
- package/src/vcs/vcm/util/style/styleFactory.js +1 -1
- package/src/vcs/vcm/util/style/styleItem.js +2 -0
- package/src/vcs/vcm/util/style/vectorStyleItem.js +2 -0
- package/src/vcs/vcm/util/viewpoint.js +3 -0
- package/src/vcs/vcm/vcsApp.js +360 -0
- package/src/vcs/vcm/vcsAppContextHelpers.js +108 -0
- 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
|
|
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}
|
|
56
|
-
* @property {string
|
|
57
|
-
* @property {
|
|
58
|
-
* @property {
|
|
59
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
|
140
|
-
minZoom: options.minZoom
|
|
141
|
-
scaleFactor: options.scaleFactor
|
|
142
|
-
hideLevels: options.hideLevels
|
|
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/
|
|
168
|
+
* @type {import("@vcmap/core").VcsEvent<Array<import("@vcmap/core").ObliqueImage>>}
|
|
151
169
|
* @api
|
|
152
170
|
*/
|
|
153
|
-
this.imagesLoaded = new
|
|
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}
|
|
283
|
+
* @param {import("@vcmap/core").ObliqueDataSet|ObliqueDataSetOptions} dataSetOptions
|
|
266
284
|
* @private
|
|
267
285
|
*/
|
|
268
|
-
_addDataSet(
|
|
269
|
-
|
|
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,
|
|
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(
|
|
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,
|
|
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("
|
|
47
|
-
* @param {
|
|
53
|
+
* @param {import("@vcmap/core").Projection|ProjectionOptions=} projection
|
|
54
|
+
* @param {TerrainProviderOptions=} terrainProviderOptions
|
|
48
55
|
*/
|
|
49
|
-
constructor(url, projection,
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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.
|
|
69
|
-
*
|
|
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
|
|
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 =
|
|
131
|
-
.then(
|
|
132
|
-
|
|
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 =
|
|
301
|
-
.
|
|
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
|
-
|
|
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.
|
|
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("
|
|
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("
|
|
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("
|
|
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 {
|
|
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/
|
|
66
|
+
* @type {import("@vcmap/core").VcsEvent<import("@vcmap/core").ObliqueImage>}
|
|
67
67
|
* @api
|
|
68
68
|
*/
|
|
69
|
-
this.imageChanged = new
|
|
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,
|
|
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(
|
|
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
|
-
|
|
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 {
|
|
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("
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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 {
|
|
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
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
|
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 =
|
|
79
|
-
let min = Number.isFinite(extent
|
|
80
|
-
let max = Number.isFinite(extent
|
|
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;
|