@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.
Files changed (146) hide show
  1. package/dist/cesium.d.ts +3 -0
  2. package/dist/index.d.ts +16 -1
  3. package/dist/index.js +16 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/ol.d.ts +8 -1
  6. package/dist/src/featureProvider/featureProviderSymbols.d.ts +5 -0
  7. package/dist/src/featureProvider/featureProviderSymbols.js +5 -1
  8. package/dist/src/featureProvider/featureProviderSymbols.js.map +1 -1
  9. package/dist/src/interaction/featureAtPixelInteraction.js +58 -62
  10. package/dist/src/interaction/featureAtPixelInteraction.js.map +1 -1
  11. package/dist/src/interaction/featureProviderInteraction.js +25 -13
  12. package/dist/src/interaction/featureProviderInteraction.js.map +1 -1
  13. package/dist/src/layer/cesium/sourceVectorContextSync.d.ts +27 -0
  14. package/dist/src/layer/cesium/sourceVectorContextSync.js +94 -0
  15. package/dist/src/layer/cesium/sourceVectorContextSync.js.map +1 -0
  16. package/dist/src/layer/cesium/vectorCesiumImpl.d.ts +4 -27
  17. package/dist/src/layer/cesium/vectorCesiumImpl.js +15 -107
  18. package/dist/src/layer/cesium/vectorCesiumImpl.js.map +1 -1
  19. package/dist/src/layer/cesium/vectorContext.d.ts +12 -1
  20. package/dist/src/layer/cesium/vectorContext.js +6 -0
  21. package/dist/src/layer/cesium/vectorContext.js.map +1 -1
  22. package/dist/src/layer/layerSymbols.js +1 -1
  23. package/dist/src/layer/layerSymbols.js.map +1 -1
  24. package/dist/src/layer/oblique/sourceObliqueSync.d.ts +18 -0
  25. package/dist/src/layer/oblique/sourceObliqueSync.js +319 -0
  26. package/dist/src/layer/oblique/sourceObliqueSync.js.map +1 -0
  27. package/dist/src/layer/oblique/vectorObliqueImpl.d.ts +2 -40
  28. package/dist/src/layer/oblique/vectorObliqueImpl.js +8 -283
  29. package/dist/src/layer/oblique/vectorObliqueImpl.js.map +1 -1
  30. package/dist/src/layer/vectorLayer.d.ts +10 -1
  31. package/dist/src/layer/vectorLayer.js +23 -1
  32. package/dist/src/layer/vectorLayer.js.map +1 -1
  33. package/dist/src/map/baseOLMap.js +8 -1
  34. package/dist/src/map/baseOLMap.js.map +1 -1
  35. package/dist/src/map/cesiumMap.d.ts +2 -0
  36. package/dist/src/map/cesiumMap.js +26 -1
  37. package/dist/src/map/cesiumMap.js.map +1 -1
  38. package/dist/src/map/vcsMap.d.ts +24 -12
  39. package/dist/src/map/vcsMap.js +92 -38
  40. package/dist/src/map/vcsMap.js.map +1 -1
  41. package/dist/src/ol/source/ClusterEnhancedVectorSource.d.ts +6 -4
  42. package/dist/src/ol/source/ClusterEnhancedVectorSource.js +4 -9
  43. package/dist/src/ol/source/ClusterEnhancedVectorSource.js.map +1 -1
  44. package/dist/src/ol/source/VcsCluster.d.ts +10 -10
  45. package/dist/src/ol/source/VcsCluster.js +23 -7
  46. package/dist/src/ol/source/VcsCluster.js.map +1 -1
  47. package/dist/src/util/clipping/clippingPolygonHelper.d.ts +7 -0
  48. package/dist/src/util/clipping/clippingPolygonHelper.js +53 -0
  49. package/dist/src/util/clipping/clippingPolygonHelper.js.map +1 -0
  50. package/dist/src/util/clipping/clippingPolygonObject.d.ts +59 -0
  51. package/dist/src/util/clipping/clippingPolygonObject.js +158 -0
  52. package/dist/src/util/clipping/clippingPolygonObject.js.map +1 -0
  53. package/dist/src/util/clipping/clippingPolygonObjectCollection.d.ts +18 -0
  54. package/dist/src/util/clipping/clippingPolygonObjectCollection.js +167 -0
  55. package/dist/src/util/clipping/clippingPolygonObjectCollection.js.map +1 -0
  56. package/dist/src/util/layerCollection.d.ts +11 -1
  57. package/dist/src/util/layerCollection.js +67 -12
  58. package/dist/src/util/layerCollection.js.map +1 -1
  59. package/dist/src/util/mapCollection.d.ts +16 -1
  60. package/dist/src/util/mapCollection.js +37 -3
  61. package/dist/src/util/mapCollection.js.map +1 -1
  62. package/dist/src/util/renderScreenshot.d.ts +9 -0
  63. package/dist/src/util/renderScreenshot.js +162 -0
  64. package/dist/src/util/renderScreenshot.js.map +1 -0
  65. package/dist/src/util/rotation.d.ts +30 -0
  66. package/dist/src/util/rotation.js +145 -0
  67. package/dist/src/util/rotation.js.map +1 -0
  68. package/dist/src/util/vcsTemplate.d.ts +7 -0
  69. package/dist/src/util/vcsTemplate.js +248 -0
  70. package/dist/src/util/vcsTemplate.js.map +1 -0
  71. package/dist/src/vcsApp.d.ts +7 -0
  72. package/dist/src/vcsApp.js +29 -0
  73. package/dist/src/vcsApp.js.map +1 -1
  74. package/dist/src/vcsModule.d.ts +6 -2
  75. package/dist/src/vcsModule.js.map +1 -1
  76. package/dist/src/vectorCluster/vectorClusterCesiumContext.d.ts +18 -0
  77. package/dist/src/{layer/cesium/clusterContext.js → vectorCluster/vectorClusterCesiumContext.js} +28 -42
  78. package/dist/src/vectorCluster/vectorClusterCesiumContext.js.map +1 -0
  79. package/dist/src/vectorCluster/vectorClusterGroup.d.ts +96 -0
  80. package/dist/src/vectorCluster/vectorClusterGroup.js +320 -0
  81. package/dist/src/vectorCluster/vectorClusterGroup.js.map +1 -0
  82. package/dist/src/vectorCluster/vectorClusterGroupCesiumImpl.d.ts +20 -0
  83. package/dist/src/vectorCluster/vectorClusterGroupCesiumImpl.js +115 -0
  84. package/dist/src/vectorCluster/vectorClusterGroupCesiumImpl.js.map +1 -0
  85. package/dist/src/vectorCluster/vectorClusterGroupCollection.d.ts +19 -0
  86. package/dist/src/vectorCluster/vectorClusterGroupCollection.js +37 -0
  87. package/dist/src/vectorCluster/vectorClusterGroupCollection.js.map +1 -0
  88. package/dist/src/vectorCluster/vectorClusterGroupImpl.d.ts +31 -0
  89. package/dist/src/vectorCluster/vectorClusterGroupImpl.js +76 -0
  90. package/dist/src/vectorCluster/vectorClusterGroupImpl.js.map +1 -0
  91. package/dist/src/vectorCluster/vectorClusterGroupObliqueImpl.d.ts +17 -0
  92. package/dist/src/vectorCluster/vectorClusterGroupObliqueImpl.js +62 -0
  93. package/dist/src/vectorCluster/vectorClusterGroupObliqueImpl.js.map +1 -0
  94. package/dist/src/vectorCluster/vectorClusterGroupOpenlayersImpl.d.ts +17 -0
  95. package/dist/src/vectorCluster/vectorClusterGroupOpenlayersImpl.js +62 -0
  96. package/dist/src/vectorCluster/vectorClusterGroupOpenlayersImpl.js.map +1 -0
  97. package/dist/src/vectorCluster/vectorClusterStyleItem.d.ts +110 -0
  98. package/dist/src/vectorCluster/vectorClusterStyleItem.js +374 -0
  99. package/dist/src/vectorCluster/vectorClusterStyleItem.js.map +1 -0
  100. package/dist/src/vectorCluster/vectorClusterSymbols.d.ts +1 -0
  101. package/dist/src/vectorCluster/vectorClusterSymbols.js +3 -0
  102. package/dist/src/vectorCluster/vectorClusterSymbols.js.map +1 -0
  103. package/index.ts +42 -1
  104. package/package.json +3 -1
  105. package/src/cesium/cesium.d.ts +3 -0
  106. package/src/featureProvider/featureProviderSymbols.ts +6 -1
  107. package/src/interaction/featureAtPixelInteraction.ts +109 -84
  108. package/src/interaction/featureProviderInteraction.ts +42 -28
  109. package/src/layer/cesium/sourceVectorContextSync.ts +134 -0
  110. package/src/layer/cesium/vcsTile/vcsDebugTile.ts +1 -1
  111. package/src/layer/cesium/vcsTile/vcsVectorTile.ts +1 -1
  112. package/src/layer/cesium/vectorCesiumImpl.ts +30 -144
  113. package/src/layer/cesium/vectorContext.ts +17 -1
  114. package/src/layer/layerSymbols.ts +1 -1
  115. package/src/layer/oblique/sourceObliqueSync.ts +436 -0
  116. package/src/layer/oblique/vectorObliqueImpl.ts +11 -397
  117. package/src/layer/vectorLayer.ts +35 -2
  118. package/src/map/baseOLMap.ts +8 -1
  119. package/src/map/cesiumMap.ts +36 -3
  120. package/src/map/vcsMap.ts +121 -47
  121. package/src/ol/ol.d.ts +8 -1
  122. package/src/ol/source/{ClusterEnhancedVectorSource.js → ClusterEnhancedVectorSource.ts} +7 -10
  123. package/src/ol/source/VcsCluster.ts +58 -0
  124. package/src/util/clipping/clippingPolygonHelper.ts +86 -0
  125. package/src/util/clipping/clippingPolygonObject.ts +223 -0
  126. package/src/util/clipping/clippingPolygonObjectCollection.ts +249 -0
  127. package/src/util/layerCollection.ts +90 -12
  128. package/src/util/mapCollection.ts +53 -2
  129. package/src/util/renderScreenshot.ts +193 -0
  130. package/src/util/rotation.ts +215 -0
  131. package/src/util/vcsTemplate.ts +373 -0
  132. package/src/vcsApp.ts +65 -0
  133. package/src/vcsModule.ts +6 -2
  134. package/src/vectorCluster/vectorClusterCesiumContext.ts +123 -0
  135. package/src/vectorCluster/vectorClusterGroup.ts +463 -0
  136. package/src/vectorCluster/vectorClusterGroupCesiumImpl.ts +176 -0
  137. package/src/vectorCluster/vectorClusterGroupCollection.ts +43 -0
  138. package/src/vectorCluster/vectorClusterGroupImpl.ts +107 -0
  139. package/src/vectorCluster/vectorClusterGroupObliqueImpl.ts +84 -0
  140. package/src/vectorCluster/vectorClusterGroupOpenlayersImpl.ts +81 -0
  141. package/src/vectorCluster/vectorClusterStyleItem.ts +490 -0
  142. package/src/vectorCluster/vectorClusterSymbols.ts +2 -0
  143. package/dist/src/layer/cesium/clusterContext.d.ts +0 -20
  144. package/dist/src/layer/cesium/clusterContext.js.map +0 -1
  145. package/src/layer/cesium/clusterContext.ts +0 -140
  146. package/src/ol/source/VcsCluster.js +0 -37
