UNPKG

itowns

Version:

A JS/WebGL framework for 3D geospatial data visualization

187 lines (156 loc) 8.86 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof = require("@babel/runtime/helpers/typeof"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = exports.ellipsoidSizes = 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 _Coordinates = _interopRequireDefault(require("../Geographic/Coordinates")); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; } var ellipsoidSizes = new THREE.Vector3(_proj["default"].WGS84.a, _proj["default"].WGS84.a, _proj["default"].WGS84.b); exports.ellipsoidSizes = ellipsoidSizes; var normal = new THREE.Vector3(); var Ellipsoid = /*#__PURE__*/function () { function Ellipsoid() { var size = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ellipsoidSizes; (0, _classCallCheck2["default"])(this, Ellipsoid); this.size = new THREE.Vector3(); this._radiiSquared = new THREE.Vector3(); this._invRadiiSquared = new THREE.Vector3(); this.setSize(size); } (0, _createClass2["default"])(Ellipsoid, [{ key: "geodeticSurfaceNormal", value: function geodeticSurfaceNormal(cartesian) { var target = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new THREE.Vector3(); return cartesian.toVector3(target).multiply(this._invRadiiSquared).normalize(); } }, { key: "geodeticSurfaceNormalCartographic", value: function geodeticSurfaceNormalCartographic(coordCarto) { var target = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new THREE.Vector3(); var longitude = THREE.MathUtils.degToRad(coordCarto.longitude); var latitude = THREE.MathUtils.degToRad(coordCarto.latitude); var cosLatitude = Math.cos(latitude); return target.set(cosLatitude * Math.cos(longitude), cosLatitude * Math.sin(longitude), Math.sin(latitude)); } }, { key: "setSize", value: function setSize(size) { this.size.set(size.x, size.y, size.z); this._radiiSquared.multiplyVectors(size, size); this._invRadiiSquared.x = size.x == 0 ? 0 : 1 / this._radiiSquared.x; this._invRadiiSquared.y = size.y == 0 ? 0 : 1 / this._radiiSquared.y; this._invRadiiSquared.z = size.z == 0 ? 0 : 1 / this._radiiSquared.z; } }, { key: "cartographicToCartesian", value: function cartographicToCartesian(coordCarto) { var target = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new THREE.Vector3(); normal.copy(coordCarto.geodesicNormal); target.multiplyVectors(this._radiiSquared, normal); var gamma = Math.sqrt(normal.dot(target)); target.divideScalar(gamma); normal.multiplyScalar(coordCarto.altitude); return target.add(normal); } /** * Convert cartesian coordinates to geographic according to the current ellipsoid of revolution. * @param {Object} position - The coordinate to convert * @param {number} position.x * @param {number} position.y * @param {number} position.z * @param {Coordinate} [target] coordinate to copy result * @returns {Coordinate} an object describing the coordinates on the reference ellipsoid, angles are in degree */ }, { key: "cartesianToCartographic", value: function cartesianToCartographic(position) { var target = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new _Coordinates["default"]('EPSG:4326', 0, 0, 0); // for details, see for example http://www.linz.govt.nz/data/geodetic-system/coordinate-conversion/geodetic-datum-conversions/equations-used-datum // TODO the following is only valable for oblate ellipsoid of revolution. do we want to support triaxial ellipsoid? var R = Math.sqrt(position.x * position.x + position.y * position.y + position.z * position.z); var a = this.size.x; // x var b = this.size.z; // z var e = Math.abs((a * a - b * b) / (a * a)); var f = 1 - Math.sqrt(1 - e); var rsqXY = Math.sqrt(position.x * position.x + position.y * position.y); var theta = Math.atan2(position.y, position.x); var nu = Math.atan(position.z / rsqXY * (1 - f + e * a / R)); var sinu = Math.sin(nu); var cosu = Math.cos(nu); var phi = Math.atan((position.z * (1 - f) + e * a * sinu * sinu * sinu) / ((1 - f) * (rsqXY - e * a * cosu * cosu * cosu))); var h = rsqXY * Math.cos(phi) + position.z * Math.sin(phi) - a * Math.sqrt(1 - e * Math.sin(phi) * Math.sin(phi)); return target.setFromValues(THREE.MathUtils.radToDeg(theta), THREE.MathUtils.radToDeg(phi), h); } }, { key: "cartographicToCartesianArray", value: function cartographicToCartesianArray(coordCartoArray) { var cartesianArray = []; for (var i = 0; i < coordCartoArray.length; i++) { cartesianArray.push(this.cartographicToCartesian(coordCartoArray[i])); } return cartesianArray; } }, { key: "intersection", value: function intersection(ray) { var EPSILON = 0.0001; var O_C = ray.origin; var dir = ray.direction; // normalizeVector( dir ); var a = dir.x * dir.x * this._invRadiiSquared.x + dir.y * dir.y * this._invRadiiSquared.y + dir.z * dir.z * this._invRadiiSquared.z; var b = 2 * O_C.x * dir.x * this._invRadiiSquared.x + 2 * O_C.y * dir.y * this._invRadiiSquared.y + 2 * O_C.z * dir.z * this._invRadiiSquared.z; var c = O_C.x * O_C.x * this._invRadiiSquared.x + O_C.y * O_C.y * this._invRadiiSquared.y + O_C.z * O_C.z * this._invRadiiSquared.z - 1; var d = b * b - 4 * a * c; if (d < 0 || a === 0 || b === 0 || c === 0) { return false; } d = Math.sqrt(d); var t1 = (-b + d) / (2 * a); var t2 = (-b - d) / (2 * a); if (t1 <= EPSILON && t2 <= EPSILON) { return false; } // both intersections are behind the ray origin // var back = (t1 <= EPSILON || t2 <= EPSILON); // If only one intersection (t>0) then we are inside the ellipsoid and the intersection is at the back of the ellipsoid var t = 0; if (t1 <= EPSILON) { t = t2; } else if (t2 <= EPSILON) { t = t1; } else { t = t1 < t2 ? t1 : t2; } if (t < EPSILON) { return false; } // Too close to intersection var inter = new THREE.Vector3(); inter.addVectors(ray.origin, dir.clone().setLength(t)); return inter; } }, { key: "computeDistance", value: function computeDistance(coordCarto1, coordCarto2) { var longitude1 = THREE.MathUtils.degToRad(coordCarto1.longitude); var latitude1 = THREE.MathUtils.degToRad(coordCarto1.latitude); var longitude2 = THREE.MathUtils.degToRad(coordCarto2.longitude); var latitude2 = THREE.MathUtils.degToRad(coordCarto2.latitude); var distRad = Math.acos(Math.sin(latitude1) * Math.sin(latitude2) + Math.cos(latitude1) * Math.cos(latitude2) * Math.cos(longitude2 - longitude1)); var a = this.size.x; var b = this.size.z; var e = Math.sqrt((a * a - b * b) / (a * a)); var latMoy = (latitude1 + latitude2) / 2; var rho = a * (1 - e * e) / Math.sqrt(1 - e * e * Math.sin(latMoy) * Math.sin(latMoy)); var N = a / Math.sqrt(1 - e * e * Math.sin(latMoy) * Math.sin(latMoy)); var distMeter = distRad * Math.sqrt(rho * N); return distMeter; } }]); return Ellipsoid; }(); var _default = Ellipsoid; exports["default"] = _default;