@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,469 @@
1
+ import VectorSource from 'ol/source/Vector.js';
2
+ import OLVectorLayer from 'ol/layer/Vector.js';
3
+ import { unByKey } from 'ol/Observable.js';
4
+ import Feature from 'ol/Feature.js';
5
+
6
+ import { mercatorProjection } from '../../util/projection.js';
7
+ import { mercatorGeometryToImageGeometry, imageGeometryToMercatorGeometry, getPolygonizedGeometry, setNewGeometry } from './obliqueHelpers.js';
8
+ import { getGlobalHider } from '../globalHider.js';
9
+ import {
10
+ actuallyIsCircle,
11
+ alreadyTransformedToImage,
12
+ doNotTransform,
13
+ obliqueGeometry,
14
+ originalFeatureSymbol,
15
+ } from '../vectorSymbols.js';
16
+ import LayerOblique from './layerOblique.js';
17
+ import { synchronizeFeatureVisibilityWithSource } from '../vectorHelpers.js';
18
+
19
+ /**
20
+ * represents a specific vector layer for oblique.
21
+ * @class
22
+ * @export
23
+ * @extends {LayerOblique}
24
+ * @implements {FeatureLayerImplementation}
25
+ */
26
+ class VectorOblique extends LayerOblique {
27
+ static get className() { return 'vcs.vcm.layer.oblique.VectorOblique'; }
28
+
29
+ /**
30
+ * @param {import("@vcmap/core").Oblique} map
31
+ * @param {VectorImplementationOptions} options
32
+ */
33
+ constructor(map, options) {
34
+ super(map, options);
35
+
36
+ /** @type {import("ol/source").Vector<import("ol/geom/Geometry").default>} */
37
+ this.obliqueSource = new VectorSource({});
38
+
39
+ /**
40
+ * @type {Object<string, Object<string, import("ol/events").EventsKey>>}
41
+ * @private
42
+ */
43
+ this._featureListeners = {};
44
+ /**
45
+ * @type {Array<import("ol/events").EventsKey>}
46
+ * @private
47
+ */
48
+ this._sourceListener = [];
49
+ /**
50
+ * The extent of the current image for which features where fetched
51
+ * @type {import("ol/extent").Extent|null}
52
+ */
53
+ this.currentExtent = null;
54
+ /**
55
+ * The image name for which the current features where fetched
56
+ * @type {string|null}
57
+ */
58
+ this.fetchedFeaturesForImageName = null;
59
+
60
+ /**
61
+ * @type {Object<string, (number|boolean)>}
62
+ * @private
63
+ */
64
+ this._updatingMercator = {};
65
+ /**
66
+ * @type {Object<string, (number|boolean|null)>}
67
+ * @private
68
+ */
69
+ this._updatingOblique = {};
70
+ /**
71
+ * @type {Array<Function>}
72
+ * @private
73
+ */
74
+ this._featureVisibilityListeners = [];
75
+ /**
76
+ * @type {import("@vcmap/core").GlobalHider}
77
+ */
78
+ this.globalHider = getGlobalHider();
79
+ /**
80
+ * @type {import("ol/source").Vector<import("ol/geom/Geometry").default>}
81
+ */
82
+ this.source = options.source;
83
+ /**
84
+ * @type {import("@vcmap/core").StyleItem}
85
+ */
86
+ this.style = options.style;
87
+ /**
88
+ * @type {import("@vcmap/core").FeatureVisibility}
89
+ */
90
+ this.featureVisibility = options.featureVisibility;
91
+ /**
92
+ * @type {import("ol/layer").Vector<import("ol/source").Vector<import("ol/geom/Geometry").default>>|null}
93
+ */
94
+ this.olLayer = null;
95
+ }
96
+
97
+ /**
98
+ * @inheritDoc
99
+ * @returns {import("ol/layer").Vector<import("ol/source").Vector<import("ol/geom/Geometry").default>>}
100
+ */
101
+ getOLLayer() {
102
+ return new OLVectorLayer({
103
+ visible: false,
104
+ source: this.obliqueSource,
105
+ style: this.style.style,
106
+ });
107
+ }
108
+
109
+ /**
110
+ * @param {import("@vcmap/core").StyleItem} style
111
+ * @param {boolean=} silent
112
+ */
113
+ // eslint-disable-next-line no-unused-vars
114
+ updateStyle(style, silent) {
115
+ this.style = style;
116
+ if (this.initialized) {
117
+ this.olLayer.setStyle(this.style.style);
118
+ }
119
+ }
120
+
121
+ /**
122
+ * clears the current image and fetches features for the next
123
+ * @private
124
+ */
125
+ _onObliqueImageChanged() {
126
+ this._clearCurrentImage();
127
+ this._fetchFeaturesInView();
128
+ }
129
+
130
+ /**
131
+ * @param {import("ol").Feature<import("ol/geom/Geometry").default>} feature
132
+ * @returns {boolean}
133
+ * @private
134
+ */
135
+ _featureInExtent(feature) {
136
+ if (this.currentExtent) {
137
+ const geometry = feature.getGeometry();
138
+ if (geometry) {
139
+ return geometry[alreadyTransformedToImage] ||
140
+ geometry.intersectsExtent(this.currentExtent);
141
+ }
142
+ }
143
+ return false;
144
+ }
145
+
146
+ /**
147
+ * @protected
148
+ */
149
+ _addSourceListeners() {
150
+ this._sourceListener.push(/** @type {import("ol/events").EventsKey} */ (this.source.on('addfeature', /** @param {import("ol/source/Vector").VectorSourceEvent} event */ (event) => {
151
+ const { feature } = event;
152
+ if (this._featureInExtent(feature)) {
153
+ this.addFeature(event.feature);
154
+ }
155
+ })));
156
+
157
+ this._sourceListener.push(/** @type {import("ol/events").EventsKey} */ (this.source.on('removefeature', /** @param {import("ol/source/Vector").VectorSourceEvent} event */ (event) => {
158
+ this.removeFeature(event.feature);
159
+ })));
160
+
161
+ this._sourceListener.push(/** @type {import("ol/events").EventsKey} */ (this.source.on('changefeature', /** @param {import("ol/source/Vector").VectorSourceEvent} event */ (event) => {
162
+ const { feature } = event;
163
+ const newFeatureId = feature.getId();
164
+ if (!this._featureListeners[newFeatureId] && this._featureInExtent(feature)) {
165
+ this.addFeature(feature);
166
+ }
167
+ })));
168
+ }
169
+
170
+ /**
171
+ * @inheritDoc
172
+ * @returns {Promise<void>}
173
+ */
174
+ async activate() {
175
+ if (!this.active) {
176
+ await super.activate();
177
+ if (this.active) {
178
+ this.olLayer.setVisible(true);
179
+ if (this._featureVisibilityListeners.length === 0) {
180
+ this._featureVisibilityListeners =
181
+ synchronizeFeatureVisibilityWithSource(this.featureVisibility, this.source, this.globalHider);
182
+ }
183
+ this._addSourceListeners();
184
+ this._imageChangedListener = this.map.imageChanged.addEventListener(this._onObliqueImageChanged.bind(this));
185
+ await this._fetchFeaturesInView();
186
+ }
187
+ }
188
+ }
189
+
190
+ /**
191
+ * @param {import("ol").Feature<import("ol/geom/Geometry").default>} originalFeature
192
+ * @returns {Promise<void>}
193
+ * @private
194
+ */
195
+ addFeature(originalFeature) {
196
+ if (!this.active) {
197
+ this.fetchedFeaturesForImageName = null;
198
+ }
199
+ if (
200
+ this.active &&
201
+ this.currentExtent
202
+ ) {
203
+ const id = originalFeature.getId();
204
+ const originalGeometry = originalFeature.getGeometry();
205
+ if (originalFeature[doNotTransform]) {
206
+ if (
207
+ originalGeometry &&
208
+ !this.obliqueSource.getFeatureById(id)
209
+ ) {
210
+ this.obliqueSource.addFeature(originalFeature);
211
+ }
212
+ return Promise.resolve();
213
+ }
214
+
215
+ if (this.obliqueSource.getFeatureById(id)) {
216
+ return Promise.resolve();
217
+ }
218
+ const obliqueFeature = new Feature({});
219
+ obliqueFeature.setId(id);
220
+ obliqueFeature[originalFeatureSymbol] = originalFeature;
221
+ setNewGeometry(originalFeature, obliqueFeature);
222
+ obliqueFeature.setStyle(originalFeature.getStyle());
223
+
224
+ this._setFeatureListeners(originalFeature, obliqueFeature);
225
+
226
+ return this._convertToOblique(originalFeature, obliqueFeature)
227
+ .then(() => {
228
+ this.obliqueSource.addFeature(obliqueFeature);
229
+ });
230
+ }
231
+ return Promise.resolve();
232
+ }
233
+
234
+ /**
235
+ * @param {Object<string, import("ol/events").EventsKey>} listeners
236
+ * @param {import("ol").Feature<import("ol/geom/Geometry").default>} originalFeature
237
+ * @param {import("ol").Feature<import("ol/geom/Geometry").default>} obliqueFeature
238
+ * @private
239
+ */
240
+ _originalGeometryChanged(listeners, originalFeature, obliqueFeature) {
241
+ unByKey(listeners.originalGeometryChanged);
242
+ unByKey(listeners.obliqueGeometryChanged);
243
+ setNewGeometry(originalFeature, obliqueFeature);
244
+ this.updateObliqueGeometry(originalFeature, obliqueFeature);
245
+ listeners.originalGeometryChanged = /** @type {import("ol/events").EventsKey} */ (originalFeature
246
+ .getGeometry().on('change', this.updateObliqueGeometry.bind(this, originalFeature, obliqueFeature)));
247
+ listeners.obliqueGeometryChanged = /** @type {import("ol/events").EventsKey} */ (obliqueFeature
248
+ .getGeometry().on('change', this.updateMercatorGeometry.bind(this, originalFeature, obliqueFeature)));
249
+ }
250
+
251
+ /**
252
+ * @param {import("ol").Feature<import("ol/geom/Geometry").default>} originalFeature
253
+ * @param {import("ol").Feature<import("ol/geom/Geometry").default>} obliqueFeature
254
+ * @private
255
+ */
256
+ _setFeatureListeners(originalFeature, obliqueFeature) {
257
+ const featureId = obliqueFeature.getId();
258
+ const listeners = {
259
+ originalFeatureGeometryChanged: /** @type {import("ol/events").EventsKey} */ (originalFeature.on('change:geometry', () => {
260
+ const originalGeometry = originalFeature.getGeometry();
261
+ if (originalGeometry[actuallyIsCircle]) {
262
+ unByKey(listeners.originalGeometryChanged);
263
+ listeners.originalGeometryChanged = /** @type {import("ol/events").EventsKey} */ (originalFeature
264
+ .getGeometry().on('change', () => {
265
+ if (this._updatingMercator[featureId]) {
266
+ return;
267
+ }
268
+ delete originalGeometry[actuallyIsCircle];
269
+ this._originalGeometryChanged(listeners, originalFeature, obliqueFeature);
270
+ }));
271
+ return;
272
+ }
273
+ this._originalGeometryChanged(listeners, originalFeature, obliqueFeature);
274
+ })),
275
+ originalFeatureChanged: /** @type {import("ol/events").EventsKey} */ (originalFeature
276
+ .on('change', () => { obliqueFeature.setStyle(originalFeature.getStyle()); })),
277
+ originalGeometryChanged: /** @type {import("ol/events").EventsKey} */ (originalFeature
278
+ .getGeometry().on('change', this.updateObliqueGeometry.bind(this, originalFeature, obliqueFeature))),
279
+ obliqueGeometryChanged: /** @type {import("ol/events").EventsKey} */ (obliqueFeature
280
+ .getGeometry().on('change', this.updateMercatorGeometry.bind(this, originalFeature, obliqueFeature))),
281
+ };
282
+ this._featureListeners[featureId] = listeners;
283
+ }
284
+
285
+ /**
286
+ * @param {import("ol").Feature<import("ol/geom/Geometry").default>} originalFeature
287
+ * @param {import("ol").Feature<import("ol/geom/Geometry").default>} obliqueFeature
288
+ * @returns {Promise<void>}
289
+ * @private
290
+ */
291
+ async _convertToOblique(originalFeature, obliqueFeature) {
292
+ const id = originalFeature.getId();
293
+ const vectorGeometry = originalFeature.getGeometry();
294
+ const imageGeometry = obliqueFeature.getGeometry();
295
+ this._updatingOblique[id] = true;
296
+ if (!vectorGeometry[alreadyTransformedToImage]) {
297
+ await mercatorGeometryToImageGeometry(vectorGeometry, imageGeometry, this.map.currentImage);
298
+ } else {
299
+ obliqueFeature.getGeometry().setCoordinates(vectorGeometry.getCoordinates());
300
+ }
301
+ this._updatingOblique[id] = null;
302
+ }
303
+
304
+ /**
305
+ * @param {import("ol").Feature<import("ol/geom/Geometry").default>} originalFeature
306
+ * @param {import("ol").Feature<import("ol/geom/Geometry").default>} obliqueFeature
307
+ */
308
+ updateObliqueGeometry(originalFeature, obliqueFeature) {
309
+ const id = originalFeature.getId();
310
+ if (this._updatingMercator[id]) {
311
+ return;
312
+ }
313
+ if (this._updatingOblique[id] != null) {
314
+ clearTimeout(/** @type {number} */ (this._updatingOblique[id]));
315
+ }
316
+ this._updatingOblique[id] = setTimeout(() => {
317
+ this._convertToOblique(originalFeature, obliqueFeature);
318
+ }, 200);
319
+ }
320
+
321
+ /**
322
+ * @param {import("ol").Feature<import("ol/geom/Geometry").default>} originalFeature
323
+ * @param {import("ol").Feature<import("ol/geom/Geometry").default>} obliqueFeature
324
+ */
325
+ updateMercatorGeometry(originalFeature, obliqueFeature) {
326
+ const id = originalFeature.getId();
327
+ if (this._updatingOblique[id]) {
328
+ return;
329
+ }
330
+ if (this._updatingMercator[id] != null) {
331
+ clearTimeout(/** @type {number} */ (this._updatingMercator[id]));
332
+ }
333
+ const imageName = this.fetchedFeaturesForImageName;
334
+ this._updatingMercator[id] = setTimeout(async () => {
335
+ const originalGeometry = getPolygonizedGeometry(originalFeature, false);
336
+ if (originalGeometry[actuallyIsCircle]) {
337
+ originalFeature.setGeometry(originalGeometry);
338
+ }
339
+ const imageGeometry = getPolygonizedGeometry(obliqueFeature, true);
340
+ this._updatingMercator[id] = true;
341
+ await imageGeometryToMercatorGeometry(
342
+ imageGeometry,
343
+ originalGeometry,
344
+ this.map.collection.getImageByName(imageName),
345
+ );
346
+ this._updatingMercator[id] = null;
347
+ }, 200);
348
+ }
349
+
350
+ /**
351
+ * Synchronizes image Features if the geometry has been changed.
352
+ * also clears source and featureListeners
353
+ */
354
+ _clearCurrentImage() {
355
+ Object.values(this._featureListeners)
356
+ .forEach((listeners) => {
357
+ unByKey(Object.values(listeners));
358
+ });
359
+ this._featureListeners = {};
360
+ this._updatingOblique = {};
361
+ this._updatingMercator = {};
362
+ this.obliqueSource.getFeatures().forEach((f) => {
363
+ const original = f[originalFeatureSymbol];
364
+ if (original) {
365
+ delete original[obliqueGeometry];
366
+ delete original.getGeometry()[alreadyTransformedToImage];
367
+ }
368
+ });
369
+ this.obliqueSource.clear(true);
370
+ this.fetchedFeaturesForImageName = null;
371
+ }
372
+
373
+ /**
374
+ * Fetches the features within the extent of the current image
375
+ * @private
376
+ */
377
+ _fetchFeaturesInView() {
378
+ if (
379
+ this.active &&
380
+ this.map.currentImage &&
381
+ this.fetchedFeaturesForImageName !== this.map.currentImage.name
382
+ ) {
383
+ this.currentExtent = this.map.getExtentOfCurrentImage()
384
+ .getCoordinatesInProjection(mercatorProjection);
385
+ this.source.forEachFeatureInExtent(this.currentExtent, (feature) => {
386
+ this.addFeature(feature);
387
+ });
388
+ this.source.forEachFeature((feature) => {
389
+ if (feature.getGeometry()[alreadyTransformedToImage]) {
390
+ this.addFeature(feature);
391
+ }
392
+ });
393
+ this.fetchedFeaturesForImageName = this.map.currentImage.name;
394
+ }
395
+ }
396
+
397
+ /**
398
+ * @param {import("ol").Feature<import("ol/geom/Geometry").default>} feature
399
+ * @private
400
+ */
401
+ removeFeature(feature) {
402
+ const feat = this.obliqueSource.getFeatureById(feature.getId());
403
+ if (feat) {
404
+ const id = /** @type {string} */ (feat.getId());
405
+ const listeners = this._featureListeners[id];
406
+ if (listeners) {
407
+ unByKey(Object.values(listeners));
408
+ delete this._featureListeners[id];
409
+ }
410
+ this.obliqueSource.removeFeature(feat);
411
+ }
412
+ }
413
+
414
+ /**
415
+ * @inheritDoc
416
+ */
417
+ deactivate() {
418
+ super.deactivate();
419
+ if (this.olLayer) {
420
+ this.olLayer.setVisible(false);
421
+ }
422
+
423
+ this._featureVisibilityListeners.forEach((cb) => { cb(); });
424
+ this._featureVisibilityListeners = [];
425
+
426
+ unByKey(this._sourceListener);
427
+ this._sourceListener = [];
428
+
429
+ if (this._imageChangedListener) {
430
+ this._imageChangedListener();
431
+ this._imageChangedListener = null;
432
+ }
433
+
434
+ this._clearCurrentImage();
435
+ }
436
+
437
+ /**
438
+ * @inheritDoc
439
+ */
440
+ destroy() {
441
+ if (this.olLayer) {
442
+ this.map.removeOLLayer(this.olLayer);
443
+ }
444
+ this.olLayer = null;
445
+
446
+ unByKey(this._sourceListener);
447
+ this._sourceListener = [];
448
+
449
+ if (this._imageChangedListener) {
450
+ this._imageChangedListener();
451
+ this._imageChangedListener = null;
452
+ }
453
+ this.obliqueSource.clear(true);
454
+ Object.values(this._updatingOblique).forEach((timer) => {
455
+ if (timer != null) {
456
+ clearTimeout(/** @type {number} */ (timer));
457
+ }
458
+ });
459
+ Object.values(this._updatingMercator).forEach((timer) => {
460
+ if (timer != null) {
461
+ clearTimeout(/** @type {number} */ (timer));
462
+ }
463
+ });
464
+ this._clearCurrentImage();
465
+ super.destroy();
466
+ }
467
+ }
468
+
469
+ export default VectorOblique;
@@ -0,0 +1,194 @@
1
+ import { ImagerySplitDirection } from '@vcmap/cesium';
2
+
3
+ import { parseNumberRange, parseInteger } from '@vcsuite/parsers';
4
+ import Layer from './layer.js';
5
+ import Openlayers from '../maps/openlayers.js';
6
+ import CesiumMap from '../maps/cesium.js';
7
+ import OpenStreetMapOpenlayers from './openlayers/openStreetMapOpenlayers.js';
8
+ import OpenStreetMapCesium from './cesium/openStreetMapCesium.js';
9
+ import VcsEvent from '../event/vcsEvent.js';
10
+ import { VcsClassRegistry } from '../classRegistry.js';
11
+
12
+ /**
13
+ * @typedef {LayerOptions} OpenStreetMapOptions
14
+ * @property {string|undefined} splitDirection - either 'left' or 'right', if omitted none is applied
15
+ * @property {number} [opacity=1.0] - opacity between 0 and 1
16
+ * @property {number} [maxLevel=19] - max level to load tiles at
17
+ * @api
18
+ */
19
+
20
+ /**
21
+ * OpenStreetMap Layer
22
+ * @class
23
+ * @export
24
+ * @extends {Layer}
25
+ * @api stable
26
+ * @implements {SplitLayer}
27
+ */
28
+ class OpenStreetMap extends Layer {
29
+ static get className() { return 'vcs.vcm.layer.OpenStreetMap'; }
30
+
31
+ /**
32
+ * @returns {OpenStreetMapOptions}
33
+ */
34
+ static getDefaultOptions() {
35
+ return {
36
+ ...Layer.getDefaultOptions,
37
+ splitDirection: undefined,
38
+ opacity: 1,
39
+ maxLevel: 19,
40
+ };
41
+ }
42
+
43
+ /**
44
+ * @param {OpenStreetMapOptions} options
45
+ */
46
+ constructor(options) {
47
+ super(options);
48
+ const defaultOptions = OpenStreetMap.getDefaultOptions();
49
+ /**
50
+ * @type {import("@vcmap/cesium").ImagerySplitDirection}
51
+ * @private
52
+ */
53
+ this._splitDirection = ImagerySplitDirection.NONE;
54
+
55
+ if (options.splitDirection) {
56
+ this._splitDirection = options.splitDirection === 'left' ?
57
+ ImagerySplitDirection.LEFT :
58
+ ImagerySplitDirection.RIGHT;
59
+ }
60
+
61
+ this._supportedMaps = [
62
+ CesiumMap.className,
63
+ Openlayers.className,
64
+ ];
65
+
66
+ /**
67
+ * @type {number}
68
+ * @private
69
+ */
70
+ this._opacity = parseNumberRange(options.opacity, defaultOptions.opacity, 0.0, 1.0);
71
+
72
+ /**
73
+ * raised if the split direction changes, is passed the split direction as its only argument
74
+ * @type {VcsEvent<import("@vcmap/cesium").ImagerySplitDirection>}
75
+ * @api
76
+ */
77
+ this.splitDirectionChanged = new VcsEvent();
78
+
79
+ /**
80
+ * The maximum level to load. Changing requires a redraw to take effect.
81
+ * @type {number}
82
+ * @api
83
+ */
84
+ this.maxLevel = parseInteger(options.maxLevel, defaultOptions.maxLevel);
85
+ }
86
+
87
+ /**
88
+ * @api
89
+ * @type {import("@vcmap/cesium").ImagerySplitDirection}
90
+ */
91
+ get splitDirection() { return this._splitDirection; }
92
+
93
+ /**
94
+ * @param {import("@vcmap/cesium").ImagerySplitDirection} direction
95
+ */
96
+ set splitDirection(direction) {
97
+ if (direction !== this._splitDirection) {
98
+ this._splitDirection = direction;
99
+ this.getImplementations().forEach((impl) => {
100
+ /** @type {OpenStreetMapCesium|OpenStreetMapOpenlayers} */
101
+ (impl).updateSplitDirection(this._splitDirection);
102
+ });
103
+ this.splitDirectionChanged.raiseEvent(this._splitDirection);
104
+ }
105
+ }
106
+
107
+ /**
108
+ * The opacity between 0 (fully transparent) and 1 (fully opaque)
109
+ * @api
110
+ * @type {number}
111
+ */
112
+ get opacity() { return this._opacity; }
113
+
114
+ /**
115
+ * @param {number} opacity
116
+ */
117
+ set opacity(opacity) {
118
+ const parsedValue = parseNumberRange(opacity, this._opacity, 0, 1);
119
+ if (this._opacity !== parsedValue) {
120
+ this._opacity = parsedValue;
121
+ this.getImplementations().forEach((impl) => {
122
+ /** @type {OpenStreetMapCesium|OpenStreetMapOpenlayers} */
123
+ (impl).updateOpacity(parsedValue);
124
+ });
125
+ }
126
+ }
127
+
128
+ /**
129
+ * @inheritDoc
130
+ * @returns {RasterLayerImplementationOptions}
131
+ */
132
+ getImplementationOptions() {
133
+ return {
134
+ ...super.getImplementationOptions(),
135
+ opacity: this.opacity,
136
+ splitDirection: this.splitDirection,
137
+ minLevel: 0,
138
+ maxLevel: this.maxLevel,
139
+ tilingSchema: '',
140
+ };
141
+ }
142
+
143
+ /**
144
+ * @inheritDoc
145
+ * @param {import("@vcmap/core").VcsMap} map
146
+ * @returns {Array<OpenStreetMapOpenlayers|OpenStreetMapCesium>}
147
+ */
148
+ createImplementationsForMap(map) {
149
+ if (map instanceof Openlayers) {
150
+ return [new OpenStreetMapOpenlayers(map, this.getImplementationOptions())];
151
+ }
152
+
153
+ if (map instanceof CesiumMap) {
154
+ return [new OpenStreetMapCesium(map, this.getImplementationOptions())];
155
+ }
156
+ return [];
157
+ }
158
+
159
+ /**
160
+ * @inheritDoc
161
+ * @returns {OpenStreetMapOptions}
162
+ */
163
+ getConfigObject() {
164
+ const config = /** @type {OpenStreetMapOptions} */ (super.getConfigObject());
165
+ const defaultOptions = OpenStreetMap.getDefaultOptions();
166
+
167
+ if (this._splitDirection !== ImagerySplitDirection.NONE) {
168
+ config.splitDirection = this._splitDirection === ImagerySplitDirection.RIGHT ?
169
+ 'right' :
170
+ 'left';
171
+ }
172
+
173
+ if (this.opacity !== defaultOptions.opacity) {
174
+ config.opacity = this.opacity;
175
+ }
176
+
177
+ if (this.maxLevel !== defaultOptions.maxLevel) {
178
+ config.maxLevel = this.maxLevel;
179
+ }
180
+
181
+ return config;
182
+ }
183
+
184
+ /**
185
+ * @inheritDoc
186
+ */
187
+ destroy() {
188
+ this.splitDirectionChanged.destroy();
189
+ super.destroy();
190
+ }
191
+ }
192
+
193
+ VcsClassRegistry.registerClass(OpenStreetMap.className, OpenStreetMap);
194
+ export default OpenStreetMap;