@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,348 @@
|
|
|
1
|
+
import { getTransform, get as getProjection, equivalent } from 'ol/proj.js';
|
|
2
|
+
import { register } from 'ol/proj/proj4.js';
|
|
3
|
+
import proj4 from 'proj4';
|
|
4
|
+
import { getLogger as getLoggerByName } from '@vcsuite/logger';
|
|
5
|
+
import { check } from '@vcsuite/check';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @typedef {Object} ProjectionOptions
|
|
9
|
+
* @property {string|number} [epsg] - EPSG of the projection, for example: "EPSG:4326" if not specified, uses the framework projection
|
|
10
|
+
* @property {string|undefined|null} [proj4] - definition of the projection. See for example: {@link http://spatialreference.org/ref/epsg/4326/proj4/} proj4
|
|
11
|
+
* @property {Array<string>|undefined|null} [alias] - aliases to define
|
|
12
|
+
* @api stable
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export const wgs84ToMercatorTransformer = getTransform('EPSG:4326', 'EPSG:3857');
|
|
16
|
+
export const mercatorToWgs84Transformer = getTransform('EPSG:3857', 'EPSG:4326');
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @returns {import("@vcsuite/logger").Logger}
|
|
21
|
+
*/
|
|
22
|
+
function getLogger() {
|
|
23
|
+
return getLoggerByName('vcs.vcm.util.Projection');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @type {ProjectionOptions}
|
|
28
|
+
*/
|
|
29
|
+
let defaultProjectionOption = {
|
|
30
|
+
epsg: 'EPSG:4326',
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @param {string|number} value
|
|
35
|
+
* @param {string=} [prefix="EPSG:"]
|
|
36
|
+
* @returns {string}
|
|
37
|
+
*/
|
|
38
|
+
function parseEPSGCode(value, prefix = 'EPSG:') {
|
|
39
|
+
const matches = `${value}`.match(/^(?:epsg:)?(\d+)/i);
|
|
40
|
+
if (matches && matches[1]) {
|
|
41
|
+
return `${prefix}${matches[1]}`;
|
|
42
|
+
}
|
|
43
|
+
return '';
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @param {ProjectionOptions} options
|
|
48
|
+
* @returns {boolean}
|
|
49
|
+
*/
|
|
50
|
+
function validateProjectionOptions(options) {
|
|
51
|
+
let proj = null;
|
|
52
|
+
if (options.epsg) {
|
|
53
|
+
try {
|
|
54
|
+
// @ts-ignore
|
|
55
|
+
proj = proj4(parseEPSGCode(options.epsg));
|
|
56
|
+
} catch (error) {
|
|
57
|
+
proj = null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (options.proj4) {
|
|
61
|
+
try {
|
|
62
|
+
// @ts-ignore
|
|
63
|
+
proj = proj4(options.proj4);
|
|
64
|
+
} catch (error) {
|
|
65
|
+
proj = null;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return proj != null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @param {ProjectionOptions} options
|
|
73
|
+
* @returns {ProjectionOptions} valid options
|
|
74
|
+
*/
|
|
75
|
+
function registerProjection(options) {
|
|
76
|
+
const saneOptions = {};
|
|
77
|
+
if (options.epsg) {
|
|
78
|
+
saneOptions.epsg = parseEPSGCode(options.epsg);
|
|
79
|
+
if (saneOptions.epsg) {
|
|
80
|
+
if (options.proj4) {
|
|
81
|
+
saneOptions.proj4 = options.proj4;
|
|
82
|
+
proj4.defs(saneOptions.epsg, options.proj4);
|
|
83
|
+
register(proj4);
|
|
84
|
+
}
|
|
85
|
+
if (options.alias && Array.isArray(options.alias)) {
|
|
86
|
+
saneOptions.alias = options.alias;
|
|
87
|
+
saneOptions.alias.forEach((alias) => {
|
|
88
|
+
proj4.defs(alias, proj4.defs(saneOptions.epsg));
|
|
89
|
+
register(proj4);
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return saneOptions;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Set the default projections epsg and proj4. Does not update
|
|
99
|
+
* projection created prior to this functions call.
|
|
100
|
+
* @param {ProjectionOptions} options
|
|
101
|
+
* @api
|
|
102
|
+
* @export
|
|
103
|
+
*/
|
|
104
|
+
export function setDefaultProjectionOptions(options) {
|
|
105
|
+
check(options, { epsg: [String, Number], proj4: [String, undefined, null] });
|
|
106
|
+
if (!validateProjectionOptions(options)) {
|
|
107
|
+
throw new Error('Cannot set invalid projection options as default options');
|
|
108
|
+
}
|
|
109
|
+
defaultProjectionOption = registerProjection(options);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Projection Class, if no valid options are given, the Projection will initialize with the Framework default Projection
|
|
114
|
+
* @class
|
|
115
|
+
* @export
|
|
116
|
+
* For example:
|
|
117
|
+
* <pre><code>
|
|
118
|
+
* {
|
|
119
|
+
* "epsg" : "EPSG:25833"
|
|
120
|
+
* "proj4" : "+proj=utm +zone=33 +ellps=GRS80 +units=m +no_defs"
|
|
121
|
+
* }
|
|
122
|
+
* </code></pre>
|
|
123
|
+
* @api stable
|
|
124
|
+
*/
|
|
125
|
+
class Projection {
|
|
126
|
+
/**
|
|
127
|
+
* @param {ProjectionOptions} options
|
|
128
|
+
*/
|
|
129
|
+
constructor(options = { epsg: '' }) {
|
|
130
|
+
const saneOptions = registerProjection(options);
|
|
131
|
+
/**
|
|
132
|
+
* @type {string|null}
|
|
133
|
+
* @private
|
|
134
|
+
*/
|
|
135
|
+
this._proj4 = saneOptions.proj4;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* @type {string}
|
|
139
|
+
* @private
|
|
140
|
+
*/
|
|
141
|
+
this._epsg = /** @type {string} */ (saneOptions.epsg);
|
|
142
|
+
|
|
143
|
+
if (!this.proj) {
|
|
144
|
+
this._epsg = Projection.parseEPSGCode(defaultProjectionOption.epsg);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* epsg code in the format "EPSG:25832"
|
|
150
|
+
* @type {string}
|
|
151
|
+
* @api
|
|
152
|
+
* @readonly
|
|
153
|
+
*/
|
|
154
|
+
get epsg() {
|
|
155
|
+
return this._epsg;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* proj4js string example for epsg:25832: +proj=utm +zone=33 +ellps=GRS80 +units=m +no_defs
|
|
160
|
+
* @type {string|null}
|
|
161
|
+
* @api
|
|
162
|
+
* @readonly
|
|
163
|
+
*/
|
|
164
|
+
get proj4() {
|
|
165
|
+
return this._proj4;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* @type {import("ol/proj/Projection").default}
|
|
170
|
+
* @api
|
|
171
|
+
* @readonly
|
|
172
|
+
*/
|
|
173
|
+
get proj() {
|
|
174
|
+
return getProjection(this.epsg);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* @returns {import("ol/proj/Projection").default}
|
|
179
|
+
* @api
|
|
180
|
+
* @deprecated 3.7
|
|
181
|
+
*/
|
|
182
|
+
getProjection() {
|
|
183
|
+
getLogger().deprecate('getProjection', 'Access the property proj directly');
|
|
184
|
+
return this.proj;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* @param {Projection} projection
|
|
189
|
+
* @returns {boolean}
|
|
190
|
+
*/
|
|
191
|
+
equals(projection) {
|
|
192
|
+
return equivalent(this.proj, projection.proj);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* @static
|
|
197
|
+
* @param {Projection} dest
|
|
198
|
+
* @param {Projection} source
|
|
199
|
+
* @param {import("ol/coordinate").Coordinate} coords
|
|
200
|
+
* @returns {import("ol/coordinate").Coordinate}
|
|
201
|
+
* @api stable
|
|
202
|
+
*/
|
|
203
|
+
static transform(dest, source, coords) {
|
|
204
|
+
const transformer = getTransform(source.proj, dest.proj);
|
|
205
|
+
const newCoords = new Array(2);
|
|
206
|
+
transformer([coords[0], coords[1]], newCoords, 2);
|
|
207
|
+
if (coords.length > 2) {
|
|
208
|
+
newCoords.push(coords[2]);
|
|
209
|
+
}
|
|
210
|
+
return newCoords;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* @param {Projection} dest
|
|
215
|
+
* @param {import("ol/coordinate").Coordinate} coords
|
|
216
|
+
* @returns {import("ol/coordinate").Coordinate}
|
|
217
|
+
* @api stable
|
|
218
|
+
*/
|
|
219
|
+
transformTo(dest, coords) {
|
|
220
|
+
return Projection.transform(dest, this, coords);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* @static
|
|
225
|
+
* @param {Projection} dest
|
|
226
|
+
* @param {Projection} source
|
|
227
|
+
* @param {Array.<import("ol/coordinate").Coordinate>} coords
|
|
228
|
+
* @returns {Array.<import("ol/coordinate").Coordinate>}
|
|
229
|
+
* @api stable
|
|
230
|
+
*/
|
|
231
|
+
static transformCoordinates(dest, source, coords) {
|
|
232
|
+
const newCoords = [];
|
|
233
|
+
for (let i = 0; i < coords.length; i++) {
|
|
234
|
+
newCoords.push(Projection.transform(dest, source, coords[i]));
|
|
235
|
+
}
|
|
236
|
+
return newCoords;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* returns a function to transform coordinates from source to dest
|
|
241
|
+
* @static
|
|
242
|
+
* @param {Projection} dest
|
|
243
|
+
* @param {Projection} source
|
|
244
|
+
* @returns {import("ol/proj").TransformFunction}
|
|
245
|
+
*/
|
|
246
|
+
static getTransformer(dest, source) {
|
|
247
|
+
return getTransform(source.proj, dest.proj);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* @param {Projection} source
|
|
252
|
+
* @param {import("ol/coordinate").Coordinate} coords
|
|
253
|
+
* @returns {import("ol/coordinate").Coordinate}
|
|
254
|
+
* @api stable
|
|
255
|
+
*/
|
|
256
|
+
transformFrom(source, coords) {
|
|
257
|
+
return Projection.transform(this, source, coords);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Returns the object literal representation of this object
|
|
262
|
+
* @returns {ProjectionOptions}
|
|
263
|
+
* @api stable
|
|
264
|
+
*/
|
|
265
|
+
getConfigObject() {
|
|
266
|
+
const configObject = {
|
|
267
|
+
epsg: this.epsg,
|
|
268
|
+
};
|
|
269
|
+
if (this.proj4) {
|
|
270
|
+
configObject.proj4 = this.proj4;
|
|
271
|
+
}
|
|
272
|
+
return configObject;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Fast transform from Web-Mercator to WGS84
|
|
277
|
+
* @param {import("ol/coordinate").Coordinate} coords
|
|
278
|
+
* @param {boolean=} inPlace - whether to transform in place
|
|
279
|
+
* @returns {import("ol/coordinate").Coordinate}
|
|
280
|
+
* @api
|
|
281
|
+
*/
|
|
282
|
+
static mercatorToWgs84(coords, inPlace) {
|
|
283
|
+
return mercatorToWgs84Transformer(coords, inPlace ? coords : undefined, coords.length);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Fast transform from WGS84 to Web-Mercator
|
|
288
|
+
* @param {import("ol/coordinate").Coordinate} coords
|
|
289
|
+
* @param {boolean=} inPlace - whether to transform in place
|
|
290
|
+
* @returns {import("ol/coordinate").Coordinate}
|
|
291
|
+
* @api
|
|
292
|
+
*/
|
|
293
|
+
static wgs84ToMercator(coords, inPlace) {
|
|
294
|
+
return wgs84ToMercatorTransformer(coords, inPlace ? coords : undefined, coords.length);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* validates projection options, combination of epsg code and proj4
|
|
299
|
+
* @param {ProjectionOptions} options
|
|
300
|
+
* @returns {boolean}
|
|
301
|
+
* @api
|
|
302
|
+
*/
|
|
303
|
+
static validateOptions(options) {
|
|
304
|
+
return validateProjectionOptions(options);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* parses an epsg code returns empty string if no code has been found
|
|
309
|
+
* for example:
|
|
310
|
+
* parseEPSGCode('epsg:4326') ==> '4326'
|
|
311
|
+
* parseEPSGCode('epsg:4326', 'EPSG:') ==> 'EPSG:4326'
|
|
312
|
+
* parseEPSGCode('asdasd', 'EPSG:') ==> ''
|
|
313
|
+
* @param {string|number|undefined} value
|
|
314
|
+
* @param {string|undefined} prefix default EPSG:
|
|
315
|
+
* @returns {string}
|
|
316
|
+
* @api
|
|
317
|
+
*/
|
|
318
|
+
static parseEPSGCode(value, prefix = 'EPSG:') {
|
|
319
|
+
return parseEPSGCode(value, prefix);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
export default Projection;
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Returns the default Projection.
|
|
327
|
+
* @api stable
|
|
328
|
+
* @returns {Projection}
|
|
329
|
+
* @export
|
|
330
|
+
*/
|
|
331
|
+
export function getDefaultProjection() {
|
|
332
|
+
return new Projection(defaultProjectionOption);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* wgs84 Projection EPSG Code: 4326
|
|
337
|
+
* @api stable
|
|
338
|
+
* @type {Projection}
|
|
339
|
+
* @export
|
|
340
|
+
*/
|
|
341
|
+
export const wgs84Projection = new Projection({ epsg: 4326 });
|
|
342
|
+
/**
|
|
343
|
+
* mercator Projection EPSG Code: 3857
|
|
344
|
+
* @api stable
|
|
345
|
+
* @type {Projection}
|
|
346
|
+
* @export
|
|
347
|
+
*/
|
|
348
|
+
export const mercatorProjection = new Projection({ epsg: 3857 });
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Cartesian3,
|
|
3
|
+
Matrix4,
|
|
4
|
+
Plane,
|
|
5
|
+
ClippingPlane,
|
|
6
|
+
ClippingPlaneCollection,
|
|
7
|
+
ImagerySplitDirection,
|
|
8
|
+
} from '@vcmap/cesium';
|
|
9
|
+
|
|
10
|
+
import { check } from '@vcsuite/check';
|
|
11
|
+
import CesiumMap from '../maps/cesium.js';
|
|
12
|
+
import ClippingObject from './clipping/clippingObject.js';
|
|
13
|
+
import Openlayers from '../maps/openlayers.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @class
|
|
17
|
+
* @api
|
|
18
|
+
*/
|
|
19
|
+
class SplitScreen {
|
|
20
|
+
/**
|
|
21
|
+
* @param {import("@vcmap/core").ClippingObjectManager} clippingObjectManager
|
|
22
|
+
*/
|
|
23
|
+
constructor(clippingObjectManager) {
|
|
24
|
+
/**
|
|
25
|
+
* @type {number}
|
|
26
|
+
* @private
|
|
27
|
+
*/
|
|
28
|
+
this._position = 0.5;
|
|
29
|
+
/**
|
|
30
|
+
* @type {import("@vcmap/cesium").Scene|null}
|
|
31
|
+
*/
|
|
32
|
+
this.scene = null;
|
|
33
|
+
/**
|
|
34
|
+
* @type {import("ol/Map").default|null}
|
|
35
|
+
*/
|
|
36
|
+
this.olMap = null;
|
|
37
|
+
/**
|
|
38
|
+
* @type {boolean}
|
|
39
|
+
* @api
|
|
40
|
+
*/
|
|
41
|
+
this.initialized = false;
|
|
42
|
+
/**
|
|
43
|
+
* @type {ClippingObject}
|
|
44
|
+
*/
|
|
45
|
+
this.leftScreenClippingObject = new ClippingObject();
|
|
46
|
+
/**
|
|
47
|
+
* @type {ClippingObject}
|
|
48
|
+
*/
|
|
49
|
+
this.rightScreenClippingObject = new ClippingObject();
|
|
50
|
+
/**
|
|
51
|
+
* @type {Function|null}
|
|
52
|
+
* @private
|
|
53
|
+
*/
|
|
54
|
+
this._cameraListener = null;
|
|
55
|
+
/**
|
|
56
|
+
* @type {number|null}
|
|
57
|
+
*/
|
|
58
|
+
this.originalCameraPercentageChanged = null;
|
|
59
|
+
/**
|
|
60
|
+
* @type {Array<Function>}
|
|
61
|
+
* @private
|
|
62
|
+
*/
|
|
63
|
+
this._targetsChangedListeners = [];
|
|
64
|
+
|
|
65
|
+
this._targetsChangedListeners = [
|
|
66
|
+
this.rightScreenClippingObject.targetsUpdated.addEventListener(() => { this._targetsChanged(); }),
|
|
67
|
+
this.leftScreenClippingObject.targetsUpdated.addEventListener(() => { this._targetsChanged(); }),
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @type {import("@vcmap/core").ClippingObjectManager}
|
|
72
|
+
* @private
|
|
73
|
+
*/
|
|
74
|
+
this._clippingObjectManager = clippingObjectManager;
|
|
75
|
+
this._clippingObjectManager.addClippingObject(this.rightScreenClippingObject);
|
|
76
|
+
this._clippingObjectManager.addClippingObject(this.leftScreenClippingObject);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @type {number}
|
|
81
|
+
* @api
|
|
82
|
+
*/
|
|
83
|
+
get position() { return this._position; }
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @param {number} position
|
|
87
|
+
*/
|
|
88
|
+
set position(position) {
|
|
89
|
+
check(position, Number);
|
|
90
|
+
if (position < 0 || position > 1) {
|
|
91
|
+
throw new Error('Position must be between 0 and 1');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (Math.abs(this._position - position) > 0.0001) {
|
|
95
|
+
this._updatePosition(position);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
_targetsChanged() {
|
|
100
|
+
if (this.scene) {
|
|
101
|
+
const numTargets = this.rightScreenClippingObject.targets.size + this.leftScreenClippingObject.targets.size;
|
|
102
|
+
const { camera } = this.scene;
|
|
103
|
+
|
|
104
|
+
if (this._cameraListener && numTargets === 0) {
|
|
105
|
+
this._cameraListener();
|
|
106
|
+
this._cameraListener = null;
|
|
107
|
+
camera.percentageChanged = this.originalCameraPercentageChanged;
|
|
108
|
+
} else if (!this._cameraListener && numTargets > 0) {
|
|
109
|
+
this.originalCameraPercentageChanged = camera.percentageChanged;
|
|
110
|
+
camera.percentageChanged = 0;
|
|
111
|
+
this._cameraListener = camera.changed.addEventListener(this._updateClippingPlanes.bind(this));
|
|
112
|
+
this._updateClippingPlanes();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* @param {number} position
|
|
119
|
+
* @private
|
|
120
|
+
*/
|
|
121
|
+
_updatePosition(position) {
|
|
122
|
+
this._position = position;
|
|
123
|
+
if (this.scene) {
|
|
124
|
+
this.scene.imagerySplitPosition = position;
|
|
125
|
+
this._updateClippingPlanes();
|
|
126
|
+
} else if (this.olMap) {
|
|
127
|
+
this.olMap.render();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* @param {import("@vcmap/core").VcsMap} map
|
|
133
|
+
*/
|
|
134
|
+
mapActivated(map) {
|
|
135
|
+
if (map instanceof CesiumMap) {
|
|
136
|
+
this.scene = map.getScene();
|
|
137
|
+
this.olMap = null;
|
|
138
|
+
this._targetsChanged();
|
|
139
|
+
} else if (map instanceof Openlayers) {
|
|
140
|
+
this.scene = null;
|
|
141
|
+
this.olMap = map.olMap;
|
|
142
|
+
}
|
|
143
|
+
this._updatePosition(this.position);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* calculate a clipping plane from the current swipe position for the given Cesium3DTileset
|
|
148
|
+
* @returns {import("@vcmap/cesium").ClippingPlane}
|
|
149
|
+
* @private
|
|
150
|
+
*/
|
|
151
|
+
_calcClippingPlane() {
|
|
152
|
+
const { camera } = this.scene;
|
|
153
|
+
const { fov, near } = /** @type {import("@vcmap/cesium").PerspectiveFrustum} */ (camera.frustum);
|
|
154
|
+
const screenWidth = this.scene.canvas.width || 1;
|
|
155
|
+
const screenHeight = this.scene.canvas.height || 1;
|
|
156
|
+
let pixelSize;
|
|
157
|
+
if (screenHeight > screenWidth) {
|
|
158
|
+
pixelSize = (near * Math.tan(0.5 * fov) * 2.0) / screenHeight;
|
|
159
|
+
} else {
|
|
160
|
+
pixelSize = (near * Math.tan(0.5 * fov) * 2.0) / screenWidth;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// extract 3 points lying on swipe plane
|
|
164
|
+
const screenX = (screenWidth * this.position) - (screenWidth / 2);
|
|
165
|
+
const screenY = screenHeight / 2;
|
|
166
|
+
const p1 = new Cartesian3(pixelSize * screenX, pixelSize * screenY, -1 * near);
|
|
167
|
+
const p2 = new Cartesian3(pixelSize * screenX, -1 * pixelSize * screenY, -1 * near);
|
|
168
|
+
Matrix4.multiplyByPoint(camera.inverseViewMatrix, p1, p1);
|
|
169
|
+
Matrix4.multiplyByPoint(camera.inverseViewMatrix, p2, p2);
|
|
170
|
+
const p3WC = camera.positionWC;
|
|
171
|
+
|
|
172
|
+
Cartesian3.subtract(p3WC, p1, p1);
|
|
173
|
+
Cartesian3.subtract(p3WC, p2, p2);
|
|
174
|
+
const normal = Cartesian3.cross(p1, p2, new Cartesian3());
|
|
175
|
+
Cartesian3.normalize(normal, normal);
|
|
176
|
+
const planeInFixedFrame = Plane.fromPointNormal(p3WC, normal);
|
|
177
|
+
|
|
178
|
+
return ClippingPlane.fromPlane(planeInFixedFrame);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* update the clipping planes for all Cesium3DTilesets loaded in the vcMap
|
|
183
|
+
* @private
|
|
184
|
+
*/
|
|
185
|
+
_updateClippingPlanes() {
|
|
186
|
+
const plane = this._calcClippingPlane();
|
|
187
|
+
this.leftScreenClippingObject.clippingPlaneCollection = new ClippingPlaneCollection({ planes: [plane] });
|
|
188
|
+
const revClippingPlane = ClippingPlane.clone(plane);
|
|
189
|
+
revClippingPlane.normal = Cartesian3.negate(revClippingPlane.normal, revClippingPlane.normal);
|
|
190
|
+
revClippingPlane.distance *= -1;
|
|
191
|
+
this.rightScreenClippingObject.clippingPlaneCollection =
|
|
192
|
+
new ClippingPlaneCollection({ planes: [revClippingPlane] });
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Gets the clipping object for a split direction
|
|
197
|
+
* @param {import("@vcmap/cesium").ImagerySplitDirection} splitDirection
|
|
198
|
+
* @returns {ClippingObject|null}
|
|
199
|
+
* @api
|
|
200
|
+
*/
|
|
201
|
+
getClippingObjectForDirection(splitDirection) {
|
|
202
|
+
check(splitDirection, [
|
|
203
|
+
ImagerySplitDirection.LEFT,
|
|
204
|
+
ImagerySplitDirection.RIGHT,
|
|
205
|
+
ImagerySplitDirection.NONE,
|
|
206
|
+
]);
|
|
207
|
+
|
|
208
|
+
if (splitDirection === ImagerySplitDirection.LEFT) {
|
|
209
|
+
return this.leftScreenClippingObject;
|
|
210
|
+
}
|
|
211
|
+
if (splitDirection === ImagerySplitDirection.RIGHT) {
|
|
212
|
+
return this.rightScreenClippingObject;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
destroy() {
|
|
219
|
+
if (this._clippingObjectManager) {
|
|
220
|
+
this._clippingObjectManager.removeClippingObject(this.rightScreenClippingObject);
|
|
221
|
+
this._clippingObjectManager.removeClippingObject(this.leftScreenClippingObject);
|
|
222
|
+
}
|
|
223
|
+
this._targetsChangedListeners.forEach((cb) => { cb(); });
|
|
224
|
+
this._targetsChangedListeners = [];
|
|
225
|
+
this._clippingObjectManager = null;
|
|
226
|
+
if (this._cameraListener) {
|
|
227
|
+
this._cameraListener();
|
|
228
|
+
this._cameraListener = null;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export default SplitScreen;
|