@vcmap/core 5.0.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +44 -0
  3. package/build/postinstall.js +44 -0
  4. package/index.js +139 -0
  5. package/package.json +92 -0
  6. package/src/cesium/cesium3DTileFeature.js +9 -0
  7. package/src/cesium/cesium3DTilePointFeature.js +9 -0
  8. package/src/cesium/cesiumVcsCameraPrimitive.js +146 -0
  9. package/src/cesium/wallpaperMaterial.js +64 -0
  10. package/src/ol/feature.js +47 -0
  11. package/src/ol/geom/circle.js +24 -0
  12. package/src/ol/geom/geometryCollection.js +33 -0
  13. package/src/ol/render/canvas/canvasTileRenderer.js +179 -0
  14. package/src/ol/source/ClusterEnhancedVectorSource.js +39 -0
  15. package/src/ol/source/VcsCluster.js +37 -0
  16. package/src/vcs/vcm/classRegistry.js +106 -0
  17. package/src/vcs/vcm/event/vcsEvent.js +89 -0
  18. package/src/vcs/vcm/globalCollections.js +11 -0
  19. package/src/vcs/vcm/interaction/abstractInteraction.js +149 -0
  20. package/src/vcs/vcm/interaction/coordinateAtPixel.js +102 -0
  21. package/src/vcs/vcm/interaction/eventHandler.js +425 -0
  22. package/src/vcs/vcm/interaction/featureAtPixelInteraction.js +286 -0
  23. package/src/vcs/vcm/interaction/featureProviderInteraction.js +54 -0
  24. package/src/vcs/vcm/interaction/interactionChain.js +124 -0
  25. package/src/vcs/vcm/interaction/interactionType.js +114 -0
  26. package/src/vcs/vcm/layer/buildings.js +17 -0
  27. package/src/vcs/vcm/layer/cesium/cesiumTilesetCesium.js +359 -0
  28. package/src/vcs/vcm/layer/cesium/clusterContext.js +95 -0
  29. package/src/vcs/vcm/layer/cesium/dataSourceCesium.js +171 -0
  30. package/src/vcs/vcm/layer/cesium/openStreetMapCesium.js +29 -0
  31. package/src/vcs/vcm/layer/cesium/pointCloudCesium.js +58 -0
  32. package/src/vcs/vcm/layer/cesium/rasterLayerCesium.js +110 -0
  33. package/src/vcs/vcm/layer/cesium/singleImageCesium.js +49 -0
  34. package/src/vcs/vcm/layer/cesium/terrainCesium.js +80 -0
  35. package/src/vcs/vcm/layer/cesium/tmsCesium.js +54 -0
  36. package/src/vcs/vcm/layer/cesium/vectorCesium.js +255 -0
  37. package/src/vcs/vcm/layer/cesium/vectorContext.js +167 -0
  38. package/src/vcs/vcm/layer/cesium/vectorRasterTileCesium.js +116 -0
  39. package/src/vcs/vcm/layer/cesium/vectorTileImageryProvider.js +246 -0
  40. package/src/vcs/vcm/layer/cesium/wmsCesium.js +71 -0
  41. package/src/vcs/vcm/layer/cesium/wmtsCesium.js +101 -0
  42. package/src/vcs/vcm/layer/cesium/x3dmHelper.js +22 -0
  43. package/src/vcs/vcm/layer/cesiumTileset.js +376 -0
  44. package/src/vcs/vcm/layer/czml.js +141 -0
  45. package/src/vcs/vcm/layer/dataSource.js +259 -0
  46. package/src/vcs/vcm/layer/featureLayer.js +261 -0
  47. package/src/vcs/vcm/layer/featureStore.js +647 -0
  48. package/src/vcs/vcm/layer/featureStoreChanges.js +360 -0
  49. package/src/vcs/vcm/layer/featureStoreState.js +19 -0
  50. package/src/vcs/vcm/layer/featureVisibility.js +435 -0
  51. package/src/vcs/vcm/layer/geojson.js +185 -0
  52. package/src/vcs/vcm/layer/geojsonHelpers.js +450 -0
  53. package/src/vcs/vcm/layer/globalHider.js +157 -0
  54. package/src/vcs/vcm/layer/layer.js +752 -0
  55. package/src/vcs/vcm/layer/layerImplementation.js +102 -0
  56. package/src/vcs/vcm/layer/layerState.js +17 -0
  57. package/src/vcs/vcm/layer/layerSymbols.js +6 -0
  58. package/src/vcs/vcm/layer/oblique/layerOblique.js +76 -0
  59. package/src/vcs/vcm/layer/oblique/obliqueHelpers.js +175 -0
  60. package/src/vcs/vcm/layer/oblique/vectorOblique.js +469 -0
  61. package/src/vcs/vcm/layer/openStreetMap.js +194 -0
  62. package/src/vcs/vcm/layer/openlayers/layerOpenlayers.js +79 -0
  63. package/src/vcs/vcm/layer/openlayers/openStreetMapOpenlayers.js +27 -0
  64. package/src/vcs/vcm/layer/openlayers/rasterLayerOpenlayers.js +121 -0
  65. package/src/vcs/vcm/layer/openlayers/singleImageOpenlayers.js +49 -0
  66. package/src/vcs/vcm/layer/openlayers/tileDebugOpenlayers.js +39 -0
  67. package/src/vcs/vcm/layer/openlayers/tmsOpenlayers.js +62 -0
  68. package/src/vcs/vcm/layer/openlayers/vectorOpenlayers.js +118 -0
  69. package/src/vcs/vcm/layer/openlayers/vectorTileOpenlayers.js +177 -0
  70. package/src/vcs/vcm/layer/openlayers/wmsOpenlayers.js +55 -0
  71. package/src/vcs/vcm/layer/openlayers/wmtsOpenlayers.js +141 -0
  72. package/src/vcs/vcm/layer/pointCloud.js +162 -0
  73. package/src/vcs/vcm/layer/rasterLayer.js +294 -0
  74. package/src/vcs/vcm/layer/singleImage.js +119 -0
  75. package/src/vcs/vcm/layer/terrain.js +122 -0
  76. package/src/vcs/vcm/layer/terrainHelpers.js +123 -0
  77. package/src/vcs/vcm/layer/tileLoadedHelper.js +72 -0
  78. package/src/vcs/vcm/layer/tileProvider/mvtTileProvider.js +104 -0
  79. package/src/vcs/vcm/layer/tileProvider/staticGeojsonTileProvider.js +67 -0
  80. package/src/vcs/vcm/layer/tileProvider/tileProvider.js +584 -0
  81. package/src/vcs/vcm/layer/tileProvider/tileProviderFactory.js +28 -0
  82. package/src/vcs/vcm/layer/tileProvider/urlTemplateTileProvider.js +106 -0
  83. package/src/vcs/vcm/layer/tms.js +121 -0
  84. package/src/vcs/vcm/layer/vector.js +632 -0
  85. package/src/vcs/vcm/layer/vectorHelpers.js +206 -0
  86. package/src/vcs/vcm/layer/vectorProperties.js +1391 -0
  87. package/src/vcs/vcm/layer/vectorSymbols.js +40 -0
  88. package/src/vcs/vcm/layer/vectorTile.js +480 -0
  89. package/src/vcs/vcm/layer/wfs.js +165 -0
  90. package/src/vcs/vcm/layer/wms.js +270 -0
  91. package/src/vcs/vcm/layer/wmsHelpers.js +65 -0
  92. package/src/vcs/vcm/layer/wmts.js +235 -0
  93. package/src/vcs/vcm/maps/baseOLMap.js +257 -0
  94. package/src/vcs/vcm/maps/cameraLimiter.js +219 -0
  95. package/src/vcs/vcm/maps/cesium.js +1192 -0
  96. package/src/vcs/vcm/maps/map.js +511 -0
  97. package/src/vcs/vcm/maps/mapState.js +17 -0
  98. package/src/vcs/vcm/maps/oblique.js +536 -0
  99. package/src/vcs/vcm/maps/openlayers.js +205 -0
  100. package/src/vcs/vcm/object.js +92 -0
  101. package/src/vcs/vcm/oblique/ObliqueCollection.js +572 -0
  102. package/src/vcs/vcm/oblique/ObliqueDataSet.js +357 -0
  103. package/src/vcs/vcm/oblique/ObliqueImage.js +247 -0
  104. package/src/vcs/vcm/oblique/ObliqueImageMeta.js +126 -0
  105. package/src/vcs/vcm/oblique/ObliqueProvider.js +433 -0
  106. package/src/vcs/vcm/oblique/ObliqueView.js +130 -0
  107. package/src/vcs/vcm/oblique/ObliqueViewDirection.js +40 -0
  108. package/src/vcs/vcm/oblique/helpers.js +483 -0
  109. package/src/vcs/vcm/oblique/parseImageJson.js +248 -0
  110. package/src/vcs/vcm/util/clipping/clippingObject.js +386 -0
  111. package/src/vcs/vcm/util/clipping/clippingObjectManager.js +312 -0
  112. package/src/vcs/vcm/util/clipping/clippingPlaneHelper.js +413 -0
  113. package/src/vcs/vcm/util/collection.js +193 -0
  114. package/src/vcs/vcm/util/dateTime.js +60 -0
  115. package/src/vcs/vcm/util/exclusiveManager.js +135 -0
  116. package/src/vcs/vcm/util/extent.js +124 -0
  117. package/src/vcs/vcm/util/featureProvider/abstractFeatureProvider.js +196 -0
  118. package/src/vcs/vcm/util/featureProvider/featureProviderHelpers.js +51 -0
  119. package/src/vcs/vcm/util/featureProvider/featureProviderSymbols.js +11 -0
  120. package/src/vcs/vcm/util/featureProvider/tileProviderFeatureProvider.js +62 -0
  121. package/src/vcs/vcm/util/featureProvider/wmsFeatureProvider.js +280 -0
  122. package/src/vcs/vcm/util/featureconverter/circleToCesium.js +215 -0
  123. package/src/vcs/vcm/util/featureconverter/convert.js +83 -0
  124. package/src/vcs/vcm/util/featureconverter/extent3d.js +154 -0
  125. package/src/vcs/vcm/util/featureconverter/featureconverterHelper.js +591 -0
  126. package/src/vcs/vcm/util/featureconverter/lineStringToCesium.js +171 -0
  127. package/src/vcs/vcm/util/featureconverter/pointToCesium.js +359 -0
  128. package/src/vcs/vcm/util/featureconverter/polygonToCesium.js +229 -0
  129. package/src/vcs/vcm/util/geometryHelpers.js +172 -0
  130. package/src/vcs/vcm/util/indexedCollection.js +158 -0
  131. package/src/vcs/vcm/util/isMobile.js +12 -0
  132. package/src/vcs/vcm/util/layerCollection.js +216 -0
  133. package/src/vcs/vcm/util/locale.js +53 -0
  134. package/src/vcs/vcm/util/mapCollection.js +363 -0
  135. package/src/vcs/vcm/util/math.js +71 -0
  136. package/src/vcs/vcm/util/projection.js +348 -0
  137. package/src/vcs/vcm/util/splitScreen.js +233 -0
  138. package/src/vcs/vcm/util/style/declarativeStyleItem.js +631 -0
  139. package/src/vcs/vcm/util/style/shapesCategory.js +67 -0
  140. package/src/vcs/vcm/util/style/styleFactory.js +48 -0
  141. package/src/vcs/vcm/util/style/styleHelpers.js +555 -0
  142. package/src/vcs/vcm/util/style/styleItem.js +226 -0
  143. package/src/vcs/vcm/util/style/vectorStyleItem.js +927 -0
  144. package/src/vcs/vcm/util/style/writeStyle.js +48 -0
  145. package/src/vcs/vcm/util/urlHelpers.js +16 -0
  146. package/src/vcs/vcm/util/viewpoint.js +333 -0
