@vcmap/core 5.0.0-rc.3 → 5.0.0-rc.30

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 (236) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +12 -5
  3. package/build/postinstall.js +14 -3
  4. package/index.d.ts +3477 -2007
  5. package/index.js +169 -131
  6. package/package.json +25 -27
  7. package/src/category/category.js +483 -0
  8. package/src/category/categoryCollection.js +153 -0
  9. package/src/cesium/cesium3DTileFeature.js +2 -2
  10. package/src/cesium/cesium3DTilePointFeature.js +1 -1
  11. package/src/cesium/cesiumVcsCameraPrimitive.js +16 -8
  12. package/src/cesium/entity.js +29 -0
  13. package/src/cesium/wallpaperMaterial.js +5 -3
  14. package/src/classRegistry.js +169 -0
  15. package/src/{vcs/vcm/util/featureProvider → featureProvider}/abstractFeatureProvider.js +49 -46
  16. package/src/{vcs/vcm/util/featureProvider → featureProvider}/tileProviderFeatureProvider.js +13 -5
  17. package/src/{vcs/vcm/util/featureProvider → featureProvider}/wmsFeatureProvider.js +56 -26
  18. package/src/{vcs/vcm/interaction → interaction}/abstractInteraction.js +33 -21
  19. package/src/{vcs/vcm/interaction → interaction}/coordinateAtPixel.js +40 -21
  20. package/src/{vcs/vcm/interaction → interaction}/eventHandler.js +131 -26
  21. package/src/{vcs/vcm/interaction → interaction}/featureAtPixelInteraction.js +108 -53
  22. package/src/interaction/featureProviderInteraction.js +58 -0
  23. package/src/{vcs/vcm/interaction → interaction}/interactionChain.js +40 -41
  24. package/src/{vcs/vcm/interaction → interaction}/interactionType.js +24 -31
  25. package/src/{vcs/vcm/layer/cesium/cesiumTilesetCesium.js → layer/cesium/cesiumTilesetCesiumImpl.js} +67 -55
  26. package/src/{vcs/vcm/layer → layer}/cesium/clusterContext.js +33 -8
  27. package/src/{vcs/vcm/layer/cesium/dataSourceCesium.js → layer/cesium/dataSourceCesiumImpl.js} +24 -13
  28. package/src/layer/cesium/openStreetMapCesiumImpl.js +32 -0
  29. package/src/{vcs/vcm/layer/cesium/rasterLayerCesium.js → layer/cesium/rasterLayerCesiumImpl.js} +12 -9
  30. package/src/{vcs/vcm/layer/cesium/singleImageCesium.js → layer/cesium/singleImageCesiumImpl.js} +19 -9
  31. package/src/{vcs/vcm/layer/cesium/terrainCesium.js → layer/cesium/terrainCesiumImpl.js} +6 -6
  32. package/src/{vcs/vcm/layer/cesium/tmsCesium.js → layer/cesium/tmsCesiumImpl.js} +21 -10
  33. package/src/{vcs/vcm/layer/cesium/vectorCesium.js → layer/cesium/vectorCesiumImpl.js} +93 -35
  34. package/src/layer/cesium/vectorContext.js +363 -0
  35. package/src/{vcs/vcm/layer/cesium/vectorRasterTileCesium.js → layer/cesium/vectorRasterTileCesiumImpl.js} +21 -13
  36. package/src/{vcs/vcm/layer → layer}/cesium/vectorTileImageryProvider.js +58 -21
  37. package/src/{vcs/vcm/layer/cesium/wmsCesium.js → layer/cesium/wmsCesiumImpl.js} +20 -9
  38. package/src/{vcs/vcm/layer/cesium/wmtsCesium.js → layer/cesium/wmtsCesiumImpl.js} +24 -13
  39. package/src/{vcs/vcm/layer → layer}/cesium/x3dmHelper.js +6 -3
  40. package/src/{vcs/vcm/layer/cesiumTileset.js → layer/cesiumTilesetLayer.js} +71 -108
  41. package/src/{vcs/vcm/layer/czml.js → layer/czmlLayer.js} +23 -20
  42. package/src/{vcs/vcm/layer/dataSource.js → layer/dataSourceLayer.js} +55 -90
  43. package/src/{vcs/vcm/layer → layer}/featureLayer.js +89 -74
  44. package/src/{vcs/vcm/layer/featureStore.js → layer/featureStoreLayer.js} +197 -150
  45. package/src/{vcs/vcm/layer/featureStoreChanges.js → layer/featureStoreLayerChanges.js} +150 -92
  46. package/src/{vcs/vcm/layer/featureStoreState.js → layer/featureStoreLayerState.js} +1 -2
  47. package/src/{vcs/vcm/layer → layer}/featureVisibility.js +114 -82
  48. package/src/{vcs/vcm/layer → layer}/geojsonHelpers.js +84 -69
  49. package/src/{vcs/vcm/layer/geojson.js → layer/geojsonLayer.js} +30 -27
  50. package/src/{vcs/vcm/layer → layer}/globalHider.js +25 -39
  51. package/src/{vcs/vcm/layer → layer}/layer.js +171 -96
  52. package/src/{vcs/vcm/layer → layer}/layerImplementation.js +13 -6
  53. package/src/{vcs/vcm/layer → layer}/layerState.js +0 -1
  54. package/src/{vcs/vcm/layer → layer}/layerSymbols.js +2 -1
  55. package/src/{vcs/vcm/layer/oblique/layerOblique.js → layer/oblique/layerObliqueImpl.js} +7 -5
  56. package/src/{vcs/vcm/layer → layer}/oblique/obliqueHelpers.js +76 -31
  57. package/src/{vcs/vcm/layer/oblique/vectorOblique.js → layer/oblique/vectorObliqueImpl.js} +198 -80
  58. package/src/{vcs/vcm/layer/openStreetMap.js → layer/openStreetMapLayer.js} +59 -40
  59. package/src/layer/openlayers/layerOpenlayersImpl.js +165 -0
  60. package/src/layer/openlayers/openStreetMapOpenlayersImpl.js +28 -0
  61. package/src/layer/openlayers/rasterLayerOpenlayersImpl.js +44 -0
  62. package/src/{vcs/vcm/layer/openlayers/singleImageOpenlayers.js → layer/openlayers/singleImageOpenlayersImpl.js} +8 -7
  63. package/src/{vcs/vcm/layer/openlayers/tileDebugOpenlayers.js → layer/openlayers/tileDebugOpenlayersImpl.js} +7 -6
  64. package/src/{vcs/vcm/layer/openlayers/tmsOpenlayers.js → layer/openlayers/tmsOpenlayersImpl.js} +12 -10
  65. package/src/{vcs/vcm/layer/openlayers/vectorOpenlayers.js → layer/openlayers/vectorOpenlayersImpl.js} +21 -12
  66. package/src/{vcs/vcm/layer/openlayers/vectorTileOpenlayers.js → layer/openlayers/vectorTileOpenlayersImpl.js} +18 -12
  67. package/src/{vcs/vcm/layer/openlayers/wmsOpenlayers.js → layer/openlayers/wmsOpenlayersImpl.js} +9 -8
  68. package/src/{vcs/vcm/layer/openlayers/wmtsOpenlayers.js → layer/openlayers/wmtsOpenlayersImpl.js} +19 -12
  69. package/src/{vcs/vcm/layer/pointCloud.js → layer/pointCloudLayer.js} +42 -39
  70. package/src/{vcs/vcm/layer → layer}/rasterLayer.js +86 -37
  71. package/src/{vcs/vcm/layer/singleImage.js → layer/singleImageLayer.js} +25 -22
  72. package/src/layer/terrainHelpers.js +98 -0
  73. package/src/{vcs/vcm/layer/terrain.js → layer/terrainLayer.js} +26 -18
  74. package/src/{vcs/vcm/layer → layer}/tileLoadedHelper.js +13 -8
  75. package/src/{vcs/vcm/layer → layer}/tileProvider/mvtTileProvider.js +51 -8
  76. package/src/layer/tileProvider/staticGeojsonTileProvider.js +87 -0
  77. package/src/{vcs/vcm/layer → layer}/tileProvider/tileProvider.js +200 -89
  78. package/src/{vcs/vcm/layer → layer}/tileProvider/urlTemplateTileProvider.js +54 -13
  79. package/src/{vcs/vcm/layer/tms.js → layer/tmsLayer.js} +22 -22
  80. package/src/layer/vectorHelpers.js +129 -0
  81. package/src/{vcs/vcm/layer/vector.js → layer/vectorLayer.js} +124 -94
  82. package/src/{vcs/vcm/layer → layer}/vectorProperties.js +419 -107
  83. package/src/{vcs/vcm/layer → layer}/vectorSymbols.js +11 -1
  84. package/src/{vcs/vcm/layer/vectorTile.js → layer/vectorTileLayer.js} +181 -116
  85. package/src/{vcs/vcm/layer/wfs.js → layer/wfsLayer.js} +33 -23
  86. package/src/{vcs/vcm/layer → layer}/wmsHelpers.js +14 -7
  87. package/src/{vcs/vcm/layer/wms.js → layer/wmsLayer.js} +53 -32
  88. package/src/{vcs/vcm/layer/wmts.js → layer/wmtsLayer.js} +56 -42
  89. package/src/{vcs/vcm/maps → map}/baseOLMap.js +83 -35
  90. package/src/{vcs/vcm/maps → map}/cameraLimiter.js +75 -32
  91. package/src/{vcs/vcm/maps/cesium.js → map/cesiumMap.js} +429 -276
  92. package/src/{vcs/vcm/maps → map}/mapState.js +0 -1
  93. package/src/{vcs/vcm/maps/oblique.js → map/obliqueMap.js} +132 -97
  94. package/src/{vcs/vcm/maps/openlayers.js → map/openlayersMap.js} +69 -45
  95. package/src/{vcs/vcm/maps/map.js → map/vcsMap.js} +118 -46
  96. package/src/oblique/defaultObliqueCollection.js +62 -0
  97. package/src/{vcs/vcm/oblique → oblique}/helpers.js +221 -78
  98. package/src/{vcs/vcm/oblique/ObliqueCollection.js → oblique/obliqueCollection.js} +145 -54
  99. package/src/{vcs/vcm/oblique/ObliqueDataSet.js → oblique/obliqueDataSet.js} +62 -32
  100. package/src/{vcs/vcm/oblique/ObliqueImage.js → oblique/obliqueImage.js} +58 -26
  101. package/src/{vcs/vcm/oblique/ObliqueImageMeta.js → oblique/obliqueImageMeta.js} +9 -9
  102. package/src/{vcs/vcm/oblique/ObliqueProvider.js → oblique/obliqueProvider.js} +85 -35
  103. package/src/{vcs/vcm/oblique/ObliqueView.js → oblique/obliqueView.js} +45 -5
  104. package/src/{vcs/vcm/oblique/ObliqueViewDirection.js → oblique/obliqueViewDirection.js} +3 -5
  105. package/src/{vcs/vcm/oblique → oblique}/parseImageJson.js +62 -28
  106. package/src/ol/feature.js +34 -1
  107. package/src/ol/geom/circle.js +14 -5
  108. package/src/ol/geom/geometryCollection.js +14 -8
  109. package/src/ol/render/canvas/canvasTileRenderer.js +11 -10
  110. package/src/overrideClassRegistry.js +214 -0
  111. package/src/style/arcStyle.js +453 -0
  112. package/src/style/arrowStyle.js +304 -0
  113. package/src/{vcs/vcm/util/style → style}/declarativeStyleItem.js +147 -82
  114. package/src/{vcs/vcm/util/style → style}/shapesCategory.js +8 -8
  115. package/src/style/styleFactory.js +32 -0
  116. package/src/{vcs/vcm/util/style → style}/styleHelpers.js +24 -26
  117. package/src/style/styleItem.js +174 -0
  118. package/src/{vcs/vcm/util/style → style}/vectorStyleItem.js +230 -156
  119. package/src/{vcs/vcm/util/style → style}/writeStyle.js +7 -12
  120. package/src/{vcs/vcm/util → util}/clipping/clippingObject.js +84 -52
  121. package/src/{vcs/vcm/util → util}/clipping/clippingObjectManager.js +56 -23
  122. package/src/{vcs/vcm/util → util}/clipping/clippingPlaneHelper.js +149 -88
  123. package/src/{vcs/vcm/util → util}/collection.js +28 -10
  124. package/src/util/editor/createFeatureSession.js +195 -0
  125. package/src/util/editor/editFeaturesSession.js +325 -0
  126. package/src/util/editor/editGeometrySession.js +452 -0
  127. package/src/util/editor/editorHelpers.js +300 -0
  128. package/src/util/editor/editorSessionHelpers.js +132 -0
  129. package/src/util/editor/editorSymbols.js +21 -0
  130. package/src/util/editor/interactions/createBBoxInteraction.js +154 -0
  131. package/src/util/editor/interactions/createCircleInteraction.js +119 -0
  132. package/src/util/editor/interactions/createLineStringInteraction.js +119 -0
  133. package/src/util/editor/interactions/createPointInteraction.js +73 -0
  134. package/src/util/editor/interactions/createPolygonInteraction.js +136 -0
  135. package/src/util/editor/interactions/editFeaturesMouseOverInteraction.js +88 -0
  136. package/src/util/editor/interactions/editGeometryMouseOverInteraction.js +119 -0
  137. package/src/util/editor/interactions/ensureHandlerSelectionInteraction.js +50 -0
  138. package/src/util/editor/interactions/insertVertexInteraction.js +103 -0
  139. package/src/util/editor/interactions/mapInteractionController.js +119 -0
  140. package/src/util/editor/interactions/removeVertexInteraction.js +42 -0
  141. package/src/util/editor/interactions/selectFeatureMouseOverInteraction.js +152 -0
  142. package/src/util/editor/interactions/selectMultiFeatureInteraction.js +165 -0
  143. package/src/util/editor/interactions/selectSingleFeatureInteraction.js +120 -0
  144. package/src/util/editor/interactions/translateVertexInteraction.js +60 -0
  145. package/src/util/editor/selectFeaturesSession.js +303 -0
  146. package/src/util/editor/transformation/create2DHandlers.js +339 -0
  147. package/src/util/editor/transformation/create3DHandlers.js +678 -0
  148. package/src/util/editor/transformation/extrudeInteraction.js +106 -0
  149. package/src/util/editor/transformation/rotateInteraction.js +201 -0
  150. package/src/util/editor/transformation/scaleInteraction.js +201 -0
  151. package/src/util/editor/transformation/transformationHandler.js +178 -0
  152. package/src/util/editor/transformation/transformationTypes.js +88 -0
  153. package/src/util/editor/transformation/translateInteraction.js +263 -0
  154. package/src/util/editor/validateGeoemetry.js +24 -0
  155. package/src/{vcs/vcm/util → util}/exclusiveManager.js +6 -3
  156. package/src/{vcs/vcm/util → util}/extent.js +26 -20
  157. package/src/util/featureconverter/arcToCesium.js +121 -0
  158. package/src/{vcs/vcm/util → util}/featureconverter/circleToCesium.js +70 -37
  159. package/src/{vcs/vcm/util → util}/featureconverter/convert.js +94 -16
  160. package/src/util/featureconverter/extent3D.js +284 -0
  161. package/src/{vcs/vcm/util → util}/featureconverter/featureconverterHelper.js +253 -94
  162. package/src/util/featureconverter/lineStringToCesium.js +343 -0
  163. package/src/util/featureconverter/pointHelpers.js +413 -0
  164. package/src/{vcs/vcm/util → util}/featureconverter/pointToCesium.js +157 -107
  165. package/src/{vcs/vcm/util → util}/featureconverter/polygonToCesium.js +57 -24
  166. package/src/util/fetch.js +34 -0
  167. package/src/{vcs/vcm/util → util}/geometryHelpers.js +25 -17
  168. package/src/{vcs/vcm/util → util}/indexedCollection.js +27 -8
  169. package/src/{vcs/vcm/util → util}/isMobile.js +8 -2
  170. package/src/{vcs/vcm/util → util}/layerCollection.js +109 -19
  171. package/src/util/locale.js +12 -0
  172. package/src/{vcs/vcm/util → util}/mapCollection.js +170 -63
  173. package/src/util/math.js +193 -0
  174. package/src/util/overrideCollection.js +261 -0
  175. package/src/{vcs/vcm/util → util}/projection.js +23 -31
  176. package/src/{vcs/vcm/util → util}/urlHelpers.js +5 -3
  177. package/src/{vcs/vcm/util → util}/viewpoint.js +83 -57
  178. package/src/vcsApp.js +657 -0
  179. package/src/{vcs/vcm/event/vcsEvent.js → vcsEvent.js} +2 -3
  180. package/src/vcsModule.js +130 -0
  181. package/src/vcsModuleHelpers.js +136 -0
  182. package/src/{vcs/vcm/object.js → vcsObject.js} +3 -10
  183. package/tests/data/dynamicPointCzml.json +53 -0
  184. package/tests/data/oblique/imageData/imagev34.json +136 -0
  185. package/tests/data/oblique/imageData/imagev35.json +307 -0
  186. package/tests/data/oblique/imageData/imagev35PerImageSize.json +333 -0
  187. package/tests/data/oblique/tiledImageData/12/2199/1342.json +11056 -0
  188. package/tests/data/oblique/tiledImageData/12/2199/1343.json +11236 -0
  189. package/tests/data/oblique/tiledImageData/12/2199/1344.json +11077 -0
  190. package/tests/data/oblique/tiledImageData/12/2200/1342.json +11036 -0
  191. package/tests/data/oblique/tiledImageData/12/2200/1343.json +11277 -0
  192. package/tests/data/oblique/tiledImageData/12/2200/1344.json +11131 -0
  193. package/tests/data/oblique/tiledImageData/12/2201/1342.json +10870 -0
  194. package/tests/data/oblique/tiledImageData/12/2201/1343.json +11492 -0
  195. package/tests/data/oblique/tiledImageData/12/2201/1344.json +10909 -0
  196. package/tests/data/oblique/tiledImageData/image.json +70 -0
  197. package/tests/data/terrain/13/8800/6485.terrain +0 -0
  198. package/tests/data/terrain/13/8800/6486.terrain +0 -0
  199. package/tests/data/terrain/13/8801/6485.terrain +0 -0
  200. package/tests/data/terrain/13/8801/6486.terrain +0 -0
  201. package/tests/data/terrain/layer.json +127 -0
  202. package/tests/data/testGeoJSON.json +149 -0
  203. package/tests/data/tile.pbf +0 -0
  204. package/tests/unit/helpers/cesiumHelpers.js +326 -0
  205. package/tests/unit/helpers/getFileNameFromUrl.js +12 -0
  206. package/tests/unit/helpers/helpers.js +32 -0
  207. package/tests/unit/helpers/imageHelpers.js +24 -0
  208. package/tests/unit/helpers/importJSON.js +15 -0
  209. package/tests/unit/helpers/obliqueData.js +102 -0
  210. package/tests/unit/helpers/obliqueHelpers.js +115 -0
  211. package/tests/unit/helpers/openlayersHelpers.js +25 -0
  212. package/tests/unit/helpers/terrain/terrainData.js +47 -0
  213. package/src/vcs/vcm/classRegistry.js +0 -106
  214. package/src/vcs/vcm/globalCollections.js +0 -11
  215. package/src/vcs/vcm/interaction/featureProviderInteraction.js +0 -54
  216. package/src/vcs/vcm/layer/buildings.js +0 -17
  217. package/src/vcs/vcm/layer/cesium/openStreetMapCesium.js +0 -29
  218. package/src/vcs/vcm/layer/cesium/pointCloudCesium.js +0 -58
  219. package/src/vcs/vcm/layer/cesium/vectorContext.js +0 -167
  220. package/src/vcs/vcm/layer/openlayers/layerOpenlayers.js +0 -79
  221. package/src/vcs/vcm/layer/openlayers/openStreetMapOpenlayers.js +0 -27
  222. package/src/vcs/vcm/layer/openlayers/rasterLayerOpenlayers.js +0 -121
  223. package/src/vcs/vcm/layer/terrainHelpers.js +0 -119
  224. package/src/vcs/vcm/layer/tileProvider/staticGeojsonTileProvider.js +0 -67
  225. package/src/vcs/vcm/layer/tileProvider/tileProviderFactory.js +0 -28
  226. package/src/vcs/vcm/layer/vectorHelpers.js +0 -206
  227. package/src/vcs/vcm/util/dateTime.js +0 -60
  228. package/src/vcs/vcm/util/featureProvider/featureProviderHelpers.js +0 -51
  229. package/src/vcs/vcm/util/featureconverter/extent3d.js +0 -154
  230. package/src/vcs/vcm/util/featureconverter/lineStringToCesium.js +0 -171
  231. package/src/vcs/vcm/util/locale.js +0 -53
  232. package/src/vcs/vcm/util/math.js +0 -71
  233. package/src/vcs/vcm/util/splitScreen.js +0 -233
  234. package/src/vcs/vcm/util/style/styleFactory.js +0 -48
  235. package/src/vcs/vcm/util/style/styleItem.js +0 -243
  236. /package/src/{vcs/vcm/util/featureProvider → featureProvider}/featureProviderSymbols.js +0 -0
