@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 @@
1
+ export declare const vectorClusterGroupName: unique symbol;
@@ -0,0 +1,3 @@
1
+ // eslint-disable-next-line import/prefer-default-export
2
+ export const vectorClusterGroupName = Symbol('vectorClusterGroupName');
3
+ //# sourceMappingURL=vectorClusterSymbols.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vectorClusterSymbols.js","sourceRoot":"","sources":["../../../src/vectorCluster/vectorClusterSymbols.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC,wBAAwB,CAAC,CAAC"}
package/index.ts CHANGED
@@ -62,7 +62,6 @@ export {
62
62
  getExtentFromTileset,
63
63
  default as CesiumTilesetCesiumImpl,
64
64
  } from './src/layer/cesium/cesiumTilesetCesiumImpl.js';
65
- export { default as ClusterContext } from './src/layer/cesium/clusterContext.js';
66
65
  export { default as DataSourceCesiumImpl } from './src/layer/cesium/dataSourceCesiumImpl.js';
67
66
  export { default as OpenStreetMapCesiumImpl } from './src/layer/cesium/openStreetMapCesiumImpl.js';
68
67
  export { default as RasterLayerCesiumImpl } from './src/layer/cesium/rasterLayerCesiumImpl.js';
@@ -105,6 +104,10 @@ export {
105
104
  getTileHash,
106
105
  getTileWgs84Extent,
107
106
  } from './src/layer/cesium/vcsTile/vcsTileHelpers.js';
107
+ export {
108
+ createSourceVectorContextSync,
109
+ SourceVectorContextSync,
110
+ } from './src/layer/cesium/sourceVectorContextSync.js';
108
111
  export { default as CzmlLayer, CzmlOptions } from './src/layer/czmlLayer.js';
