You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1132 lines
38 KiB
JavaScript
1132 lines
38 KiB
JavaScript
import when from "../ThirdParty/when.js";
|
|
import Cartesian2 from "./Cartesian2.js";
|
|
import Cartesian3 from "./Cartesian3.js";
|
|
import Cartesian4 from "./Cartesian4.js";
|
|
import Cartographic from "./Cartographic.js";
|
|
import Check from "./Check.js";
|
|
import defaultValue from "./defaultValue.js";
|
|
import defined from "./defined.js";
|
|
import DeveloperError from "./DeveloperError.js";
|
|
import EarthOrientationParameters from "./EarthOrientationParameters.js";
|
|
import EarthOrientationParametersSample from "./EarthOrientationParametersSample.js";
|
|
import Ellipsoid from "./Ellipsoid.js";
|
|
import HeadingPitchRoll from "./HeadingPitchRoll.js";
|
|
import Iau2006XysData from "./Iau2006XysData.js";
|
|
import Iau2006XysSample from "./Iau2006XysSample.js";
|
|
import JulianDate from "./JulianDate.js";
|
|
import CesiumMath from "./Math.js";
|
|
import Matrix3 from "./Matrix3.js";
|
|
import Matrix4 from "./Matrix4.js";
|
|
import Quaternion from "./Quaternion.js";
|
|
import TimeConstants from "./TimeConstants.js";
|
|
|
|
/**
|
|
* Contains functions for transforming positions to various reference frames.
|
|
*
|
|
* @namespace Transforms
|
|
*/
|
|
var Transforms = {};
|
|
|
|
var vectorProductLocalFrame = {
|
|
up: {
|
|
south: "east",
|
|
north: "west",
|
|
west: "south",
|
|
east: "north",
|
|
},
|
|
down: {
|
|
south: "west",
|
|
north: "east",
|
|
west: "north",
|
|
east: "south",
|
|
},
|
|
south: {
|
|
up: "west",
|
|
down: "east",
|
|
west: "down",
|
|
east: "up",
|
|
},
|
|
north: {
|
|
up: "east",
|
|
down: "west",
|
|
west: "up",
|
|
east: "down",
|
|
},
|
|
west: {
|
|
up: "north",
|
|
down: "south",
|
|
north: "down",
|
|
south: "up",
|
|
},
|
|
east: {
|
|
up: "south",
|
|
down: "north",
|
|
north: "up",
|
|
south: "down",
|
|
},
|
|
};
|
|
|
|
var degeneratePositionLocalFrame = {
|
|
north: [-1, 0, 0],
|
|
east: [0, 1, 0],
|
|
up: [0, 0, 1],
|
|
south: [1, 0, 0],
|
|
west: [0, -1, 0],
|
|
down: [0, 0, -1],
|
|
};
|
|
|
|
var localFrameToFixedFrameCache = {};
|
|
|
|
var scratchCalculateCartesian = {
|
|
east: new Cartesian3(),
|
|
north: new Cartesian3(),
|
|
up: new Cartesian3(),
|
|
west: new Cartesian3(),
|
|
south: new Cartesian3(),
|
|
down: new Cartesian3(),
|
|
};
|
|
var scratchFirstCartesian = new Cartesian3();
|
|
var scratchSecondCartesian = new Cartesian3();
|
|
var scratchThirdCartesian = new Cartesian3();
|
|
/**
|
|
* Generates a function that computes a 4x4 transformation matrix from a reference frame
|
|
* centered at the provided origin to the provided ellipsoid's fixed reference frame.
|
|
* @param {String} firstAxis name of the first axis of the local reference frame. Must be
|
|
* 'east', 'north', 'up', 'west', 'south' or 'down'.
|
|
* @param {String} secondAxis name of the second axis of the local reference frame. Must be
|
|
* 'east', 'north', 'up', 'west', 'south' or 'down'.
|
|
* @return {Transforms.LocalFrameToFixedFrame} The function that will computes a
|
|
* 4x4 transformation matrix from a reference frame, with first axis and second axis compliant with the parameters,
|
|
*/
|
|
Transforms.localFrameToFixedFrameGenerator = function (firstAxis, secondAxis) {
|
|
if (
|
|
!vectorProductLocalFrame.hasOwnProperty(firstAxis) ||
|
|
!vectorProductLocalFrame[firstAxis].hasOwnProperty(secondAxis)
|
|
) {
|
|
throw new DeveloperError(
|
|
"firstAxis and secondAxis must be east, north, up, west, south or down."
|
|
);
|
|
}
|
|
var thirdAxis = vectorProductLocalFrame[firstAxis][secondAxis];
|
|
|
|
/**
|
|
* Computes a 4x4 transformation matrix from a reference frame
|
|
* centered at the provided origin to the provided ellipsoid's fixed reference frame.
|
|
* @callback Transforms.LocalFrameToFixedFrame
|
|
* @param {Cartesian3} origin The center point of the local reference frame.
|
|
* @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation.
|
|
* @param {Matrix4} [result] The object onto which to store the result.
|
|
* @returns {Matrix4} The modified result parameter or a new Matrix4 instance if none was provided.
|
|
*/
|
|
var resultat;
|
|
var hashAxis = firstAxis + secondAxis;
|
|
if (defined(localFrameToFixedFrameCache[hashAxis])) {
|
|
resultat = localFrameToFixedFrameCache[hashAxis];
|
|
} else {
|
|
resultat = function (origin, ellipsoid, result) {
|
|
//>>includeStart('debug', pragmas.debug);
|
|
if (!defined(origin)) {
|
|
throw new DeveloperError("origin is required.");
|
|
}
|
|
//>>includeEnd('debug');
|
|
if (!defined(result)) {
|
|
result = new Matrix4();
|
|
}
|
|
if (
|
|
Cartesian3.equalsEpsilon(origin, Cartesian3.ZERO, CesiumMath.EPSILON14)
|
|
) {
|
|
// If x, y, and z are zero, use the degenerate local frame, which is a special case
|
|
Cartesian3.unpack(
|
|
degeneratePositionLocalFrame[firstAxis],
|
|
0,
|
|
scratchFirstCartesian
|
|
);
|
|
Cartesian3.unpack(
|
|
degeneratePositionLocalFrame[secondAxis],
|
|
0,
|
|
scratchSecondCartesian
|
|
);
|
|
Cartesian3.unpack(
|
|
degeneratePositionLocalFrame[thirdAxis],
|
|
0,
|
|
scratchThirdCartesian
|
|
);
|
|
} else if (
|
|
CesiumMath.equalsEpsilon(origin.x, 0.0, CesiumMath.EPSILON14) &&
|
|
CesiumMath.equalsEpsilon(origin.y, 0.0, CesiumMath.EPSILON14)
|
|
) {
|
|
// If x and y are zero, assume origin is at a pole, which is a special case.
|
|
var sign = CesiumMath.sign(origin.z);
|
|
|
|
Cartesian3.unpack(
|
|
degeneratePositionLocalFrame[firstAxis],
|
|
0,
|
|
scratchFirstCartesian
|
|
);
|
|
if (firstAxis !== "east" && firstAxis !== "west") {
|
|
Cartesian3.multiplyByScalar(
|
|
scratchFirstCartesian,
|
|
sign,
|
|
scratchFirstCartesian
|
|
);
|
|
}
|
|
|
|
Cartesian3.unpack(
|
|
degeneratePositionLocalFrame[secondAxis],
|
|
0,
|
|
scratchSecondCartesian
|
|
);
|
|
if (secondAxis !== "east" && secondAxis !== "west") {
|
|
Cartesian3.multiplyByScalar(
|
|
scratchSecondCartesian,
|
|
sign,
|
|
scratchSecondCartesian
|
|
);
|
|
}
|
|
|
|
Cartesian3.unpack(
|
|
degeneratePositionLocalFrame[thirdAxis],
|
|
0,
|
|
scratchThirdCartesian
|
|
);
|
|
if (thirdAxis !== "east" && thirdAxis !== "west") {
|
|
Cartesian3.multiplyByScalar(
|
|
scratchThirdCartesian,
|
|
sign,
|
|
scratchThirdCartesian
|
|
);
|
|
}
|
|
} else {
|
|
ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);
|
|
ellipsoid.geodeticSurfaceNormal(origin, scratchCalculateCartesian.up);
|
|
|
|
var up = scratchCalculateCartesian.up;
|
|
var east = scratchCalculateCartesian.east;
|
|
east.x = -origin.y;
|
|
east.y = origin.x;
|
|
east.z = 0.0;
|
|
Cartesian3.normalize(east, scratchCalculateCartesian.east);
|
|
Cartesian3.cross(up, east, scratchCalculateCartesian.north);
|
|
|
|
Cartesian3.multiplyByScalar(
|
|
scratchCalculateCartesian.up,
|
|
-1,
|
|
scratchCalculateCartesian.down
|
|
);
|
|
Cartesian3.multiplyByScalar(
|
|
scratchCalculateCartesian.east,
|
|
-1,
|
|
scratchCalculateCartesian.west
|
|
);
|
|
Cartesian3.multiplyByScalar(
|
|
scratchCalculateCartesian.north,
|
|
-1,
|
|
scratchCalculateCartesian.south
|
|
);
|
|
|
|
scratchFirstCartesian = scratchCalculateCartesian[firstAxis];
|
|
scratchSecondCartesian = scratchCalculateCartesian[secondAxis];
|
|
scratchThirdCartesian = scratchCalculateCartesian[thirdAxis];
|
|
}
|
|
result[0] = scratchFirstCartesian.x;
|
|
result[1] = scratchFirstCartesian.y;
|
|
result[2] = scratchFirstCartesian.z;
|
|
result[3] = 0.0;
|
|
result[4] = scratchSecondCartesian.x;
|
|
result[5] = scratchSecondCartesian.y;
|
|
result[6] = scratchSecondCartesian.z;
|
|
result[7] = 0.0;
|
|
result[8] = scratchThirdCartesian.x;
|
|
result[9] = scratchThirdCartesian.y;
|
|
result[10] = scratchThirdCartesian.z;
|
|
result[11] = 0.0;
|
|
result[12] = origin.x;
|
|
result[13] = origin.y;
|
|
result[14] = origin.z;
|
|
result[15] = 1.0;
|
|
return result;
|
|
};
|
|
localFrameToFixedFrameCache[hashAxis] = resultat;
|
|
}
|
|
return resultat;
|
|
};
|
|
|
|
/**
|
|
* Computes a 4x4 transformation matrix from a reference frame with an east-north-up axes
|
|
* centered at the provided origin to the provided ellipsoid's fixed reference frame.
|
|
* The local axes are defined as:
|
|
* <ul>
|
|
* <li>The <code>x</code> axis points in the local east direction.</li>
|
|
* <li>The <code>y</code> axis points in the local north direction.</li>
|
|
* <li>The <code>z</code> axis points in the direction of the ellipsoid surface normal which passes through the position.</li>
|
|
* </ul>
|
|
*
|
|
* @function
|
|
* @param {Cartesian3} origin The center point of the local reference frame.
|
|
* @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation.
|
|
* @param {Matrix4} [result] The object onto which to store the result.
|
|
* @returns {Matrix4} The modified result parameter or a new Matrix4 instance if none was provided.
|
|
*
|
|
* @example
|
|
* // Get the transform from local east-north-up at cartographic (0.0, 0.0) to Earth's fixed frame.
|
|
* var center = Cesium.Cartesian3.fromDegrees(0.0, 0.0);
|
|
* var transform = Cesium.Transforms.eastNorthUpToFixedFrame(center);
|
|
*/
|
|
Transforms.eastNorthUpToFixedFrame = Transforms.localFrameToFixedFrameGenerator(
|
|
"east",
|
|
"north"
|
|
);
|
|
|
|
/**
|
|
* Computes a 4x4 transformation matrix from a reference frame with an north-east-down axes
|
|
* centered at the provided origin to the provided ellipsoid's fixed reference frame.
|
|
* The local axes are defined as:
|
|
* <ul>
|
|
* <li>The <code>x</code> axis points in the local north direction.</li>
|
|
* <li>The <code>y</code> axis points in the local east direction.</li>
|
|
* <li>The <code>z</code> axis points in the opposite direction of the ellipsoid surface normal which passes through the position.</li>
|
|
* </ul>
|
|
*
|
|
* @function
|
|
* @param {Cartesian3} origin The center point of the local reference frame.
|
|
* @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation.
|
|
* @param {Matrix4} [result] The object onto which to store the result.
|
|
* @returns {Matrix4} The modified result parameter or a new Matrix4 instance if none was provided.
|
|
*
|
|
* @example
|
|
* // Get the transform from local north-east-down at cartographic (0.0, 0.0) to Earth's fixed frame.
|
|
* var center = Cesium.Cartesian3.fromDegrees(0.0, 0.0);
|
|
* var transform = Cesium.Transforms.northEastDownToFixedFrame(center);
|
|
*/
|
|
Transforms.northEastDownToFixedFrame = Transforms.localFrameToFixedFrameGenerator(
|
|
"north",
|
|
"east"
|
|
);
|
|
|
|
/**
|
|
* Computes a 4x4 transformation matrix from a reference frame with an north-up-east axes
|
|
* centered at the provided origin to the provided ellipsoid's fixed reference frame.
|
|
* The local axes are defined as:
|
|
* <ul>
|
|
* <li>The <code>x</code> axis points in the local north direction.</li>
|
|
* <li>The <code>y</code> axis points in the direction of the ellipsoid surface normal which passes through the position.</li>
|
|
* <li>The <code>z</code> axis points in the local east direction.</li>
|
|
* </ul>
|
|
*
|
|
* @function
|
|
* @param {Cartesian3} origin The center point of the local reference frame.
|
|
* @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation.
|
|
* @param {Matrix4} [result] The object onto which to store the result.
|
|
* @returns {Matrix4} The modified result parameter or a new Matrix4 instance if none was provided.
|
|
*
|
|
* @example
|
|
* // Get the transform from local north-up-east at cartographic (0.0, 0.0) to Earth's fixed frame.
|
|
* var center = Cesium.Cartesian3.fromDegrees(0.0, 0.0);
|
|
* var transform = Cesium.Transforms.northUpEastToFixedFrame(center);
|
|
*/
|
|
Transforms.northUpEastToFixedFrame = Transforms.localFrameToFixedFrameGenerator(
|
|
"north",
|
|
"up"
|
|
);
|
|
|
|
/**
|
|
* Computes a 4x4 transformation matrix from a reference frame with an north-west-up axes
|
|
* centered at the provided origin to the provided ellipsoid's fixed reference frame.
|
|
* The local axes are defined as:
|
|
* <ul>
|
|
* <li>The <code>x</code> axis points in the local north direction.</li>
|
|
* <li>The <code>y</code> axis points in the local west direction.</li>
|
|
* <li>The <code>z</code> axis points in the direction of the ellipsoid surface normal which passes through the position.</li>
|
|
* </ul>
|
|
*
|
|
* @function
|
|
* @param {Cartesian3} origin The center point of the local reference frame.
|
|
* @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation.
|
|
* @param {Matrix4} [result] The object onto which to store the result.
|
|
* @returns {Matrix4} The modified result parameter or a new Matrix4 instance if none was provided.
|
|
*
|
|
* @example
|
|
* // Get the transform from local north-West-Up at cartographic (0.0, 0.0) to Earth's fixed frame.
|
|
* var center = Cesium.Cartesian3.fromDegrees(0.0, 0.0);
|
|
* var transform = Cesium.Transforms.northWestUpToFixedFrame(center);
|
|
*/
|
|
Transforms.northWestUpToFixedFrame = Transforms.localFrameToFixedFrameGenerator(
|
|
"north",
|
|
"west"
|
|
);
|
|
|
|
var scratchHPRQuaternion = new Quaternion();
|
|
var scratchScale = new Cartesian3(1.0, 1.0, 1.0);
|
|
var scratchHPRMatrix4 = new Matrix4();
|
|
|
|
/**
|
|
* Computes a 4x4 transformation matrix from a reference frame with axes computed from the heading-pitch-roll angles
|
|
* centered at the provided origin to the provided ellipsoid's fixed reference frame. Heading is the rotation from the local north
|
|
* direction where a positive angle is increasing eastward. Pitch is the rotation from the local east-north plane. Positive pitch angles
|
|
* are above the plane. Negative pitch angles are below the plane. Roll is the first rotation applied about the local east axis.
|
|
*
|
|
* @param {Cartesian3} origin The center point of the local reference frame.
|
|
* @param {HeadingPitchRoll} headingPitchRoll The heading, pitch, and roll.
|
|
* @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation.
|
|
* @param {Transforms.LocalFrameToFixedFrame} [fixedFrameTransform=Transforms.eastNorthUpToFixedFrame] A 4x4 transformation
|
|
* matrix from a reference frame to the provided ellipsoid's fixed reference frame
|
|
* @param {Matrix4} [result] The object onto which to store the result.
|
|
* @returns {Matrix4} The modified result parameter or a new Matrix4 instance if none was provided.
|
|
*
|
|
* @example
|
|
* // Get the transform from local heading-pitch-roll at cartographic (0.0, 0.0) to Earth's fixed frame.
|
|
* var center = Cesium.Cartesian3.fromDegrees(0.0, 0.0);
|
|
* var heading = -Cesium.Math.PI_OVER_TWO;
|
|
* var pitch = Cesium.Math.PI_OVER_FOUR;
|
|
* var roll = 0.0;
|
|
* var hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
|
|
* var transform = Cesium.Transforms.headingPitchRollToFixedFrame(center, hpr);
|
|
*/
|
|
Transforms.headingPitchRollToFixedFrame = function (
|
|
origin,
|
|
headingPitchRoll,
|
|
ellipsoid,
|
|
fixedFrameTransform,
|
|
result
|
|
) {
|
|
//>>includeStart('debug', pragmas.debug);
|
|
Check.typeOf.object("HeadingPitchRoll", headingPitchRoll);
|
|
//>>includeEnd('debug');
|
|
|
|
fixedFrameTransform = defaultValue(
|
|
fixedFrameTransform,
|
|
Transforms.eastNorthUpToFixedFrame
|
|
);
|
|
var hprQuaternion = Quaternion.fromHeadingPitchRoll(
|
|
headingPitchRoll,
|
|
scratchHPRQuaternion
|
|
);
|
|
var hprMatrix = Matrix4.fromTranslationQuaternionRotationScale(
|
|
Cartesian3.ZERO,
|
|
hprQuaternion,
|
|
scratchScale,
|
|
scratchHPRMatrix4
|
|
);
|
|
result = fixedFrameTransform(origin, ellipsoid, result);
|
|
return Matrix4.multiply(result, hprMatrix, result);
|
|
};
|
|
|
|
var scratchENUMatrix4 = new Matrix4();
|
|
var scratchHPRMatrix3 = new Matrix3();
|
|
|
|
/**
|
|
* Computes a quaternion from a reference frame with axes computed from the heading-pitch-roll angles
|
|
* centered at the provided origin. Heading is the rotation from the local north
|
|
* direction where a positive angle is increasing eastward. Pitch is the rotation from the local east-north plane. Positive pitch angles
|
|
* are above the plane. Negative pitch angles are below the plane. Roll is the first rotation applied about the local east axis.
|
|
*
|
|
* @param {Cartesian3} origin The center point of the local reference frame.
|
|
* @param {HeadingPitchRoll} headingPitchRoll The heading, pitch, and roll.
|
|
* @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation.
|
|
* @param {Transforms.LocalFrameToFixedFrame} [fixedFrameTransform=Transforms.eastNorthUpToFixedFrame] A 4x4 transformation
|
|
* matrix from a reference frame to the provided ellipsoid's fixed reference frame
|
|
* @param {Quaternion} [result] The object onto which to store the result.
|
|
* @returns {Quaternion} The modified result parameter or a new Quaternion instance if none was provided.
|
|
*
|
|
* @example
|
|
* // Get the quaternion from local heading-pitch-roll at cartographic (0.0, 0.0) to Earth's fixed frame.
|
|
* var center = Cesium.Cartesian3.fromDegrees(0.0, 0.0);
|
|
* var heading = -Cesium.Math.PI_OVER_TWO;
|
|
* var pitch = Cesium.Math.PI_OVER_FOUR;
|
|
* var roll = 0.0;
|
|
* var hpr = new HeadingPitchRoll(heading, pitch, roll);
|
|
* var quaternion = Cesium.Transforms.headingPitchRollQuaternion(center, hpr);
|
|
*/
|
|
Transforms.headingPitchRollQuaternion = function (
|
|
origin,
|
|
headingPitchRoll,
|
|
ellipsoid,
|
|
fixedFrameTransform,
|
|
result
|
|
) {
|
|
//>>includeStart('debug', pragmas.debug);
|
|
Check.typeOf.object("HeadingPitchRoll", headingPitchRoll);
|
|
//>>includeEnd('debug');
|
|
|
|
var transform = Transforms.headingPitchRollToFixedFrame(
|
|
origin,
|
|
headingPitchRoll,
|
|
ellipsoid,
|
|
fixedFrameTransform,
|
|
scratchENUMatrix4
|
|
);
|
|
var rotation = Matrix4.getMatrix3(transform, scratchHPRMatrix3);
|
|
return Quaternion.fromRotationMatrix(rotation, result);
|
|
};
|
|
|
|
var noScale = new Cartesian3(1.0, 1.0, 1.0);
|
|
var hprCenterScratch = new Cartesian3();
|
|
var ffScratch = new Matrix4();
|
|
var hprTransformScratch = new Matrix4();
|
|
var hprRotationScratch = new Matrix3();
|
|
var hprQuaternionScratch = new Quaternion();
|
|
/**
|
|
* Computes heading-pitch-roll angles from a transform in a particular reference frame. Heading is the rotation from the local north
|
|
* direction where a positive angle is increasing eastward. Pitch is the rotation from the local east-north plane. Positive pitch angles
|
|
* are above the plane. Negative pitch angles are below the plane. Roll is the first rotation applied about the local east axis.
|
|
*
|
|
* @param {Matrix4} transform The transform
|
|
* @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation.
|
|
* @param {Transforms.LocalFrameToFixedFrame} [fixedFrameTransform=Transforms.eastNorthUpToFixedFrame] A 4x4 transformation
|
|
* matrix from a reference frame to the provided ellipsoid's fixed reference frame
|
|
* @param {HeadingPitchRoll} [result] The object onto which to store the result.
|
|
* @returns {HeadingPitchRoll} The modified result parameter or a new HeadingPitchRoll instance if none was provided.
|
|
*/
|
|
Transforms.fixedFrameToHeadingPitchRoll = function (
|
|
transform,
|
|
ellipsoid,
|
|
fixedFrameTransform,
|
|
result
|
|
) {
|
|
//>>includeStart('debug', pragmas.debug);
|
|
Check.defined("transform", transform);
|
|
//>>includeEnd('debug');
|
|
|
|
ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);
|
|
fixedFrameTransform = defaultValue(
|
|
fixedFrameTransform,
|
|
Transforms.eastNorthUpToFixedFrame
|
|
);
|
|
if (!defined(result)) {
|
|
result = new HeadingPitchRoll();
|
|
}
|
|
|
|
var center = Matrix4.getTranslation(transform, hprCenterScratch);
|
|
if (Cartesian3.equals(center, Cartesian3.ZERO)) {
|
|
result.heading = 0;
|
|
result.pitch = 0;
|
|
result.roll = 0;
|
|
return result;
|
|
}
|
|
var toFixedFrame = Matrix4.inverseTransformation(
|
|
fixedFrameTransform(center, ellipsoid, ffScratch),
|
|
ffScratch
|
|
);
|
|
var transformCopy = Matrix4.setScale(transform, noScale, hprTransformScratch);
|
|
transformCopy = Matrix4.setTranslation(
|
|
transformCopy,
|
|
Cartesian3.ZERO,
|
|
transformCopy
|
|
);
|
|
|
|
toFixedFrame = Matrix4.multiply(toFixedFrame, transformCopy, toFixedFrame);
|
|
var quaternionRotation = Quaternion.fromRotationMatrix(
|
|
Matrix4.getMatrix3(toFixedFrame, hprRotationScratch),
|
|
hprQuaternionScratch
|
|
);
|
|
quaternionRotation = Quaternion.normalize(
|
|
quaternionRotation,
|
|
quaternionRotation
|
|
);
|
|
|
|
return HeadingPitchRoll.fromQuaternion(quaternionRotation, result);
|
|
};
|
|
|
|
var gmstConstant0 = 6 * 3600 + 41 * 60 + 50.54841;
|
|
var gmstConstant1 = 8640184.812866;
|
|
var gmstConstant2 = 0.093104;
|
|
var gmstConstant3 = -6.2e-6;
|
|
var rateCoef = 1.1772758384668e-19;
|
|
var wgs84WRPrecessing = 7.2921158553e-5;
|
|
var twoPiOverSecondsInDay = CesiumMath.TWO_PI / 86400.0;
|
|
var dateInUtc = new JulianDate();
|
|
|
|
/**
|
|
* Computes a rotation matrix to transform a point or vector from True Equator Mean Equinox (TEME) axes to the
|
|
* pseudo-fixed axes at a given time. This method treats the UT1 time standard as equivalent to UTC.
|
|
*
|
|
* @param {JulianDate} date The time at which to compute the rotation matrix.
|
|
* @param {Matrix3} [result] The object onto which to store the result.
|
|
* @returns {Matrix3} The modified result parameter or a new Matrix3 instance if none was provided.
|
|
*
|
|
* @example
|
|
* //Set the view to the inertial frame.
|
|
* scene.postUpdate.addEventListener(function(scene, time) {
|
|
* var now = Cesium.JulianDate.now();
|
|
* var offset = Cesium.Matrix4.multiplyByPoint(camera.transform, camera.position, new Cesium.Cartesian3());
|
|
* var transform = Cesium.Matrix4.fromRotationTranslation(Cesium.Transforms.computeTemeToPseudoFixedMatrix(now));
|
|
* var inverseTransform = Cesium.Matrix4.inverseTransformation(transform, new Cesium.Matrix4());
|
|
* Cesium.Matrix4.multiplyByPoint(inverseTransform, offset, offset);
|
|
* camera.lookAtTransform(transform, offset);
|
|
* });
|
|
*/
|
|
Transforms.computeTemeToPseudoFixedMatrix = function (date, result) {
|
|
//>>includeStart('debug', pragmas.debug);
|
|
if (!defined(date)) {
|
|
throw new DeveloperError("date is required.");
|
|
}
|
|
//>>includeEnd('debug');
|
|
|
|
// GMST is actually computed using UT1. We're using UTC as an approximation of UT1.
|
|
// We do not want to use the function like convertTaiToUtc in JulianDate because
|
|
// we explicitly do not want to fail when inside the leap second.
|
|
|
|
dateInUtc = JulianDate.addSeconds(
|
|
date,
|
|
-JulianDate.computeTaiMinusUtc(date),
|
|
dateInUtc
|
|
);
|
|
var utcDayNumber = dateInUtc.dayNumber;
|
|
var utcSecondsIntoDay = dateInUtc.secondsOfDay;
|
|
|
|
var t;
|
|
var diffDays = utcDayNumber - 2451545;
|
|
if (utcSecondsIntoDay >= 43200.0) {
|
|
t = (diffDays + 0.5) / TimeConstants.DAYS_PER_JULIAN_CENTURY;
|
|
} else {
|
|
t = (diffDays - 0.5) / TimeConstants.DAYS_PER_JULIAN_CENTURY;
|
|
}
|
|
|
|
var gmst0 =
|
|
gmstConstant0 +
|
|
t * (gmstConstant1 + t * (gmstConstant2 + t * gmstConstant3));
|
|
var angle = (gmst0 * twoPiOverSecondsInDay) % CesiumMath.TWO_PI;
|
|
var ratio = wgs84WRPrecessing + rateCoef * (utcDayNumber - 2451545.5);
|
|
var secondsSinceMidnight =
|
|
(utcSecondsIntoDay + TimeConstants.SECONDS_PER_DAY * 0.5) %
|
|
TimeConstants.SECONDS_PER_DAY;
|
|
var gha = angle + ratio * secondsSinceMidnight;
|
|
var cosGha = Math.cos(gha);
|
|
var sinGha = Math.sin(gha);
|
|
|
|
if (!defined(result)) {
|
|
return new Matrix3(
|
|
cosGha,
|
|
sinGha,
|
|
0.0,
|
|
-sinGha,
|
|
cosGha,
|
|
0.0,
|
|
0.0,
|
|
0.0,
|
|
1.0
|
|
);
|
|
}
|
|
result[0] = cosGha;
|
|
result[1] = -sinGha;
|
|
result[2] = 0.0;
|
|
result[3] = sinGha;
|
|
result[4] = cosGha;
|
|
result[5] = 0.0;
|
|
result[6] = 0.0;
|
|
result[7] = 0.0;
|
|
result[8] = 1.0;
|
|
return result;
|
|
};
|
|
|
|
/**
|
|
* The source of IAU 2006 XYS data, used for computing the transformation between the
|
|
* Fixed and ICRF axes.
|
|
* @type {Iau2006XysData}
|
|
*
|
|
* @see Transforms.computeIcrfToFixedMatrix
|
|
* @see Transforms.computeFixedToIcrfMatrix
|
|
*
|
|
* @private
|
|
*/
|
|
Transforms.iau2006XysData = new Iau2006XysData();
|
|
|
|
/**
|
|
* The source of Earth Orientation Parameters (EOP) data, used for computing the transformation
|
|
* between the Fixed and ICRF axes. By default, zero values are used for all EOP values,
|
|
* yielding a reasonable but not completely accurate representation of the ICRF axes.
|
|
* @type {EarthOrientationParameters}
|
|
*
|
|
* @see Transforms.computeIcrfToFixedMatrix
|
|
* @see Transforms.computeFixedToIcrfMatrix
|
|
*
|
|
* @private
|
|
*/
|
|
Transforms.earthOrientationParameters = EarthOrientationParameters.NONE;
|
|
|
|
var ttMinusTai = 32.184;
|
|
var j2000ttDays = 2451545.0;
|
|
|
|
/**
|
|
* Preloads the data necessary to transform between the ICRF and Fixed axes, in either
|
|
* direction, over a given interval. This function returns a promise that, when resolved,
|
|
* indicates that the preload has completed.
|
|
*
|
|
* @param {TimeInterval} timeInterval The interval to preload.
|
|
* @returns {Promise<void>} A promise that, when resolved, indicates that the preload has completed
|
|
* and evaluation of the transformation between the fixed and ICRF axes will
|
|
* no longer return undefined for a time inside the interval.
|
|
*
|
|
*
|
|
* @example
|
|
* var interval = new Cesium.TimeInterval(...);
|
|
* when(Cesium.Transforms.preloadIcrfFixed(interval), function() {
|
|
* // the data is now loaded
|
|
* });
|
|
*
|
|
* @see Transforms.computeIcrfToFixedMatrix
|
|
* @see Transforms.computeFixedToIcrfMatrix
|
|
* @see when
|
|
*/
|
|
Transforms.preloadIcrfFixed = function (timeInterval) {
|
|
var startDayTT = timeInterval.start.dayNumber;
|
|
var startSecondTT = timeInterval.start.secondsOfDay + ttMinusTai;
|
|
var stopDayTT = timeInterval.stop.dayNumber;
|
|
var stopSecondTT = timeInterval.stop.secondsOfDay + ttMinusTai;
|
|
|
|
var xysPromise = Transforms.iau2006XysData.preload(
|
|
startDayTT,
|
|
startSecondTT,
|
|
stopDayTT,
|
|
stopSecondTT
|
|
);
|
|
var eopPromise = Transforms.earthOrientationParameters.getPromiseToLoad();
|
|
|
|
return when.all([xysPromise, eopPromise]);
|
|
};
|
|
|
|
/**
|
|
* Computes a rotation matrix to transform a point or vector from the International Celestial
|
|
* Reference Frame (GCRF/ICRF) inertial frame axes to the Earth-Fixed frame axes (ITRF)
|
|
* at a given time. This function may return undefined if the data necessary to
|
|
* do the transformation is not yet loaded.
|
|
*
|
|
* @param {JulianDate} date The time at which to compute the rotation matrix.
|
|
* @param {Matrix3} [result] The object onto which to store the result. If this parameter is
|
|
* not specified, a new instance is created and returned.
|
|
* @returns {Matrix3} The rotation matrix, or undefined if the data necessary to do the
|
|
* transformation is not yet loaded.
|
|
*
|
|
*
|
|
* @example
|
|
* scene.postUpdate.addEventListener(function(scene, time) {
|
|
* // View in ICRF.
|
|
* var icrfToFixed = Cesium.Transforms.computeIcrfToFixedMatrix(time);
|
|
* if (Cesium.defined(icrfToFixed)) {
|
|
* var offset = Cesium.Cartesian3.clone(camera.position);
|
|
* var transform = Cesium.Matrix4.fromRotationTranslation(icrfToFixed);
|
|
* camera.lookAtTransform(transform, offset);
|
|
* }
|
|
* });
|
|
*
|
|
* @see Transforms.preloadIcrfFixed
|
|
*/
|
|
Transforms.computeIcrfToFixedMatrix = function (date, result) {
|
|
//>>includeStart('debug', pragmas.debug);
|
|
if (!defined(date)) {
|
|
throw new DeveloperError("date is required.");
|
|
}
|
|
//>>includeEnd('debug');
|
|
if (!defined(result)) {
|
|
result = new Matrix3();
|
|
}
|
|
|
|
var fixedToIcrfMtx = Transforms.computeFixedToIcrfMatrix(date, result);
|
|
if (!defined(fixedToIcrfMtx)) {
|
|
return undefined;
|
|
}
|
|
|
|
return Matrix3.transpose(fixedToIcrfMtx, result);
|
|
};
|
|
|
|
var xysScratch = new Iau2006XysSample(0.0, 0.0, 0.0);
|
|
var eopScratch = new EarthOrientationParametersSample(
|
|
0.0,
|
|
0.0,
|
|
0.0,
|
|
0.0,
|
|
0.0,
|
|
0.0
|
|
);
|
|
var rotation1Scratch = new Matrix3();
|
|
var rotation2Scratch = new Matrix3();
|
|
|
|
/**
|
|
* Computes a rotation matrix to transform a point or vector from the Earth-Fixed frame axes (ITRF)
|
|
* to the International Celestial Reference Frame (GCRF/ICRF) inertial frame axes
|
|
* at a given time. This function may return undefined if the data necessary to
|
|
* do the transformation is not yet loaded.
|
|
*
|
|
* @param {JulianDate} date The time at which to compute the rotation matrix.
|
|
* @param {Matrix3} [result] The object onto which to store the result. If this parameter is
|
|
* not specified, a new instance is created and returned.
|
|
* @returns {Matrix3} The rotation matrix, or undefined if the data necessary to do the
|
|
* transformation is not yet loaded.
|
|
*
|
|
*
|
|
* @example
|
|
* // Transform a point from the ICRF axes to the Fixed axes.
|
|
* var now = Cesium.JulianDate.now();
|
|
* var pointInFixed = Cesium.Cartesian3.fromDegrees(0.0, 0.0);
|
|
* var fixedToIcrf = Cesium.Transforms.computeIcrfToFixedMatrix(now);
|
|
* var pointInInertial = new Cesium.Cartesian3();
|
|
* if (Cesium.defined(fixedToIcrf)) {
|
|
* pointInInertial = Cesium.Matrix3.multiplyByVector(fixedToIcrf, pointInFixed, pointInInertial);
|
|
* }
|
|
*
|
|
* @see Transforms.preloadIcrfFixed
|
|
*/
|
|
Transforms.computeFixedToIcrfMatrix = function (date, result) {
|
|
//>>includeStart('debug', pragmas.debug);
|
|
if (!defined(date)) {
|
|
throw new DeveloperError("date is required.");
|
|
}
|
|
//>>includeEnd('debug');
|
|
|
|
if (!defined(result)) {
|
|
result = new Matrix3();
|
|
}
|
|
|
|
// Compute pole wander
|
|
var eop = Transforms.earthOrientationParameters.compute(date, eopScratch);
|
|
if (!defined(eop)) {
|
|
return undefined;
|
|
}
|
|
|
|
// There is no external conversion to Terrestrial Time (TT).
|
|
// So use International Atomic Time (TAI) and convert using offsets.
|
|
// Here we are assuming that dayTT and secondTT are positive
|
|
var dayTT = date.dayNumber;
|
|
// It's possible here that secondTT could roll over 86400
|
|
// This does not seem to affect the precision (unit tests check for this)
|
|
var secondTT = date.secondsOfDay + ttMinusTai;
|
|
|
|
var xys = Transforms.iau2006XysData.computeXysRadians(
|
|
dayTT,
|
|
secondTT,
|
|
xysScratch
|
|
);
|
|
if (!defined(xys)) {
|
|
return undefined;
|
|
}
|
|
|
|
var x = xys.x + eop.xPoleOffset;
|
|
var y = xys.y + eop.yPoleOffset;
|
|
|
|
// Compute XYS rotation
|
|
var a = 1.0 / (1.0 + Math.sqrt(1.0 - x * x - y * y));
|
|
|
|
var rotation1 = rotation1Scratch;
|
|
rotation1[0] = 1.0 - a * x * x;
|
|
rotation1[3] = -a * x * y;
|
|
rotation1[6] = x;
|
|
rotation1[1] = -a * x * y;
|
|
rotation1[4] = 1 - a * y * y;
|
|
rotation1[7] = y;
|
|
rotation1[2] = -x;
|
|
rotation1[5] = -y;
|
|
rotation1[8] = 1 - a * (x * x + y * y);
|
|
|
|
var rotation2 = Matrix3.fromRotationZ(-xys.s, rotation2Scratch);
|
|
var matrixQ = Matrix3.multiply(rotation1, rotation2, rotation1Scratch);
|
|
|
|
// Similar to TT conversions above
|
|
// It's possible here that secondTT could roll over 86400
|
|
// This does not seem to affect the precision (unit tests check for this)
|
|
var dateUt1day = date.dayNumber;
|
|
var dateUt1sec =
|
|
date.secondsOfDay - JulianDate.computeTaiMinusUtc(date) + eop.ut1MinusUtc;
|
|
|
|
// Compute Earth rotation angle
|
|
// The IERS standard for era is
|
|
// era = 0.7790572732640 + 1.00273781191135448 * Tu
|
|
// where
|
|
// Tu = JulianDateInUt1 - 2451545.0
|
|
// However, you get much more precision if you make the following simplification
|
|
// era = a + (1 + b) * (JulianDayNumber + FractionOfDay - 2451545)
|
|
// era = a + (JulianDayNumber - 2451545) + FractionOfDay + b (JulianDayNumber - 2451545 + FractionOfDay)
|
|
// era = a + FractionOfDay + b (JulianDayNumber - 2451545 + FractionOfDay)
|
|
// since (JulianDayNumber - 2451545) represents an integer number of revolutions which will be discarded anyway.
|
|
var daysSinceJ2000 = dateUt1day - 2451545;
|
|
var fractionOfDay = dateUt1sec / TimeConstants.SECONDS_PER_DAY;
|
|
var era =
|
|
0.779057273264 +
|
|
fractionOfDay +
|
|
0.00273781191135448 * (daysSinceJ2000 + fractionOfDay);
|
|
era = (era % 1.0) * CesiumMath.TWO_PI;
|
|
|
|
var earthRotation = Matrix3.fromRotationZ(era, rotation2Scratch);
|
|
|
|
// pseudoFixed to ICRF
|
|
var pfToIcrf = Matrix3.multiply(matrixQ, earthRotation, rotation1Scratch);
|
|
|
|
// Compute pole wander matrix
|
|
var cosxp = Math.cos(eop.xPoleWander);
|
|
var cosyp = Math.cos(eop.yPoleWander);
|
|
var sinxp = Math.sin(eop.xPoleWander);
|
|
var sinyp = Math.sin(eop.yPoleWander);
|
|
|
|
var ttt = dayTT - j2000ttDays + secondTT / TimeConstants.SECONDS_PER_DAY;
|
|
ttt /= 36525.0;
|
|
|
|
// approximate sp value in rad
|
|
var sp = (-47.0e-6 * ttt * CesiumMath.RADIANS_PER_DEGREE) / 3600.0;
|
|
var cossp = Math.cos(sp);
|
|
var sinsp = Math.sin(sp);
|
|
|
|
var fToPfMtx = rotation2Scratch;
|
|
fToPfMtx[0] = cosxp * cossp;
|
|
fToPfMtx[1] = cosxp * sinsp;
|
|
fToPfMtx[2] = sinxp;
|
|
fToPfMtx[3] = -cosyp * sinsp + sinyp * sinxp * cossp;
|
|
fToPfMtx[4] = cosyp * cossp + sinyp * sinxp * sinsp;
|
|
fToPfMtx[5] = -sinyp * cosxp;
|
|
fToPfMtx[6] = -sinyp * sinsp - cosyp * sinxp * cossp;
|
|
fToPfMtx[7] = sinyp * cossp - cosyp * sinxp * sinsp;
|
|
fToPfMtx[8] = cosyp * cosxp;
|
|
|
|
return Matrix3.multiply(pfToIcrf, fToPfMtx, result);
|
|
};
|
|
|
|
var pointToWindowCoordinatesTemp = new Cartesian4();
|
|
|
|
/**
|
|
* Transform a point from model coordinates to window coordinates.
|
|
*
|
|
* @param {Matrix4} modelViewProjectionMatrix The 4x4 model-view-projection matrix.
|
|
* @param {Matrix4} viewportTransformation The 4x4 viewport transformation.
|
|
* @param {Cartesian3} point The point to transform.
|
|
* @param {Cartesian2} [result] The object onto which to store the result.
|
|
* @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if none was provided.
|
|
*/
|
|
Transforms.pointToWindowCoordinates = function (
|
|
modelViewProjectionMatrix,
|
|
viewportTransformation,
|
|
point,
|
|
result
|
|
) {
|
|
result = Transforms.pointToGLWindowCoordinates(
|
|
modelViewProjectionMatrix,
|
|
viewportTransformation,
|
|
point,
|
|
result
|
|
);
|
|
result.y = 2.0 * viewportTransformation[5] - result.y;
|
|
return result;
|
|
};
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
Transforms.pointToGLWindowCoordinates = function (
|
|
modelViewProjectionMatrix,
|
|
viewportTransformation,
|
|
point,
|
|
result
|
|
) {
|
|
//>>includeStart('debug', pragmas.debug);
|
|
if (!defined(modelViewProjectionMatrix)) {
|
|
throw new DeveloperError("modelViewProjectionMatrix is required.");
|
|
}
|
|
|
|
if (!defined(viewportTransformation)) {
|
|
throw new DeveloperError("viewportTransformation is required.");
|
|
}
|
|
|
|
if (!defined(point)) {
|
|
throw new DeveloperError("point is required.");
|
|
}
|
|
//>>includeEnd('debug');
|
|
|
|
if (!defined(result)) {
|
|
result = new Cartesian2();
|
|
}
|
|
|
|
var tmp = pointToWindowCoordinatesTemp;
|
|
|
|
Matrix4.multiplyByVector(
|
|
modelViewProjectionMatrix,
|
|
Cartesian4.fromElements(point.x, point.y, point.z, 1, tmp),
|
|
tmp
|
|
);
|
|
Cartesian4.multiplyByScalar(tmp, 1.0 / tmp.w, tmp);
|
|
Matrix4.multiplyByVector(viewportTransformation, tmp, tmp);
|
|
return Cartesian2.fromCartesian4(tmp, result);
|
|
};
|
|
|
|
var normalScratch = new Cartesian3();
|
|
var rightScratch = new Cartesian3();
|
|
var upScratch = new Cartesian3();
|
|
|
|
/**
|
|
* Transform a position and velocity to a rotation matrix.
|
|
*
|
|
* @param {Cartesian3} position The position to transform.
|
|
* @param {Cartesian3} velocity The velocity vector to transform.
|
|
* @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation.
|
|
* @param {Matrix3} [result] The object onto which to store the result.
|
|
* @returns {Matrix3} The modified result parameter or a new Matrix3 instance if none was provided.
|
|
*/
|
|
Transforms.rotationMatrixFromPositionVelocity = function (
|
|
position,
|
|
velocity,
|
|
ellipsoid,
|
|
result
|
|
) {
|
|
//>>includeStart('debug', pragmas.debug);
|
|
if (!defined(position)) {
|
|
throw new DeveloperError("position is required.");
|
|
}
|
|
|
|
if (!defined(velocity)) {
|
|
throw new DeveloperError("velocity is required.");
|
|
}
|
|
//>>includeEnd('debug');
|
|
|
|
var normal = defaultValue(ellipsoid, Ellipsoid.WGS84).geodeticSurfaceNormal(
|
|
position,
|
|
normalScratch
|
|
);
|
|
var right = Cartesian3.cross(velocity, normal, rightScratch);
|
|
|
|
if (Cartesian3.equalsEpsilon(right, Cartesian3.ZERO, CesiumMath.EPSILON6)) {
|
|
right = Cartesian3.clone(Cartesian3.UNIT_X, right);
|
|
}
|
|
|
|
var up = Cartesian3.cross(right, velocity, upScratch);
|
|
Cartesian3.normalize(up, up);
|
|
Cartesian3.cross(velocity, up, right);
|
|
Cartesian3.negate(right, right);
|
|
Cartesian3.normalize(right, right);
|
|
|
|
if (!defined(result)) {
|
|
result = new Matrix3();
|
|
}
|
|
|
|
result[0] = velocity.x;
|
|
result[1] = velocity.y;
|
|
result[2] = velocity.z;
|
|
result[3] = right.x;
|
|
result[4] = right.y;
|
|
result[5] = right.z;
|
|
result[6] = up.x;
|
|
result[7] = up.y;
|
|
result[8] = up.z;
|
|
|
|
return result;
|
|
};
|
|
|
|
var swizzleMatrix = new Matrix4(
|
|
0.0,
|
|
0.0,
|
|
1.0,
|
|
0.0,
|
|
1.0,
|
|
0.0,
|
|
0.0,
|
|
0.0,
|
|
0.0,
|
|
1.0,
|
|
0.0,
|
|
0.0,
|
|
0.0,
|
|
0.0,
|
|
0.0,
|
|
1.0
|
|
);
|
|
|
|
var scratchCartographic = new Cartographic();
|
|
var scratchCartesian3Projection = new Cartesian3();
|
|
var scratchCenter = new Cartesian3();
|
|
var scratchRotation = new Matrix3();
|
|
var scratchFromENU = new Matrix4();
|
|
var scratchToENU = new Matrix4();
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
Transforms.basisTo2D = function (projection, matrix, result) {
|
|
//>>includeStart('debug', pragmas.debug);
|
|
if (!defined(projection)) {
|
|
throw new DeveloperError("projection is required.");
|
|
}
|
|
if (!defined(matrix)) {
|
|
throw new DeveloperError("matrix is required.");
|
|
}
|
|
if (!defined(result)) {
|
|
throw new DeveloperError("result is required.");
|
|
}
|
|
//>>includeEnd('debug');
|
|
|
|
var rtcCenter = Matrix4.getTranslation(matrix, scratchCenter);
|
|
var ellipsoid = projection.ellipsoid;
|
|
|
|
// Get the 2D Center
|
|
var cartographic = ellipsoid.cartesianToCartographic(
|
|
rtcCenter,
|
|
scratchCartographic
|
|
);
|
|
var projectedPosition = projection.project(
|
|
cartographic,
|
|
scratchCartesian3Projection
|
|
);
|
|
Cartesian3.fromElements(
|
|
projectedPosition.z,
|
|
projectedPosition.x,
|
|
projectedPosition.y,
|
|
projectedPosition
|
|
);
|
|
|
|
// Assuming the instance are positioned in WGS84, invert the WGS84 transform to get the local transform and then convert to 2D
|
|
var fromENU = Transforms.eastNorthUpToFixedFrame(
|
|
rtcCenter,
|
|
ellipsoid,
|
|
scratchFromENU
|
|
);
|
|
var toENU = Matrix4.inverseTransformation(fromENU, scratchToENU);
|
|
var rotation = Matrix4.getMatrix3(matrix, scratchRotation);
|
|
var local = Matrix4.multiplyByMatrix3(toENU, rotation, result);
|
|
Matrix4.multiply(swizzleMatrix, local, result); // Swap x, y, z for 2D
|
|
Matrix4.setTranslation(result, projectedPosition, result); // Use the projected center
|
|
|
|
return result;
|
|
};
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
Transforms.wgs84To2DModelMatrix = function (projection, center, result) {
|
|
//>>includeStart('debug', pragmas.debug);
|
|
if (!defined(projection)) {
|
|
throw new DeveloperError("projection is required.");
|
|
}
|
|
if (!defined(center)) {
|
|
throw new DeveloperError("center is required.");
|
|
}
|
|
if (!defined(result)) {
|
|
throw new DeveloperError("result is required.");
|
|
}
|
|
//>>includeEnd('debug');
|
|
|
|
var ellipsoid = projection.ellipsoid;
|
|
|
|
var fromENU = Transforms.eastNorthUpToFixedFrame(
|
|
center,
|
|
ellipsoid,
|
|
scratchFromENU
|
|
);
|
|
var toENU = Matrix4.inverseTransformation(fromENU, scratchToENU);
|
|
|
|
var cartographic = ellipsoid.cartesianToCartographic(
|
|
center,
|
|
scratchCartographic
|
|
);
|
|
var projectedPosition = projection.project(
|
|
cartographic,
|
|
scratchCartesian3Projection
|
|
);
|
|
Cartesian3.fromElements(
|
|
projectedPosition.z,
|
|
projectedPosition.x,
|
|
projectedPosition.y,
|
|
projectedPosition
|
|
);
|
|
|
|
var translation = Matrix4.fromTranslation(projectedPosition, scratchFromENU);
|
|
Matrix4.multiply(swizzleMatrix, toENU, result);
|
|
Matrix4.multiply(translation, result, result);
|
|
|
|
return result;
|
|
};
|
|
export default Transforms;
|