@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,413 @@
1
+ import {
2
+ Cartesian3,
3
+ Plane,
4
+ ClippingPlane,
5
+ Matrix3,
6
+ Matrix4,
7
+ ClippingPlaneCollection,
8
+ Entity,
9
+ ConstantProperty,
10
+ JulianDate,
11
+ Cesium3DTileset,
12
+ Globe,
13
+ } from '@vcmap/cesium';
14
+ import Feature from 'ol/Feature.js';
15
+ import LineString from 'ol/geom/LineString.js';
16
+ import { offset } from 'ol/sphere.js';
17
+ import GeometryLayout from 'ol/geom/GeometryLayout.js';
18
+ import Polygon from 'ol/geom/Polygon.js';
19
+
20
+ import { check, checkMaybe } from '@vcsuite/check';
21
+ import Projection, { mercatorProjection, wgs84Projection } from '../projection.js';
22
+ import { createOrUpdateFromGeometry } from '../featureconverter/extent3d.js';
23
+ import { enforceEndingVertex, enforceRightHand, getFlatCoordinatesFromGeometry } from '../geometryHelpers.js';
24
+
25
+ /**
26
+ * Options to the define how Cesium.ClippingPlanes are created from a ol.Feature.
27
+ * @typedef {Object} CreationOptions
28
+ * @property {boolean|undefined} reverse - specify the clip direction. If true, everything outside the clippingPlaneCollection should be cut off
29
+ * @property {boolean|undefined} createVerticalPlanes - specify whether to create the vertical clipping planes
30
+ * @property {boolean|undefined} createTopPlane - specify whether to create the horizontal clipping plane on the top level of an extruded geometry
31
+ * @property {boolean|undefined} createBottomPlane - specify whether to create the horizontal clipping plane on the ground level
32
+ * @property {boolean|undefined} createEndingPlanes - create 2 planes at the end of a line with only two coordinates
33
+ * @api
34
+ */
35
+
36
+ /**
37
+ * Creates a Plane on p1 with the normal in the direction of P2
38
+ * @param {import("@vcmap/cesium").Cartesian3} p1
39
+ * @param {import("@vcmap/cesium").Cartesian3} p2
40
+ * @returns {import("@vcmap/cesium").ClippingPlane}
41
+ */
42
+ function createPlane(p1, p2) {
43
+ const planeNormal = Cartesian3.subtract(p1, p2, new Cartesian3());
44
+ Cartesian3.normalize(planeNormal, planeNormal);
45
+ const plane = Plane.fromPointNormal(p1, planeNormal);
46
+ return ClippingPlane.fromPlane(plane);
47
+ }
48
+
49
+ /**
50
+ * @param {Array<import("ol/coordinate").Coordinate>} coords
51
+ * @returns {Array<import("@vcmap/cesium").ClippingPlane>} clippingPlanes
52
+ */
53
+ function createVerticalPlanes(coords) {
54
+ const clippingPlanes = [];
55
+ // @ts-ignore
56
+ const cartesiansCoords = coords.map(c => Cartesian3.fromDegrees(...Projection.mercatorToWgs84(c)));
57
+ for (let i = 0; i < cartesiansCoords.length - 1; i++) {
58
+ const nextIndex = i + 1;
59
+ const normal = new Cartesian3();
60
+ Cartesian3.cross(cartesiansCoords[nextIndex], cartesiansCoords[i], normal);
61
+ Cartesian3.normalize(normal, normal);
62
+ const verticalPlane = new Plane(normal, 0.0);
63
+ if (!Number.isNaN(verticalPlane.distance)) {
64
+ clippingPlanes.push(ClippingPlane.fromPlane(verticalPlane));
65
+ }
66
+ }
67
+ return clippingPlanes;
68
+ }
69
+
70
+ /**
71
+ * @param {import("ol").Feature<import("ol/geom/Geometry").default>} feature
72
+ * @param {Array<import("ol/coordinate").Coordinate>} coords
73
+ * @param {CreationOptions=} options
74
+ * @returns {Array<import("@vcmap/cesium").ClippingPlane>} clippingPlanes
75
+ */
76
+ function createHorizontalPlanes(feature, coords, options) {
77
+ const clippingPlanes = [];
78
+ const extent = createOrUpdateFromGeometry(feature.getGeometry());
79
+ let min = Number.isFinite(extent[2]) ? extent[2] : 0;
80
+ let max = Number.isFinite(extent[5]) ? extent[5] : 0;
81
+ const extruded = feature.get('olcs_extrudedHeight');
82
+ if (extruded) {
83
+ max += extruded;
84
+ if (feature.get('olcs_skirt')) {
85
+ min -= feature.get('olcs_skirt');
86
+ }
87
+ }
88
+
89
+
90
+ if (min === max) {
91
+ max += 1;
92
+ }
93
+
94
+ const [lon, lat] = Projection.mercatorToWgs84(coords[0]);
95
+ const lowerPoint = Cartesian3.fromDegrees(lon, lat, min);
96
+ const upperPoint = Cartesian3.fromDegrees(lon, lat, max);
97
+ if (options.createBottomPlane) {
98
+ clippingPlanes.push(createPlane(lowerPoint, upperPoint));
99
+ }
100
+ if (extruded && options.createTopPlane) {
101
+ clippingPlanes.push(createPlane(upperPoint, lowerPoint));
102
+ }
103
+ return clippingPlanes;
104
+ }
105
+
106
+ /**
107
+ * creates a plane for each point in the opposite direction of the other point.
108
+ * only works for two coordinates
109
+ * @param {Array<import("ol/coordinate").Coordinate>} coords
110
+ * @returns {Array<import("@vcmap/cesium").ClippingPlane>} clippingPlanes
111
+ */
112
+ function createEndingPlanes(coords) {
113
+ const clippingPlanes = [];
114
+ // @ts-ignore
115
+ const cartesiansCoords = coords.map(c => Cartesian3.fromDegrees(...Projection.mercatorToWgs84(c)));
116
+ const normal = new Cartesian3();
117
+ Cartesian3.cross(cartesiansCoords[0], cartesiansCoords[1], normal);
118
+ Cartesian3.normalize(normal, normal);
119
+
120
+ function createOuter(cartesian) {
121
+ const moved = Cartesian3.add(cartesian, normal, new Cartesian3());
122
+ const planeNormal = new Cartesian3();
123
+ Cartesian3.cross(cartesian, moved, planeNormal);
124
+ Cartesian3.normalize(planeNormal, planeNormal);
125
+ const verticalPlane = new Plane(planeNormal, 0.0);
126
+ clippingPlanes.push(ClippingPlane.fromPlane(verticalPlane));
127
+ }
128
+
129
+ createOuter(cartesiansCoords[0]);
130
+ Cartesian3.negate(normal, normal);
131
+ createOuter(cartesiansCoords[1]);
132
+ return clippingPlanes;
133
+ }
134
+
135
+ /**
136
+ * create a Cesium ClippingPlaneCollection based on a given feature having a multi-curve, polygon, or extruded solid geometry
137
+ * @param {import("ol").Feature<import("ol/geom/Geometry").default>} feature - base for calculating the clipping planes.
138
+ * @param {CreationOptions=} options
139
+ * @param {import("@vcmap/cesium").Matrix4=} transformMatrix - 4x4 matrix specifying the transform of clipping planes from Earth's fixed frame to another one
140
+ * @returns {import("@vcmap/cesium").ClippingPlaneCollection|null}
141
+ * @api stable
142
+ * @export
143
+ */
144
+ export function createClippingPlaneCollection(feature, options = {}, transformMatrix) {
145
+ check(feature, Feature);
146
+ check(options, Object);
147
+ checkMaybe(transformMatrix, Matrix4);
148
+
149
+ const clippingPlanes = [];
150
+ const geometry = feature.getGeometry();
151
+ const geometryType = geometry.getType();
152
+
153
+ if (geometryType === 'Point') {
154
+ clippingPlanes.push(...createHorizontalPlanes(feature, [geometry.getCoordinates()], options));
155
+ } else {
156
+ const coords = getFlatCoordinatesFromGeometry(geometry);
157
+ if (coords.length < 2 || (coords[0][0] === coords[1][0] && coords[0][1] === coords[1][1])) {
158
+ return null;
159
+ }
160
+
161
+ if (geometryType === 'Polygon') {
162
+ enforceEndingVertex(coords);
163
+ enforceRightHand(coords);
164
+ } else if (geometryType === 'LineString' && coords.length === 2 && options.createEndingPlanes) {
165
+ clippingPlanes.push(...createEndingPlanes(coords));
166
+ }
167
+
168
+ if (options.createVerticalPlanes) {
169
+ clippingPlanes.push(...createVerticalPlanes(coords));
170
+ }
171
+
172
+ if (feature.get('olcs_altitudeMode') === 'absolute' && (options.createBottomPlane || options.createTopPlane)) {
173
+ clippingPlanes.push(...createHorizontalPlanes(feature, coords, options));
174
+ }
175
+ }
176
+
177
+ if (transformMatrix) {
178
+ clippingPlanes.forEach((/** @type {import("@vcmap/cesium").ClippingPlane} */ plane) => {
179
+ const result = Plane.transform(plane, transformMatrix);
180
+ plane.normal = result.normal;
181
+ plane.distance = result.distance;
182
+ });
183
+ }
184
+
185
+ if (options.reverse) {
186
+ clippingPlanes.forEach((/** @type {import("@vcmap/cesium").ClippingPlane} */ plane) => {
187
+ Cartesian3.negate(plane.normal, plane.normal);
188
+ plane.distance *= -1;
189
+ });
190
+ }
191
+
192
+ return new ClippingPlaneCollection({
193
+ planes: clippingPlanes,
194
+ unionClippingRegions: options.reverse,
195
+ });
196
+ }
197
+
198
+ /**
199
+ * copies the clippingplanes and the properties from source to result
200
+ * @param {import("@vcmap/cesium").ClippingPlaneCollection} source
201
+ * @param {import("@vcmap/cesium").ClippingPlaneCollection} result
202
+ * @param {import("@vcmap/cesium").Matrix4=} transformMatrix - 4x4 matrix specifying the transform of clipping planes from Earth's fixed frame to another one
203
+ * @param {import("@vcmap/cesium").Cartesian3=} originPoint - the origin point of the transformation target, so the plane distance can be set correctly
204
+ * @returns {import("@vcmap/cesium").ClippingPlaneCollection}
205
+ * @api stable
206
+ * @export
207
+ */
208
+ export function copyClippingPlanesToCollection(source, result, transformMatrix, originPoint) {
209
+ check(source, ClippingPlaneCollection);
210
+ check(result, ClippingPlaneCollection);
211
+
212
+ if (result.length > 0) {
213
+ result.removeAll();
214
+ }
215
+ for (let i = 0; i < source.length; i++) {
216
+ const plane = source.get(i);
217
+ if (transformMatrix && originPoint) {
218
+ const distance = Plane.getPointDistance(plane, originPoint);
219
+ const transformedPlane = Plane.transform(plane, transformMatrix);
220
+ transformedPlane.distance = distance;
221
+ result.add(ClippingPlane.fromPlane(transformedPlane));
222
+ } else {
223
+ result.add(ClippingPlane.clone(plane));
224
+ }
225
+ }
226
+ result.modelMatrix = source.modelMatrix.clone();
227
+ result.unionClippingRegions = source.unionClippingRegions;
228
+ result.edgeColor = source.edgeColor.clone();
229
+ result.edgeWidth = source.edgeWidth;
230
+ return result;
231
+ }
232
+
233
+ /**
234
+ * @param {import("@vcmap/cesium").Globe|import("@vcmap/cesium").Cesium3DTileset|import("@vcmap/cesium").Entity} target
235
+ */
236
+ export function clearClippingPlanes(target) {
237
+ if (target instanceof Entity) {
238
+ if (target.model) {
239
+ if (target.model.clippingPlanes) {
240
+ const entityClippingPlanes =
241
+ (/** @type {import("@vcmap/cesium").ConstantProperty} */ (target.model.clippingPlanes)).getValue();
242
+ entityClippingPlanes.removeAll();
243
+ } else {
244
+ target.model.clippingPlanes = new ConstantProperty(new ClippingPlaneCollection());
245
+ }
246
+ }
247
+ } else if (target.clippingPlanes) {
248
+ target.clippingPlanes.removeAll();
249
+ } else {
250
+ target.clippingPlanes = new ClippingPlaneCollection();
251
+ }
252
+ }
253
+
254
+ /**
255
+ * @param {import("@vcmap/cesium").Cesium3DTileset} cesium3DTileset
256
+ * @param {import("@vcmap/cesium").ClippingPlaneCollection} clippingPlaneCollection
257
+ * @param {boolean=} local
258
+ */
259
+ function setTilesetClippingPlane(cesium3DTileset, clippingPlaneCollection, local) {
260
+ clearClippingPlanes(cesium3DTileset);
261
+ // copyClippingPlanesToCollection(clippingPlaneCollection, cesium3DTileset.clippingPlanes); XXX this is in release-4.0 but i think its an oversight
262
+ if (!local) {
263
+ if (!clippingPlaneCollection.modelMatrix.equals(Matrix4.IDENTITY)) {
264
+ copyClippingPlanesToCollection(clippingPlaneCollection, cesium3DTileset.clippingPlanes);
265
+ cesium3DTileset.clippingPlanes.modelMatrix = Matrix4.multiply(
266
+ Matrix4.inverse(
267
+ cesium3DTileset.clippingPlanesOriginMatrix,
268
+ cesium3DTileset.clippingPlanes.modelMatrix,
269
+ ),
270
+ clippingPlaneCollection.modelMatrix,
271
+ cesium3DTileset.clippingPlanes.modelMatrix,
272
+ );
273
+ } else {
274
+ const rotation = Matrix4.getMatrix3(
275
+ Matrix4.inverse(cesium3DTileset.clippingPlanesOriginMatrix, new Matrix4()),
276
+ new Matrix3(),
277
+ );
278
+ const transformationMatrix = Matrix4.fromRotationTranslation(rotation, new Cartesian3());
279
+ copyClippingPlanesToCollection(
280
+ clippingPlaneCollection,
281
+ cesium3DTileset.clippingPlanes,
282
+ transformationMatrix,
283
+ cesium3DTileset.boundingSphere.center,
284
+ );
285
+ }
286
+ } else {
287
+ copyClippingPlanesToCollection(clippingPlaneCollection, cesium3DTileset.clippingPlanes);
288
+ }
289
+ }
290
+
291
+ /**
292
+ * @param {import("@vcmap/cesium").Globe} globe
293
+ * @param {import("@vcmap/cesium").ClippingPlaneCollection} clippingPlaneCollection
294
+ */
295
+ function setGlobeClippingPlanes(globe, clippingPlaneCollection) {
296
+ clearClippingPlanes(globe);
297
+ copyClippingPlanesToCollection(clippingPlaneCollection, globe.clippingPlanes);
298
+ }
299
+
300
+ /**
301
+ * apply a clippingPlaneCollection to an entity
302
+ * @param {import("@vcmap/cesium").Entity} entity
303
+ * @param {import("@vcmap/cesium").ClippingPlaneCollection} clippingPlaneCollection
304
+ * @param {boolean=} local
305
+ */
306
+ function setEntityClippingPlanes(entity, clippingPlaneCollection, local) {
307
+ if (entity.model) {
308
+ clearClippingPlanes(entity);
309
+ const entityClippingPlanes =
310
+ (/** @type {import("@vcmap/cesium").ConstantProperty} */ (entity.model.clippingPlanes)).getValue();
311
+ copyClippingPlanesToCollection(clippingPlaneCollection, entityClippingPlanes);
312
+ if (!local) {
313
+ const localToFixedFrame = entity.computeModelMatrix(JulianDate.now());
314
+ Matrix4.inverseTransformation(localToFixedFrame, entityClippingPlanes.modelMatrix);
315
+ if (!clippingPlaneCollection.modelMatrix.equals(Matrix4.IDENTITY)) {
316
+ Matrix4.multiply(
317
+ entityClippingPlanes.modelMatrix,
318
+ clippingPlaneCollection.modelMatrix,
319
+ entityClippingPlanes.modelMatrix,
320
+ );
321
+ }
322
+ }
323
+ }
324
+ }
325
+
326
+ /**
327
+ * @param {import("@vcmap/cesium").Globe|import("@vcmap/cesium").Cesium3DTileset|import("@vcmap/cesium").Entity} target
328
+ * @param {import("@vcmap/cesium").ClippingPlaneCollection} clippingPlaneCollection
329
+ * @param {boolean=} local
330
+ */
331
+ export function setClippingPlanes(target, clippingPlaneCollection, local) {
332
+ if (target instanceof Cesium3DTileset) {
333
+ setTilesetClippingPlane(target, clippingPlaneCollection, local);
334
+ } else if (target instanceof Globe) {
335
+ setGlobeClippingPlanes(target, clippingPlaneCollection);
336
+ } else {
337
+ setEntityClippingPlanes(target, clippingPlaneCollection, local);
338
+ }
339
+ }
340
+
341
+ /**
342
+ * Creates a new feature at the given coordinate, which can be set on a {@link ClippingObjectEditor}.
343
+ * @param {import("ol/coordinate").Coordinate} coordinate - in WGS84
344
+ * @param {import("@vcmap/cesium").Camera} camera
345
+ * @param {boolean} [vertical=false]
346
+ * @param {number} [offsetDistance=25] - the offset from the coordinate to use for the size of the geometry
347
+ * @returns {import("ol").Feature<import("ol/geom/Geometry").default>} - the features geometry is in web mercator
348
+ * @api
349
+ * @export
350
+ */
351
+ export function createClippingFeature(coordinate, camera, vertical = false, offsetDistance = 25) {
352
+ check(coordinate, [Number]);
353
+ check(vertical, Boolean);
354
+ check(offsetDistance, Number);
355
+
356
+ let geometry;
357
+ if (vertical) {
358
+ const p1 = offset(coordinate, -offsetDistance, camera.heading);
359
+ const p2 = offset(coordinate, offsetDistance, camera.heading);
360
+ geometry = new LineString([
361
+ [p1[0], p1[1], coordinate[2]],
362
+ [p2[0], p2[1], coordinate[2]],
363
+ // @ts-ignore
364
+ ], GeometryLayout.XYZ);
365
+ } else {
366
+ geometry = new Polygon([[]], GeometryLayout.XYZ);
367
+ let bearing = (2 * Math.PI) - (Math.PI / 4); // Bearing NW
368
+ const coordinates = [...new Array(4)].map(() => {
369
+ const newPoint = offset(coordinate, offsetDistance, bearing);
370
+ bearing -= (Math.PI / 2);
371
+ return [newPoint[0], newPoint[1], coordinate[2]];
372
+ });
373
+ geometry.setCoordinates([coordinates]);
374
+ }
375
+ const feature = new Feature({ geometry });
376
+ feature.set('olcs_altitudeMode', 'absolute');
377
+ if (vertical) {
378
+ feature.set('olcs_extrudedHeight', offsetDistance * 2);
379
+ }
380
+
381
+ geometry.transform(wgs84Projection.proj, mercatorProjection.proj);
382
+ return feature;
383
+ }
384
+
385
+ /**
386
+ * Gets the clipping options for the current feature to be infinite or not for the given feature created by
387
+ * {@link createClippingFeature}.
388
+ * @param {import("ol").Feature<import("ol/geom/Geometry").default>=} feature - the feature created by {@link createClippingFeature}
389
+ * @param {boolean=} [infinite=false]
390
+ * @returns {CreationOptions}
391
+ * @api
392
+ * @export
393
+ */
394
+ export function getClippingOptions(feature, infinite = false) {
395
+ checkMaybe(feature, Feature);
396
+ check(infinite, Boolean);
397
+
398
+ const vertical = feature ?
399
+ feature.getGeometry().getType() === 'LineString' :
400
+ false;
401
+
402
+ return vertical ?
403
+ {
404
+ createBottomPlane: !infinite,
405
+ createTopPlane: !infinite,
406
+ createEndingPlanes: !infinite,
407
+ createVerticalPlanes: true,
408
+ } :
409
+ {
410
+ createVerticalPlanes: !infinite,
411
+ createBottomPlane: true,
412
+ };
413
+ }
@@ -0,0 +1,193 @@
1
+ import VcsEvent from '../event/vcsEvent.js';
2
+
3
+ /**
4
+ * A generic array based collection. Implements the Symbol.iterator (e.g. [...collection])
5
+ * @class
6
+ * @export
7
+ * @template {*} T
8
+ * @api
9
+ */
10
+ class Collection {
11
+ /**
12
+ * Creates a Collection from an iterable, such as an Array.
13
+ * @template {*} T
14
+ * @param {Iterable<T>} iterable
15
+ * @param {(string|symbol|boolean)=} [uniqueKey='name'] - a key to maintain uniquely within the collection. passing false disables uniqueness.
16
+ * @returns {Collection<T>}
17
+ * @api
18
+ */
19
+ static from(iterable, uniqueKey) {
20
+ const collection = /** @type {Collection<T>} */ (new Collection(uniqueKey));
21
+ if (iterable) {
22
+ // eslint-disable-next-line no-restricted-syntax
23
+ for (const i of iterable) {
24
+ collection.add(i);
25
+ }
26
+ }
27
+ return collection;
28
+ }
29
+
30
+ /**
31
+ * @param {(string|symbol|boolean)=} [uniqueKey='name'] - a key to maintain uniquely within the collection. passing false disables uniqueness.
32
+ */
33
+ constructor(uniqueKey) {
34
+ /**
35
+ * @protected
36
+ * @type {Array<T>}
37
+ */
38
+ this._array = [];
39
+
40
+ /**
41
+ * @type {string|symbol}
42
+ * @private
43
+ */
44
+ this._uniqueKey = 'name';
45
+ if (typeof uniqueKey === 'string' || typeof uniqueKey === 'symbol') {
46
+ this._uniqueKey = uniqueKey;
47
+ } else if (uniqueKey === false) {
48
+ this._uniqueKey = undefined;
49
+ }
50
+
51
+ /**
52
+ * Event raised if an item is added. Is passed the added item.
53
+ * @type {VcsEvent<T>}
54
+ * @api
55
+ */
56
+ this.added = new VcsEvent();
57
+
58
+ /**
59
+ * Event raised if an item is removed. Is passed the removed item.
60
+ * @type {VcsEvent<T>}
61
+ * @api
62
+ */
63
+ this.removed = new VcsEvent();
64
+ }
65
+
66
+ * [Symbol.iterator]() {
67
+ const arrayLength = this._array.length;
68
+ for (let i = 0; i < arrayLength; i++) {
69
+ yield this._array[i];
70
+ }
71
+ }
72
+
73
+ /**
74
+ * The key by which to check uniqueness against. undefined if no uniqueness constraint is set.
75
+ * @readonly
76
+ * @type {string|symbol}
77
+ * @api
78
+ */
79
+ get uniqueKey() { return this._uniqueKey; }
80
+
81
+ /**
82
+ * @readonly
83
+ * @type {number}
84
+ * @api
85
+ */
86
+ get size() { return this._array.length; }
87
+
88
+ /**
89
+ * Returns an item identified by the unique constraint key. Returns null, if there is no uniqueness constraint.
90
+ * @param {*} value - the value to test against. does a shallow comparison, if the passed a non-atomic value
91
+ * @returns {T|undefined}
92
+ * @api
93
+ */
94
+ getByKey(value) {
95
+ if (!this._uniqueKey) {
96
+ return undefined;
97
+ }
98
+ return this._array.find(e => e[this._uniqueKey] === value);
99
+ }
100
+
101
+ /**
102
+ * @param {T} item
103
+ * @returns {boolean}
104
+ * @protected
105
+ */
106
+ _checkUniqueness(item) {
107
+ if (this._uniqueKey) {
108
+ if (item == null || typeof item !== 'object') {
109
+ return false;
110
+ }
111
+ const value = item[this._uniqueKey];
112
+ if (value == null) {
113
+ return false;
114
+ }
115
+ const found = this.getByKey(value);
116
+ if (found != null) {
117
+ return false;
118
+ }
119
+ }
120
+ return true;
121
+ }
122
+
123
+ /**
124
+ * Adds an item to the collection.
125
+ * @param {T} item - the item to be inserted
126
+ * @returns {number|null} the index at which the item was inserted
127
+ * @api
128
+ */
129
+ add(item) {
130
+ if (this._checkUniqueness(item)) {
131
+ this._array.push(item);
132
+ this.added.raiseEvent(item);
133
+ return this._array.length - 1;
134
+ }
135
+ return null;
136
+ }
137
+
138
+ /**
139
+ * Removes an item from the collection
140
+ * @param {T} item
141
+ * @api
142
+ */
143
+ remove(item) {
144
+ const index = this._array.indexOf(item);
145
+ if (index > -1) {
146
+ this._array.splice(index, 1);
147
+ this.removed.raiseEvent(item);
148
+ }
149
+ }
150
+
151
+ /**
152
+ * Equivalent to Array.prototype.includes
153
+ * @param {T} item
154
+ * @returns {boolean}
155
+ * @api
156
+ */
157
+ has(item) {
158
+ return this._array.includes(item);
159
+ }
160
+
161
+ /**
162
+ * Returns true, if the key exists. Returns undefined, if there is no uniqueness constraint.
163
+ * @param {*} value
164
+ * @returns {boolean}
165
+ * @api
166
+ */
167
+ hasKey(value) {
168
+ if (!this._uniqueKey) {
169
+ return undefined;
170
+ }
171
+ return this._array.some(e => e[this._uniqueKey] === value);
172
+ }
173
+
174
+ /**
175
+ * clears the array
176
+ * @api
177
+ */
178
+ clear() {
179
+ this._array.forEach((i) => { this.removed.raiseEvent(i); });
180
+ this._array.splice(0);
181
+ }
182
+
183
+ /**
184
+ * Destroys the collection, clearing the array and all its events
185
+ */
186
+ destroy() {
187
+ this._array = [];
188
+ this.added.destroy();
189
+ this.removed.destroy();
190
+ }
191
+ }
192
+
193
+ export default Collection;
@@ -0,0 +1,60 @@
1
+ /**
2
+ * @param {Date} date
3
+ * @param {string=} locale
4
+ * @returns {string}
5
+ */
6
+ export function getShortLocaleDate(date, locale) {
7
+ // dateStyle is not within the standard yet
8
+ // @ts-ignore
9
+ return new Intl.DateTimeFormat(locale, { dateStyle: 'short' }).format(date);
10
+ }
11
+
12
+ /**
13
+ * @param {Date} date
14
+ * @param {string=} locale
15
+ * @returns {string}
16
+ */
17
+ export function getShortLocaleTime(date, locale) {
18
+ // timeStyle is not within the standard yet
19
+ // @ts-ignore
20
+ return new Intl.DateTimeFormat(locale, { timeStyle: 'short' }).format(date);
21
+ }
22
+
23
+ /**
24
+ * @param {Date} date
25
+ * @returns {string}
26
+ */
27
+ export function getISODateString(date) {
28
+ const month = date.getMonth() + 1;
29
+ const day = date.getDate();
30
+ return `${date.getFullYear()}-${month > 9 ? '' : 0}${month}-${day > 9 ? '' : 0}${day}`;
31
+ }
32
+
33
+ /**
34
+ * @param {Date} date
35
+ * @returns {number}
36
+ */
37
+ export function getDayOfYear(date) {
38
+ const start = new Date(date.getFullYear(), 0, 0);
39
+ // TS cant handle date manipulation
40
+ // @ts-ignore
41
+ const diff = (date - start) + ((start.getTimezoneOffset() - date.getTimezoneOffset()) * 60 * 1000);
42
+ const oneDay = 1000 * 60 * 60 * 24;
43
+ return Math.floor(diff / oneDay);
44
+ }
45
+
46
+ /**
47
+ * @param {Date} date
48
+ * @returns {boolean}
49
+ */
50
+ export function isLeapYear(date) {
51
+ const currentYear = date.getFullYear();
52
+ if (currentYear % 4 !== 0) {
53
+ return false;
54
+ } else if (currentYear % 100 !== 0) {
55
+ return true;
56
+ } else if (currentYear % 400 !== 0) {
57
+ return false;
58
+ }
59
+ return true;
60
+ }