109
112
  export {
110
113
  default as DataSourceLayer,
@@ -183,6 +186,10 @@ export {
183
186
  setNewGeometry,
184
187
  } from './src/layer/oblique/obliqueHelpers.js';
185
188
  export { default as VectorObliqueImpl } from './src/layer/oblique/vectorObliqueImpl.js';
189
+ export {
190
+ createSourceObliqueSync,
191
+ SourceObliqueSync,
192
+ } from './src/layer/oblique/sourceObliqueSync.js';
186
193
  export {
187
194
  default as OpenStreetMapLayer,
188
195
  OpenStreetMapOptions,
@@ -257,6 +264,28 @@ export {
257
264
  default as URLTemplateTileProvider,
258
265
  URLTemplateTileProviderOptions,
259
266
  } from './src/layer/tileProvider/urlTemplateTileProvider.js';
267
+ export {
268
+ default as ClusterContext,
269
+ default as VectorClusterCesiumContext,
270
+ } from './src/vectorCluster/vectorClusterCesiumContext.js';
271
+ export {
272
+ default as VectorClusterStyleItem,
273
+ VectorClusterStyleItemOptions,
274
+ VectorClusterTemplateFunction,
275
+ getDefaultClusterStyleItem,
276
+ getDefaultClusterHighlightStyleItem,
277
+ } from './src/vectorCluster/vectorClusterStyleItem.js';
278
+ export { default as VectorClusterGroupCesiumImpl } from './src/vectorCluster/vectorClusterGroupCesiumImpl.js';
279
+ export { default as VectorClusterGroupOpenlayersImpl } from './src/vectorCluster/vectorClusterGroupOpenlayersImpl.js';
280
+ export {
281
+ default as VectorClusterGroup,
282
+ VectorClusterGroupOptions,
283
+ VectorClusterGroupImplementationOptions,
284
+ } from './src/vectorCluster/vectorClusterGroup.js';
285
+ export { default as VectorClusterGroupImpl } from './src/vectorCluster/vectorClusterGroupImpl.js';
286
+ export { default as VectorClusterGroupObliqueImpl } from './src/vectorCluster/vectorClusterGroupObliqueImpl.js';
287
+ export { default as VectorClusterGroupCollection } from './src/vectorCluster/vectorClusterGroupCollection.js';
288
+ export { vectorClusterGroupName } from './src/vectorCluster/vectorClusterSymbols.js';
260
289
  export {
261
290
  default as TMSLayer,
262
291
  TMSOptions,
@@ -496,6 +525,12 @@ export {
496
525
  getClippingOptions,
497
526
  ClippingPlaneCreationOptions,
498
527
  } from './src/util/clipping/clippingPlaneHelper.js';
528
+ export {
529
+ default as ClippingPolygonObject,
530
+ ClippingPolygonObjectOptions,
531
+ ClippingPolygonObjectState,
532
+ } from './src/util/clipping/clippingPolygonObject.js';
533
+ export { default as ClippingPolygonObjectCollection } from './src/util/clipping/clippingPolygonObjectCollection.js';
499
534
  export {
500
535
  default as DisplayQuality,
501
536
  DisplayQualityLevel,
@@ -833,3 +868,9 @@ export {
833
868
  } from './src/util/flight/flightVisualizer.js';
834
869
  export { getTileLoadFunction } from './src/layer/openlayers/loadFunctionHelpers.js';
835
870
  export { default as ModelFill } from './src/style/modelFill.js';
871
+ export { renderTemplate } from './src/util/vcsTemplate.js';
872
+ export {
873
+ startRotation,
874
+ rotationMapControlSymbol,
875
+ } from './src/util/rotation.js';
876
+ export { default as renderScreenshot } from './src/util/renderScreenshot.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vcmap/core",
3
- "version": "6.0.7",
3
+ "version": "6.1.0-rc.2",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -39,6 +39,7 @@
39
39
  "license": "MIT",
40
40
  "devDependencies": {
41
41
  "@types/chai": "^4.3.16",
42
+ "@types/chai-as-promised": "^8.0.1",
42
43
  "@types/geojson": "^7946.0.10",
43
44
  "@types/mocha": "^10.0.7",
44
45
  "@types/node": "^20.16.5",
@@ -50,6 +51,7 @@
50
51
  "c8": "^10.1.2",
51
52
  "canvas": "^2.11.2",
52
53
  "chai": "^4.4.1",
54
+ "chai-as-promised": "^8.0.1",
53
55
  "eslint": "^8.38.0",
54
56
  "jsdom": "^24.1.0",
55
57
  "jsdom-global": "^3.0.2",
@@ -27,6 +27,7 @@ import {
27
27
  updateFeatureOverride,
28
28
  } from '../layer/cesium/cesiumTilesetCesiumImpl.js';
29
29
  import { isTiledFeature } from '../layer/featureStoreLayer.js';
30
+ import { vectorClusterGroupName } from '../vectorCluster/vectorClusterSymbols.js';
30
31
 
31
32
  declare module '@vcmap-cesium/engine' {
32
33
  interface Scene {
@@ -61,6 +62,7 @@ declare module '@vcmap-cesium/engine' {
61
62
  getPropertyInherited(key: string): any;
62
63
  getAttributes(): Record<string, unknown>;
63
64
  [vcsLayerName]?: string;
65
+ [vectorClusterGroupName]?: string;
64
66
  [globalHidden]?: boolean;
65
67
  [hidden]?: boolean;
66
68
  [highlighted]?: VectorStyleItem;
@@ -112,6 +114,7 @@ declare module '@vcmap-cesium/engine' {
112
114
 
113
115
  interface CustomDataSource {
114
116
  [vcsLayerName]?: string;
117
+ [vectorClusterGroupName]?: string;
115
118
  }
116
119
 
117
120
  interface CzmlDataSource {
@@ -1,5 +1,10 @@
1
1
  /**
2
2
  * Added to ol.Feature, if they are not part of a layer, but provided by an {@link AbstractFeatureProvider}.
3
3
  */
4
- // eslint-disable-next-line import/prefer-default-export
5
4
  export const isProvidedFeature: unique symbol = Symbol('isProvidedFeature');
5
+
6
+ /**
7
+ * Added to ol.Feature, if a {@link AbstractFeatureProvider} provides more than one feature for one location.
8
+ * The provided feature is a cluster feature. The single features can be accessed by `feature.get('features')`.
9
+ */
10
+ export const isProvidedClusterFeature = Symbol('isProvidedClusterFeature');
@@ -5,10 +5,11 @@ import {
5
5
  Cesium3DTileFeature,
6
6
  Cesium3DTilePointFeature,
7
7
  Entity,
8
+ Scene,
9
+ Cartesian2,
8
10
  } from '@vcmap-cesium/engine';
11
+ import OLMap from 'ol/Map.js';
9
12
  import type { Feature } from 'ol/index.js';
10
- import type { Layer as OLLayer } from 'ol/layer.js';
11
-
12
13
  import AbstractInteraction, {
13
14
  type EventFeature,
14
15
  type InteractionEvent,
@@ -25,6 +26,96 @@ import type OpenlayersMap from '../map/openlayersMap.js';
25
26
  import type ObliqueMap from '../map/obliqueMap.js';
26
27
  import type CesiumMap from '../map/cesiumMap.js';
27
28
 
29
+ /**
30
+ * This is the return from cesium scene.pick and scene.drillPick, which returns "any". We cast to this type.
31
+ */
32
+ type CesiumPickObject = {
33
+ primitive?: {
34
+ olFeature?: Feature;
35
+ pointCloudShading?: { attenuation: unknown };
36
+ [vcsLayerName]?: string;
37
+ };
38
+ id?: {
39
+ olFeature?: Feature;
40
+ [vcsLayerName]?: string;
41
+ };
42
+ };
43
+
44
+ function getFeatureFromOlMap(
45
+ map: OLMap,
46
+ pixel: [number, number],
47
+ hitTolerance: number,
48
+ ): Feature | undefined {
49
+ let feature: Feature | undefined;
50
+ map.forEachFeatureAtPixel(
51
+ pixel,
52
+ (feat) => {
53
+ if (
54
+ feat &&
55
+ (feat.get('olcs_allowPicking') == null ||
56
+ feat.get('olcs_allowPicking') === true)
57
+ ) {
58
+ feature = (feat as Feature)[originalFeatureSymbol] || (feat as Feature);
59
+ }
60
+ return true;
61
+ },
62
+ { hitTolerance },
63
+ );
64
+
65
+ return feature;
66
+ }
67
+
68
+ function getFeatureFromPickObject(
69
+ object: CesiumPickObject,
70
+ ): EventFeature | undefined {
71
+ let feature: EventFeature | undefined;
72
+ if (object.primitive && object.primitive.olFeature) {
73
+ feature = object.primitive.olFeature;
74
+ } else if (
75
+ object.primitive &&
76
+ object.primitive[vcsLayerName] &&
77
+ (object instanceof Cesium3DTileFeature ||
78
+ object instanceof Cesium3DTilePointFeature)
79
+ ) {
80
+ // cesium 3d tileset
81
+ feature = object;
82
+ const symbols = Object.getOwnPropertySymbols(object.primitive);
83
+ const symbolLength = symbols.length;
84
+ for (let i = 0; i < symbolLength; i++) {
85
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
86
+ // @ts-ignore
87
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
88
+ feature[symbols[i]] = object.primitive[symbols[i]];
89
+ }
90
+ } else if (object.id && object.id.olFeature) {
91
+ // cluster size === 1
92
+ feature = object.id.olFeature;
93
+ } else if (
94
+ object.id &&
95
+ object.id[vcsLayerName] &&
96
+ object.id instanceof Entity
97
+ ) {
98
+ // entity
99
+ feature = object.id;
100
+ }
101
+
102
+ return feature;
103
+ }
104
+
105
+ function getFeatureFromScene(
106
+ scene: Scene,
107
+ windowPosition: Cartesian2,
108
+ hitTolerance: number,
109
+ ): EventFeature | undefined {
110
+ const pickObject = scene.pick(
111
+ windowPosition,
112
+ hitTolerance,
113
+ hitTolerance,
114
+ ) as CesiumPickObject;
115
+
116
+ return getFeatureFromPickObject(pickObject);
117
+ }
118
+
28
119
  /**
29
120
  * @group Interaction
30
121
  */
@@ -100,54 +191,28 @@ class FeatureAtPixelInteraction extends AbstractInteraction {
100
191
  private _openlayersHandler(
101
192
  event: InteractionEvent,
102
193
  ): Promise<InteractionEvent> {
103
- let found: Feature | null = null;
104
- let foundLayer: OLLayer | null = null;
105
- (event.map as OpenlayersMap).olMap!.forEachFeatureAtPixel(
194
+ const feature = getFeatureFromOlMap(
195
+ (event.map as OpenlayersMap).olMap!,
106
196
  [event.windowPosition.x, event.windowPosition.y],
107
- (feat, layer) => {
108
- if (
109
- feat &&
110
- (feat.get('olcs_allowPicking') == null ||
111
- feat.get('olcs_allowPicking') === true)
112
- ) {
113
- found = feat as Feature;
114
- foundLayer = layer;
115
- }
116
- return true;
117
- },
118
- { hitTolerance: this.hitTolerance },
197
+ this.hitTolerance,
119
198
  );
120
199
 
121
- if (found && foundLayer) {
122
- event.feature = found as Feature;
123
- if (event.feature.get('features') as Feature[] | undefined) {
124
- event.feature[vcsLayerName] = foundLayer[vcsLayerName];
125
- }
200
+ if (feature) {
201
+ event.feature = feature;
126
202
  event.exactPosition = true;
127
203
  }
128
204
  return Promise.resolve(event);
129
205
  }
130
206
 
131
207
  private _obliqueHandler(event: InteractionEvent): Promise<InteractionEvent> {
132
- let found: Feature | null = null;
133
- let foundLayer: OLLayer | null = null;
134
- (event.map as ObliqueMap).olMap!.forEachFeatureAtPixel(
208
+ const feature = getFeatureFromOlMap(
209
+ (event.map as ObliqueMap).olMap!,
135
210
  [event.windowPosition.x, event.windowPosition.y],
136
- (feat, layer) => {
137
- if (feat) {
138
- found = (feat as Feature)[originalFeatureSymbol] || (feat as Feature);
139
- }
140
- foundLayer = layer;
141
- return true;
142
- },
143
- { hitTolerance: this.hitTolerance },
211
+ this.hitTolerance,
144
212
  );
145
213
 
146
- if (found && foundLayer) {
147
- event.feature = found as Feature;
148
- if (event.feature.get('features') as Feature[] | undefined) {
149
- event.feature[vcsLayerName] = foundLayer[vcsLayerName];
150
- }
214
+ if (feature) {
215
+ event.feature = feature;
151
216
  event.exactPosition = true;
152
217
  }
153
218
  return Promise.resolve(event);
@@ -161,21 +226,11 @@ class FeatureAtPixelInteraction extends AbstractInteraction {
161
226
  return Promise.resolve(event);
162
227
  }
163
228
 
164
- const object = scene.pick(
229
+ const feature = getFeatureFromScene(
230
+ scene,
165
231
  event.windowPosition,
166
232
  this.hitTolerance,
167
- this.hitTolerance,
168
- ) as {
169
- primitive?: {
170
- olFeature?: Feature;
171
- pointCloudShading?: { attenuation: unknown };
172
- [vcsLayerName]?: string;
173
- };
174
- id?: {
175
- olFeature?: Feature;
176
- [vcsLayerName]?: string;
177
- };
178
- };
233
+ );
179
234
 
180
235
  let scratchCartographic = new Cartographic();
181
236
  let scratchCartesian = new Cartesian3();
@@ -220,44 +275,14 @@ class FeatureAtPixelInteraction extends AbstractInteraction {
220
275
  return Promise.resolve(event);
221
276
  };
222
277
 
223
- if (object) {
224
- if (object.primitive && object.primitive.olFeature) {
225
- // vector & vectorCluster
226
- event.feature = object.primitive.olFeature;
227
- } else if (
228
- object.primitive &&
229
- object.primitive[vcsLayerName] &&
230
- (object instanceof Cesium3DTileFeature ||
231
- object instanceof Cesium3DTilePointFeature)
232
- ) {
233
- // building
234
- event.feature = object;
235
- const symbols = Object.getOwnPropertySymbols(object.primitive);
236
- const symbolLength = symbols.length;
237
- for (let i = 0; i < symbolLength; i++) {
238
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
239
- // @ts-ignore
240
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
241
- event.feature[symbols[i]] = object.primitive[symbols[i]];
242
- }
243
- } else if (object.id && object.id.olFeature) {
244
- // cluster size === 1
245
- event.feature = object.id.olFeature;
246
- } else if (
247
- object.id &&
248
- object.id[vcsLayerName] &&
249
- object.id instanceof Entity
250
- ) {
251
- // entity
252
- event.feature = object.id;
253
- }
254
-
278
+ if (feature) {
279
+ event.feature = feature;
255
280
  if (!(event.type & this.pickPosition)) {
256
281
  return Promise.resolve(event);
257
282
  }
258
283
 
259
284
  if (scene.pickPositionSupported) {
260
- if (object.primitive && this.pickTranslucent) {
285
+ if (this.pickTranslucent) {
261
286
  scene.pickTranslucentDepth = true;
262
287
  event.exactPosition = true;
263
288
  }
@@ -1,5 +1,7 @@
1
1
  import type { Coordinate } from 'ol/coordinate.js';
2
2
 
3
+ import Point from 'ol/geom/Point.js';
4
+ import Feature from 'ol/Feature.js';
3
5
  import AbstractInteraction, {
4
6
  type InteractionEvent,
5
7
  } from './abstractInteraction.js';
@@ -8,6 +10,10 @@ import {
8
10
  ModificationKeyType,
9
11
  PointerKeyType,
10
12
  } from './interactionType.js';
13
+ import {
14
+ isProvidedClusterFeature,
15
+ isProvidedFeature,
16
+ } from '../featureProvider/featureProviderSymbols.js';
11
17
 
12
18
  /**
13
19
  * @group Interaction
@@ -21,36 +27,44 @@ class FeatureProviderInteraction extends AbstractInteraction {
21
27
 
22
28
  // eslint-disable-next-line class-methods-use-this
23
29
  async pipe(event: InteractionEvent): Promise<InteractionEvent> {
24
- if (!event.feature) {
25
- const layersWithProvider = [...event.map.layerCollection]
26
- .filter((l) => {
27
- return (
28
- l.featureProvider &&
29
- l.active &&
30
- l.isSupported(event.map) &&
31
- l.featureProvider.isSupported(event.map)
32
- );
33
- })
34
- .reverse();
35
-
36
- if (layersWithProvider.length > 0) {
37
- const resolution = event.map.getCurrentResolution(
38
- event.position as Coordinate,
30
+ const layersWithProvider = [...event.map.layerCollection]
31
+ .filter((l) => {
32
+ return (
33
+ l.featureProvider &&
34
+ l.active &&
35
+ l.isSupported(event.map) &&
36
+ l.featureProvider.isSupported(event.map)
39
37
  );
40
- const features = (
41
- await Promise.all(
42
- layersWithProvider.map(
43
- (l) =>
44
- l.featureProvider?.getFeaturesByCoordinate?.(
45
- event.position as Coordinate,
46
- resolution,
47
- l.headers,
48
- ),
49
- ),
50
- )
51
- ).flat();
38
+ })
39
+ .reverse();
40
+
41
+ if (layersWithProvider.length > 0) {
42
+ const resolution = event.map.getCurrentResolution(
43
+ event.position as Coordinate,
44
+ );
45
+ const features = (
46
+ await Promise.all(
47
+ layersWithProvider.map(
48
+ (l) =>
49
+ l.featureProvider?.getFeaturesByCoordinate?.(
50
+ event.position as Coordinate,
51
+ resolution,
52
+ l.headers,
53
+ ),
54
+ ),
55
+ )
56
+ )
57
+ .filter((f) => !!f)
58
+ .flat();
52
59
 
53
- if (features.length > 0) {
60
+ if (features.length > 0) {
61
+ if (features.length > 1) {
62
+ const feature = new Feature({ features });
63
+ feature[isProvidedFeature] = true; // backward compatibility, may remove in future
64
+ feature[isProvidedClusterFeature] = true;
65
+ feature.setGeometry(new Point(event.position as Coordinate));
66
+ event.feature = feature;
67
+ } else if (!event.feature) {
54
68
  event.feature = features[0];
55
69
  }
56
70
  }
@@ -0,0 +1,134 @@
1
+ import { getLogger } from '@vcsuite/logger';
2
+ import { unByKey } from 'ol/Observable.js';
3
+ import type VectorSource from 'ol/source/Vector.js';
4
+ import type { Feature } from 'ol';
5
+ import { StyleLike } from 'ol/style/Style.js';
6
+ import type { Scene } from '@vcmap-cesium/engine';
7
+ import type VectorContext from './vectorContext.js';
8
+ import type VectorClusterCesiumContext from '../../vectorCluster/vectorClusterCesiumContext.js';
9
+ import VectorProperties from '../vectorProperties.js';
10
+
11
+ export type SourceVectorContextSync = {
12
+ readonly active: boolean;
13
+ activate(): void;
14
+ deactivate(): void;
15
+ /**
16
+ * Clears the context and adds all features from the source.
17
+ */
18
+ refresh(): void;
19
+ destroy(): void;
20
+ };
21
+
22
+ /**
23
+ * Creates a SourceVectorContextSync. This ensures that the features in the source are synced to the context.
24
+ * Adding, removing and changing features in the source will be reflected in the context.
25
+ * @param source
26
+ * @param context
27
+ * @param scene
28
+ * @param style
29
+ * @param vectorProperties - the vector properties or a function returning vector properties for a feature
30
+ */
31
+ export function createSourceVectorContextSync(
32
+ source: VectorSource,
33
+ context: VectorContext | VectorClusterCesiumContext,
34
+ scene: Scene,
35
+ style: StyleLike,
36
+ vectorProperties: VectorProperties | ((f: Feature) => VectorProperties),
37
+ ): SourceVectorContextSync {
38
+ const featureToAdd = new Set<Feature>();
39
+ let active = false;
40
+ const vectorPropertiesChanged = new Map<VectorProperties, () => void>();
41
+ const getVectorProperties =
42
+ typeof vectorProperties === 'function'
43
+ ? vectorProperties
44
+ : (): VectorProperties => vectorProperties;
45
+
46
+ let refresh: () => void;
47
+ const addFeature = async (feature: Feature): Promise<void> => {
48
+ const featureVectorProperties = getVectorProperties(feature);
49
+ if (!vectorPropertiesChanged.has(featureVectorProperties)) {
50
+ vectorPropertiesChanged.set(
51
+ featureVectorProperties,
52
+ featureVectorProperties.propertyChanged.addEventListener(refresh),
53
+ );
54
+ }
55
+ if (active) {
56
+ // XXX cluster check here? or on init?
57
+ await context.addFeature(feature, style, featureVectorProperties, scene);
58
+ } else {
59
+ featureToAdd.add(feature);
60
+ }
61
+ };
62
+
63
+ const removeFeature = (feature: Feature): void => {
64
+ context.removeFeature(feature);
65
+ featureToAdd.delete(feature);
66
+ };
67
+
68
+ const featureChanged = async (feature: Feature): Promise<void> => {
69
+ featureToAdd.delete(feature);
70
+ await addFeature(feature);
71
+ };
72
+
73
+ const addFeatures = (features: Feature[]): void => {
74
+ // TODO we should make this non-blocking to better handle larger data sets check in RIWA Impl
75
+ features.forEach((f) => {
76
+ addFeature(f).catch((err) => {
77
+ getLogger('SourceVectorContextSync').error(
78
+ 'failed to convert feature',
79
+ f,
80
+ err,
81
+ );
82
+ });
83
+ });
84
+ };
85
+
86
+ const addCachedFeatures = (): void => {
87
+ addFeatures([...featureToAdd]);
88
+ featureToAdd.clear();
89
+ };
90
+
91
+ refresh = (): void => {
92
+ context.clear();
93
+ addFeatures(source.getFeatures());
94
+ };
95
+
96
+ const olListeners = [
97
+ source.on('addfeature', (event) => {
98
+ addFeature(event.feature as Feature).catch(() => {
99
+ getLogger().error('failed to convert feature');
100
+ });
101
+ }),
102
+ source.on('removefeature', (event) => {
103
+ removeFeature(event.feature as Feature);
104
+ }),
105
+ source.on('changefeature', (event) => {
106
+ featureChanged(event.feature as Feature).catch((_e) => {
107
+ getLogger().error('failed to convert feature');
108
+ });
109
+ }),
110
+ ];
111
+
112
+ addFeatures(source.getFeatures());
113
+
114
+ return {
115
+ get active(): boolean {
116
+ return active;
117
+ },
118
+ activate(): void {
119
+ active = true;
120
+ addCachedFeatures();
121
+ },
122
+ deactivate(): void {
123
+ active = false;
124
+ },
125
+ refresh,
126
+ destroy(): void {
127
+ unByKey(olListeners);
128
+ vectorPropertiesChanged.forEach((removeListener) => {
129
+ removeListener();
130
+ });
131
+ vectorPropertiesChanged.clear();
132
+ },
133
+ };
134
+ }
@@ -29,7 +29,7 @@ import Projection, {
29
29
  import { createSync } from '../../vectorSymbols.js';
30
30
  import VectorProperties from '../../vectorProperties.js';
31
31
  import CesiumMap from '../../../map/cesiumMap.js';
32
- import { TileProvider } from '../../../../index.js';
32
+ import type TileProvider from '../../tileProvider/tileProvider.js';
33
33
 
34
34
  let vectorProperties: VectorProperties | undefined;
35
35
  function getDebugVectorProperties(): VectorProperties {
@@ -19,8 +19,8 @@ import {
19
19
  VcsTileType,
20
20
  } from './vcsTileHelpers.js';
21
21
  import CesiumMap from '../../../map/cesiumMap.js';
22
- import { TileProvider } from '../../../../index.js';
23
22
  import VectorProperties from '../../vectorProperties.js';
23
+ import type TileProvider from '../../tileProvider/tileProvider.js';
24
24
 
25
25
  export default class VcsVectorTile implements VcsTile {
26
26
  state = VcsTileState.LOADING;