智慧水务管理系统 - 精河县供水工程综合管理平台

EntityView.js 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. import Cartesian3 from "../Core/Cartesian3.js";
  2. import Check from "../Core/Check.js";
  3. import defined from "../Core/defined.js";
  4. import Ellipsoid from "../Core/Ellipsoid.js";
  5. import HeadingPitchRange from "../Core/HeadingPitchRange.js";
  6. import JulianDate from "../Core/JulianDate.js";
  7. import CesiumMath from "../Core/Math.js";
  8. import Matrix3 from "../Core/Matrix3.js";
  9. import Matrix4 from "../Core/Matrix4.js";
  10. import Quaternion from "../Core/Quaternion.js";
  11. import TrackingReferenceFrame from "../Core/TrackingReferenceFrame.js";
  12. import Transforms from "../Core/Transforms.js";
  13. import SceneMode from "../Scene/SceneMode.js";
  14. import VelocityVectorProperty from "./VelocityVectorProperty.js";
  15. const updateTransformMatrix3Scratch1 = new Matrix3();
  16. const updateTransformMatrix3Scratch2 = new Matrix3();
  17. const updateTransformMatrix3Scratch3 = new Matrix3();
  18. const updateTransformMatrix4Scratch = new Matrix4();
  19. const updateTransformCartesian3Scratch1 = new Cartesian3();
  20. const updateTransformCartesian3Scratch2 = new Cartesian3();
  21. const updateTransformCartesian3Scratch3 = new Cartesian3();
  22. const updateTransformCartesian3Scratch4 = new Cartesian3();
  23. const updateTransformCartesian3Scratch5 = new Cartesian3();
  24. const updateTransformCartesian3Scratch6 = new Cartesian3();
  25. const updateTransformOrientationScratch = new Quaternion();
  26. const velocityScratch = new Cartesian3();
  27. const rotationScratch = new Matrix3();
  28. const deltaTime = new JulianDate();
  29. const northUpAxisFactor = 1.25; // times ellipsoid's maximum radius
  30. function updateTransform(
  31. that,
  32. camera,
  33. updateLookAt,
  34. saveCamera,
  35. positionProperty,
  36. velocityProperty,
  37. orientationProperty,
  38. trackingReferenceFrame,
  39. time,
  40. ellipsoid,
  41. ) {
  42. const mode = that.scene.mode;
  43. let cartesian = positionProperty.getValue(time, that._lastCartesian);
  44. if (defined(cartesian)) {
  45. let hasBasis = false;
  46. let invertVelocity = false;
  47. let xBasis;
  48. let yBasis;
  49. let zBasis;
  50. if (mode === SceneMode.SCENE3D) {
  51. // The time delta was determined based on how fast satellites move compared to vehicles near the surface.
  52. // Slower moving vehicles will most likely default to east-north-up, while faster ones will be VVLH.
  53. JulianDate.addSeconds(time, 0.001, deltaTime);
  54. let deltaCartesian = positionProperty.getValue(
  55. deltaTime,
  56. updateTransformCartesian3Scratch1,
  57. );
  58. // If no valid position at (time + 0.001), sample at (time - 0.001) and invert the vector
  59. if (!defined(deltaCartesian)) {
  60. JulianDate.addSeconds(time, -0.001, deltaTime);
  61. deltaCartesian = positionProperty.getValue(
  62. deltaTime,
  63. updateTransformCartesian3Scratch1,
  64. );
  65. invertVelocity = true;
  66. }
  67. if (defined(deltaCartesian)) {
  68. let toInertial = Transforms.computeFixedToIcrfMatrix(
  69. time,
  70. updateTransformMatrix3Scratch1,
  71. );
  72. let toInertialDelta = Transforms.computeFixedToIcrfMatrix(
  73. deltaTime,
  74. updateTransformMatrix3Scratch2,
  75. );
  76. let toFixed;
  77. if (!defined(toInertial) || !defined(toInertialDelta)) {
  78. toFixed = Transforms.computeTemeToPseudoFixedMatrix(
  79. time,
  80. updateTransformMatrix3Scratch3,
  81. );
  82. toInertial = Matrix3.transpose(
  83. toFixed,
  84. updateTransformMatrix3Scratch1,
  85. );
  86. toInertialDelta = Transforms.computeTemeToPseudoFixedMatrix(
  87. deltaTime,
  88. updateTransformMatrix3Scratch2,
  89. );
  90. Matrix3.transpose(toInertialDelta, toInertialDelta);
  91. } else {
  92. toFixed = Matrix3.transpose(
  93. toInertial,
  94. updateTransformMatrix3Scratch3,
  95. );
  96. }
  97. const inertialCartesian = Matrix3.multiplyByVector(
  98. toInertial,
  99. cartesian,
  100. updateTransformCartesian3Scratch5,
  101. );
  102. const inertialDeltaCartesian = Matrix3.multiplyByVector(
  103. toInertialDelta,
  104. deltaCartesian,
  105. updateTransformCartesian3Scratch6,
  106. );
  107. Cartesian3.subtract(
  108. inertialCartesian,
  109. inertialDeltaCartesian,
  110. updateTransformCartesian3Scratch4,
  111. );
  112. const inertialVelocity =
  113. Cartesian3.magnitude(updateTransformCartesian3Scratch4) * 1000.0; // meters/sec
  114. const mu = CesiumMath.GRAVITATIONALPARAMETER; // m^3 / sec^2
  115. const semiMajorAxis =
  116. -mu /
  117. (inertialVelocity * inertialVelocity -
  118. (2 * mu) / Cartesian3.magnitude(inertialCartesian));
  119. if (
  120. semiMajorAxis < 0 ||
  121. semiMajorAxis > northUpAxisFactor * ellipsoid.maximumRadius
  122. ) {
  123. // North-up viewing from deep space.
  124. // X along the nadir
  125. xBasis = updateTransformCartesian3Scratch2;
  126. Cartesian3.normalize(cartesian, xBasis);
  127. Cartesian3.negate(xBasis, xBasis);
  128. // Z is North
  129. zBasis = Cartesian3.clone(
  130. Cartesian3.UNIT_Z,
  131. updateTransformCartesian3Scratch3,
  132. );
  133. // Y is along the cross of z and x (right handed basis / in the direction of motion)
  134. yBasis = Cartesian3.cross(
  135. zBasis,
  136. xBasis,
  137. updateTransformCartesian3Scratch1,
  138. );
  139. if (Cartesian3.magnitude(yBasis) > CesiumMath.EPSILON7) {
  140. Cartesian3.normalize(xBasis, xBasis);
  141. Cartesian3.normalize(yBasis, yBasis);
  142. zBasis = Cartesian3.cross(
  143. xBasis,
  144. yBasis,
  145. updateTransformCartesian3Scratch3,
  146. );
  147. Cartesian3.normalize(zBasis, zBasis);
  148. hasBasis = true;
  149. }
  150. } else if (
  151. !Cartesian3.equalsEpsilon(
  152. cartesian,
  153. deltaCartesian,
  154. CesiumMath.EPSILON7,
  155. )
  156. ) {
  157. // Approximation of VVLH (Vehicle Velocity Local Horizontal) with the Z-axis flipped.
  158. // Z along the position
  159. zBasis = updateTransformCartesian3Scratch2;
  160. Cartesian3.normalize(inertialCartesian, zBasis);
  161. Cartesian3.normalize(inertialDeltaCartesian, inertialDeltaCartesian);
  162. // Y is along the angular momentum vector (e.g. "orbit normal")
  163. yBasis = Cartesian3.cross(
  164. zBasis,
  165. inertialDeltaCartesian,
  166. updateTransformCartesian3Scratch3,
  167. );
  168. if (invertVelocity) {
  169. yBasis = Cartesian3.multiplyByScalar(yBasis, -1, yBasis);
  170. }
  171. if (
  172. !Cartesian3.equalsEpsilon(
  173. yBasis,
  174. Cartesian3.ZERO,
  175. CesiumMath.EPSILON7,
  176. )
  177. ) {
  178. // X is along the cross of y and z (right handed basis / in the direction of motion)
  179. xBasis = Cartesian3.cross(
  180. yBasis,
  181. zBasis,
  182. updateTransformCartesian3Scratch1,
  183. );
  184. Matrix3.multiplyByVector(toFixed, xBasis, xBasis);
  185. Matrix3.multiplyByVector(toFixed, yBasis, yBasis);
  186. Matrix3.multiplyByVector(toFixed, zBasis, zBasis);
  187. Cartesian3.normalize(xBasis, xBasis);
  188. Cartesian3.normalize(yBasis, yBasis);
  189. Cartesian3.normalize(zBasis, zBasis);
  190. hasBasis = true;
  191. }
  192. }
  193. }
  194. }
  195. if (defined(that.boundingSphere)) {
  196. cartesian = that.boundingSphere.center;
  197. }
  198. let position;
  199. let direction;
  200. let up;
  201. if (saveCamera) {
  202. position = Cartesian3.clone(
  203. camera.position,
  204. updateTransformCartesian3Scratch4,
  205. );
  206. direction = Cartesian3.clone(
  207. camera.direction,
  208. updateTransformCartesian3Scratch5,
  209. );
  210. up = Cartesian3.clone(camera.up, updateTransformCartesian3Scratch6);
  211. }
  212. const transform = updateTransformMatrix4Scratch;
  213. let orientation;
  214. if (defined(orientationProperty)) {
  215. orientation = orientationProperty.getValue(
  216. time,
  217. updateTransformOrientationScratch,
  218. );
  219. }
  220. const velocity = velocityProperty.getValue(time, velocityScratch);
  221. if (
  222. trackingReferenceFrame === TrackingReferenceFrame.INERTIAL &&
  223. defined(orientation)
  224. ) {
  225. Matrix4.fromTranslationQuaternionRotationScale(
  226. cartesian,
  227. orientation,
  228. Cartesian3.ONE,
  229. transform,
  230. );
  231. } else if (
  232. trackingReferenceFrame === TrackingReferenceFrame.VELOCITY &&
  233. defined(velocity)
  234. ) {
  235. const rotation = Transforms.rotationMatrixFromPositionVelocity(
  236. cartesian,
  237. velocity,
  238. ellipsoid,
  239. rotationScratch,
  240. );
  241. Matrix4.fromRotationTranslation(rotation, cartesian, transform);
  242. } else if (
  243. trackingReferenceFrame === TrackingReferenceFrame.ENU ||
  244. !hasBasis
  245. ) {
  246. Transforms.eastNorthUpToFixedFrame(cartesian, ellipsoid, transform);
  247. } else {
  248. transform[0] = xBasis.x;
  249. transform[1] = xBasis.y;
  250. transform[2] = xBasis.z;
  251. transform[3] = 0.0;
  252. transform[4] = yBasis.x;
  253. transform[5] = yBasis.y;
  254. transform[6] = yBasis.z;
  255. transform[7] = 0.0;
  256. transform[8] = zBasis.x;
  257. transform[9] = zBasis.y;
  258. transform[10] = zBasis.z;
  259. transform[11] = 0.0;
  260. transform[12] = cartesian.x;
  261. transform[13] = cartesian.y;
  262. transform[14] = cartesian.z;
  263. transform[15] = 0.0;
  264. }
  265. camera._setTransform(transform);
  266. if (saveCamera) {
  267. Cartesian3.clone(position, camera.position);
  268. Cartesian3.clone(direction, camera.direction);
  269. Cartesian3.clone(up, camera.up);
  270. Cartesian3.cross(direction, up, camera.right);
  271. }
  272. }
  273. if (updateLookAt) {
  274. const offset =
  275. mode === SceneMode.SCENE2D ||
  276. Cartesian3.equals(that._offset3D, Cartesian3.ZERO)
  277. ? undefined
  278. : that._offset3D;
  279. camera.lookAtTransform(camera.transform, offset);
  280. }
  281. }
  282. /**
  283. * A utility object for tracking an entity with the camera.
  284. * @alias EntityView
  285. * @constructor
  286. *
  287. * @param {Entity} entity The entity to track with the camera.
  288. * @param {Scene} scene The scene to use.
  289. * @param {Ellipsoid} [ellipsoid=Ellipsoid.default] The ellipsoid to use for orienting the camera.
  290. */
  291. function EntityView(entity, scene, ellipsoid) {
  292. //>>includeStart('debug', pragmas.debug);
  293. Check.defined("entity", entity);
  294. Check.defined("scene", scene);
  295. //>>includeEnd('debug');
  296. /**
  297. * The entity to track with the camera.
  298. * @type {Entity}
  299. */
  300. this.entity = entity;
  301. /**
  302. * The scene in which to track the object.
  303. * @type {Scene}
  304. */
  305. this.scene = scene;
  306. /**
  307. * The ellipsoid to use for orienting the camera.
  308. * @type {Ellipsoid}
  309. */
  310. this.ellipsoid = ellipsoid ?? Ellipsoid.default;
  311. /**
  312. * The bounding sphere of the object.
  313. * @type {BoundingSphere}
  314. */
  315. this.boundingSphere = undefined;
  316. // Shadow copies of the objects so we can detect changes.
  317. this._lastEntity = undefined;
  318. this._mode = undefined;
  319. this._lastCartesian = new Cartesian3();
  320. this._defaultOffset3D = undefined;
  321. this._velocityProperty = new VelocityVectorProperty(entity.position, true);
  322. this._offset3D = new Cartesian3();
  323. }
  324. // STATIC properties defined here, not per-instance.
  325. Object.defineProperties(EntityView, {
  326. /**
  327. * Gets or sets a camera offset that will be used to
  328. * initialize subsequent EntityViews.
  329. * @memberof EntityView
  330. * @type {Cartesian3}
  331. */
  332. defaultOffset3D: {
  333. get: function () {
  334. return this._defaultOffset3D;
  335. },
  336. set: function (vector) {
  337. this._defaultOffset3D = Cartesian3.clone(vector, new Cartesian3());
  338. },
  339. },
  340. });
  341. // Initialize the static property.
  342. EntityView.defaultOffset3D = new Cartesian3(-14000, 3500, 3500);
  343. const scratchHeadingPitchRange = new HeadingPitchRange();
  344. const scratchCartesian = new Cartesian3();
  345. /**
  346. * Should be called each animation frame to update the camera
  347. * to the latest settings.
  348. * @param {JulianDate} time The current animation time.
  349. * @param {BoundingSphere} [boundingSphere] bounding sphere of the object.
  350. */
  351. EntityView.prototype.update = function (time, boundingSphere) {
  352. //>>includeStart('debug', pragmas.debug);
  353. Check.defined("time", time);
  354. //>>includeEnd('debug');
  355. const scene = this.scene;
  356. const ellipsoid = this.ellipsoid;
  357. const sceneMode = scene.mode;
  358. if (sceneMode === SceneMode.MORPHING) {
  359. return;
  360. }
  361. const entity = this.entity;
  362. const trackingReferenceFrame = entity.trackingReferenceFrame;
  363. const positionProperty = entity.position;
  364. if (!defined(positionProperty)) {
  365. return;
  366. }
  367. const velocityProperty = this._velocityProperty;
  368. const orientationProperty = entity.orientation;
  369. const objectChanged = entity !== this._lastEntity;
  370. const sceneModeChanged = sceneMode !== this._mode;
  371. const camera = scene.camera;
  372. let updateLookAt = objectChanged || sceneModeChanged;
  373. let saveCamera = true;
  374. if (objectChanged) {
  375. const viewFromProperty = entity.viewFrom;
  376. const hasViewFrom = defined(viewFromProperty);
  377. if (!hasViewFrom && defined(boundingSphere)) {
  378. // The default HPR is not ideal for high altitude objects so
  379. // we scale the pitch as we get further from the earth for a more
  380. // downward view.
  381. scratchHeadingPitchRange.pitch = -CesiumMath.PI_OVER_FOUR;
  382. scratchHeadingPitchRange.range = 0;
  383. const position = positionProperty.getValue(time, scratchCartesian);
  384. if (defined(position)) {
  385. const factor =
  386. 2 -
  387. 1 /
  388. Math.max(
  389. 1,
  390. Cartesian3.magnitude(position) / ellipsoid.maximumRadius,
  391. );
  392. scratchHeadingPitchRange.pitch *= factor;
  393. }
  394. camera.viewBoundingSphere(boundingSphere, scratchHeadingPitchRange);
  395. this.boundingSphere = boundingSphere;
  396. updateLookAt = false;
  397. saveCamera = false;
  398. } else if (
  399. !hasViewFrom ||
  400. !defined(viewFromProperty.getValue(time, this._offset3D))
  401. ) {
  402. Cartesian3.clone(EntityView._defaultOffset3D, this._offset3D);
  403. }
  404. } else if (!sceneModeChanged && this._mode !== SceneMode.SCENE2D) {
  405. Cartesian3.clone(camera.position, this._offset3D);
  406. }
  407. this._lastEntity = entity;
  408. this._mode = sceneMode;
  409. updateTransform(
  410. this,
  411. camera,
  412. updateLookAt,
  413. saveCamera,
  414. positionProperty,
  415. velocityProperty,
  416. orientationProperty,
  417. trackingReferenceFrame,
  418. time,
  419. ellipsoid,
  420. );
  421. };
  422. export default EntityView;