@vcmap/core 6.3.0-rc.1 → 6.3.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 (159) hide show
  1. package/dist/cesium.d.ts +12 -0
  2. package/dist/index.d.ts +10 -2
  3. package/dist/index.js +9 -2
  4. package/dist/index.js.map +1 -1
  5. package/dist/ol.d.ts +13 -2
  6. package/dist/src/cesium/cesium3DTileFeature.d.ts +1 -0
  7. package/dist/src/cesium/cesium3DTileFeature.js +16 -3
  8. package/dist/src/cesium/cesium3DTileFeature.js.map +1 -1
  9. package/dist/src/cesium/cesium3DTilePointFeature.js +2 -1
  10. package/dist/src/cesium/cesium3DTilePointFeature.js.map +1 -1
  11. package/dist/src/classRegistry.d.ts +7 -1
  12. package/dist/src/classRegistry.js.map +1 -1
  13. package/dist/src/featureProvider/abstractAttributeProvider.d.ts +62 -0
  14. package/dist/src/featureProvider/abstractAttributeProvider.js +129 -0
  15. package/dist/src/featureProvider/abstractAttributeProvider.js.map +1 -0
  16. package/dist/src/featureProvider/abstractFeatureProvider.d.ts +9 -18
  17. package/dist/src/featureProvider/abstractFeatureProvider.js +7 -38
  18. package/dist/src/featureProvider/abstractFeatureProvider.js.map +1 -1
  19. package/dist/src/featureProvider/compositeFeatureProvider.d.ts +27 -0
  20. package/dist/src/featureProvider/compositeFeatureProvider.js +53 -0
  21. package/dist/src/featureProvider/compositeFeatureProvider.js.map +1 -0
  22. package/dist/src/featureProvider/csvAttributeProvider.d.ts +41 -0
  23. package/dist/src/featureProvider/csvAttributeProvider.js +126 -0
  24. package/dist/src/featureProvider/csvAttributeProvider.js.map +1 -0
  25. package/dist/src/featureProvider/featureProviderFactory.d.ts +3 -0
  26. package/dist/src/featureProvider/featureProviderFactory.js +17 -0
  27. package/dist/src/featureProvider/featureProviderFactory.js.map +1 -0
  28. package/dist/src/featureProvider/i3sAttributeProvider.d.ts +7 -0
  29. package/dist/src/featureProvider/i3sAttributeProvider.js +43 -0
  30. package/dist/src/featureProvider/i3sAttributeProvider.js.map +1 -0
  31. package/dist/src/featureProvider/jsonAttributeProvider.d.ts +26 -0
  32. package/dist/src/featureProvider/jsonAttributeProvider.js +73 -0
  33. package/dist/src/featureProvider/jsonAttributeProvider.js.map +1 -0
  34. package/dist/src/featureProvider/tileProviderFeatureProvider.d.ts +4 -6
  35. package/dist/src/featureProvider/tileProviderFeatureProvider.js +9 -11
  36. package/dist/src/featureProvider/tileProviderFeatureProvider.js.map +1 -1
  37. package/dist/src/featureProvider/urlIdAttributeProvider.d.ts +28 -0
  38. package/dist/src/featureProvider/urlIdAttributeProvider.js +50 -0
  39. package/dist/src/featureProvider/urlIdAttributeProvider.js.map +1 -0
  40. package/dist/src/featureProvider/wmsFeatureProvider.d.ts +12 -3
  41. package/dist/src/featureProvider/wmsFeatureProvider.js +17 -6
  42. package/dist/src/featureProvider/wmsFeatureProvider.js.map +1 -1
  43. package/dist/src/interaction/featureAtPixelInteraction.d.ts +15 -3
  44. package/dist/src/interaction/featureAtPixelInteraction.js +41 -1
  45. package/dist/src/interaction/featureAtPixelInteraction.js.map +1 -1
  46. package/dist/src/interaction/featureProviderInteraction.js +42 -26
  47. package/dist/src/interaction/featureProviderInteraction.js.map +1 -1
  48. package/dist/src/layer/cesium/cesiumTilesetCesiumImpl.d.ts +14 -5
  49. package/dist/src/layer/cesium/cesiumTilesetCesiumImpl.js +243 -128
  50. package/dist/src/layer/cesium/cesiumTilesetCesiumImpl.js.map +1 -1
  51. package/dist/src/layer/cesium/i3sCesiumImpl.d.ts +33 -0
  52. package/dist/src/layer/cesium/i3sCesiumImpl.js +107 -0
  53. package/dist/src/layer/cesium/i3sCesiumImpl.js.map +1 -0
  54. package/dist/src/layer/cesium/vcsTile/vcsQuadtreeTileProvider.js +2 -1
  55. package/dist/src/layer/cesium/vcsTile/vcsQuadtreeTileProvider.js.map +1 -1
  56. package/dist/src/layer/cesium/vectorRasterTileCesiumImpl.js +7 -6
  57. package/dist/src/layer/cesium/vectorRasterTileCesiumImpl.js.map +1 -1
  58. package/dist/src/layer/cesium/vectorTileImageryProvider.js +2 -2
  59. package/dist/src/layer/cesium/vectorTileImageryProvider.js.map +1 -1
  60. package/dist/src/layer/cesiumTilesetLayer.d.ts +9 -0
  61. package/dist/src/layer/cesiumTilesetLayer.js +26 -1
  62. package/dist/src/layer/cesiumTilesetLayer.js.map +1 -1
  63. package/dist/src/layer/i3sLayer.d.ts +80 -0
  64. package/dist/src/layer/i3sLayer.js +242 -0
  65. package/dist/src/layer/i3sLayer.js.map +1 -0
  66. package/dist/src/layer/layer.d.ts +8 -3
  67. package/dist/src/layer/layer.js +7 -1
  68. package/dist/src/layer/layer.js.map +1 -1
  69. package/dist/src/layer/layerSymbols.d.ts +4 -0
  70. package/dist/src/layer/layerSymbols.js +4 -0
  71. package/dist/src/layer/layerSymbols.js.map +1 -1
  72. package/dist/src/layer/panoramaDatasetLayer.d.ts +2 -0
  73. package/dist/src/layer/panoramaDatasetLayer.js +33 -13
  74. package/dist/src/layer/panoramaDatasetLayer.js.map +1 -1
  75. package/dist/src/layer/tileProvider/flatGeobufTileProvider.js +3 -2
  76. package/dist/src/layer/tileProvider/flatGeobufTileProvider.js.map +1 -1
  77. package/dist/src/layer/tileProvider/mvtTileProvider.js +3 -2
  78. package/dist/src/layer/tileProvider/mvtTileProvider.js.map +1 -1
  79. package/dist/src/layer/tileProvider/tileProvider.d.ts +6 -0
  80. package/dist/src/layer/tileProvider/tileProvider.js +12 -1
  81. package/dist/src/layer/tileProvider/tileProvider.js.map +1 -1
  82. package/dist/src/layer/vectorLayer.js +2 -2
  83. package/dist/src/layer/vectorLayer.js.map +1 -1
  84. package/dist/src/layer/vectorProperties.js +10 -1
  85. package/dist/src/layer/vectorProperties.js.map +1 -1
  86. package/dist/src/layer/vectorTileLayer.d.ts +14 -5
  87. package/dist/src/layer/vectorTileLayer.js +78 -26
  88. package/dist/src/layer/vectorTileLayer.js.map +1 -1
  89. package/dist/src/layer/wmsLayer.d.ts +3 -0
  90. package/dist/src/layer/wmsLayer.js +62 -32
  91. package/dist/src/layer/wmsLayer.js.map +1 -1
  92. package/dist/src/map/baseCesiumMap.d.ts +4 -4
  93. package/dist/src/map/baseCesiumMap.js +12 -0
  94. package/dist/src/map/baseCesiumMap.js.map +1 -1
  95. package/dist/src/map/cesiumMap.js +0 -11
  96. package/dist/src/map/cesiumMap.js.map +1 -1
  97. package/dist/src/map/obliqueMap.js +11 -4
  98. package/dist/src/map/obliqueMap.js.map +1 -1
  99. package/dist/src/map/panoramaMap.js +1 -1
  100. package/dist/src/panorama/panoramaImage.js +6 -5
  101. package/dist/src/panorama/panoramaImage.js.map +1 -1
  102. package/dist/src/style/declarativeStyleItem.js +7 -8
  103. package/dist/src/style/declarativeStyleItem.js.map +1 -1
  104. package/dist/src/util/fetch.d.ts +7 -0
  105. package/dist/src/util/fetch.js +7 -0
  106. package/dist/src/util/fetch.js.map +1 -1
  107. package/dist/src/vcsApp.d.ts +2 -3
  108. package/dist/src/vcsApp.js.map +1 -1
  109. package/dist/src/vcsModuleHelpers.d.ts +5 -2
  110. package/dist/src/vcsModuleHelpers.js +27 -1
  111. package/dist/src/vcsModuleHelpers.js.map +1 -1
  112. package/dist/tests/unit/helpers/cesiumHelpers.js +7 -1
  113. package/dist/tests/unit/helpers/cesiumHelpers.js.map +1 -1
  114. package/index.ts +27 -0
  115. package/package.json +2 -2
  116. package/src/cesium/cesium.d.ts +12 -0
  117. package/src/cesium/cesium3DTileFeature.ts +25 -3
  118. package/src/cesium/cesium3DTilePointFeature.ts +3 -1
  119. package/src/classRegistry.ts +8 -3
  120. package/src/featureProvider/abstractAttributeProvider.ts +201 -0
  121. package/src/featureProvider/abstractFeatureProvider.ts +27 -47
  122. package/src/featureProvider/compositeFeatureProvider.ts +103 -0
  123. package/src/featureProvider/csvAttributeProvider.ts +186 -0
  124. package/src/featureProvider/featureProviderFactory.ts +31 -0
  125. package/src/featureProvider/i3sAttributeProvider.ts +60 -0
  126. package/src/featureProvider/jsonAttributeProvider.ts +109 -0
  127. package/src/featureProvider/tileProviderFeatureProvider.ts +13 -14
  128. package/src/featureProvider/urlIdAttributeProvider.ts +82 -0
  129. package/src/featureProvider/wmsFeatureProvider.ts +24 -7
  130. package/src/global.d.ts +2 -0
  131. package/src/interaction/featureAtPixelInteraction.ts +53 -3
  132. package/src/interaction/featureProviderInteraction.ts +59 -38
  133. package/src/layer/cesium/cesiumTilesetCesiumImpl.ts +296 -157
  134. package/src/layer/cesium/i3sCesiumImpl.ts +141 -0
  135. package/src/layer/cesium/vcsTile/vcsQuadtreeTileProvider.ts +4 -3
  136. package/src/layer/cesium/vectorRasterTileCesiumImpl.ts +7 -6
  137. package/src/layer/cesium/vectorTileImageryProvider.ts +2 -2
  138. package/src/layer/cesiumTilesetLayer.ts +51 -1
  139. package/src/layer/i3sLayer.ts +343 -0
  140. package/src/layer/layer.ts +30 -3
  141. package/src/layer/layerSymbols.ts +5 -0
  142. package/src/layer/panoramaDatasetLayer.ts +44 -13
  143. package/src/layer/tileProvider/flatGeobufTileProvider.ts +3 -2
  144. package/src/layer/tileProvider/mvtTileProvider.ts +3 -2
  145. package/src/layer/tileProvider/tileProvider.ts +13 -1
  146. package/src/layer/vectorLayer.ts +4 -2
  147. package/src/layer/vectorProperties.ts +10 -1
  148. package/src/layer/vectorTileLayer.ts +135 -47
  149. package/src/layer/wmsLayer.ts +77 -44
  150. package/src/map/baseCesiumMap.ts +29 -5
  151. package/src/map/cesiumMap.ts +0 -15
  152. package/src/map/obliqueMap.ts +13 -6
  153. package/src/map/panoramaMap.ts +1 -1
  154. package/src/ol/ol.d.ts +13 -2
  155. package/src/panorama/panoramaImage.ts +8 -5
  156. package/src/style/declarativeStyleItem.ts +7 -9
  157. package/src/util/fetch.ts +7 -0
  158. package/src/vcsApp.ts +7 -8
  159. package/src/vcsModuleHelpers.ts +62 -4
