@vcmap/core 6.0.7 → 6.1.0-rc.2
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/dist/cesium.d.ts +3 -0
- package/dist/index.d.ts +16 -1
- package/dist/index.js +16 -1
- package/dist/index.js.map +1 -1
- package/dist/ol.d.ts +8 -1
- package/dist/src/featureProvider/featureProviderSymbols.d.ts +5 -0
- package/dist/src/featureProvider/featureProviderSymbols.js +5 -1
- package/dist/src/featureProvider/featureProviderSymbols.js.map +1 -1
- package/dist/src/interaction/featureAtPixelInteraction.js +58 -62
- package/dist/src/interaction/featureAtPixelInteraction.js.map +1 -1
- package/dist/src/interaction/featureProviderInteraction.js +25 -13
- package/dist/src/interaction/featureProviderInteraction.js.map +1 -1
- package/dist/src/layer/cesium/sourceVectorContextSync.d.ts +27 -0
- package/dist/src/layer/cesium/sourceVectorContextSync.js +94 -0
- package/dist/src/layer/cesium/sourceVectorContextSync.js.map +1 -0
- package/dist/src/layer/cesium/vectorCesiumImpl.d.ts +4 -27
- package/dist/src/layer/cesium/vectorCesiumImpl.js +15 -107
- package/dist/src/layer/cesium/vectorCesiumImpl.js.map +1 -1
- package/dist/src/layer/cesium/vectorContext.d.ts +12 -1
- package/dist/src/layer/cesium/vectorContext.js +6 -0
- package/dist/src/layer/cesium/vectorContext.js.map +1 -1
- package/dist/src/layer/layerSymbols.js +1 -1
- package/dist/src/layer/layerSymbols.js.map +1 -1
- package/dist/src/layer/oblique/sourceObliqueSync.d.ts +18 -0
- package/dist/src/layer/oblique/sourceObliqueSync.js +319 -0
- package/dist/src/layer/oblique/sourceObliqueSync.js.map +1 -0
- package/dist/src/layer/oblique/vectorObliqueImpl.d.ts +2 -40
- package/dist/src/layer/oblique/vectorObliqueImpl.js +8 -283
- package/dist/src/layer/oblique/vectorObliqueImpl.js.map +1 -1
- package/dist/src/layer/vectorLayer.d.ts +10 -1
- package/dist/src/layer/vectorLayer.js +23 -1
- package/dist/src/layer/vectorLayer.js.map +1 -1
- package/dist/src/map/baseOLMap.js +8 -1
- package/dist/src/map/baseOLMap.js.map +1 -1
- package/dist/src/map/cesiumMap.d.ts +2 -0
- package/dist/src/map/cesiumMap.js +26 -1
- package/dist/src/map/cesiumMap.js.map +1 -1
- package/dist/src/map/vcsMap.d.ts +24 -12
- package/dist/src/map/vcsMap.js +92 -38
- package/dist/src/map/vcsMap.js.map +1 -1
- package/dist/src/ol/source/ClusterEnhancedVectorSource.d.ts +6 -4
- package/dist/src/ol/source/ClusterEnhancedVectorSource.js +4 -9
- package/dist/src/ol/source/ClusterEnhancedVectorSource.js.map +1 -1
- package/dist/src/ol/source/VcsCluster.d.ts +10 -10
- package/dist/src/ol/source/VcsCluster.js +23 -7
- package/dist/src/ol/source/VcsCluster.js.map +1 -1
- package/dist/src/util/clipping/clippingPolygonHelper.d.ts +7 -0
- package/dist/src/util/clipping/clippingPolygonHelper.js +53 -0
- package/dist/src/util/clipping/clippingPolygonHelper.js.map +1 -0
- package/dist/src/util/clipping/clippingPolygonObject.d.ts +59 -0
- package/dist/src/util/clipping/clippingPolygonObject.js +158 -0
- package/dist/src/util/clipping/clippingPolygonObject.js.map +1 -0
- package/dist/src/util/clipping/clippingPolygonObjectCollection.d.ts +18 -0
- package/dist/src/util/clipping/clippingPolygonObjectCollection.js +167 -0
- package/dist/src/util/clipping/clippingPolygonObjectCollection.js.map +1 -0
- package/dist/src/util/layerCollection.d.ts +11 -1
- package/dist/src/util/layerCollection.js +67 -12
- package/dist/src/util/layerCollection.js.map +1 -1
- package/dist/src/util/mapCollection.d.ts +16 -1
- package/dist/src/util/mapCollection.js +37 -3
- package/dist/src/util/mapCollection.js.map +1 -1
- package/dist/src/util/renderScreenshot.d.ts +9 -0
- package/dist/src/util/renderScreenshot.js +162 -0
- package/dist/src/util/renderScreenshot.js.map +1 -0
- package/dist/src/util/rotation.d.ts +30 -0
- package/dist/src/util/rotation.js +145 -0
- package/dist/src/util/rotation.js.map +1 -0
- package/dist/src/util/vcsTemplate.d.ts +7 -0
- package/dist/src/util/vcsTemplate.js +248 -0
- package/dist/src/util/vcsTemplate.js.map +1 -0
- package/dist/src/vcsApp.d.ts +7 -0
- package/dist/src/vcsApp.js +29 -0
- package/dist/src/vcsApp.js.map +1 -1
- package/dist/src/vcsModule.d.ts +6 -2
- package/dist/src/vcsModule.js.map +1 -1
- package/dist/src/vectorCluster/vectorClusterCesiumContext.d.ts +18 -0
- package/dist/src/{layer/cesium/clusterContext.js → vectorCluster/vectorClusterCesiumContext.js} +28 -42
- package/dist/src/vectorCluster/vectorClusterCesiumContext.js.map +1 -0
- package/dist/src/vectorCluster/vectorClusterGroup.d.ts +96 -0
- package/dist/src/vectorCluster/vectorClusterGroup.js +320 -0
- package/dist/src/vectorCluster/vectorClusterGroup.js.map +1 -0
- package/dist/src/vectorCluster/vectorClusterGroupCesiumImpl.d.ts +20 -0
- package/dist/src/vectorCluster/vectorClusterGroupCesiumImpl.js +115 -0
- package/dist/src/vectorCluster/vectorClusterGroupCesiumImpl.js.map +1 -0
- package/dist/src/vectorCluster/vectorClusterGroupCollection.d.ts +19 -0
- package/dist/src/vectorCluster/vectorClusterGroupCollection.js +37 -0
- package/dist/src/vectorCluster/vectorClusterGroupCollection.js.map +1 -0
- package/dist/src/vectorCluster/vectorClusterGroupImpl.d.ts +31 -0
- package/dist/src/vectorCluster/vectorClusterGroupImpl.js +76 -0
- package/dist/src/vectorCluster/vectorClusterGroupImpl.js.map +1 -0
- package/dist/src/vectorCluster/vectorClusterGroupObliqueImpl.d.ts +17 -0
- package/dist/src/vectorCluster/vectorClusterGroupObliqueImpl.js +62 -0
- package/dist/src/vectorCluster/vectorClusterGroupObliqueImpl.js.map +1 -0
- package/dist/src/vectorCluster/vectorClusterGroupOpenlayersImpl.d.ts +17 -0
- package/dist/src/vectorCluster/vectorClusterGroupOpenlayersImpl.js +62 -0
- package/dist/src/vectorCluster/vectorClusterGroupOpenlayersImpl.js.map +1 -0
- package/dist/src/vectorCluster/vectorClusterStyleItem.d.ts +110 -0
- package/dist/src/vectorCluster/vectorClusterStyleItem.js +374 -0
- package/dist/src/vectorCluster/vectorClusterStyleItem.js.map +1 -0
- package/dist/src/vectorCluster/vectorClusterSymbols.d.ts +1 -0
- package/dist/src/vectorCluster/vectorClusterSymbols.js +3 -0
- package/dist/src/vectorCluster/vectorClusterSymbols.js.map +1 -0
- package/index.ts +42 -1
- package/package.json +3 -1
- package/src/cesium/cesium.d.ts +3 -0
- package/src/featureProvider/featureProviderSymbols.ts +6 -1
- package/src/interaction/featureAtPixelInteraction.ts +109 -84
- package/src/interaction/featureProviderInteraction.ts +42 -28
- package/src/layer/cesium/sourceVectorContextSync.ts +134 -0
- package/src/layer/cesium/vcsTile/vcsDebugTile.ts +1 -1
- package/src/layer/cesium/vcsTile/vcsVectorTile.ts +1 -1
- package/src/layer/cesium/vectorCesiumImpl.ts +30 -144
- package/src/layer/cesium/vectorContext.ts +17 -1
- package/src/layer/layerSymbols.ts +1 -1
- package/src/layer/oblique/sourceObliqueSync.ts +436 -0
- package/src/layer/oblique/vectorObliqueImpl.ts +11 -397
- package/src/layer/vectorLayer.ts +35 -2
- package/src/map/baseOLMap.ts +8 -1
- package/src/map/cesiumMap.ts +36 -3
- package/src/map/vcsMap.ts +121 -47
- package/src/ol/ol.d.ts +8 -1
- package/src/ol/source/{ClusterEnhancedVectorSource.js → ClusterEnhancedVectorSource.ts} +7 -10
- package/src/ol/source/VcsCluster.ts +58 -0
- package/src/util/clipping/clippingPolygonHelper.ts +86 -0
- package/src/util/clipping/clippingPolygonObject.ts +223 -0
- package/src/util/clipping/clippingPolygonObjectCollection.ts +249 -0
- package/src/util/layerCollection.ts +90 -12
- package/src/util/mapCollection.ts +53 -2
- package/src/util/renderScreenshot.ts +193 -0
- package/src/util/rotation.ts +215 -0
- package/src/util/vcsTemplate.ts +373 -0
- package/src/vcsApp.ts +65 -0
- package/src/vcsModule.ts +6 -2
- package/src/vectorCluster/vectorClusterCesiumContext.ts +123 -0
- package/src/vectorCluster/vectorClusterGroup.ts +463 -0
- package/src/vectorCluster/vectorClusterGroupCesiumImpl.ts +176 -0
- package/src/vectorCluster/vectorClusterGroupCollection.ts +43 -0
- package/src/vectorCluster/vectorClusterGroupImpl.ts +107 -0
- package/src/vectorCluster/vectorClusterGroupObliqueImpl.ts +84 -0
- package/src/vectorCluster/vectorClusterGroupOpenlayersImpl.ts +81 -0
- package/src/vectorCluster/vectorClusterStyleItem.ts +490 -0
- package/src/vectorCluster/vectorClusterSymbols.ts +2 -0
- package/dist/src/layer/cesium/clusterContext.d.ts +0 -20
- package/dist/src/layer/cesium/clusterContext.js.map +0 -1
- package/src/layer/cesium/clusterContext.ts +0 -140
- package/src/ol/source/VcsCluster.js +0 -37
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { check, maybe, oneOf } from '@vcsuite/check';
|
|
2
2
|
import { getLogger } from '@vcsuite/logger';
|
|
3
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
3
4
|
import VcsEvent from '../vcsEvent.js';
|
|
4
5
|
import Collection from './collection.js';
|
|
5
6
|
import EventHandler from '../interaction/eventHandler.js';
|
|
@@ -129,6 +130,13 @@ class MapCollection extends Collection<VcsMap> {
|
|
|
129
130
|
// eslint-disable-next-line class-methods-use-this
|
|
130
131
|
private _exclusiveMapControlsRemoved: () => void = () => {};
|
|
131
132
|
|
|
133
|
+
private _exclusiveMapControlsChanged = new VcsEvent<{
|
|
134
|
+
options: DisableMapControlOptions;
|
|
135
|
+
id?: string | symbol;
|
|
136
|
+
}>();
|
|
137
|
+
|
|
138
|
+
private _exclusiveMapControlsId: string | symbol | undefined;
|
|
139
|
+
|
|
132
140
|
constructor() {
|
|
133
141
|
super();
|
|
134
142
|
|
|
@@ -202,6 +210,23 @@ class MapCollection extends Collection<VcsMap> {
|
|
|
202
210
|
return this._postRender;
|
|
203
211
|
}
|
|
204
212
|
|
|
213
|
+
/**
|
|
214
|
+
* Event raised when exclusive map controls are changed. If the Id is empty the default map controls have been reinstated
|
|
215
|
+
*/
|
|
216
|
+
get exclusiveMapControlsChanged(): VcsEvent<{
|
|
217
|
+
options: DisableMapControlOptions;
|
|
218
|
+
id?: string | symbol;
|
|
219
|
+
}> {
|
|
220
|
+
return this._exclusiveMapControlsChanged;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* The id of the current exclusive map controls owner.
|
|
225
|
+
*/
|
|
226
|
+
get exclusiveMapControlsId(): string | symbol | undefined {
|
|
227
|
+
return this._exclusiveMapControlsId;
|
|
228
|
+
}
|
|
229
|
+
|
|
205
230
|
/**
|
|
206
231
|
* Adds a map to the collection. This will set the collections target
|
|
207
232
|
* and the collections on the map.
|
|
@@ -399,30 +424,56 @@ class MapCollection extends Collection<VcsMap> {
|
|
|
399
424
|
* Manages the disabling of map navigation controls. By calling this function the map navigation controls passed in the options are disabled. The remove function passed by the previous caller is executed.
|
|
400
425
|
* @param options - which of the movement controls should be disabled.
|
|
401
426
|
* @param removed - the callback for when the interaction is forcefully removed.
|
|
427
|
+
* @param id - an optional id to identify the owner of the exclusive map controls.
|
|
402
428
|
* @returns function to reset map controls.
|
|
403
429
|
*/
|
|
404
430
|
requestExclusiveMapControls(
|
|
405
431
|
options: DisableMapControlOptions,
|
|
406
432
|
removed: () => void,
|
|
433
|
+
id?: string | symbol,
|
|
407
434
|
): () => void {
|
|
408
435
|
this._exclusiveMapControlsRemoved();
|
|
409
436
|
if (this._activeMap) {
|
|
410
437
|
this._activeMap.disableMovement(options);
|
|
411
438
|
}
|
|
412
439
|
|
|
413
|
-
|
|
440
|
+
if (options.pointerEvents || options.keyEvents || options.apiCalls) {
|
|
441
|
+
this._exclusiveMapControlsId = id || uuidv4();
|
|
442
|
+
this._exclusiveMapControlsRemoved = removed;
|
|
443
|
+
} else {
|
|
444
|
+
this._exclusiveMapControlsRemoved = (): void => {};
|
|
445
|
+
this._exclusiveMapControlsId = undefined;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
this._exclusiveMapControlsChanged.raiseEvent({
|
|
449
|
+
options,
|
|
450
|
+
id: this._exclusiveMapControlsId,
|
|
451
|
+
});
|
|
414
452
|
|
|
415
453
|
return () => {
|
|
416
454
|
// only reset if this function is called by the current exclusiveMapControls owner.
|
|
417
455
|
if (removed === this._exclusiveMapControlsRemoved) {
|
|
418
|
-
this._exclusiveMapControlsRemoved = (): void => {};
|
|
419
456
|
if (this._activeMap) {
|
|
420
457
|
this._activeMap.disableMovement(false);
|
|
421
458
|
}
|
|
459
|
+
|
|
460
|
+
this._exclusiveMapControlsRemoved = (): void => {};
|
|
461
|
+
this._exclusiveMapControlsId = undefined;
|
|
462
|
+
|
|
463
|
+
this._exclusiveMapControlsChanged.raiseEvent({
|
|
464
|
+
options: { apiCalls: false, keyEvents: false, pointerEvents: false },
|
|
465
|
+
});
|
|
422
466
|
}
|
|
423
467
|
};
|
|
424
468
|
}
|
|
425
469
|
|
|
470
|
+
resetExclusiveMapControls(): void {
|
|
471
|
+
this.requestExclusiveMapControls(
|
|
472
|
+
{ keyEvents: false, apiCalls: false, pointerEvents: false },
|
|
473
|
+
() => {},
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
|
|
426
477
|
destroy(): void {
|
|
427
478
|
super.destroy();
|
|
428
479
|
[...this._layerCollection].forEach((l) => {
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { Size } from 'ol/size.js';
|
|
2
|
+
import { getLogger } from '@vcsuite/logger';
|
|
3
|
+
import CesiumMap from '../map/cesiumMap.js';
|
|
4
|
+
import OpenlayersMap from '../map/openlayersMap.js';
|
|
5
|
+
import ObliqueMap from '../map/obliqueMap.js';
|
|
6
|
+
import VcsApp from '../vcsApp.js';
|
|
7
|
+
/**
|
|
8
|
+
* Prepares the cesium map for the screenshot
|
|
9
|
+
* @param map - The cesium map
|
|
10
|
+
* @param scale - The factor to scale the map according to the required resolution
|
|
11
|
+
* @returns The function to reset the applied scale.
|
|
12
|
+
*/
|
|
13
|
+
function prepareCesiumMap(map: CesiumMap, scale: number): () => void {
|
|
14
|
+
const viewer = map.getCesiumWidget()!;
|
|
15
|
+
const { resolutionScale } = viewer;
|
|
16
|
+
viewer.resolutionScale = scale;
|
|
17
|
+
|
|
18
|
+
return function resetCesiumMap() {
|
|
19
|
+
viewer.resolutionScale = resolutionScale;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Returns a function to reset the OLMap to the original state.
|
|
25
|
+
* @param map - The map instance.
|
|
26
|
+
* @param renderSize - The size to set for rendering.
|
|
27
|
+
* @returns The function to reset the map.
|
|
28
|
+
*/
|
|
29
|
+
function prepareOlMap(
|
|
30
|
+
map: OpenlayersMap | ObliqueMap,
|
|
31
|
+
renderSize: Size,
|
|
32
|
+
): () => void {
|
|
33
|
+
const { olMap } = map;
|
|
34
|
+
if (olMap) {
|
|
35
|
+
const olSize = olMap.getSize();
|
|
36
|
+
const extent = olMap.getView().calculateExtent(olSize);
|
|
37
|
+
const originalMinZoom = olMap.getView().getMinZoom();
|
|
38
|
+
const originalMaxZoom = olMap.getView().getMaxZoom();
|
|
39
|
+
olMap.setSize(renderSize);
|
|
40
|
+
olMap.getView().setMinZoom(0);
|
|
41
|
+
olMap.getView().setMaxZoom(28);
|
|
42
|
+
olMap.getView().fit(extent, { size: renderSize });
|
|
43
|
+
olMap.set('vcs_scale', renderSize, true);
|
|
44
|
+
|
|
45
|
+
return function resetOlMap() {
|
|
46
|
+
olMap.setSize(olSize);
|
|
47
|
+
olMap.getView().setMinZoom(originalMinZoom);
|
|
48
|
+
olMap.getView().setMaxZoom(originalMaxZoom);
|
|
49
|
+
olMap.getView().fit(extent, { size: olSize });
|
|
50
|
+
olMap.unset('vcs_scale', true);
|
|
51
|
+
olMap.renderSync();
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
return () => {};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Copies Cesium content on the given canvas.
|
|
59
|
+
* @param map - The Cesium map instance.
|
|
60
|
+
* @returns A promise that resolves to the canvas element.
|
|
61
|
+
*/
|
|
62
|
+
async function getImageFromCesium(map: CesiumMap): Promise<HTMLCanvasElement> {
|
|
63
|
+
const { scene } = map.getCesiumWidget()!;
|
|
64
|
+
|
|
65
|
+
return new Promise((resolve) => {
|
|
66
|
+
const removePreListener = scene.preUpdate.addEventListener(() => {
|
|
67
|
+
const { canvas } = scene;
|
|
68
|
+
const removePostListener = scene.postRender.addEventListener(() => {
|
|
69
|
+
resolve(canvas);
|
|
70
|
+
removePostListener();
|
|
71
|
+
});
|
|
72
|
+
removePreListener();
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Copies Openlayers content on the given canvas
|
|
79
|
+
* @param map - The map instance.
|
|
80
|
+
* @param canvasSize - The size of the canvas.
|
|
81
|
+
* @returns A promise that resolves to the canvas element.
|
|
82
|
+
*/
|
|
83
|
+
async function getImageFromOpenlayers(
|
|
84
|
+
map: OpenlayersMap | ObliqueMap,
|
|
85
|
+
canvasSize: Size,
|
|
86
|
+
): Promise<HTMLCanvasElement> {
|
|
87
|
+
const canvas = document.createElement('canvas');
|
|
88
|
+
canvas.width = canvasSize[0];
|
|
89
|
+
canvas.height = canvasSize[1];
|
|
90
|
+
const { olMap } = map;
|
|
91
|
+
const canvasContext = canvas.getContext('2d')!;
|
|
92
|
+
// fill canvas with white so transparent pixels are not printed as black when exporting as jpeg.
|
|
93
|
+
canvasContext.fillStyle = 'white';
|
|
94
|
+
canvasContext.fillRect(0, 0, canvas.width, canvas.height);
|
|
95
|
+
await new Promise<void>((resolve) => {
|
|
96
|
+
if (olMap) {
|
|
97
|
+
olMap.once('rendercomplete', () => {
|
|
98
|
+
const olLayerCanvasList = Array.from(
|
|
99
|
+
olMap
|
|
100
|
+
.getViewport()
|
|
101
|
+
.querySelectorAll<HTMLCanvasElement>('.ol-layer canvas'),
|
|
102
|
+
);
|
|
103
|
+
olLayerCanvasList.forEach((layerCanvas) => {
|
|
104
|
+
if (layerCanvas.width > 0) {
|
|
105
|
+
const opacity =
|
|
106
|
+
(layerCanvas.parentNode instanceof HTMLElement
|
|
107
|
+
? layerCanvas.parentNode.style.opacity
|
|
108
|
+
: '') || layerCanvas.style.opacity;
|
|
109
|
+
canvasContext.globalAlpha = opacity === '' ? 1 : Number(opacity);
|
|
110
|
+
const { transform } = layerCanvas.style;
|
|
111
|
+
const matrix = transform
|
|
112
|
+
.match(/^matrix\(([^(]*)\)$/)?.[1]
|
|
113
|
+
.split(',')
|
|
114
|
+
.map(Number) as
|
|
115
|
+
| [number, number, number, number, number, number]
|
|
116
|
+
| undefined;
|
|
117
|
+
if (matrix) {
|
|
118
|
+
canvasContext.setTransform(...matrix);
|
|
119
|
+
}
|
|
120
|
+
canvasContext.drawImage(layerCanvas, 0, 0);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
resolve();
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
return canvas;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Renders a screenshot of the active map in the VcsApp.
|
|
132
|
+
*
|
|
133
|
+
* @param app - The VcsApp instance containing the active map.
|
|
134
|
+
* @param width - The desired width of the screenshot.
|
|
135
|
+
* @returns A promise that resolves to the canvas element containing the screenshot.
|
|
136
|
+
*/
|
|
137
|
+
export default async function renderScreenshot(
|
|
138
|
+
app: VcsApp,
|
|
139
|
+
width: number,
|
|
140
|
+
): Promise<HTMLCanvasElement> {
|
|
141
|
+
let screenshotCanvas: HTMLCanvasElement;
|
|
142
|
+
|
|
143
|
+
function calcRenderSize(mapSize: Size, screenshotWidth: number): Size {
|
|
144
|
+
const aspectRatio = mapSize[0] / mapSize[1];
|
|
145
|
+
return [screenshotWidth, screenshotWidth / aspectRatio];
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function checkChromeMaxPixel(renderSize: Size, threshold: number): void {
|
|
149
|
+
const totalPixelCount = renderSize[0] * renderSize[1];
|
|
150
|
+
if (totalPixelCount > threshold && 'chrome' in window) {
|
|
151
|
+
getLogger('@vcmap/print').warning(
|
|
152
|
+
`The created image might have black bars at some of the edges. This is due to a behavior of chromium based browsers
|
|
153
|
+
that occurs when the total pixel count of the cesium map exceeds a threshold of thirty-three million pixels.
|
|
154
|
+
In order to avoid this either reduce the resolution or switch to Mozilla Firefox browser.`,
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Function for resetting map after screenshot processes finished.
|
|
160
|
+
*/
|
|
161
|
+
let resetMap: () => void;
|
|
162
|
+
const map = app.maps.activeMap;
|
|
163
|
+
|
|
164
|
+
if (map instanceof CesiumMap) {
|
|
165
|
+
const { canvas } = map.getCesiumWidget()!.scene;
|
|
166
|
+
const canvasWidth = canvas.width;
|
|
167
|
+
const canvasHeight = canvas.height;
|
|
168
|
+
|
|
169
|
+
// check if render size is above chromium threshold
|
|
170
|
+
checkChromeMaxPixel(
|
|
171
|
+
calcRenderSize([canvasWidth, canvasHeight], width),
|
|
172
|
+
33000000,
|
|
173
|
+
);
|
|
174
|
+
const scale = width / canvasWidth;
|
|
175
|
+
resetMap = prepareCesiumMap(map, scale);
|
|
176
|
+
screenshotCanvas = await getImageFromCesium(map);
|
|
177
|
+
} else if (map instanceof OpenlayersMap || map instanceof ObliqueMap) {
|
|
178
|
+
const biggestCanvas = Array.from(
|
|
179
|
+
map
|
|
180
|
+
.olMap!.getViewport()
|
|
181
|
+
.querySelectorAll<HTMLCanvasElement>('.ol-layer canvas'),
|
|
182
|
+
).reduce((acc, val) => (acc.width > val.width ? val : acc));
|
|
183
|
+
const canvasWidth = biggestCanvas.width;
|
|
184
|
+
const canvasHeight = biggestCanvas.height;
|
|
185
|
+
const renderSize = calcRenderSize([canvasWidth, canvasHeight], width);
|
|
186
|
+
resetMap = prepareOlMap(map, renderSize);
|
|
187
|
+
screenshotCanvas = await getImageFromOpenlayers(map, renderSize);
|
|
188
|
+
} else {
|
|
189
|
+
throw new Error('wrong Map');
|
|
190
|
+
}
|
|
191
|
+
resetMap();
|
|
192
|
+
return screenshotCanvas;
|
|
193
|
+
}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Camera,
|
|
3
|
+
Cartesian2,
|
|
4
|
+
Cartesian3,
|
|
5
|
+
Cartographic,
|
|
6
|
+
Math as CesiumMath,
|
|
7
|
+
JulianDate,
|
|
8
|
+
HeadingPitchRollValues,
|
|
9
|
+
} from '@vcmap-cesium/engine';
|
|
10
|
+
import Viewpoint from './viewpoint.js';
|
|
11
|
+
import VcsApp from '../vcsApp.js';
|
|
12
|
+
import { CesiumMap } from '../../index.js';
|
|
13
|
+
import Projection from './projection.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Unique symbol for rotation.
|
|
17
|
+
* @type {symbol}
|
|
18
|
+
*/
|
|
19
|
+
export const rotationMapControlSymbol: unique symbol = Symbol(
|
|
20
|
+
'rotationMapControlSymbol',
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
export type SetViewOptions = {
|
|
24
|
+
destination: Cartesian3;
|
|
25
|
+
orientation: HeadingPitchRollValues;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Rotates the camera to a specified viewpoint.
|
|
30
|
+
* @param {SetViewOptions} options - The options for setting the view.
|
|
31
|
+
* @param {number} [distance] - The distance to move backward.
|
|
32
|
+
* @param {CesiumMap} activeMap - The active map instance.
|
|
33
|
+
*/
|
|
34
|
+
function setUpdatedPosition(
|
|
35
|
+
options: SetViewOptions,
|
|
36
|
+
distance: number | undefined,
|
|
37
|
+
activeMap: CesiumMap,
|
|
38
|
+
): void {
|
|
39
|
+
let cameraPosition: Cartesian3;
|
|
40
|
+
|
|
41
|
+
const clonedCamera = new Camera(activeMap.getCesiumWidget()!.scene);
|
|
42
|
+
|
|
43
|
+
clonedCamera.setView(options);
|
|
44
|
+
clonedCamera.moveBackward(distance);
|
|
45
|
+
|
|
46
|
+
cameraPosition = clonedCamera.position;
|
|
47
|
+
|
|
48
|
+
const cam = activeMap.getCesiumWidget()!.scene.camera;
|
|
49
|
+
const cameraOptions = {
|
|
50
|
+
heading: options.orientation.heading,
|
|
51
|
+
pitch: options.orientation.pitch,
|
|
52
|
+
roll: options.orientation.roll,
|
|
53
|
+
};
|
|
54
|
+
cameraPosition = cameraPosition || null;
|
|
55
|
+
cam.cancelFlight();
|
|
56
|
+
|
|
57
|
+
cam.setView({
|
|
58
|
+
destination: cameraPosition,
|
|
59
|
+
orientation: cameraOptions,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Rotates the center of the map.
|
|
65
|
+
* @param {number} heading - The current heading of the view.
|
|
66
|
+
* @param {CesiumMap} activeMap - The current Cesium Map.
|
|
67
|
+
* @param {number} timePerRotation - The current rotation speed.
|
|
68
|
+
* @param {JulianDate} [timeLastTick] - The time of the last tick.
|
|
69
|
+
* @returns {number | undefined} The new heading.
|
|
70
|
+
*/
|
|
71
|
+
export function calculateRotation(
|
|
72
|
+
heading: number,
|
|
73
|
+
activeMap: CesiumMap,
|
|
74
|
+
timePerRotation: number,
|
|
75
|
+
timeLastTick?: JulianDate,
|
|
76
|
+
): number {
|
|
77
|
+
let localHeading = heading;
|
|
78
|
+
|
|
79
|
+
const { clock } = activeMap.getCesiumWidget()!;
|
|
80
|
+
let timeDifference = timeLastTick
|
|
81
|
+
? clock.currentTime.secondsOfDay - timeLastTick.secondsOfDay
|
|
82
|
+
: 1 / 60;
|
|
83
|
+
if (timeDifference <= 0 || timeDifference > 1) {
|
|
84
|
+
timeDifference = 1 / 60;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const timeFactor = timeDifference / (1 / 60);
|
|
88
|
+
const headingDiff = CesiumMath.TWO_PI / ((timePerRotation * 60) / timeFactor);
|
|
89
|
+
localHeading += headingDiff;
|
|
90
|
+
localHeading = CesiumMath.zeroToTwoPi(localHeading);
|
|
91
|
+
return localHeading;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Starts the rotation of the map.
|
|
96
|
+
* @param app - The VCS application instance.
|
|
97
|
+
* @param [viewpoint] - The optional viewpoint to start the rotation from, if no viewpoint is provided the current Viewpoint is used.
|
|
98
|
+
* @param [timePerRotation=60] - The duration of a single full rotation in seconds.
|
|
99
|
+
* @returns A function to stop the rotation.
|
|
100
|
+
*/
|
|
101
|
+
export async function startRotation(
|
|
102
|
+
app: VcsApp,
|
|
103
|
+
viewpoint?: Viewpoint,
|
|
104
|
+
timePerRotation = 60,
|
|
105
|
+
): Promise<() => void> {
|
|
106
|
+
const { activeMap } = app.maps;
|
|
107
|
+
|
|
108
|
+
let localViewpoint: Viewpoint | undefined;
|
|
109
|
+
|
|
110
|
+
let rotationListener: (() => void) | undefined;
|
|
111
|
+
let resetMapControls: (() => void) | undefined;
|
|
112
|
+
|
|
113
|
+
const stopRotation: () => void = () => {
|
|
114
|
+
if (rotationListener) {
|
|
115
|
+
rotationListener();
|
|
116
|
+
rotationListener = undefined;
|
|
117
|
+
}
|
|
118
|
+
if (resetMapControls) {
|
|
119
|
+
resetMapControls();
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
if (activeMap instanceof CesiumMap) {
|
|
124
|
+
const scene = activeMap.getScene();
|
|
125
|
+
if (scene) {
|
|
126
|
+
if (!(viewpoint instanceof Viewpoint)) {
|
|
127
|
+
localViewpoint = activeMap.getViewpointSync() || undefined;
|
|
128
|
+
} else {
|
|
129
|
+
localViewpoint = viewpoint.clone();
|
|
130
|
+
}
|
|
131
|
+
if (localViewpoint) {
|
|
132
|
+
if (!localViewpoint.animate) {
|
|
133
|
+
localViewpoint.animate = true;
|
|
134
|
+
|
|
135
|
+
localViewpoint.duration = 0.00000001;
|
|
136
|
+
}
|
|
137
|
+
await activeMap.gotoViewpoint(localViewpoint);
|
|
138
|
+
|
|
139
|
+
const newCenter = scene.pickPosition(
|
|
140
|
+
new Cartesian2(scene.canvas.width / 2, scene.canvas.height / 2),
|
|
141
|
+
);
|
|
142
|
+
if (newCenter) {
|
|
143
|
+
const cartographic = Cartographic.fromCartesian(newCenter);
|
|
144
|
+
localViewpoint.groundPosition = [
|
|
145
|
+
CesiumMath.toDegrees(cartographic.longitude),
|
|
146
|
+
CesiumMath.toDegrees(cartographic.latitude),
|
|
147
|
+
cartographic.height,
|
|
148
|
+
];
|
|
149
|
+
localViewpoint.distance = Cartesian3.distance(
|
|
150
|
+
newCenter,
|
|
151
|
+
scene.camera.position,
|
|
152
|
+
);
|
|
153
|
+
} else {
|
|
154
|
+
throw new Error('new ground position could not be determined');
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const { distance } = localViewpoint;
|
|
158
|
+
const heading = CesiumMath.toRadians(localViewpoint.heading);
|
|
159
|
+
const pitch = CesiumMath.toRadians(localViewpoint.pitch);
|
|
160
|
+
const roll = CesiumMath.toRadians(localViewpoint.roll);
|
|
161
|
+
|
|
162
|
+
const groundPositionCoords = localViewpoint.groundPosition;
|
|
163
|
+
if (!groundPositionCoords[2]) {
|
|
164
|
+
const positions = await activeMap.getHeightFromTerrain([
|
|
165
|
+
Projection.wgs84ToMercator(groundPositionCoords),
|
|
166
|
+
]);
|
|
167
|
+
groundPositionCoords[2] = positions[0][2];
|
|
168
|
+
}
|
|
169
|
+
const groundPosition = Cartesian3.fromDegrees(
|
|
170
|
+
groundPositionCoords[0],
|
|
171
|
+
groundPositionCoords[1],
|
|
172
|
+
groundPositionCoords[2],
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
const options = {
|
|
176
|
+
destination: groundPosition,
|
|
177
|
+
orientation: {
|
|
178
|
+
heading,
|
|
179
|
+
pitch,
|
|
180
|
+
roll,
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
let timeLastTick: JulianDate | undefined;
|
|
185
|
+
|
|
186
|
+
resetMapControls = app.maps.requestExclusiveMapControls(
|
|
187
|
+
{ apiCalls: true, keyEvents: true, pointerEvents: true },
|
|
188
|
+
stopRotation,
|
|
189
|
+
rotationMapControlSymbol,
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
rotationListener = activeMap
|
|
193
|
+
.getCesiumWidget()!
|
|
194
|
+
.scene.postRender.addEventListener(() => {
|
|
195
|
+
options.orientation.heading = calculateRotation(
|
|
196
|
+
options.orientation.heading,
|
|
197
|
+
activeMap,
|
|
198
|
+
timePerRotation,
|
|
199
|
+
timeLastTick,
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
if (options) {
|
|
203
|
+
setUpdatedPosition(options, distance, activeMap);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
timeLastTick = activeMap.getCesiumWidget()!.clock.currentTime;
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return (): void => {
|
|
213
|
+
stopRotation();
|
|
214
|
+
};
|
|
215
|
+
}
|