@@ -0,0 +1,483 @@
1
+ import { check } from '@vcsuite/check';
2
+ import { v4 as uuidv4 } from 'uuid';
3
+ import { Feature } from 'ol';
4
+ import { moduleIdSymbol, destroyCollection } from '../vcsModuleHelpers.js';
5
+ import makeOverrideCollection, {
6
+ isOverrideCollection,
7
+ } from '../util/overrideCollection.js';
8
+ import VcsObject from '../vcsObject.js';
9
+ import VectorLayer from '../layer/vectorLayer.js';
10
+ import IndexedCollection from '../util/indexedCollection.js';
11
+ import { parseGeoJSON, writeGeoJSONFeature } from '../layer/geojsonHelpers.js';
12
+ import Collection from '../util/collection.js';
13
+ import { getStyleOrDefaultStyle } from '../style/styleFactory.js';
14
+ import {
15
+ categoryClassRegistry,
16
+ getObjectFromClassRegistry,
17
+ } from '../classRegistry.js';
18
+ import OverrideClassRegistry from '../overrideClassRegistry.js';
19
+ import VcsEvent from '../vcsEvent.js';
20
+
21
+ /**
22
+ * @typedef {VcsObjectOptions} CategoryOptions
23
+ * @property {string} [title]
24
+ * @property {string|symbol} [classRegistryName] - the class registry name on the current app to provide classes for this category. if provided, parseItems will deserialize using this class registry. See: {@link getObjectFromClassRegistry}.
25
+ * @property {string|undefined} [featureProperty]
26
+ * @property {VectorOptions} [layerOptions={}]
27
+ * @property {string} [keyProperty=name]
28
+ */
29
+
30
+ /**
31
+ * @type {*|string}
32
+ */
33
+ const categoryModuleId = uuidv4();
34
+
35
+ /**
36
+ * @param {import("@vcmap/core").VectorLayer} layer
37
+ * @param {VectorOptions} options
38
+ * @private
39
+ */
40
+ function assignLayerOptions(layer, options) {
41
+ if (options.style) {
42
+ layer.setStyle(getStyleOrDefaultStyle(options.style, layer.defaultStyle));
43
+ }
44
+
45
+ if (options.highlightStyle) {
46
+ const highlightStyle = getStyleOrDefaultStyle(
47
+ options.highlightStyle,
48
+ layer.highlightStyle,
49
+ );
50
+ layer.setHighlightStyle(
51
+ /** @type {import("@vcmap/core").VectorStyleItem} */ (highlightStyle),
52
+ );
53
+ }
54
+
55
+ if (options.vectorProperties) {
56
+ layer.vectorProperties.setValues(options.vectorProperties);
57
+ }
58
+
59
+ if (options.zIndex != null) {
60
+ layer.zIndex = options.zIndex;
61
+ }
62
+ }
63
+
64
+ /**
65
+ * @param {string} key
66
+ * @param {T} value
67
+ * @param {T} defaultOption
68
+ * @param {T=} option
69
+ * @template {number|boolean|string|symbol} T
70
+ * @returns {void}
71
+ */
72
+ function checkMergeOptionOverride(key, value, defaultOption, option) {
73
+ const isOverride =
74
+ option == null ? value !== defaultOption : option !== value;
75
+ if (isOverride) {
76
+ throw new Error(`Cannot merge options, values of ${key} do not match`);
77
+ }
78
+ }
79
+
80
+ /**
81
+ * A category contains user based items and is a special container. The container should not be created directly, but via
82
+ * the requestCategory API on the categories collection. Do not use toJSON to retrieve the state of a category, since
83
+ * categories outlive modules and may be changed with mergeOptions to no longer reflect your initial state. Requestors
84
+ * should keep track of the requested options themselves.
85
+ * @class
86
+ * @extends {VcsObject}
87
+ * @template {Object|VcsObject} T
88
+ */
89
+ class Category extends VcsObject {
90
+ static get className() {
91
+ return 'Category';
92
+ }
93
+
94
+ /**
95
+ * @returns {CategoryOptions}
96
+ */
97
+ static getDefaultConfig() {
98
+ return {
99
+ title: '',
100
+ featureProperty: undefined,
101
+ classRegistryName: undefined,
102
+ layerOptions: {},
103
+ keyProperty: 'name',
104
+ };
105
+ }
106
+
107
+ /**
108
+ * @param {CategoryOptions} options
109
+ */
110
+ constructor(options) {
111
+ super(options);
112
+ const defaultOptions = Category.getDefaultConfig();
113
+ /**
114
+ * @type {string}
115
+ */
116
+ this.title = options.title || this.name;
117
+ /**
118
+ * @type {import("@vcmap/core").VcsApp}
119
+ * @protected
120
+ */
121
+ this._app = null;
122
+ /**
123
+ * @type {string}
124
+ * @private
125
+ */
126
+ this._featureProperty =
127
+ options.featureProperty || defaultOptions.featureProperty;
128
+ /**
129
+ * @type {string|symbol}
130
+ * @private
131
+ */
132
+ this._classRegistryName = options.classRegistryName;
133
+ /**
134
+ * @type {VectorOptions}
135
+ * @private
136
+ */
137
+ this._layerOptions = options.layerOptions || defaultOptions.layerOptions;
138
+ /**
139
+ * @type {import("@vcmap/core").VectorLayer}
140
+ * @protected
141
+ */
142
+ this._layer = null;
143
+ if (this._featureProperty) {
144
+ this._layer = new VectorLayer(this._layerOptions);
145
+ this._layer[moduleIdSymbol] = categoryModuleId;
146
+ }
147
+ /**
148
+ * @type {string}
149
+ * @private
150
+ */
151
+ this._keyProperty = options.keyProperty || defaultOptions.keyProperty;
152
+ /**
153
+ * Event raised if the collection is reset
154
+ * @type {VcsEvent<void>}
155
+ * @private
156
+ */
157
+ this._collectionChanged = new VcsEvent();
158
+ /**
159
+ * @type {Array<function():void>}
160
+ * @private
161
+ */
162
+ this._collectionListeners = [];
163
+ /**
164
+ * @type {OverrideCollection<T>}
165
+ * @private
166
+ */
167
+ this._collection = null;
168
+ this.setCollection(new IndexedCollection(this._keyProperty));
169
+ /**
170
+ * @type {function():void}
171
+ * @private
172
+ */
173
+ this._moduleRemovedListener = () => {};
174
+ }
175
+
176
+ /**
177
+ * @type {string|symbol}
178
+ * @readonly
179
+ */
180
+ get classRegistryName() {
181
+ return this._classRegistryName;
182
+ }
183
+
184
+ /**
185
+ * The collection of this category.
186
+ * @type {OverrideCollection<T>}
187
+ * @readonly
188
+ */
189
+ get collection() {
190
+ return this._collection;
191
+ }
192
+
193
+ /**
194
+ * Event raised if the collection is reset
195
+ * @type {VcsEvent<void>}
196
+ * @readonly
197
+ */
198
+ get collectionChanged() {
199
+ return this._collectionChanged;
200
+ }
201
+
202
+ /**
203
+ * Returns the layer of this collection. Caution, do not use the layer API to add or remove items.
204
+ * When adding items to the collection, the features are added to the layer async (timeout of 0), since there is weird behavior
205
+ * when removing and adding a feature with the same id in the same sync call.
206
+ * @type {import("@vcmap/core").VectorLayer|null}
207
+ */
208
+ get layer() {
209
+ return this._layer;
210
+ }
211
+
212
+ /**
213
+ * @param {T} item
214
+ * @protected
215
+ */
216
+ _itemAdded(item) {
217
+ if (this._featureProperty) {
218
+ const id = item[this._keyProperty];
219
+ this._layer.removeFeaturesById([id]); // this may be a replacement.
220
+
221
+ const geoJsonFeature = item[this._featureProperty];
222
+ let feature;
223
+ if (geoJsonFeature instanceof Feature) {
224
+ feature = geoJsonFeature;
225
+ } else if (typeof geoJsonFeature === 'object') {
226
+ const { features } = parseGeoJSON(geoJsonFeature);
227
+ if (features[0]) {
228
+ // XXX do we warn on feature collection?
229
+ feature = features[0];
230
+ }
231
+ }
232
+
233
+ if (feature) {
234
+ feature.setId(id);
235
+ setTimeout(() => {
236
+ this._layer.addFeatures([feature]);
237
+ }, 0); // We need to set a timeout, since removing and adding the feature in the same sync call leads to undefined behavior in OL TODO recheck in ol 6.11
238
+ }
239
+ }
240
+ }
241
+
242
+ /**
243
+ * @param {T} item
244
+ * @protected
245
+ */
246
+ _itemRemoved(item) {
247
+ if (this._featureProperty) {
248
+ this._layer.removeFeaturesById([item[this._keyProperty]]);
249
+ }
250
+ }
251
+
252
+ /**
253
+ * @param {T} item
254
+ * @protected
255
+ */
256
+ // eslint-disable-next-line class-methods-use-this,no-unused-vars
257
+ _itemReplaced(item) {}
258
+
259
+ /**
260
+ * @param {T} item
261
+ * @protected
262
+ */
263
+ // eslint-disable-next-line class-methods-use-this,no-unused-vars
264
+ _itemMoved(item) {}
265
+
266
+ /**
267
+ * @returns {string}
268
+ * @private
269
+ */
270
+ _getDynamicModuleId() {
271
+ if (!this._app) {
272
+ throw new Error('Cannot get dynamic module id, before setting the vcApp');
273
+ }
274
+ return this._app.dynamicModuleId;
275
+ }
276
+
277
+ /**
278
+ * Throws if typed, featureProperty and keyProperty do not match. Merges other options.
279
+ * Only merges: style, highlightStyle, zIndex & vectorProperties from layerOptions.
280
+ * @param {CategoryOptions} options
281
+ */
282
+ mergeOptions(options) {
283
+ const defaultOptions = Category.getDefaultConfig();
284
+ checkMergeOptionOverride(
285
+ 'classRegistryName',
286
+ this._classRegistryName,
287
+ defaultOptions.classRegistryName,
288
+ options.classRegistryName,
289
+ );
290
+ checkMergeOptionOverride(
291
+ 'featureProperty',
292
+ this._featureProperty,
293
+ defaultOptions.featureProperty,
294
+ options.featureProperty,
295
+ );
296
+ checkMergeOptionOverride(
297
+ 'keyProperty',
298
+ this._keyProperty,
299
+ defaultOptions.keyProperty,
300
+ options.keyProperty,
301
+ );
302
+ this.title = options.title || this.title;
303
+ if (options.layerOptions && this._layer) {
304
+ assignLayerOptions(this._layer, options.layerOptions);
305
+ }
306
+ }
307
+
308
+ /**
309
+ * When setting the category, it MUST use the same uniqueKey as the previous collection (default is "name").
310
+ * All items in the current collection _will be destroyed_ and the current collection will be destroyed. The category will take
311
+ * complete ownership of the collection and destroy it once the category is destroyed. The collection will
312
+ * be turned into an {@see OverrideCollection}.
313
+ * @param {import("@vcmap/core").Collection<T>} collection
314
+ */
315
+ setCollection(collection) {
316
+ check(collection, Collection);
317
+
318
+ if (this._keyProperty !== collection.uniqueKey) {
319
+ throw new Error(
320
+ 'The collections key property does not match the categories key property',
321
+ );
322
+ }
323
+
324
+ this._collectionListeners.forEach((cb) => {
325
+ cb();
326
+ });
327
+ if (this._collection) {
328
+ destroyCollection(this._collection);
329
+ }
330
+ if (this._layer) {
331
+ this._layer.removeAllFeatures(); // XXX should we call `itemRemoved` instead?
332
+ }
333
+
334
+ this._collection = collection[isOverrideCollection]
335
+ ? /** @type {OverrideCollection} */ (collection)
336
+ : makeOverrideCollection(
337
+ collection,
338
+ this._getDynamicModuleId.bind(this),
339
+ this._serializeItem.bind(this),
340
+ this._deserializeItem.bind(this),
341
+ );
342
+
343
+ [...this.collection].forEach((item) => {
344
+ this._itemAdded(item);
345
+ });
346
+ /**
347
+ * @type {Array<function():void>}
348
+ * @private
349
+ */
350
+ this._collectionListeners = [
351
+ this._collection.added.addEventListener(this._itemAdded.bind(this)),
352
+ this._collection.removed.addEventListener(this._itemRemoved.bind(this)),
353
+ this._collection.replaced.addEventListener(this._itemReplaced.bind(this)),
354
+ ];
355
+
356
+ // @ts-ignore
357
+ if (this._collection.moved) {
358
+ this._collectionListeners.push(
359
+ // @ts-ignore
360
+ this._collection.moved.addEventListener(this._itemMoved.bind(this)),
361
+ );
362
+ }
363
+ this.collectionChanged.raiseEvent();
364
+ }
365
+
366
+ /**
367
+ * @param {import("@vcmap/core").VcsApp} app
368
+ */
369
+ setApp(app) {
370
+ if (this._app) {
371
+ throw new Error('Cannot switch apps');
372
+ }
373
+ this._app = app;
374
+ this._moduleRemovedListener = this._app.moduleRemoved.addEventListener(
375
+ (module) => {
376
+ this._collection.removeModule(module._id);
377
+ },
378
+ );
379
+ if (this._layer) {
380
+ this._app.layers.add(this._layer);
381
+ }
382
+ }
383
+
384
+ /**
385
+ * @protected
386
+ * @param {*} config
387
+ * @returns {Promise<T>} // XXX should this still be async?
388
+ */
389
+ async _deserializeItem(config) {
390
+ if (!this._app) {
391
+ throw new Error('Cannot deserialize item before setting the vcApp');
392
+ }
393
+ const classRegistry = this._classRegistryName
394
+ ? this._app[this._classRegistryName]
395
+ : null;
396
+ if (classRegistry && classRegistry instanceof OverrideClassRegistry) {
397
+ return getObjectFromClassRegistry(classRegistry, config);
398
+ }
399
+ return config;
400
+ }
401
+
402
+ /**
403
+ * @protected
404
+ * @param {T} item
405
+ * @returns {Object}
406
+ */
407
+ _serializeItem(item) {
408
+ const config = JSON.parse(JSON.stringify(item));
409
+ if (this._featureProperty) {
410
+ const feature = this._layer.getFeatureById(item[this._keyProperty]);
411
+ if (feature) {
412
+ config[this._featureProperty] = writeGeoJSONFeature(feature);
413
+ }
414
+ }
415
+ return config;
416
+ }
417
+
418
+ /**
419
+ * @param {string} moduleId
420
+ * @returns {{ name: string, items: Array<Object>}|null}
421
+ */
422
+ serializeModule(moduleId) {
423
+ if (this._collection.size === 0) {
424
+ return null;
425
+ }
426
+
427
+ return {
428
+ name: this.name,
429
+ items: this.collection.serializeModule(moduleId),
430
+ };
431
+ }
432
+
433
+ /**
434
+ * @returns {CategoryOptions}
435
+ */
436
+ toJSON() {
437
+ const config = /** @type {CategoryOptions} */ (super.toJSON());
438
+
439
+ const defaultOptions = Category.getDefaultConfig();
440
+ if (this.title !== this.name) {
441
+ config.title = this.title;
442
+ }
443
+ if (this._featureProperty !== defaultOptions.featureProperty) {
444
+ config.featureProperty = this._featureProperty;
445
+ }
446
+ if (this._classRegistryName !== defaultOptions.classRegistryName) {
447
+ config.classRegistryName = this._classRegistryName;
448
+ }
449
+ if (Object.keys(this._layerOptions).length > 0) {
450
+ config.layerOptions = { ...this._layerOptions };
451
+ }
452
+ if (this._keyProperty !== defaultOptions.keyProperty) {
453
+ config.keyProperty = this._keyProperty;
454
+ }
455
+ return config;
456
+ }
457
+
458
+ /**
459
+ * @inheritDoc
460
+ */
461
+ destroy() {
462
+ super.destroy();
463
+ if (this._app && this._layer) {
464
+ this._app.layers.remove(this._layer);
465
+ }
466
+ if (this._layer) {
467
+ this._layer.destroy();
468
+ }
469
+
470
+ this._collectionListeners.forEach((cb) => {
471
+ cb();
472
+ });
473
+ this._collectionListeners.splice(0);
474
+ this._moduleRemovedListener();
475
+ this._moduleRemovedListener = () => {};
476
+ destroyCollection(this._collection);
477
+ this._collectionChanged.destroy();
478
+ this._app = null;
479
+ }
480
+ }
481
+
482
+ export default Category;
483
+ categoryClassRegistry.registerClass(Category.className, Category);
@@ -0,0 +1,153 @@
1
+ import { getLogger as getLoggerByName } from '@vcsuite/logger';
2
+ import Category from './category.js';
3
+ import IndexedCollection from '../util/indexedCollection.js';
4
+ import { getObjectFromClassRegistry } from '../classRegistry.js';
5
+
6
+ /**
7
+ * @returns {import("@vcsuite/logger").Logger}
8
+ */
9
+ function getLogger() {
10
+ return getLoggerByName('CategoryCollection');
11
+ }
12
+
13
+ /**
14
+ * @class
15
+ * @extends {IndexedCollection<Category<Object|import("@vcmap/core").VcsObject>>}
16
+ */
17
+ class CategoryCollection extends IndexedCollection {
18
+ /**
19
+ * @param {import("@vcmap/core").VcsApp} app
20
+ */
21
+ constructor(app) {
22
+ super();
23
+ /**
24
+ * @type {import("@vcmap/core").VcsApp}
25
+ * @private
26
+ */
27
+ this._app = app;
28
+ /**
29
+ * Map of category names, where the value is a map of moduleId and items.
30
+ * @type {Map<string, Map<string, Array<Object>>>}
31
+ * @private
32
+ */
33
+ this._cache = new Map();
34
+ /**
35
+ * @type {Function}
36
+ * @private
37
+ */
38
+ this._moduleRemovedListener = this._app.moduleRemoved.addEventListener(
39
+ (module) => {
40
+ this._cache.forEach((moduleMap, name) => {
41
+ moduleMap.delete(module._id);
42
+ if (moduleMap.size === 0) {
43
+ this._cache.delete(name);
44
+ }
45
+ });
46
+ },
47
+ );
48
+ }
49
+
50
+ /**
51
+ * Do not call add directly. Use request category for adding categories.
52
+ * @param {Category<Object|import("@vcmap/core").VcsObject>} category
53
+ * @returns {number|null}
54
+ */
55
+ add(category) {
56
+ // XXX use a symbol to enforce using request over add?
57
+ if (this.hasKey(category.name)) {
58
+ return null;
59
+ }
60
+
61
+ category.setApp(this._app);
62
+ const added = super.add(category);
63
+ if (added != null && this._cache.has(category.name)) {
64
+ this._cache.get(category.name).forEach((items, moduleId) => {
65
+ this.parseCategoryItems(category.name, items, moduleId);
66
+ });
67
+
68
+ this._cache.delete(category.name);
69
+ }
70
+ return added;
71
+ }
72
+
73
+ /**
74
+ * Categories should be static. Removing them can lead to undefined behavior.
75
+ * @param {Category<Object|import("@vcmap/core").VcsObject>} category
76
+ */
77
+ remove(category) {
78
+ // XXX add logger warning?
79
+ super.remove(category);
80
+ this._cache.delete(category.name);
81
+ }
82
+
83
+ /**
84
+ * Parses the category items. Items will only be parsed, if a category with said name exists. Otherwise,
85
+ * they will be cached, until such a category is requested.
86
+ * @param {string} name
87
+ * @param {Array<Object>} items
88
+ * @param {string} moduleId
89
+ * @returns {Promise<void>}
90
+ */
91
+ async parseCategoryItems(name, items, moduleId) {
92
+ const category = this.getByKey(name);
93
+
94
+ if (category) {
95
+ await category.collection.parseItems(items, moduleId);
96
+ } else if (this._cache.has(name)) {
97
+ this._cache.get(name).set(moduleId, items);
98
+ } else {
99
+ this._cache.set(name, new Map([[moduleId, items]]));
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Add categories with this API.
105
+ * @param {CategoryOptions} options
106
+ * @returns {Promise<Category<Object|import("@vcmap/core").VcsObject>>}
107
+ */
108
+ async requestCategory(options) {
109
+ if (!options.name) {
110
+ getLogger().error('Cannot request a category without a name');
111
+ return null;
112
+ }
113
+
114
+ if (!options.type) {
115
+ getLogger().warning(
116
+ `Implicitly typing category ${options.name} as ${Category.className}`,
117
+ );
118
+ options.type = Category.className;
119
+ }
120
+
121
+ let category;
122
+ if (this.hasKey(options.name)) {
123
+ category = this.getByKey(options.name);
124
+ category.mergeOptions(options);
125
+ } else {
126
+ category = await getObjectFromClassRegistry(
127
+ this._app.categoryClassRegistry,
128
+ options,
129
+ );
130
+ if (category) {
131
+ if (this.add(category) == null) {
132
+ return null;
133
+ }
134
+ }
135
+ }
136
+
137
+ if (!category) {
138
+ throw new Error(
139
+ `Category ${options.name} with type ${options.type} could not be created`,
140
+ );
141
+ }
142
+ return category;
143
+ }
144
+
145
+ destroy() {
146
+ super.destroy();
147
+ this._moduleRemovedListener();
148
+ this._cache.clear();
149
+ this._app = null;
150
+ }
151
+ }
152
+
153
+ export default CategoryCollection;
@@ -1,9 +1,9 @@
1
1
  // @ts-nocheck
2
- import { Cesium3DTileFeature } from '@vcmap/cesium';
2
+ import { Cesium3DTileFeature } from '@vcmap-cesium/engine';
3
3
 
4
4
  /**
5
5
  * @returns {string|number}
6
6
  */
7
7
  Cesium3DTileFeature.prototype.getId = function getId() {
8
- return this.getProperty('id') || `${this.content.url}${this._batchId}`;
8
+ return this.getProperty('id') || `${this.content.url}${this._batchId}`; // XXX there is a new property `featureId` on the Cesium3DTileset. this may cause issues when picking b3dm.
9
9
  };
@@ -1,5 +1,5 @@
1
1
  // @ts-nocheck
2
- import { Cesium3DTilePointFeature } from '@vcmap/cesium';
2
+ import { Cesium3DTilePointFeature } from '@vcmap-cesium/engine';
3
3
 
4
4
  /**
5
5
  * @returns {string|number}