@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,48 @@
1
+ import VectorStyleItem from './vectorStyleItem.js';
2
+ import DeclarativeStyleItem from './declarativeStyleItem.js';
3
+ import { referenceableStyleSymbol } from './styleItem.js';
4
+
5
+ /**
6
+ * @param {VectorStyleItemOptions} obj
7
+ * @param {Array<string>=} embeddedIcons
8
+ * @returns {VectorStyleItemOptions}
9
+ */
10
+ export function embedIconsInStyle(obj, embeddedIcons) {
11
+ if (
12
+ obj.image &&
13
+ obj.image.src &&
14
+ /^data:/.test(obj.image.src)
15
+ ) {
16
+ if (embeddedIcons) {
17
+ let index = embeddedIcons.indexOf(obj.image.src);
18
+ if (index === -1) {
19
+ embeddedIcons.push(obj.image.src);
20
+ index = embeddedIcons.length - 1;
21
+ }
22
+ obj.image.src = `:${index}`;
23
+ } else {
24
+ obj.image = { // XXX is this the correct fallback?
25
+ radius: 5,
26
+ };
27
+ }
28
+ }
29
+ return obj;
30
+ }
31
+
32
+ /**
33
+ * @param {import("@vcmap/core").StyleItem} style
34
+ * @param {VcsMeta=} vcsMeta
35
+ * @returns {VcsMeta}
36
+ */
37
+ function writeStyle(style, vcsMeta = {}) {
38
+ if (style[referenceableStyleSymbol]) { // XXX this should be configurable. In some cases, writting out the actual style would be desirable
39
+ vcsMeta.style = style.getReference();
40
+ } else if (style instanceof VectorStyleItem) {
41
+ vcsMeta.style = embedIconsInStyle(style.getOptions(), vcsMeta.embeddedIcons);
42
+ } else if (style instanceof DeclarativeStyleItem) {
43
+ vcsMeta.style = style.getOptions();
44
+ }
45
+ return vcsMeta;
46
+ }
47
+
48
+ export default writeStyle;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @param {string} source
3
+ * @returns {boolean}
4
+ */
5
+ // eslint-disable-next-line import/prefer-default-export
6
+ export function isSameOrigin(source) {
7
+ const { location } = window;
8
+ const url = new URL(source, `${location.protocol}//${location.host}${location.pathname}`);
9
+ // for instance data: URIs have no host information and are implicitly same origin
10
+ // see https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy#inherited_origins
11
+ if (!url.host) {
12
+ return true;
13
+ }
14
+ return url.protocol === location.protocol &&
15
+ url.host === location.host;
16
+ }
@@ -0,0 +1,333 @@
1
+ import { EasingFunction } from '@vcmap/cesium';
2
+ import { parseBoolean, parseNumber } from '@vcsuite/parsers';
3
+ import Projection, { wgs84Projection } from './projection.js';
4
+ import VcsObject from '../object.js';
5
+ import Extent from './extent.js';
6
+
7
+ /**
8
+ * compares two numeric properties
9
+ * @param {number} left
10
+ * @param {number} right
11
+ * @param {number} epsilon
12
+ * @returns {boolean}
13
+ * @export
14
+ */
15
+ export function propertyEqualsEpsilon(left, right, epsilon) {
16
+ return Math.abs(left - right) <= epsilon;
17
+ }
18
+
19
+ /**
20
+ * compares two angles in 360 degree range
21
+ * @param {number} left angle in degree
22
+ * @param {number} right angle in degree
23
+ * @param {number} epsilon in degree
24
+ * @returns {boolean}
25
+ * @export
26
+ */
27
+ export function angleEqualsEpsilon(left, right, epsilon) {
28
+ const diff = (left - right) - Math.trunc((left - right) / 360) * 360;
29
+ return Math.abs(diff) <= epsilon;
30
+ }
31
+
32
+
33
+ /**
34
+ * compares two coordinates componentwise
35
+ * @param {import("ol/coordinate").Coordinate} left
36
+ * @param {import("ol/coordinate").Coordinate} right
37
+ * @param {number} epsilon
38
+ * @returns {boolean}
39
+ * @export
40
+ */
41
+ export function coordinateEqualsEpsilon(left, right, epsilon) {
42
+ return left !== null && right !== null &&
43
+ left.every((val, idx) => propertyEqualsEpsilon(val, right[idx], epsilon));
44
+ }
45
+
46
+ /**
47
+ * @typedef {VcsObjectOptions} ViewPointOptions
48
+ * @property {import("ol/coordinate").Coordinate|undefined} cameraPosition - ol3 coordinate array with xyz coordinates (z value is mandatory)
49
+ * @property {import("ol/coordinate").Coordinate|undefined} groundPosition - ol3 coordinate array with xyz coordinates (z value is optional)
50
+ * @property {number|undefined} distance - distance between the camera position and the target
51
+ * @property {number} [heading=0] - angle between 0 and 360 degree
52
+ * @property {number} [pitch=-90] - angle between 0 and 360 degree
53
+ * @property {number} [roll=0] - angle between 0 and 360 degree
54
+ * @property {boolean} [animate=false] - if possible the switching to the new viewpoint will be animated
55
+ * @property {number|undefined} duration - animation duration override
56
+ * @property {string|undefined} easingFunctionName - a Cesium.EasingFunction name to use for the flight
57
+ * @api
58
+ */
59
+
60
+ /**
61
+ * A Viewpoint Object
62
+ * @class
63
+ * @export
64
+ * @extends {VcsObject}
65
+ * @api stable
66
+ */
67
+ class ViewPoint extends VcsObject {
68
+ static get className() { return 'vcs.vcm.util.ViewPoint'; }
69
+
70
+ /**
71
+ * @param {ViewPointOptions} options
72
+ */
73
+ constructor(options) {
74
+ super(options);
75
+
76
+ /**
77
+ * position of the camera (optional) (cameraPosition needs x, y, and height value)
78
+ * either a cameraPosition or a groundPosition have to be provided
79
+ * @type {?import("ol/coordinate").Coordinate}
80
+ * @api
81
+ */
82
+ this.cameraPosition = null;
83
+ if (Array.isArray(options.cameraPosition) && options.cameraPosition.length === 3) {
84
+ this.cameraPosition = options.cameraPosition.map(c => Number(c));
85
+ }
86
+
87
+ /**
88
+ * groundPosition, point on the ground the camera looks at (optional)
89
+ * either a cameraPosition or a groundPosition have to be provided
90
+ * @type {?import("ol/coordinate").Coordinate}
91
+ * @api
92
+ */
93
+ this.groundPosition = null;
94
+ if (Array.isArray(options.groundPosition)) {
95
+ this.groundPosition = options.groundPosition.map(c => Number(c));
96
+ }
97
+
98
+ /**
99
+ * distance between target and camera position, only needed if a groundPosition is given
100
+ * is used to move the cameraPosition backwards to get some distance from the ground
101
+ * @type {?number}
102
+ * @api
103
+ */
104
+ this.distance = parseNumber(options.distance, this.cameraPosition ? this.cameraPosition[2] : 1000);
105
+
106
+ /**
107
+ * heading, angle between 0 and 360 degree 0° = North, 90° = east ...
108
+ * @type {number}
109
+ * @api
110
+ */
111
+ this.heading = parseNumber(options.heading, 0);
112
+
113
+ /**
114
+ * pitch in degrees ranges -90 to 90
115
+ * @type {number}
116
+ * @api
117
+ */
118
+ this.pitch = parseNumber(options.pitch, -90);
119
+
120
+ /**
121
+ * roll in degrees, ranges -90 to 90
122
+ * @type {number}
123
+ * @api
124
+ */
125
+ this.roll = parseNumber(options.roll, 0);
126
+
127
+ /**
128
+ * animate this viewpoint when setting it on a map
129
+ * @type {boolean}
130
+ * @api
131
+ */
132
+ this.animate = parseBoolean(options.animate, false);
133
+ /**
134
+ * An optional duration in seconds to override durations when animating this viewpoint
135
+ * @type {number|null}
136
+ * @api
137
+ */
138
+ this.duration = options.duration || null;
139
+ /**
140
+ * The name of the easing function to use
141
+ * @type {string|null}
142
+ * @api
143
+ */
144
+ this.easingFunctionName = options.easingFunctionName || null;
145
+ }
146
+
147
+ /**
148
+ * The current easing function
149
+ * @type {import("@vcmap/cesium").EasingFunction.Callback|null}
150
+ * @api
151
+ * @readonly
152
+ */
153
+ get easingFunction() {
154
+ return this.easingFunctionName ? EasingFunction[this.easingFunctionName] : null;
155
+ }
156
+
157
+ /**
158
+ * @returns {ViewPointOptions} returns a options object. This object can be used to reconstruct a new viewpoint
159
+ * @api stable
160
+ */
161
+ getConfigObject() {
162
+ return {
163
+ ...super.getConfigObject(),
164
+ distance: this.distance,
165
+ cameraPosition: this.cameraPosition ? this.cameraPosition.slice() : null,
166
+ groundPosition: this.groundPosition ? this.groundPosition.slice() : null,
167
+ heading: this.heading,
168
+ pitch: this.pitch,
169
+ roll: this.roll,
170
+ animate: this.animate,
171
+ duration: this.duration,
172
+ easingFunctionName: this.easingFunctionName,
173
+ };
174
+ }
175
+
176
+ /**
177
+ * clones the viewpoint
178
+ * @returns {ViewPoint} viewpoint
179
+ * @api stable
180
+ */
181
+ clone() {
182
+ return new ViewPoint(this.getConfigObject());
183
+ }
184
+
185
+ /**
186
+ * creates a String representation of this viewpoint
187
+ * @returns {string}
188
+ * @api stable
189
+ */
190
+ toString() {
191
+ const stringRep = `ViewPoint: [Ground:${String(this.groundPosition ? this.groundPosition : null)}]` +
192
+ `[Camera:${String(this.cameraPosition ? this.cameraPosition : null)}]` +
193
+ `[Distance:${this.distance}]` +
194
+ `[heading:${this.distance}]` +
195
+ `[pitch:${this.distance}]` +
196
+ `[roll:${this.distance}]`;
197
+ return stringRep;
198
+ }
199
+
200
+ /**
201
+ * Creates a viewpoint based on an extent
202
+ * @param {import("ol/extent").Extent|Extent} extent
203
+ * @returns {?ViewPoint}
204
+ * @api
205
+ */
206
+ static createViewPointFromExtent(extent) {
207
+ const extentCoordinates = extent instanceof Extent ?
208
+ extent.getCoordinatesInProjection(wgs84Projection) :
209
+ extent;
210
+
211
+ if (extentCoordinates && extentCoordinates.length === 4) {
212
+ const minx = extentCoordinates[0];
213
+ const miny = extentCoordinates[1];
214
+ const maxx = extentCoordinates[2];
215
+ const maxy = extentCoordinates[3];
216
+
217
+ const center = [(maxx - minx) / 2 + minx, (maxy - miny) / 2 + miny];
218
+ let distance = 0;
219
+ const delta = Math.max(maxx - minx, maxy - miny);
220
+ if (delta < 0.001) {
221
+ distance = 400;
222
+ } else {
223
+ distance = (delta) * 300000;
224
+ }
225
+
226
+ return new ViewPoint({
227
+ name: 'viewpointFromExtend',
228
+ distance,
229
+ groundPosition: center,
230
+ heading: 360,
231
+ pitch: -90,
232
+ roll: 0,
233
+ animate: true,
234
+ });
235
+ }
236
+ return null;
237
+ }
238
+
239
+ /**
240
+ * creates a new ViewPoint Object from url Paramter
241
+ * @param {Object} urlParameter
242
+ * @returns {ViewPoint}
243
+ */
244
+ static parseURLparameter(urlParameter) {
245
+ let { cameraPosition, groundPosition } = urlParameter;
246
+ if (cameraPosition != null) {
247
+ cameraPosition = cameraPosition.split(',').map(c => Number(c));
248
+ }
249
+
250
+ if (groundPosition != null) {
251
+ groundPosition = groundPosition.split(',').map(c => Number(c));
252
+ }
253
+
254
+ if (urlParameter.epsg != null) {
255
+ const { epsg, proj4: proj4String } = urlParameter;
256
+ const srcProjection = new Projection({ epsg, proj4: proj4String });
257
+ const destProjection = wgs84Projection;
258
+ if (groundPosition) {
259
+ groundPosition = Projection.transform(destProjection, srcProjection, groundPosition);
260
+ }
261
+ if (cameraPosition) {
262
+ cameraPosition = Projection.transform(destProjection, srcProjection, cameraPosition);
263
+ }
264
+ }
265
+
266
+ const options = {
267
+ cameraPosition,
268
+ groundPosition,
269
+ distance: Number(urlParameter.distance),
270
+ pitch: Number(urlParameter.pitch),
271
+ heading: Number(urlParameter.heading),
272
+ roll: Number(urlParameter.roll),
273
+ };
274
+
275
+ return new ViewPoint(options);
276
+ }
277
+
278
+ /**
279
+ * Checks if this Viewpoint is Valid
280
+ * @api stable
281
+ * @throws {InvalidArgument} on invalid viewpoint
282
+ * @returns {boolean}
283
+ */
284
+ isValid() {
285
+ const hasCamera = this.cameraPosition &&
286
+ Array.isArray(this.cameraPosition) &&
287
+ this.cameraPosition.length === 3 &&
288
+ this.cameraPosition.every(position => Number.isFinite(position));
289
+ const hasGround = this.groundPosition &&
290
+ Array.isArray(this.groundPosition) &&
291
+ this.groundPosition.length > 1 &&
292
+ this.groundPosition.length < 4 &&
293
+ this.groundPosition.every(position => Number.isFinite(position));
294
+ if (!hasGround && !hasCamera) {
295
+ return false;
296
+ }
297
+ if (!hasCamera && !Number.isFinite(this.distance)) {
298
+ return false;
299
+ }
300
+ if (!Number.isFinite(this.heading)) {
301
+ return false;
302
+ }
303
+ if (!Number.isFinite(this.pitch)) {
304
+ return false;
305
+ }
306
+ if (!Number.isFinite(this.roll)) {
307
+ return false;
308
+ }
309
+ return true;
310
+ }
311
+
312
+ /**
313
+ * compares the provided Viewpoint with this viewpoint componentwise
314
+ * @param {ViewPoint} other
315
+ * @param {number} [epsilon=0]
316
+ * @returns {boolean}
317
+ */
318
+ equals(other, epsilon = 0) {
319
+ return other === this || (
320
+ other !== null &&
321
+ propertyEqualsEpsilon(other.distance, this.distance, epsilon) &&
322
+ angleEqualsEpsilon(other.heading, this.heading, epsilon) &&
323
+ angleEqualsEpsilon(other.pitch, this.pitch, epsilon) &&
324
+ angleEqualsEpsilon(other.roll, this.roll, epsilon) &&
325
+ (
326
+ coordinateEqualsEpsilon(other.cameraPosition, this.cameraPosition, epsilon) ||
327
+ coordinateEqualsEpsilon(other.groundPosition, this.groundPosition, epsilon)
328
+ )
329
+ );
330
+ }
331
+ }
332
+
333
+ export default ViewPoint;