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

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 +3480 -2008
  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} +83 -70
  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} +8 -9
  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 -112
  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 +95 -0
  73. package/src/{vcs/vcm/layer/terrain.js → layer/terrainLayer.js} +28 -21
  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 +64 -37
  91. package/src/{vcs/vcm/maps/cesium.js → map/cesiumMap.js} +431 -277
  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} +151 -55
  99. package/src/{vcs/vcm/oblique/ObliqueDataSet.js → oblique/obliqueDataSet.js} +77 -46
  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 +79 -49
  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 +45 -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,60 @@
1
+ import AbstractInteraction from '../../../interaction/abstractInteraction.js';
2
+ import { EventType } from '../../../interaction/interactionType.js';
3
+ import { vertexSymbol } from '../editorSymbols.js';
4
+ import VcsEvent from '../../../vcsEvent.js';
5
+
6
+ /**
7
+ * Class to translate a vertex. Will call the passed in vertex changed event with the changed vertex.
8
+ * Will modify the vertex in place
9
+ * @class
10
+ * @extends {AbstractInteraction}
11
+ */
12
+ class TranslateVertexInteraction extends AbstractInteraction {
13
+ constructor() {
14
+ super(EventType.DRAGEVENTS);
15
+ /**
16
+ * @type {import("@vcmap/core").VcsEvent<Vertex>}
17
+ */
18
+ this.vertexChanged = new VcsEvent();
19
+ /**
20
+ * @type {Vertex|null}
21
+ * @private
22
+ */
23
+ this._vertex = null;
24
+ this.setActive();
25
+ }
26
+
27
+ /**
28
+ * @inheritDoc
29
+ * @param {InteractionEvent} event
30
+ * @returns {Promise<InteractionEvent>}
31
+ */
32
+ async pipe(event) {
33
+ if (this._vertex) {
34
+ this._vertex.getGeometry().setCoordinates(event.positionOrPixel);
35
+ this.vertexChanged.raiseEvent(this._vertex);
36
+
37
+ if (event.type & EventType.DRAGEND) {
38
+ this._vertex.unset('olcs_allowPicking');
39
+ this._vertex = null;
40
+ }
41
+ event.stopPropagation = true;
42
+ } else if (
43
+ event.type & EventType.DRAGSTART &&
44
+ event.feature &&
45
+ event.feature[vertexSymbol]
46
+ ) {
47
+ this._vertex = /** @type {Vertex} */ (event.feature);
48
+ this._vertex.set('olcs_allowPicking', false);
49
+ event.stopPropagation = true;
50
+ }
51
+ return event;
52
+ }
53
+
54
+ destroy() {
55
+ this.vertexChanged.destroy();
56
+ super.destroy();
57
+ }
58
+ }
59
+
60
+ export default TranslateVertexInteraction;
@@ -0,0 +1,303 @@
1
+ import { check } from '@vcsuite/check';
2
+ import { Circle, Fill, Style, Stroke } from 'ol/style.js';
3
+ import { createSync } from '../../layer/vectorSymbols.js';
4
+ import { SessionType, setupInteractionChain } from './editorSessionHelpers.js';
5
+ import SelectSingleFeatureInteraction from './interactions/selectSingleFeatureInteraction.js';
6
+ import SelectMultiFeatureInteraction from './interactions/selectMultiFeatureInteraction.js';
7
+ import SelectFeatureMouseOverInteraction, {
8
+ SelectionMode,
9
+ } from './interactions/selectFeatureMouseOverInteraction.js';
10
+ import VcsEvent from '../../vcsEvent.js';
11
+ import ObliqueMap from '../../map/obliqueMap.js';
12
+ import { vcsLayerName } from '../../layer/layerSymbols.js';
13
+
14
+ /**
15
+ * @typedef {Object} SelectionHighlightManager
16
+ * @property {Array<import("ol").Feature>} highlightedFeatures Currently highlighted features.
17
+ * @property {function(Array<import("ol").Feature>):void} update Sets the new features to be highlighted. All currently highlighted features that are not part of the new features are unhighlighted. Features that are not on the highlight layer are ignored.
18
+ * @property {function():void} destroy Stops all listeners, unhighlights all features.
19
+ */
20
+
21
+ /**
22
+ * Creates the selection highlight manager. By calling update features can be highlighted.
23
+ * @param {import("@vcmap/core").VectorLayer} layer The layer of the features to be highlighted.
24
+ * @param {import("ol/style").Style} highlightStyle Highlight style for the highlighted features.
25
+ * @returns {SelectionHighlightManager} Object that manages highlighting and allowPicking property of features. Has own state for selected features.
26
+ */
27
+ function createHighlightManager(layer, highlightStyle) {
28
+ const currentFeaturesMap = new Map();
29
+
30
+ /**
31
+ * Sets the new features to be highlighted. All currently highlighted features that are not part of the new features are unhighlighted.
32
+ * @param {Array<import("ol").Feature>} newFeatures Features to be highlighted.
33
+ */
34
+ const update = (newFeatures) => {
35
+ const newIds = new Set(
36
+ newFeatures.map((f) => {
37
+ f[createSync] = true;
38
+ return f.getId();
39
+ }),
40
+ );
41
+ const idsToHighlight = [];
42
+ newIds.forEach((id) => {
43
+ if (!currentFeaturesMap.has(id)) {
44
+ idsToHighlight.push(id);
45
+ }
46
+ });
47
+
48
+ const idsToUnHighlight = [];
49
+ currentFeaturesMap.forEach((feature, id) => {
50
+ if (!newIds.has(id)) {
51
+ idsToUnHighlight.push(id);
52
+ }
53
+ });
54
+
55
+ layer.featureVisibility.unHighlight(idsToUnHighlight);
56
+ layer.featureVisibility.highlight(
57
+ Object.fromEntries(idsToHighlight.map((id) => [id, highlightStyle])),
58
+ );
59
+ layer
60
+ .getFeaturesById(idsToUnHighlight)
61
+ .forEach((feature) => delete feature[createSync]);
62
+
63
+ currentFeaturesMap.clear();
64
+ newFeatures.forEach((feature) =>
65
+ currentFeaturesMap.set(feature.getId(), feature),
66
+ );
67
+ };
68
+
69
+ return {
70
+ get highlightedFeatures() {
71
+ return [...currentFeaturesMap.values()];
72
+ },
73
+ update(newFeatures) {
74
+ const featuresOnHighlightLayer = newFeatures.filter(
75
+ (feature) => feature[vcsLayerName] === layer.name,
76
+ );
77
+ update(featuresOnHighlightLayer);
78
+ },
79
+ destroy() {
80
+ if (currentFeaturesMap.size > 0) {
81
+ const idsToUnHighlight = [...currentFeaturesMap.keys()];
82
+ layer.featureVisibility.unHighlight(idsToUnHighlight);
83
+ layer
84
+ .getFeaturesById(idsToUnHighlight)
85
+ .forEach((feature) => delete feature[createSync]);
86
+ currentFeaturesMap.clear();
87
+ }
88
+ },
89
+ };
90
+ }
91
+
92
+ /**
93
+ * @returns {import("ol/style").Style}
94
+ */
95
+ export function getDefaultHighlightStyle() {
96
+ const fill = new Fill({ color: 'rgba(76,175,80,0.2)' });
97
+ const stroke = new Stroke({ color: '#4CAF50', width: 2 });
98
+
99
+ return new Style({
100
+ fill,
101
+ stroke,
102
+ image: new Circle({
103
+ fill,
104
+ stroke,
105
+ radius: 14,
106
+ }),
107
+ });
108
+ }
109
+
110
+ /**
111
+ * @typedef {EditorSession} SelectFeaturesSession
112
+ * @property {Array<import("ol").Feature>} currentFeatures
113
+ * @property {import("ol").Feature} firstFeature
114
+ * @property {VcsEvent<Array<import("ol").Feature>>} featuresChanged
115
+ * @property {SelectionMode} mode
116
+ * @property {function(SelectionMode):void} setMode Sets the selection mode. Raises modeChanged event, throws error when invalid selection mode input.
117
+ * @property {VcsEvent<SelectionMode>} modeChanged
118
+ * @property {function(Array<import("ol").Feature>): Promise<void>} setCurrentFeatures Promise that resolves when features are set.
119
+ * @property {function(): void} clearSelection Deselects all features.
120
+ */
121
+
122
+ /**
123
+ * @param {import("@vcmap/core").VcsApp} app
124
+ * @param {import("@vcmap/core").VectorLayer} layer
125
+ * @param {string=} [interactionId] id for registering mutliple exclusive interaction.
126
+ * @param {SelectionMode=} [initialMode=SelectionMode.MULTI]
127
+ * @param {import("ol/style").Style=} [highlightStyle]
128
+ * @returns {SelectFeaturesSession}
129
+ */
130
+ function startSelectFeaturesSession(
131
+ app,
132
+ layer,
133
+ interactionId,
134
+ initialMode = SelectionMode.MULTI,
135
+ highlightStyle = getDefaultHighlightStyle(),
136
+ ) {
137
+ /** @type {VcsEvent<void>} */
138
+ const stopped = new VcsEvent();
139
+ /** @type {VcsEvent<SelectionMode>} */
140
+ const modeChanged = new VcsEvent();
141
+ /** @type {VcsEvent<Array<import("ol").Feature>>} */
142
+ const featuresChanged = new VcsEvent();
143
+ /** @type {SelectSingleFeatureInteraction | SelectMultiFeatureInteraction | null} */
144
+ let currentSelectInteraction = null;
145
+ /** @type {SelectFeatureMouseOverInteraction} */
146
+ let mouseOverInteraction = null;
147
+ /** @type {SelectionMode} */
148
+ let currentSelectionMode = null;
149
+ /** @type {ObliqueMap|null} */
150
+ let obliqueMap = null;
151
+
152
+ const {
153
+ interactionChain,
154
+ removed: interactionRemoved,
155
+ destroy: destroyInteractionChain,
156
+ } = setupInteractionChain(app.maps.eventHandler, interactionId);
157
+
158
+ const highlightManager = createHighlightManager(layer, highlightStyle);
159
+
160
+ let interactionListeners = [];
161
+ function destroyCurrentSelectInteraction() {
162
+ if (currentSelectInteraction) {
163
+ if (currentSelectInteraction) {
164
+ interactionChain.removeInteraction(currentSelectInteraction);
165
+ currentSelectInteraction.destroy();
166
+ currentSelectInteraction = null;
167
+ }
168
+ if (mouseOverInteraction) {
169
+ interactionChain.removeInteraction(mouseOverInteraction);
170
+ mouseOverInteraction.destroy();
171
+ mouseOverInteraction = null;
172
+ }
173
+ }
174
+ interactionListeners.forEach((cb) => {
175
+ cb();
176
+ });
177
+ interactionListeners = [];
178
+ }
179
+
180
+ /**
181
+ * Destroys current selection interaction and creates new one. Sets all highlighted features as selected. If previous mode was multi and new mode is single, only first feature is selected and highlighted.
182
+ * @param {SelectionMode} newMode Either single or multi selection mode.
183
+ * @returns {void}
184
+ */
185
+ function createSelectInteraction(newMode) {
186
+ if (newMode === currentSelectionMode) {
187
+ return;
188
+ }
189
+
190
+ destroyCurrentSelectInteraction();
191
+ if (newMode === SelectionMode.SINGLE) {
192
+ currentSelectInteraction = new SelectSingleFeatureInteraction(layer);
193
+
194
+ interactionListeners.push(
195
+ currentSelectInteraction.featureChanged.addEventListener((feature) => {
196
+ const featureArray = feature ? [feature] : [];
197
+ highlightManager.update(featureArray);
198
+ featuresChanged.raiseEvent(featureArray);
199
+ if (obliqueMap) {
200
+ obliqueMap.switchEnabled = !feature;
201
+ }
202
+ }),
203
+ );
204
+ } else if (newMode === SelectionMode.MULTI) {
205
+ currentSelectInteraction = new SelectMultiFeatureInteraction(layer);
206
+ interactionListeners.push(
207
+ currentSelectInteraction.featuresChanged.addEventListener(
208
+ (features) => {
209
+ highlightManager.update(features);
210
+ featuresChanged.raiseEvent(features);
211
+ if (obliqueMap) {
212
+ obliqueMap.switchEnabled = features.length === 0;
213
+ }
214
+ },
215
+ ),
216
+ );
217
+ }
218
+ const { highlightedFeatures } = highlightManager;
219
+ if (highlightedFeatures) {
220
+ // if single select interaction, only one features is set. This triggers the event listener which ensures that only this feature is highlighted.
221
+ currentSelectInteraction.setSelected(highlightedFeatures);
222
+ }
223
+ currentSelectionMode = newMode;
224
+ interactionChain.addInteraction(currentSelectInteraction);
225
+ mouseOverInteraction = new SelectFeatureMouseOverInteraction(
226
+ layer.name,
227
+ currentSelectInteraction,
228
+ );
229
+ interactionChain.addInteraction(mouseOverInteraction);
230
+ }
231
+
232
+ createSelectInteraction(initialMode);
233
+
234
+ /**
235
+ * @type {function():void}
236
+ */
237
+ let obliqueImageChangedListener = () => {};
238
+ const mapChanged = (map) => {
239
+ obliqueImageChangedListener();
240
+ if (map instanceof ObliqueMap) {
241
+ currentSelectInteraction.clear();
242
+ obliqueImageChangedListener = map.imageChanged.addEventListener(() => {
243
+ currentSelectInteraction.clear();
244
+ });
245
+ obliqueMap = map;
246
+ } else {
247
+ if (obliqueMap) {
248
+ currentSelectInteraction.clear();
249
+ }
250
+ obliqueMap = null;
251
+ obliqueImageChangedListener = () => {};
252
+ }
253
+ };
254
+ const mapChangedListener = app.maps.mapActivated.addEventListener(mapChanged);
255
+ mapChanged(app.maps.activeMap);
256
+
257
+ const stop = () => {
258
+ destroyCurrentSelectInteraction();
259
+ destroyInteractionChain();
260
+ highlightManager.destroy();
261
+ mapChangedListener();
262
+ obliqueImageChangedListener();
263
+ if (obliqueMap) {
264
+ obliqueMap.switchEnabled = true;
265
+ }
266
+ stopped.raiseEvent();
267
+ stopped.destroy();
268
+ modeChanged.destroy();
269
+ featuresChanged.destroy();
270
+ };
271
+ interactionRemoved.addEventListener(stop);
272
+
273
+ return {
274
+ type: SessionType.SELECT,
275
+ stopped,
276
+ stop,
277
+ setCurrentFeatures(features) {
278
+ return currentSelectInteraction.setSelected(features);
279
+ },
280
+ get currentFeatures() {
281
+ return currentSelectInteraction.selected;
282
+ },
283
+ get firstFeature() {
284
+ return currentSelectInteraction.selected[0] || null;
285
+ },
286
+ get mode() {
287
+ return currentSelectionMode;
288
+ },
289
+ setMode(newMode) {
290
+ check(newMode, Object.values(SelectionMode));
291
+
292
+ createSelectInteraction(newMode);
293
+ modeChanged.raiseEvent(currentSelectionMode);
294
+ },
295
+ modeChanged,
296
+ featuresChanged,
297
+ clearSelection() {
298
+ currentSelectInteraction.clear();
299
+ },
300
+ };
301
+ }
302
+
303
+ export default startSelectFeaturesSession;
@@ -0,0 +1,339 @@
1
+ import { Feature } from 'ol';
2
+ import { Circle, LineString, Point, Polygon } from 'ol/geom.js';
3
+ import { Fill, Icon, Stroke, Style } from 'ol/style.js';
4
+ import { Color } from '@vcmap-cesium/engine';
5
+ import { unByKey } from 'ol/Observable.js';
6
+ import { handlerSymbol } from '../editorSymbols.js';
7
+ import {
8
+ AXIS_AND_PLANES,
9
+ greyedOutColor,
10
+ is1DAxis,
11
+ is2DAxis,
12
+ TransformationMode,
13
+ } from './transformationTypes.js';
14
+ import { mercatorProjection } from '../../projection.js';
15
+ import Vector from '../../../layer/vectorLayer.js';
16
+
17
+ /**
18
+ * @param {import("ol/coordinate").Coordinate} center
19
+ * @param {AXIS_AND_PLANES} axis
20
+ * @param {import("ol/extent").Extent} extent
21
+ * @returns {Array<import("ol/coordinate").Coordinate>}
22
+ */
23
+ function createAxisPositions(center, axis, extent) {
24
+ if (axis === AXIS_AND_PLANES.X) {
25
+ return [
26
+ [extent[0], center[1], center[2]],
27
+ [center[0], center[1], center[2]],
28
+ [extent[2], center[1], center[2]],
29
+ ];
30
+ }
31
+
32
+ return [
33
+ [center[0], extent[1], center[2]],
34
+ [center[0], center[1], center[2]],
35
+ [center[0], extent[3], center[2]],
36
+ ];
37
+ }
38
+
39
+ /**
40
+ * Creates a function to add axis to the scratch layer. To cleanup features created by this function, you can call
41
+ * it with AXIS_AND_PLANES.NONE.
42
+ * @param {import("@vcmap/core").VectorLayer} scratchLayer
43
+ * @param {import("ol/extent").Extent} [projectionExtent]
44
+ * @returns {function(AXIS_AND_PLANES, import("ol/coordinate").Coordinate):void}
45
+ */
46
+ function createShowAxisFeatures(scratchLayer, projectionExtent) {
47
+ let featureIds;
48
+ const extent = projectionExtent ?? mercatorProjection.proj.getExtent();
49
+
50
+ return (axis, center) => {
51
+ if (featureIds) {
52
+ scratchLayer.removeFeaturesById(featureIds);
53
+ featureIds = null;
54
+ }
55
+ if (axis !== AXIS_AND_PLANES.NONE) {
56
+ const features = [];
57
+ if (axis === AXIS_AND_PLANES.X || axis === AXIS_AND_PLANES.XY) {
58
+ const feature = new Feature({
59
+ geometry: new LineString(
60
+ createAxisPositions(center, AXIS_AND_PLANES.X, extent),
61
+ ),
62
+ });
63
+ feature.setStyle(
64
+ new Style({
65
+ stroke: new Stroke({
66
+ color: Color.RED.withAlpha(0.5).toCssColorString(),
67
+ width: 1,
68
+ }),
69
+ }),
70
+ );
71
+ features.push(feature);
72
+ }
73
+ if (axis === AXIS_AND_PLANES.Y || axis === AXIS_AND_PLANES.XY) {
74
+ const feature = new Feature({
75
+ geometry: new LineString(
76
+ createAxisPositions(center, AXIS_AND_PLANES.Y, extent),
77
+ ),
78
+ });
79
+ feature.setStyle(
80
+ new Style({
81
+ stroke: new Stroke({
82
+ color: Color.GREEN.withAlpha(0.5).toCssColorString(),
83
+ width: 1,
84
+ }),
85
+ }),
86
+ );
87
+ features.push(feature);
88
+ }
89
+ features.forEach((f) => {
90
+ const geometry = f.getGeometry();
91
+ geometry[Vector.alreadyTransformedToImage] = true;
92
+ geometry[Vector.doNotTransform] = true;
93
+ });
94
+ featureIds = scratchLayer.addFeatures(features);
95
+ }
96
+ };
97
+ }
98
+
99
+ /**
100
+ * @param {AXIS_AND_PLANES} axis
101
+ * @param {TransformationMode} mode
102
+ * @param {string=} [colorOverride]
103
+ * @returns {Array<import("ol").Feature>}
104
+ */
105
+ function createLineAxisFeatures(axis, mode, colorOverride) {
106
+ let color;
107
+ let coordinates;
108
+ let rotation = 0;
109
+
110
+ if (axis === AXIS_AND_PLANES.X) {
111
+ color = Color.RED.toCssColorString();
112
+ coordinates = [
113
+ [0, 0, 0],
114
+ [1, 0, 0],
115
+ ];
116
+ rotation = Math.PI / 2;
117
+ } else {
118
+ color = Color.GREEN.toCssColorString();
119
+ coordinates = [
120
+ [0, 0, 0],
121
+ [0, 1, 0],
122
+ ];
123
+ }
124
+ color = colorOverride ?? color;
125
+ let src;
126
+ if (mode === TransformationMode.TRANSLATE) {
127
+ src =
128
+ '<svg height="13" width="13" xmlns="http://www.w3.org/2000/svg"><polygon points="0,13 13,13 6,0" style="fill:white;" /></svg>'; // an arrow svg
129
+ } else {
130
+ src =
131
+ '<svg height="13" width="13" xmlns="http://www.w3.org/2000/svg"><polygon points="0,0 13,0 13,13 0,13" style="fill:white" /></svg>'; // a cube svg
132
+ }
133
+ src = `data:image/svg+xml,${encodeURIComponent(src)}`;
134
+
135
+ const features = [
136
+ new Feature({
137
+ geometry: new Point(coordinates[1].slice()),
138
+ axis,
139
+ }),
140
+ new Feature({
141
+ geometry: new LineString(coordinates),
142
+ axis,
143
+ }),
144
+ ];
145
+ features[0].setStyle(
146
+ new Style({
147
+ image: new Icon({
148
+ src,
149
+ anchor: [0.5, 1],
150
+ color,
151
+ rotation,
152
+ }),
153
+ }),
154
+ );
155
+ features[1].setStyle(new Style({ stroke: new Stroke({ color, width: 4 }) }));
156
+
157
+ return features;
158
+ }
159
+
160
+ /**
161
+ * @param {string=} [colorOverride]
162
+ * @returns {import("ol").Feature<Polygon>}
163
+ */
164
+ function createPlaneFeature(colorOverride) {
165
+ const feature = new Feature({
166
+ geometry: new Polygon([
167
+ [
168
+ [0.2, 0.2, 0],
169
+ [0.2, 0.4, 0],
170
+ [0.4, 0.4, 0],
171
+ [0.4, 0.2, 0],
172
+ [0.2, 0.2, 0],
173
+ ],
174
+ ]),
175
+ axis: AXIS_AND_PLANES.XY,
176
+ });
177
+ const color = colorOverride ?? Color.BLUE.toCssColorString();
178
+ feature.setStyle(new Style({ fill: new Fill({ color }) }));
179
+ return feature;
180
+ }
181
+
182
+ /**
183
+ * Creates a function to add a shadow (greyed out clone of a handler) to the scratch layer. To cleanup features created by this function, you can call
184
+ * it with AXIS_AND_PLANES.NONE.
185
+ * @param {import("@vcmap/core").VectorLayer} scratchLayer
186
+ * @returns {function(AXIS_AND_PLANES, TransformationMode, import("ol/coordinate").Coordinate, number):void}
187
+ */
188
+ function createShowShadowFeatures(scratchLayer) {
189
+ let featureIds;
190
+ const color = greyedOutColor.toCssColorString();
191
+
192
+ return (axis, mode, center, scale) => {
193
+ if (featureIds) {
194
+ scratchLayer.removeFeaturesById(featureIds);
195
+ featureIds = null;
196
+ }
197
+ if (axis !== AXIS_AND_PLANES.NONE) {
198
+ let features = [];
199
+ if (is1DAxis(axis)) {
200
+ features = createLineAxisFeatures(axis, mode, color);
201
+ } else if (is2DAxis(axis)) {
202
+ features = [createPlaneFeature(color)];
203
+ }
204
+ features.forEach((f) => {
205
+ f.getGeometry().applyTransform((input, output) => {
206
+ const inputLength = input.length;
207
+ for (let i = 0; i < inputLength; i += 3) {
208
+ output[i] = input[i] * scale + center[0];
209
+ output[i + 1] = input[i + 1] * scale + center[1];
210
+ output[i + 2] = 0;
211
+ }
212
+ return output;
213
+ });
214
+ });
215
+ featureIds = scratchLayer.addFeatures(features);
216
+ }
217
+ };
218
+ }
219
+
220
+ /**
221
+ * The function will create 2D handlers for the {@see OpenlayerMap} and the {@see ObliqueMap} depending on the provided mode.
222
+ * In most scenarios, handlers must not be created using this function, but using the startEditFeaturesSession or for lower
223
+ * level access the createTransformationHandler instead.
224
+ * @param {import("@vcmap/core").BaseOLMap} map
225
+ * @param {import("@vcmap/core").VectorLayer} scratchLayer
226
+ * @param {TransformationMode} mode
227
+ * @returns {Handlers}
228
+ */
229
+ export default function create2DHandlers(map, scratchLayer, mode) {
230
+ let center = [0, 0, 0];
231
+ let scale = 1;
232
+ let features = [];
233
+ if (
234
+ mode === TransformationMode.TRANSLATE ||
235
+ mode === TransformationMode.SCALE
236
+ ) {
237
+ features = [
238
+ ...createLineAxisFeatures(AXIS_AND_PLANES.X, mode),
239
+ ...createLineAxisFeatures(AXIS_AND_PLANES.Y, mode),
240
+ createPlaneFeature(),
241
+ ];
242
+ } else if (mode === TransformationMode.ROTATE) {
243
+ features = [
244
+ new Feature({
245
+ geometry: new Circle([0, 0, 0], 0.5),
246
+ axis: AXIS_AND_PLANES.Z,
247
+ }),
248
+ ];
249
+ features[0].setStyle(
250
+ new Style({
251
+ stroke: new Stroke({ color: Color.BLUE.toCssColorString(), width: 2 }),
252
+ }),
253
+ );
254
+ }
255
+
256
+ features.forEach((f) => {
257
+ const geometry = f.getGeometry();
258
+ geometry[Vector.alreadyTransformedToImage] = true;
259
+ geometry[Vector.doNotTransform] = true;
260
+ f[handlerSymbol] = f.get('axis');
261
+ });
262
+
263
+ const postRenderListenerKey = map.olMap.on('postrender', () => {
264
+ if (!(center[0] === 0 && center[1] === 0 && center[2] === 0)) {
265
+ const res = map.getCurrentResolution(center) * 60;
266
+ const factor = res / scale;
267
+ if (factor !== 1) {
268
+ features.forEach((f) => {
269
+ f.getGeometry().applyTransform((input, output) => {
270
+ const inputLength = input.length;
271
+ for (let i = 0; i < inputLength; i += 3) {
272
+ output[i] = (input[i] - center[0]) * factor + center[0];
273
+ output[i + 1] = (input[i + 1] - center[1]) * factor + center[1];
274
+ output[i + 2] = 0;
275
+ }
276
+ return output;
277
+ });
278
+ });
279
+ }
280
+
281
+ scale = res;
282
+ }
283
+ });
284
+
285
+ let showAxis = AXIS_AND_PLANES.NONE;
286
+ const showAxisFeatures = createShowAxisFeatures(scratchLayer);
287
+ const showShadowFeatures = createShowShadowFeatures(scratchLayer);
288
+
289
+ let showing = false;
290
+
291
+ return {
292
+ get show() {
293
+ return showing;
294
+ },
295
+ set show(show) {
296
+ if (show !== showing) {
297
+ showing = show;
298
+ if (!show) {
299
+ scratchLayer.removeFeaturesById(features.map((f) => f.getId()));
300
+ } else {
301
+ scratchLayer.addFeatures(features);
302
+ }
303
+ }
304
+ },
305
+ get showAxis() {
306
+ return showAxis;
307
+ },
308
+ set showAxis(axis) {
309
+ showAxis = axis;
310
+ showAxisFeatures(axis, center);
311
+ showShadowFeatures(axis, mode, center, scale);
312
+ },
313
+ greyOutZ: false,
314
+ setCenter(newCenter) {
315
+ const dx = newCenter[0] - center[0];
316
+ const dy = newCenter[1] - center[1];
317
+ features.forEach((f) => {
318
+ f.getGeometry().applyTransform((input, output) => {
319
+ const inputLength = input.length;
320
+ for (let i = 0; i < inputLength; i += 3) {
321
+ output[i] = input[i] + dx;
322
+ output[i + 1] = input[i + 1] + dy;
323
+ output[i + 2] = input[i + 2];
324
+ }
325
+ return output;
326
+ });
327
+ });
328
+ center = newCenter.slice();
329
+ },
330
+ destroy() {
331
+ unByKey(postRenderListenerKey);
332
+ showAxisFeatures(AXIS_AND_PLANES.NONE, center);
333
+ showShadowFeatures(AXIS_AND_PLANES.NONE, mode, center, scale);
334
+ scratchLayer.removeFeaturesById(
335
+ features.map((f) => f.getId()).filter((id) => id),
336
+ );
337
+ },
338
+ };
339
+ }