@@ -0,0 +1,450 @@
1
+ import GeoJSON from 'ol/format/GeoJSON.js';
2
+ import Polygon from 'ol/geom/Polygon.js';
3
+ import MultiPolygon from 'ol/geom/MultiPolygon.js';
4
+ import Feature from 'ol/Feature.js';
5
+ import Point from 'ol/geom/Point.js';
6
+ import Circle from 'ol/geom/Circle.js';
7
+
8
+ import { getDistance as haversineDistance } from 'ol/sphere.js';
9
+ import { getLogger as getLoggerByName } from '@vcsuite/logger';
10
+ import Projection, { mercatorProjection, wgs84Projection } from '../util/projection.js';
11
+ import VectorStyleItem, { defaultVectorStyle, vectorStyleSymbol } from '../util/style/vectorStyleItem.js';
12
+ import { parseColor } from '../util/style/styleHelpers.js';
13
+ import Vector from './vector.js';
14
+ import { featureStoreStateSymbol } from './featureStoreState.js';
15
+ import { StyleType } from '../util/style/styleItem.js';
16
+ import writeStyle, { embedIconsInStyle } from '../util/style/writeStyle.js';
17
+ import DeclarativeStyleItem from '../util/style/declarativeStyleItem.js';
18
+ import { vcsMetaVersion } from './layer.js';
19
+ import { createOrUpdateFromGeometry } from '../util/featureconverter/extent3d.js';
20
+ import { styleCollection } from '../globalCollections.js';
21
+ import { circleFromCenterRadius, enforceEndingVertex, removeEndingVertexFromGeometry } from '../util/geometryHelpers.js';
22
+
23
+ const featureProjection = 'EPSG:3857';
24
+
25
+ /**
26
+ * @type {import("ol/format/GeoJSON").default}
27
+ * @private
28
+ */
29
+ let format;
30
+
31
+ /**
32
+ * @returns {import("ol/format/GeoJSON").default}
33
+ */
34
+ function getFormat() {
35
+ if (!format) {
36
+ format = new GeoJSON();
37
+ }
38
+ return format;
39
+ }
40
+
41
+ /**
42
+ * @returns {import("@vcsuite/logger").Logger}
43
+ */
44
+ function getLogger() {
45
+ return getLoggerByName('vcs.vcm.layer.GeoJSONHelper');
46
+ }
47
+
48
+ /**
49
+ * @typedef {Object} GeoJSONData
50
+ * @property {Array<import("ol").Feature<import("ol/geom/Geometry").default>>} features
51
+ * @property {import("@vcmap/core").StyleItem|undefined} style
52
+ * @property {VcsMeta|undefined} vcsMeta
53
+ * @api
54
+ */
55
+
56
+ /**
57
+ * @typedef {GeoJSONreadOptions} GeoJSONinternalReadOptions
58
+ * @property {import("ol/format/Feature").ReadOptions|undefined} formatOptions
59
+ * @property {Array<string>|undefined} embeddedIcons
60
+ */
61
+
62
+ /**
63
+ * @typedef {Object} GeoJSONreadOptions
64
+ * @property {Projection|undefined} targetProjection - projection of the output features, if undefined Mercator will be used
65
+ * @property {Projection|undefined} dataProjection - projection of the input dataset if undefined WGS84 will be assumed
66
+ * @property {boolean} [dynamicStyle=false]
67
+ * @property {boolean} [readLegacyStyleOptions=false]
68
+ * @property {boolean} [dontReadStyle=false]
69
+ * @property {VectorStyleItem|undefined} defaultStyle
70
+ */
71
+
72
+ /**
73
+ * @typedef {Object} GeoJSONwriteOptions
74
+ * @property {boolean} [asObject=false] - whether to write an object or a string
75
+ * @property {boolean} [writeStyle=false] - whether to include vcsStyle options
76
+ * @property {boolean} [writeDefaultStyle=false] - whether to output the default style. if the style of a layer is the default layer it is not written.
77
+ * @property {boolean} [embedIcons=false] - whether to embed custom icons when writing styles, otherwise no style is written for custom icons
78
+ * @property {boolean} [prettyPrint=false] - pretty print the json, if not asObject
79
+ * @property {boolean} [writeId=false] - whether to output the feature ID
80
+ * @api
81
+ */
82
+
83
+
84
+ /**
85
+ * @param {Object} geojson
86
+ * @returns {string|null}
87
+ * @export
88
+ */
89
+ export function getEPSGCodeFromGeojson(geojson) {
90
+ const { crs } = geojson;
91
+ if (crs) {
92
+ if (crs.type === 'name') {
93
+ return crs.properties.name;
94
+ } else if (crs.type === 'EPSG') {
95
+ // 'EPSG' is not part of the GeoJSON specification, but is generated by
96
+ // GeoServer.
97
+ // TODO: remove this when http://jira.codehaus.org/browse/GEOS-5996
98
+ // is fixed and widely deployed.
99
+ return `EPSG:${crs.properties.code}`;
100
+ }
101
+ }
102
+ return null;
103
+ }
104
+
105
+ /**
106
+ * updates legacy features to the new olcesium namespaceing olcs_
107
+ * @param {import("ol").Feature<import("ol/geom/Geometry").default>} feature
108
+ * @export
109
+ */
110
+ export function updateLegacyFeature(feature) {
111
+ // these changes can be done silently, because the features haven't been added to any layer
112
+ if (feature.get('altitudeMode')) {
113
+ feature.set('olcs_altitudeMode', feature.get('altitudeMode'), true);
114
+ feature.unset('altitudeMode', true);
115
+ }
116
+ if (feature.get('extrudedHeight')) {
117
+ if (feature.get('drawingType')) {
118
+ feature.set('olcs_extrudedHeight', feature.get('extrudedHeight'), true);
119
+ } else {
120
+ const extent = createOrUpdateFromGeometry(feature.getGeometry());
121
+ const minHeight = Number.isFinite(extent[2]) ? extent[2] : 0;
122
+ feature.set('olcs_extrudedHeight', feature.get('extrudedHeight') - minHeight, true);
123
+ }
124
+ feature.unset('extrudedHeight', true);
125
+ }
126
+ if (feature.get('skirt')) {
127
+ feature.set('olcs_skirt', feature.get('skirt'), true);
128
+ feature.unset('skirt', true);
129
+ }
130
+
131
+ if (feature.get('radius')) {
132
+ feature.unset('radius', true);
133
+ }
134
+ }
135
+
136
+ /**
137
+ * @param {Object} geometryObj
138
+ * @param {GeoJSONinternalReadOptions} options
139
+ * @returns {import("ol").Feature<import("ol/geom/Geometry").default>}
140
+ */
141
+ function readGeometry(geometryObj, options) {
142
+ const geometry = getFormat().readGeometry(geometryObj, options.formatOptions);
143
+ if (String(options.formatOptions.featureProjection) === 'EPSG:3857') {
144
+ geometry[Vector.alreadyTransformedToMercator] = true;
145
+ }
146
+ removeEndingVertexFromGeometry(geometry);
147
+ return new Feature({ geometry });
148
+ }
149
+
150
+ /**
151
+ * @param {VectorStyleItemOptions} object
152
+ * @param {GeoJSONinternalReadOptions} options
153
+ * @returns {VectorStyleItemOptions}
154
+ * @todo this could also be done for declarative styles image and conditions could be checked?
155
+ */
156
+ function setEmbeddedIcons(object, options) {
157
+ if (
158
+ object.image &&
159
+ object.image.src &&
160
+ /^:\d+$/.test(object.image.src)
161
+ ) {
162
+ if (options.embeddedIcons) {
163
+ object.image.src = options.embeddedIcons[object.image.src.substring(1)];
164
+ } else {
165
+ delete object.image.src;
166
+ }
167
+ }
168
+ return object;
169
+ }
170
+
171
+ /**
172
+ * @param {Object} properties
173
+ * @param {string} geometryType
174
+ * @returns {VectorStyleItemOptions|undefined}
175
+ */
176
+ function parseLegacyStyleOptions(properties, geometryType) {
177
+ const color = properties.color ? parseColor(properties.color) : false;
178
+ const width = properties.width || 1.25;
179
+ const radius = properties.pointRadius || 5;
180
+ const opacity = properties.opacity || 0.8;
181
+
182
+ delete properties.color;
183
+ delete properties.width;
184
+ delete properties.pointRadius;
185
+ delete properties.opacity;
186
+
187
+ if (geometryType === 'Polygon' || geometryType === 'Circle') {
188
+ const fillColor = color ? color.slice() : [255, 255, 255, 0.4];
189
+ fillColor[3] = opacity;
190
+ return {
191
+ fill: { color: /** @type {import("ol/color").Color} */ (fillColor) },
192
+ stroke: {
193
+ color: color || parseColor('#3399CC'),
194
+ width,
195
+ },
196
+ };
197
+ }
198
+ if (geometryType === 'LineString') {
199
+ return {
200
+ stroke: {
201
+ color: color || parseColor('#3399CC'),
202
+ width,
203
+ },
204
+ };
205
+ }
206
+ if (geometryType === 'Point') {
207
+ return {
208
+ image: {
209
+ fill: {
210
+ color: [255, 255, 255, 0.4],
211
+ },
212
+ radius,
213
+ stroke: {
214
+ color: color || parseColor('#3399CC'),
215
+ width: 1,
216
+ },
217
+ },
218
+ };
219
+ }
220
+ return undefined;
221
+ }
222
+ /**
223
+ * @param {Object} featureObj
224
+ * @param {GeoJSONinternalReadOptions} options
225
+ * @returns {import("ol").Feature<import("ol/geom/Geometry").default>|null}
226
+ */
227
+ function readFeature(featureObj, options) {
228
+ if (!featureObj.geometry) {
229
+ return null;
230
+ }
231
+ const radius = featureObj.geometry.olcs_radius;
232
+ let geometry = getFormat().readGeometry(featureObj.geometry, options.formatOptions);
233
+
234
+ if (featureObj.radius && geometry instanceof Point) {
235
+ const coordinates = geometry.getCoordinates();
236
+ if (coordinates.length === 2) {
237
+ coordinates.push(0);
238
+ }
239
+ geometry = new Circle(coordinates, featureObj.radius, 'XYZ');
240
+ }
241
+ if (radius && geometry instanceof Point) {
242
+ const coordinates = geometry.getCoordinates();
243
+ if (coordinates.length === 2) {
244
+ coordinates.push(0);
245
+ }
246
+ geometry = circleFromCenterRadius(coordinates, radius);
247
+ }
248
+ if (String(options.formatOptions.featureProjection) === 'EPSG:3857') {
249
+ geometry[Vector.alreadyTransformedToMercator] = true;
250
+ }
251
+
252
+ featureObj.vcsMeta = featureObj.vcsMeta || {};
253
+ if (featureObj.vcsStyle) {
254
+ featureObj.vcsMeta.style = featureObj.vcsMeta.style || featureObj.vcsStyle;
255
+ }
256
+ const { properties } = featureObj;
257
+ if (options.readLegacyStyleOptions && !featureObj.vcsMeta.style) {
258
+ featureObj.vcsMeta.style = parseLegacyStyleOptions(properties, geometry.getType());
259
+ }
260
+ removeEndingVertexFromGeometry(geometry);
261
+ const feature = new Feature({ ...properties, geometry });
262
+ if (featureObj.id) {
263
+ feature.setId(featureObj.id);
264
+ }
265
+
266
+ if (featureObj.state) {
267
+ feature[featureStoreStateSymbol] = featureObj.state;
268
+ }
269
+
270
+ if (featureObj.vcsMeta.style && !options.dontReadStyle) {
271
+ featureObj.vcsMeta.style = setEmbeddedIcons(featureObj.vcsMeta.style, options);
272
+ let styleItem;
273
+ if (options.defaultStyle) {
274
+ styleItem = options.defaultStyle
275
+ .clone()
276
+ .assign(new VectorStyleItem(featureObj.vcsMeta.style));
277
+ if (styleItem.label != null) {
278
+ geometry.set('_vcsGeomType', 'Label');
279
+ }
280
+ } else {
281
+ styleItem = new VectorStyleItem(featureObj.vcsMeta.style);
282
+ }
283
+ feature[vectorStyleSymbol] = styleItem;
284
+ feature.setStyle(styleItem.style);
285
+ }
286
+ updateLegacyFeature(feature);
287
+ return feature;
288
+ }
289
+
290
+ /**
291
+ * parses a string to GeoJSON
292
+ * @param {string|Object} input
293
+ * @param {GeoJSONreadOptions=} readOptions
294
+ * @returns {GeoJSONData}
295
+ * @throws SyntaxError
296
+ * @export
297
+ * @api
298
+ */
299
+ export function parseGeoJSON(input, readOptions = {}) {
300
+ const geoJSON = typeof input === 'string' ? JSON.parse(input) : input;
301
+
302
+ const epsgCode = getEPSGCodeFromGeojson(geoJSON);
303
+ const defaultDataProjection = epsgCode ? { epsg: epsgCode } : readOptions.dataProjection;
304
+ /** @type {GeoJSONinternalReadOptions} */
305
+ const options = {
306
+ formatOptions: {
307
+ dataProjection: defaultDataProjection ?
308
+ defaultDataProjection.epsg :
309
+ wgs84Projection.epsg,
310
+ featureProjection: readOptions.targetProjection ?
311
+ readOptions.targetProjection.epsg :
312
+ mercatorProjection.epsg,
313
+ },
314
+ dontReadStyle: readOptions.dontReadStyle,
315
+ readLegacyStyleOptions: readOptions.readLegacyStyleOptions,
316
+ defaultStyle: readOptions.defaultStyle,
317
+ };
318
+
319
+ if (readOptions.dynamicStyle && !options.defaultStyle) {
320
+ options.defaultStyle = defaultVectorStyle;
321
+ }
322
+
323
+ if (geoJSON.type === 'FeatureCollection') {
324
+ geoJSON.vcsMeta = geoJSON.vcsMeta || {
325
+ embeddedIcons: geoJSON.vcsEmbeddedIcons,
326
+ style: geoJSON.vcsStyle,
327
+ };
328
+
329
+ let style;
330
+ if (geoJSON.vcsMeta.embeddedIcons) {
331
+ options.embeddedIcons = geoJSON.vcsMeta.embeddedIcons;
332
+ }
333
+ if (geoJSON.vcsMeta.style && readOptions.dynamicStyle) {
334
+ if (geoJSON.vcsMeta.style.type === StyleType.REFERENCE) {
335
+ style = styleCollection.getByKey(geoJSON.vcsMeta.style.name);
336
+ if (!style) {
337
+ getLogger().warning(`could not load referenced style ${geoJSON.vcsMeta.style.name}`);
338
+ } else if (style instanceof VectorStyleItem) {
339
+ options.defaultStyle = style;
340
+ }
341
+ } else if (geoJSON.vcsMeta.style.type === StyleType.DECLARATIVE) {
342
+ style = new DeclarativeStyleItem(geoJSON.vcsMeta.style);
343
+ } else {
344
+ geoJSON.vcsMeta.style = setEmbeddedIcons(geoJSON.vcsMeta.style, options);
345
+ options.defaultStyle = options.defaultStyle
346
+ .clone()
347
+ .assign(new VectorStyleItem(geoJSON.vcsMeta.style));
348
+ style = options.defaultStyle;
349
+ }
350
+ }
351
+ return {
352
+ features: geoJSON.features.map(f => readFeature(f, options)).filter(f => f),
353
+ style: geoJSON.vcsMeta.style ? style : undefined,
354
+ vcsMeta: geoJSON.vcsMeta ? geoJSON.vcsMeta : undefined,
355
+ };
356
+ } else if (geoJSON.type === 'Feature') {
357
+ const feature = readFeature(geoJSON, options);
358
+ return { features: feature ? [feature] : [], vcsMeta: geoJSON.vcsMeta ? geoJSON.vcsMeta : undefined };
359
+ } else if (geoJSON.type != null) {
360
+ return { features: [readGeometry(geoJSON, options)] };
361
+ }
362
+ return { features: [] };
363
+ }
364
+
365
+ /**
366
+ * @param {import("ol").Feature<import("ol/geom/Geometry").default>} feature
367
+ * @param {GeoJSONwriteOptions=} options
368
+ * @param {Array=} embeddedIcons
369
+ * @returns {Object}
370
+ */
371
+ export function writeGeoJSONFeature(feature, options = {}, embeddedIcons) {
372
+ const featureObject = {
373
+ type: 'Feature',
374
+ properties: feature.getProperties(),
375
+ };
376
+
377
+ if (options.writeId) {
378
+ featureObject.id = feature.getId();
379
+ }
380
+
381
+ delete featureObject.properties[feature.getGeometryName()];
382
+ delete featureObject.properties.style;
383
+ delete featureObject.properties.olcs_allowPicking;
384
+
385
+ let geometry = feature.getGeometry();
386
+ let radius = null;
387
+ if (geometry instanceof Circle) {
388
+ const coordinates = geometry.getCoordinates();
389
+ radius = haversineDistance(
390
+ Projection.mercatorToWgs84(coordinates[0], true),
391
+ Projection.mercatorToWgs84(coordinates[1], true),
392
+ );
393
+ geometry = new Point(geometry.getCenter());
394
+ } else if (geometry instanceof Polygon) {
395
+ const coordinates = geometry.getCoordinates();
396
+ coordinates.forEach((ring) => { enforceEndingVertex(ring); });
397
+ geometry.setCoordinates(coordinates);
398
+ } else if (geometry instanceof MultiPolygon) {
399
+ const coordinates = geometry.getCoordinates();
400
+ coordinates.forEach((poly) => {
401
+ poly.forEach((ring) => { enforceEndingVertex(ring); });
402
+ });
403
+ geometry.setCoordinates(coordinates);
404
+ }
405
+
406
+ featureObject.geometry = getFormat().writeGeometryObject(geometry, {
407
+ featureProjection,
408
+ rightHanded: true,
409
+ });
410
+
411
+ if (radius) {
412
+ featureObject.geometry.olcs_radius = radius;
413
+ }
414
+
415
+ featureObject.vcsMeta = {};
416
+
417
+ if (options.writeStyle && feature[vectorStyleSymbol]) {
418
+ featureObject.vcsMeta.style = embedIconsInStyle(
419
+ feature[vectorStyleSymbol].getOptionsForFeature(feature),
420
+ embeddedIcons,
421
+ );
422
+ }
423
+
424
+ return featureObject;
425
+ }
426
+
427
+ /**
428
+ * Writes all the features of the current layer to GeoJSON
429
+ * @param {GeoJSONData} data
430
+ * @param {GeoJSONwriteOptions=} options
431
+ * @returns {string|Object}
432
+ * @export
433
+ */
434
+ export function writeGeoJSON(data, options = {}) { // how to handel embedded icons when they are not set on the vcsMeta but options is true?
435
+ const vcsMeta = data.vcsMeta || {};
436
+ vcsMeta.version = vcsMetaVersion;
437
+ const featureObjs = data.features.map(feature => writeGeoJSONFeature(feature, options, vcsMeta.embeddedIcons));
438
+ const obj = {
439
+ type: 'FeatureCollection',
440
+ features: featureObjs,
441
+ vcsMeta,
442
+ };
443
+
444
+ if (options.writeStyle && data.style) { // legacy fallback for plugin use
445
+ getLogger().deprecate('data.style', 'use layer.getVcsMeta and pass that in instead');
446
+ writeStyle(data.style, obj.vcsMeta);
447
+ }
448
+
449
+ return options.asObject ? obj : JSON.stringify(obj, null, options.prettyPrint ? 2 : null);
450
+ }
@@ -0,0 +1,157 @@
1
+ import { check } from '@vcsuite/check';
2
+ import { getLogger } from '@vcsuite/logger';
3
+ import {
4
+ globalHidden,
5
+ hideFeature,
6
+ cacheOriginalStyle,
7
+ showFeature,
8
+ FeatureVisibilityAction,
9
+ } from './featureVisibility.js';
10
+ import VcsEvent from '../event/vcsEvent.js';
11
+
12
+ /**
13
+ * @type {GlobalHider}
14
+ */
15
+ let instance;
16
+
17
+ /**
18
+ * @class
19
+ */
20
+ class GlobalHider {
21
+ constructor() {
22
+ /**
23
+ * @type {Object<string, number>}
24
+ * @api
25
+ */
26
+ this.hiddenObjects = {};
27
+ /**
28
+ * @type {Object<string, Set<import("ol").Feature<import("ol/geom/Geometry").default>|import("@vcmap/cesium").Cesium3DTileFeature|import("@vcmap/cesium").Cesium3DTilePointFeature|import("@vcmap/cesium").Entity>>}
29
+ * @private
30
+ */
31
+ this._hiddenObjectFeatures = {};
32
+ /**
33
+ * @type {number}
34
+ * @api
35
+ */
36
+ this.lastUpdated = Date.now();
37
+ /**
38
+ * An event raised when the hidden ids change. Is called with
39
+ * {@link FeatureVisibilityEvent} as its only argument
40
+ * @type {VcsEvent<FeatureVisibilityEvent>}
41
+ */
42
+ this.changed = new VcsEvent();
43
+ }
44
+
45
+ /**
46
+ * Add a tick to the hide count, hidding the features if they are not already hidden
47
+ * @param {Array<string>} uuids
48
+ * @api
49
+ */
50
+ hideObjects(uuids) {
51
+ check(uuids, [String]);
52
+
53
+ const updatedIds = [];
54
+ uuids.forEach((uuid) => {
55
+ if (!this.hiddenObjects[uuid]) {
56
+ updatedIds.push(uuid);
57
+ this.hiddenObjects[uuid] = 0;
58
+ }
59
+ this.hiddenObjects[uuid] += 1;
60
+ });
61
+
62
+ if (updatedIds.length > 0) {
63
+ this.lastUpdated = Date.now();
64
+ this.changed.raiseEvent({ action: FeatureVisibilityAction.HIDE, ids: updatedIds });
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Subtract from the hide count for an Array of ids. If the array reaches 0, features with said UUID will be shown
70
+ * @param {Array<string>} uuids
71
+ * @api
72
+ */
73
+ showObjects(uuids) {
74
+ check(uuids, [String]);
75
+
76
+ const updatedIds = [];
77
+ uuids.forEach((uuid) => {
78
+ if (this.hiddenObjects[uuid]) {
79
+ this.hiddenObjects[uuid] -= 1;
80
+ if (this.hiddenObjects[uuid] === 0) {
81
+ if (this._hiddenObjectFeatures[uuid]) {
82
+ this._hiddenObjectFeatures[uuid].forEach((f) => {
83
+ showFeature(f, globalHidden);
84
+ });
85
+ this._hiddenObjectFeatures[uuid].clear();
86
+ }
87
+ delete this.hiddenObjects[uuid];
88
+ updatedIds.push(uuid);
89
+ }
90
+ }
91
+ });
92
+
93
+ if (updatedIds.length > 0) {
94
+ this.changed.raiseEvent({ action: FeatureVisibilityAction.SHOW, ids: updatedIds });
95
+ }
96
+ }
97
+
98
+ /**
99
+ * @param {number|string} uuid
100
+ * @param {import("ol").Feature<import("ol/geom/Geometry").default>|import("@vcmap/cesium").Cesium3DTileFeature|import("@vcmap/cesium").Cesium3DTilePointFeature|import("@vcmap/cesium").Entity} feature
101
+ */
102
+ addFeature(uuid, feature) {
103
+ if (!this._hiddenObjectFeatures[uuid]) {
104
+ this._hiddenObjectFeatures[uuid] = new Set();
105
+ }
106
+ cacheOriginalStyle(feature);
107
+ this._hiddenObjectFeatures[uuid].add(feature);
108
+ feature[globalHidden] = true;
109
+ hideFeature(feature);
110
+ }
111
+
112
+ /**
113
+ * @param {string|number} uuid
114
+ * @param {import("ol").Feature<import("ol/geom/Geometry").default>|import("@vcmap/cesium").Cesium3DTileFeature|import("@vcmap/cesium").Cesium3DTilePointFeature|import("@vcmap/cesium").Entity} feature
115
+ * @returns {boolean}
116
+ */
117
+ hasFeature(uuid, feature) {
118
+ return this._hiddenObjectFeatures[uuid] ? this._hiddenObjectFeatures[uuid].has(feature) : false;
119
+ }
120
+
121
+ destroy() {
122
+ this.hiddenObjects = {};
123
+ Object.values(this._hiddenObjectFeatures).forEach((set) => { set.clear(); });
124
+ this._hiddenObjectFeatures = {};
125
+ this.changed.destroy();
126
+ }
127
+
128
+ static destroy() {
129
+ if (instance) {
130
+ instance.destroy();
131
+ }
132
+ instance = undefined;
133
+ }
134
+ }
135
+
136
+ /**
137
+ * @returns {GlobalHider}
138
+ * @export
139
+ * @api
140
+ */
141
+ export function getGlobalHider() {
142
+ if (!instance) {
143
+ instance = new GlobalHider();
144
+ }
145
+ return instance;
146
+ }
147
+
148
+ /**
149
+ * @returns {GlobalHider}
150
+ * @deprecated v4.1
151
+ */
152
+ export function getInstance() {
153
+ getLogger('vcs.vcm.layer.GlobalHider').deprecate('getInstance', 'use getGlobalHider instead');
154
+ return getGlobalHider();
155
+ }
156
+
157
+ export default GlobalHider;