@vcmap/core 5.0.0-rc.23 → 5.0.0-rc.24
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/index.d.ts +597 -98
- package/index.js +24 -9
- package/package.json +2 -2
- package/src/category/category.js +1 -1
- package/src/featureProvider/abstractFeatureProvider.js +1 -18
- package/src/interaction/eventHandler.js +14 -0
- package/src/layer/cesium/clusterContext.js +12 -0
- package/src/layer/cesium/vectorCesiumImpl.js +2 -2
- package/src/layer/cesium/vectorContext.js +115 -7
- package/src/layer/cesiumTilesetLayer.js +0 -14
- package/src/layer/czmlLayer.js +1 -1
- package/src/layer/dataSourceLayer.js +1 -53
- package/src/layer/featureLayer.js +0 -44
- package/src/layer/featureStoreLayer.js +0 -15
- package/src/layer/layer.js +0 -11
- package/src/layer/vectorHelpers.js +0 -85
- package/src/layer/vectorLayer.js +0 -9
- package/src/layer/vectorProperties.js +150 -8
- package/src/layer/vectorTileLayer.js +0 -9
- package/src/map/cesiumMap.js +26 -7
- package/src/style/arcStyle.js +316 -0
- package/src/style/arrowStyle.js +269 -0
- package/src/util/editor/createFeatureSession.js +3 -1
- package/src/util/editor/editFeaturesSession.js +315 -0
- package/src/util/editor/editGeometrySession.js +5 -1
- package/src/util/editor/editorHelpers.js +118 -14
- package/src/util/editor/editorSessionHelpers.js +12 -0
- package/src/util/editor/editorSymbols.js +6 -0
- package/src/util/editor/interactions/editFeaturesMouseOverInteraction.js +120 -0
- package/src/util/editor/interactions/editGeometryMouseOverInteraction.js +1 -3
- package/src/util/editor/interactions/ensureHandlerSelectionInteraction.js +48 -0
- package/src/util/editor/interactions/mapInteractionController.js +5 -2
- package/src/util/editor/interactions/selectMultiFeatureInteraction.js +146 -0
- package/src/util/editor/interactions/translateVertexInteraction.js +2 -2
- package/src/util/editor/transformation/create2DHandlers.js +294 -0
- package/src/util/editor/transformation/create3DHandlers.js +575 -0
- package/src/util/editor/transformation/extrudeInteraction.js +91 -0
- package/src/util/editor/transformation/rotateInteraction.js +188 -0
- package/src/util/editor/transformation/scaleInteraction.js +185 -0
- package/src/util/editor/transformation/transformationHandler.js +168 -0
- package/src/util/editor/transformation/transformationTypes.js +83 -0
- package/src/util/editor/transformation/translateInteraction.js +209 -0
- package/src/util/featureconverter/arcToCesium.js +87 -0
- package/src/util/featureconverter/convert.js +7 -1
- package/src/util/featureconverter/extent3D.js +64 -1
- package/src/util/featureconverter/lineStringToCesium.js +103 -2
- package/src/util/featureconverter/pointHelpers.js +341 -0
- package/src/util/featureconverter/pointToCesium.js +27 -76
- package/src/util/geometryHelpers.js +11 -8
- package/src/util/math.js +99 -2
- package/tests/unit/helpers/cesiumHelpers.js +14 -4
- package/tests/unit/helpers/helpers.js +13 -0
- package/src/featureProvider/featureProviderHelpers.js +0 -50
|
@@ -0,0 +1,575 @@
|
|
|
1
|
+
import { Feature } from 'ol';
|
|
2
|
+
import {
|
|
3
|
+
ArcType, BoxGeometry,
|
|
4
|
+
Cartesian3,
|
|
5
|
+
Color, CoplanarPolygonGeometry, CylinderGeometry, EllipsoidGeometry,
|
|
6
|
+
GeometryInstance, HeadingPitchRoll,
|
|
7
|
+
Material,
|
|
8
|
+
MaterialAppearance, Math as CesiumMath, Matrix3, Matrix4, PolygonHierarchy, PolylineGeometry,
|
|
9
|
+
PolylineMaterialAppearance,
|
|
10
|
+
Primitive, PrimitiveCollection, Transforms,
|
|
11
|
+
} from '@vcmap/cesium';
|
|
12
|
+
import { handlerSymbol } from '../editorSymbols.js';
|
|
13
|
+
import { AXIS_AND_PLANES, greyedOutColor, is1DAxis, is2DAxis, TransformationMode } from './transformationTypes.js';
|
|
14
|
+
import Projection from '../../projection.js';
|
|
15
|
+
import { mercatorToCartesian } from '../../math.js';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @param {import("@vcmap/cesium").Primitive} primitive
|
|
19
|
+
*/
|
|
20
|
+
function setFeatureOnPrimitive(primitive) {
|
|
21
|
+
if (primitive[handlerSymbol]) {
|
|
22
|
+
const feature = new Feature();
|
|
23
|
+
feature[handlerSymbol] = primitive[handlerSymbol];
|
|
24
|
+
primitive.olFeature = feature;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @param {import("@vcmap/cesium").Color} color
|
|
30
|
+
* @returns {{ depthFailAppearance: import("@vcmap/cesium").PolylineMaterialAppearance, appearance: import("@vcmap/cesium").PolylineMaterialAppearance }}
|
|
31
|
+
*/
|
|
32
|
+
function createPolylineAppearances(color) {
|
|
33
|
+
return {
|
|
34
|
+
appearance: new PolylineMaterialAppearance({
|
|
35
|
+
material: Material.fromType('Color', {
|
|
36
|
+
color,
|
|
37
|
+
}),
|
|
38
|
+
}),
|
|
39
|
+
depthFailAppearance: new PolylineMaterialAppearance({
|
|
40
|
+
material: Material.fromType('Color', {
|
|
41
|
+
color: Color.divideByScalar(color, 1.5, new Color()).withAlpha(0.2),
|
|
42
|
+
}),
|
|
43
|
+
}),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @param {import("@vcmap/cesium").Color} color
|
|
49
|
+
* @returns {{ depthFailAppearance: import("@vcmap/cesium").PolylineMaterialAppearance, appearance: import("@vcmap/cesium").PolylineMaterialAppearance }}
|
|
50
|
+
*/
|
|
51
|
+
function getPolygonAppearance(color) {
|
|
52
|
+
return {
|
|
53
|
+
appearance: new MaterialAppearance({
|
|
54
|
+
flat: true,
|
|
55
|
+
material: Material.fromType('Color', {
|
|
56
|
+
color,
|
|
57
|
+
}),
|
|
58
|
+
}),
|
|
59
|
+
depthFailAppearance: new MaterialAppearance({
|
|
60
|
+
flat: true,
|
|
61
|
+
material: Material.fromType('Color', {
|
|
62
|
+
color: Color.divideByScalar(color, 1.5, new Color()).withAlpha(0.2),
|
|
63
|
+
}),
|
|
64
|
+
}),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @param {AXIS_AND_PLANES} axis
|
|
70
|
+
* @param {import("@vcmap/cesium").Matrix4} modelMatrix
|
|
71
|
+
* @param {boolean} [greyOut=false]
|
|
72
|
+
* @returns {import("@vcmap/cesium").Primitive}
|
|
73
|
+
*/
|
|
74
|
+
function createRingPrimitive(axis, modelMatrix, greyOut = false) {
|
|
75
|
+
let color;
|
|
76
|
+
let rotation;
|
|
77
|
+
|
|
78
|
+
if (axis === AXIS_AND_PLANES.Z) {
|
|
79
|
+
color = Color.BLUE;
|
|
80
|
+
rotation = Matrix3.IDENTITY.clone();
|
|
81
|
+
} else if (axis === AXIS_AND_PLANES.X) {
|
|
82
|
+
color = Color.RED;
|
|
83
|
+
rotation = Matrix3.multiply(Matrix3.fromRotationY(Math.PI / 2), Matrix3.fromRotationX(Math.PI / 2), new Matrix3());
|
|
84
|
+
} else {
|
|
85
|
+
color = Color.GREEN;
|
|
86
|
+
rotation = Matrix3.fromRotationY(Math.PI / 2);
|
|
87
|
+
}
|
|
88
|
+
color = greyOut ? greyedOutColor : color;
|
|
89
|
+
const primitive = new Primitive({
|
|
90
|
+
allowPicking: !greyOut,
|
|
91
|
+
asynchronous: false,
|
|
92
|
+
geometryInstances: [
|
|
93
|
+
new GeometryInstance({
|
|
94
|
+
geometry: new EllipsoidGeometry({
|
|
95
|
+
radii: new Cartesian3(0.5, 0.5, 0.5),
|
|
96
|
+
innerRadii: new Cartesian3(0.45, 0.45, 0.45),
|
|
97
|
+
minimumCone: CesiumMath.toRadians(88),
|
|
98
|
+
maximumCone: CesiumMath.toRadians(92),
|
|
99
|
+
}),
|
|
100
|
+
}),
|
|
101
|
+
],
|
|
102
|
+
...getPolygonAppearance(color),
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
let primitiveModelMatrix = Matrix4.multiplyByMatrix3(modelMatrix, rotation, new Matrix4());
|
|
106
|
+
Object.defineProperty(primitive, 'modelMatrix', {
|
|
107
|
+
set(newModelMatrix) { // updating requires recalculation using the geometry model matrix.
|
|
108
|
+
if (!Matrix4.equals(newModelMatrix, primitiveModelMatrix)) {
|
|
109
|
+
primitiveModelMatrix = Matrix4.multiplyByMatrix3(newModelMatrix, rotation, primitiveModelMatrix);
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
get() {
|
|
113
|
+
return primitiveModelMatrix;
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
if (!greyOut) {
|
|
117
|
+
primitive[handlerSymbol] = axis;
|
|
118
|
+
}
|
|
119
|
+
setFeatureOnPrimitive(primitive);
|
|
120
|
+
return primitive;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* @param {import("ol/coordinate").Coordinate} coordinateWgs84
|
|
125
|
+
*/
|
|
126
|
+
function ensureWrappedCoordinate(coordinateWgs84) {
|
|
127
|
+
if (coordinateWgs84[0] > 180) {
|
|
128
|
+
coordinateWgs84[0] -= 360;
|
|
129
|
+
} else if (coordinateWgs84[0] < -180) {
|
|
130
|
+
coordinateWgs84[0] += 360;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (coordinateWgs84[1] > 90) {
|
|
134
|
+
coordinateWgs84[1] = 90 - (coordinateWgs84[1] - 90);
|
|
135
|
+
if (coordinateWgs84[0] < 180) {
|
|
136
|
+
coordinateWgs84[0] += 180;
|
|
137
|
+
} else {
|
|
138
|
+
coordinateWgs84[1] -= 180;
|
|
139
|
+
}
|
|
140
|
+
} else if (coordinateWgs84[1] < -90) {
|
|
141
|
+
coordinateWgs84[1] = -90 + (coordinateWgs84[1] + 90);
|
|
142
|
+
if (coordinateWgs84[0] < 180) {
|
|
143
|
+
coordinateWgs84[0] += 180;
|
|
144
|
+
} else {
|
|
145
|
+
coordinateWgs84[1] -= 180;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* @param {import("ol/coordinate").Coordinate} centerWgs84
|
|
152
|
+
* @param {AXIS_AND_PLANES} direction
|
|
153
|
+
* @returns {Array<import("ol/coordinate").Coordinate>}
|
|
154
|
+
*/
|
|
155
|
+
function createRhumbLinePositions(centerWgs84, direction) {
|
|
156
|
+
const offsets = [-15, -5, 0, 5, 15];
|
|
157
|
+
return offsets.map((offset) => {
|
|
158
|
+
const position = centerWgs84.slice();
|
|
159
|
+
if (direction === AXIS_AND_PLANES.X) {
|
|
160
|
+
position[0] += offset;
|
|
161
|
+
} else {
|
|
162
|
+
position[1] += offset;
|
|
163
|
+
}
|
|
164
|
+
ensureWrappedCoordinate(position);
|
|
165
|
+
return position;
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* @param {AXIS_AND_PLANES} axis
|
|
171
|
+
* @param {import("ol/coordinate").Coordinate} center
|
|
172
|
+
* @returns {import("@vcmap/cesium").PrimitiveCollection}
|
|
173
|
+
*/
|
|
174
|
+
function createAxisPrimitive(axis, center) {
|
|
175
|
+
const primitives = [];
|
|
176
|
+
const centerWgs84 = Projection.mercatorToWgs84(center);
|
|
177
|
+
if (axis === AXIS_AND_PLANES.X || axis === AXIS_AND_PLANES.XY || axis === AXIS_AND_PLANES.XZ) {
|
|
178
|
+
primitives.push(new Primitive({
|
|
179
|
+
asynchronous: false,
|
|
180
|
+
geometryInstances: [
|
|
181
|
+
new GeometryInstance({
|
|
182
|
+
geometry: new PolylineGeometry({
|
|
183
|
+
positions: Cartesian3
|
|
184
|
+
.fromDegreesArrayHeights(createRhumbLinePositions(centerWgs84, AXIS_AND_PLANES.X).flat()),
|
|
185
|
+
width: 1,
|
|
186
|
+
arcType: ArcType.RHUMB,
|
|
187
|
+
}),
|
|
188
|
+
}),
|
|
189
|
+
],
|
|
190
|
+
...createPolylineAppearances(Color.RED.withAlpha(0.5)),
|
|
191
|
+
}));
|
|
192
|
+
}
|
|
193
|
+
if (axis === AXIS_AND_PLANES.Y || axis === AXIS_AND_PLANES.XY || axis === AXIS_AND_PLANES.YZ) {
|
|
194
|
+
primitives.push(new Primitive({
|
|
195
|
+
asynchronous: false,
|
|
196
|
+
geometryInstances: [
|
|
197
|
+
new GeometryInstance({
|
|
198
|
+
geometry: new PolylineGeometry({
|
|
199
|
+
positions: Cartesian3
|
|
200
|
+
.fromDegreesArrayHeights(createRhumbLinePositions(centerWgs84, AXIS_AND_PLANES.Y).flat()),
|
|
201
|
+
width: 1,
|
|
202
|
+
arcType: ArcType.RHUMB,
|
|
203
|
+
}),
|
|
204
|
+
}),
|
|
205
|
+
],
|
|
206
|
+
...createPolylineAppearances(Color.GREEN.withAlpha(0.5)),
|
|
207
|
+
}));
|
|
208
|
+
}
|
|
209
|
+
if (axis === AXIS_AND_PLANES.Z || axis === AXIS_AND_PLANES.XZ || axis === AXIS_AND_PLANES.YZ) {
|
|
210
|
+
primitives.push(new Primitive({
|
|
211
|
+
asynchronous: false,
|
|
212
|
+
geometryInstances: [
|
|
213
|
+
new GeometryInstance({
|
|
214
|
+
geometry: new PolylineGeometry({
|
|
215
|
+
positions: Cartesian3.fromDegreesArrayHeights([
|
|
216
|
+
centerWgs84[0], centerWgs84[1], center[2] - 500000,
|
|
217
|
+
centerWgs84[0], centerWgs84[1], center[2],
|
|
218
|
+
centerWgs84[0], centerWgs84[1], center[2] + 500000,
|
|
219
|
+
]),
|
|
220
|
+
width: 1,
|
|
221
|
+
}),
|
|
222
|
+
}),
|
|
223
|
+
],
|
|
224
|
+
...createPolylineAppearances(Color.BLUE.withAlpha(0.5)),
|
|
225
|
+
}));
|
|
226
|
+
}
|
|
227
|
+
const primitiveCollection = new PrimitiveCollection();
|
|
228
|
+
primitives.forEach((p) => {
|
|
229
|
+
primitiveCollection.add(p);
|
|
230
|
+
});
|
|
231
|
+
return primitiveCollection;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* @param {import("@vcmap/cesium").PrimitiveCollection} primitiveCollection
|
|
236
|
+
* @returns {function(AXIS_AND_PLANES, import("ol/coordinate").Coordinate):void}
|
|
237
|
+
*/
|
|
238
|
+
function createShowAxisPrimitive(primitiveCollection) {
|
|
239
|
+
let primitive;
|
|
240
|
+
return (axis, center) => {
|
|
241
|
+
if (primitive) {
|
|
242
|
+
primitiveCollection.remove(primitive);
|
|
243
|
+
primitive = null;
|
|
244
|
+
}
|
|
245
|
+
if (axis !== AXIS_AND_PLANES.NONE) {
|
|
246
|
+
primitive = createAxisPrimitive(axis, center);
|
|
247
|
+
primitiveCollection.add(primitive);
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* @param {import("@vcmap/cesium").CylinderGeometry|import("@vcmap/cesium").BoxGeometry} geometry
|
|
254
|
+
* @param {import("@vcmap/cesium").Color} color
|
|
255
|
+
* @param {import("@vcmap/cesium").Matrix4} modelMatrix
|
|
256
|
+
* @param {import("@vcmap/cesium").Matrix4} geometryModelMatrix
|
|
257
|
+
* @param {boolean} allowPicking
|
|
258
|
+
* @returns {import("@vcmap/cesium").Primitive}
|
|
259
|
+
*/
|
|
260
|
+
function createAxisEndingPrimitive(geometry, color, modelMatrix, geometryModelMatrix, allowPicking) {
|
|
261
|
+
const primitive = new Primitive({
|
|
262
|
+
allowPicking,
|
|
263
|
+
asynchronous: false,
|
|
264
|
+
geometryInstances: [
|
|
265
|
+
new GeometryInstance({
|
|
266
|
+
geometry,
|
|
267
|
+
}),
|
|
268
|
+
],
|
|
269
|
+
...getPolygonAppearance(color),
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
let primitiveModelMatrix = Matrix4.multiply(modelMatrix, geometryModelMatrix, new Matrix4());
|
|
273
|
+
Object.defineProperty(primitive, 'modelMatrix', {
|
|
274
|
+
set(newModelMatrix) { // updating requires recalculation using the geometry model matrix.
|
|
275
|
+
if (!Matrix4.equals(newModelMatrix, primitiveModelMatrix)) {
|
|
276
|
+
primitiveModelMatrix = Matrix4.multiply(newModelMatrix, geometryModelMatrix, primitiveModelMatrix);
|
|
277
|
+
}
|
|
278
|
+
},
|
|
279
|
+
get() {
|
|
280
|
+
return primitiveModelMatrix;
|
|
281
|
+
},
|
|
282
|
+
});
|
|
283
|
+
return primitive;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* @param {AXIS_AND_PLANES} axis
|
|
288
|
+
* @param {import("@vcmap/cesium").Matrix4} modelMatrix
|
|
289
|
+
* @param {TransformationMode} mode
|
|
290
|
+
* @param {boolean} [greyOut=false]
|
|
291
|
+
* @returns {Array<import("@vcmap/cesium").Primitive>}
|
|
292
|
+
*/
|
|
293
|
+
function createLineAxisPrimitives(axis, modelMatrix, mode, greyOut = false) {
|
|
294
|
+
let to;
|
|
295
|
+
let color;
|
|
296
|
+
let arrowTransformation;
|
|
297
|
+
if (axis === AXIS_AND_PLANES.X) {
|
|
298
|
+
to = new Cartesian3(1, CesiumMath.EPSILON8, 0); // we cannot use 0 because of normalization issues
|
|
299
|
+
color = Color.RED;
|
|
300
|
+
arrowTransformation = Matrix4.fromRotationTranslation(
|
|
301
|
+
Matrix3.fromRotationY(Math.PI / 2),
|
|
302
|
+
new Cartesian3(1, 0, 0),
|
|
303
|
+
);
|
|
304
|
+
} else if (axis === AXIS_AND_PLANES.Y) {
|
|
305
|
+
to = new Cartesian3(CesiumMath.EPSILON8, 1, 0);
|
|
306
|
+
color = Color.GREEN;
|
|
307
|
+
arrowTransformation = Matrix4.fromRotationTranslation(
|
|
308
|
+
Matrix3.multiply(Matrix3.fromRotationY(Math.PI / 2), Matrix3.fromRotationX(-(Math.PI / 2)), new Matrix3()),
|
|
309
|
+
new Cartesian3(0, 1, 0),
|
|
310
|
+
);
|
|
311
|
+
} else {
|
|
312
|
+
to = new Cartesian3(CesiumMath.EPSILON8, CesiumMath.EPSILON8, 1);
|
|
313
|
+
color = Color.BLUE;
|
|
314
|
+
arrowTransformation = Matrix4.fromRotationTranslation(
|
|
315
|
+
Matrix3.IDENTITY.clone(),
|
|
316
|
+
new Cartesian3(0, 0, 1),
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
color = greyOut ? greyedOutColor : color;
|
|
320
|
+
|
|
321
|
+
const arrowGeometry = mode === TransformationMode.SCALE ?
|
|
322
|
+
new BoxGeometry({
|
|
323
|
+
minimum: new Cartesian3(-0.1, -0.1, -0.1),
|
|
324
|
+
maximum: new Cartesian3(0.1, 0.1, 0.1),
|
|
325
|
+
}) :
|
|
326
|
+
new CylinderGeometry({
|
|
327
|
+
length: 0.2,
|
|
328
|
+
topRadius: 0,
|
|
329
|
+
bottomRadius: 0.06,
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
const primitives = [
|
|
333
|
+
new Primitive({
|
|
334
|
+
allowPicking: !greyOut,
|
|
335
|
+
asynchronous: false,
|
|
336
|
+
geometryInstances: [
|
|
337
|
+
new GeometryInstance({
|
|
338
|
+
geometry: new PolylineGeometry({
|
|
339
|
+
positions: [
|
|
340
|
+
new Cartesian3(CesiumMath.EPSILON8, CesiumMath.EPSILON8, 0),
|
|
341
|
+
to,
|
|
342
|
+
],
|
|
343
|
+
width: 5,
|
|
344
|
+
arcType: ArcType.NONE,
|
|
345
|
+
}),
|
|
346
|
+
}),
|
|
347
|
+
],
|
|
348
|
+
...createPolylineAppearances(color),
|
|
349
|
+
modelMatrix,
|
|
350
|
+
}),
|
|
351
|
+
createAxisEndingPrimitive(arrowGeometry, color, modelMatrix, arrowTransformation, !greyOut),
|
|
352
|
+
];
|
|
353
|
+
|
|
354
|
+
if (!greyOut) {
|
|
355
|
+
primitives.forEach((p) => {
|
|
356
|
+
p[handlerSymbol] = axis;
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
return primitives;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* @param {AXIS_AND_PLANES} plane
|
|
365
|
+
* @param {import("@vcmap/cesium").Matrix4} modelMatrix
|
|
366
|
+
* @param {boolean} [greyOut]
|
|
367
|
+
* @returns {import("@vcmap/cesium").Primitive}
|
|
368
|
+
*/
|
|
369
|
+
function createPlanePrimitive(plane, modelMatrix, greyOut = false) {
|
|
370
|
+
let positions;
|
|
371
|
+
let color;
|
|
372
|
+
if (plane === AXIS_AND_PLANES.XY) {
|
|
373
|
+
positions = [
|
|
374
|
+
new Cartesian3(0.2, 0.2, 0),
|
|
375
|
+
new Cartesian3(0.4, 0.2, 0),
|
|
376
|
+
new Cartesian3(0.4, 0.4, 0),
|
|
377
|
+
new Cartesian3(0.2, 0.4, 0),
|
|
378
|
+
];
|
|
379
|
+
color = Color.BLUE;
|
|
380
|
+
} else if (plane === AXIS_AND_PLANES.XZ) {
|
|
381
|
+
positions = [
|
|
382
|
+
new Cartesian3(0.2, 0.0000001, 0.2),
|
|
383
|
+
new Cartesian3(0.4, 0.0000001, 0.2),
|
|
384
|
+
new Cartesian3(0.4, 0.0000001, 0.4),
|
|
385
|
+
new Cartesian3(0.2, 0.0000001, 0.4),
|
|
386
|
+
];
|
|
387
|
+
color = Color.GREEN;
|
|
388
|
+
} else {
|
|
389
|
+
positions = [
|
|
390
|
+
new Cartesian3(0.0000001, 0.2, 0.2),
|
|
391
|
+
new Cartesian3(0.0000001, 0.4, 0.2),
|
|
392
|
+
new Cartesian3(0.0000001, 0.4, 0.4),
|
|
393
|
+
new Cartesian3(0.0000001, 0.2, 0.4),
|
|
394
|
+
];
|
|
395
|
+
color = Color.RED;
|
|
396
|
+
}
|
|
397
|
+
color = greyOut ? greyedOutColor : color;
|
|
398
|
+
const primitive = new Primitive({
|
|
399
|
+
allowPicking: !greyOut,
|
|
400
|
+
asynchronous: false,
|
|
401
|
+
geometryInstances: [
|
|
402
|
+
new GeometryInstance({
|
|
403
|
+
geometry: new CoplanarPolygonGeometry({
|
|
404
|
+
polygonHierarchy: new PolygonHierarchy(positions),
|
|
405
|
+
}),
|
|
406
|
+
}),
|
|
407
|
+
],
|
|
408
|
+
...getPolygonAppearance(color),
|
|
409
|
+
modelMatrix,
|
|
410
|
+
});
|
|
411
|
+
if (!greyOut) {
|
|
412
|
+
primitive[handlerSymbol] = plane;
|
|
413
|
+
}
|
|
414
|
+
return primitive;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* @param {import("@vcmap/cesium").PrimitiveCollection} primitiveCollection
|
|
419
|
+
* @returns {(function(AXIS_AND_PLANES, import("@vcmap/cesium").Matrix4, TransformationMode): void)}
|
|
420
|
+
*/
|
|
421
|
+
function createShowShadowPrimitive(primitiveCollection) {
|
|
422
|
+
let primitive;
|
|
423
|
+
|
|
424
|
+
return (axis, modelMatrix, mode) => {
|
|
425
|
+
if (primitive) {
|
|
426
|
+
primitiveCollection.remove(primitive);
|
|
427
|
+
primitive = null;
|
|
428
|
+
}
|
|
429
|
+
if (axis !== AXIS_AND_PLANES.NONE) {
|
|
430
|
+
primitive = new PrimitiveCollection();
|
|
431
|
+
if (is1DAxis(axis)) {
|
|
432
|
+
createLineAxisPrimitives(axis, modelMatrix, mode, true)
|
|
433
|
+
.forEach((p) => {
|
|
434
|
+
primitive.add(p);
|
|
435
|
+
});
|
|
436
|
+
} else if (is2DAxis(axis)) {
|
|
437
|
+
primitive.add(createPlanePrimitive(axis, modelMatrix, true));
|
|
438
|
+
}
|
|
439
|
+
primitiveCollection.add(primitive);
|
|
440
|
+
}
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* The function will create 3D handlers for the {@see CesiumMap} depending on the provided mode.
|
|
446
|
+
* In most scenarios, handlers must not be created using this function, but using the startEditFeaturesSession or for lower
|
|
447
|
+
* level access the createTransformationHandler instead.
|
|
448
|
+
* @param {import("@vcmap/core").CesiumMap} map
|
|
449
|
+
* @param {TransformationMode} mode
|
|
450
|
+
* @returns {Handlers}
|
|
451
|
+
*/
|
|
452
|
+
export default function create3DHandlers(map, mode) {
|
|
453
|
+
const primitiveCollection = new PrimitiveCollection();
|
|
454
|
+
const modelMatrix = Matrix4.fromTranslation(Cartesian3.fromDegrees(0, 0, 0));
|
|
455
|
+
const zPrimitives = [];
|
|
456
|
+
|
|
457
|
+
if (mode === TransformationMode.TRANSLATE || mode === TransformationMode.SCALE) {
|
|
458
|
+
const primitives = [
|
|
459
|
+
...createLineAxisPrimitives(AXIS_AND_PLANES.X, modelMatrix, mode),
|
|
460
|
+
...createLineAxisPrimitives(AXIS_AND_PLANES.Y, modelMatrix, mode),
|
|
461
|
+
createPlanePrimitive(AXIS_AND_PLANES.XY, modelMatrix),
|
|
462
|
+
];
|
|
463
|
+
|
|
464
|
+
if (mode === TransformationMode.TRANSLATE) {
|
|
465
|
+
zPrimitives.push(
|
|
466
|
+
...createLineAxisPrimitives(AXIS_AND_PLANES.Z, modelMatrix, mode),
|
|
467
|
+
createPlanePrimitive(AXIS_AND_PLANES.XZ, modelMatrix),
|
|
468
|
+
createPlanePrimitive(AXIS_AND_PLANES.YZ, modelMatrix),
|
|
469
|
+
);
|
|
470
|
+
primitives.push(...zPrimitives);
|
|
471
|
+
}
|
|
472
|
+
primitives.forEach((p) => {
|
|
473
|
+
setFeatureOnPrimitive(p);
|
|
474
|
+
primitiveCollection.add(p);
|
|
475
|
+
});
|
|
476
|
+
} else if (mode === TransformationMode.ROTATE) {
|
|
477
|
+
primitiveCollection.add(createRingPrimitive(AXIS_AND_PLANES.X, modelMatrix, true));
|
|
478
|
+
primitiveCollection.add(createRingPrimitive(AXIS_AND_PLANES.Y, modelMatrix, true));
|
|
479
|
+
primitiveCollection.add(createRingPrimitive(AXIS_AND_PLANES.Z, modelMatrix));
|
|
480
|
+
} else if (mode === TransformationMode.EXTRUDE) {
|
|
481
|
+
createLineAxisPrimitives(AXIS_AND_PLANES.Z, modelMatrix, mode)
|
|
482
|
+
.forEach((p) => {
|
|
483
|
+
setFeatureOnPrimitive(p);
|
|
484
|
+
primitiveCollection.add(p);
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
const scene = map.getScene();
|
|
489
|
+
let center = [0, 0, 0];
|
|
490
|
+
let scale = 1;
|
|
491
|
+
|
|
492
|
+
const postRenderListener = scene.postRender.addEventListener(() => {
|
|
493
|
+
if (!(center[0] === 0 && center[1] === 0 && center[2] === 0)) {
|
|
494
|
+
const res = map.getCurrentResolution(center) * 60;
|
|
495
|
+
if (res !== scale) {
|
|
496
|
+
Matrix4.setScale(modelMatrix, new Cartesian3(res, res, res), modelMatrix);
|
|
497
|
+
for (let i = 0; i < primitiveCollection.length; i++) {
|
|
498
|
+
primitiveCollection.get(i).modelMatrix = modelMatrix;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
scale = res;
|
|
503
|
+
}
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
let showAxis = AXIS_AND_PLANES.NONE;
|
|
507
|
+
const showAxisPrimitives = createShowAxisPrimitive(primitiveCollection);
|
|
508
|
+
const showShadowPrimitive = createShowShadowPrimitive(primitiveCollection);
|
|
509
|
+
|
|
510
|
+
let greyOutZ = false;
|
|
511
|
+
return {
|
|
512
|
+
get show() {
|
|
513
|
+
return primitiveCollection.show;
|
|
514
|
+
},
|
|
515
|
+
set show(show) {
|
|
516
|
+
primitiveCollection.show = show;
|
|
517
|
+
if (show && !scene.primitives.contains(primitiveCollection)) {
|
|
518
|
+
scene.primitives.add(primitiveCollection);
|
|
519
|
+
}
|
|
520
|
+
},
|
|
521
|
+
get showAxis() {
|
|
522
|
+
return showAxis;
|
|
523
|
+
},
|
|
524
|
+
set showAxis(axis) {
|
|
525
|
+
showAxis = axis;
|
|
526
|
+
showAxisPrimitives(axis, center.slice());
|
|
527
|
+
showShadowPrimitive(axis, modelMatrix.clone(), mode);
|
|
528
|
+
},
|
|
529
|
+
get greyOutZ() { return greyOutZ; },
|
|
530
|
+
set greyOutZ(greyOut) {
|
|
531
|
+
if (greyOut !== greyOutZ) {
|
|
532
|
+
greyOutZ = greyOut;
|
|
533
|
+
zPrimitives.forEach((p) => {
|
|
534
|
+
primitiveCollection.remove(p);
|
|
535
|
+
});
|
|
536
|
+
zPrimitives.splice(0);
|
|
537
|
+
if (mode === TransformationMode.TRANSLATE) {
|
|
538
|
+
zPrimitives.push(
|
|
539
|
+
...createLineAxisPrimitives(AXIS_AND_PLANES.Z, modelMatrix, mode, greyOut),
|
|
540
|
+
createPlanePrimitive(AXIS_AND_PLANES.XZ, modelMatrix, greyOut),
|
|
541
|
+
createPlanePrimitive(AXIS_AND_PLANES.YZ, modelMatrix, greyOut),
|
|
542
|
+
);
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
zPrimitives.forEach((p) => {
|
|
546
|
+
setFeatureOnPrimitive(p);
|
|
547
|
+
primitiveCollection.add(p);
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
},
|
|
551
|
+
setCenter(newCenter) {
|
|
552
|
+
center = newCenter.slice();
|
|
553
|
+
Transforms.headingPitchRollToFixedFrame(
|
|
554
|
+
mercatorToCartesian(center),
|
|
555
|
+
new HeadingPitchRoll(0, 0, 0),
|
|
556
|
+
null,
|
|
557
|
+
null,
|
|
558
|
+
modelMatrix,
|
|
559
|
+
);
|
|
560
|
+
Matrix4.multiplyByUniformScale(modelMatrix, scale, modelMatrix);
|
|
561
|
+
|
|
562
|
+
for (let i = 0; i < primitiveCollection.length; i++) {
|
|
563
|
+
primitiveCollection.get(i).modelMatrix = modelMatrix;
|
|
564
|
+
}
|
|
565
|
+
},
|
|
566
|
+
destroy() {
|
|
567
|
+
postRenderListener();
|
|
568
|
+
showAxisPrimitives(AXIS_AND_PLANES.NONE, center);
|
|
569
|
+
showShadowPrimitive(AXIS_AND_PLANES.NONE, modelMatrix.clone(), mode);
|
|
570
|
+
if (scene.primitives.contains(primitiveCollection)) {
|
|
571
|
+
scene.primitives.remove(primitiveCollection);
|
|
572
|
+
}
|
|
573
|
+
},
|
|
574
|
+
};
|
|
575
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import AbstractInteraction from '../../../interaction/abstractInteraction.js';
|
|
2
|
+
import { EventType } from '../../../interaction/interactionType.js';
|
|
3
|
+
import { handlerSymbol } from '../editorSymbols.js';
|
|
4
|
+
import {
|
|
5
|
+
createCameraVerticalPlane,
|
|
6
|
+
getCartographicFromPlane,
|
|
7
|
+
} from '../editorHelpers.js';
|
|
8
|
+
import VcsEvent from '../../../vcsEvent.js';
|
|
9
|
+
import { AXIS_AND_PLANES } from './transformationTypes.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* A class to handle events on a {@see TransformationHandler}. Should be used with {@see TransformationHandler} created for mode TransformationMode.EXTRUDE.
|
|
13
|
+
* If the Z handler is dragged, the extruded event will be raised with a delta in Z direction. This
|
|
14
|
+
* interaction only works if a {@see CesiumMap} is the active map.
|
|
15
|
+
* @class
|
|
16
|
+
* @extends {AbstractInteraction}
|
|
17
|
+
*/
|
|
18
|
+
class ExtrudeInteraction extends AbstractInteraction {
|
|
19
|
+
/**
|
|
20
|
+
* @param {TransformationHandler} transformationHandler
|
|
21
|
+
*/
|
|
22
|
+
constructor(transformationHandler) {
|
|
23
|
+
super(EventType.DRAGEVENTS);
|
|
24
|
+
/**
|
|
25
|
+
* @type {TransformationHandler}
|
|
26
|
+
* @private
|
|
27
|
+
*/
|
|
28
|
+
this._transformationHandler = transformationHandler;
|
|
29
|
+
/**
|
|
30
|
+
* @type {VcsEvent<number>}
|
|
31
|
+
* @private
|
|
32
|
+
*/
|
|
33
|
+
this._extruded = new VcsEvent();
|
|
34
|
+
/**
|
|
35
|
+
* @type {null|function(import("ol/coordinate").Coordinate, import("@vcmap/cesium").Cartesian2):number}
|
|
36
|
+
* @private
|
|
37
|
+
*/
|
|
38
|
+
this._getExtrudeEvent = null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Event raised with the extrusion delta to the last event fired.
|
|
43
|
+
* @type {VcsEvent<number>}
|
|
44
|
+
* @readonly
|
|
45
|
+
*/
|
|
46
|
+
get extruded() {
|
|
47
|
+
return this._extruded;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @param {InteractionEvent} event
|
|
52
|
+
* @returns {Promise<InteractionEvent>}
|
|
53
|
+
*/
|
|
54
|
+
async pipe(event) {
|
|
55
|
+
if (this._getExtrudeEvent) {
|
|
56
|
+
this._extruded.raiseEvent(this._getExtrudeEvent(event.positionOrPixel, event.windowPosition));
|
|
57
|
+
if (event.type === EventType.DRAGEND) {
|
|
58
|
+
this._getExtrudeEvent = null;
|
|
59
|
+
this._transformationHandler.showAxis = AXIS_AND_PLANES.NONE;
|
|
60
|
+
}
|
|
61
|
+
} else if (
|
|
62
|
+
event.type === EventType.DRAGSTART &&
|
|
63
|
+
event?.feature?.[handlerSymbol]
|
|
64
|
+
) {
|
|
65
|
+
const axis = event.feature[handlerSymbol];
|
|
66
|
+
if (axis === AXIS_AND_PLANES.Z) {
|
|
67
|
+
const scene = /** @type {import("@vcmap/core").CesiumMap} */ (event.map).getScene();
|
|
68
|
+
this._transformationHandler.showAxis = axis;
|
|
69
|
+
const plane = createCameraVerticalPlane(this._transformationHandler.center.slice(), scene);
|
|
70
|
+
let currentHeight = getCartographicFromPlane(plane, scene.camera, event.windowPosition).height;
|
|
71
|
+
this._getExtrudeEvent = (c, windowPosition) => {
|
|
72
|
+
const newHeight = getCartographicFromPlane(plane, scene.camera, windowPosition).height;
|
|
73
|
+
const extrude = newHeight - currentHeight;
|
|
74
|
+
currentHeight = newHeight;
|
|
75
|
+
return extrude;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return event;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* @inheritDoc
|
|
84
|
+
*/
|
|
85
|
+
destroy() {
|
|
86
|
+
this._transformationHandler = null;
|
|
87
|
+
this._extruded.destroy();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export default ExtrudeInteraction;
|