@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,348 @@
1
+ import { getTransform, get as getProjection, equivalent } from 'ol/proj.js';
2
+ import { register } from 'ol/proj/proj4.js';
3
+ import proj4 from 'proj4';
4
+ import { getLogger as getLoggerByName } from '@vcsuite/logger';
5
+ import { check } from '@vcsuite/check';
6
+
7
+ /**
8
+ * @typedef {Object} ProjectionOptions
9
+ * @property {string|number} [epsg] - EPSG of the projection, for example: "EPSG:4326" if not specified, uses the framework projection
10
+ * @property {string|undefined|null} [proj4] - definition of the projection. See for example: {@link http://spatialreference.org/ref/epsg/4326/proj4/} proj4
11
+ * @property {Array<string>|undefined|null} [alias] - aliases to define
12
+ * @api stable
13
+ */
14
+
15
+ export const wgs84ToMercatorTransformer = getTransform('EPSG:4326', 'EPSG:3857');
16
+ export const mercatorToWgs84Transformer = getTransform('EPSG:3857', 'EPSG:4326');
17
+
18
+
19
+ /**
20
+ * @returns {import("@vcsuite/logger").Logger}
21
+ */
22
+ function getLogger() {
23
+ return getLoggerByName('vcs.vcm.util.Projection');
24
+ }
25
+
26
+ /**
27
+ * @type {ProjectionOptions}
28
+ */
29
+ let defaultProjectionOption = {
30
+ epsg: 'EPSG:4326',
31
+ };
32
+
33
+ /**
34
+ * @param {string|number} value
35
+ * @param {string=} [prefix="EPSG:"]
36
+ * @returns {string}
37
+ */
38
+ function parseEPSGCode(value, prefix = 'EPSG:') {
39
+ const matches = `${value}`.match(/^(?:epsg:)?(\d+)/i);
40
+ if (matches && matches[1]) {
41
+ return `${prefix}${matches[1]}`;
42
+ }
43
+ return '';
44
+ }
45
+
46
+ /**
47
+ * @param {ProjectionOptions} options
48
+ * @returns {boolean}
49
+ */
50
+ function validateProjectionOptions(options) {
51
+ let proj = null;
52
+ if (options.epsg) {
53
+ try {
54
+ // @ts-ignore
55
+ proj = proj4(parseEPSGCode(options.epsg));
56
+ } catch (error) {
57
+ proj = null;
58
+ }
59
+ }
60
+ if (options.proj4) {
61
+ try {
62
+ // @ts-ignore
63
+ proj = proj4(options.proj4);
64
+ } catch (error) {
65
+ proj = null;
66
+ }
67
+ }
68
+ return proj != null;
69
+ }
70
+
71
+ /**
72
+ * @param {ProjectionOptions} options
73
+ * @returns {ProjectionOptions} valid options
74
+ */
75
+ function registerProjection(options) {
76
+ const saneOptions = {};
77
+ if (options.epsg) {
78
+ saneOptions.epsg = parseEPSGCode(options.epsg);
79
+ if (saneOptions.epsg) {
80
+ if (options.proj4) {
81
+ saneOptions.proj4 = options.proj4;
82
+ proj4.defs(saneOptions.epsg, options.proj4);
83
+ register(proj4);
84
+ }
85
+ if (options.alias && Array.isArray(options.alias)) {
86
+ saneOptions.alias = options.alias;
87
+ saneOptions.alias.forEach((alias) => {
88
+ proj4.defs(alias, proj4.defs(saneOptions.epsg));
89
+ register(proj4);
90
+ });
91
+ }
92
+ }
93
+ }
94
+ return saneOptions;
95
+ }
96
+
97
+ /**
98
+ * Set the default projections epsg and proj4. Does not update
99
+ * projection created prior to this functions call.
100
+ * @param {ProjectionOptions} options
101
+ * @api
102
+ * @export
103
+ */
104
+ export function setDefaultProjectionOptions(options) {
105
+ check(options, { epsg: [String, Number], proj4: [String, undefined, null] });
106
+ if (!validateProjectionOptions(options)) {
107
+ throw new Error('Cannot set invalid projection options as default options');
108
+ }
109
+ defaultProjectionOption = registerProjection(options);
110
+ }
111
+
112
+ /**
113
+ * Projection Class, if no valid options are given, the Projection will initialize with the Framework default Projection
114
+ * @class
115
+ * @export
116
+ * For example:
117
+ * <pre><code>
118
+ * {
119
+ * "epsg" : "EPSG:25833"
120
+ * "proj4" : "+proj=utm +zone=33 +ellps=GRS80 +units=m +no_defs"
121
+ * }
122
+ * </code></pre>
123
+ * @api stable
124
+ */
125
+ class Projection {
126
+ /**
127
+ * @param {ProjectionOptions} options
128
+ */
129
+ constructor(options = { epsg: '' }) {
130
+ const saneOptions = registerProjection(options);
131
+ /**
132
+ * @type {string|null}
133
+ * @private
134
+ */
135
+ this._proj4 = saneOptions.proj4;
136
+
137
+ /**
138
+ * @type {string}
139
+ * @private
140
+ */
141
+ this._epsg = /** @type {string} */ (saneOptions.epsg);
142
+
143
+ if (!this.proj) {
144
+ this._epsg = Projection.parseEPSGCode(defaultProjectionOption.epsg);
145
+ }
146
+ }
147
+
148
+ /**
149
+ * epsg code in the format "EPSG:25832"
150
+ * @type {string}
151
+ * @api
152
+ * @readonly
153
+ */
154
+ get epsg() {
155
+ return this._epsg;
156
+ }
157
+
158
+ /**
159
+ * proj4js string example for epsg:25832: +proj=utm +zone=33 +ellps=GRS80 +units=m +no_defs
160
+ * @type {string|null}
161
+ * @api
162
+ * @readonly
163
+ */
164
+ get proj4() {
165
+ return this._proj4;
166
+ }
167
+
168
+ /**
169
+ * @type {import("ol/proj/Projection").default}
170
+ * @api
171
+ * @readonly
172
+ */
173
+ get proj() {
174
+ return getProjection(this.epsg);
175
+ }
176
+
177
+ /**
178
+ * @returns {import("ol/proj/Projection").default}
179
+ * @api
180
+ * @deprecated 3.7
181
+ */
182
+ getProjection() {
183
+ getLogger().deprecate('getProjection', 'Access the property proj directly');
184
+ return this.proj;
185
+ }
186
+
187
+ /**
188
+ * @param {Projection} projection
189
+ * @returns {boolean}
190
+ */
191
+ equals(projection) {
192
+ return equivalent(this.proj, projection.proj);
193
+ }
194
+
195
+ /**
196
+ * @static
197
+ * @param {Projection} dest
198
+ * @param {Projection} source
199
+ * @param {import("ol/coordinate").Coordinate} coords
200
+ * @returns {import("ol/coordinate").Coordinate}
201
+ * @api stable
202
+ */
203
+ static transform(dest, source, coords) {
204
+ const transformer = getTransform(source.proj, dest.proj);
205
+ const newCoords = new Array(2);
206
+ transformer([coords[0], coords[1]], newCoords, 2);
207
+ if (coords.length > 2) {
208
+ newCoords.push(coords[2]);
209
+ }
210
+ return newCoords;
211
+ }
212
+
213
+ /**
214
+ * @param {Projection} dest
215
+ * @param {import("ol/coordinate").Coordinate} coords
216
+ * @returns {import("ol/coordinate").Coordinate}
217
+ * @api stable
218
+ */
219
+ transformTo(dest, coords) {
220
+ return Projection.transform(dest, this, coords);
221
+ }
222
+
223
+ /**
224
+ * @static
225
+ * @param {Projection} dest
226
+ * @param {Projection} source
227
+ * @param {Array.<import("ol/coordinate").Coordinate>} coords
228
+ * @returns {Array.<import("ol/coordinate").Coordinate>}
229
+ * @api stable
230
+ */
231
+ static transformCoordinates(dest, source, coords) {
232
+ const newCoords = [];
233
+ for (let i = 0; i < coords.length; i++) {
234
+ newCoords.push(Projection.transform(dest, source, coords[i]));
235
+ }
236
+ return newCoords;
237
+ }
238
+
239
+ /**
240
+ * returns a function to transform coordinates from source to dest
241
+ * @static
242
+ * @param {Projection} dest
243
+ * @param {Projection} source
244
+ * @returns {import("ol/proj").TransformFunction}
245
+ */
246
+ static getTransformer(dest, source) {
247
+ return getTransform(source.proj, dest.proj);
248
+ }
249
+
250
+ /**
251
+ * @param {Projection} source
252
+ * @param {import("ol/coordinate").Coordinate} coords
253
+ * @returns {import("ol/coordinate").Coordinate}
254
+ * @api stable
255
+ */
256
+ transformFrom(source, coords) {
257
+ return Projection.transform(this, source, coords);
258
+ }
259
+
260
+ /**
261
+ * Returns the object literal representation of this object
262
+ * @returns {ProjectionOptions}
263
+ * @api stable
264
+ */
265
+ getConfigObject() {
266
+ const configObject = {
267
+ epsg: this.epsg,
268
+ };
269
+ if (this.proj4) {
270
+ configObject.proj4 = this.proj4;
271
+ }
272
+ return configObject;
273
+ }
274
+
275
+ /**
276
+ * Fast transform from Web-Mercator to WGS84
277
+ * @param {import("ol/coordinate").Coordinate} coords
278
+ * @param {boolean=} inPlace - whether to transform in place
279
+ * @returns {import("ol/coordinate").Coordinate}
280
+ * @api
281
+ */
282
+ static mercatorToWgs84(coords, inPlace) {
283
+ return mercatorToWgs84Transformer(coords, inPlace ? coords : undefined, coords.length);
284
+ }
285
+
286
+ /**
287
+ * Fast transform from WGS84 to Web-Mercator
288
+ * @param {import("ol/coordinate").Coordinate} coords
289
+ * @param {boolean=} inPlace - whether to transform in place
290
+ * @returns {import("ol/coordinate").Coordinate}
291
+ * @api
292
+ */
293
+ static wgs84ToMercator(coords, inPlace) {
294
+ return wgs84ToMercatorTransformer(coords, inPlace ? coords : undefined, coords.length);
295
+ }
296
+
297
+ /**
298
+ * validates projection options, combination of epsg code and proj4
299
+ * @param {ProjectionOptions} options
300
+ * @returns {boolean}
301
+ * @api
302
+ */
303
+ static validateOptions(options) {
304
+ return validateProjectionOptions(options);
305
+ }
306
+
307
+ /**
308
+ * parses an epsg code returns empty string if no code has been found
309
+ * for example:
310
+ * parseEPSGCode('epsg:4326') ==> '4326'
311
+ * parseEPSGCode('epsg:4326', 'EPSG:') ==> 'EPSG:4326'
312
+ * parseEPSGCode('asdasd', 'EPSG:') ==> ''
313
+ * @param {string|number|undefined} value
314
+ * @param {string|undefined} prefix default EPSG:
315
+ * @returns {string}
316
+ * @api
317
+ */
318
+ static parseEPSGCode(value, prefix = 'EPSG:') {
319
+ return parseEPSGCode(value, prefix);
320
+ }
321
+ }
322
+
323
+ export default Projection;
324
+
325
+ /**
326
+ * Returns the default Projection.
327
+ * @api stable
328
+ * @returns {Projection}
329
+ * @export
330
+ */
331
+ export function getDefaultProjection() {
332
+ return new Projection(defaultProjectionOption);
333
+ }
334
+
335
+ /**
336
+ * wgs84 Projection EPSG Code: 4326
337
+ * @api stable
338
+ * @type {Projection}
339
+ * @export
340
+ */
341
+ export const wgs84Projection = new Projection({ epsg: 4326 });
342
+ /**
343
+ * mercator Projection EPSG Code: 3857
344
+ * @api stable
345
+ * @type {Projection}
346
+ * @export
347
+ */
348
+ export const mercatorProjection = new Projection({ epsg: 3857 });
@@ -0,0 +1,233 @@
1
+ import {
2
+ Cartesian3,
3
+ Matrix4,
4
+ Plane,
5
+ ClippingPlane,
6
+ ClippingPlaneCollection,
7
+ ImagerySplitDirection,
8
+ } from '@vcmap/cesium';
9
+
10
+ import { check } from '@vcsuite/check';
11
+ import CesiumMap from '../maps/cesium.js';
12
+ import ClippingObject from './clipping/clippingObject.js';
13
+ import Openlayers from '../maps/openlayers.js';
14
+
15
+ /**
16
+ * @class
17
+ * @api
18
+ */
19
+ class SplitScreen {
20
+ /**
21
+ * @param {import("@vcmap/core").ClippingObjectManager} clippingObjectManager
22
+ */
23
+ constructor(clippingObjectManager) {
24
+ /**
25
+ * @type {number}
26
+ * @private
27
+ */
28
+ this._position = 0.5;
29
+ /**
30
+ * @type {import("@vcmap/cesium").Scene|null}
31
+ */
32
+ this.scene = null;
33
+ /**
34
+ * @type {import("ol/Map").default|null}
35
+ */
36
+ this.olMap = null;
37
+ /**
38
+ * @type {boolean}
39
+ * @api
40
+ */
41
+ this.initialized = false;
42
+ /**
43
+ * @type {ClippingObject}
44
+ */
45
+ this.leftScreenClippingObject = new ClippingObject();
46
+ /**
47
+ * @type {ClippingObject}
48
+ */
49
+ this.rightScreenClippingObject = new ClippingObject();
50
+ /**
51
+ * @type {Function|null}
52
+ * @private
53
+ */
54
+ this._cameraListener = null;
55
+ /**
56
+ * @type {number|null}
57
+ */
58
+ this.originalCameraPercentageChanged = null;
59
+ /**
60
+ * @type {Array<Function>}
61
+ * @private
62
+ */
63
+ this._targetsChangedListeners = [];
64
+
65
+ this._targetsChangedListeners = [
66
+ this.rightScreenClippingObject.targetsUpdated.addEventListener(() => { this._targetsChanged(); }),
67
+ this.leftScreenClippingObject.targetsUpdated.addEventListener(() => { this._targetsChanged(); }),
68
+ ];
69
+
70
+ /**
71
+ * @type {import("@vcmap/core").ClippingObjectManager}
72
+ * @private
73
+ */
74
+ this._clippingObjectManager = clippingObjectManager;
75
+ this._clippingObjectManager.addClippingObject(this.rightScreenClippingObject);
76
+ this._clippingObjectManager.addClippingObject(this.leftScreenClippingObject);
77
+ }
78
+
79
+ /**
80
+ * @type {number}
81
+ * @api
82
+ */
83
+ get position() { return this._position; }
84
+
85
+ /**
86
+ * @param {number} position
87
+ */
88
+ set position(position) {
89
+ check(position, Number);
90
+ if (position < 0 || position > 1) {
91
+ throw new Error('Position must be between 0 and 1');
92
+ }
93
+
94
+ if (Math.abs(this._position - position) > 0.0001) {
95
+ this._updatePosition(position);
96
+ }
97
+ }
98
+
99
+ _targetsChanged() {
100
+ if (this.scene) {
101
+ const numTargets = this.rightScreenClippingObject.targets.size + this.leftScreenClippingObject.targets.size;
102
+ const { camera } = this.scene;
103
+
104
+ if (this._cameraListener && numTargets === 0) {
105
+ this._cameraListener();
106
+ this._cameraListener = null;
107
+ camera.percentageChanged = this.originalCameraPercentageChanged;
108
+ } else if (!this._cameraListener && numTargets > 0) {
109
+ this.originalCameraPercentageChanged = camera.percentageChanged;
110
+ camera.percentageChanged = 0;
111
+ this._cameraListener = camera.changed.addEventListener(this._updateClippingPlanes.bind(this));
112
+ this._updateClippingPlanes();
113
+ }
114
+ }
115
+ }
116
+
117
+ /**
118
+ * @param {number} position
119
+ * @private
120
+ */
121
+ _updatePosition(position) {
122
+ this._position = position;
123
+ if (this.scene) {
124
+ this.scene.imagerySplitPosition = position;
125
+ this._updateClippingPlanes();
126
+ } else if (this.olMap) {
127
+ this.olMap.render();
128
+ }
129
+ }
130
+
131
+ /**
132
+ * @param {import("@vcmap/core").VcsMap} map
133
+ */
134
+ mapActivated(map) {
135
+ if (map instanceof CesiumMap) {
136
+ this.scene = map.getScene();
137
+ this.olMap = null;
138
+ this._targetsChanged();
139
+ } else if (map instanceof Openlayers) {
140
+ this.scene = null;
141
+ this.olMap = map.olMap;
142
+ }
143
+ this._updatePosition(this.position);
144
+ }
145
+
146
+ /**
147
+ * calculate a clipping plane from the current swipe position for the given Cesium3DTileset
148
+ * @returns {import("@vcmap/cesium").ClippingPlane}
149
+ * @private
150
+ */
151
+ _calcClippingPlane() {
152
+ const { camera } = this.scene;
153
+ const { fov, near } = /** @type {import("@vcmap/cesium").PerspectiveFrustum} */ (camera.frustum);
154
+ const screenWidth = this.scene.canvas.width || 1;
155
+ const screenHeight = this.scene.canvas.height || 1;
156
+ let pixelSize;
157
+ if (screenHeight > screenWidth) {
158
+ pixelSize = (near * Math.tan(0.5 * fov) * 2.0) / screenHeight;
159
+ } else {
160
+ pixelSize = (near * Math.tan(0.5 * fov) * 2.0) / screenWidth;
161
+ }
162
+
163
+ // extract 3 points lying on swipe plane
164
+ const screenX = (screenWidth * this.position) - (screenWidth / 2);
165
+ const screenY = screenHeight / 2;
166
+ const p1 = new Cartesian3(pixelSize * screenX, pixelSize * screenY, -1 * near);
167
+ const p2 = new Cartesian3(pixelSize * screenX, -1 * pixelSize * screenY, -1 * near);
168
+ Matrix4.multiplyByPoint(camera.inverseViewMatrix, p1, p1);
169
+ Matrix4.multiplyByPoint(camera.inverseViewMatrix, p2, p2);
170
+ const p3WC = camera.positionWC;
171
+
172
+ Cartesian3.subtract(p3WC, p1, p1);
173
+ Cartesian3.subtract(p3WC, p2, p2);
174
+ const normal = Cartesian3.cross(p1, p2, new Cartesian3());
175
+ Cartesian3.normalize(normal, normal);
176
+ const planeInFixedFrame = Plane.fromPointNormal(p3WC, normal);
177
+
178
+ return ClippingPlane.fromPlane(planeInFixedFrame);
179
+ }
180
+
181
+ /**
182
+ * update the clipping planes for all Cesium3DTilesets loaded in the vcMap
183
+ * @private
184
+ */
185
+ _updateClippingPlanes() {
186
+ const plane = this._calcClippingPlane();
187
+ this.leftScreenClippingObject.clippingPlaneCollection = new ClippingPlaneCollection({ planes: [plane] });
188
+ const revClippingPlane = ClippingPlane.clone(plane);
189
+ revClippingPlane.normal = Cartesian3.negate(revClippingPlane.normal, revClippingPlane.normal);
190
+ revClippingPlane.distance *= -1;
191
+ this.rightScreenClippingObject.clippingPlaneCollection =
192
+ new ClippingPlaneCollection({ planes: [revClippingPlane] });
193
+ }
194
+
195
+ /**
196
+ * Gets the clipping object for a split direction
197
+ * @param {import("@vcmap/cesium").ImagerySplitDirection} splitDirection
198
+ * @returns {ClippingObject|null}
199
+ * @api
200
+ */
201
+ getClippingObjectForDirection(splitDirection) {
202
+ check(splitDirection, [
203
+ ImagerySplitDirection.LEFT,
204
+ ImagerySplitDirection.RIGHT,
205
+ ImagerySplitDirection.NONE,
206
+ ]);
207
+
208
+ if (splitDirection === ImagerySplitDirection.LEFT) {
209
+ return this.leftScreenClippingObject;
210
+ }
211
+ if (splitDirection === ImagerySplitDirection.RIGHT) {
212
+ return this.rightScreenClippingObject;
213
+ }
214
+
215
+ return null;
216
+ }
217
+
218
+ destroy() {
219
+ if (this._clippingObjectManager) {
220
+ this._clippingObjectManager.removeClippingObject(this.rightScreenClippingObject);
221
+ this._clippingObjectManager.removeClippingObject(this.leftScreenClippingObject);
222
+ }
223
+ this._targetsChangedListeners.forEach((cb) => { cb(); });
224
+ this._targetsChangedListeners = [];
225
+ this._clippingObjectManager = null;
226
+ if (this._cameraListener) {
227
+ this._cameraListener();
228
+ this._cameraListener = null;
229
+ }
230
+ }
231
+ }
232
+
233
+ export default SplitScreen;