itowns 2.44.3-next.40 → 2.44.3-next.42

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