@@ -0,0 +1,223 @@
1
+ import deepEqual from 'fast-deep-equal';
2
+ import { Coordinate } from 'ol/coordinate.js';
3
+ import { Feature } from 'ol';
4
+ import { Polygon } from 'ol/geom.js';
5
+ import { check, oneOf } from '@vcsuite/check';
6
+ import { parseBoolean } from '@vcsuite/parsers';
7
+ import { getLogger } from '@vcsuite/logger';
8
+ import { Cartesian3, ClippingPolygon } from '@vcmap-cesium/engine';
9
+ import VcsObject, { VcsObjectOptions } from '../../vcsObject.js';
10
+ import VcsEvent from '../../vcsEvent.js';
11
+
12
+ export enum ClippingPolygonObjectState {
13
+ INACTIVE = 1,
14
+ ACTIVE = 2,
15
+ }
16
+
17
+ export type ClippingPolygonObjectOptions = VcsObjectOptions & {
18
+ layerNames?: string[] | 'all';
19
+ terrain?: boolean;
20
+ activeOnStartup?: boolean;
21
+ coordinates: Array<Coordinate>;
22
+ };
23
+
24
+ function getLayerNamesClone(layerNames: string[] | 'all'): string[] | 'all' {
25
+ return Array.isArray(layerNames) ? layerNames.slice() : layerNames;
26
+ }
27
+
28
+ class ClippingPolygonObject extends VcsObject {
29
+ static get className(): string {
30
+ return 'ClippingPolygonObject';
31
+ }
32
+
33
+ static getDefaultOptions(): ClippingPolygonObjectOptions {
34
+ return {
35
+ activeOnStartup: false,
36
+ layerNames: 'all',
37
+ terrain: false,
38
+ coordinates: [],
39
+ };
40
+ }
41
+
42
+ static fromFeature(feature: Feature<Polygon>): ClippingPolygonObject | null {
43
+ const geometry = feature.getGeometry();
44
+ if (geometry instanceof Polygon) {
45
+ return ClippingPolygonObject.fromGeometry(geometry);
46
+ }
47
+ return null;
48
+ }
49
+
50
+ static fromGeometry(geometry: Polygon): ClippingPolygonObject {
51
+ check(geometry, Polygon);
52
+ const ring = geometry.getLinearRing(0)!;
53
+ const coordinates = ring.getCoordinates();
54
+ return new ClippingPolygonObject({ coordinates });
55
+ }
56
+
57
+ activeOnStartup: boolean;
58
+
59
+ private _state: ClippingPolygonObjectState;
60
+
61
+ stateChanged = new VcsEvent<ClippingPolygonObjectState>();
62
+
63
+ private _layerNames: string[] | 'all';
64
+
65
+ private _terrain: boolean;
66
+
67
+ private _coordinates: Array<Coordinate> = [];
68
+
69
+ private _clippingPolygon: ClippingPolygon | undefined = undefined;
70
+
71
+ clippingPolygonChanged = new VcsEvent<{
72
+ newValue: ClippingPolygon;
73
+ oldValue: ClippingPolygon | undefined;
74
+ }>();
75
+
76
+ layersChanged = new VcsEvent<{
77
+ newValue: string[] | 'all';
78
+ oldValue: string[] | 'all';
79
+ }>();
80
+
81
+ terrainChanged = new VcsEvent<boolean>();
82
+
83
+ constructor(options: ClippingPolygonObjectOptions) {
84
+ super(options);
85
+ const defaultOptions = ClippingPolygonObject.getDefaultOptions();
86
+
87
+ this.activeOnStartup = parseBoolean(
88
+ options.activeOnStartup,
89
+ defaultOptions.activeOnStartup,
90
+ );
91
+
92
+ this._state = ClippingPolygonObjectState.INACTIVE;
93
+
94
+ this._layerNames = options.layerNames || defaultOptions.layerNames!;
95
+
96
+ this._terrain = parseBoolean(options.terrain, defaultOptions.terrain);
97
+
98
+ this.setCoordinates(options.coordinates || defaultOptions.coordinates);
99
+ }
100
+
101
+ /**
102
+ * Whether the clipping polygon object is active or not
103
+ */
104
+ get active(): boolean {
105
+ return this._state === ClippingPolygonObjectState.ACTIVE;
106
+ }
107
+
108
+ get layerNames(): string[] | 'all' {
109
+ return this._layerNames;
110
+ }
111
+
112
+ get terrain(): boolean {
113
+ return this._terrain;
114
+ }
115
+
116
+ set terrain(terrain: boolean) {
117
+ check(terrain, Boolean);
118
+
119
+ if (this._terrain !== terrain) {
120
+ this._terrain = terrain;
121
+ this.terrainChanged.raiseEvent(this._terrain);
122
+ }
123
+ }
124
+
125
+ get clippingPolygon(): ClippingPolygon | undefined {
126
+ return this._clippingPolygon;
127
+ }
128
+
129
+ get coordinates(): readonly Readonly<Coordinate>[] {
130
+ return this._coordinates;
131
+ }
132
+
133
+ /**
134
+ * Set polygon coordinates from an array of geographic wgs84 coordinates
135
+ * @param coordinates
136
+ */
137
+ setCoordinates(coordinates: Coordinate[]): void {
138
+ check(coordinates, [[Number]]);
139
+
140
+ if (coordinates.length < 3) {
141
+ getLogger('ClippingPolygonObject').error(
142
+ 'At least 3 coordinates are required!',
143
+ );
144
+ return;
145
+ }
146
+
147
+ if (deepEqual(this._coordinates, coordinates)) {
148
+ getLogger('ClippingPolygonObject').error(
149
+ 'The provided coordinates are already set!',
150
+ );
151
+ return;
152
+ }
153
+
154
+ const positions = coordinates.map((c) => {
155
+ return Cartesian3.fromDegrees(c[0], c[1], c[2]);
156
+ });
157
+ this._coordinates = structuredClone(coordinates);
158
+
159
+ const oldValue = this._clippingPolygon;
160
+ const newValue = new ClippingPolygon({ positions });
161
+ this._clippingPolygon = newValue;
162
+ this.clippingPolygonChanged.raiseEvent({ oldValue, newValue });
163
+ }
164
+
165
+ setLayerNames(layerNames: string[] | 'all'): void {
166
+ check(layerNames, oneOf([String], 'all'));
167
+
168
+ if (!deepEqual(this._layerNames, layerNames)) {
169
+ const oldValue = this._layerNames;
170
+ this._layerNames = getLayerNamesClone(layerNames);
171
+ this.layersChanged.raiseEvent({
172
+ newValue: layerNames,
173
+ oldValue,
174
+ });
175
+ }
176
+ }
177
+
178
+ activate(): void {
179
+ if (this._state === ClippingPolygonObjectState.INACTIVE) {
180
+ this._state = ClippingPolygonObjectState.ACTIVE;
181
+ this.stateChanged.raiseEvent(this._state);
182
+ }
183
+ }
184
+
185
+ deactivate(): void {
186
+ if (this._state === ClippingPolygonObjectState.ACTIVE) {
187
+ this._state = ClippingPolygonObjectState.INACTIVE;
188
+ this.stateChanged.raiseEvent(this._state);
189
+ }
190
+ }
191
+
192
+ toJSON(): ClippingPolygonObjectOptions {
193
+ const config: ClippingPolygonObjectOptions = {
194
+ ...super.toJSON(),
195
+ coordinates: structuredClone(this._coordinates),
196
+ };
197
+ const defaultOptions = ClippingPolygonObject.getDefaultOptions();
198
+
199
+ if (!deepEqual(this._layerNames, defaultOptions.layerNames)) {
200
+ config.layerNames = getLayerNamesClone(this._layerNames);
201
+ }
202
+
203
+ if (this._terrain !== defaultOptions.terrain) {
204
+ config.terrain = this._terrain;
205
+ }
206
+
207
+ if (this.activeOnStartup !== defaultOptions.activeOnStartup) {
208
+ config.activeOnStartup = this.activeOnStartup;
209
+ }
210
+
211
+ return config;
212
+ }
213
+
214
+ destroy(): void {
215
+ this.stateChanged.destroy();
216
+ this.clippingPolygonChanged.destroy();
217
+ this.layersChanged.destroy();
218
+ this.terrainChanged.destroy();
219
+ super.destroy();
220
+ }
221
+ }
222
+
223
+ export default ClippingPolygonObject;
@@ -0,0 +1,249 @@
1
+ import { Cesium3DTileset } from '@vcmap-cesium/engine';
2
+ import Collection from '../collection.js';
3
+ import VcsEvent from '../../vcsEvent.js';
4
+ import type VcsApp from '../../vcsApp.js';
5
+ import type ClippingPolygonObject from './clippingPolygonObject.js';
6
+ import {
7
+ addClippingPolygon,
8
+ addClippingPolygonObjectToMap,
9
+ getTargetTilesets,
10
+ removeClippingPolygon,
11
+ removeClippingPolygonFromMap,
12
+ } from './clippingPolygonHelper.js';
13
+ import { vcsLayerName } from '../../layer/layerSymbols.js';
14
+ import CesiumMap from '../../map/cesiumMap.js';
15
+ import MapState from '../../map/mapState.js';
16
+
17
+ class ClippingPolygonObjectCollection extends Collection<ClippingPolygonObject> {
18
+ private _app: VcsApp;
19
+
20
+ private _listener: Array<() => void>;
21
+
22
+ private _mapListener: Map<string, () => void> = new Map();
23
+
24
+ private _itemListener: Map<string, () => void> = new Map();
25
+
26
+ stateChanged: VcsEvent<ClippingPolygonObject> = new VcsEvent();
27
+
28
+ constructor(app: VcsApp) {
29
+ super();
30
+
31
+ this._app = app;
32
+
33
+ this._listener = [
34
+ this.added.addEventListener((item) => {
35
+ this._itemListener.set(item.name, this._setItemListener(item));
36
+ if (item.activeOnStartup) {
37
+ item.activate();
38
+ }
39
+ }),
40
+ this.removed.addEventListener((item) => {
41
+ if (item.active) {
42
+ const maps = this._getActiveCesiumMaps();
43
+ maps.forEach((map) => {
44
+ removeClippingPolygonFromMap(
45
+ map,
46
+ item.clippingPolygon,
47
+ item.terrain,
48
+ item.layerNames,
49
+ );
50
+ });
51
+ }
52
+ if (this._itemListener.has(item.name)) {
53
+ this._itemListener.get(item.name)?.();
54
+ this._itemListener.delete(item.name);
55
+ }
56
+ }),
57
+ this._app.maps.added.addEventListener((map) => {
58
+ if (map instanceof CesiumMap) {
59
+ this._mapListener.set(map.name, this._setMapListener(map));
60
+ }
61
+ }),
62
+ this._app.maps.removed.addEventListener((map) => {
63
+ if (map instanceof CesiumMap) {
64
+ this._array.forEach((item) => {
65
+ removeClippingPolygonFromMap(
66
+ map,
67
+ item.clippingPolygon,
68
+ item.terrain,
69
+ item.layerNames,
70
+ );
71
+ });
72
+ if (this._mapListener.has(map.name)) {
73
+ this._mapListener.get(map.name)?.();
74
+ this._mapListener.delete(map.name);
75
+ }
76
+ }
77
+ }),
78
+ this._app.maps.replaced.addEventListener(({ old }) => {
79
+ if (old instanceof CesiumMap) {
80
+ this._array.forEach((item) => {
81
+ removeClippingPolygonFromMap(
82
+ old,
83
+ item.clippingPolygon,
84
+ item.terrain,
85
+ item.layerNames,
86
+ );
87
+ });
88
+ if (this._mapListener.has(old.name)) {
89
+ this._mapListener.get(old.name)?.();
90
+ this._mapListener.delete(old.name);
91
+ }
92
+ }
93
+ }),
94
+ ];
95
+ }
96
+
97
+ _getActiveCesiumMaps(): CesiumMap[] {
98
+ return this._app.maps
99
+ .getByType(CesiumMap.className)
100
+ .filter((map) => map.active) as CesiumMap[];
101
+ }
102
+
103
+ _setMapListener(map: CesiumMap): () => void {
104
+ const listener = [
105
+ map.stateChanged.addEventListener((state) => {
106
+ if (state === MapState.INACTIVE) {
107
+ this._array.forEach((item) => {
108
+ removeClippingPolygonFromMap(
109
+ map,
110
+ item.clippingPolygon,
111
+ item.terrain,
112
+ item.layerNames,
113
+ );
114
+ });
115
+ } else if (state === MapState.ACTIVE) {
116
+ this._array
117
+ .filter((item) => item.active)
118
+ .forEach((item) => {
119
+ addClippingPolygonObjectToMap(
120
+ map,
121
+ item.clippingPolygon,
122
+ item.terrain,
123
+ item.layerNames,
124
+ );
125
+ });
126
+ }
127
+ }),
128
+ map.visualizationAdded.addEventListener((v) => {
129
+ if (v instanceof Cesium3DTileset) {
130
+ this._array
131
+ .filter(
132
+ (item) =>
133
+ item.active &&
134
+ (item.layerNames === 'all' ||
135
+ item.layerNames.includes(v[vcsLayerName])),
136
+ )
137
+ .forEach((item) => {
138
+ addClippingPolygon(v, item.clippingPolygon);
139
+ });
140
+ }
141
+ }),
142
+ map.visualizationRemoved.addEventListener((v) => {
143
+ if (v instanceof Cesium3DTileset) {
144
+ this._array
145
+ .filter(
146
+ (item) =>
147
+ item.layerNames === 'all' ||
148
+ item.layerNames.includes(v[vcsLayerName]),
149
+ )
150
+ .forEach((item) => {
151
+ removeClippingPolygon(v, item.clippingPolygon);
152
+ });
153
+ }
154
+ }),
155
+ ];
156
+
157
+ return () => listener.forEach((cb) => cb());
158
+ }
159
+
160
+ _setItemListener(item: ClippingPolygonObject): () => void {
161
+ const listener = [
162
+ item.stateChanged.addEventListener(() => {
163
+ const maps = this._getActiveCesiumMaps();
164
+ if (item.active) {
165
+ maps.forEach((map) =>
166
+ addClippingPolygonObjectToMap(
167
+ map,
168
+ item.clippingPolygon,
169
+ item.terrain,
170
+ item.layerNames,
171
+ ),
172
+ );
173
+ } else {
174
+ maps.forEach((map) =>
175
+ removeClippingPolygonFromMap(
176
+ map,
177
+ item.clippingPolygon,
178
+ item.terrain,
179
+ item.layerNames,
180
+ ),
181
+ );
182
+ }
183
+ }),
184
+ item.clippingPolygonChanged.addEventListener(({ oldValue, newValue }) => {
185
+ if (item.active) {
186
+ const maps = this._getActiveCesiumMaps();
187
+ maps.forEach((map) =>
188
+ removeClippingPolygonFromMap(
189
+ map,
190
+ oldValue,
191
+ item.terrain,
192
+ item.layerNames,
193
+ ),
194
+ );
195
+ maps.forEach((map) =>
196
+ addClippingPolygonObjectToMap(
197
+ map,
198
+ newValue,
199
+ item.terrain,
200
+ item.layerNames,
201
+ ),
202
+ );
203
+ }
204
+ }),
205
+ item.terrainChanged.addEventListener(() => {
206
+ if (item.active) {
207
+ const globes = this._getActiveCesiumMaps()
208
+ .map((map) => map.getScene()?.globe)
209
+ .filter((g) => !!g);
210
+ if (item.terrain) {
211
+ globes.forEach((g) => addClippingPolygon(g, item.clippingPolygon));
212
+ } else {
213
+ globes.forEach((g) =>
214
+ removeClippingPolygon(g, item.clippingPolygon),
215
+ );
216
+ }
217
+ }
218
+ }),
219
+ item.layersChanged.addEventListener(({ newValue, oldValue }) => {
220
+ const maps = this._getActiveCesiumMaps();
221
+ maps.forEach((map) => {
222
+ const old = getTargetTilesets(map, oldValue);
223
+ const tilesets = getTargetTilesets(map, newValue);
224
+
225
+ const added = tilesets.filter((i) => !old.includes(i));
226
+ const removed = old.filter((i) => !tilesets.includes(i));
227
+
228
+ removed.forEach((tileset) => {
229
+ removeClippingPolygon(tileset, item.clippingPolygon);
230
+ });
231
+ added.forEach((tileset) => {
232
+ addClippingPolygon(tileset, item.clippingPolygon);
233
+ });
234
+ });
235
+ }),
236
+ ];
237
+
238
+ return () => listener.forEach((cb) => cb());
239
+ }
240
+
241
+ destroy(): void {
242
+ this._listener.forEach((cb) => cb());
243
+ this._mapListener.forEach((cb) => cb());
244
+ this._itemListener.forEach((cb) => cb());
245
+ super.destroy();
246
+ }
247
+ }
248
+
249
+ export default ClippingPolygonObjectCollection;
@@ -1,4 +1,4 @@
1
- /* eslint-disable @typescript-eslint/ban-ts-comment */
1
+ import { parseBoolean } from '@vcsuite/parsers';
2
2
  import { check } from '@vcsuite/check';
