@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.
- package/LICENSE.md +21 -0
- package/README.md +44 -0
- package/build/postinstall.js +44 -0
- package/index.js +139 -0
- package/package.json +92 -0
- package/src/cesium/cesium3DTileFeature.js +9 -0
- package/src/cesium/cesium3DTilePointFeature.js +9 -0
- package/src/cesium/cesiumVcsCameraPrimitive.js +146 -0
- package/src/cesium/wallpaperMaterial.js +64 -0
- package/src/ol/feature.js +47 -0
- package/src/ol/geom/circle.js +24 -0
- package/src/ol/geom/geometryCollection.js +33 -0
- package/src/ol/render/canvas/canvasTileRenderer.js +179 -0
- package/src/ol/source/ClusterEnhancedVectorSource.js +39 -0
- package/src/ol/source/VcsCluster.js +37 -0
- package/src/vcs/vcm/classRegistry.js +106 -0
- package/src/vcs/vcm/event/vcsEvent.js +89 -0
- package/src/vcs/vcm/globalCollections.js +11 -0
- package/src/vcs/vcm/interaction/abstractInteraction.js +149 -0
- package/src/vcs/vcm/interaction/coordinateAtPixel.js +102 -0
- package/src/vcs/vcm/interaction/eventHandler.js +425 -0
- package/src/vcs/vcm/interaction/featureAtPixelInteraction.js +286 -0
- package/src/vcs/vcm/interaction/featureProviderInteraction.js +54 -0
- package/src/vcs/vcm/interaction/interactionChain.js +124 -0
- package/src/vcs/vcm/interaction/interactionType.js +114 -0
- package/src/vcs/vcm/layer/buildings.js +17 -0
- package/src/vcs/vcm/layer/cesium/cesiumTilesetCesium.js +359 -0
- package/src/vcs/vcm/layer/cesium/clusterContext.js +95 -0
- package/src/vcs/vcm/layer/cesium/dataSourceCesium.js +171 -0
- package/src/vcs/vcm/layer/cesium/openStreetMapCesium.js +29 -0
- package/src/vcs/vcm/layer/cesium/pointCloudCesium.js +58 -0
- package/src/vcs/vcm/layer/cesium/rasterLayerCesium.js +110 -0
- package/src/vcs/vcm/layer/cesium/singleImageCesium.js +49 -0
- package/src/vcs/vcm/layer/cesium/terrainCesium.js +80 -0
- package/src/vcs/vcm/layer/cesium/tmsCesium.js +54 -0
- package/src/vcs/vcm/layer/cesium/vectorCesium.js +255 -0
- package/src/vcs/vcm/layer/cesium/vectorContext.js +167 -0
- package/src/vcs/vcm/layer/cesium/vectorRasterTileCesium.js +116 -0
- package/src/vcs/vcm/layer/cesium/vectorTileImageryProvider.js +246 -0
- package/src/vcs/vcm/layer/cesium/wmsCesium.js +71 -0
- package/src/vcs/vcm/layer/cesium/wmtsCesium.js +101 -0
- package/src/vcs/vcm/layer/cesium/x3dmHelper.js +22 -0
- package/src/vcs/vcm/layer/cesiumTileset.js +376 -0
- package/src/vcs/vcm/layer/czml.js +141 -0
- package/src/vcs/vcm/layer/dataSource.js +259 -0
- package/src/vcs/vcm/layer/featureLayer.js +261 -0
- package/src/vcs/vcm/layer/featureStore.js +647 -0
- package/src/vcs/vcm/layer/featureStoreChanges.js +360 -0
- package/src/vcs/vcm/layer/featureStoreState.js +19 -0
- package/src/vcs/vcm/layer/featureVisibility.js +435 -0
- package/src/vcs/vcm/layer/geojson.js +185 -0
- package/src/vcs/vcm/layer/geojsonHelpers.js +450 -0
- package/src/vcs/vcm/layer/globalHider.js +157 -0
- package/src/vcs/vcm/layer/layer.js +752 -0
- package/src/vcs/vcm/layer/layerImplementation.js +102 -0
- package/src/vcs/vcm/layer/layerState.js +17 -0
- package/src/vcs/vcm/layer/layerSymbols.js +6 -0
- package/src/vcs/vcm/layer/oblique/layerOblique.js +76 -0
- package/src/vcs/vcm/layer/oblique/obliqueHelpers.js +175 -0
- package/src/vcs/vcm/layer/oblique/vectorOblique.js +469 -0
- package/src/vcs/vcm/layer/openStreetMap.js +194 -0
- package/src/vcs/vcm/layer/openlayers/layerOpenlayers.js +79 -0
- package/src/vcs/vcm/layer/openlayers/openStreetMapOpenlayers.js +27 -0
- package/src/vcs/vcm/layer/openlayers/rasterLayerOpenlayers.js +121 -0
- package/src/vcs/vcm/layer/openlayers/singleImageOpenlayers.js +49 -0
- package/src/vcs/vcm/layer/openlayers/tileDebugOpenlayers.js +39 -0
- package/src/vcs/vcm/layer/openlayers/tmsOpenlayers.js +62 -0
- package/src/vcs/vcm/layer/openlayers/vectorOpenlayers.js +118 -0
- package/src/vcs/vcm/layer/openlayers/vectorTileOpenlayers.js +177 -0
- package/src/vcs/vcm/layer/openlayers/wmsOpenlayers.js +55 -0
- package/src/vcs/vcm/layer/openlayers/wmtsOpenlayers.js +141 -0
- package/src/vcs/vcm/layer/pointCloud.js +162 -0
- package/src/vcs/vcm/layer/rasterLayer.js +294 -0
- package/src/vcs/vcm/layer/singleImage.js +119 -0
- package/src/vcs/vcm/layer/terrain.js +122 -0
- package/src/vcs/vcm/layer/terrainHelpers.js +123 -0
- package/src/vcs/vcm/layer/tileLoadedHelper.js +72 -0
- package/src/vcs/vcm/layer/tileProvider/mvtTileProvider.js +104 -0
- package/src/vcs/vcm/layer/tileProvider/staticGeojsonTileProvider.js +67 -0
- package/src/vcs/vcm/layer/tileProvider/tileProvider.js +584 -0
- package/src/vcs/vcm/layer/tileProvider/tileProviderFactory.js +28 -0
- package/src/vcs/vcm/layer/tileProvider/urlTemplateTileProvider.js +106 -0
- package/src/vcs/vcm/layer/tms.js +121 -0
- package/src/vcs/vcm/layer/vector.js +632 -0
- package/src/vcs/vcm/layer/vectorHelpers.js +206 -0
- package/src/vcs/vcm/layer/vectorProperties.js +1391 -0
- package/src/vcs/vcm/layer/vectorSymbols.js +40 -0
- package/src/vcs/vcm/layer/vectorTile.js +480 -0
- package/src/vcs/vcm/layer/wfs.js +165 -0
- package/src/vcs/vcm/layer/wms.js +270 -0
- package/src/vcs/vcm/layer/wmsHelpers.js +65 -0
- package/src/vcs/vcm/layer/wmts.js +235 -0
- package/src/vcs/vcm/maps/baseOLMap.js +257 -0
- package/src/vcs/vcm/maps/cameraLimiter.js +219 -0
- package/src/vcs/vcm/maps/cesium.js +1192 -0
- package/src/vcs/vcm/maps/map.js +511 -0
- package/src/vcs/vcm/maps/mapState.js +17 -0
- package/src/vcs/vcm/maps/oblique.js +536 -0
- package/src/vcs/vcm/maps/openlayers.js +205 -0
- package/src/vcs/vcm/object.js +92 -0
- package/src/vcs/vcm/oblique/ObliqueCollection.js +572 -0
- package/src/vcs/vcm/oblique/ObliqueDataSet.js +357 -0
- package/src/vcs/vcm/oblique/ObliqueImage.js +247 -0
- package/src/vcs/vcm/oblique/ObliqueImageMeta.js +126 -0
- package/src/vcs/vcm/oblique/ObliqueProvider.js +433 -0
- package/src/vcs/vcm/oblique/ObliqueView.js +130 -0
- package/src/vcs/vcm/oblique/ObliqueViewDirection.js +40 -0
- package/src/vcs/vcm/oblique/helpers.js +483 -0
- package/src/vcs/vcm/oblique/parseImageJson.js +248 -0
- package/src/vcs/vcm/util/clipping/clippingObject.js +386 -0
- package/src/vcs/vcm/util/clipping/clippingObjectManager.js +312 -0
- package/src/vcs/vcm/util/clipping/clippingPlaneHelper.js +413 -0
- package/src/vcs/vcm/util/collection.js +193 -0
- package/src/vcs/vcm/util/dateTime.js +60 -0
- package/src/vcs/vcm/util/exclusiveManager.js +135 -0
- package/src/vcs/vcm/util/extent.js +124 -0
- package/src/vcs/vcm/util/featureProvider/abstractFeatureProvider.js +196 -0
- package/src/vcs/vcm/util/featureProvider/featureProviderHelpers.js +51 -0
- package/src/vcs/vcm/util/featureProvider/featureProviderSymbols.js +11 -0
- package/src/vcs/vcm/util/featureProvider/tileProviderFeatureProvider.js +62 -0
- package/src/vcs/vcm/util/featureProvider/wmsFeatureProvider.js +280 -0
- package/src/vcs/vcm/util/featureconverter/circleToCesium.js +215 -0
- package/src/vcs/vcm/util/featureconverter/convert.js +83 -0
- package/src/vcs/vcm/util/featureconverter/extent3d.js +154 -0
- package/src/vcs/vcm/util/featureconverter/featureconverterHelper.js +591 -0
- package/src/vcs/vcm/util/featureconverter/lineStringToCesium.js +171 -0
- package/src/vcs/vcm/util/featureconverter/pointToCesium.js +359 -0
- package/src/vcs/vcm/util/featureconverter/polygonToCesium.js +229 -0
- package/src/vcs/vcm/util/geometryHelpers.js +172 -0
- package/src/vcs/vcm/util/indexedCollection.js +158 -0
- package/src/vcs/vcm/util/isMobile.js +12 -0
- package/src/vcs/vcm/util/layerCollection.js +216 -0
- package/src/vcs/vcm/util/locale.js +53 -0
- package/src/vcs/vcm/util/mapCollection.js +363 -0
- package/src/vcs/vcm/util/math.js +71 -0
- package/src/vcs/vcm/util/projection.js +348 -0
- package/src/vcs/vcm/util/splitScreen.js +233 -0
- package/src/vcs/vcm/util/style/declarativeStyleItem.js +631 -0
- package/src/vcs/vcm/util/style/shapesCategory.js +67 -0
- package/src/vcs/vcm/util/style/styleFactory.js +48 -0
- package/src/vcs/vcm/util/style/styleHelpers.js +555 -0
- package/src/vcs/vcm/util/style/styleItem.js +226 -0
- package/src/vcs/vcm/util/style/vectorStyleItem.js +927 -0
- package/src/vcs/vcm/util/style/writeStyle.js +48 -0
- package/src/vcs/vcm/util/urlHelpers.js +16 -0
- 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;
|