itowns 2.44.3-next.8 → 2.45.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 (219) hide show
  1. package/README.md +3 -129
  2. package/examples/3dtiles_loader.html +123 -48
  3. package/examples/config.json +3 -10
  4. package/examples/copc_simple_loader.html +15 -5
  5. package/examples/effects_stereo.html +2 -2
  6. package/examples/entwine_3d_loader.html +3 -1
  7. package/examples/entwine_simple_loader.html +1 -1
  8. package/examples/images/itowns_logo.svg +123 -0
  9. package/examples/js/plugins/COGParser.js +1 -1
  10. package/examples/jsm/OGC3DTilesHelper.js +6 -1
  11. package/examples/layers/JSONLayers/GeoidMNT.json +3 -1
  12. package/examples/misc_collada.html +2 -2
  13. package/examples/source_file_geojson_3d.html +0 -1
  14. package/examples/source_file_kml_raster_usgs.html +0 -1
  15. package/examples/source_stream_wfs_raster.html +0 -7
  16. package/examples/vector_tile_mapbox_raster.html +91 -0
  17. package/examples/view_3d_map_webxr.html +3 -1
  18. package/examples/view_multi_25d.html +2 -2
  19. package/package.json +21 -75
  20. package/CODING.md +0 -120
  21. package/CONTRIBUTING.md +0 -150
  22. package/CONTRIBUTORS.md +0 -55
  23. package/LICENSE.md +0 -44
  24. package/changelog.md +0 -1361
  25. package/dist/455.js +0 -2
  26. package/dist/455.js.map +0 -1
  27. package/dist/debug.js +0 -3
  28. package/dist/debug.js.LICENSE.txt +0 -13
  29. package/dist/debug.js.map +0 -1
  30. package/dist/itowns.js +0 -3
  31. package/dist/itowns.js.LICENSE.txt +0 -7
  32. package/dist/itowns.js.map +0 -1
  33. package/dist/itowns_lasparser.js +0 -2
  34. package/dist/itowns_lasparser.js.map +0 -1
  35. package/dist/itowns_lasworker.js +0 -2
  36. package/dist/itowns_lasworker.js.map +0 -1
  37. package/dist/itowns_potree2worker.js +0 -2
  38. package/dist/itowns_potree2worker.js.map +0 -1
  39. package/dist/itowns_widgets.js +0 -2
  40. package/dist/itowns_widgets.js.map +0 -1
  41. package/examples/.eslintrc.cjs +0 -35
  42. package/examples/3dtiles_25d.html +0 -120
  43. package/examples/3dtiles_basic.html +0 -94
  44. package/examples/3dtiles_batch_table.html +0 -86
  45. package/examples/3dtiles_ion.html +0 -126
  46. package/examples/3dtiles_pointcloud.html +0 -95
  47. package/examples/jsm/.eslintrc.cjs +0 -38
  48. package/lib/Controls/FirstPersonControls.js +0 -308
  49. package/lib/Controls/FlyControls.js +0 -175
  50. package/lib/Controls/GlobeControls.js +0 -1162
  51. package/lib/Controls/PlanarControls.js +0 -1025
  52. package/lib/Controls/StateControl.js +0 -429
  53. package/lib/Controls/StreetControls.js +0 -392
  54. package/lib/Converter/Feature2Mesh.js +0 -615
  55. package/lib/Converter/Feature2Texture.js +0 -170
  56. package/lib/Converter/convertToTile.js +0 -75
  57. package/lib/Converter/textureConverter.js +0 -44
  58. package/lib/Core/3DTiles/C3DTBatchTable.js +0 -131
  59. package/lib/Core/3DTiles/C3DTBatchTableHierarchyExtension.js +0 -96
  60. package/lib/Core/3DTiles/C3DTBoundingVolume.js +0 -157
  61. package/lib/Core/3DTiles/C3DTExtensions.js +0 -97
  62. package/lib/Core/3DTiles/C3DTFeature.js +0 -110
  63. package/lib/Core/3DTiles/C3DTilesEnums.js +0 -20
  64. package/lib/Core/3DTiles/C3DTileset.js +0 -99
  65. package/lib/Core/3DTiles/utils/BinaryPropertyAccessor.js +0 -100
  66. package/lib/Core/AnimationPlayer.js +0 -142
  67. package/lib/Core/CopcNode.js +0 -174
  68. package/lib/Core/Deprecated/Undeprecator.js +0 -75
  69. package/lib/Core/EntwinePointTileNode.js +0 -126
  70. package/lib/Core/Feature.js +0 -490
  71. package/lib/Core/Geographic/CoordStars.js +0 -80
  72. package/lib/Core/Geographic/Coordinates.js +0 -320
  73. package/lib/Core/Geographic/Crs.js +0 -175
  74. package/lib/Core/Geographic/Extent.js +0 -534
  75. package/lib/Core/Geographic/GeoidGrid.js +0 -109
  76. package/lib/Core/Label.js +0 -222
  77. package/lib/Core/MainLoop.js +0 -211
  78. package/lib/Core/Math/Ellipsoid.js +0 -144
  79. package/lib/Core/Picking.js +0 -255
  80. package/lib/Core/PointCloudNode.js +0 -42
  81. package/lib/Core/Potree2Node.js +0 -206
  82. package/lib/Core/Potree2PointAttributes.js +0 -139
  83. package/lib/Core/PotreeNode.js +0 -101
  84. package/lib/Core/Prefab/Globe/Atmosphere.js +0 -299
  85. package/lib/Core/Prefab/Globe/BuilderEllipsoidTile.js +0 -110
  86. package/lib/Core/Prefab/Globe/GlobeLayer.js +0 -145
  87. package/lib/Core/Prefab/Globe/SkyShader.js +0 -78
  88. package/lib/Core/Prefab/GlobeView.js +0 -161
  89. package/lib/Core/Prefab/Planar/PlanarLayer.js +0 -53
  90. package/lib/Core/Prefab/Planar/PlanarTileBuilder.js +0 -72
  91. package/lib/Core/Prefab/PlanarView.js +0 -62
  92. package/lib/Core/Prefab/TileBuilder.js +0 -80
  93. package/lib/Core/Prefab/computeBufferTileGeometry.js +0 -183
  94. package/lib/Core/Scheduler/Cache.js +0 -256
  95. package/lib/Core/Scheduler/CancelledCommandException.js +0 -15
  96. package/lib/Core/Scheduler/Scheduler.js +0 -294
  97. package/lib/Core/Style.js +0 -1121
  98. package/lib/Core/System/Capabilities.js +0 -63
  99. package/lib/Core/Tile/Tile.js +0 -219
  100. package/lib/Core/Tile/TileGrid.js +0 -46
  101. package/lib/Core/TileGeometry.js +0 -40
  102. package/lib/Core/TileMesh.js +0 -109
  103. package/lib/Core/View.js +0 -1109
  104. package/lib/Layer/C3DTilesLayer.js +0 -455
  105. package/lib/Layer/ColorLayer.js +0 -128
  106. package/lib/Layer/CopcLayer.js +0 -58
  107. package/lib/Layer/ElevationLayer.js +0 -107
  108. package/lib/Layer/EntwinePointTileLayer.js +0 -64
  109. package/lib/Layer/FeatureGeometryLayer.js +0 -63
  110. package/lib/Layer/GeoidLayer.js +0 -80
  111. package/lib/Layer/GeometryLayer.js +0 -202
  112. package/lib/Layer/InfoLayer.js +0 -64
  113. package/lib/Layer/LabelLayer.js +0 -456
  114. package/lib/Layer/Layer.js +0 -304
  115. package/lib/Layer/LayerUpdateState.js +0 -89
  116. package/lib/Layer/LayerUpdateStrategy.js +0 -80
  117. package/lib/Layer/OGC3DTilesLayer.js +0 -387
  118. package/lib/Layer/OrientedImageLayer.js +0 -222
  119. package/lib/Layer/PointCloudLayer.js +0 -359
  120. package/lib/Layer/Potree2Layer.js +0 -164
  121. package/lib/Layer/PotreeLayer.js +0 -65
  122. package/lib/Layer/RasterLayer.js +0 -27
  123. package/lib/Layer/ReferencingLayerProperties.js +0 -62
  124. package/lib/Layer/TiledGeometryLayer.js +0 -403
  125. package/lib/Loader/LASLoader.js +0 -193
  126. package/lib/Loader/Potree2BrotliLoader.js +0 -261
  127. package/lib/Loader/Potree2Loader.js +0 -207
  128. package/lib/Main.js +0 -115
  129. package/lib/MainBundle.js +0 -4
  130. package/lib/Parser/B3dmParser.js +0 -174
  131. package/lib/Parser/CameraCalibrationParser.js +0 -94
  132. package/lib/Parser/GDFParser.js +0 -72
  133. package/lib/Parser/GTXParser.js +0 -75
  134. package/lib/Parser/GeoJsonParser.js +0 -212
  135. package/lib/Parser/GpxParser.js +0 -25
  136. package/lib/Parser/ISGParser.js +0 -71
  137. package/lib/Parser/KMLParser.js +0 -25
  138. package/lib/Parser/LASParser.js +0 -137
  139. package/lib/Parser/MapBoxUrlParser.js +0 -83
  140. package/lib/Parser/PntsParser.js +0 -131
  141. package/lib/Parser/Potree2BinParser.js +0 -92
  142. package/lib/Parser/PotreeBinParser.js +0 -106
  143. package/lib/Parser/PotreeCinParser.js +0 -29
  144. package/lib/Parser/ShapefileParser.js +0 -78
  145. package/lib/Parser/VectorTileParser.js +0 -202
  146. package/lib/Parser/XbilParser.js +0 -119
  147. package/lib/Parser/deprecated/LegacyGLTFLoader.js +0 -1386
  148. package/lib/Parser/iGLTFLoader.js +0 -168
  149. package/lib/Process/3dTilesProcessing.js +0 -304
  150. package/lib/Process/FeatureProcessing.js +0 -76
  151. package/lib/Process/LayeredMaterialNodeProcessing.js +0 -221
  152. package/lib/Process/ObjectRemovalHelper.js +0 -97
  153. package/lib/Process/handlerNodeError.js +0 -23
  154. package/lib/Provider/3dTilesProvider.js +0 -149
  155. package/lib/Provider/DataSourceProvider.js +0 -8
  156. package/lib/Provider/Fetcher.js +0 -229
  157. package/lib/Provider/PointCloudProvider.js +0 -45
  158. package/lib/Provider/TileProvider.js +0 -16
  159. package/lib/Provider/URLBuilder.js +0 -116
  160. package/lib/Renderer/Camera.js +0 -281
  161. package/lib/Renderer/Color.js +0 -56
  162. package/lib/Renderer/ColorLayersOrdering.js +0 -115
  163. package/lib/Renderer/CommonMaterial.js +0 -31
  164. package/lib/Renderer/Label2DRenderer.js +0 -190
  165. package/lib/Renderer/LayeredMaterial.js +0 -243
  166. package/lib/Renderer/OBB.js +0 -153
  167. package/lib/Renderer/OrientedImageCamera.js +0 -118
  168. package/lib/Renderer/OrientedImageMaterial.js +0 -167
  169. package/lib/Renderer/PointsMaterial.js +0 -485
  170. package/lib/Renderer/RasterTile.js +0 -209
  171. package/lib/Renderer/RenderMode.js +0 -31
  172. package/lib/Renderer/Shader/ShaderChunk.js +0 -160
  173. package/lib/Renderer/Shader/ShaderUtils.js +0 -47
  174. package/lib/Renderer/SphereHelper.js +0 -23
  175. package/lib/Renderer/WebXR.js +0 -51
  176. package/lib/Renderer/c3DEngine.js +0 -214
  177. package/lib/Source/C3DTilesGoogleSource.js +0 -74
  178. package/lib/Source/C3DTilesIonSource.js +0 -54
  179. package/lib/Source/C3DTilesSource.js +0 -30
  180. package/lib/Source/CopcSource.js +0 -115
  181. package/lib/Source/EntwinePointTileSource.js +0 -62
  182. package/lib/Source/FileSource.js +0 -189
  183. package/lib/Source/OGC3DTilesGoogleSource.js +0 -29
  184. package/lib/Source/OGC3DTilesIonSource.js +0 -34
  185. package/lib/Source/OGC3DTilesSource.js +0 -21
  186. package/lib/Source/OrientedImageSource.js +0 -59
  187. package/lib/Source/Potree2Source.js +0 -167
  188. package/lib/Source/PotreeSource.js +0 -82
  189. package/lib/Source/Source.js +0 -223
  190. package/lib/Source/TMSSource.js +0 -145
  191. package/lib/Source/VectorTilesSource.js +0 -178
  192. package/lib/Source/WFSSource.js +0 -168
  193. package/lib/Source/WMSSource.js +0 -133
  194. package/lib/Source/WMTSSource.js +0 -86
  195. package/lib/ThreeExtended/capabilities/WebGL.js +0 -69
  196. package/lib/ThreeExtended/libs/ktx-parse.module.js +0 -470
  197. package/lib/ThreeExtended/libs/zstddec.module.js +0 -29
  198. package/lib/ThreeExtended/loaders/DDSLoader.js +0 -200
  199. package/lib/ThreeExtended/loaders/DRACOLoader.js +0 -399
  200. package/lib/ThreeExtended/loaders/GLTFLoader.js +0 -2876
  201. package/lib/ThreeExtended/loaders/KTX2Loader.js +0 -625
  202. package/lib/ThreeExtended/utils/BufferGeometryUtils.js +0 -846
  203. package/lib/ThreeExtended/utils/WorkerPool.js +0 -70
  204. package/lib/Utils/CameraUtils.js +0 -555
  205. package/lib/Utils/DEMUtils.js +0 -350
  206. package/lib/Utils/FeaturesUtils.js +0 -156
  207. package/lib/Utils/Gradients.js +0 -16
  208. package/lib/Utils/OrientationUtils.js +0 -457
  209. package/lib/Utils/ThreeUtils.js +0 -115
  210. package/lib/Utils/gui/C3DTilesStyle.js +0 -215
  211. package/lib/Utils/gui/Main.js +0 -7
  212. package/lib/Utils/gui/Minimap.js +0 -154
  213. package/lib/Utils/gui/Navigation.js +0 -245
  214. package/lib/Utils/gui/Scale.js +0 -107
  215. package/lib/Utils/gui/Searchbar.js +0 -234
  216. package/lib/Utils/gui/Widget.js +0 -80
  217. package/lib/Utils/placeObjectOnGround.js +0 -137
  218. package/lib/Worker/LASLoaderWorker.js +0 -19
  219. package/lib/Worker/Potree2Worker.js +0 -21