@@ -3,6 +3,8 @@ import type {
3
3
  Cesium3DTileContent,
4
4
  SplitDirection,
5
5
  CustomShader,
6
+ TileBoundingVolume,
7
+ BoundingSphere,
6
8
  } from '@vcmap-cesium/engine';
7
9
  import {
8
10
  Composite3DTileContent,
@@ -38,6 +40,8 @@ import type StyleItem from '../../style/styleItem.js';
38
40
  import type GlobalHider from '../globalHider.js';
39
41
  import { getResourceOrUrl } from './resourceHelper.js';
40
42
  import type BaseCesiumMap from '../../map/baseCesiumMap.js';
43
+ import type { AttributeProvider } from '../../featureProvider/abstractAttributeProvider.js';
44
+ import type I3SCesiumImpl from './i3sCesiumImpl.js';
41
45
 
42
46
  export const cesiumTilesetLastUpdated: unique symbol = Symbol(
43
47
  'cesiumTilesetLastUpdated',
@@ -47,13 +51,11 @@ export const updateFeatureOverride: unique symbol = Symbol(
47
51
  'updateFeatureOverride',
48
52
  );
49
53
 
50
- export function getExtentFromTileset(
51
- cesium3DTileset?: Cesium3DTileset,
54
+ function getExtentFromBoundingVolume(
55
+ boundingVolume: TileBoundingVolume,
56
+ boundingSphere: BoundingSphere,
52
57
  ): OLExtent {
53
- if (!cesium3DTileset) {
54
- return createEmpty();
55
- }
56
- const { rectangle } = cesium3DTileset.root.boundingVolume;
58
+ const { rectangle } = boundingVolume;
57
59
  if (rectangle) {
58
60
  const scratchSW = Rectangle.southwest(rectangle);
59
61
  const scratchNE = Rectangle.northeast(rectangle);
@@ -69,7 +71,7 @@ export function getExtentFromTileset(
69
71
  return [mercatorSW[0], mercatorSW[1], mercatorNE[0], mercatorNE[1]];
70
72
  }
71
73
 
72
- const { center, radius } = cesium3DTileset.boundingSphere;
74
+ const { center, radius } = boundingSphere;
73
75
  const cart = Cartographic.fromCartesian(center);
74
76
  const mercatorCenter = Projection.wgs84ToMercator([
75
77
  CesiumMath.toDegrees(cart.longitude),
@@ -80,6 +82,274 @@ export function getExtentFromTileset(
80
82
  return circle.getExtent();
81
83
  }
82
84
 
85
+ export function getExtentFromTileset(
86
+ cesium3DTileset?: Cesium3DTileset,
87
+ ): OLExtent {
88
+ if (!cesium3DTileset) {
89
+ return createEmpty();
90
+ }
91
+ return getExtentFromBoundingVolume(
92
+ cesium3DTileset.root.boundingVolume,
93
+ cesium3DTileset.boundingSphere,
94
+ );
95
+ }
96
+
97
+ export function createCesiumStylingContext(
98
+ impl: CesiumTilesetCesiumImpl | I3SCesiumImpl,
99
+ ): {
100
+ styleContent: (content: Cesium3DTileContent) => void;
101
+ updateStyle: (style: StyleItem) => void;
102
+ applyStyle: (tile: Cesium3DTile) => void;
103
+ destroy: () => void;
104
+ } {
105
+ let styleLastUpdated = 0;
106
+ let onStyleChangeRemover: (() => void) | null = null;
107
+ let onFeatureVisibilityChangeRemover: (() => void) | null = null;
108
+
109
+ function styleContent(content: Cesium3DTileContent): void {
110
+ const styleHasChanged =
111
+ styleLastUpdated > (content[cesiumTilesetLastUpdated] ?? 0);
112
+
113
+ if (
114
+ !content[cesiumTilesetLastUpdated] ||
115
+ content[cesiumTilesetLastUpdated] < impl.featureVisibility.lastUpdated ||
116
+ content[cesiumTilesetLastUpdated] <
117
+ (impl.globalHider?.lastUpdated ?? 0) ||
118
+ styleHasChanged
119
+ ) {
120
+ delete content[updateFeatureOverride];
121
+ const batchSize = content.featuresLength;
122
+ const featureOverride = {
123
+ hideLocal: [] as [string, HighlightableFeature][],
124
+ hideGlobal: [] as [string, HighlightableFeature][],
125
+ highlight: [] as [string, HighlightableFeature][],
126
+ };
127
+ for (let batchId = 0; batchId < batchSize; batchId++) {
128
+ const feature = content.getFeature(batchId);
129
+ if (feature) {
130
+ const id = String(feature.getId());
131
+ let shouldUpdateOriginalStyle = true;
132
+ if (
133
+ impl.featureVisibility.highlightedObjects[id] &&
134
+ !impl.featureVisibility.hasHighlightFeature(id, feature)
135
+ ) {
136
+ impl.featureVisibility.addHighlightFeature(id, feature);
137
+ featureOverride.highlight.push([id, feature]);
138
+ shouldUpdateOriginalStyle = false;
139
+ } else if (
140
+ impl.featureVisibility.hasHighlightFeature(id, feature) &&
141
+ styleHasChanged &&
142
+ feature[originalStyle]
143
+ ) {
144
+ // Feature is already highlighted and style has changed
145
+ // Clear the old cached style - when unhighlighted, we'll force a tileset style update
146
+ delete feature[originalStyle];
147
+ featureOverride.highlight.push([id, feature]);
148
+ shouldUpdateOriginalStyle = false;
149
+ }
150
+
151
+ if (impl.featureVisibility.hiddenObjects[id]) {
152
+ if (!impl.featureVisibility.hasHiddenFeature(id, feature)) {
153
+ impl.featureVisibility.addHiddenFeature(id, feature);
154
+ featureOverride.hideLocal.push([id, feature]);
155
+ } else if (styleHasChanged && feature[originalStyle]) {
156
+ // Feature is already hidden and style has changed, clear original style
157
+ // so it will be re-cached with the new style when shown
158
+ delete feature[originalStyle];
159
+ }
160
+ shouldUpdateOriginalStyle = false;
161
+ }
162
+
163
+ if (impl.globalHider?.hiddenObjects[id]) {
164
+ if (!impl.globalHider?.hasFeature(id, feature)) {
165
+ impl.globalHider?.addFeature(id, feature);
166
+ }
167
+ featureOverride.hideGlobal.push([id, feature]);
168
+ if (styleHasChanged && feature[originalStyle]) {
169
+ // Feature is globally hidden and style has changed, clear original style
170
+ delete feature[originalStyle];
171
+ }
172
+ shouldUpdateOriginalStyle = false;
173
+ }
174
+
175
+ if (
176
+ shouldUpdateOriginalStyle &&
177
+ styleHasChanged &&
178
+ feature[originalStyle] // can only be a color for cesium, so no check for undefined required
179
+ ) {
180
+ updateOriginalStyle(feature);
181
+ }
182
+ }
183
+ }
184
+ if (
185
+ featureOverride.hideLocal.length > 0 ||
186
+ featureOverride.hideGlobal.length > 0 ||
187
+ featureOverride.highlight.length > 0
188
+ ) {
189
+ content[updateFeatureOverride] = (): void => {
190
+ featureOverride.hideGlobal.forEach(([id, feature]) => {
191
+ if (impl.globalHider?.hasFeature(id, feature)) {
192
+ hideFeature(feature);
193
+ }
194
+ });
195
+
196
+ featureOverride.hideLocal.forEach(([id, feature]) => {
197
+ if (impl.featureVisibility.hasHiddenFeature(id, feature)) {
198
+ hideFeature(feature);
199
+ }
200
+ });
201
+
202
+ featureOverride.highlight.forEach(([id, feature]) => {
203
+ if (impl.featureVisibility.hasHighlightFeature(id, feature)) {
204
+ highlightFeature(feature);
205
+ }
206
+ });
207
+ };
208
+ }
209
+ content[cesiumTilesetLastUpdated] = Date.now();
210
+ } else {
211
+ content[updateFeatureOverride]?.();
212
+ }
213
+ }
214
+ function updateStyle(style: StyleItem): void {
215
+ impl.style = style;
216
+
217
+ function updateTilesetStyle(tileset: Cesium3DTileset): void {
218
+ tileset.style = impl.style.cesiumStyle;
219
+ if (onStyleChangeRemover) {
220
+ onStyleChangeRemover();
221
+ }
222
+ styleLastUpdated = Date.now();
223
+ if (tileset.colorBlendMode !== impl.style.colorBlendMode) {
224
+ // we only support replace and mix mode if the _3DTILESDIFFUSE Flag is set in the tileset
225
+ if (
226
+ impl.style.colorBlendMode !== Cesium3DTileColorBlendMode.HIGHLIGHT
227
+ ) {
228
+ if (
229
+ tileset.extras &&
230
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,no-underscore-dangle
231
+ (tileset.extras._3DTILESDIFFUSE as boolean)
232
+ ) {
233
+ tileset.colorBlendMode = impl.style.colorBlendMode;
234
+ }
235
+ } else {
236
+ tileset.colorBlendMode = impl.style.colorBlendMode;
237
+ }
238
+ }
239
+ }
240
+ if (impl.initialized) {
241
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
242
+ if (impl instanceof CesiumTilesetCesiumImpl) {
243
+ if (impl.cesium3DTileset) {
244
+ updateTilesetStyle(impl.cesium3DTileset);
245
+ onStyleChangeRemover = impl.style.styleChanged.addEventListener(
246
+ () => {
247
+ impl.cesium3DTileset?.makeStyleDirty();
248
+ styleLastUpdated = Date.now();
249
+ },
250
+ );
251
+ }
252
+ } else if (impl.data) {
253
+ impl.data.layers.forEach(({ tileset }) => {
254
+ if (tileset) {
255
+ updateTilesetStyle(tileset);
256
+ }
257
+ });
258
+ onStyleChangeRemover = impl.style.styleChanged.addEventListener(() => {
259
+ impl.data?.layers.forEach(({ tileset }) => {
260
+ tileset?.makeStyleDirty();
261
+ });
262
+ styleLastUpdated = Date.now();
263
+ });
264
+ }
265
+ }
266
+ }
267
+ function applyStyle(tile: Cesium3DTile): void {
268
+ if (tile.contentReady) {
269
+ if (tile.content instanceof Composite3DTileContent) {
270
+ for (let i = 0; i < tile.content.innerContents.length; i++) {
271
+ styleContent(tile.content.innerContents[i] as Cesium3DTileContent);
272
+ }
273
+ } else {
274
+ styleContent(tile.content);
275
+ }
276
+ }
277
+ }
278
+
279
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
280
+ if (impl instanceof CesiumTilesetCesiumImpl) {
281
+ onFeatureVisibilityChangeRemover =
282
+ impl.featureVisibility.changed.addEventListener(() => {
283
+ impl.cesium3DTileset?.makeStyleDirty();
284
+ });
285
+ } else {
286
+ onFeatureVisibilityChangeRemover =
287
+ impl.featureVisibility.changed.addEventListener(() => {
288
+ impl.data?.layers.forEach(({ tileset }) => {
289
+ tileset?.makeStyleDirty();
290
+ });
291
+ styleLastUpdated = Date.now();
292
+ });
293
+ }
294
+
295
+ return {
296
+ styleContent,
297
+ updateStyle,
298
+ applyStyle,
299
+ destroy: (): void => {
300
+ if (onStyleChangeRemover) {
301
+ onStyleChangeRemover();
302
+ onStyleChangeRemover = null;
303
+ }
304
+ if (onFeatureVisibilityChangeRemover) {
305
+ onFeatureVisibilityChangeRemover();
306
+ onFeatureVisibilityChangeRemover = null;
307
+ }
308
+ },
309
+ };
310
+ }
311
+
312
+ export function createTilesetEventListeners(
313
+ impl: CesiumTilesetCesiumImpl | I3SCesiumImpl,
314
+ tileset: Cesium3DTileset,
315
+ ): void {
316
+ function tileLoadedHandler(tile: Cesium3DTile): void {
317
+ if (impl.attributeProvider) {
318
+ const extent = getExtentFromBoundingVolume(
319
+ tile.contentBoundingVolume,
320
+ tile.boundingSphere,
321
+ );
322
+ const features: HighlightableFeature[] = [];
323
+ const batchSize = tile.content.featuresLength;
324
+ for (let batchId = 0; batchId < batchSize; batchId++) {
325
+ const feature = tile.content.getFeature(batchId);
326
+ if (feature) {
327
+ features.push(feature);
328
+ }
329
+ }
330
+
331
+ impl.attributeProvider
332
+ .augmentFeatures(features, extent)
333
+ .then(() => {
334
+ impl.applyStyle(tile);
335
+ })
336
+ .catch((err: unknown) => {
337
+ impl
338
+ .getLogger()
339
+ .error(`Error augmenting features in ${impl.className}:`, err);
340
+ });
341
+ }
342
+ }
343
+
344
+ tileset.tileLoad.addEventListener(tileLoadedHandler);
345
+ tileset.tileVisible.addEventListener(impl.applyStyle);
346
+ tileset.tileUnload.addEventListener((tile: Cesium3DTile) => {
347
+ delete tile[cesiumTilesetLastUpdated];
348
+ delete tile.content[cesiumTilesetLastUpdated];
349
+ delete tile.content[updateFeatureOverride];
350
+ });
351
+ }
352
+
83
353
  /**
84
354
  * represents the cesium implementation for a {@link CesiumTilesetLayer} layer.
85
355
  */
@@ -111,16 +381,22 @@ class CesiumTilesetCesiumImpl
111
381
 
112
382
  allowPicking: boolean;
113
383
 
384
+ attributeProvider?: AttributeProvider;
385
+
114
386
  private _initializedPromise: Promise<Cesium3DTileset> | null = null;
115
387
 
116
388
  private _originalOrigin: Cartesian3 | null = null;
117
389
 
118
- private _styleLastUpdated: number = Date.now();
119
-
120
- private _onStyleChangeRemover: (() => void) | null = null;
390
+ private _destroyStyle: (() => void) | null = null;
121
391
 
122
392
  private _customShader: CustomShader | undefined;
123
393
 
394
+ styleContent: (content: Cesium3DTileContent) => void;
395
+
396
+ updateStyle: (style: StyleItem) => void;
397
+
398
+ applyStyle: (tile: Cesium3DTile) => void;
399
+
124
400
  constructor(map: BaseCesiumMap, options: CesiumTilesetImplementationOptions) {
125
401
  super(map, options);
126
402
 
@@ -135,6 +411,13 @@ class CesiumTilesetCesiumImpl
135
411
  this.offset = options.offset;
136
412
  this._customShader = options.customShader;
137
413
  this.allowPicking = options.allowPicking;
414
+ this.attributeProvider = options.attributeProvider;
415
+
416
+ const stylingContext = createCesiumStylingContext(this);
417
+ this.styleContent = stylingContext.styleContent;
418
+ this.updateStyle = stylingContext.updateStyle;
419
+ this.applyStyle = stylingContext.applyStyle;
420
+ this._destroyStyle = stylingContext.destroy;
138
421
  }
139
422
 
140
423
  get customShader(): CustomShader | undefined {
@@ -184,14 +467,7 @@ class CesiumTilesetCesiumImpl
184
467
  }
185
468
  this.cesium3DTileset[vcsLayerName] = this.name;
186
469
  this.cesium3DTileset[allowPicking] = this.allowPicking;
187
- this.cesium3DTileset.tileVisible.addEventListener(
188
- this.applyStyle.bind(this),
189
- );
190
- this.cesium3DTileset.tileUnload.addEventListener((tile: Cesium3DTile) => {
191
- delete tile[cesiumTilesetLastUpdated];
192
- delete tile.content[cesiumTilesetLastUpdated];
193
- delete tile.content[updateFeatureOverride];
194
- });
470
+ createTilesetEventListeners(this, this.cesium3DTileset);
195
471
 
196
472
  this._originalOrigin = Cartesian3.clone(
197
473
  this.cesium3DTileset.boundingSphere.center,
@@ -275,39 +551,6 @@ class CesiumTilesetCesiumImpl
275
551
  }
276
552
  }
277
553
 
278
- updateStyle(style: StyleItem): void {
279
- this.style = style;
280
- if (this.initialized && this.cesium3DTileset) {
281
- this.cesium3DTileset.style = this.style.cesiumStyle;
282
- if (this._onStyleChangeRemover) {
283
- this._onStyleChangeRemover();
284
- }
285
- this._onStyleChangeRemover = this.style.styleChanged.addEventListener(
286
- () => {
287
- this.cesium3DTileset?.makeStyleDirty();
288
- this._styleLastUpdated = Date.now();
289
- },
290
- );
291
- this._styleLastUpdated = Date.now();
292
- if (this.cesium3DTileset.colorBlendMode !== this.style.colorBlendMode) {
293
- // we only support replace and mix mode if the _3DTILESDIFFUSE Flag is set in the tileset
294
- if (
295
- this.style.colorBlendMode !== Cesium3DTileColorBlendMode.HIGHLIGHT
296
- ) {
297
- if (
298
- this.cesium3DTileset.extras &&
299
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,no-underscore-dangle
300
- (this.cesium3DTileset.extras._3DTILESDIFFUSE as boolean)
301
- ) {
302
- this.cesium3DTileset.colorBlendMode = this.style.colorBlendMode;
303
- }
304
- } else {
305
- this.cesium3DTileset.colorBlendMode = this.style.colorBlendMode;
306
- }
307
- }
308
- }
309
- }
310
-
311
554
  updateSplitDirection(splitDirection: SplitDirection): void {
312
555
  this.splitDirection = splitDirection;
313
556
  if (this.cesium3DTileset) {
@@ -315,110 +558,6 @@ class CesiumTilesetCesiumImpl
315
558
  }
316
559
  }
317
560
 
318
- applyStyle(tile: Cesium3DTile): void {
319
- if (tile.contentReady) {
320
- if (tile.content instanceof Composite3DTileContent) {
321
- for (let i = 0; i < tile.content.innerContents.length; i++) {
322
- this.styleContent(
323
- tile.content.innerContents[i] as Cesium3DTileContent,
324
- );
325
- }
326
- } else {
327
- this.styleContent(tile.content);
328
- }
329
- }
330
- }
331
-
332
- styleContent(content: Cesium3DTileContent): void {
333
- if (
334
- !content[cesiumTilesetLastUpdated] ||
335
- content[cesiumTilesetLastUpdated] < this.featureVisibility.lastUpdated ||
336
- content[cesiumTilesetLastUpdated] <
337
- (this.globalHider?.lastUpdated ?? 0) ||
338
- content[cesiumTilesetLastUpdated] < this._styleLastUpdated
339
- ) {
340
- // content[updateFeatureOverride]?.reset();
341
- delete content[updateFeatureOverride];
342
- const batchSize = content.featuresLength;
343
- const featureOverride = {
344
- hideLocal: [] as [string, HighlightableFeature][],
345
- hideGlobal: [] as [string, HighlightableFeature][],
346
- highlight: [] as [string, HighlightableFeature][],
347
- };
348
- for (let batchId = 0; batchId < batchSize; batchId++) {
349
- const feature = content.getFeature(batchId);
350
- if (feature) {
351
- let id = feature.getProperty('id') as string | undefined;
352
- if (!id) {
353
- id = `${content.url}${String(batchId)}`;
354
- }
355
-
356
- let shouldUpdateOriginalStyle = true;
357
- if (
358
- this.featureVisibility.highlightedObjects[id] &&
359
- !this.featureVisibility.hasHighlightFeature(id, feature)
360
- ) {
361
- this.featureVisibility.addHighlightFeature(id, feature);
362
- featureOverride.highlight.push([id, feature]);
363
- shouldUpdateOriginalStyle = false;
364
- }
365
-
366
- if (
367
- this.featureVisibility.hiddenObjects[id] &&
368
- !this.featureVisibility.hasHiddenFeature(id, feature)
369
- ) {
370
- this.featureVisibility.addHiddenFeature(id, feature);
371
- featureOverride.hideLocal.push([id, feature]);
372
- }
373
-
374
- if (
375
- this.globalHider?.hiddenObjects[id] &&
376
- !this.globalHider?.hasFeature(id, feature)
377
- ) {
378
- this.globalHider?.addFeature(id, feature);
379
- featureOverride.hideGlobal.push([id, feature]);
380
- }
381
-
382
- if (
383
- shouldUpdateOriginalStyle &&
384
- this._styleLastUpdated > (content[cesiumTilesetLastUpdated] ?? 0) &&
385
- feature[originalStyle] // can only be a color for cesium, so no check for undefined required
386
- ) {
387
- updateOriginalStyle(feature);
388
- }
389
- }
390
- }
391
- if (
392
- featureOverride.hideLocal.length > 0 ||
393
- featureOverride.hideGlobal.length > 0 ||
394
- featureOverride.highlight.length > 0
395
- ) {
396
- content[updateFeatureOverride] = (): void => {
397
- featureOverride.hideGlobal.forEach(([id, feature]) => {
398
- if (this.globalHider?.hasFeature(id, feature)) {
399
- hideFeature(feature);
400
- }
401
- });
402
-
403
- featureOverride.hideLocal.forEach(([id, feature]) => {
404
- if (this.featureVisibility.hasHiddenFeature(id, feature)) {
405
- hideFeature(feature);
406
- }
407
- });
408
-
409
- featureOverride.highlight.forEach(([id, feature]) => {
410
- if (this.featureVisibility.hasHighlightFeature(id, feature)) {
411
- highlightFeature(feature);
412
- }
413
- });
414
- };
415
- }
416
- content[cesiumTilesetLastUpdated] = Date.now();
417
- } else {
418
- content[updateFeatureOverride]?.();
419
- }
420
- }
421
-
422
561
  destroy(): void {
423
562
  if (this.cesium3DTileset) {
424
563
  if (this.map.initialized) {
@@ -431,8 +570,8 @@ class CesiumTilesetCesiumImpl
431
570
  this.cesium3DTileset = null;
432
571
  }
433
572
 
434
- if (this._onStyleChangeRemover) {
435
- this._onStyleChangeRemover();
573
+ if (this._destroyStyle) {
574
+ this._destroyStyle();
436
575
  }
437
576
 
438
577
  super.destroy();
@@ -0,0 +1,141 @@
1
+ import type {
2
+ Cesium3DTile,
3
+ Cesium3DTileContent,
4
+ SplitDirection,
5
+ } from '@vcmap-cesium/engine';
6
+ import { I3SDataProvider } from '@vcmap-cesium/engine';
7
+ import type BaseCesiumMap from '../../map/baseCesiumMap.js';
8
+ import type StyleItem from '../../style/styleItem.js';
9
+ import type { AttributeProvider } from '../../featureProvider/abstractAttributeProvider.js';
10
+ import type { FeatureLayerImplementation } from '../featureLayer.js';
11
+ import type FeatureVisibility from '../featureVisibility.js';
12
+ import type GlobalHider from '../globalHider.js';
13
+ import type { I3SImplementationOptions } from '../i3sLayer.js';
14
+ import LayerImplementation from '../layerImplementation.js';
15
+ import { allowPicking, vcsLayerName } from '../layerSymbols.js';
16
+ import { getResourceOrUrl } from './resourceHelper.js';
17
+ import {
18
+ createCesiumStylingContext,
19
+ createTilesetEventListeners,
20
+ } from './cesiumTilesetCesiumImpl.js';
21
+
22
+ class I3SCesiumImpl
23
+ extends LayerImplementation<BaseCesiumMap>
24
+ implements FeatureLayerImplementation
25
+ {
26
+ static get className(): string {
27
+ return 'I3SCesiumImpl';
28
+ }
29
+
30
+ data: I3SDataProvider | null;
31
+ i3sOptions: I3SImplementationOptions;
32
+ splitDirection: SplitDirection;
33
+ style: StyleItem;
34
+ featureVisibility: FeatureVisibility;
35
+ globalHider: GlobalHider | undefined;
36
+ allowPicking: boolean;
37
+
38
+ attributeProvider?: AttributeProvider;
39
+ private _initializedPromise: Promise<I3SDataProvider> | null = null;
40
+ private _destroyStyle: (() => void) | null = null;
41
+ styleContent: (content: Cesium3DTileContent) => void;
42
+ updateStyle: (style: StyleItem) => void;
43
+ applyStyle: (tile: Cesium3DTile) => void;
44
+
45
+ constructor(map: BaseCesiumMap, options: I3SImplementationOptions) {
46
+ super(map, options);
47
+ this.data = null;
48
+ this.i3sOptions = options;
49
+ this.splitDirection = options.splitDirection;
50
+ this.style = options.style;
51
+ this.featureVisibility = options.featureVisibility;
52
+ this.globalHider = options.globalHider;
53
+ this.allowPicking = options.allowPicking;
54
+ this.attributeProvider = options.attributeProvider;
55
+
56
+ const stylingContext = createCesiumStylingContext(this);
57
+ this.styleContent = stylingContext.styleContent;
58
+ this.updateStyle = stylingContext.updateStyle;
59
+ this.applyStyle = stylingContext.applyStyle;
60
+ this._destroyStyle = stylingContext.destroy;
61
+ }
62
+
63
+ async initialize(): Promise<void> {
64
+ if (!this._initializedPromise) {
65
+ this._initializedPromise = I3SDataProvider.fromUrl(
66
+ getResourceOrUrl(this.url!, this.headers),
67
+ { ...this.i3sOptions, show: false },
68
+ );
69
+ this.data = await this._initializedPromise;
70
+
71
+ if (this.isDestroyed) {
72
+ this.data.destroy();
73
+ return;
74
+ }
75
+ this.data[vcsLayerName] = this.name;
76
+ this.data[allowPicking] = this.allowPicking;
77
+ this.data.layers.forEach(({ tileset }) => {
78
+ if (tileset) {
79
+ createTilesetEventListeners(this, tileset);
80
+ }
81
+ });
82
+
83
+ this.map.addPrimitiveCollection(this.data);
84
+ await super.initialize();
85
+
86
+ if (this.splitDirection) {
87
+ this.data.layers.forEach(({ tileset }) => {
88
+ if (tileset) {
89
+ tileset.splitDirection = this.splitDirection;
90
+ }
91
+ });
92
+ }
93
+ this.updateStyle(this.style);
94
+ }
95
+ await this._initializedPromise;
96
+ }
97
+
98
+ async activate(): Promise<void> {
99
+ await super.activate();
100
+ if (this.active && this.data) {
101
+ this.data.show = true;
102
+ }
103
+ }
104
+
105
+ deactivate(): void {
106
+ super.deactivate();
107
+ if (this.data) {
108
+ this.data.show = false;
109
+ }
110
+ }
111
+
112
+ updateSplitDirection(splitDirection: SplitDirection): void {
113
+ this.splitDirection = splitDirection;
114
+ if (this.data) {
115
+ this.data.layers.forEach(({ tileset }) => {
116
+ if (tileset) {
117
+ tileset.splitDirection = splitDirection;
118
+ }
119
+ });
120
+ }
121
+ }
122
+
123
+ destroy(): void {
124
+ if (this.data) {
125
+ if (this.map.initialized) {
126
+ const toRemove = this.data;
127
+ this.map.removePrimitiveCollection(toRemove);
128
+ } else {
129
+ this.data.destroy();
130
+ }
131
+ this.data = null;
132
+ }
133
+
134
+ if (this._destroyStyle) {
135
+ this._destroyStyle();
136
+ }
137
+
138
+ super.destroy();
139
+ }
140
+ }
141
+ export default I3SCesiumImpl;
@@ -91,10 +91,11 @@ export default class VcsQuadtreeTileProvider
91
91
  this.tilingScheme,
92
92
  );
93
93
 
94
+ const { tileProvider } = layerOptions;
94
95
  const { dataLevels, dataRange } = getDataTiles(
95
- layerOptions.minLevel,
96
- layerOptions.maxLevel,
97
- layerOptions.tileProvider,
96
+ layerOptions.minLevel ?? tileProvider.baseLevels.at(-1) ?? 0,
97
+ layerOptions.maxLevel ?? tileProvider.baseLevels[0],
98
+ tileProvider,
98
99
  );
99
100
  this._dataLevels = dataLevels;
100
101
  this._dataRange = dataRange;