3
3
  import IndexedCollection from './indexedCollection.js';
4
4
  import ExclusiveManager from './exclusiveManager.js';
@@ -7,6 +7,9 @@ import VcsEvent from '../vcsEvent.js';
7
7
  import GlobalHider from '../layer/globalHider.js';
8
8
  // eslint-disable-next-line import/no-named-default
9
9
  import type { default as Layer, SplitLayer } from '../layer/layer.js';
10
+ import VectorClusterGroupCollection from '../vectorCluster/vectorClusterGroupCollection.js';
11
+ import type VectorLayer from '../layer/vectorLayer.js';
12
+ import { destroyCollection } from '../vcsModuleHelpers.js';
10
13
 
11
14
  /**
12
15
  * The largest integer zindex which can be safely assigned to a layer (equal to Number.MAX_SAFE_INTEGER)
@@ -14,6 +17,11 @@ import type { default as Layer, SplitLayer } from '../layer/layer.js';
14
17
  */
15
18
  export const maxZIndex = Number.MAX_SAFE_INTEGER;
16
19
 
20
+ export type LayerCollectionOptions = {
21
+ vectorClusterGroupCollection?: VectorClusterGroupCollection;
22
+ destroyVectorClusterGroupCollection?: boolean;
23
+ };
24
+
17
25
  /**
18
26
  * A collection of layers. Manages rendering order and layer exclusivity. Emits state changes for convenience. Passed to
19
27
  * {@link Map} for layers available to said map. Layers must have unique names.
@@ -57,6 +65,8 @@ class LayerCollection extends IndexedCollection<Layer> {
57
65
  */
