itowns
Version:
A JS/WebGL framework for 3D geospatial data visualization
187 lines (156 loc) • 8.86 kB
JavaScript
"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;