@vcmap/core 5.0.0-rc.0

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 (146) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +44 -0
  3. package/build/postinstall.js +44 -0
  4. package/index.js +139 -0
  5. package/package.json +92 -0
  6. package/src/cesium/cesium3DTileFeature.js +9 -0
  7. package/src/cesium/cesium3DTilePointFeature.js +9 -0
  8. package/src/cesium/cesiumVcsCameraPrimitive.js +146 -0
  9. package/src/cesium/wallpaperMaterial.js +64 -0
  10. package/src/ol/feature.js +47 -0
  11. package/src/ol/geom/circle.js +24 -0
  12. package/src/ol/geom/geometryCollection.js +33 -0
  13. package/src/ol/render/canvas/canvasTileRenderer.js +179 -0
  14. package/src/ol/source/ClusterEnhancedVectorSource.js +39 -0
  15. package/src/ol/source/VcsCluster.js +37 -0
  16. package/src/vcs/vcm/classRegistry.js +106 -0
  17. package/src/vcs/vcm/event/vcsEvent.js +89 -0
  18. package/src/vcs/vcm/globalCollections.js +11 -0
  19. package/src/vcs/vcm/interaction/abstractInteraction.js +149 -0
  20. package/src/vcs/vcm/interaction/coordinateAtPixel.js +102 -0
  21. package/src/vcs/vcm/interaction/eventHandler.js +425 -0
  22. package/src/vcs/vcm/interaction/featureAtPixelInteraction.js +286 -0
  23. package/src/vcs/vcm/interaction/featureProviderInteraction.js +54 -0
  24. package/src/vcs/vcm/interaction/interactionChain.js +124 -0
  25. package/src/vcs/vcm/interaction/interactionType.js +114 -0
  26. package/src/vcs/vcm/layer/buildings.js +17 -0
  27. package/src/vcs/vcm/layer/cesium/cesiumTilesetCesium.js +359 -0
  28. package/src/vcs/vcm/layer/cesium/clusterContext.js +95 -0
  29. package/src/vcs/vcm/layer/cesium/dataSourceCesium.js +171 -0
  30. package/src/vcs/vcm/layer/cesium/openStreetMapCesium.js +29 -0
  31. package/src/vcs/vcm/layer/cesium/pointCloudCesium.js +58 -0
  32. package/src/vcs/vcm/layer/cesium/rasterLayerCesium.js +110 -0
  33. package/src/vcs/vcm/layer/cesium/singleImageCesium.js +49 -0
  34. package/src/vcs/vcm/layer/cesium/terrainCesium.js +80 -0
  35. package/src/vcs/vcm/layer/cesium/tmsCesium.js +54 -0
  36. package/src/vcs/vcm/layer/cesium/vectorCesium.js +255 -0
  37. package/src/vcs/vcm/layer/cesium/vectorContext.js +167 -0
  38. package/src/vcs/vcm/layer/cesium/vectorRasterTileCesium.js +116 -0
  39. package/src/vcs/vcm/layer/cesium/vectorTileImageryProvider.js +246 -0
  40. package/src/vcs/vcm/layer/cesium/wmsCesium.js +71 -0
  41. package/src/vcs/vcm/layer/cesium/wmtsCesium.js +101 -0
  42. package/src/vcs/vcm/layer/cesium/x3dmHelper.js +22 -0
  43. package/src/vcs/vcm/layer/cesiumTileset.js +376 -0
  44. package/src/vcs/vcm/layer/czml.js +141 -0
  45. package/src/vcs/vcm/layer/dataSource.js +259 -0
  46. package/src/vcs/vcm/layer/featureLayer.js +261 -0
  47. package/src/vcs/vcm/layer/featureStore.js +647 -0
  48. package/src/vcs/vcm/layer/featureStoreChanges.js +360 -0
  49. package/src/vcs/vcm/layer/featureStoreState.js +19 -0
  50. package/src/vcs/vcm/layer/featureVisibility.js +435 -0
  51. package/src/vcs/vcm/layer/geojson.js +185 -0
  52. package/src/vcs/vcm/layer/geojsonHelpers.js +450 -0
  53. package/src/vcs/vcm/layer/globalHider.js +157 -0
  54. package/src/vcs/vcm/layer/layer.js +752 -0
  55. package/src/vcs/vcm/layer/layerImplementation.js +102 -0
  56. package/src/vcs/vcm/layer/layerState.js +17 -0
  57. package/src/vcs/vcm/layer/layerSymbols.js +6 -0
  58. package/src/vcs/vcm/layer/oblique/layerOblique.js +76 -0
  59. package/src/vcs/vcm/layer/oblique/obliqueHelpers.js +175 -0
  60. package/src/vcs/vcm/layer/oblique/vectorOblique.js +469 -0
  61. package/src/vcs/vcm/layer/openStreetMap.js +194 -0
  62. package/src/vcs/vcm/layer/openlayers/layerOpenlayers.js +79 -0
  63. package/src/vcs/vcm/layer/openlayers/openStreetMapOpenlayers.js +27 -0
  64. package/src/vcs/vcm/layer/openlayers/rasterLayerOpenlayers.js +121 -0
  65. package/src/vcs/vcm/layer/openlayers/singleImageOpenlayers.js +49 -0
  66. package/src/vcs/vcm/layer/openlayers/tileDebugOpenlayers.js +39 -0
  67. package/src/vcs/vcm/layer/openlayers/tmsOpenlayers.js +62 -0
  68. package/src/vcs/vcm/layer/openlayers/vectorOpenlayers.js +118 -0
  69. package/src/vcs/vcm/layer/openlayers/vectorTileOpenlayers.js +177 -0
  70. package/src/vcs/vcm/layer/openlayers/wmsOpenlayers.js +55 -0
  71. package/src/vcs/vcm/layer/openlayers/wmtsOpenlayers.js +141 -0
  72. package/src/vcs/vcm/layer/pointCloud.js +162 -0
  73. package/src/vcs/vcm/layer/rasterLayer.js +294 -0
  74. package/src/vcs/vcm/layer/singleImage.js +119 -0
  75. package/src/vcs/vcm/layer/terrain.js +122 -0
  76. package/src/vcs/vcm/layer/terrainHelpers.js +123 -0
  77. package/src/vcs/vcm/layer/tileLoadedHelper.js +72 -0
  78. package/src/vcs/vcm/layer/tileProvider/mvtTileProvider.js +104 -0
  79. package/src/vcs/vcm/layer/tileProvider/staticGeojsonTileProvider.js +67 -0
  80. package/src/vcs/vcm/layer/tileProvider/tileProvider.js +584 -0
  81. package/src/vcs/vcm/layer/tileProvider/tileProviderFactory.js +28 -0
  82. package/src/vcs/vcm/layer/tileProvider/urlTemplateTileProvider.js +106 -0
  83. package/src/vcs/vcm/layer/tms.js +121 -0
  84. package/src/vcs/vcm/layer/vector.js +632 -0
  85. package/src/vcs/vcm/layer/vectorHelpers.js +206 -0
  86. package/src/vcs/vcm/layer/vectorProperties.js +1391 -0
  87. package/src/vcs/vcm/layer/vectorSymbols.js +40 -0
  88. package/src/vcs/vcm/layer/vectorTile.js +480 -0
  89. package/src/vcs/vcm/layer/wfs.js +165 -0
  90. package/src/vcs/vcm/layer/wms.js +270 -0
  91. package/src/vcs/vcm/layer/wmsHelpers.js +65 -0
  92. package/src/vcs/vcm/layer/wmts.js +235 -0
  93. package/src/vcs/vcm/maps/baseOLMap.js +257 -0
  94. package/src/vcs/vcm/maps/cameraLimiter.js +219 -0
  95. package/src/vcs/vcm/maps/cesium.js +1192 -0
  96. package/src/vcs/vcm/maps/map.js +511 -0
  97. package/src/vcs/vcm/maps/mapState.js +17 -0
  98. package/src/vcs/vcm/maps/oblique.js +536 -0
  99. package/src/vcs/vcm/maps/openlayers.js +205 -0
  100. package/src/vcs/vcm/object.js +92 -0
  101. package/src/vcs/vcm/oblique/ObliqueCollection.js +572 -0
  102. package/src/vcs/vcm/oblique/ObliqueDataSet.js +357 -0
  103. package/src/vcs/vcm/oblique/ObliqueImage.js +247 -0
  104. package/src/vcs/vcm/oblique/ObliqueImageMeta.js +126 -0
  105. package/src/vcs/vcm/oblique/ObliqueProvider.js +433 -0
  106. package/src/vcs/vcm/oblique/ObliqueView.js +130 -0
  107. package/src/vcs/vcm/oblique/ObliqueViewDirection.js +40 -0
  108. package/src/vcs/vcm/oblique/helpers.js +483 -0
  109. package/src/vcs/vcm/oblique/parseImageJson.js +248 -0
  110. package/src/vcs/vcm/util/clipping/clippingObject.js +386 -0
  111. package/src/vcs/vcm/util/clipping/clippingObjectManager.js +312 -0
  112. package/src/vcs/vcm/util/clipping/clippingPlaneHelper.js +413 -0
  113. package/src/vcs/vcm/util/collection.js +193 -0
  114. package/src/vcs/vcm/util/dateTime.js +60 -0
  115. package/src/vcs/vcm/util/exclusiveManager.js +135 -0
  116. package/src/vcs/vcm/util/extent.js +124 -0
  117. package/src/vcs/vcm/util/featureProvider/abstractFeatureProvider.js +196 -0
  118. package/src/vcs/vcm/util/featureProvider/featureProviderHelpers.js +51 -0
  119. package/src/vcs/vcm/util/featureProvider/featureProviderSymbols.js +11 -0
  120. package/src/vcs/vcm/util/featureProvider/tileProviderFeatureProvider.js +62 -0
  121. package/src/vcs/vcm/util/featureProvider/wmsFeatureProvider.js +280 -0
  122. package/src/vcs/vcm/util/featureconverter/circleToCesium.js +215 -0
  123. package/src/vcs/vcm/util/featureconverter/convert.js +83 -0
  124. package/src/vcs/vcm/util/featureconverter/extent3d.js +154 -0
  125. package/src/vcs/vcm/util/featureconverter/featureconverterHelper.js +591 -0
  126. package/src/vcs/vcm/util/featureconverter/lineStringToCesium.js +171 -0
  127. package/src/vcs/vcm/util/featureconverter/pointToCesium.js +359 -0
  128. package/src/vcs/vcm/util/featureconverter/polygonToCesium.js +229 -0
  129. package/src/vcs/vcm/util/geometryHelpers.js +172 -0
  130. package/src/vcs/vcm/util/indexedCollection.js +158 -0
  131. package/src/vcs/vcm/util/isMobile.js +12 -0
  132. package/src/vcs/vcm/util/layerCollection.js +216 -0
  133. package/src/vcs/vcm/util/locale.js +53 -0
  134. package/src/vcs/vcm/util/mapCollection.js +363 -0
  135. package/src/vcs/vcm/util/math.js +71 -0
  136. package/src/vcs/vcm/util/projection.js +348 -0
  137. package/src/vcs/vcm/util/splitScreen.js +233 -0
  138. package/src/vcs/vcm/util/style/declarativeStyleItem.js +631 -0
  139. package/src/vcs/vcm/util/style/shapesCategory.js +67 -0
  140. package/src/vcs/vcm/util/style/styleFactory.js +48 -0
  141. package/src/vcs/vcm/util/style/styleHelpers.js +555 -0
  142. package/src/vcs/vcm/util/style/styleItem.js +226 -0
  143. package/src/vcs/vcm/util/style/vectorStyleItem.js +927 -0
  144. package/src/vcs/vcm/util/style/writeStyle.js +48 -0
  145. package/src/vcs/vcm/util/urlHelpers.js +16 -0
  146. package/src/vcs/vcm/util/viewpoint.js +333 -0
