@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.
Files changed (53) hide show
  1. package/index.d.ts +597 -98
  2. package/index.js +24 -9
  3. package/package.json +2 -2
  4. package/src/category/category.js +1 -1
  5. package/src/featureProvider/abstractFeatureProvider.js +1 -18
  6. package/src/interaction/eventHandler.js +14 -0
  7. package/src/layer/cesium/clusterContext.js +12 -0
  8. package/src/layer/cesium/vectorCesiumImpl.js +2 -2
  9. package/src/layer/cesium/vectorContext.js +115 -7
  10. package/src/layer/cesiumTilesetLayer.js +0 -14
  11. package/src/layer/czmlLayer.js +1 -1
  12. package/src/layer/dataSourceLayer.js +1 -53
  13. package/src/layer/featureLayer.js +0 -44
  14. package/src/layer/featureStoreLayer.js +0 -15
  15. package/src/layer/layer.js +0 -11
  16. package/src/layer/vectorHelpers.js +0 -85
  17. package/src/layer/vectorLayer.js +0 -9
  18. package/src/layer/vectorProperties.js +150 -8
  19. package/src/layer/vectorTileLayer.js +0 -9
  20. package/src/map/cesiumMap.js +26 -7
  21. package/src/style/arcStyle.js +316 -0
  22. package/src/style/arrowStyle.js +269 -0
  23. package/src/util/editor/createFeatureSession.js +3 -1
  24. package/src/util/editor/editFeaturesSession.js +315 -0
  25. package/src/util/editor/editGeometrySession.js +5 -1
  26. package/src/util/editor/editorHelpers.js +118 -14
  27. package/src/util/editor/editorSessionHelpers.js +12 -0
  28. package/src/util/editor/editorSymbols.js +6 -0
  29. package/src/util/editor/interactions/editFeaturesMouseOverInteraction.js +120 -0
  30. package/src/util/editor/interactions/editGeometryMouseOverInteraction.js +1 -3
  31. package/src/util/editor/interactions/ensureHandlerSelectionInteraction.js +48 -0
  32. package/src/util/editor/interactions/mapInteractionController.js +5 -2
  33. package/src/util/editor/interactions/selectMultiFeatureInteraction.js +146 -0
  34. package/src/util/editor/interactions/translateVertexInteraction.js +2 -2
  35. package/src/util/editor/transformation/create2DHandlers.js +294 -0
  36. package/src/util/editor/transformation/create3DHandlers.js +575 -0
  37. package/src/util/editor/transformation/extrudeInteraction.js +91 -0
  38. package/src/util/editor/transformation/rotateInteraction.js +188 -0
  39. package/src/util/editor/transformation/scaleInteraction.js +185 -0
  40. package/src/util/editor/transformation/transformationHandler.js +168 -0
  41. package/src/util/editor/transformation/transformationTypes.js +83 -0
  42. package/src/util/editor/transformation/translateInteraction.js +209 -0
  43. package/src/util/featureconverter/arcToCesium.js +87 -0
  44. package/src/util/featureconverter/convert.js +7 -1
  45. package/src/util/featureconverter/extent3D.js +64 -1
  46. package/src/util/featureconverter/lineStringToCesium.js +103 -2
  47. package/src/util/featureconverter/pointHelpers.js +341 -0
  48. package/src/util/featureconverter/pointToCesium.js +27 -76
  49. package/src/util/geometryHelpers.js +11 -8
  50. package/src/util/math.js +99 -2
  51. package/tests/unit/helpers/cesiumHelpers.js +14 -4
  52. package/tests/unit/helpers/helpers.js +13 -0
  53. 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;