import Cartesian3 from './Cartesian3.js'; import Check from './Check.js'; import defaultValue from './defaultValue.js'; import defined from './defined.js'; import freezeObject from './freezeObject.js'; import CesiumMath from './Math.js'; import scaleToGeodeticSurface from './scaleToGeodeticSurface.js'; /** * A position defined by longitude, latitude, and height. * @alias Cartographic * @constructor * * @param {Number} [longitude=0.0] The longitude, in radians. * @param {Number} [latitude=0.0] The latitude, in radians. * @param {Number} [height=0.0] The height, in meters, above the ellipsoid. * * @see Ellipsoid */ function Cartographic(longitude, latitude, height) { /** * The longitude, in radians. * @type {Number} * @default 0.0 */ this.longitude = defaultValue(longitude, 0.0); /** * The latitude, in radians. * @type {Number} * @default 0.0 */ this.latitude = defaultValue(latitude, 0.0); /** * The height, in meters, above the ellipsoid. * @type {Number} * @default 0.0 */ this.height = defaultValue(height, 0.0); } /** * Creates a new Cartographic instance from longitude and latitude * specified in radians. * * @param {Number} longitude The longitude, in radians. * @param {Number} latitude The latitude, in radians. * @param {Number} [height=0.0] The height, in meters, above the ellipsoid. * @param {Cartographic} [result] The object onto which to store the result. * @returns {Cartographic} The modified result parameter or a new Cartographic instance if one was not provided. */ Cartographic.fromRadians = function(longitude, latitude, height, result) { //>>includeStart('debug', pragmas.debug); Check.typeOf.number('longitude', longitude); Check.typeOf.number('latitude', latitude); //>>includeEnd('debug'); height = defaultValue(height, 0.0); if (!defined(result)) { return new Cartographic(longitude, latitude, height); } result.longitude = longitude; result.latitude = latitude; result.height = height; return result; }; /** * Creates a new Cartographic instance from longitude and latitude * specified in degrees. The values in the resulting object will * be in radians. * * @param {Number} longitude The longitude, in degrees. * @param {Number} latitude The latitude, in degrees. * @param {Number} [height=0.0] The height, in meters, above the ellipsoid. * @param {Cartographic} [result] The object onto which to store the result. * @returns {Cartographic} The modified result parameter or a new Cartographic instance if one was not provided. */ Cartographic.fromDegrees = function(longitude, latitude, height, result) { //>>includeStart('debug', pragmas.debug); Check.typeOf.number('longitude', longitude); Check.typeOf.number('latitude', latitude); //>>includeEnd('debug'); longitude = CesiumMath.toRadians(longitude); latitude = CesiumMath.toRadians(latitude); return Cartographic.fromRadians(longitude, latitude, height, result); }; var cartesianToCartographicN = new Cartesian3(); var cartesianToCartographicP = new Cartesian3(); var cartesianToCartographicH = new Cartesian3(); var wgs84OneOverRadii = new Cartesian3(1.0 / 6378137.0, 1.0 / 6378137.0, 1.0 / 6356752.3142451793); var wgs84OneOverRadiiSquared = new Cartesian3(1.0 / (6378137.0 * 6378137.0), 1.0 / (6378137.0 * 6378137.0), 1.0 / (6356752.3142451793 * 6356752.3142451793)); var wgs84CenterToleranceSquared = CesiumMath.EPSILON1; /** * Creates a new Cartographic instance from a Cartesian position. The values in the * resulting object will be in radians. * * @param {Cartesian3} cartesian The Cartesian position to convert to cartographic representation. * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the position lies. * @param {Cartographic} [result] The object onto which to store the result. * @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. */ Cartographic.fromCartesian = function(cartesian, ellipsoid, result) { var oneOverRadii = defined(ellipsoid) ? ellipsoid.oneOverRadii : wgs84OneOverRadii; var oneOverRadiiSquared = defined(ellipsoid) ? ellipsoid.oneOverRadiiSquared : wgs84OneOverRadiiSquared; var centerToleranceSquared = defined(ellipsoid) ? ellipsoid._centerToleranceSquared : wgs84CenterToleranceSquared; //`cartesian is required.` is thrown from scaleToGeodeticSurface var p = scaleToGeodeticSurface(cartesian, oneOverRadii, oneOverRadiiSquared, centerToleranceSquared, cartesianToCartographicP); if (!defined(p)) { return undefined; } var n = Cartesian3.multiplyComponents(p, oneOverRadiiSquared, cartesianToCartographicN); n = Cartesian3.normalize(n, n); var h = Cartesian3.subtract(cartesian, p, cartesianToCartographicH); var longitude = Math.atan2(n.y, n.x); var latitude = Math.asin(n.z); var height = CesiumMath.sign(Cartesian3.dot(h, cartesian)) * Cartesian3.magnitude(h); if (!defined(result)) { return new Cartographic(longitude, latitude, height); } result.longitude = longitude; result.latitude = latitude; result.height = height; return result; }; /** * Creates a new Cartesian3 instance from a Cartographic input. The values in the inputted * object should be in radians. * * @param {Cartographic} cartographic Input to be converted into a Cartesian3 output. * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the position lies. * @param {Cartesian3} [result] The object onto which to store the result. * @returns {Cartesian3} The position */ Cartographic.toCartesian = function(cartographic, ellipsoid, result) { //>>includeStart('debug', pragmas.debug); Check.defined('cartographic', cartographic); //>>includeEnd('debug'); return Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, cartographic.height, ellipsoid, result); }; /** * Duplicates a Cartographic instance. * * @param {Cartographic} cartographic The cartographic to duplicate. * @param {Cartographic} [result] The object onto which to store the result. * @returns {Cartographic} The modified result parameter or a new Cartographic instance if one was not provided. (Returns undefined if cartographic is undefined) */ Cartographic.clone = function(cartographic, result) { if (!defined(cartographic)) { return undefined; } if (!defined(result)) { return new Cartographic(cartographic.longitude, cartographic.latitude, cartographic.height); } result.longitude = cartographic.longitude; result.latitude = cartographic.latitude; result.height = cartographic.height; return result; }; /** * Compares the provided cartographics componentwise and returns * true if they are equal, false otherwise. * * @param {Cartographic} [left] The first cartographic. * @param {Cartographic} [right] The second cartographic. * @returns {Boolean} true if left and right are equal, false otherwise. */ Cartographic.equals = function(left, right) { return (left === right) || ((defined(left)) && (defined(right)) && (left.longitude === right.longitude) && (left.latitude === right.latitude) && (left.height === right.height)); }; /** * Compares the provided cartographics componentwise and returns * true if they are within the provided epsilon, * false otherwise. * * @param {Cartographic} [left] The first cartographic. * @param {Cartographic} [right] The second cartographic. * @param {Number} epsilon The epsilon to use for equality testing. * @returns {Boolean} true if left and right are within the provided epsilon, false otherwise. */ Cartographic.equalsEpsilon = function(left, right, epsilon) { //>>includeStart('debug', pragmas.debug); Check.typeOf.number('epsilon', epsilon); //>>includeEnd('debug'); return (left === right) || ((defined(left)) && (defined(right)) && (Math.abs(left.longitude - right.longitude) <= epsilon) && (Math.abs(left.latitude - right.latitude) <= epsilon) && (Math.abs(left.height - right.height) <= epsilon)); }; /** * An immutable Cartographic instance initialized to (0.0, 0.0, 0.0). * * @type {Cartographic} * @constant */ Cartographic.ZERO = freezeObject(new Cartographic(0.0, 0.0, 0.0)); /** * Duplicates this instance. * * @param {Cartographic} [result] The object onto which to store the result. * @returns {Cartographic} The modified result parameter or a new Cartographic instance if one was not provided. */ Cartographic.prototype.clone = function(result) { return Cartographic.clone(this, result); }; /** * Compares the provided against this cartographic componentwise and returns * true if they are equal, false otherwise. * * @param {Cartographic} [right] The second cartographic. * @returns {Boolean} true if left and right are equal, false otherwise. */ Cartographic.prototype.equals = function(right) { return Cartographic.equals(this, right); }; /** * Compares the provided against this cartographic componentwise and returns * true if they are within the provided epsilon, * false otherwise. * * @param {Cartographic} [right] The second cartographic. * @param {Number} epsilon The epsilon to use for equality testing. * @returns {Boolean} true if left and right are within the provided epsilon, false otherwise. */ Cartographic.prototype.equalsEpsilon = function(right, epsilon) { return Cartographic.equalsEpsilon(this, right, epsilon); }; /** * Creates a string representing this cartographic in the format '(longitude, latitude, height)'. * * @returns {String} A string representing the provided cartographic in the format '(longitude, latitude, height)'. */ Cartographic.prototype.toString = function() { return '(' + this.longitude + ', ' + this.latitude + ', ' + this.height + ')'; }; export default Cartographic;