@@ -0,0 +1,257 @@
1
+ import { Cartesian2 } from '@vcmap/cesium';
2
+ import { unByKey } from 'ol/Observable.js';
3
+ import OLMap from 'ol/Map.js';
4
+ import { defaults as defaultInteractions } from 'ol/interaction.js';
5
+ import VcsMap from './map.js';
6
+ import { vcsLayerName } from '../layer/layerSymbols.js';
7
+ import { ModificationKeyType, PointerEventType, PointerKeyType } from '../interaction/interactionType.js';
8
+ import { VcsClassRegistry } from '../classRegistry.js';
9
+
10
+ /**
11
+ * @param {import("ol/Collection").default<import("ol/layer/Layer").default>} layers
12
+ * @param {import("ol/layer/Layer").default} layer
13
+ * @param {import("@vcmap/core").LayerCollection} layerCollection
14
+ * @private
15
+ */
16
+ export function ensureLayerInCollection(layers, layer, layerCollection) {
17
+ const targetIndex = layerCollection.indexOfKey(layer[vcsLayerName]);
18
+ if (targetIndex > -1) {
19
+ const layerArray = layers.getArray();
20
+
21
+ if (!layerArray.includes(layer)) {
22
+ let indexInOlCollection = layerArray.findIndex((l) => {
23
+ const layerIndex = layerCollection.indexOfKey(l[vcsLayerName]);
24
+ return layerIndex > targetIndex;
25
+ });
26
+ if (indexInOlCollection === -1) {
27
+ indexInOlCollection = layerArray.length;
28
+ }
29
+ layers.insertAt(indexInOlCollection, layer);
30
+ }
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Openlayers Map base map.
36
+ * @class
37
+ * @abstract
38
+ * @api
39
+ * @export
40
+ * @extends {VcsMap}
41
+ */
42
+ class BaseOLMap extends VcsMap {
43
+ static get className() { return 'vcs.vcm.maps.BaseOLMap'; }
44
+
45
+ /**
46
+ * @param {VcsMapOptions} options
47
+ */
48
+ constructor(options) {
49
+ super(options);
50
+
51
+ /**
52
+ * the openlayers map object, set after initialization
53
+ * @private
54
+ * @type {import("ol/Map").default|null}
55
+ */
56
+ this._olMap = null;
57
+ /**
58
+ * @type {Array<import("ol/events").EventsKey>}
59
+ * @private
60
+ */
61
+ this._olListeners = [];
62
+ }
63
+
64
+ /**
65
+ * @returns {import("ol/Map").default}
66
+ * @readonly
67
+ * @api
68
+ */
69
+ get olMap() {
70
+ return this._olMap;
71
+ }
72
+
73
+ /**
74
+ * @param {import("ol/MapBrowserEvent").default} olEvent
75
+ * @param {PointerEventType} pointerEvent
76
+ * @private
77
+ */
78
+ _raisePointerInteraction(olEvent, pointerEvent) {
79
+ const pointerMap = {
80
+ '-1': PointerKeyType.ALL,
81
+ 0: PointerKeyType.LEFT,
82
+ 1: PointerKeyType.MIDDLE,
83
+ 2: PointerKeyType.RIGHT,
84
+ };
85
+ let key = olEvent.originalEvent.shiftKey ? ModificationKeyType.SHIFT : ModificationKeyType.NONE;
86
+ key = olEvent.originalEvent.ctrlKey ? ModificationKeyType.CTRL : key;
87
+ key = olEvent.originalEvent.altKey ? ModificationKeyType.ALT : key;
88
+ if (key !== ModificationKeyType.NONE) {
89
+ olEvent.preventDefault();
90
+ }
91
+ olEvent.originalEvent.preventDefault();
92
+ const position = [olEvent.coordinate[0], olEvent.coordinate[1], 0];
93
+ this.pointerInteractionEvent.raiseEvent({
94
+ map: this,
95
+ position,
96
+ positionOrPixel: position,
97
+ windowPosition: Cartesian2.fromArray(olEvent.pixel, 0, new Cartesian2()),
98
+ key,
99
+ pointer: pointerMap[olEvent.originalEvent.button || 0],
100
+ pointerEvent,
101
+ });
102
+ }
103
+
104
+ /**
105
+ * @inheritDoc
106
+ * @param {string|HTMLElement|null} target
107
+ */
108
+ setTarget(target) {
109
+ super.setTarget(target);
110
+ if (this._olMap && this.target) {
111
+ this._olMap.updateSize();
112
+ }
113
+ }
114
+
115
+ /**
116
+ * @inheritDoc
117
+ * @returns {Promise<void>}
118
+ */
119
+ async initialize() {
120
+ if (!this._olMap) {
121
+ this._olMap = new OLMap({
122
+ layers: [],
123
+ controls: [],
124
+ interactions: defaultInteractions({
125
+ altShiftDragRotate: false,
126
+ pinchRotate: false,
127
+ shiftDragZoom: false,
128
+ doubleClickZoom: false,
129
+ }),
130
+ target: this.mapElement,
131
+ });
132
+
133
+ // @ts-ignore
134
+ const pointerDownListener = /** @type {import("ol/events").EventsKey} */ (this.olMap.on('pointerdown', (event) => {
135
+ this._raisePointerInteraction(
136
+ /** @type {import("ol/MapBrowserEvent").default} */ (event),
137
+ PointerEventType.DOWN,
138
+ );
139
+ }));
140
+ // @ts-ignore
141
+ const pointerUpListener = /** @type {import("ol/events").EventsKey} */ (this.olMap.on('pointerup', (event) => {
142
+ this._raisePointerInteraction(
143
+ /** @type {import("ol/MapBrowserEvent").default} */ (event),
144
+ PointerEventType.UP,
145
+ );
146
+ }));
147
+ // @ts-ignore
148
+ const pointerMoveListener = /** @type {import("ol/events").EventsKey} */ (this.olMap.on('pointermove', (event) => {
149
+ this._raisePointerInteraction(event, PointerEventType.MOVE);
150
+ }));
151
+ this._olListeners.push(pointerDownListener, pointerUpListener, pointerMoveListener);
152
+ }
153
+ }
154
+
155
+ /**
156
+ * @inheritDoc
157
+ * @returns {Promise<void>}
158
+ */
159
+ async activate() {
160
+ await super.activate();
161
+ if (this.active) {
162
+ this._olMap.updateSize();
163
+ }
164
+ }
165
+
166
+ /**
167
+ * @inheritDoc
168
+ * @param {import("@vcmap/core").Layer} layer
169
+ */
170
+ indexChanged(layer) {
171
+ const viz = this.getVisualizationsForLayer(layer);
172
+ if (viz) {
173
+ viz.forEach(/** @param {import("ol/layer/Layer").default<import("ol/source").Source>} olLayer */ (olLayer) => {
174
+ const layers = /** @type {import("ol/Collection").default<import("ol/layer/Layer").default<import("ol/source").Source>>} */
175
+ (this._olMap.getLayers());
176
+ layers.remove(olLayer);
177
+ ensureLayerInCollection(layers, olLayer, this.layerCollection);
178
+ });
179
+ }
180
+ }
181
+
182
+ /**
183
+ * Internal API for registering representations.
184
+ * @param {import("ol/layer/Layer").default<import("ol/source").Source>} olLayer
185
+ */
186
+ addOLLayer(olLayer) {
187
+ if (this.validateVisualization(olLayer)) {
188
+ this.addVisualization(olLayer);
189
+ ensureLayerInCollection(
190
+ /** @type {import("ol/Collection").default<import("ol/layer/Layer").default<import("ol/source").Source>>} */
191
+ (this._olMap.getLayers()),
192
+ olLayer,
193
+ this.layerCollection,
194
+ );
195
+ }
196
+ }
197
+
198
+ /**
199
+ * Internal API for deregistering representations.
200
+ * @param {import("ol/layer/Layer").default<import("ol/source").Source>} olLayer
201
+ */
202
+ removeOLLayer(olLayer) {
203
+ this.removeVisualization(olLayer);
204
+ this._olMap.getLayers().remove(olLayer);
205
+ }
206
+
207
+ /**
208
+ * @param {boolean} prevent
209
+ * @inheritDoc
210
+ */
211
+ disableMovement(prevent) {
212
+ super.disableMovement(prevent);
213
+ if (this._olMap) {
214
+ this._olMap.getInteractions().forEach((i) => { i.setActive(!prevent); });
215
+ }
216
+ }
217
+
218
+ /**
219
+ * @inheritDoc
220
+ * @param {import("ol/coordinate").Coordinate} coordinate
221
+ * @returns {number}
222
+ * @api
223
+ */
224
+ // eslint-disable-next-line no-unused-vars
225
+ getCurrentResolution(coordinate) {
226
+ const view = this.olMap ? this.olMap.getView() : null;
227
+ if (view) {
228
+ return view.getResolution();
229
+ }
230
+ return 1;
231
+ }
232
+
233
+ /**
234
+ * @inheritDoc
235
+ * @api
236
+ */
237
+ requestRender() {
238
+ if (this._olMap) {
239
+ this._olMap.render();
240
+ }
241
+ }
242
+
243
+ /**
244
+ * @inheritDoc
245
+ * @api
246
+ */
247
+ destroy() {
248
+ if (this._olMap) {
249
+ this._olMap.setTarget(null);
250
+ }
251
+ unByKey(this._olListeners);
252
+ super.destroy();
253
+ }
254
+ }
255
+
256
+ VcsClassRegistry.registerClass(BaseOLMap.className, BaseOLMap);
257
+ export default BaseOLMap;
@@ -0,0 +1,219 @@
1
+ import { Cartographic, Ellipsoid, Math as CesiumMath } from '@vcmap/cesium';
2
+ import { checkMaybe } from '@vcsuite/check';
3
+ import { parseInteger, parseNumber, parseEnumValue } from '@vcsuite/parsers';
4
+ import {
5
+ sampleCesiumTerrain,
6
+ sampleCesiumTerrainMostDetailed,
7
+ getTerrainProviderForUrl,
8
+ isTerrainTileAvailable,
9
+ } from '../layer/terrainHelpers.js';
10
+
11
+ /**
12
+ * @typedef {Object} CameraLimiterOptions
13
+ * @property {string|undefined} terrainUrl - required if mode is distance.
14
+ * @property {string|undefined} [mode="height"] - either "height" or "distance".
15
+ * @property {number} [limit=200]
16
+ * @property {number|null} [level=12] - the level at which to request terrain data. setting this to null will request most detailed
17
+ * @api
18
+ */
19
+
20
+ /**
21
+ * Enumeration of camera limiter modes.
22
+ * @enum {string}
23
+ * @property {string} HEIGHT
24
+ * @property {string} DISTANCE
25
+ */
26
+ export const Mode = {
27
+ HEIGHT: 'height',
28
+ DISTANCE: 'distance',
29
+ };
30
+
31
+ /**
32
+ * Can limit a Cesium.Cameras position based on absolute height or distance to a given terrain
33
+ * @class
34
+ * @export
35
+ * @api
36
+ */
37
+ class CameraLimiter {
38
+ static get className() { return 'vcs.vcm.maps.CameraLimiter'; }
39
+
40
+ /**
41
+ * @returns {CameraLimiterOptions}
42
+ */
43
+ static getDefaultOptions() {
44
+ return {
45
+ mode: Mode.HEIGHT,
46
+ terrainUrl: undefined,
47
+ limit: 200,
48
+ level: 12,
49
+ };
50
+ }
51
+
52
+ /**
53
+ * @param {CameraLimiterOptions} options
54
+ */
55
+ constructor(options) {
56
+ const defaultOptions = CameraLimiter.getDefaultOptions();
57
+ /**
58
+ * The mode to use. When using DISTANCE mode, be sure to have a terrainProvider set.
59
+ * @type {Mode}
60
+ * @api
61
+ */
62
+ this.mode = parseEnumValue(options.mode, Mode, defaultOptions.mode);
63
+ /**
64
+ * @type {string|null}
65
+ * @private
66
+ */
67
+ this._terrainUrl = options.terrainUrl || defaultOptions.terrainUrl;
68
+ /**
69
+ * @type {import("@vcmap/cesium").CesiumTerrainProvider|null}
70
+ * @private
71
+ */
72
+ this._terrainProvider = this._terrainUrl ? getTerrainProviderForUrl({ url: this._terrainUrl }) : null;
73
+ /**
74
+ * The minimum height/distance to the terrain the camera must maintain
75
+ * @type {number}
76
+ * @api
77
+ */
78
+ this.limit = parseNumber(options.limit, defaultOptions.limit);
79
+ /**
80
+ * The level to request terrain data at
81
+ * @type {number|null}
82
+ * @api
83
+ */
84
+ this.level = options.level === null ? null : parseInteger(options.level, defaultOptions.level);
85
+ /**
86
+ * last checked camera position
87
+ * @type {import("@vcmap/cesium").Cartographic}
88
+ */
89
+ this.lastCheckedPosition = new Cartographic();
90
+ /**
91
+ * last updated terrain height
92
+ * @type {number|null}
93
+ * @private
94
+ */
95
+ this._terrainHeight = null;
96
+ /**
97
+ * @type {boolean}
98
+ * @private
99
+ */
100
+ this._updatingTerrainHeight = false;
101
+ }
102
+
103
+ /**
104
+ * The url of the terrain to use. Required for mode DISTANCE
105
+ * @type {string|null}
106
+ * @api
107
+ */
108
+ get terrainUrl() {
109
+ return this._terrainUrl;
110
+ }
111
+
112
+ /**
113
+ * @param {string|null} url
114
+ */
115
+ set terrainUrl(url) {
116
+ checkMaybe(url, String);
117
+
118
+ if (this._terrainUrl !== url) {
119
+ this._terrainUrl = url;
120
+ this._terrainProvider = this._terrainUrl ? getTerrainProviderForUrl({ url: this._terrainUrl }) : null;
121
+ }
122
+ }
123
+
124
+ /**
125
+ * @param {import("@vcmap/cesium").Cartographic} cameraCartographic
126
+ * @returns {Promise<Array<import("@vcmap/cesium").Cartographic>>}
127
+ * @private
128
+ */
129
+ _limitWithLevel(cameraCartographic) {
130
+ if (isTerrainTileAvailable(this._terrainProvider, this.level, cameraCartographic)) {
131
+ return sampleCesiumTerrain(this._terrainProvider, this.level, [cameraCartographic]);
132
+ }
133
+ return this._limitMostDetailed(cameraCartographic);
134
+ }
135
+
136
+ /**
137
+ * @param {import("@vcmap/cesium").Cartographic} cameraCartographic
138
+ * @returns {Promise<Array<import("@vcmap/cesium").Cartographic>>}
139
+ * @private
140
+ */
141
+ _limitMostDetailed(cameraCartographic) {
142
+ return sampleCesiumTerrainMostDetailed(this._terrainProvider, [cameraCartographic]);
143
+ }
144
+
145
+ /**
146
+ * @param {import("@vcmap/cesium").Cartographic} cameraCartographic
147
+ * @returns {Promise<void>}
148
+ * @private
149
+ */
150
+ async _updateTerrainHeight(cameraCartographic) {
151
+ if (!this._updatingTerrainHeight &&
152
+ !cameraCartographic.equalsEpsilon(this.lastCheckedPosition, CesiumMath.EPSILON5)) {
153
+ this._updatingTerrainHeight = true;
154
+ const [updatedPosition] = this.level != null ?
155
+ await this._limitWithLevel(cameraCartographic.clone()) :
156
+ await this._limitMostDetailed(cameraCartographic.clone());
157
+ this._terrainHeight = updatedPosition.height;
158
+ this.lastCheckedPosition = cameraCartographic;
159
+ this._updatingTerrainHeight = false;
160
+ }
161
+ }
162
+
163
+ /**
164
+ * Limits the given camera based on this limiters specs.
165
+ * @param {import("@vcmap/cesium").Camera} camera
166
+ * @api
167
+ * @returns {Promise<void>}
168
+ */
169
+ limitCamera(camera) {
170
+ let promise = Promise.resolve();
171
+ const cameraCartographic = Cartographic.fromCartesian(camera.position);
172
+ if (cameraCartographic) {
173
+ if (this.mode === Mode.DISTANCE && this._terrainProvider) {
174
+ promise = this._updateTerrainHeight(cameraCartographic);
175
+ if (this._terrainHeight && (cameraCartographic.height - this._terrainHeight) < this.limit) {
176
+ const newHeight = this._terrainHeight + this.limit;
177
+ Cartographic.toCartesian(
178
+ new Cartographic(cameraCartographic.longitude, cameraCartographic.latitude, newHeight),
179
+ Ellipsoid.WGS84,
180
+ camera.position,
181
+ );
182
+ }
183
+ } else if (cameraCartographic.height < this.limit) {
184
+ Cartographic.toCartesian(
185
+ new Cartographic(cameraCartographic.longitude, cameraCartographic.latitude, this.limit),
186
+ Ellipsoid.WGS84,
187
+ camera.position,
188
+ );
189
+ }
190
+ }
191
+ return promise;
192
+ }
193
+
194
+ /**
195
+ * @returns {CameraLimiterOptions}
196
+ */
197
+ getConfigObject() {
198
+ const config = {};
199
+ const defaultOptions = CameraLimiter.getDefaultOptions();
200
+ if (this.terrainUrl) {
201
+ config.terrainUrl = this.terrainUrl;
202
+ }
203
+
204
+ if (this.limit !== defaultOptions.limit) {
205
+ config.limit = this.limit;
206
+ }
207
+
208
+ if (this.mode !== defaultOptions.mode) {
209
+ config.mode = this.mode;
210
+ }
211
+
212
+ if (this.level !== defaultOptions.level) {
213
+ config.level = this.level;
214
+ }
215
+ return config;
216
+ }
217
+ }
218
+
219
+ export default CameraLimiter;