58
66
  private _globalHider: GlobalHider;
59
67
 
68
+ private _vectorClusterGroups: VectorClusterGroupCollection;
69
+
60
70
  /**
61
71
  * Locale for this layerCollection, will be synchronized by the vcsApp, if part of an vcsApp.
62
72
  * This Locale will be set on all Member Layers. On setting the Locale this will trigger a reload of all locale
@@ -64,7 +74,11 @@ class LayerCollection extends IndexedCollection<Layer> {
64
74
  */
65
75
  private _locale: string;
66
76
 
67
- constructor() {
77
+ private _vectorClusterGroupListeners: (() => void) | undefined;
78
+
79
+ destroyVectorClusterGroupCollection: boolean;
80
+
81
+ constructor(options: LayerCollectionOptions = {}) {
68
82
  super();
69
83
 
70
84
  this._layerEventListeners = {};
@@ -73,6 +87,18 @@ class LayerCollection extends IndexedCollection<Layer> {
73
87
  this.exclusiveManager = new ExclusiveManager();
74
88
  this._globalHider = new GlobalHider();
75
89
  this._locale = 'en';
90
+ if (options.vectorClusterGroupCollection) {
91
+ this._vectorClusterGroups = options.vectorClusterGroupCollection;
92
+ } else {
93
+ this._vectorClusterGroups = new VectorClusterGroupCollection(
94
+ this._globalHider,
95
+ );
96
+ }
97
+ this.destroyVectorClusterGroupCollection = parseBoolean(
98
+ options.destroyVectorClusterGroupCollection,
99
+ !options.vectorClusterGroupCollection,
100
+ );
101
+ this._setupVectorClusterGroupListeners();
76
102
  }
77
103
 
78
104
  /**
@@ -102,6 +128,7 @@ class LayerCollection extends IndexedCollection<Layer> {
102
128
  this._array.forEach((layer) => {
103
129
  layer.setGlobalHider(this._globalHider);
104
130
  });
131
+ this.vectorClusterGroups.globalHider = this._globalHider;
105
132
  }
106
133
 
107
134
  get locale(): string {
@@ -119,6 +146,10 @@ class LayerCollection extends IndexedCollection<Layer> {
119
146
  }
120
147
  }
121
148
 
149
+ get vectorClusterGroups(): VectorClusterGroupCollection {
150
+ return this._vectorClusterGroups;
151
+ }
152
+
122
153
  private _listenToLayerEvents(layer: Layer): void {
123
154
  const stateListener = layer.stateChanged.addEventListener(
124
155
  (state: LayerState) => {
@@ -148,6 +179,25 @@ class LayerCollection extends IndexedCollection<Layer> {
148
179
  ),
149
180
  );
150
181
  }
182
+
183
+ if ((layer as VectorLayer).vectorClusterGroupChanged) {
184
+ listeners.push(
185
+ (layer as VectorLayer).vectorClusterGroupChanged.addEventListener(
186
+ ({ newGroup, oldGroup }) => {
187
+ if (oldGroup) {
188
+ this._vectorClusterGroups
189
+ .getByKey(oldGroup)
190
+ ?.removeLayer(layer as VectorLayer);
191
+ }
192
+ if (newGroup) {
193
+ this._vectorClusterGroups
194
+ .getByKey(newGroup)
195
+ ?.addLayer(layer as VectorLayer);
196
+ }
197
+ },
198
+ ),
199
+ );
200
+ }
151
201
  this._layerEventListeners[layer.name] = listeners;
152
202
  }
153
203
 
@@ -158,7 +208,7 @@ class LayerCollection extends IndexedCollection<Layer> {
158
208
  */
159
209
  private _findZIndexPosition(zIndex: number): number | null {
160
210
  const usedIndex = this._array.findIndex(
161
- // @ts-ignore
211
+ // @ts-expect-error: z index is undefined
162
212
  (l) => l[this._zIndexSymbol] > zIndex,
163
213
  );
164
214
  return usedIndex > -1 ? usedIndex : null;
@@ -173,7 +223,7 @@ class LayerCollection extends IndexedCollection<Layer> {
173
223
  private _zIndexChanged(layer: Layer): void {
174
224
  const currentIndex = this.indexOf(layer);
175
225
  if (currentIndex > -1) {
176
- // @ts-ignore
226
+ // @ts-expect-error: z index is undefined
177
227
  layer[this._zIndexSymbol] = layer.zIndex;
178
228
  let zIndexPosition = this._findZIndexPosition(layer.zIndex);
179
229
  if (
@@ -197,29 +247,43 @@ class LayerCollection extends IndexedCollection<Layer> {
197
247
  */
198
248
  private _ensureLocalZIndex(layer: Layer): void {
199
249
  const currentIndex = this.indexOf(layer);
200
- // @ts-ignore
250
+ // @ts-expect-error: z index is undefined
201
251
  const currentLayerZIndex = layer[this._zIndexSymbol] as number;
202
252
  if (currentIndex > 0) {
203
- // @ts-ignore
253
+ // @ts-expect-error: z index is undefined
204
254
  const below: number = this._array[currentIndex - 1][
205
255
  this._zIndexSymbol
206
256
  ] as number;
207
257
  if (below > currentLayerZIndex) {
208
- // @ts-ignore
258
+ // @ts-expect-error: z index is undefined
209
259
  layer[this._zIndexSymbol] = below;
210
260
  }
211
261
  }
212
262
 
213
263
  if (currentIndex < this._array.length - 1) {
214
- // @ts-ignore
264
+ // @ts-expect-error: z index is undefined
215
265
  const above = this._array[currentIndex + 1][this._zIndexSymbol] as number;
216
266
  if (above < currentLayerZIndex) {
217
- // @ts-ignore
267
+ // @ts-expect-error: z index is undefined
218
268
  layer[this._zIndexSymbol] = above;
219
269
  }
220
270
  }
221
271
  }
222
272
 
273
+ private _setupVectorClusterGroupListeners(): void {
274
+ this._vectorClusterGroupListeners =
275
+ this._vectorClusterGroups.added.addEventListener((collection) => {
276
+ this._array
277
+ .filter(
278
+ (layer) =>
279
+ (layer as VectorLayer).vectorClusterGroup === collection.name,
280
+ )
281
+ .forEach((layer) => {
282
+ collection.addLayer(layer as VectorLayer);
283
+ });
284
+ });
285
+ }
286
+
223
287
  /**
224
288
  * Adds a layer to the collection. Can optionally be passed an index at which to insert the layer.
225
289
  * The layer locale will be set to the same locale of the layerCollection. This will trigger a forceRedraw
@@ -235,13 +299,18 @@ class LayerCollection extends IndexedCollection<Layer> {
235
299
  }
236
300
  const insertedAt = super.add(layer, usedIndex);
237
301
  if (insertedAt != null) {
238
- // @ts-ignore
302
+ // @ts-expect-error: z index is undefined
239
303
  layer[this._zIndexSymbol] = layer.zIndex;
240
304
  layer.setGlobalHider(this._globalHider);
241
305
  layer.locale = this.locale;
242
306
  this._ensureLocalZIndex(layer);
243
307
  this._listenToLayerEvents(layer);
244
308
  this.exclusiveManager.registerLayer(layer);
309
+ if ((layer as VectorLayer).vectorClusterGroup) {
310
+ this._vectorClusterGroups
311
+ .getByKey((layer as VectorLayer).vectorClusterGroup)
312
+ ?.addLayer(layer as VectorLayer);
313
+ }
245
314
  }
246
315
  return insertedAt;
247
316
  }
@@ -253,10 +322,15 @@ class LayerCollection extends IndexedCollection<Layer> {
253
322
  });
254
323
  delete this._layerEventListeners[layer.name];
255
324
  }
256
- // @ts-ignore
325
+ // @ts-expect-error: z index is undefined
257
326
  delete layer[this._zIndexSymbol];
258
327
  layer.setGlobalHider();
259
328
  this.exclusiveManager.unregisterLayer(layer);
329
+ if ((layer as VectorLayer).vectorClusterGroup) {
330
+ this._vectorClusterGroups
331
+ .getByKey((layer as VectorLayer).vectorClusterGroup)
332
+ ?.removeLayer(layer as VectorLayer);
333
+ }
260
334
  return super._remove(layer);
261
335
  }
262
336
 
@@ -267,7 +341,7 @@ class LayerCollection extends IndexedCollection<Layer> {
267
341
  r();
268
342
  });
269
343
  this._array.forEach((l) => {
270
- // @ts-ignore
344
+ // @ts-expect-error: z index is undefined
271
345
  delete l[this._zIndexSymbol];
272
346
  });
273
347
 
@@ -286,6 +360,10 @@ class LayerCollection extends IndexedCollection<Layer> {
286
360
  this._layerEventListeners = {};
287
361
  this.exclusiveManager.destroy();
288
362
  this._globalHider.destroy();
363
+ this._vectorClusterGroupListeners?.();
364
+ if (this.destroyVectorClusterGroupCollection) {
365
+ destroyCollection(this._vectorClusterGroups);
366
+ }
289
367
  super.destroy();
290
368
  }
291
369
  }