HeadingPitchRoll.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. import defaultValue from "./defaultValue.js";
  2. import defined from "./defined.js";
  3. import DeveloperError from "./DeveloperError.js";
  4. import CesiumMath from "./Math.js";
  5. /**
  6. * A rotation expressed as a heading, pitch, and roll. Heading is the rotation about the
  7. * negative z axis. Pitch is the rotation about the negative y axis. Roll is the rotation about
  8. * the positive x axis.
  9. * @alias HeadingPitchRoll
  10. * @constructor
  11. *
  12. * @param {number} [heading=0.0] The heading component in radians.
  13. * @param {number} [pitch=0.0] The pitch component in radians.
  14. * @param {number} [roll=0.0] The roll component in radians.
  15. */
  16. function HeadingPitchRoll(heading, pitch, roll) {
  17. /**
  18. * Gets or sets the heading.
  19. * @type {number}
  20. * @default 0.0
  21. */
  22. this.heading = defaultValue(heading, 0.0);
  23. /**
  24. * Gets or sets the pitch.
  25. * @type {number}
  26. * @default 0.0
  27. */
  28. this.pitch = defaultValue(pitch, 0.0);
  29. /**
  30. * Gets or sets the roll.
  31. * @type {number}
  32. * @default 0.0
  33. */
  34. this.roll = defaultValue(roll, 0.0);
  35. }
  36. /**
  37. * Computes the heading, pitch and roll from a quaternion (see http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles )
  38. *
  39. * @param {Quaternion} quaternion The quaternion from which to retrieve heading, pitch, and roll, all expressed in radians.
  40. * @param {HeadingPitchRoll} [result] The object in which to store the result. If not provided, a new instance is created and returned.
  41. * @returns {HeadingPitchRoll} The modified result parameter or a new HeadingPitchRoll instance if one was not provided.
  42. */
  43. HeadingPitchRoll.fromQuaternion = function (quaternion, result) {
  44. //>>includeStart('debug', pragmas.debug);
  45. if (!defined(quaternion)) {
  46. throw new DeveloperError("quaternion is required");
  47. }
  48. //>>includeEnd('debug');
  49. if (!defined(result)) {
  50. result = new HeadingPitchRoll();
  51. }
  52. const test = 2 * (quaternion.w * quaternion.y - quaternion.z * quaternion.x);
  53. const denominatorRoll =
  54. 1 - 2 * (quaternion.x * quaternion.x + quaternion.y * quaternion.y);
  55. const numeratorRoll =
  56. 2 * (quaternion.w * quaternion.x + quaternion.y * quaternion.z);
  57. const denominatorHeading =
  58. 1 - 2 * (quaternion.y * quaternion.y + quaternion.z * quaternion.z);
  59. const numeratorHeading =
  60. 2 * (quaternion.w * quaternion.z + quaternion.x * quaternion.y);
  61. result.heading = -Math.atan2(numeratorHeading, denominatorHeading);
  62. result.roll = Math.atan2(numeratorRoll, denominatorRoll);
  63. result.pitch = -CesiumMath.asinClamped(test);
  64. return result;
  65. };
  66. /**
  67. * Returns a new HeadingPitchRoll instance from angles given in degrees.
  68. *
  69. * @param {number} heading the heading in degrees
  70. * @param {number} pitch the pitch in degrees
  71. * @param {number} roll the heading in degrees
  72. * @param {HeadingPitchRoll} [result] The object in which to store the result. If not provided, a new instance is created and returned.
  73. * @returns {HeadingPitchRoll} A new HeadingPitchRoll instance
  74. */
  75. HeadingPitchRoll.fromDegrees = function (heading, pitch, roll, result) {
  76. //>>includeStart('debug', pragmas.debug);
  77. if (!defined(heading)) {
  78. throw new DeveloperError("heading is required");
  79. }
  80. if (!defined(pitch)) {
  81. throw new DeveloperError("pitch is required");
  82. }
  83. if (!defined(roll)) {
  84. throw new DeveloperError("roll is required");
  85. }
  86. //>>includeEnd('debug');
  87. if (!defined(result)) {
  88. result = new HeadingPitchRoll();
  89. }
  90. result.heading = heading * CesiumMath.RADIANS_PER_DEGREE;
  91. result.pitch = pitch * CesiumMath.RADIANS_PER_DEGREE;
  92. result.roll = roll * CesiumMath.RADIANS_PER_DEGREE;
  93. return result;
  94. };
  95. /**
  96. * Duplicates a HeadingPitchRoll instance.
  97. *
  98. * @param {HeadingPitchRoll} headingPitchRoll The HeadingPitchRoll to duplicate.
  99. * @param {HeadingPitchRoll} [result] The object onto which to store the result.
  100. * @returns {HeadingPitchRoll} The modified result parameter or a new HeadingPitchRoll instance if one was not provided. (Returns undefined if headingPitchRoll is undefined)
  101. */
  102. HeadingPitchRoll.clone = function (headingPitchRoll, result) {
  103. if (!defined(headingPitchRoll)) {
  104. return undefined;
  105. }
  106. if (!defined(result)) {
  107. return new HeadingPitchRoll(
  108. headingPitchRoll.heading,
  109. headingPitchRoll.pitch,
  110. headingPitchRoll.roll
  111. );
  112. }
  113. result.heading = headingPitchRoll.heading;
  114. result.pitch = headingPitchRoll.pitch;
  115. result.roll = headingPitchRoll.roll;
  116. return result;
  117. };
  118. /**
  119. * Compares the provided HeadingPitchRolls componentwise and returns
  120. * <code>true</code> if they are equal, <code>false</code> otherwise.
  121. *
  122. * @param {HeadingPitchRoll} [left] The first HeadingPitchRoll.
  123. * @param {HeadingPitchRoll} [right] The second HeadingPitchRoll.
  124. * @returns {boolean} <code>true</code> if left and right are equal, <code>false</code> otherwise.
  125. */
  126. HeadingPitchRoll.equals = function (left, right) {
  127. return (
  128. left === right ||
  129. (defined(left) &&
  130. defined(right) &&
  131. left.heading === right.heading &&
  132. left.pitch === right.pitch &&
  133. left.roll === right.roll)
  134. );
  135. };
  136. /**
  137. * Compares the provided HeadingPitchRolls componentwise and returns
  138. * <code>true</code> if they pass an absolute or relative tolerance test,
  139. * <code>false</code> otherwise.
  140. *
  141. * @param {HeadingPitchRoll} [left] The first HeadingPitchRoll.
  142. * @param {HeadingPitchRoll} [right] The second HeadingPitchRoll.
  143. * @param {number} [relativeEpsilon=0] The relative epsilon tolerance to use for equality testing.
  144. * @param {number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing.
  145. * @returns {boolean} <code>true</code> if left and right are within the provided epsilon, <code>false</code> otherwise.
  146. */
  147. HeadingPitchRoll.equalsEpsilon = function (
  148. left,
  149. right,
  150. relativeEpsilon,
  151. absoluteEpsilon
  152. ) {
  153. return (
  154. left === right ||
  155. (defined(left) &&
  156. defined(right) &&
  157. CesiumMath.equalsEpsilon(
  158. left.heading,
  159. right.heading,
  160. relativeEpsilon,
  161. absoluteEpsilon
  162. ) &&
  163. CesiumMath.equalsEpsilon(
  164. left.pitch,
  165. right.pitch,
  166. relativeEpsilon,
  167. absoluteEpsilon
  168. ) &&
  169. CesiumMath.equalsEpsilon(
  170. left.roll,
  171. right.roll,
  172. relativeEpsilon,
  173. absoluteEpsilon
  174. ))
  175. );
  176. };
  177. /**
  178. * Duplicates this HeadingPitchRoll instance.
  179. *
  180. * @param {HeadingPitchRoll} [result] The object onto which to store the result.
  181. * @returns {HeadingPitchRoll} The modified result parameter or a new HeadingPitchRoll instance if one was not provided.
  182. */
  183. HeadingPitchRoll.prototype.clone = function (result) {
  184. return HeadingPitchRoll.clone(this, result);
  185. };
  186. /**
  187. * Compares this HeadingPitchRoll against the provided HeadingPitchRoll componentwise and returns
  188. * <code>true</code> if they are equal, <code>false</code> otherwise.
  189. *
  190. * @param {HeadingPitchRoll} [right] The right hand side HeadingPitchRoll.
  191. * @returns {boolean} <code>true</code> if they are equal, <code>false</code> otherwise.
  192. */
  193. HeadingPitchRoll.prototype.equals = function (right) {
  194. return HeadingPitchRoll.equals(this, right);
  195. };
  196. /**
  197. * Compares this HeadingPitchRoll against the provided HeadingPitchRoll componentwise and returns
  198. * <code>true</code> if they pass an absolute or relative tolerance test,
  199. * <code>false</code> otherwise.
  200. *
  201. * @param {HeadingPitchRoll} [right] The right hand side HeadingPitchRoll.
  202. * @param {number} [relativeEpsilon=0] The relative epsilon tolerance to use for equality testing.
  203. * @param {number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing.
  204. * @returns {boolean} <code>true</code> if they are within the provided epsilon, <code>false</code> otherwise.
  205. */
  206. HeadingPitchRoll.prototype.equalsEpsilon = function (
  207. right,
  208. relativeEpsilon,
  209. absoluteEpsilon
  210. ) {
  211. return HeadingPitchRoll.equalsEpsilon(
  212. this,
  213. right,
  214. relativeEpsilon,
  215. absoluteEpsilon
  216. );
  217. };
  218. /**
  219. * Creates a string representing this HeadingPitchRoll in the format '(heading, pitch, roll)' in radians.
  220. *
  221. * @returns {string} A string representing the provided HeadingPitchRoll in the format '(heading, pitch, roll)'.
  222. */
  223. HeadingPitchRoll.prototype.toString = function () {
  224. return `(${this.heading}, ${this.pitch}, ${this.roll})`;
  225. };
  226. export default HeadingPitchRoll;