function fromCartesian(cartesian) {
const oneOverRadii = {
x: 1.0 / 6378137.0,
y: 1.0 / 6378137.0,
z: 1.0 / 6356752.3142451793
};
const oneOverRadiiSquared = {
x: 1.0 / (6378137.0 * 6378137.0),
y: 1.0 / (6378137.0 * 6378137.0),
z: 1.0 / (6356752.3142451793 * 6356752.3142451793)
};
const p = scaleToGeodeticSurface(
cartesian,
oneOverRadii,
oneOverRadiiSquared,
0.1
);
if (!(p !== undefined && p !== null)) {
return undefined;
}
let n = {
x: p.x * oneOverRadiiSquared.x,
y: p.y * oneOverRadiiSquared.y,
z: p.z * oneOverRadiiSquared.z
};
const m1 = magnitude(n);
n = {
x: n.x / m1,
y: n.y / m1,
z: n.z / m1
};
const h = {
x: cartesian.x - p.x,
y: cartesian.y - p.y,
z: cartesian.z - p.z
};
const longitude = Math.atan2(n.y, n.x);
const latitude = Math.asin(n.z);
const height =
Math.sign(h.x * cartesian.x + h.y * cartesian.y + h.z * cartesian.z) *
magnitude(h);
let result = {};
result.longitude = (longitude * 180.0) / Math.PI;
result.latitude = (latitude * 180.0) / Math.PI;
result.height = height;
return result;
}
function scaleToGeodeticSurface(
cartesian,
oneOverRadii,
oneOverRadiiSquared,
centerToleranceSquared
) {
const positionX = cartesian.x;
const positionY = cartesian.y;
const positionZ = cartesian.z;
const oneOverRadiiX = oneOverRadii.x;
const oneOverRadiiY = oneOverRadii.y;
const oneOverRadiiZ = oneOverRadii.z;
const x2 = positionX * positionX * oneOverRadiiX * oneOverRadiiX;
const y2 = positionY * positionY * oneOverRadiiY * oneOverRadiiY;
const z2 = positionZ * positionZ * oneOverRadiiZ * oneOverRadiiZ;
// Compute the squared ellipsoid norm.
const squaredNorm = x2 + y2 + z2;
const ratio = Math.sqrt(1.0 / squaredNorm);
// As an initial approximation, assume that the radial intersection is the projection point.
const intersection = {
x: cartesian.x * ratio,
y: cartesian.y * ratio,
z: cartesian.z * ratio
};
// If the position is near the center, the iteration will not converge.
if (squaredNorm < centerToleranceSquared) {
return !isFinite(ratio) ? undefined : intersection;
}
const oneOverRadiiSquaredX = oneOverRadiiSquared.x;
const oneOverRadiiSquaredY = oneOverRadiiSquared.y;
const oneOverRadiiSquaredZ = oneOverRadiiSquared.z;
// Use the gradient at the intersection point in place of the true unit normal.
// The difference in magnitude will be absorbed in the multiplier.
const gradient = {
x: intersection.x * oneOverRadiiSquaredX * 2.0,
y: intersection.y * oneOverRadiiSquaredY * 2.0,
z: intersection.z * oneOverRadiiSquaredZ * 2.0
};
// Compute the initial guess at the normal vector multiplier, lambda.
let lambda =
((1.0 - ratio) * magnitude(cartesian)) / (0.5 * magnitude(gradient));
let correction = 0.0;
let func;
let denominator;
let xMultiplier;
let yMultiplier;
let zMultiplier;
let xMultiplier2;
let yMultiplier2;
let zMultiplier2;
let xMultiplier3;
let yMultiplier3;
let zMultiplier3;
do {
lambda -= correction;
xMultiplier = 1.0 / (1.0 + lambda * oneOverRadiiSquaredX);
yMultiplier = 1.0 / (1.0 + lambda * oneOverRadiiSquaredY);
zMultiplier = 1.0 / (1.0 + lambda * oneOverRadiiSquaredZ);
xMultiplier2 = xMultiplier * xMultiplier;
yMultiplier2 = yMultiplier * yMultiplier;
zMultiplier2 = zMultiplier * zMultiplier;
xMultiplier3 = xMultiplier2 * xMultiplier;
yMultiplier3 = yMultiplier2 * yMultiplier;
zMultiplier3 = zMultiplier2 * zMultiplier;
func = x2 * xMultiplier2 + y2 * yMultiplier2 + z2 * zMultiplier2 - 1.0;
// "denominator" here refers to the use of this expression in the velocity and acceleration
// computations in the sections to follow.
denominator =
x2 * xMultiplier3 * oneOverRadiiSquaredX +
y2 * yMultiplier3 * oneOverRadiiSquaredY +
z2 * zMultiplier3 * oneOverRadiiSquaredZ;
const derivative = -2.0 * denominator;
correction = func / derivative;
} while (Math.abs(func) > 0.000000000001);
// if (!(result !== undefined && result !== null)) {
// return new Cartesian3(
// positionX * xMultiplier,
// positionY * yMultiplier,
// positionZ * zMultiplier
// );
// }
let result = {
x: positionX * xMultiplier,
y: positionY * yMultiplier,
z: positionZ * zMultiplier
};
return result;
}
function magnitude(cartesian) {
return Math.sqrt(
cartesian.x * cartesian.x +
cartesian.y * cartesian.y +
cartesian.z * cartesian.z
);
}
fromCartesian({x:-2307065.8,y:5418833.5,z:2440308.2})