@@ -1,1162 +0,0 @@
1
- import * as THREE from 'three';
2
- import AnimationPlayer from "../Core/AnimationPlayer.js";
3
- import Coordinates from "../Core/Geographic/Coordinates.js";
4
- import { ellipsoidSizes } from "../Core/Math/Ellipsoid.js";
5
- import CameraUtils from "../Utils/CameraUtils.js";
6
- import StateControl from "./StateControl.js";
7
- import { VIEW_EVENTS } from "../Core/View.js";
8
-
9
- // private members
10
- const EPS = 0.000001;
11
- const direction = {
12
- up: new THREE.Vector2(0, 1),
13
- bottom: new THREE.Vector2(0, -1),
14
- left: new THREE.Vector2(1, 0),
15
- right: new THREE.Vector2(-1, 0)
16
- };
17
-
18
- // Orbit
19
- const rotateStart = new THREE.Vector2();
20
- const rotateEnd = new THREE.Vector2();
21
- const rotateDelta = new THREE.Vector2();
22
- const spherical = new THREE.Spherical(1.0, 0.01, 0);
23
- const sphericalDelta = new THREE.Spherical(1.0, 0, 0);
24
- let orbitScale = 1.0;
25
-
26
- // Pan
27
- const panStart = new THREE.Vector2();
28
- const panEnd = new THREE.Vector2();
29
- const panDelta = new THREE.Vector2();
30
- const panOffset = new THREE.Vector3();
31
-
32
- // Dolly
33
- const dollyStart = new THREE.Vector2();
34
- const dollyEnd = new THREE.Vector2();
35
- const dollyDelta = new THREE.Vector2();
36
- let dollyScale;
37
-
38
- // Globe move
39
- const moveAroundGlobe = new THREE.Quaternion();
40
- const cameraTarget = new THREE.Object3D();
41
- const coordCameraTarget = new Coordinates('EPSG:4978');
42
- cameraTarget.matrixWorldInverse = new THREE.Matrix4();
43
- const xyz = new Coordinates('EPSG:4978', 0, 0, 0);
44
- const c = new Coordinates('EPSG:4326', 0, 0, 0);
45
- // Position object on globe
46
- function positionObject(newPosition, object) {
47
- xyz.setFromVector3(newPosition).as('EPSG:4326', c);
48
- object.position.copy(newPosition);
49
- object.lookAt(c.geodesicNormal.add(newPosition));
50
- object.rotateX(Math.PI * 0.5);
51
- object.updateMatrixWorld(true);
52
- }
53
-
54
- // Save the last time of mouse move for damping
55
- let lastTimeMouseMove = 0;
56
-
57
- // Animations and damping
58
- let enableAnimation = true;
59
- const dampingFactorDefault = 0.25;
60
- const dampingMove = new THREE.Quaternion(0, 0, 0, 1);
61
- const durationDampingMove = 120;
62
- const durationDampingOrbital = 60;
63
-
64
- // Pan Move
65
- const panVector = new THREE.Vector3();
66
-
67
- // Save last transformation
68
- const lastPosition = new THREE.Vector3();
69
- const lastQuaternion = new THREE.Quaternion();
70
-
71
- // Tangent sphere to ellipsoid
72
- const pickSphere = new THREE.Sphere();
73
- const pickingPoint = new THREE.Vector3();
74
-
75
- // Sphere intersection
76
- const intersection = new THREE.Vector3();
77
-
78
- // Set to true to enable target helper
79
- const enableTargetHelper = false;
80
- const helpers = {};
81
- /**
82
- * Globe control pan event. Fires after camera pan
83
- * @event GlobeControls#pan-changed
84
- * @property target {GlobeControls} dispatched on controls
85
- * @property type {string} orientation-changed
86
- */
87
- /**
88
- * Globe control orientation event. Fires when camera's orientation change
89
- * @event GlobeControls#orientation-changed
90
- * @property new {object}
91
- * @property new.tilt {number} the new value of the tilt of the camera
92
- * @property new.heading {number} the new value of the heading of the camera
93
- * @property previous {object}
94
- * @property previous.tilt {number} the previous value of the tilt of the camera
95
- * @property previous.heading {number} the previous value of the heading of the camera
96
- * @property target {GlobeControls} dispatched on controls
97
- * @property type {string} orientation-changed
98
- */
99
- /**
100
- * Globe control range event. Fires when camera's range to target change
101
- * @event GlobeControls#range-changed
102
- * @property new {number} the new value of the range
103
- * @property previous {number} the previous value of the range
104
- * @property target {GlobeControls} dispatched on controls
105
- * @property type {string} range-changed
106
- */
107
- /**
108
- * Globe control camera's target event. Fires when camera's target change
109
- * @event GlobeControls#camera-target-changed
110
- * @property new {object}
111
- * @property new {Coordinates} the new camera's target coordinates
112
- * @property previous {Coordinates} the previous camera's target coordinates
113
- * @property target {GlobeControls} dispatched on controls
114
- * @property type {string} camera-target-changed
115
- */
116
-
117
- /**
118
- * globe controls events
119
- * @property PAN_CHANGED {string} Fires after camera pan
120
- * @property ORIENTATION_CHANGED {string} Fires when camera's orientation change
121
- * @property RANGE_CHANGED {string} Fires when camera's range to target change
122
- * @property CAMERA_TARGET_CHANGED {string} Fires when camera's target change
123
- */
124
-
125
- export const CONTROL_EVENTS = {
126
- PAN_CHANGED: 'pan-changed',
127
- ORIENTATION_CHANGED: 'orientation-changed',
128
- RANGE_CHANGED: 'range-changed',
129
- CAMERA_TARGET_CHANGED: 'camera-target-changed'
130
- };
131
- const quaterPano = new THREE.Quaternion();
132
- const quaterAxis = new THREE.Quaternion();
133
- const axisX = new THREE.Vector3(1, 0, 0);
134
- let minDistanceZ = Infinity;
135
- const lastNormalizedIntersection = new THREE.Vector3();
136
- const normalizedIntersection = new THREE.Vector3();
137
- const raycaster = new THREE.Raycaster();
138
- const targetPosition = new THREE.Vector3();
139
- const pickedPosition = new THREE.Vector3();
140
- const sphereCamera = new THREE.Sphere();
141
- let previous;
142
- /**
143
- * GlobeControls is a camera controller
144
- *
145
- * @class GlobeControls
146
- * @param {GlobeView} view the view where the control will be used
147
- * @param {CameraTransformOptions|Extent} placement the {@link CameraTransformOptions} to apply to view's camera
148
- * or the extent it must display at initialisation, see {@link CameraTransformOptions} in {@link CameraUtils}.
149
- * @param {object} [options] An object with one or more configuration properties. Any property of GlobeControls
150
- * can be passed in this object.
151
- * @property {number} zoomFactor The factor the scale is multiplied by when dollying (zooming) in or
152
- * divided by when dollying out. Default is 2.
153
- * @property {number} rotateSpeed Speed camera rotation in orbit and panoramic mode. Default is 0.25.
154
- * @property {number} minDistance Minimum distance between ground and camera in meters (Perspective Camera only).
155
- * Default is 250.
156
- * @property {number} maxDistance Maximum distance between ground and camera in meters
157
- * (Perspective Camera only). Default is ellipsoid radius * 8.
158
- * @property {number} minZoom How far you can zoom in, in meters (Orthographic Camera only). Default is 0.
159
- * @property {number} maxZoom How far you can zoom out, in meters (Orthographic Camera only). Default
160
- * is Infinity.
161
- * @property {number} keyPanSpeed Number of pixels moved per push on array key. Default is 7.
162
- * @property {number} minPolarAngle Minimum vertical orbit angle (in degrees). Default is 0.5.
163
- * @property {number} maxPolarAngle Maximum vertical orbit angle (in degrees). Default is 86.
164
- * @property {number} minAzimuthAngle Minimum horizontal orbit angle (in degrees). If modified,
165
- * should be in [-180,0]. Default is -Infinity.
166
- * @property {number} maxAzimuthAngle Maximum horizontal orbit angle (in degrees). If modified,
167
- * should be in [0,180]. Default is Infinity.
168
- * @property {boolean} handleCollision Handle collision between camera and ground or not, i.e. whether
169
- * you can zoom underground or not. Default is true.
170
- * @property {boolean} enableDamping Enable damping or not (simulates the lag that a real camera
171
- * operator introduces while operating a heavy physical camera). Default is true.
172
- * @property {boolean} dampingMoveFactor the damping move factor. Default is 0.25.
173
- * @property {StateControl~State} stateControl redefining which controls state is triggered by the keyboard/mouse
174
- * event (For example, rewrite the PAN movement to be triggered with the 'left' mouseButton instead of 'right').
175
- */
176
- class GlobeControls extends THREE.EventDispatcher {
177
- constructor(view, placement) {
178
- let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
179
- super();
180
- this.player = new AnimationPlayer();
181
- this.view = view;
182
- this.camera = view.camera3D;
183
-
184
- // State control
185
- this.states = new StateControl(this.view, options.stateControl);
186
-
187
- // this.enabled property has moved to StateControl
188
- Object.defineProperty(this, 'enabled', {
189
- get: () => this.states.enabled,
190
- set: value => {
191
- console.warn('GlobeControls.enabled property is deprecated. Use StateControl.enabled instead ' + '- which you can access with GlobeControls.states.enabled.');
192
- this.states.enabled = value;
193
- }
194
- });
195
-
196
- // These options actually enables dollying in and out; left as "zoom" for
197
- // backwards compatibility
198
- if (options.zoomSpeed) {
199
- console.warn('Controls zoomSpeed parameter is deprecated. Use zoomFactor instead.');
200
- options.zoomFactor = options.zoomFactor || options.zoomSpeed;
201
- }
202
- this.zoomFactor = options.zoomFactor || 1.25;
203
-
204
- // Limits to how far you can dolly in and out ( PerspectiveCamera only )
205
- this.minDistance = options.minDistance || 250;
206
- this.maxDistance = options.maxDistance || ellipsoidSizes.x * 8.0;
207
-
208
- // Limits to how far you can zoom in and out ( OrthographicCamera only )
209
- this.minZoom = options.minZoom || 0;
210
- this.maxZoom = options.maxZoom || Infinity;
211
-
212
- // Set to true to disable this control
213
- this.rotateSpeed = options.rotateSpeed || 0.25;
214
-
215
- // Set to true to disable this control
216
- this.keyPanSpeed = options.keyPanSpeed || 7.0; // pixels moved per arrow key push
217
-
218
- // How far you can orbit vertically, upper and lower limits.
219
- // Range is 0 to Math.PI radians.
220
- // TODO Warning minPolarAngle = 0.01 -> it isn't possible to be perpendicular on Globe
221
- this.minPolarAngle = THREE.MathUtils.degToRad(options.minPolarAngle ?? 0.5);
222
- this.maxPolarAngle = THREE.MathUtils.degToRad(options.minPolarAngle ?? 86);
223
-
224
- // How far you can orbit horizontally, upper and lower limits.
225
- // If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ].
226
- this.minAzimuthAngle = options.minAzimuthAngle ? THREE.MathUtils.degToRad(options.minAzimuthAngle) : -Infinity; // radians
227
- this.maxAzimuthAngle = options.maxAzimuthAngle ? THREE.MathUtils.degToRad(options.maxAzimuthAngle) : Infinity; // radians
228
-
229
- // Set collision options
230
- this.handleCollision = typeof options.handleCollision !== 'undefined' ? options.handleCollision : true;
231
- this.minDistanceCollision = 60;
232
-
233
- // this.enableKeys property has moved to StateControl
234
- Object.defineProperty(this, 'enableKeys', {
235
- get: () => this.states.enableKeys,
236
- set: value => {
237
- console.warn('GlobeControls.enableKeys property is deprecated. Use StateControl.enableKeys instead ' + '- which you can access with GlobeControls.states.enableKeys.');
238
- this.states.enableKeys = value;
239
- }
240
- });
241
-
242
- // Enable Damping
243
- this.enableDamping = options.enableDamping !== false;
244
- this.dampingMoveFactor = options.dampingMoveFactor != undefined ? options.dampingMoveFactor : dampingFactorDefault;
245
- this.startEvent = {
246
- type: 'start'
247
- };
248
- this.endEvent = {
249
- type: 'end'
250
- };
251
- // Update helper
252
- this.updateHelper = enableTargetHelper ? (position, helper) => {
253
- positionObject(position, helper);
254
- view.notifyChange(this.camera);
255
- } : function () {};
256
- this._onEndingMove = null;
257
- this._onTravel = this.travel.bind(this);
258
- this._onTouchStart = this.onTouchStart.bind(this);
259
- this._onTouchEnd = this.onTouchEnd.bind(this);
260
- this._onTouchMove = this.onTouchMove.bind(this);
261
- this._onStateChange = this.onStateChange.bind(this);
262
- this._onRotation = this.handleRotation.bind(this);
263
- this._onDrag = this.handleDrag.bind(this);
264
- this._onDolly = this.handleDolly.bind(this);
265
- this._onPan = this.handlePan.bind(this);
266
- this._onPanoramic = this.handlePanoramic.bind(this);
267
- this._onZoom = this.handleZoom.bind(this);
268
- this.states.addEventListener('state-changed', this._onStateChange, false);
269
- this.states.addEventListener(this.states.ORBIT._event, this._onRotation, false);
270
- this.states.addEventListener(this.states.MOVE_GLOBE._event, this._onDrag, false);
271
- this.states.addEventListener(this.states.DOLLY._event, this._onDolly, false);
272
- this.states.addEventListener(this.states.PAN._event, this._onPan, false);
273
- this.states.addEventListener(this.states.PANORAMIC._event, this._onPanoramic, false);
274
- this.states.addEventListener('zoom', this._onZoom, false);
275
- this.view.domElement.addEventListener('touchstart', this._onTouchStart, false);
276
- this.view.domElement.addEventListener('touchend', this._onTouchEnd, false);
277
- this.view.domElement.addEventListener('touchmove', this._onTouchMove, false);
278
- this.states.addEventListener(this.states.TRAVEL_IN._event, this._onTravel, false);
279
- this.states.addEventListener(this.states.TRAVEL_OUT._event, this._onTravel, false);
280
- view.scene.add(cameraTarget);
281
- if (enableTargetHelper) {
282
- cameraTarget.add(helpers.target);
283
- view.scene.add(helpers.picking);
284
- }
285
- if (placement.isExtent) {
286
- placement.center().as('EPSG:4978', xyz);
287
- } else {
288
- placement.coord.as('EPSG:4978', xyz);
289
- placement.tilt = placement.tilt || 89.5;
290
- placement.heading = placement.heading || 0;
291
- }
292
- positionObject(xyz, cameraTarget);
293
- this.lookAtCoordinate(placement, false);
294
- coordCameraTarget.crs = this.view.referenceCrs;
295
- }
296
- get dollyInScale() {
297
- return this.zoomFactor;
298
- }
299
- get dollyOutScale() {
300
- return 1 / this.zoomFactor;
301
- }
302
- get isPaused() {
303
- // TODO : also check if CameraUtils is performing an animation
304
- return this.states.currentState === this.states.NONE && !this.player.isPlaying();
305
- }
306
- onEndingMove(current) {
307
- if (this._onEndingMove) {
308
- this.player.removeEventListener('animation-stopped', this._onEndingMove);
309
- this._onEndingMove = null;
310
- }
311
- this.handlingEvent(current);
312
- }
313
- rotateLeft() {
314
- let angle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
315
- sphericalDelta.theta -= angle;
316
- }
317
- rotateUp() {
318
- let angle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
319
- sphericalDelta.phi -= angle;
320
- }
321
-
322
- // pass in distance in world space to move left
323
- panLeft(distance) {
324
- const te = this.camera.matrix.elements;
325
- // get X column of matrix
326
- panOffset.fromArray(te);
327
- panOffset.multiplyScalar(-distance);
328
- panVector.add(panOffset);
329
- }
330
-
331
- // pass in distance in world space to move up
332
- panUp(distance) {
333
- const te = this.camera.matrix.elements;
334
- // get Y column of matrix
335
- panOffset.fromArray(te, 4);
336
- panOffset.multiplyScalar(distance);
337
- panVector.add(panOffset);
338
- }
339
-
340
- // pass in x,y of change desired in pixel space,
341
- // right and down are positive
342
- mouseToPan(deltaX, deltaY) {
343
- const gfx = this.view.mainLoop.gfxEngine;
344
- if (this.camera.isPerspectiveCamera) {
345
- let targetDistance = this.camera.position.distanceTo(this.getCameraTargetPosition());
346
- // half of the fov is center to top of screen
347
- targetDistance *= 2 * Math.tan(THREE.MathUtils.degToRad(this.camera.fov * 0.5));
348
-
349
- // we actually don't use screenWidth, since perspective camera is fixed to screen height
350
- this.panLeft(deltaX * targetDistance / gfx.width * this.camera.aspect);
351
- this.panUp(deltaY * targetDistance / gfx.height);
352
- } else if (this.camera.isOrthographicCamera) {
353
- // orthographic
354
- this.panLeft(deltaX * (this.camera.right - this.camera.left) / gfx.width);
355
- this.panUp(deltaY * (this.camera.top - this.camera.bottom) / gfx.height);
356
- }
357
- }
358
- dolly(delta) {
359
- if (delta === 0) {
360
- return;
361
- }
362
- dollyScale = delta > 0 ? this.dollyInScale : this.dollyOutScale;
363
- if (this.camera.isPerspectiveCamera) {
364
- orbitScale /= dollyScale;
365
- } else if (this.camera.isOrthographicCamera) {
366
- this.camera.zoom = THREE.MathUtils.clamp(this.camera.zoom * dollyScale, this.minZoom, this.maxZoom);
367
- this.camera.updateProjectionMatrix();
368
- this.view.notifyChange(this.camera);
369
- }
370
- }
371
- getMinDistanceCameraBoundingSphereObbsUp(tile) {
372
- if (tile.level > 10 && tile.children.length == 1 && tile.geometry) {
373
- const obb = tile.obb;
374
- sphereCamera.center.copy(this.camera.position);
375
- sphereCamera.radius = this.minDistanceCollision;
376
- if (obb.isSphereAboveXYBox(sphereCamera)) {
377
- minDistanceZ = Math.min(sphereCamera.center.z - obb.box3D.max.z, minDistanceZ);
378
- }
379
- }
380
- }
381
- update() {
382
- let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.states.currentState;
383
- // We compute distance between camera's bounding sphere and geometry's obb up face
384
- minDistanceZ = Infinity;
385
- if (this.handleCollision) {
386
- // We check distance to the ground/surface geometry
387
- // add minDistanceZ between camera's bounding and tiles's oriented bounding box (up face only)
388
- // Depending on the distance of the camera with obbs, we add a slowdown or constrain to the movement.
389
- // this constraint or deceleration is suitable for two types of movement MOVE_GLOBE and ORBIT.
390
- // This constraint or deceleration inversely proportional to the camera/obb distance
391
- if (this.view.tileLayer) {
392
- for (const tile of this.view.tileLayer.level0Nodes) {
393
- tile.traverse(this.getMinDistanceCameraBoundingSphereObbsUp.bind(this));
394
- }
395
- }
396
- }
397
- switch (state) {
398
- // MOVE_GLOBE Rotate globe with mouse
399
- case this.states.MOVE_GLOBE:
400
- if (minDistanceZ < 0) {
401
- cameraTarget.translateY(-minDistanceZ);
402
- this.camera.position.setLength(this.camera.position.length() - minDistanceZ);
403
- } else if (minDistanceZ < this.minDistanceCollision) {
404
- const translate = this.minDistanceCollision * (1.0 - minDistanceZ / this.minDistanceCollision);
405
- cameraTarget.translateY(translate);
406
- this.camera.position.setLength(this.camera.position.length() + translate);
407
- }
408
- lastNormalizedIntersection.copy(normalizedIntersection).applyQuaternion(moveAroundGlobe);
409
- cameraTarget.position.applyQuaternion(moveAroundGlobe);
410
- this.camera.position.applyQuaternion(moveAroundGlobe);
411
- break;
412
- // PAN Move camera in projection plan
413
- case this.states.PAN:
414
- this.camera.position.add(panVector);
415
- cameraTarget.position.add(panVector);
416
- break;
417
- // PANORAMIC Move target camera
418
- case this.states.PANORAMIC:
419
- {
420
- this.camera.worldToLocal(cameraTarget.position);
421
- const normal = this.camera.position.clone().normalize().applyQuaternion(this.camera.quaternion.clone().invert());
422
- quaterPano.setFromAxisAngle(normal, sphericalDelta.theta).multiply(quaterAxis.setFromAxisAngle(axisX, sphericalDelta.phi));
423
- cameraTarget.position.applyQuaternion(quaterPano);
424
- this.camera.localToWorld(cameraTarget.position);
425
- break;
426
- }
427
- // ZOOM/ORBIT Move Camera around the target camera
428
- default:
429
- {
430
- // get camera position in local space of target
431
- this.camera.position.applyMatrix4(cameraTarget.matrixWorldInverse);
432
-
433
- // angle from z-axis around y-axis
434
- if (sphericalDelta.theta || sphericalDelta.phi) {
435
- spherical.setFromVector3(this.camera.position);
436
- }
437
- // far underground
438
- const dynamicRadius = spherical.radius * Math.sin(this.minPolarAngle);
439
- const slowdownLimit = dynamicRadius * 8;
440
- const contraryLimit = dynamicRadius * 2;
441
- const minContraintPhi = -0.01;
442
- if (this.handleCollision) {
443
- if (minDistanceZ < slowdownLimit && minDistanceZ > contraryLimit && sphericalDelta.phi > 0) {
444
- // slowdown zone : slowdown sphericalDelta.phi
445
- const slowdownZone = slowdownLimit - contraryLimit;
446
- // the deeper the camera is in this zone, the bigger the factor is
447
- const slowdownFactor = 1 - (slowdownZone - (minDistanceZ - contraryLimit)) / slowdownZone;
448
- // apply slowdown factor on tilt mouvement
449
- sphericalDelta.phi *= slowdownFactor * slowdownFactor;
450
- } else if (minDistanceZ < contraryLimit && minDistanceZ > -contraryLimit && sphericalDelta.phi > minContraintPhi) {
451
- // contraint zone : contraint sphericalDelta.phi
452
-
453
- // calculation of the angle of rotation which allows to leave this zone
454
- let contraryPhi = -Math.asin((contraryLimit - minDistanceZ) * 0.25 / spherical.radius);
455
- // clamp contraryPhi to make a less brutal exit
456
- contraryPhi = THREE.MathUtils.clamp(contraryPhi, minContraintPhi, 0);
457
- // the deeper the camera is in this zone, the bigger the factor is
458
- const contraryFactor = 1 - (contraryLimit - minDistanceZ) / (2 * contraryLimit);
459
- sphericalDelta.phi = THREE.MathUtils.lerp(sphericalDelta.phi, contraryPhi, contraryFactor);
460
- minDistanceZ -= Math.sin(sphericalDelta.phi) * spherical.radius;
461
- }
462
- }
463
- spherical.theta += sphericalDelta.theta;
464
- spherical.phi += sphericalDelta.phi;
465
-
466
- // restrict spherical.theta to be between desired limits
467
- spherical.theta = Math.max(this.minAzimuthAngle, Math.min(this.maxAzimuthAngle, spherical.theta));
468
-
469
- // restrict spherical.phi to be between desired limits
470
- spherical.phi = Math.max(this.minPolarAngle, Math.min(this.maxPolarAngle, spherical.phi));
471
- spherical.radius = this.camera.position.length() * orbitScale;
472
-
473
- // restrict spherical.phi to be betwee EPS and PI-EPS
474
- spherical.makeSafe();
475
-
476
- // restrict radius to be between desired limits
477
- spherical.radius = Math.max(this.minDistance, Math.min(this.maxDistance, spherical.radius));
478
- this.camera.position.setFromSpherical(spherical);
479
-
480
- // if camera is underground, so move up camera
481
- if (minDistanceZ < 0) {
482
- this.camera.position.y -= minDistanceZ;
483
- spherical.setFromVector3(this.camera.position);
484
- sphericalDelta.phi = 0;
485
- }
486
- cameraTarget.localToWorld(this.camera.position);
487
- }
488
- }
489
- this.camera.up.copy(cameraTarget.position).normalize();
490
- this.camera.lookAt(cameraTarget.position);
491
- if (!this.enableDamping) {
492
- sphericalDelta.theta = 0;
493
- sphericalDelta.phi = 0;
494
- moveAroundGlobe.set(0, 0, 0, 1);
495
- } else {
496
- sphericalDelta.theta *= 1 - dampingFactorDefault;
497
- sphericalDelta.phi *= 1 - dampingFactorDefault;
498
- moveAroundGlobe.slerp(dampingMove, this.dampingMoveFactor * 0.2);
499
- }
500
- orbitScale = 1;
501
- panVector.set(0, 0, 0);
502
-
503
- // update condition is:
504
- // min(camera displacement, camera rotation in radians)^2 > EPS
505
- // using small-angle approximation cos(x/2) = 1 - x^2 / 8
506
- if (lastPosition.distanceToSquared(this.camera.position) > EPS || 8 * (1 - lastQuaternion.dot(this.camera.quaternion)) > EPS) {
507
- this.view.notifyChange(this.camera);
508
- lastPosition.copy(this.camera.position);
509
- lastQuaternion.copy(this.camera.quaternion);
510
- }
511
- // Launch animationdamping if mouse stops these movements
512
- if (this.enableDamping && state === this.states.ORBIT && this.player.isStopped() && (sphericalDelta.theta > EPS || sphericalDelta.phi > EPS)) {
513
- this.player.setCallback(() => {
514
- this.update(this.states.ORBIT);
515
- });
516
- this.player.playLater(durationDampingOrbital, 2);
517
- }
518
- this.view.dispatchEvent({
519
- type: VIEW_EVENTS.CAMERA_MOVED,
520
- coord: coordCameraTarget.setFromVector3(cameraTarget.position),
521
- range: spherical.radius,
522
- heading: -THREE.MathUtils.radToDeg(spherical.theta),
523
- tilt: 90 - THREE.MathUtils.radToDeg(spherical.phi)
524
- });
525
- }
526
- onStateChange(event) {
527
- // If the state changed to NONE, end the movement associated to the previous state.
528
- if (this.states.currentState === this.states.NONE) {
529
- this.handleEndMovement(event);
530
- return;
531
- }
532
-
533
- // Stop CameraUtils ongoing animations, which can for instance be triggered with `this.travel` or
534
- // `this.lookAtCoordinate` methods.
535
- CameraUtils.stop(this.view, this.camera);
536
-
537
- // Dispatch events which specify if changes occurred in camera transform options.
538
- this.onEndingMove();
539
-
540
- // Stop eventual damping movement.
541
- this.player.stop();
542
-
543
- // Update camera transform options.
544
- this.updateTarget();
545
- previous = CameraUtils.getTransformCameraLookingAtTarget(this.view, this.camera, pickedPosition);
546
-
547
- // Initialize rotation and panoramic movements.
548
- rotateStart.copy(event.viewCoords);
549
-
550
- // Initialize drag movement.
551
- if (this.view.getPickingPositionFromDepth(event.viewCoords, pickingPoint)) {
552
- pickSphere.radius = pickingPoint.length();
553
- lastNormalizedIntersection.copy(pickingPoint).normalize();
554
- this.updateHelper(pickingPoint, helpers.picking);
555
- }
556
-
557
- // Initialize dolly movement.
558
- dollyStart.copy(event.viewCoords);
559
-
560
- // Initialize pan movement.
561
- panStart.copy(event.viewCoords);
562
- }
563
- handleRotation(event) {
564
- // Stop player if needed. Player can be playing while moving mouse in the case of rotation. This is due to the
565
- // fact that a damping move can occur while rotating (without the need of releasing the mouse button)
566
- this.player.stop();
567
- this.handlePanoramic(event);
568
- }
569
- handleDrag(event) {
570
- const normalized = this.view.viewToNormalizedCoords(event.viewCoords);
571
-
572
- // An updateMatrixWorld on the camera prevents camera jittering when moving globe on a zoomed out view, with
573
- // devtools open in web browser.
574
- this.camera.updateMatrixWorld();
575
- raycaster.setFromCamera(normalized, this.camera);
576
-
577
- // If there's intersection then move globe else we stop the move
578
- if (raycaster.ray.intersectSphere(pickSphere, intersection)) {
579
- normalizedIntersection.copy(intersection).normalize();
580
- moveAroundGlobe.setFromUnitVectors(normalizedIntersection, lastNormalizedIntersection);
581
- lastTimeMouseMove = Date.now();
582
- this.update();
583
- } else {
584
- this.states.onPointerUp();
585
- }
586
- }
587
- handleDolly(event) {
588
- dollyEnd.copy(event.viewCoords);
589
- dollyDelta.subVectors(dollyEnd, dollyStart);
590
- this.dolly(-dollyDelta.y);
591
- dollyStart.copy(dollyEnd);
592
- this.update();
593
- }
594
- handlePan(event) {
595
- if (event.viewCoords) {
596
- panEnd.copy(event.viewCoords);
597
- panDelta.subVectors(panEnd, panStart);
598
- panStart.copy(panEnd);
599
- } else if (event.direction) {
600
- panDelta.copy(direction[event.direction]).multiplyScalar(this.keyPanSpeed);
601
- }
602
- this.mouseToPan(panDelta.x, panDelta.y);
603
- this.update(this.states.PAN);
604
- }
605
- handlePanoramic(event) {
606
- rotateEnd.copy(event.viewCoords);
607
- rotateDelta.subVectors(rotateEnd, rotateStart);
608
- const gfx = this.view.mainLoop.gfxEngine;
609
- sphericalDelta.theta -= 2 * Math.PI * rotateDelta.x / gfx.width * this.rotateSpeed;
610
- // rotating up and down along whole screen attempts to go 360, but limited to 180
611
- sphericalDelta.phi -= 2 * Math.PI * rotateDelta.y / gfx.height * this.rotateSpeed;
612
- rotateStart.copy(rotateEnd);
613
- this.update();
614
- }
615
- handleEndMovement() {
616
- let event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
617
- this.dispatchEvent(this.endEvent);
618
- this.player.stop();
619
-
620
- // Launch damping movement for :
621
- // * this.states.ORBIT
622
- // * this.states.MOVE_GLOBE
623
- if (this.enableDamping) {
624
- if (event.previous === this.states.ORBIT && (sphericalDelta.theta > EPS || sphericalDelta.phi > EPS)) {
625
- this.player.setCallback(() => {
626
- this.update(this.states.ORBIT);
627
- });
628
- this.player.play(durationDampingOrbital);
629
- this._onEndingMove = () => this.onEndingMove();
630
- this.player.addEventListener('animation-stopped', this._onEndingMove);
631
- } else if (event.previous === this.states.MOVE_GLOBE && Date.now() - lastTimeMouseMove < 50) {
632
- this.player.setCallback(() => {
633
- this.update(this.states.MOVE_GLOBE);
634
- });
635
- // animation since mouse up event occurs less than 50ms after the last mouse move
636
- this.player.play(durationDampingMove);
637
- this._onEndingMove = () => this.onEndingMove();
638
- this.player.addEventListener('animation-stopped', this._onEndingMove);
639
- } else {
640
- this.onEndingMove();
641
- }
642
- } else {
643
- this.onEndingMove();
644
- }
645
- }
646
- updateTarget() {
647
- // Check if the middle of the screen is on the globe (to prevent having a dark-screen bug if outside the globe)
648
- if (this.view.getPickingPositionFromDepth(null, pickedPosition)) {
649
- // Update camera's target position
650
- const distance = !isNaN(pickedPosition.x) ? this.camera.position.distanceTo(pickedPosition) : 100;
651
- targetPosition.set(0, 0, -distance);
652
- this.camera.localToWorld(targetPosition);
653
-
654
- // set new camera target on globe
655
- positionObject(targetPosition, cameraTarget);
656
- cameraTarget.matrixWorldInverse.copy(cameraTarget.matrixWorld).invert();
657
- targetPosition.copy(this.camera.position);
658
- targetPosition.applyMatrix4(cameraTarget.matrixWorldInverse);
659
- spherical.setFromVector3(targetPosition);
660
- }
661
- }
662
- handlingEvent(current) {
663
- current = current || CameraUtils.getTransformCameraLookingAtTarget(this.view, this.camera);
664
- const diff = CameraUtils.getDiffParams(previous, current);
665
- if (diff) {
666
- if (diff.range) {
667
- this.dispatchEvent({
668
- type: CONTROL_EVENTS.RANGE_CHANGED,
669
- previous: diff.range.previous,
670
- new: diff.range.new
671
- });
672
- }
673
- if (diff.coord) {
674
- this.dispatchEvent({
675
- type: CONTROL_EVENTS.CAMERA_TARGET_CHANGED,
676
- previous: diff.coord.previous,
677
- new: diff.coord.new
678
- });
679
- }
680
- if (diff.tilt || diff.heading) {
681
- const event = {
682
- type: CONTROL_EVENTS.ORIENTATION_CHANGED
683
- };
684
- if (diff.tilt) {
685
- event.previous = {
686
- tilt: diff.tilt.previous
687
- };
688
- event.new = {
689
- tilt: diff.tilt.new
690
- };
691
- }
692
- if (diff.heading) {
693
- event.previous = event.previous || {};
694
- event.new = event.new || {};
695
- event.new.heading = diff.heading.new;
696
- event.previous.heading = diff.heading.previous;
697
- }
698
- this.dispatchEvent(event);
699
- }
700
- }
701
- }
702
- travel(event) {
703
- this.player.stop();
704
- const point = this.view.getPickingPositionFromDepth(event.viewCoords);
705
- const range = this.getRange(point);
706
- if (point && range > this.minDistance) {
707
- return this.lookAtCoordinate({
708
- coord: new Coordinates('EPSG:4978', point),
709
- range: range * (event.direction === 'out' ? 1 / 0.6 : 0.6),
710
- time: 1500
711
- });
712
- }
713
- }
714
- handleZoom(event) {
715
- this.player.stop();
716
- CameraUtils.stop(this.view, this.camera);
717
- this.updateTarget();
718
- const delta = -event.delta;
719
- this.dolly(delta);
720
- const previousRange = this.getRange(pickedPosition);
721
- this.update();
722
- const newRange = this.getRange(pickedPosition);
723
- if (Math.abs(newRange - previousRange) / previousRange > 0.001) {
724
- this.dispatchEvent({
725
- type: CONTROL_EVENTS.RANGE_CHANGED,
726
- previous: previousRange,
727
- new: newRange
728
- });
729
- }
730
- this.dispatchEvent(this.startEvent);
731
- this.dispatchEvent(this.endEvent);
732
- }
733
- onTouchStart(event) {
734
- // CameraUtils.stop(view);
735
- this.player.stop();
736
- // TODO : this.states.enabled check should be removed when moving touch events management to StateControl
737
- if (this.states.enabled === false) {
738
- return;
739
- }
740
- this.state = this.states.touchToState(event.touches.length);
741
- this.updateTarget();
742
- if (this.state !== this.states.NONE) {
743
- switch (this.state) {
744
- case this.states.MOVE_GLOBE:
745
- {
746
- const coords = this.view.eventToViewCoords(event);
747
- if (this.view.getPickingPositionFromDepth(coords, pickingPoint)) {
748
- pickSphere.radius = pickingPoint.length();
749
- lastNormalizedIntersection.copy(pickingPoint).normalize();
750
- this.updateHelper(pickingPoint, helpers.picking);
751
- } else {
752
- this.state = this.states.NONE;
753
- }
754
- break;
755
- }
756
- case this.states.ORBIT:
757
- case this.states.DOLLY:
758
- {
759
- const x = event.touches[0].pageX;
760
- const y = event.touches[0].pageY;
761
- const dx = x - event.touches[1].pageX;
762
- const dy = y - event.touches[1].pageY;
763
- const distance = Math.sqrt(dx * dx + dy * dy);
764
- dollyStart.set(0, distance);
765
- rotateStart.set(x, y);
766
- break;
767
- }
768
- case this.states.PAN:
769
- panStart.set(event.touches[0].pageX, event.touches[0].pageY);
770
- break;
771
- default:
772
- }
773
- this.dispatchEvent(this.startEvent);
774
- }
775
- }
776
- onTouchMove(event) {
777
- if (this.player.isPlaying()) {
778
- this.player.stop();
779
- }
780
- // TODO : this.states.enabled check should be removed when moving touch events management to StateControl
781
- if (this.states.enabled === false) {
782
- return;
783
- }
784
- event.preventDefault();
785
- event.stopPropagation();
786
- switch (event.touches.length) {
787
- case this.states.MOVE_GLOBE.finger:
788
- {
789
- const coords = this.view.eventToViewCoords(event);
790
- const normalized = this.view.viewToNormalizedCoords(coords);
791
- // An updateMatrixWorld on the camera prevents camera jittering when moving globe on a zoomed out view, with
792
- // devtools open in web browser.
793
- this.camera.updateMatrixWorld();
794
- raycaster.setFromCamera(normalized, this.camera);
795
- // If there's intersection then move globe else we stop the move
796
- if (raycaster.ray.intersectSphere(pickSphere, intersection)) {
797
- normalizedIntersection.copy(intersection).normalize();
798
- moveAroundGlobe.setFromUnitVectors(normalizedIntersection, lastNormalizedIntersection);
799
- lastTimeMouseMove = Date.now();
800
- } else {
801
- this.onTouchEnd();
802
- }
803
- break;
804
- }
805
- case this.states.ORBIT.finger:
806
- case this.states.DOLLY.finger:
807
- {
808
- const gfx = this.view.mainLoop.gfxEngine;
809
- rotateEnd.set(event.touches[0].pageX, event.touches[0].pageY);
810
- rotateDelta.subVectors(rotateEnd, rotateStart);
811
-
812
- // rotating across whole screen goes 360 degrees around
813
- this.rotateLeft(2 * Math.PI * rotateDelta.x / gfx.width * this.rotateSpeed);
814
- // rotating up and down along whole screen attempts to go 360, but limited to 180
815
- this.rotateUp(2 * Math.PI * rotateDelta.y / gfx.height * this.rotateSpeed);
816
- rotateStart.copy(rotateEnd);
817
- const dx = event.touches[0].pageX - event.touches[1].pageX;
818
- const dy = event.touches[0].pageY - event.touches[1].pageY;
819
- const distance = Math.sqrt(dx * dx + dy * dy);
820
- dollyEnd.set(0, distance);
821
- dollyDelta.subVectors(dollyEnd, dollyStart);
822
- this.dolly(dollyDelta.y);
823
- dollyStart.copy(dollyEnd);
824
- break;
825
- }
826
- case this.states.PAN.finger:
827
- panEnd.set(event.touches[0].pageX, event.touches[0].pageY);
828
- panDelta.subVectors(panEnd, panStart);
829
- this.mouseToPan(panDelta.x, panDelta.y);
830
- panStart.copy(panEnd);
831
- break;
832
- default:
833
- this.state = this.states.NONE;
834
- }
835
- if (this.state !== this.states.NONE) {
836
- this.update(this.state);
837
- }
838
- }
839
- onTouchEnd() {
840
- this.handleEndMovement({
841
- previous: this.state
842
- });
843
- this.state = this.states.NONE;
844
- }
845
- dispose() {
846
- this.view.domElement.removeEventListener('touchstart', this._onTouchStart, false);
847
- this.view.domElement.removeEventListener('touchend', this._onTouchEnd, false);
848
- this.view.domElement.removeEventListener('touchmove', this._onTouchMove, false);
849
- this.states.dispose();
850
- this.states.removeEventListener('state-changed', this._onStateChange, false);
851
- this.states.removeEventListener(this.states.ORBIT._event, this._onRotation, false);
852
- this.states.removeEventListener(this.states.MOVE_GLOBE._event, this._onDrag, false);
853
- this.states.removeEventListener(this.states.DOLLY._event, this._onDolly, false);
854
- this.states.removeEventListener(this.states.PAN._event, this._onPan, false);
855
- this.states.removeEventListener(this.states.PANORAMIC._event, this._onPanoramic, false);
856
- this.states.removeEventListener('zoom', this._onZoom, false);
857
- this.states.removeEventListener(this.states.TRAVEL_IN._event, this._onTravel, false);
858
- this.states.removeEventListener(this.states.TRAVEL_OUT._event, this._onTravel, false);
859
- this.dispatchEvent({
860
- type: 'dispose'
861
- });
862
- }
863
- /**
864
- * Changes the tilt of the current camera, in degrees.
865
- * @param {number} tilt
866
- * @param {boolean} isAnimated
867
- * @return {Promise<void>}
868
- */
869
- setTilt(tilt, isAnimated) {
870
- return this.lookAtCoordinate({
871
- tilt
872
- }, isAnimated);
873
- }
874
-
875
- /**
876
- * Changes the heading of the current camera, in degrees.
877
- * @param {number} heading
878
- * @param {boolean} isAnimated
879
- * @return {Promise<void>}
880
- */
881
- setHeading(heading, isAnimated) {
882
- return this.lookAtCoordinate({
883
- heading
884
- }, isAnimated);
885
- }
886
-
887
- /**
888
- * Sets the "range": the distance in meters between the camera and the current central point on the screen.
889
- * @param {number} range
890
- * @param {boolean} isAnimated
891
- * @return {Promise<void>}
892
- */
893
- setRange(range, isAnimated) {
894
- return this.lookAtCoordinate({
895
- range
896
- }, isAnimated);
897
- }
898
-
899
- /**
900
- * Returns the {@linkcode Coordinates} of the globe point targeted by the camera in EPSG:4978 projection. See {@linkcode Coordinates} for conversion
901
- * @return {THREE.Vector3} position
902
- */
903
- getCameraTargetPosition() {
904
- return cameraTarget.position;
905
- }
906
-
907
- /**
908
- * Returns the "range": the distance in meters between the camera and the current central point on the screen.
909
- * @param {THREE.Vector3} [position] - The position to consider as picked on
910
- * the ground.
911
- * @return {number} number
912
- */
913
- getRange(position) {
914
- return CameraUtils.getTransformCameraLookingAtTarget(this.view, this.camera, position).range;
915
- }
916
-
917
- /**
918
- * Returns the tilt of the current camera in degrees.
919
- * @param {THREE.Vector3} [position] - The position to consider as picked on
920
- * the ground.
921
- * @return {number} The angle of the rotation in degrees.
922
- */
923
- getTilt(position) {
924
- return CameraUtils.getTransformCameraLookingAtTarget(this.view, this.camera, position).tilt;
925
- }
926
-
927
- /**
928
- * Returns the heading of the current camera in degrees.
929
- * @param {THREE.Vector3} [position] - The position to consider as picked on
930
- * the ground.
931
- * @return {number} The angle of the rotation in degrees.
932
- */
933
- getHeading(position) {
934
- return CameraUtils.getTransformCameraLookingAtTarget(this.view, this.camera, position).heading;
935
- }
936
-
937
- /**
938
- * Displaces the central point to a specific amount of pixels from its current position.
939
- * The view flies to the desired coordinate, i.e.is not teleported instantly. Note : The results can be strange in some cases, if ever possible, when e.g.the camera looks horizontally or if the displaced center would not pick the ground once displaced.
940
- * @param {vector} pVector The vector
941
- * @return {Promise}
942
- */
943
- pan(pVector) {
944
- this.mouseToPan(pVector.x, pVector.y);
945
- this.update(this.states.PAN);
946
- return Promise.resolve();
947
- }
948
-
949
- /**
950
- * Returns the orientation angles of the current camera, in degrees.
951
- * @return {Array<number>}
952
- */
953
- getCameraOrientation() {
954
- this.view.getPickingPositionFromDepth(null, pickedPosition);
955
- return [this.getTilt(pickedPosition), this.getHeading(pickedPosition)];
956
- }
957
-
958
- /**
959
- * Returns the camera location projected on the ground in lat,lon. See {@linkcode Coordinates} for conversion.
960
- * @return {Coordinates} position
961
- */
962
-
963
- getCameraCoordinate() {
964
- return new Coordinates('EPSG:4978', this.camera.position).as('EPSG:4326');
965
- }
966
-
967
- /**
968
- * Returns the {@linkcode Coordinates} of the central point on screen in lat,lon. See {@linkcode Coordinates} for conversion.
969
- * @return {Coordinates} coordinate
970
- */
971
- getLookAtCoordinate() {
972
- return CameraUtils.getTransformCameraLookingAtTarget(this.view, this.camera).coord;
973
- }
974
-
975
- /**
976
- * Sets the animation enabled.
977
- * @param {boolean} enable enable
978
- */
979
- setAnimationEnabled(enable) {
980
- enableAnimation = enable;
981
- }
982
-
983
- /**
984
- * Determines if animation enabled.
985
- * @return {boolean} True if animation enabled, False otherwise.
986
- */
987
- isAnimationEnabled() {
988
- return enableAnimation;
989
- }
990
-
991
- /**
992
- * Returns the actual zoom. The zoom will always be between the [getMinZoom(), getMaxZoom()].
993
- * @return {number} The zoom .
994
- */
995
- getZoom() {
996
- return this.view.tileLayer.computeTileZoomFromDistanceCamera(this.getRange(), this.view.camera);
997
- }
998
-
999
- /**
1000
- * Sets the current zoom, which is an index in the logical scales predefined for the application.
1001
- * The higher the zoom, the closer to the ground.
1002
- * The zoom is always in the [getMinZoom(), getMaxZoom()] range.
1003
- * @param {number} zoom The zoom
1004
- * @param {boolean} isAnimated Indicates if animated
1005
- * @return {Promise}
1006
- */
1007
- setZoom(zoom, isAnimated) {
1008
- return this.lookAtCoordinate({
1009
- zoom
1010
- }, isAnimated);
1011
- }
1012
-
1013
- /**
1014
- * Return the current zoom scale at the central point of the view.
1015
- * This function compute the scale of a map
1016
- * @param {number} pitch Screen pitch, in millimeters ; 0.28 by default
1017
- * @return {number} The zoom scale.
1018
- *
1019
- * @deprecated Use View#getScale instead.
1020
- */
1021
- getScale(pitch) /* istanbul ignore next */{
1022
- console.warn('Deprecated, use View#getScale instead.');
1023
- return this.view.getScale(pitch);
1024
- }
1025
-
1026
- /**
1027
- * To convert the projection in meters on the globe of a number of pixels of screen
1028
- * @param {number} pixels count pixels to project
1029
- * @param {number} pixelPitch Screen pixel pitch, in millimeters (default = 0.28 mm / standard pixel size of 0.28 millimeters as defined by the OGC)
1030
- * @return {number} projection in meters on globe
1031
- *
1032
- * @deprecated Use `View#getPixelsToMeters` instead.
1033
- */
1034
- pixelsToMeters(pixels) /* istanbul ignore next */{
1035
- let pixelPitch = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0.28;
1036
- console.warn('Deprecated use View#getPixelsToMeters instead.');
1037
- const scaled = this.getScale(pixelPitch);
1038
- return pixels * pixelPitch / scaled / 1000;
1039
- }
1040
-
1041
- /**
1042
- * To convert the projection a number of horizontal pixels of screen to longitude degree WGS84 on the globe
1043
- * @param {number} pixels count pixels to project
1044
- * @param {number} pixelPitch Screen pixel pitch, in millimeters (default = 0.28 mm / standard pixel size of 0.28 millimeters as defined by the OGC)
1045
- * @return {number} projection in degree on globe
1046
- *
1047
- * @deprecated Use `View#getPixelsToMeters` and `GlobeControls#metersToDegrees`
1048
- * instead.
1049
- */
1050
- pixelsToDegrees(pixels) /* istanbul ignore next */{
1051
- let pixelPitch = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0.28;
1052
- console.warn('Deprecated, use View#getPixelsToMeters and GlobeControls#getMetersToDegrees instead.');
1053
- const chord = this.pixelsToMeters(pixels, pixelPitch);
1054
- return THREE.MathUtils.radToDeg(2 * Math.asin(chord / (2 * ellipsoidSizes.x)));
1055
- }
1056
-
1057
- /**
1058
- * Projection on screen in pixels of length in meter on globe
1059
- * @param {number} value Length in meter on globe
1060
- * @param {number} pixelPitch Screen pixel pitch, in millimeters (default = 0.28 mm / standard pixel size of 0.28 millimeters as defined by the OGC)
1061
- * @return {number} projection in pixels on screen
1062
- *
1063
- * @deprecated Use `View#getMetersToPixels` instead.
1064
- */
1065
- metersToPixels(value) /* istanbul ignore next */{
1066
- let pixelPitch = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0.28;
1067
- console.warn('Deprecated, use View#getMetersToPixels instead.');
1068
- const scaled = this.getScale(pixelPitch);
1069
- pixelPitch /= 1000;
1070
- return value * scaled / pixelPitch;
1071
- }
1072
-
1073
- /**
1074
- * Changes the zoom of the central point of screen so that screen acts as a map with a specified scale.
1075
- * The view flies to the desired zoom scale;
1076
- * @param {number} scale The scale
1077
- * @param {number} pitch The pitch
1078
- * @param {boolean} isAnimated Indicates if animated
1079
- * @return {Promise}
1080
- */
1081
- setScale(scale, pitch, isAnimated) {
1082
- return this.lookAtCoordinate({
1083
- scale,
1084
- pitch
1085
- }, isAnimated);
1086
- }
1087
-
1088
- /**
1089
- * Changes the center of the scene on screen to the specified in lat, lon. See {@linkcode Coordinates} for conversion.
1090
- * This function allows to change the central position, the zoom, the range, the scale and the camera orientation at the same time.
1091
- * The zoom has to be between the [getMinZoom(), getMaxZoom()].
1092
- * Zoom parameter is ignored if range is set
1093
- * The tilt's interval is between 4 and 89.5 degree
1094
- *
1095
- * @param {CameraUtils~CameraTransformOptions|Extent} [params] - camera transformation to apply
1096
- * @param {number} [params.zoom] - zoom
1097
- * @param {number} [params.scale] - scale
1098
- * @param {boolean} [isAnimated] - Indicates if animated
1099
- * @return {Promise} A promise that resolves when transformation is complete
1100
- */
1101
- lookAtCoordinate() {
1102
- let params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1103
- let isAnimated = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.isAnimationEnabled();
1104
- this.player.stop();
1105
- if (!params.isExtent) {
1106
- if (params.zoom) {
1107
- params.range = this.view.tileLayer.computeDistanceCameraFromTileZoom(params.zoom, this.view.camera);
1108
- } else if (params.scale) {
1109
- params.range = this.view.getScaleFromDistance(params.pitch, params.scale);
1110
- if (params.range < this.minDistance || params.range > this.maxDistance) {
1111
- // eslint-disable-next-line no-console
1112
- console.warn(`This scale ${params.scale} can not be reached`);
1113
- params.range = THREE.MathUtils.clamp(params.range, this.minDistance, this.maxDistance);
1114
- }
1115
- }
1116
- if (params.tilt !== undefined) {
1117
- const minTilt = 90 - THREE.MathUtils.radToDeg(this.maxPolarAngle);
1118
- const maxTilt = 90 - THREE.MathUtils.radToDeg(this.minPolarAngle);
1119
- if (params.tilt < minTilt || params.tilt > maxTilt) {
1120
- params.tilt = THREE.MathUtils.clamp(params.tilt, minTilt, maxTilt);
1121
- // eslint-disable-next-line no-console
1122
- console.warn('Tilt was clamped to ', params.tilt, ` the interval is between ${minTilt} and ${maxTilt} degree`);
1123
- }
1124
- }
1125
- }
1126
- previous = CameraUtils.getTransformCameraLookingAtTarget(this.view, this.camera);
1127
- if (isAnimated) {
1128
- params.callback = r => cameraTarget.position.copy(r.targetWorldPosition);
1129
- this.dispatchEvent({
1130
- type: 'animation-started'
1131
- });
1132
- return CameraUtils.animateCameraToLookAtTarget(this.view, this.camera, params).then(result => {
1133
- this.dispatchEvent({
1134
- type: 'animation-ended'
1135
- });
1136
- this.handlingEvent(result);
1137
- return result;
1138
- });
1139
- } else {
1140
- return CameraUtils.transformCameraToLookAtTarget(this.view, this.camera, params).then(result => {
1141
- cameraTarget.position.copy(result.targetWorldPosition);
1142
- this.handlingEvent(result);
1143
- return result;
1144
- });
1145
- }
1146
- }
1147
-
1148
- /**
1149
- * Pick a position on the globe at the given position in lat,lon. See {@linkcode Coordinates} for conversion.
1150
- * @param {Vector2} windowCoords - window coordinates
1151
- * @param {number=} y - The y-position inside the Globe element.
1152
- * @return {Coordinates} position
1153
- */
1154
- pickGeoPosition(windowCoords) {
1155
- const pickedPosition = this.view.getPickingPositionFromDepth(windowCoords);
1156
- if (!pickedPosition) {
1157
- return;
1158
- }
1159
- return new Coordinates('EPSG:4978', pickedPosition).as('EPSG:4326');
1160
- }
1161
- }
1162
- export default GlobeControls;