UNPKG

itowns

Version:

A JS/WebGL framework for 3D geospatial data visualization

316 lines (279 loc) 10.9 kB
"use strict"; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = void 0; var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var THREE = _interopRequireWildcard(require("three")); var _proj = _interopRequireDefault(require("proj4")); var _Crs = _interopRequireDefault(require("./Crs")); var _Ellipsoid = _interopRequireDefault(require("../Math/Ellipsoid")); _proj["default"].defs('EPSG:4978', '+proj=geocent +datum=WGS84 +units=m +no_defs'); var ellipsoid = new _Ellipsoid["default"](); var vectorPivot = new THREE.Vector3(); var coordPivot; var projectionCache = {}; function proj4cache(crsIn, crsOut) { if (!projectionCache[crsIn]) { projectionCache[crsIn] = {}; } if (!projectionCache[crsIn][crsOut]) { projectionCache[crsIn][crsOut] = (0, _proj["default"])(crsIn, crsOut); } return projectionCache[crsIn][crsOut]; } // Internal method, takes a coord and put some proj4 values in it function setFromProj4(coord, proj4value, z) { return coord.setFromValues(proj4value[0], proj4value[1], z); } /** * A Coordinates object, defined by a [crs]{@link http://inspire.ec.europa.eu/theme/rs} * and three values. These values are accessible through `x`, `y` and `z`, * although it can also be accessible through `latitude`, `longitude` and * `altitude`. To change a value, prefer the `set()` method below. * * @property {boolean} isCoordinates - Used to checkout whether this coordinates * is a Coordinates. Default is true. You should not change this, as it is used * internally for optimisation. * @property {string} crs - A supported crs by default in * [`proj4js`](https://github.com/proj4js/proj4js#named-projections), or an * added crs to `proj4js` (using `proj4.defs`). Note that `EPSG:4978` is also * supported by default in itowns. * @property {number} x - The first value of the coordinate. * @property {number} y - The second value of the coordinate. * @property {number} z - The third value of the coordinate. * @property {number} latitude - The first value of the coordinate. * @property {number} longitude - The second value of the coordinate. * @property {number} altitude - The third value of the coordinate. * @property {THREE.Vector3} geodesicNormal - The geodesic normal of the * coordinate. * * @example * new Coordinates('EPSG:4978', 20885167, 849862, 23385912); //Geocentric coordinates * * @example * new Coordinates('EPSG:4326', 2.33, 48.24, 24999549); //Geographic coordinates */ var Coordinates = /*#__PURE__*/ function () { /** * @constructor * * @param {string} crs - A supported crs (see the `crs` property below). * @param {number|Array<number>|Coordinates|THREE.Vector3} [v0=0] - * x or longitude value, or a more complex one: it can be an array of three * numbers, being x/lon, x/lat, z/alt, or it can be `THREE.Vector3`. It can * also simply be a Coordinates. * @param {number} [v1=0] - y or latitude value. * @param {number} [v2=0] - z or altitude value. */ function Coordinates(crs) { var v0 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; var v1 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; var v2 = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; (0, _classCallCheck2["default"])(this, Coordinates); this.isCoordinates = true; _Crs["default"].isValid(crs); this.crs = crs; // Storing the coordinates as is, not in arrays, as it is // slower (see https://jsbench.me/40jumfag6g/1) this.x = 0; this.y = 0; this.z = 0; // Normal this._normal = new THREE.Vector3(); if (v0.length > 0) { this.setFromArray(v0); } else if (v0.isVector3 || v0.isCoordinates) { this.setFromVector3(v0); } else { this.setFromValues(v0, v1, v2); } this._normalNeedsUpdate = true; } /** * Set the values of this Coordinates. * * @param {number} [v0=0] - x or longitude value. * @param {number} [v1=0] - y or latitude value. * @param {number} [v2=0] - z or altitude value. * * @return {Coordinates} This Coordinates. */ (0, _createClass2["default"])(Coordinates, [{ key: "setFromValues", value: function setFromValues() { var v0 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; var v1 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; var v2 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; this.x = v0 == undefined ? 0 : v0; this.y = v1 == undefined ? 0 : v1; this.z = v2 == undefined ? 0 : v2; this._normalNeedsUpdate = true; return this; } /** * Set the values of this Coordinates from an array. * * @param {Array<number>} array - An array of number to assign to the * Coordinates. * @param {number} [offset] - Optional offset into the array. * * @return {Coordinates} This Coordinates. */ }, { key: "setFromArray", value: function setFromArray(array) { var offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; return this.setFromValues(array[offset], array[offset + 1], array[offset + 2]); } /** * Set the values of this Coordinates from a `THREE.Vector3` or an `Object` * having `x/y/z` properties, like a `Coordinates`. * * @param {THREE.Vector3|Coordinates} v0 - The object to read the values * from. * * @return {Coordinates} This Coordinates. */ }, { key: "setFromVector3", value: function setFromVector3(v0) { return this.setFromValues(v0.x, v0.y, v0.z); } /** * Returns a new Coordinates with the same values as this one. It will * instantiate a new Coordinates with the same CRS as this one. * * @return {Coordinates} The target with its new coordinates. */ }, { key: "clone", value: function clone() { return new Coordinates(this.crs, this); } /** * Copies the values of the passed Coordinates to this one. The CRS is * however not copied. * * @param {Coordinates} src - The source to copy from. * * @return {Coordinates} This Coordinates. */ }, { key: "copy", value: function copy(src) { this.crs = src.crs; return this.setFromVector3(src); } }, { key: "toVector3", /** * Return this Coordinates values into a `THREE.Vector3`. * * @param {THREE.Vector3} [target] - The target to put the values in. If not * specified, a new vector will be created. * * @return {THREE.Vector3} */ value: function toVector3() { var target = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new THREE.Vector3(); return target.copy(this); } /** * Returns coordinates in the wanted [CRS]{@link http://inspire.ec.europa.eu/theme/rs}. * * @param {string} crs - The CRS to convert the Coordinates into. * @param {Coordinates} [target] - The target to put the converted * Coordinates into. If not specified a new one will be created. * * @return {Coordinates} - The resulting Coordinates after the conversion. * * @example * const position = { longitude: 2.33, latitude: 48.24, altitude: 24999549 }; * const coords = new Coordinates('EPSG:4326', position.longitude, position.latitude, position.altitude); // Geographic system * const coordinates = coords.as('EPSG:4978'); // Geocentric system * * @example * const position = { x: 20885167, y: 849862, z: 23385912 }; * const coords = new Coordinates('EPSG:4978', position.x, position.y, position.z); // Geocentric system * const coordinates = coords.as('EPSG:4326'); // Geographic system * * @example * new Coordinates('EPSG:4326', longitude: 2.33, latitude: 48.24, altitude: 24999549).as('EPSG:4978'); // Geocentric system * * @example * new Coordinates('EPSG:4978', x: 20885167, y: 849862, z: 23385912).as('EPSG:4326'); // Geographic system */ }, { key: "as", value: function as(crs) { var target = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new Coordinates(crs); if (this.crs == crs) { target.copy(this); // there is a bug for converting anything from and to 4978 with proj4 // https://github.com/proj4js/proj4js/issues/195 // the workaround is to use an intermediate projection, like EPSG:4326 } else if (crs == 'EPSG:4978') { if (_Crs["default"].is4326(this.crs)) { ellipsoid.cartographicToCartesian(this, vectorPivot); target.setFromVector3(vectorPivot); } else { setFromProj4(coordPivot, proj4cache(this.crs, 'EPSG:4326').forward([this.x, this.y]), this.z); coordPivot.as('EPSG:4978', target); } } else if (this.crs == 'EPSG:4978') { if (_Crs["default"].is4326(crs)) { ellipsoid.cartesianToCartographic(this, target); } else { this.as('EPSG:4326', coordPivot); setFromProj4(target, proj4cache('EPSG:4326', crs).forward([coordPivot.x, coordPivot.y]), coordPivot.z); } } else if (_Crs["default"].is4326(this.crs) && crs == 'EPSG:3857') { this.y = THREE.Math.clamp(this.y, -89.999999, 89.999999); setFromProj4(target, proj4cache(this.crs, crs).forward([this.x, this.y]), this.z); } else { setFromProj4(target, proj4cache(this.crs, crs).forward([this.x, this.y]), this.z); } target.crs = crs; return target; } }, { key: "longitude", get: function get() { return this.x; } }, { key: "latitude", get: function get() { return this.y; } }, { key: "altitude", get: function get() { return this.z; }, set: function set(value) { this.z = value; } }, { key: "geodesicNormal", get: function get() { if (this._normalNeedsUpdate) { this._normalNeedsUpdate = false; if (_Crs["default"].is4326(this.crs)) { ellipsoid.geodeticSurfaceNormalCartographic(this, this._normal); } else if (this.crs == 'EPSG:4978') { ellipsoid.geodeticSurfaceNormal(this, this._normal); } else { this._normal.set(0, 0, 1); } } return this._normal; } }]); return Coordinates; }(); coordPivot = new Coordinates('EPSG:4326'); var _default = Coordinates; exports["default"] = _default;