@vcmap/core 5.0.0-rc.3 → 5.0.0-rc.6
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 +280 -75
- package/index.js +12 -3
- package/package.json +7 -14
- 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/globalCollections.js +1 -5
- 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/singleImage.js +2 -1
- 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 +19 -24
- package/src/vcs/vcm/object.js +1 -1
- package/src/vcs/vcm/oblique/ObliqueCollection.js +25 -1
- package/src/vcs/vcm/oblique/ObliqueDataSet.js +7 -7
- package/src/vcs/vcm/oblique/ObliqueImageMeta.js +2 -2
- package/src/vcs/vcm/oblique/ObliqueProvider.js +2 -1
- package/src/vcs/vcm/oblique/ObliqueView.js +31 -1
- package/src/vcs/vcm/oblique/defaultObliqueCollection.js +62 -0
- package/src/vcs/vcm/util/clipping/clippingPlaneHelper.js +4 -4
- package/src/vcs/vcm/util/extent.js +7 -10
- 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/overrideCollection.js +224 -0
- 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/vcsApp.js +373 -0
- package/src/vcs/vcm/vcsAppContextHelpers.js +108 -0
- package/src/vcs/vcm/util/featureconverter/extent3d.js +0 -154
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import axios from 'axios';
|
|
2
1
|
import { createXYZ } from 'ol/tilegrid.js';
|
|
3
2
|
import { cartesian2DDistance } from '../util/math.js';
|
|
4
3
|
import { parseImageData, parseImageMeta, parseLegacyImageData, getVersionFromImageJson } from './parseImageJson.js';
|
|
5
4
|
import VcsEvent from '../event/vcsEvent.js';
|
|
6
5
|
import { getTerrainProviderForUrl } from '../layer/terrainHelpers.js';
|
|
7
6
|
import Projection from '../util/projection.js';
|
|
7
|
+
import { requestJson } from '../util/fetch.js';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* @typedef {Object} ObliqueDataSetImagesLoaded
|
|
@@ -156,9 +156,10 @@ class ObliqueDataSet {
|
|
|
156
156
|
if (!this._loadingPromise) {
|
|
157
157
|
this._state = DataState.LOADING;
|
|
158
158
|
|
|
159
|
-
this._loadingPromise =
|
|
160
|
-
.then(
|
|
161
|
-
|
|
159
|
+
this._loadingPromise = requestJson(this.url)
|
|
160
|
+
.then(data => this._initialize(data))
|
|
161
|
+
.catch((err) => {
|
|
162
|
+
return Promise.reject(err);
|
|
162
163
|
});
|
|
163
164
|
}
|
|
164
165
|
return this._loadingPromise;
|
|
@@ -326,9 +327,8 @@ class ObliqueDataSet {
|
|
|
326
327
|
}
|
|
327
328
|
|
|
328
329
|
this._tiles.set(stringTileCoordinates, DataState.LOADING);
|
|
329
|
-
const promise =
|
|
330
|
-
.
|
|
331
|
-
.then(({ data }) => {
|
|
330
|
+
const promise = requestJson(`${this.baseUrl}/${stringTileCoordinates}.json`)
|
|
331
|
+
.then((data) => {
|
|
332
332
|
const images = parseImageData(data, this._imageMetas);
|
|
333
333
|
if (images.length > 0) {
|
|
334
334
|
this._images = this._images.concat(images);
|
|
@@ -11,7 +11,7 @@ import { cartesian2DDistance } from '../util/math.js';
|
|
|
11
11
|
* @property {Array<number>} tileResolution
|
|
12
12
|
* @property {import("@vcmap/core").Projection} projection
|
|
13
13
|
* @property {string} url
|
|
14
|
-
* @property {import("@vcmap/cesium").CesiumTerrainProvider} terrainProvider
|
|
14
|
+
* @property {import("@vcmap/cesium").CesiumTerrainProvider} [terrainProvider]
|
|
15
15
|
* @property {string} name
|
|
16
16
|
* @property {string|undefined} [format='jpg']
|
|
17
17
|
* @api
|
|
@@ -75,7 +75,7 @@ class ObliqueImageMeta {
|
|
|
75
75
|
this.url = options.url;
|
|
76
76
|
/**
|
|
77
77
|
* An optional terrain provider
|
|
78
|
-
* @type {import("@vcmap/cesium").CesiumTerrainProvider}
|
|
78
|
+
* @type {import("@vcmap/cesium").CesiumTerrainProvider|undefined}
|
|
79
79
|
* @api
|
|
80
80
|
*/
|
|
81
81
|
this.terrainProvider = options.terrainProvider;
|
|
@@ -7,6 +7,7 @@ import { transformFromImage } from './helpers.js';
|
|
|
7
7
|
import { getHeightFromTerrainProvider } from '../layer/terrainHelpers.js';
|
|
8
8
|
import { mercatorProjection } from '../util/projection.js';
|
|
9
9
|
import VcsEvent from '../event/vcsEvent.js';
|
|
10
|
+
import { isDefaultImageSymbol } from './defaultObliqueCollection.js';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* @typedef {Object} ObliqueViewPoint
|
|
@@ -293,7 +294,7 @@ class ObliqueProvider {
|
|
|
293
294
|
const previousView = this._currentView;
|
|
294
295
|
this._currentView = olView;
|
|
295
296
|
if (isNewImage) {
|
|
296
|
-
this._currentView.setImageName(this._currentImage.name);
|
|
297
|
+
this._currentView.setImageName(this._currentImage.name, this._currentImage[isDefaultImageSymbol]);
|
|
297
298
|
}
|
|
298
299
|
|
|
299
300
|
const [width, height] = this._currentImage.meta.size;
|
|
@@ -6,6 +6,29 @@ import TileImage from 'ol/source/TileImage.js';
|
|
|
6
6
|
import Tile from 'ol/layer/Tile.js';
|
|
7
7
|
import { hasSameOrigin } from './helpers.js';
|
|
8
8
|
|
|
9
|
+
/** @type {string} */
|
|
10
|
+
let defaultImage = '';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @returns {string}
|
|
14
|
+
*/
|
|
15
|
+
function getDefaultImage() {
|
|
16
|
+
if (!defaultImage) {
|
|
17
|
+
const canvas = document.createElement('canvas');
|
|
18
|
+
canvas.height = 512;
|
|
19
|
+
canvas.width = 512;
|
|
20
|
+
const context = canvas.getContext('2d');
|
|
21
|
+
context.fillStyle = '#409D76';
|
|
22
|
+
context.fillRect(0, 0, 512, 512);
|
|
23
|
+
context.font = 'bold 46px Monospace, Courier New';
|
|
24
|
+
context.fillStyle = '#424242';
|
|
25
|
+
context.textAlign = 'center';
|
|
26
|
+
context.fillText('No Image', 256, 256);
|
|
27
|
+
defaultImage = canvas.toDataURL('png');
|
|
28
|
+
}
|
|
29
|
+
return defaultImage;
|
|
30
|
+
}
|
|
31
|
+
|
|
9
32
|
/**
|
|
10
33
|
* @typedef {Object} ObliqueViewOptions
|
|
11
34
|
* @property {number} minZoom
|
|
@@ -108,9 +131,16 @@ class ObliqueView {
|
|
|
108
131
|
/**
|
|
109
132
|
* Sets the layers source to request data for this image
|
|
110
133
|
* @param {string} name
|
|
134
|
+
* @param {boolean} [isDefaultImage=false]
|
|
111
135
|
* @api
|
|
112
136
|
*/
|
|
113
|
-
setImageName(name) {
|
|
137
|
+
setImageName(name, isDefaultImage = false) {
|
|
138
|
+
if (isDefaultImage) {
|
|
139
|
+
this.tileImageSource.setTileLoadFunction(/** @param {import("ol").ImageTile} tile */ (tile) => {
|
|
140
|
+
/** @type {HTMLImageElement} */ (tile.getImage()).src = getDefaultImage();
|
|
141
|
+
tile.load();
|
|
142
|
+
});
|
|
143
|
+
}
|
|
114
144
|
this.tileImageSource.setTileUrlFunction((coords) => {
|
|
115
145
|
const [z, x, yInverted] = coords;
|
|
116
146
|
const y = -yInverted - 1;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import ObliqueCollection from './ObliqueCollection.js';
|
|
2
|
+
import ObliqueImage from './ObliqueImage.js';
|
|
3
|
+
import ObliqueImageMeta from './ObliqueImageMeta.js';
|
|
4
|
+
import { ObliqueViewDirection } from './ObliqueViewDirection.js';
|
|
5
|
+
import { mercatorProjection } from '../util/projection.js';
|
|
6
|
+
|
|
7
|
+
const defaultMeta = new ObliqueImageMeta({
|
|
8
|
+
name: 'defaultObliqueMeta',
|
|
9
|
+
size: [512, 512],
|
|
10
|
+
tileSize: [512, 512],
|
|
11
|
+
tileResolution: [1],
|
|
12
|
+
projection: mercatorProjection,
|
|
13
|
+
format: 'png',
|
|
14
|
+
url: '',
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @type {symbol}
|
|
19
|
+
* @private
|
|
20
|
+
*/
|
|
21
|
+
export const isDefaultImageSymbol = Symbol('isDefaultImage');
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* This is a special oblique collection wich is shown, if no other oblique collection is set on an Oblique map.
|
|
25
|
+
* It will render a single image which indicates that no images can be loaded.
|
|
26
|
+
* @class
|
|
27
|
+
* @extends {ObliqueCollection}
|
|
28
|
+
*/
|
|
29
|
+
class DefaultObliqueCollection extends ObliqueCollection {
|
|
30
|
+
constructor() {
|
|
31
|
+
super({});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @param {import("ol/coordinate").Coordinate} mercatorCoordinate
|
|
36
|
+
* @param {ObliqueViewDirection} viewDirection
|
|
37
|
+
* @returns {ObliqueImage}
|
|
38
|
+
*/
|
|
39
|
+
// eslint-disable-next-line no-unused-vars
|
|
40
|
+
getImageForCoordinate(mercatorCoordinate, viewDirection) {
|
|
41
|
+
const groundCoordinates = [
|
|
42
|
+
[mercatorCoordinate[0] - 100, mercatorCoordinate[1] - 100, 0],
|
|
43
|
+
[mercatorCoordinate[0] + 100, mercatorCoordinate[1] - 100, 0],
|
|
44
|
+
[mercatorCoordinate[0] + 100, mercatorCoordinate[1] + 100, 0],
|
|
45
|
+
[mercatorCoordinate[0] - 100, mercatorCoordinate[1] + 100, 0],
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
const image = new ObliqueImage({
|
|
49
|
+
meta: defaultMeta,
|
|
50
|
+
viewDirection: ObliqueViewDirection.NORTH,
|
|
51
|
+
viewDirectionAngle: 0,
|
|
52
|
+
name: this.name,
|
|
53
|
+
groundCoordinates,
|
|
54
|
+
centerPointOnGround: mercatorCoordinate,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
image[isDefaultImageSymbol] = true;
|
|
58
|
+
return image;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export default DefaultObliqueCollection;
|
|
@@ -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;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import Projection from './projection.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* @typedef {
|
|
5
|
-
* @property {
|
|
4
|
+
* @typedef {Object} ExtentOptions
|
|
5
|
+
* @property {string} [type]
|
|
6
|
+
* @property {import("ol/extent").Extent|undefined} [coordinates] - if not specified, the extent of the projection is used
|
|
7
|
+
* @property {ProjectionOptions} [projection] - if not specified the default projection is assumed
|
|
6
8
|
* @api
|
|
7
9
|
*/
|
|
8
10
|
|
|
@@ -45,12 +47,7 @@ class Extent {
|
|
|
45
47
|
*/
|
|
46
48
|
constructor(options = {}) {
|
|
47
49
|
/** @type {Projection} */
|
|
48
|
-
this.projection = new Projection(
|
|
49
|
-
epsg: options.epsg,
|
|
50
|
-
proj4: options.proj4,
|
|
51
|
-
alias: options.alias,
|
|
52
|
-
prefix: options.prefix,
|
|
53
|
-
});
|
|
50
|
+
this.projection = new Projection(options.projection);
|
|
54
51
|
|
|
55
52
|
/** @type {import("ol/extent").Extent|null} */
|
|
56
53
|
this.extent = options.coordinates || this.projection.proj.getExtent();
|
|
@@ -87,7 +84,7 @@ class Extent {
|
|
|
87
84
|
toJSON() {
|
|
88
85
|
return {
|
|
89
86
|
coordinates: this.extent.slice(),
|
|
90
|
-
|
|
87
|
+
projection: this.projection.toJSON(),
|
|
91
88
|
type: Extent.className,
|
|
92
89
|
};
|
|
93
90
|
}
|
|
@@ -122,7 +119,7 @@ class Extent {
|
|
|
122
119
|
* @api
|
|
123
120
|
*/
|
|
124
121
|
static validateOptions(options) {
|
|
125
|
-
return Projection.validateOptions(options) && checkExtentValidity(options.coordinates);
|
|
122
|
+
return Projection.validateOptions(options.projection || {}) && checkExtentValidity(options.coordinates);
|
|
126
123
|
}
|
|
127
124
|
|
|
128
125
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getCenter } from 'ol/extent.js';
|
|
2
2
|
import Projection from '../projection.js';
|
|
3
|
-
import
|
|
3
|
+
import Extent3D from '../featureconverter/extent3D.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @param {VectorClickedObject} feature
|
|
@@ -32,9 +32,8 @@ export function getGenericFeatureFromProvidedFeature(feature, layer) {
|
|
|
32
32
|
|
|
33
33
|
let heightOffset = clickedPosition.height;
|
|
34
34
|
if (!isModel) {
|
|
35
|
-
const extent =
|
|
36
|
-
|
|
37
|
-
heightOffset = max;
|
|
35
|
+
const extent = Extent3D.fromGeometry(geometry);
|
|
36
|
+
heightOffset = Number.isFinite(extent.maxZ) ? extent.maxZ : 0;
|
|
38
37
|
}
|
|
39
38
|
const relativeToGround = !isModel && feature.get('olcs_altitudeMode') === 'relativeToGround';
|
|
40
39
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import axios from 'axios';
|
|
2
1
|
import GML2 from 'ol/format/GML2.js';
|
|
3
2
|
import WFS from 'ol/format/WFS.js';
|
|
4
3
|
import GeoJSON from 'ol/format/GeoJSON.js';
|
|
@@ -10,6 +9,7 @@ import AbstractFeatureProvider from './abstractFeatureProvider.js';
|
|
|
10
9
|
import Projection, { mercatorProjection } from '../projection.js';
|
|
11
10
|
import { getWMSSource } from '../../layer/wmsHelpers.js';
|
|
12
11
|
import Extent from '../extent.js';
|
|
12
|
+
import { requestJson } from '../fetch.js';
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* @typedef {AbstractFeatureProviderOptions} WMSFeatureProviderOptions
|
|
@@ -155,12 +155,11 @@ class WMSFeatureProvider extends AbstractFeatureProvider {
|
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
/**
|
|
158
|
-
* @param {import("
|
|
158
|
+
* @param {import("ol/format/GeoJSON").GeoJSONObject} data
|
|
159
159
|
* @param {import("ol/coordinate").Coordinate} coordinate
|
|
160
160
|
* @returns {Array<import("ol").Feature<import("ol/geom/Geometry").default>>}
|
|
161
161
|
*/
|
|
162
|
-
featureResponseCallback(
|
|
163
|
-
const { data } = response;
|
|
162
|
+
featureResponseCallback(data, coordinate) {
|
|
164
163
|
/** @type {Array<import("ol").Feature<import("ol/geom/Geometry").default>>} */
|
|
165
164
|
let features;
|
|
166
165
|
|
|
@@ -211,8 +210,14 @@ class WMSFeatureProvider extends AbstractFeatureProvider {
|
|
|
211
210
|
);
|
|
212
211
|
|
|
213
212
|
if (url) {
|
|
214
|
-
|
|
215
|
-
|
|
213
|
+
let data;
|
|
214
|
+
try {
|
|
215
|
+
data = await requestJson(url);
|
|
216
|
+
} catch (ex) {
|
|
217
|
+
this.getLogger().error(`Failed fetching WMS FeatureInfo ${url}`);
|
|
218
|
+
return [];
|
|
219
|
+
}
|
|
220
|
+
return this.featureResponseCallback(data, coordinate)
|
|
216
221
|
.map(f => this.getProviderFeature(f));
|
|
217
222
|
}
|
|
218
223
|
return [];
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import GeometryType from 'ol/geom/GeometryType.js';
|
|
2
|
+
import { check } from '@vcsuite/check';
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Extent3D {
|
|
6
|
+
/**
|
|
7
|
+
* @param {Array<number>} array
|
|
8
|
+
* @returns {Extent3D}
|
|
9
|
+
*/
|
|
10
|
+
static fromArray(array) {
|
|
11
|
+
check(array, [Number]);
|
|
12
|
+
check(array.length, 6);
|
|
13
|
+
return new Extent3D(array[0], array[1], array[2], array[3], array[4], array[5]);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param {import("ol/geom").Geometry} geometry
|
|
18
|
+
* @returns {Extent3D}
|
|
19
|
+
*/
|
|
20
|
+
static fromGeometry(geometry) {
|
|
21
|
+
const extent = new Extent3D();
|
|
22
|
+
extent.extendWithGeometry(geometry);
|
|
23
|
+
return extent;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @param {VectorHeightInfo} heightInfo
|
|
28
|
+
* @returns {Extent3D}
|
|
29
|
+
*/
|
|
30
|
+
static fromHeightInfo(heightInfo) {
|
|
31
|
+
const extent = new Extent3D();
|
|
32
|
+
extent.extendWithHeightInfo(heightInfo);
|
|
33
|
+
return extent;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @param {number} minX
|
|
38
|
+
* @param {number} minY
|
|
39
|
+
* @param {number} minZ
|
|
40
|
+
* @param {number} maxX
|
|
41
|
+
* @param {number} maxY
|
|
42
|
+
* @param {number} maxZ
|
|
43
|
+
*/
|
|
44
|
+
constructor(minX = Infinity, minY = Infinity, minZ = Infinity, maxX = -Infinity, maxY = -Infinity, maxZ = -Infinity) {
|
|
45
|
+
/**
|
|
46
|
+
* @type {number}
|
|
47
|
+
*/
|
|
48
|
+
this.minX = minX;
|
|
49
|
+
/**
|
|
50
|
+
* @type {number}
|
|
51
|
+
*/
|
|
52
|
+
this.minY = minY;
|
|
53
|
+
/**
|
|
54
|
+
* @type {number}
|
|
55
|
+
*/
|
|
56
|
+
this.minZ = minZ;
|
|
57
|
+
/**
|
|
58
|
+
* @type {number}
|
|
59
|
+
*/
|
|
60
|
+
this.maxX = maxX;
|
|
61
|
+
/**
|
|
62
|
+
* @type {number}
|
|
63
|
+
*/
|
|
64
|
+
this.maxY = maxY;
|
|
65
|
+
/**
|
|
66
|
+
* @type {number}
|
|
67
|
+
*/
|
|
68
|
+
this.maxZ = maxZ;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @param {import("ol/geom").Geometry} geometry
|
|
73
|
+
*/
|
|
74
|
+
extendWithGeometry(geometry) {
|
|
75
|
+
if (geometry.getType() === GeometryType.GEOMETRY_COLLECTION) {
|
|
76
|
+
/** @type {import("ol/geom/GeometryCollection").default} */ (geometry)
|
|
77
|
+
.getGeometriesArray().forEach((geom) => { this.extendWithGeometry(geom); });
|
|
78
|
+
} else if (geometry.getType() === GeometryType.CIRCLE) {
|
|
79
|
+
const flatCoordinates = /** @type {import("ol/geom/Circle").default} */ (geometry).getFlatCoordinates();
|
|
80
|
+
const stride = /** @type {import("ol/geom/Circle").default} */ (geometry).getStride();
|
|
81
|
+
const radius = flatCoordinates[stride] - flatCoordinates[0];
|
|
82
|
+
this.extendXY(
|
|
83
|
+
flatCoordinates[0] - radius,
|
|
84
|
+
flatCoordinates[1] - radius,
|
|
85
|
+
);
|
|
86
|
+
this.extendXY(
|
|
87
|
+
flatCoordinates[0] + radius,
|
|
88
|
+
flatCoordinates[1] + radius,
|
|
89
|
+
);
|
|
90
|
+
if (stride > 2) {
|
|
91
|
+
this.extendZ(flatCoordinates[2]);
|
|
92
|
+
}
|
|
93
|
+
} else {
|
|
94
|
+
const flatCoordinates = /** @type {import("ol/geom/SimpleGeometry").default} */ (geometry).getFlatCoordinates();
|
|
95
|
+
const stride = /** @type {import("ol/geom/SimpleGeometry").default} */ (geometry).getStride();
|
|
96
|
+
this.extendFlatCoordinates(flatCoordinates, stride);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @param {VectorHeightInfo} heightInfo
|
|
102
|
+
*/
|
|
103
|
+
extendWithHeightInfo(heightInfo) {
|
|
104
|
+
if (heightInfo.extruded) {
|
|
105
|
+
const calculatedFeatureMaxHeight =
|
|
106
|
+
heightInfo.groundLevel + heightInfo.storeyHeightsAboveGround.reduce((accumulator, currentValue) => {
|
|
107
|
+
return accumulator + currentValue;
|
|
108
|
+
}, 0);
|
|
109
|
+
this.extendZ(calculatedFeatureMaxHeight);
|
|
110
|
+
const calculatedFeatureMinHeight =
|
|
111
|
+
heightInfo.groundLevel - heightInfo.storeyHeightsBelowGround.reduce((accumulator, currentValue) => {
|
|
112
|
+
return accumulator + currentValue;
|
|
113
|
+
}, 0);
|
|
114
|
+
this.extendZ(calculatedFeatureMinHeight);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* @param {number} x
|
|
120
|
+
* @param {number} y
|
|
121
|
+
* @param {number} z
|
|
122
|
+
*/
|
|
123
|
+
extendXYZ(x, y, z) {
|
|
124
|
+
this.minX = Math.min(this.minX, x);
|
|
125
|
+
this.minY = Math.min(this.minY, y);
|
|
126
|
+
this.minZ = Math.min(this.minZ, z);
|
|
127
|
+
this.maxX = Math.max(this.maxX, x);
|
|
128
|
+
this.maxY = Math.max(this.maxY, y);
|
|
129
|
+
this.maxZ = Math.max(this.maxZ, z);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* @param {number} x
|
|
134
|
+
* @param {number} y
|
|
135
|
+
*/
|
|
136
|
+
extendXY(x, y) {
|
|
137
|
+
this.minX = Math.min(this.minX, x);
|
|
138
|
+
this.minY = Math.min(this.minY, y);
|
|
139
|
+
this.maxX = Math.max(this.maxX, x);
|
|
140
|
+
this.maxY = Math.max(this.maxY, y);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* @param {number} z
|
|
145
|
+
*/
|
|
146
|
+
extendZ(z) {
|
|
147
|
+
this.minZ = Math.min(this.minZ, z);
|
|
148
|
+
this.maxZ = Math.max(this.maxZ, z);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* @param {Array<number>} flatCoordinates
|
|
153
|
+
* @param {number} stride
|
|
154
|
+
*/
|
|
155
|
+
extendFlatCoordinates(flatCoordinates, stride) {
|
|
156
|
+
const { length } = flatCoordinates;
|
|
157
|
+
for (let offset = 0; offset < length; offset += stride) {
|
|
158
|
+
if (stride > 2) {
|
|
159
|
+
this.extendXYZ(flatCoordinates[offset], flatCoordinates[offset + 1], flatCoordinates[offset + 2]);
|
|
160
|
+
} else {
|
|
161
|
+
this.extendXY(flatCoordinates[offset], flatCoordinates[offset + 1]);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* @returns {import("ol/extent").Extent}
|
|
168
|
+
*/
|
|
169
|
+
to2D() {
|
|
170
|
+
return [this.minX, this.minY, this.maxX, this.maxY];
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* @returns {Array<number>}
|
|
175
|
+
*/
|
|
176
|
+
toArray() {
|
|
177
|
+
return [this.minX, this.minY, this.minZ, this.maxX, this.maxY, this.maxZ];
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export default Extent3D;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {string} url
|
|
3
|
+
* @param {RequestInit=} init
|
|
4
|
+
* @returns {Promise<Response>}
|
|
5
|
+
*/
|
|
6
|
+
export async function requestUrl(url, init) {
|
|
7
|
+
const response = await fetch(url, init);
|
|
8
|
+
if (!response.ok) {
|
|
9
|
+
throw new Error(`Failed fetching url ${url} with status: ${response.status}`);
|
|
10
|
+
}
|
|
11
|
+
return response;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @param {string} url
|
|
16
|
+
* @param {RequestInit=} init
|
|
17
|
+
* @returns {Promise<any>}
|
|
18
|
+
*/
|
|
19
|
+
export async function requestJson(url, init) {
|
|
20
|
+
const response = await requestUrl(url, init);
|
|
21
|
+
return response.json();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @param {string} url
|
|
26
|
+
* @param {RequestInit=} init
|
|
27
|
+
* @returns {Promise<ArrayBuffer>}
|
|
28
|
+
*/
|
|
29
|
+
export async function requestArrayBuffer(url, init) {
|
|
30
|
+
const response = await requestUrl(url, init);
|
|
31
|
+
return response.arrayBuffer();
|
|
32
|
+
}
|