@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.
- package/LICENSE.md +21 -0
- package/README.md +44 -0
- package/build/postinstall.js +44 -0
- package/index.js +139 -0
- package/package.json +92 -0
- package/src/cesium/cesium3DTileFeature.js +9 -0
- package/src/cesium/cesium3DTilePointFeature.js +9 -0
- package/src/cesium/cesiumVcsCameraPrimitive.js +146 -0
- package/src/cesium/wallpaperMaterial.js +64 -0
- package/src/ol/feature.js +47 -0
- package/src/ol/geom/circle.js +24 -0
- package/src/ol/geom/geometryCollection.js +33 -0
- package/src/ol/render/canvas/canvasTileRenderer.js +179 -0
- package/src/ol/source/ClusterEnhancedVectorSource.js +39 -0
- package/src/ol/source/VcsCluster.js +37 -0
- package/src/vcs/vcm/classRegistry.js +106 -0
- package/src/vcs/vcm/event/vcsEvent.js +89 -0
- package/src/vcs/vcm/globalCollections.js +11 -0
- package/src/vcs/vcm/interaction/abstractInteraction.js +149 -0
- package/src/vcs/vcm/interaction/coordinateAtPixel.js +102 -0
- package/src/vcs/vcm/interaction/eventHandler.js +425 -0
- package/src/vcs/vcm/interaction/featureAtPixelInteraction.js +286 -0
- package/src/vcs/vcm/interaction/featureProviderInteraction.js +54 -0
- package/src/vcs/vcm/interaction/interactionChain.js +124 -0
- package/src/vcs/vcm/interaction/interactionType.js +114 -0
- package/src/vcs/vcm/layer/buildings.js +17 -0
- package/src/vcs/vcm/layer/cesium/cesiumTilesetCesium.js +359 -0
- package/src/vcs/vcm/layer/cesium/clusterContext.js +95 -0
- package/src/vcs/vcm/layer/cesium/dataSourceCesium.js +171 -0
- package/src/vcs/vcm/layer/cesium/openStreetMapCesium.js +29 -0
- package/src/vcs/vcm/layer/cesium/pointCloudCesium.js +58 -0
- package/src/vcs/vcm/layer/cesium/rasterLayerCesium.js +110 -0
- package/src/vcs/vcm/layer/cesium/singleImageCesium.js +49 -0
- package/src/vcs/vcm/layer/cesium/terrainCesium.js +80 -0
- package/src/vcs/vcm/layer/cesium/tmsCesium.js +54 -0
- package/src/vcs/vcm/layer/cesium/vectorCesium.js +255 -0
- package/src/vcs/vcm/layer/cesium/vectorContext.js +167 -0
- package/src/vcs/vcm/layer/cesium/vectorRasterTileCesium.js +116 -0
- package/src/vcs/vcm/layer/cesium/vectorTileImageryProvider.js +246 -0
- package/src/vcs/vcm/layer/cesium/wmsCesium.js +71 -0
- package/src/vcs/vcm/layer/cesium/wmtsCesium.js +101 -0
- package/src/vcs/vcm/layer/cesium/x3dmHelper.js +22 -0
- package/src/vcs/vcm/layer/cesiumTileset.js +376 -0
- package/src/vcs/vcm/layer/czml.js +141 -0
- package/src/vcs/vcm/layer/dataSource.js +259 -0
- package/src/vcs/vcm/layer/featureLayer.js +261 -0
- package/src/vcs/vcm/layer/featureStore.js +647 -0
- package/src/vcs/vcm/layer/featureStoreChanges.js +360 -0
- package/src/vcs/vcm/layer/featureStoreState.js +19 -0
- package/src/vcs/vcm/layer/featureVisibility.js +435 -0
- package/src/vcs/vcm/layer/geojson.js +185 -0
- package/src/vcs/vcm/layer/geojsonHelpers.js +450 -0
- package/src/vcs/vcm/layer/globalHider.js +157 -0
- package/src/vcs/vcm/layer/layer.js +752 -0
- package/src/vcs/vcm/layer/layerImplementation.js +102 -0
- package/src/vcs/vcm/layer/layerState.js +17 -0
- package/src/vcs/vcm/layer/layerSymbols.js +6 -0
- package/src/vcs/vcm/layer/oblique/layerOblique.js +76 -0
- package/src/vcs/vcm/layer/oblique/obliqueHelpers.js +175 -0
- package/src/vcs/vcm/layer/oblique/vectorOblique.js +469 -0
- package/src/vcs/vcm/layer/openStreetMap.js +194 -0
- package/src/vcs/vcm/layer/openlayers/layerOpenlayers.js +79 -0
- package/src/vcs/vcm/layer/openlayers/openStreetMapOpenlayers.js +27 -0
- package/src/vcs/vcm/layer/openlayers/rasterLayerOpenlayers.js +121 -0
- package/src/vcs/vcm/layer/openlayers/singleImageOpenlayers.js +49 -0
- package/src/vcs/vcm/layer/openlayers/tileDebugOpenlayers.js +39 -0
- package/src/vcs/vcm/layer/openlayers/tmsOpenlayers.js +62 -0
- package/src/vcs/vcm/layer/openlayers/vectorOpenlayers.js +118 -0
- package/src/vcs/vcm/layer/openlayers/vectorTileOpenlayers.js +177 -0
- package/src/vcs/vcm/layer/openlayers/wmsOpenlayers.js +55 -0
- package/src/vcs/vcm/layer/openlayers/wmtsOpenlayers.js +141 -0
- package/src/vcs/vcm/layer/pointCloud.js +162 -0
- package/src/vcs/vcm/layer/rasterLayer.js +294 -0
- package/src/vcs/vcm/layer/singleImage.js +119 -0
- package/src/vcs/vcm/layer/terrain.js +122 -0
- package/src/vcs/vcm/layer/terrainHelpers.js +123 -0
- package/src/vcs/vcm/layer/tileLoadedHelper.js +72 -0
- package/src/vcs/vcm/layer/tileProvider/mvtTileProvider.js +104 -0
- package/src/vcs/vcm/layer/tileProvider/staticGeojsonTileProvider.js +67 -0
- package/src/vcs/vcm/layer/tileProvider/tileProvider.js +584 -0
- package/src/vcs/vcm/layer/tileProvider/tileProviderFactory.js +28 -0
- package/src/vcs/vcm/layer/tileProvider/urlTemplateTileProvider.js +106 -0
- package/src/vcs/vcm/layer/tms.js +121 -0
- package/src/vcs/vcm/layer/vector.js +632 -0
- package/src/vcs/vcm/layer/vectorHelpers.js +206 -0
- package/src/vcs/vcm/layer/vectorProperties.js +1391 -0
- package/src/vcs/vcm/layer/vectorSymbols.js +40 -0
- package/src/vcs/vcm/layer/vectorTile.js +480 -0
- package/src/vcs/vcm/layer/wfs.js +165 -0
- package/src/vcs/vcm/layer/wms.js +270 -0
- package/src/vcs/vcm/layer/wmsHelpers.js +65 -0
- package/src/vcs/vcm/layer/wmts.js +235 -0
- package/src/vcs/vcm/maps/baseOLMap.js +257 -0
- package/src/vcs/vcm/maps/cameraLimiter.js +219 -0
- package/src/vcs/vcm/maps/cesium.js +1192 -0
- package/src/vcs/vcm/maps/map.js +511 -0
- package/src/vcs/vcm/maps/mapState.js +17 -0
- package/src/vcs/vcm/maps/oblique.js +536 -0
- package/src/vcs/vcm/maps/openlayers.js +205 -0
- package/src/vcs/vcm/object.js +92 -0
- package/src/vcs/vcm/oblique/ObliqueCollection.js +572 -0
- package/src/vcs/vcm/oblique/ObliqueDataSet.js +357 -0
- package/src/vcs/vcm/oblique/ObliqueImage.js +247 -0
- package/src/vcs/vcm/oblique/ObliqueImageMeta.js +126 -0
- package/src/vcs/vcm/oblique/ObliqueProvider.js +433 -0
- package/src/vcs/vcm/oblique/ObliqueView.js +130 -0
- package/src/vcs/vcm/oblique/ObliqueViewDirection.js +40 -0
- package/src/vcs/vcm/oblique/helpers.js +483 -0
- package/src/vcs/vcm/oblique/parseImageJson.js +248 -0
- package/src/vcs/vcm/util/clipping/clippingObject.js +386 -0
- package/src/vcs/vcm/util/clipping/clippingObjectManager.js +312 -0
- package/src/vcs/vcm/util/clipping/clippingPlaneHelper.js +413 -0
- package/src/vcs/vcm/util/collection.js +193 -0
- package/src/vcs/vcm/util/dateTime.js +60 -0
- package/src/vcs/vcm/util/exclusiveManager.js +135 -0
- package/src/vcs/vcm/util/extent.js +124 -0
- package/src/vcs/vcm/util/featureProvider/abstractFeatureProvider.js +196 -0
- package/src/vcs/vcm/util/featureProvider/featureProviderHelpers.js +51 -0
- package/src/vcs/vcm/util/featureProvider/featureProviderSymbols.js +11 -0
- package/src/vcs/vcm/util/featureProvider/tileProviderFeatureProvider.js +62 -0
- package/src/vcs/vcm/util/featureProvider/wmsFeatureProvider.js +280 -0
- package/src/vcs/vcm/util/featureconverter/circleToCesium.js +215 -0
- package/src/vcs/vcm/util/featureconverter/convert.js +83 -0
- package/src/vcs/vcm/util/featureconverter/extent3d.js +154 -0
- package/src/vcs/vcm/util/featureconverter/featureconverterHelper.js +591 -0
- package/src/vcs/vcm/util/featureconverter/lineStringToCesium.js +171 -0
- package/src/vcs/vcm/util/featureconverter/pointToCesium.js +359 -0
- package/src/vcs/vcm/util/featureconverter/polygonToCesium.js +229 -0
- package/src/vcs/vcm/util/geometryHelpers.js +172 -0
- package/src/vcs/vcm/util/indexedCollection.js +158 -0
- package/src/vcs/vcm/util/isMobile.js +12 -0
- package/src/vcs/vcm/util/layerCollection.js +216 -0
- package/src/vcs/vcm/util/locale.js +53 -0
- package/src/vcs/vcm/util/mapCollection.js +363 -0
- package/src/vcs/vcm/util/math.js +71 -0
- package/src/vcs/vcm/util/projection.js +348 -0
- package/src/vcs/vcm/util/splitScreen.js +233 -0
- package/src/vcs/vcm/util/style/declarativeStyleItem.js +631 -0
- package/src/vcs/vcm/util/style/shapesCategory.js +67 -0
- package/src/vcs/vcm/util/style/styleFactory.js +48 -0
- package/src/vcs/vcm/util/style/styleHelpers.js +555 -0
- package/src/vcs/vcm/util/style/styleItem.js +226 -0
- package/src/vcs/vcm/util/style/vectorStyleItem.js +927 -0
- package/src/vcs/vcm/util/style/writeStyle.js +48 -0
- package/src/vcs/vcm/util/urlHelpers.js +16 -0
- 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
|
+
}
|