Cartographic.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. import Cartesian3 from './Cartesian3.js';
  2. import Check from './Check.js';
  3. import defaultValue from './defaultValue.js';
  4. import defined from './defined.js';
  5. import freezeObject from './freezeObject.js';
  6. import CesiumMath from './Math.js';
  7. import scaleToGeodeticSurface from './scaleToGeodeticSurface.js';
  8. /**
  9. * A position defined by longitude, latitude, and height.
  10. * @alias Cartographic
  11. * @constructor
  12. *
  13. * @param {Number} [longitude=0.0] The longitude, in radians.
  14. * @param {Number} [latitude=0.0] The latitude, in radians.
  15. * @param {Number} [height=0.0] The height, in meters, above the ellipsoid.
  16. *
  17. * @see Ellipsoid
  18. */
  19. function Cartographic(longitude, latitude, height) {
  20. /**
  21. * The longitude, in radians.
  22. * @type {Number}
  23. * @default 0.0
  24. */
  25. this.longitude = defaultValue(longitude, 0.0);
  26. /**
  27. * The latitude, in radians.
  28. * @type {Number}
  29. * @default 0.0
  30. */
  31. this.latitude = defaultValue(latitude, 0.0);
  32. /**
  33. * The height, in meters, above the ellipsoid.
  34. * @type {Number}
  35. * @default 0.0
  36. */
  37. this.height = defaultValue(height, 0.0);
  38. }
  39. /**
  40. * Creates a new Cartographic instance from longitude and latitude
  41. * specified in radians.
  42. *
  43. * @param {Number} longitude The longitude, in radians.
  44. * @param {Number} latitude The latitude, in radians.
  45. * @param {Number} [height=0.0] The height, in meters, above the ellipsoid.
  46. * @param {Cartographic} [result] The object onto which to store the result.
  47. * @returns {Cartographic} The modified result parameter or a new Cartographic instance if one was not provided.
  48. */
  49. Cartographic.fromRadians = function(longitude, latitude, height, result) {
  50. //>>includeStart('debug', pragmas.debug);
  51. Check.typeOf.number('longitude', longitude);
  52. Check.typeOf.number('latitude', latitude);
  53. //>>includeEnd('debug');
  54. height = defaultValue(height, 0.0);
  55. if (!defined(result)) {
  56. return new Cartographic(longitude, latitude, height);
  57. }
  58. result.longitude = longitude;
  59. result.latitude = latitude;
  60. result.height = height;
  61. return result;
  62. };
  63. /**
  64. * Creates a new Cartographic instance from longitude and latitude
  65. * specified in degrees. The values in the resulting object will
  66. * be in radians.
  67. *
  68. * @param {Number} longitude The longitude, in degrees.
  69. * @param {Number} latitude The latitude, in degrees.
  70. * @param {Number} [height=0.0] The height, in meters, above the ellipsoid.
  71. * @param {Cartographic} [result] The object onto which to store the result.
  72. * @returns {Cartographic} The modified result parameter or a new Cartographic instance if one was not provided.
  73. */
  74. Cartographic.fromDegrees = function(longitude, latitude, height, result) {
  75. //>>includeStart('debug', pragmas.debug);
  76. Check.typeOf.number('longitude', longitude);
  77. Check.typeOf.number('latitude', latitude);
  78. //>>includeEnd('debug');
  79. longitude = CesiumMath.toRadians(longitude);
  80. latitude = CesiumMath.toRadians(latitude);
  81. return Cartographic.fromRadians(longitude, latitude, height, result);
  82. };
  83. var cartesianToCartographicN = new Cartesian3();
  84. var cartesianToCartographicP = new Cartesian3();
  85. var cartesianToCartographicH = new Cartesian3();
  86. var wgs84OneOverRadii = new Cartesian3(1.0 / 6378137.0, 1.0 / 6378137.0, 1.0 / 6356752.3142451793);
  87. var wgs84OneOverRadiiSquared = new Cartesian3(1.0 / (6378137.0 * 6378137.0), 1.0 / (6378137.0 * 6378137.0), 1.0 / (6356752.3142451793 * 6356752.3142451793));
  88. var wgs84CenterToleranceSquared = CesiumMath.EPSILON1;
  89. /**
  90. * Creates a new Cartographic instance from a Cartesian position. The values in the
  91. * resulting object will be in radians.
  92. *
  93. * @param {Cartesian3} cartesian The Cartesian position to convert to cartographic representation.
  94. * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the position lies.
  95. * @param {Cartographic} [result] The object onto which to store the result.
  96. * @returns {Cartographic} The modified result parameter, new Cartographic instance if none was provided, or undefined if the cartesian is at the center of the ellipsoid.
  97. */
  98. Cartographic.fromCartesian = function(cartesian, ellipsoid, result) {
  99. var oneOverRadii = defined(ellipsoid) ? ellipsoid.oneOverRadii : wgs84OneOverRadii;
  100. var oneOverRadiiSquared = defined(ellipsoid) ? ellipsoid.oneOverRadiiSquared : wgs84OneOverRadiiSquared;
  101. var centerToleranceSquared = defined(ellipsoid) ? ellipsoid._centerToleranceSquared : wgs84CenterToleranceSquared;
  102. //`cartesian is required.` is thrown from scaleToGeodeticSurface
  103. var p = scaleToGeodeticSurface(cartesian, oneOverRadii, oneOverRadiiSquared, centerToleranceSquared, cartesianToCartographicP);
  104. if (!defined(p)) {
  105. return undefined;
  106. }
  107. var n = Cartesian3.multiplyComponents(p, oneOverRadiiSquared, cartesianToCartographicN);
  108. n = Cartesian3.normalize(n, n);
  109. var h = Cartesian3.subtract(cartesian, p, cartesianToCartographicH);
  110. var longitude = Math.atan2(n.y, n.x);
  111. var latitude = Math.asin(n.z);
  112. var height = CesiumMath.sign(Cartesian3.dot(h, cartesian)) * Cartesian3.magnitude(h);
  113. if (!defined(result)) {
  114. return new Cartographic(longitude, latitude, height);
  115. }
  116. result.longitude = longitude;
  117. result.latitude = latitude;
  118. result.height = height;
  119. return result;
  120. };
  121. /**
  122. * Creates a new Cartesian3 instance from a Cartographic input. The values in the inputted
  123. * object should be in radians.
  124. *
  125. * @param {Cartographic} cartographic Input to be converted into a Cartesian3 output.
  126. * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the position lies.
  127. * @param {Cartesian3} [result] The object onto which to store the result.
  128. * @returns {Cartesian3} The position
  129. */
  130. Cartographic.toCartesian = function(cartographic, ellipsoid, result) {
  131. //>>includeStart('debug', pragmas.debug);
  132. Check.defined('cartographic', cartographic);
  133. //>>includeEnd('debug');
  134. return Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, cartographic.height, ellipsoid, result);
  135. };
  136. /**
  137. * Duplicates a Cartographic instance.
  138. *
  139. * @param {Cartographic} cartographic The cartographic to duplicate.
  140. * @param {Cartographic} [result] The object onto which to store the result.
  141. * @returns {Cartographic} The modified result parameter or a new Cartographic instance if one was not provided. (Returns undefined if cartographic is undefined)
  142. */
  143. Cartographic.clone = function(cartographic, result) {
  144. if (!defined(cartographic)) {
  145. return undefined;
  146. }
  147. if (!defined(result)) {
  148. return new Cartographic(cartographic.longitude, cartographic.latitude, cartographic.height);
  149. }
  150. result.longitude = cartographic.longitude;
  151. result.latitude = cartographic.latitude;
  152. result.height = cartographic.height;
  153. return result;
  154. };
  155. /**
  156. * Compares the provided cartographics componentwise and returns
  157. * <code>true</code> if they are equal, <code>false</code> otherwise.
  158. *
  159. * @param {Cartographic} [left] The first cartographic.
  160. * @param {Cartographic} [right] The second cartographic.
  161. * @returns {Boolean} <code>true</code> if left and right are equal, <code>false</code> otherwise.
  162. */
  163. Cartographic.equals = function(left, right) {
  164. return (left === right) ||
  165. ((defined(left)) &&
  166. (defined(right)) &&
  167. (left.longitude === right.longitude) &&
  168. (left.latitude === right.latitude) &&
  169. (left.height === right.height));
  170. };
  171. /**
  172. * Compares the provided cartographics componentwise and returns
  173. * <code>true</code> if they are within the provided epsilon,
  174. * <code>false</code> otherwise.
  175. *
  176. * @param {Cartographic} [left] The first cartographic.
  177. * @param {Cartographic} [right] The second cartographic.
  178. * @param {Number} epsilon The epsilon to use for equality testing.
  179. * @returns {Boolean} <code>true</code> if left and right are within the provided epsilon, <code>false</code> otherwise.
  180. */
  181. Cartographic.equalsEpsilon = function(left, right, epsilon) {
  182. //>>includeStart('debug', pragmas.debug);
  183. Check.typeOf.number('epsilon', epsilon);
  184. //>>includeEnd('debug');
  185. return (left === right) ||
  186. ((defined(left)) &&
  187. (defined(right)) &&
  188. (Math.abs(left.longitude - right.longitude) <= epsilon) &&
  189. (Math.abs(left.latitude - right.latitude) <= epsilon) &&
  190. (Math.abs(left.height - right.height) <= epsilon));
  191. };
  192. /**
  193. * An immutable Cartographic instance initialized to (0.0, 0.0, 0.0).
  194. *
  195. * @type {Cartographic}
  196. * @constant
  197. */
  198. Cartographic.ZERO = freezeObject(new Cartographic(0.0, 0.0, 0.0));
  199. /**
  200. * Duplicates this instance.
  201. *
  202. * @param {Cartographic} [result] The object onto which to store the result.
  203. * @returns {Cartographic} The modified result parameter or a new Cartographic instance if one was not provided.
  204. */
  205. Cartographic.prototype.clone = function(result) {
  206. return Cartographic.clone(this, result);
  207. };
  208. /**
  209. * Compares the provided against this cartographic componentwise and returns
  210. * <code>true</code> if they are equal, <code>false</code> otherwise.
  211. *
  212. * @param {Cartographic} [right] The second cartographic.
  213. * @returns {Boolean} <code>true</code> if left and right are equal, <code>false</code> otherwise.
  214. */
  215. Cartographic.prototype.equals = function(right) {
  216. return Cartographic.equals(this, right);
  217. };
  218. /**
  219. * Compares the provided against this cartographic componentwise and returns
  220. * <code>true</code> if they are within the provided epsilon,
  221. * <code>false</code> otherwise.
  222. *
  223. * @param {Cartographic} [right] The second cartographic.
  224. * @param {Number} epsilon The epsilon to use for equality testing.
  225. * @returns {Boolean} <code>true</code> if left and right are within the provided epsilon, <code>false</code> otherwise.
  226. */
  227. Cartographic.prototype.equalsEpsilon = function(right, epsilon) {
  228. return Cartographic.equalsEpsilon(this, right, epsilon);
  229. };
  230. /**
  231. * Creates a string representing this cartographic in the format '(longitude, latitude, height)'.
  232. *
  233. * @returns {String} A string representing the provided cartographic in the format '(longitude, latitude, height)'.
  234. */
  235. Cartographic.prototype.toString = function() {
  236. return '(' + this.longitude + ', ' + this.latitude + ', ' + this.height + ')';
  237. };
  238. export default Cartographic;