From 4b92800bfb6aaa2184587a37eb1d5a37c63cf5d0 Mon Sep 17 00:00:00 2001 From: Don McCurdy <1848368+donmccurdy@users.noreply.github.com> Date: Thu, 8 Jan 2026 12:34:47 -0500 Subject: [PATCH] refactor(engine): Opt-in to type checks on Cartesian2.js --- packages/engine/Source/Core/Cartesian2.js | 1361 +++++++++++---------- 1 file changed, 682 insertions(+), 679 deletions(-) diff --git a/packages/engine/Source/Core/Cartesian2.js b/packages/engine/Source/Core/Cartesian2.js index bd7d21ad931f..fa22dc94175c 100644 --- a/packages/engine/Source/Core/Cartesian2.js +++ b/packages/engine/Source/Core/Cartesian2.js @@ -1,8 +1,13 @@ +// @ts-check +/* eslint no-use-before-define: ["error", { "variables": false }] */ import Check from "./Check.js"; import defined from "./defined.js"; import DeveloperError from "./DeveloperError.js"; import CesiumMath from "./Math.js"; +/** @import Cartesian3 from './Cartesian3.js'; */ +/** @import Cartesian4 from './Cartesian4.js'; */ + /** * A 2D Cartesian point. * @alias Cartesian2 @@ -15,726 +20,776 @@ import CesiumMath from "./Math.js"; * @see Cartesian4 * @see Packable */ -function Cartesian2(x, y) { +class Cartesian2 { + constructor(x, y) { + /** + * The X component. + * @type {number} + * @default 0.0 + */ + this.x = x ?? 0.0; + + /** + * The Y component. + * @type {number} + * @default 0.0 + */ + this.y = y ?? 0.0; + } + /** - * The X component. - * @type {number} - * @default 0.0 + * Creates a Cartesian2 instance from x and y coordinates. + * + * @param {number} x The x coordinate. + * @param {number} y The y coordinate. + * @param {Cartesian2} [result] The object onto which to store the result. + * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided. */ - this.x = x ?? 0.0; + static fromElements(x, y, result) { + if (!defined(result)) { + return new Cartesian2(x, y); + } + + result.x = x; + result.y = y; + return result; + } /** - * The Y component. - * @type {number} - * @default 0.0 + * Duplicates a Cartesian2 instance. + * + * @param {Cartesian2} cartesian The Cartesian to duplicate. + * @param {Cartesian2} [result] The object onto which to store the result. + * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided. (Returns undefined if cartesian is undefined) */ - this.y = y ?? 0.0; -} + static clone(cartesian, result) { + if (!defined(cartesian)) { + return undefined; + } + if (!defined(result)) { + return new Cartesian2(cartesian.x, cartesian.y); + } + + result.x = cartesian.x; + result.y = cartesian.y; + return result; + } -/** - * Creates a Cartesian2 instance from x and y coordinates. - * - * @param {number} x The x coordinate. - * @param {number} y The y coordinate. - * @param {Cartesian2} [result] The object onto which to store the result. - * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided. - */ -Cartesian2.fromElements = function (x, y, result) { - if (!defined(result)) { - return new Cartesian2(x, y); + /** + * Stores the provided instance into the provided array. + * + * @param {Cartesian2} value The value to pack. + * @param {number[]} array The array to pack into. + * @param {number} [startingIndex=0] The index into the array at which to start packing the elements. + * + * @returns {number[]} The array that was packed into + */ + static pack(value, array, startingIndex) { + //>>includeStart('debug', pragmas.debug); + Check.typeOf.object("value", value); + Check.defined("array", array); + //>>includeEnd('debug'); + + startingIndex = startingIndex ?? 0; + + array[startingIndex++] = value.x; + array[startingIndex] = value.y; + + return array; } - result.x = x; - result.y = y; - return result; -}; + /** + * Retrieves an instance from a packed array. + * + * @param {number[]} array The packed array. + * @param {number} [startingIndex=0] The starting index of the element to be unpacked. + * @param {Cartesian2} [result] The object into which to store the result. + * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided. + */ + static unpack(array, startingIndex, result) { + //>>includeStart('debug', pragmas.debug); + Check.defined("array", array); + //>>includeEnd('debug'); -/** - * Duplicates a Cartesian2 instance. - * - * @param {Cartesian2} cartesian The Cartesian to duplicate. - * @param {Cartesian2} [result] The object onto which to store the result. - * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided. (Returns undefined if cartesian is undefined) - */ -Cartesian2.clone = function (cartesian, result) { - if (!defined(cartesian)) { - return undefined; + startingIndex = startingIndex ?? 0; + + if (!defined(result)) { + result = new Cartesian2(); + } + result.x = array[startingIndex++]; + result.y = array[startingIndex]; + return result; } - if (!defined(result)) { - return new Cartesian2(cartesian.x, cartesian.y); + + /** + * Flattens an array of Cartesian2s into an array of components. + * + * @param {Cartesian2[]} array The array of cartesians to pack. + * @param {number[]} [result] The array onto which to store the result. If this is a typed array, it must have array.length * 2 components, else a {@link DeveloperError} will be thrown. If it is a regular array, it will be resized to have (array.length * 2) elements. + * @returns {number[]} The packed array. + */ + static packArray(array, result) { + //>>includeStart('debug', pragmas.debug); + Check.defined("array", array); + //>>includeEnd('debug'); + + const length = array.length; + const resultLength = length * 2; + if (!defined(result)) { + result = new Array(resultLength); + // @ts-expect-error TODO: Requires method signature update. + } else if (!Array.isArray(result) && result.length !== resultLength) { + //>>includeStart('debug', pragmas.debug); + throw new DeveloperError( + "If result is a typed array, it must have exactly array.length * 2 elements", + ); + //>>includeEnd('debug'); + } else if (result.length !== resultLength) { + result.length = resultLength; + } + + for (let i = 0; i < length; ++i) { + Cartesian2.pack(array[i], result, i * 2); + } + return result; } - result.x = cartesian.x; - result.y = cartesian.y; - return result; -}; + /** + * Unpacks an array of cartesian components into an array of Cartesian2s. + * + * @param {number[]} array The array of components to unpack. + * @param {Cartesian2[]} [result] The array onto which to store the result. + * @returns {Cartesian2[]} The unpacked array. + */ + static unpackArray(array, result) { + //>>includeStart('debug', pragmas.debug); + Check.defined("array", array); + Check.typeOf.number.greaterThanOrEquals("array.length", array.length, 2); + if (array.length % 2 !== 0) { + throw new DeveloperError("array length must be a multiple of 2."); + } + //>>includeEnd('debug'); -/** - * Creates a Cartesian2 instance from an existing Cartesian3. This simply takes the - * x and y properties of the Cartesian3 and drops z. - * @function - * - * @param {Cartesian3} cartesian The Cartesian3 instance to create a Cartesian2 instance from. - * @param {Cartesian2} [result] The object onto which to store the result. - * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided. - */ -Cartesian2.fromCartesian3 = Cartesian2.clone; + const length = array.length; + if (!defined(result)) { + result = new Array(length / 2); + } else { + result.length = length / 2; + } + + for (let i = 0; i < length; i += 2) { + const index = i / 2; + result[index] = Cartesian2.unpack(array, i, result[index]); + } + return result; + } -/** - * Creates a Cartesian2 instance from an existing Cartesian4. This simply takes the - * x and y properties of the Cartesian4 and drops z and w. - * @function - * - * @param {Cartesian4} cartesian The Cartesian4 instance to create a Cartesian2 instance from. - * @param {Cartesian2} [result] The object onto which to store the result. - * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided. - */ -Cartesian2.fromCartesian4 = Cartesian2.clone; + /** + * Computes the value of the maximum component for the supplied Cartesian. + * + * @param {Cartesian2} cartesian The cartesian to use. + * @returns {number} The value of the maximum component. + */ + static maximumComponent(cartesian) { + //>>includeStart('debug', pragmas.debug); + Check.typeOf.object("cartesian", cartesian); + //>>includeEnd('debug'); -/** - * The number of elements used to pack the object into an array. - * @type {number} - */ -Cartesian2.packedLength = 2; + return Math.max(cartesian.x, cartesian.y); + } -/** - * Stores the provided instance into the provided array. - * - * @param {Cartesian2} value The value to pack. - * @param {number[]} array The array to pack into. - * @param {number} [startingIndex=0] The index into the array at which to start packing the elements. - * - * @returns {number[]} The array that was packed into - */ -Cartesian2.pack = function (value, array, startingIndex) { - //>>includeStart('debug', pragmas.debug); - Check.typeOf.object("value", value); - Check.defined("array", array); - //>>includeEnd('debug'); + /** + * Computes the value of the minimum component for the supplied Cartesian. + * + * @param {Cartesian2} cartesian The cartesian to use. + * @returns {number} The value of the minimum component. + */ + static minimumComponent(cartesian) { + //>>includeStart('debug', pragmas.debug); + Check.typeOf.object("cartesian", cartesian); + //>>includeEnd('debug'); - startingIndex = startingIndex ?? 0; + return Math.min(cartesian.x, cartesian.y); + } - array[startingIndex++] = value.x; - array[startingIndex] = value.y; + /** + * Compares two Cartesians and computes a Cartesian which contains the minimum components of the supplied Cartesians. + * + * @param {Cartesian2} first A cartesian to compare. + * @param {Cartesian2} second A cartesian to compare. + * @param {Cartesian2} result The object into which to store the result. + * @returns {Cartesian2} A cartesian with the minimum components. + */ + static minimumByComponent(first, second, result) { + //>>includeStart('debug', pragmas.debug); + Check.typeOf.object("first", first); + Check.typeOf.object("second", second); + Check.typeOf.object("result", result); + //>>includeEnd('debug'); - return array; -}; + result.x = Math.min(first.x, second.x); + result.y = Math.min(first.y, second.y); -/** - * Retrieves an instance from a packed array. - * - * @param {number[]} array The packed array. - * @param {number} [startingIndex=0] The starting index of the element to be unpacked. - * @param {Cartesian2} [result] The object into which to store the result. - * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided. - */ -Cartesian2.unpack = function (array, startingIndex, result) { - //>>includeStart('debug', pragmas.debug); - Check.defined("array", array); - //>>includeEnd('debug'); + return result; + } - startingIndex = startingIndex ?? 0; + /** + * Compares two Cartesians and computes a Cartesian which contains the maximum components of the supplied Cartesians. + * + * @param {Cartesian2} first A cartesian to compare. + * @param {Cartesian2} second A cartesian to compare. + * @param {Cartesian2} result The object into which to store the result. + * @returns {Cartesian2} A cartesian with the maximum components. + */ + static maximumByComponent(first, second, result) { + //>>includeStart('debug', pragmas.debug); + Check.typeOf.object("first", first); + Check.typeOf.object("second", second); + Check.typeOf.object("result", result); + //>>includeEnd('debug'); - if (!defined(result)) { - result = new Cartesian2(); + result.x = Math.max(first.x, second.x); + result.y = Math.max(first.y, second.y); + return result; } - result.x = array[startingIndex++]; - result.y = array[startingIndex]; - return result; -}; -/** - * Flattens an array of Cartesian2s into an array of components. - * - * @param {Cartesian2[]} array The array of cartesians to pack. - * @param {number[]} [result] The array onto which to store the result. If this is a typed array, it must have array.length * 2 components, else a {@link DeveloperError} will be thrown. If it is a regular array, it will be resized to have (array.length * 2) elements. - * @returns {number[]} The packed array. - */ -Cartesian2.packArray = function (array, result) { - //>>includeStart('debug', pragmas.debug); - Check.defined("array", array); - //>>includeEnd('debug'); - - const length = array.length; - const resultLength = length * 2; - if (!defined(result)) { - result = new Array(resultLength); - } else if (!Array.isArray(result) && result.length !== resultLength) { + /** + * Constrain a value to lie between two values. + * + * @param {Cartesian2} value The value to clamp. + * @param {Cartesian2} min The minimum bound. + * @param {Cartesian2} max The maximum bound. + * @param {Cartesian2} result The object into which to store the result. + * @returns {Cartesian2} The clamped value such that min <= result <= max. + */ + static clamp(value, min, max, result) { //>>includeStart('debug', pragmas.debug); - throw new DeveloperError( - "If result is a typed array, it must have exactly array.length * 2 elements", - ); + Check.typeOf.object("value", value); + Check.typeOf.object("min", min); + Check.typeOf.object("max", max); + Check.typeOf.object("result", result); //>>includeEnd('debug'); - } else if (result.length !== resultLength) { - result.length = resultLength; + + const x = CesiumMath.clamp(value.x, min.x, max.x); + const y = CesiumMath.clamp(value.y, min.y, max.y); + + result.x = x; + result.y = y; + + return result; } - for (let i = 0; i < length; ++i) { - Cartesian2.pack(array[i], result, i * 2); + /** + * Computes the provided Cartesian's squared magnitude. + * + * @param {Cartesian2} cartesian The Cartesian instance whose squared magnitude is to be computed. + * @returns {number} The squared magnitude. + */ + static magnitudeSquared(cartesian) { + //>>includeStart('debug', pragmas.debug); + Check.typeOf.object("cartesian", cartesian); + //>>includeEnd('debug'); + + return cartesian.x * cartesian.x + cartesian.y * cartesian.y; } - return result; -}; -/** - * Unpacks an array of cartesian components into an array of Cartesian2s. - * - * @param {number[]} array The array of components to unpack. - * @param {Cartesian2[]} [result] The array onto which to store the result. - * @returns {Cartesian2[]} The unpacked array. - */ -Cartesian2.unpackArray = function (array, result) { - //>>includeStart('debug', pragmas.debug); - Check.defined("array", array); - Check.typeOf.number.greaterThanOrEquals("array.length", array.length, 2); - if (array.length % 2 !== 0) { - throw new DeveloperError("array length must be a multiple of 2."); + /** + * Computes the Cartesian's magnitude (length). + * + * @param {Cartesian2} cartesian The Cartesian instance whose magnitude is to be computed. + * @returns {number} The magnitude. + */ + static magnitude(cartesian) { + return Math.sqrt(Cartesian2.magnitudeSquared(cartesian)); } - //>>includeEnd('debug'); - const length = array.length; - if (!defined(result)) { - result = new Array(length / 2); - } else { - result.length = length / 2; + /** + * Computes the distance between two points. + * + * @param {Cartesian2} left The first point to compute the distance from. + * @param {Cartesian2} right The second point to compute the distance to. + * @returns {number} The distance between two points. + * + * @example + * // Returns 1.0 + * const d = Cesium.Cartesian2.distance(new Cesium.Cartesian2(1.0, 0.0), new Cesium.Cartesian2(2.0, 0.0)); + */ + static distance(left, right) { + //>>includeStart('debug', pragmas.debug); + Check.typeOf.object("left", left); + Check.typeOf.object("right", right); + //>>includeEnd('debug'); + + Cartesian2.subtract(left, right, distanceScratch); + return Cartesian2.magnitude(distanceScratch); } - for (let i = 0; i < length; i += 2) { - const index = i / 2; - result[index] = Cartesian2.unpack(array, i, result[index]); + /** + * Computes the squared distance between two points. Comparing squared distances + * using this function is more efficient than comparing distances using {@link Cartesian2#distance}. + * + * @param {Cartesian2} left The first point to compute the distance from. + * @param {Cartesian2} right The second point to compute the distance to. + * @returns {number} The distance between two points. + * + * @example + * // Returns 4.0, not 2.0 + * const d = Cesium.Cartesian2.distance(new Cesium.Cartesian2(1.0, 0.0), new Cesium.Cartesian2(3.0, 0.0)); + */ + static distanceSquared(left, right) { + //>>includeStart('debug', pragmas.debug); + Check.typeOf.object("left", left); + Check.typeOf.object("right", right); + //>>includeEnd('debug'); + + Cartesian2.subtract(left, right, distanceScratch); + return Cartesian2.magnitudeSquared(distanceScratch); } - return result; -}; -/** - * Creates a Cartesian2 from two consecutive elements in an array. - * @function - * - * @param {number[]} array The array whose two consecutive elements correspond to the x and y components, respectively. - * @param {number} [startingIndex=0] The offset into the array of the first element, which corresponds to the x component. - * @param {Cartesian2} [result] The object onto which to store the result. - * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided. - * - * @example - * // Create a Cartesian2 with (1.0, 2.0) - * const v = [1.0, 2.0]; - * const p = Cesium.Cartesian2.fromArray(v); - * - * // Create a Cartesian2 with (1.0, 2.0) using an offset into an array - * const v2 = [0.0, 0.0, 1.0, 2.0]; - * const p2 = Cesium.Cartesian2.fromArray(v2, 2); - */ -Cartesian2.fromArray = Cartesian2.unpack; + /** + * Computes the normalized form of the supplied Cartesian. + * + * @param {Cartesian2} cartesian The Cartesian to be normalized. + * @param {Cartesian2} result The object onto which to store the result. + * @returns {Cartesian2} The modified result parameter. + */ + static normalize(cartesian, result) { + //>>includeStart('debug', pragmas.debug); + Check.typeOf.object("cartesian", cartesian); + Check.typeOf.object("result", result); + //>>includeEnd('debug'); -/** - * Computes the value of the maximum component for the supplied Cartesian. - * - * @param {Cartesian2} cartesian The cartesian to use. - * @returns {number} The value of the maximum component. - */ -Cartesian2.maximumComponent = function (cartesian) { - //>>includeStart('debug', pragmas.debug); - Check.typeOf.object("cartesian", cartesian); - //>>includeEnd('debug'); + const magnitude = Cartesian2.magnitude(cartesian); - return Math.max(cartesian.x, cartesian.y); -}; + result.x = cartesian.x / magnitude; + result.y = cartesian.y / magnitude; -/** - * Computes the value of the minimum component for the supplied Cartesian. - * - * @param {Cartesian2} cartesian The cartesian to use. - * @returns {number} The value of the minimum component. - */ -Cartesian2.minimumComponent = function (cartesian) { - //>>includeStart('debug', pragmas.debug); - Check.typeOf.object("cartesian", cartesian); - //>>includeEnd('debug'); + //>>includeStart('debug', pragmas.debug); + if (isNaN(result.x) || isNaN(result.y)) { + throw new DeveloperError("normalized result is not a number"); + } + //>>includeEnd('debug'); - return Math.min(cartesian.x, cartesian.y); -}; + return result; + } -/** - * Compares two Cartesians and computes a Cartesian which contains the minimum components of the supplied Cartesians. - * - * @param {Cartesian2} first A cartesian to compare. - * @param {Cartesian2} second A cartesian to compare. - * @param {Cartesian2} result The object into which to store the result. - * @returns {Cartesian2} A cartesian with the minimum components. - */ -Cartesian2.minimumByComponent = function (first, second, result) { - //>>includeStart('debug', pragmas.debug); - Check.typeOf.object("first", first); - Check.typeOf.object("second", second); - Check.typeOf.object("result", result); - //>>includeEnd('debug'); + /** + * Computes the dot (scalar) product of two Cartesians. + * + * @param {Cartesian2} left The first Cartesian. + * @param {Cartesian2} right The second Cartesian. + * @returns {number} The dot product. + */ + static dot(left, right) { + //>>includeStart('debug', pragmas.debug); + Check.typeOf.object("left", left); + Check.typeOf.object("right", right); + //>>includeEnd('debug'); - result.x = Math.min(first.x, second.x); - result.y = Math.min(first.y, second.y); + return left.x * right.x + left.y * right.y; + } - return result; -}; + /** + * Computes the magnitude of the cross product that would result from implicitly setting the Z coordinate of the input vectors to 0 + * + * @param {Cartesian2} left The first Cartesian. + * @param {Cartesian2} right The second Cartesian. + * @returns {number} The cross product. + */ + static cross(left, right) { + //>>includeStart('debug', pragmas.debug); + Check.typeOf.object("left", left); + Check.typeOf.object("right", right); + //>>includeEnd('debug'); -/** - * Compares two Cartesians and computes a Cartesian which contains the maximum components of the supplied Cartesians. - * - * @param {Cartesian2} first A cartesian to compare. - * @param {Cartesian2} second A cartesian to compare. - * @param {Cartesian2} result The object into which to store the result. - * @returns {Cartesian2} A cartesian with the maximum components. - */ -Cartesian2.maximumByComponent = function (first, second, result) { - //>>includeStart('debug', pragmas.debug); - Check.typeOf.object("first", first); - Check.typeOf.object("second", second); - Check.typeOf.object("result", result); - //>>includeEnd('debug'); - - result.x = Math.max(first.x, second.x); - result.y = Math.max(first.y, second.y); - return result; -}; + return left.x * right.y - left.y * right.x; + } -/** - * Constrain a value to lie between two values. - * - * @param {Cartesian2} value The value to clamp. - * @param {Cartesian2} min The minimum bound. - * @param {Cartesian2} max The maximum bound. - * @param {Cartesian2} result The object into which to store the result. - * @returns {Cartesian2} The clamped value such that min <= result <= max. - */ -Cartesian2.clamp = function (value, min, max, result) { - //>>includeStart('debug', pragmas.debug); - Check.typeOf.object("value", value); - Check.typeOf.object("min", min); - Check.typeOf.object("max", max); - Check.typeOf.object("result", result); - //>>includeEnd('debug'); + /** + * Computes the componentwise product of two Cartesians. + * + * @param {Cartesian2} left The first Cartesian. + * @param {Cartesian2} right The second Cartesian. + * @param {Cartesian2} result The object onto which to store the result. + * @returns {Cartesian2} The modified result parameter. + */ + static multiplyComponents(left, right, result) { + //>>includeStart('debug', pragmas.debug); + Check.typeOf.object("left", left); + Check.typeOf.object("right", right); + Check.typeOf.object("result", result); + //>>includeEnd('debug'); - const x = CesiumMath.clamp(value.x, min.x, max.x); - const y = CesiumMath.clamp(value.y, min.y, max.y); + result.x = left.x * right.x; + result.y = left.y * right.y; + return result; + } - result.x = x; - result.y = y; + /** + * Computes the componentwise quotient of two Cartesians. + * + * @param {Cartesian2} left The first Cartesian. + * @param {Cartesian2} right The second Cartesian. + * @param {Cartesian2} result The object onto which to store the result. + * @returns {Cartesian2} The modified result parameter. + */ + static divideComponents(left, right, result) { + //>>includeStart('debug', pragmas.debug); + Check.typeOf.object("left", left); + Check.typeOf.object("right", right); + Check.typeOf.object("result", result); + //>>includeEnd('debug'); - return result; -}; + result.x = left.x / right.x; + result.y = left.y / right.y; + return result; + } -/** - * Computes the provided Cartesian's squared magnitude. - * - * @param {Cartesian2} cartesian The Cartesian instance whose squared magnitude is to be computed. - * @returns {number} The squared magnitude. - */ -Cartesian2.magnitudeSquared = function (cartesian) { - //>>includeStart('debug', pragmas.debug); - Check.typeOf.object("cartesian", cartesian); - //>>includeEnd('debug'); + /** + * Computes the componentwise sum of two Cartesians. + * + * @param {Cartesian2} left The first Cartesian. + * @param {Cartesian2} right The second Cartesian. + * @param {Cartesian2} result The object onto which to store the result. + * @returns {Cartesian2} The modified result parameter. + */ + static add(left, right, result) { + //>>includeStart('debug', pragmas.debug); + Check.typeOf.object("left", left); + Check.typeOf.object("right", right); + Check.typeOf.object("result", result); + //>>includeEnd('debug'); - return cartesian.x * cartesian.x + cartesian.y * cartesian.y; -}; + result.x = left.x + right.x; + result.y = left.y + right.y; + return result; + } -/** - * Computes the Cartesian's magnitude (length). - * - * @param {Cartesian2} cartesian The Cartesian instance whose magnitude is to be computed. - * @returns {number} The magnitude. - */ -Cartesian2.magnitude = function (cartesian) { - return Math.sqrt(Cartesian2.magnitudeSquared(cartesian)); -}; + /** + * Computes the componentwise difference of two Cartesians. + * + * @param {Cartesian2} left The first Cartesian. + * @param {Cartesian2} right The second Cartesian. + * @param {Cartesian2} result The object onto which to store the result. + * @returns {Cartesian2} The modified result parameter. + */ + static subtract(left, right, result) { + //>>includeStart('debug', pragmas.debug); + Check.typeOf.object("left", left); + Check.typeOf.object("right", right); + Check.typeOf.object("result", result); + //>>includeEnd('debug'); -const distanceScratch = new Cartesian2(); + result.x = left.x - right.x; + result.y = left.y - right.y; + return result; + } -/** - * Computes the distance between two points. - * - * @param {Cartesian2} left The first point to compute the distance from. - * @param {Cartesian2} right The second point to compute the distance to. - * @returns {number} The distance between two points. - * - * @example - * // Returns 1.0 - * const d = Cesium.Cartesian2.distance(new Cesium.Cartesian2(1.0, 0.0), new Cesium.Cartesian2(2.0, 0.0)); - */ -Cartesian2.distance = function (left, right) { - //>>includeStart('debug', pragmas.debug); - Check.typeOf.object("left", left); - Check.typeOf.object("right", right); - //>>includeEnd('debug'); + /** + * Multiplies the provided Cartesian componentwise by the provided scalar. + * + * @param {Cartesian2} cartesian The Cartesian to be scaled. + * @param {number} scalar The scalar to multiply with. + * @param {Cartesian2} result The object onto which to store the result. + * @returns {Cartesian2} The modified result parameter. + */ + static multiplyByScalar(cartesian, scalar, result) { + //>>includeStart('debug', pragmas.debug); + Check.typeOf.object("cartesian", cartesian); + Check.typeOf.number("scalar", scalar); + Check.typeOf.object("result", result); + //>>includeEnd('debug'); - Cartesian2.subtract(left, right, distanceScratch); - return Cartesian2.magnitude(distanceScratch); -}; + result.x = cartesian.x * scalar; + result.y = cartesian.y * scalar; + return result; + } -/** - * Computes the squared distance between two points. Comparing squared distances - * using this function is more efficient than comparing distances using {@link Cartesian2#distance}. - * - * @param {Cartesian2} left The first point to compute the distance from. - * @param {Cartesian2} right The second point to compute the distance to. - * @returns {number} The distance between two points. - * - * @example - * // Returns 4.0, not 2.0 - * const d = Cesium.Cartesian2.distance(new Cesium.Cartesian2(1.0, 0.0), new Cesium.Cartesian2(3.0, 0.0)); - */ -Cartesian2.distanceSquared = function (left, right) { - //>>includeStart('debug', pragmas.debug); - Check.typeOf.object("left", left); - Check.typeOf.object("right", right); - //>>includeEnd('debug'); + /** + * Divides the provided Cartesian componentwise by the provided scalar. + * + * @param {Cartesian2} cartesian The Cartesian to be divided. + * @param {number} scalar The scalar to divide by. + * @param {Cartesian2} result The object onto which to store the result. + * @returns {Cartesian2} The modified result parameter. + */ + static divideByScalar(cartesian, scalar, result) { + //>>includeStart('debug', pragmas.debug); + Check.typeOf.object("cartesian", cartesian); + Check.typeOf.number("scalar", scalar); + Check.typeOf.object("result", result); + //>>includeEnd('debug'); - Cartesian2.subtract(left, right, distanceScratch); - return Cartesian2.magnitudeSquared(distanceScratch); -}; + result.x = cartesian.x / scalar; + result.y = cartesian.y / scalar; + return result; + } -/** - * Computes the normalized form of the supplied Cartesian. - * - * @param {Cartesian2} cartesian The Cartesian to be normalized. - * @param {Cartesian2} result The object onto which to store the result. - * @returns {Cartesian2} The modified result parameter. - */ -Cartesian2.normalize = function (cartesian, result) { - //>>includeStart('debug', pragmas.debug); - Check.typeOf.object("cartesian", cartesian); - Check.typeOf.object("result", result); - //>>includeEnd('debug'); + /** + * Negates the provided Cartesian. + * + * @param {Cartesian2} cartesian The Cartesian to be negated. + * @param {Cartesian2} result The object onto which to store the result. + * @returns {Cartesian2} The modified result parameter. + */ + static negate(cartesian, result) { + //>>includeStart('debug', pragmas.debug); + Check.typeOf.object("cartesian", cartesian); + Check.typeOf.object("result", result); + //>>includeEnd('debug'); - const magnitude = Cartesian2.magnitude(cartesian); + result.x = -cartesian.x; + result.y = -cartesian.y; + return result; + } - result.x = cartesian.x / magnitude; - result.y = cartesian.y / magnitude; + /** + * Computes the absolute value of the provided Cartesian. + * + * @param {Cartesian2} cartesian The Cartesian whose absolute value is to be computed. + * @param {Cartesian2} result The object onto which to store the result. + * @returns {Cartesian2} The modified result parameter. + */ + static abs(cartesian, result) { + //>>includeStart('debug', pragmas.debug); + Check.typeOf.object("cartesian", cartesian); + Check.typeOf.object("result", result); + //>>includeEnd('debug'); - //>>includeStart('debug', pragmas.debug); - if (isNaN(result.x) || isNaN(result.y)) { - throw new DeveloperError("normalized result is not a number"); + result.x = Math.abs(cartesian.x); + result.y = Math.abs(cartesian.y); + return result; } - //>>includeEnd('debug'); - return result; -}; + /** + * Computes the linear interpolation or extrapolation at t using the provided cartesians. + * + * @param {Cartesian2} start The value corresponding to t at 0.0. + * @param {Cartesian2} end The value corresponding to t at 1.0. + * @param {number} t The point along t at which to interpolate. + * @param {Cartesian2} result The object onto which to store the result. + * @returns {Cartesian2} The modified result parameter. + */ + static lerp(start, end, t, result) { + //>>includeStart('debug', pragmas.debug); + Check.typeOf.object("start", start); + Check.typeOf.object("end", end); + Check.typeOf.number("t", t); + Check.typeOf.object("result", result); + //>>includeEnd('debug'); -/** - * Computes the dot (scalar) product of two Cartesians. - * - * @param {Cartesian2} left The first Cartesian. - * @param {Cartesian2} right The second Cartesian. - * @returns {number} The dot product. - */ -Cartesian2.dot = function (left, right) { - //>>includeStart('debug', pragmas.debug); - Check.typeOf.object("left", left); - Check.typeOf.object("right", right); - //>>includeEnd('debug'); + Cartesian2.multiplyByScalar(end, t, lerpScratch); + result = Cartesian2.multiplyByScalar(start, 1.0 - t, result); + return Cartesian2.add(lerpScratch, result, result); + } - return left.x * right.x + left.y * right.y; -}; + /** + * Returns the angle, in radians, between the provided Cartesians. + * + * @param {Cartesian2} left The first Cartesian. + * @param {Cartesian2} right The second Cartesian. + * @returns {number} The angle between the Cartesians. + */ + static angleBetween(left, right) { + //>>includeStart('debug', pragmas.debug); + Check.typeOf.object("left", left); + Check.typeOf.object("right", right); + //>>includeEnd('debug'); -/** - * Computes the magnitude of the cross product that would result from implicitly setting the Z coordinate of the input vectors to 0 - * - * @param {Cartesian2} left The first Cartesian. - * @param {Cartesian2} right The second Cartesian. - * @returns {number} The cross product. - */ -Cartesian2.cross = function (left, right) { - //>>includeStart('debug', pragmas.debug); - Check.typeOf.object("left", left); - Check.typeOf.object("right", right); - //>>includeEnd('debug'); + Cartesian2.normalize(left, angleBetweenScratch); + Cartesian2.normalize(right, angleBetweenScratch2); + return CesiumMath.acosClamped( + Cartesian2.dot(angleBetweenScratch, angleBetweenScratch2), + ); + } - return left.x * right.y - left.y * right.x; -}; + /** + * Returns the axis that is most orthogonal to the provided Cartesian. + * + * @param {Cartesian2} cartesian The Cartesian on which to find the most orthogonal axis. + * @param {Cartesian2} result The object onto which to store the result. + * @returns {Cartesian2} The most orthogonal axis. + */ + static mostOrthogonalAxis(cartesian, result) { + //>>includeStart('debug', pragmas.debug); + Check.typeOf.object("cartesian", cartesian); + Check.typeOf.object("result", result); + //>>includeEnd('debug'); -/** - * Computes the componentwise product of two Cartesians. - * - * @param {Cartesian2} left The first Cartesian. - * @param {Cartesian2} right The second Cartesian. - * @param {Cartesian2} result The object onto which to store the result. - * @returns {Cartesian2} The modified result parameter. - */ -Cartesian2.multiplyComponents = function (left, right, result) { - //>>includeStart('debug', pragmas.debug); - Check.typeOf.object("left", left); - Check.typeOf.object("right", right); - Check.typeOf.object("result", result); - //>>includeEnd('debug'); - - result.x = left.x * right.x; - result.y = left.y * right.y; - return result; -}; + const f = Cartesian2.normalize(cartesian, mostOrthogonalAxisScratch); + Cartesian2.abs(f, f); -/** - * Computes the componentwise quotient of two Cartesians. - * - * @param {Cartesian2} left The first Cartesian. - * @param {Cartesian2} right The second Cartesian. - * @param {Cartesian2} result The object onto which to store the result. - * @returns {Cartesian2} The modified result parameter. - */ -Cartesian2.divideComponents = function (left, right, result) { - //>>includeStart('debug', pragmas.debug); - Check.typeOf.object("left", left); - Check.typeOf.object("right", right); - Check.typeOf.object("result", result); - //>>includeEnd('debug'); - - result.x = left.x / right.x; - result.y = left.y / right.y; - return result; -}; + if (f.x <= f.y) { + result = Cartesian2.clone(Cartesian2.UNIT_X, result); + } else { + result = Cartesian2.clone(Cartesian2.UNIT_Y, result); + } -/** - * Computes the componentwise sum of two Cartesians. - * - * @param {Cartesian2} left The first Cartesian. - * @param {Cartesian2} right The second Cartesian. - * @param {Cartesian2} result The object onto which to store the result. - * @returns {Cartesian2} The modified result parameter. - */ -Cartesian2.add = function (left, right, result) { - //>>includeStart('debug', pragmas.debug); - Check.typeOf.object("left", left); - Check.typeOf.object("right", right); - Check.typeOf.object("result", result); - //>>includeEnd('debug'); - - result.x = left.x + right.x; - result.y = left.y + right.y; - return result; -}; + return result; + } -/** - * Computes the componentwise difference of two Cartesians. - * - * @param {Cartesian2} left The first Cartesian. - * @param {Cartesian2} right The second Cartesian. - * @param {Cartesian2} result The object onto which to store the result. - * @returns {Cartesian2} The modified result parameter. - */ -Cartesian2.subtract = function (left, right, result) { - //>>includeStart('debug', pragmas.debug); - Check.typeOf.object("left", left); - Check.typeOf.object("right", right); - Check.typeOf.object("result", result); - //>>includeEnd('debug'); - - result.x = left.x - right.x; - result.y = left.y - right.y; - return result; -}; + /** + * Compares the provided Cartesians componentwise and returns + * true if they are equal, false otherwise. + * + * @param {Cartesian2} [left] The first Cartesian. + * @param {Cartesian2} [right] The second Cartesian. + * @returns {boolean} true if left and right are equal, false otherwise. + */ + static equals(left, right) { + return ( + left === right || + (defined(left) && + defined(right) && + left.x === right.x && + left.y === right.y) + ); + } -/** - * Multiplies the provided Cartesian componentwise by the provided scalar. - * - * @param {Cartesian2} cartesian The Cartesian to be scaled. - * @param {number} scalar The scalar to multiply with. - * @param {Cartesian2} result The object onto which to store the result. - * @returns {Cartesian2} The modified result parameter. - */ -Cartesian2.multiplyByScalar = function (cartesian, scalar, result) { - //>>includeStart('debug', pragmas.debug); - Check.typeOf.object("cartesian", cartesian); - Check.typeOf.number("scalar", scalar); - Check.typeOf.object("result", result); - //>>includeEnd('debug'); - - result.x = cartesian.x * scalar; - result.y = cartesian.y * scalar; - return result; -}; + /** + * @private + */ + static equalsArray(cartesian, array, offset) { + return cartesian.x === array[offset] && cartesian.y === array[offset + 1]; + } -/** - * Divides the provided Cartesian componentwise by the provided scalar. - * - * @param {Cartesian2} cartesian The Cartesian to be divided. - * @param {number} scalar The scalar to divide by. - * @param {Cartesian2} result The object onto which to store the result. - * @returns {Cartesian2} The modified result parameter. - */ -Cartesian2.divideByScalar = function (cartesian, scalar, result) { - //>>includeStart('debug', pragmas.debug); - Check.typeOf.object("cartesian", cartesian); - Check.typeOf.number("scalar", scalar); - Check.typeOf.object("result", result); - //>>includeEnd('debug'); - - result.x = cartesian.x / scalar; - result.y = cartesian.y / scalar; - return result; -}; + /** + * Compares the provided Cartesians componentwise and returns + * true if they pass an absolute or relative tolerance test, + * false otherwise. + * + * @param {Cartesian2} [left] The first Cartesian. + * @param {Cartesian2} [right] The second Cartesian. + * @param {number} [relativeEpsilon=0] The relative epsilon tolerance to use for equality testing. + * @param {number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing. + * @returns {boolean} true if left and right are within the provided epsilon, false otherwise. + */ + static equalsEpsilon(left, right, relativeEpsilon, absoluteEpsilon) { + return ( + left === right || + (defined(left) && + defined(right) && + CesiumMath.equalsEpsilon( + left.x, + right.x, + relativeEpsilon, + absoluteEpsilon, + ) && + CesiumMath.equalsEpsilon( + left.y, + right.y, + relativeEpsilon, + absoluteEpsilon, + )) + ); + } -/** - * Negates the provided Cartesian. - * - * @param {Cartesian2} cartesian The Cartesian to be negated. - * @param {Cartesian2} result The object onto which to store the result. - * @returns {Cartesian2} The modified result parameter. - */ -Cartesian2.negate = function (cartesian, result) { - //>>includeStart('debug', pragmas.debug); - Check.typeOf.object("cartesian", cartesian); - Check.typeOf.object("result", result); - //>>includeEnd('debug'); + /** + * Duplicates this Cartesian2 instance. + * + * @param {Cartesian2} [result] The object onto which to store the result. + * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided. + */ + clone(result) { + return Cartesian2.clone(this, result); + } - result.x = -cartesian.x; - result.y = -cartesian.y; - return result; -}; + /** + * Compares this Cartesian against the provided Cartesian componentwise and returns + * true if they are equal, false otherwise. + * + * @param {Cartesian2} [right] The right hand side Cartesian. + * @returns {boolean} true if they are equal, false otherwise. + */ + equals(right) { + return Cartesian2.equals(this, right); + } -/** - * Computes the absolute value of the provided Cartesian. - * - * @param {Cartesian2} cartesian The Cartesian whose absolute value is to be computed. - * @param {Cartesian2} result The object onto which to store the result. - * @returns {Cartesian2} The modified result parameter. - */ -Cartesian2.abs = function (cartesian, result) { - //>>includeStart('debug', pragmas.debug); - Check.typeOf.object("cartesian", cartesian); - Check.typeOf.object("result", result); - //>>includeEnd('debug'); + /** + * Compares this Cartesian against the provided Cartesian componentwise and returns + * true if they pass an absolute or relative tolerance test, + * false otherwise. + * + * @param {Cartesian2} [right] The right hand side Cartesian. + * @param {number} [relativeEpsilon=0] The relative epsilon tolerance to use for equality testing. + * @param {number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing. + * @returns {boolean} true if they are within the provided epsilon, false otherwise. + */ + equalsEpsilon(right, relativeEpsilon, absoluteEpsilon) { + return Cartesian2.equalsEpsilon( + this, + right, + relativeEpsilon, + absoluteEpsilon, + ); + } - result.x = Math.abs(cartesian.x); - result.y = Math.abs(cartesian.y); - return result; -}; + /** + * Creates a string representing this Cartesian in the format '(x, y)'. + * + * @returns {string} A string representing the provided Cartesian in the format '(x, y)'. + */ + toString() { + return `(${this.x}, ${this.y})`; + } +} -const lerpScratch = new Cartesian2(); /** - * Computes the linear interpolation or extrapolation at t using the provided cartesians. + * Creates a Cartesian2 instance from an existing Cartesian3. This simply takes the + * x and y properties of the Cartesian3 and drops z. + * @function * - * @param {Cartesian2} start The value corresponding to t at 0.0. - * @param {Cartesian2} end The value corresponding to t at 1.0. - * @param {number} t The point along t at which to interpolate. - * @param {Cartesian2} result The object onto which to store the result. - * @returns {Cartesian2} The modified result parameter. + * @param {Cartesian3} cartesian The Cartesian3 instance to create a Cartesian2 instance from. + * @param {Cartesian2} [result] The object onto which to store the result. + * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided. */ -Cartesian2.lerp = function (start, end, t, result) { - //>>includeStart('debug', pragmas.debug); - Check.typeOf.object("start", start); - Check.typeOf.object("end", end); - Check.typeOf.number("t", t); - Check.typeOf.object("result", result); - //>>includeEnd('debug'); - - Cartesian2.multiplyByScalar(end, t, lerpScratch); - result = Cartesian2.multiplyByScalar(start, 1.0 - t, result); - return Cartesian2.add(lerpScratch, result, result); -}; +Cartesian2.fromCartesian3 = Cartesian2.clone; -const angleBetweenScratch = new Cartesian2(); -const angleBetweenScratch2 = new Cartesian2(); /** - * Returns the angle, in radians, between the provided Cartesians. + * Creates a Cartesian2 instance from an existing Cartesian4. This simply takes the + * x and y properties of the Cartesian4 and drops z and w. + * @function * - * @param {Cartesian2} left The first Cartesian. - * @param {Cartesian2} right The second Cartesian. - * @returns {number} The angle between the Cartesians. + * @param {Cartesian4} cartesian The Cartesian4 instance to create a Cartesian2 instance from. + * @param {Cartesian2} [result] The object onto which to store the result. + * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided. */ -Cartesian2.angleBetween = function (left, right) { - //>>includeStart('debug', pragmas.debug); - Check.typeOf.object("left", left); - Check.typeOf.object("right", right); - //>>includeEnd('debug'); - - Cartesian2.normalize(left, angleBetweenScratch); - Cartesian2.normalize(right, angleBetweenScratch2); - return CesiumMath.acosClamped( - Cartesian2.dot(angleBetweenScratch, angleBetweenScratch2), - ); -}; +Cartesian2.fromCartesian4 = Cartesian2.clone; -const mostOrthogonalAxisScratch = new Cartesian2(); /** - * Returns the axis that is most orthogonal to the provided Cartesian. - * - * @param {Cartesian2} cartesian The Cartesian on which to find the most orthogonal axis. - * @param {Cartesian2} result The object onto which to store the result. - * @returns {Cartesian2} The most orthogonal axis. + * The number of elements used to pack the object into an array. + * @type {number} */ -Cartesian2.mostOrthogonalAxis = function (cartesian, result) { - //>>includeStart('debug', pragmas.debug); - Check.typeOf.object("cartesian", cartesian); - Check.typeOf.object("result", result); - //>>includeEnd('debug'); - - const f = Cartesian2.normalize(cartesian, mostOrthogonalAxisScratch); - Cartesian2.abs(f, f); - - if (f.x <= f.y) { - result = Cartesian2.clone(Cartesian2.UNIT_X, result); - } else { - result = Cartesian2.clone(Cartesian2.UNIT_Y, result); - } - - return result; -}; +Cartesian2.packedLength = 2; /** - * Compares the provided Cartesians componentwise and returns - * true if they are equal, false otherwise. + * Creates a Cartesian2 from two consecutive elements in an array. + * @function + * + * @param {number[]} array The array whose two consecutive elements correspond to the x and y components, respectively. + * @param {number} [startingIndex=0] The offset into the array of the first element, which corresponds to the x component. + * @param {Cartesian2} [result] The object onto which to store the result. + * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided. * - * @param {Cartesian2} [left] The first Cartesian. - * @param {Cartesian2} [right] The second Cartesian. - * @returns {boolean} true if left and right are equal, false otherwise. + * @example + * // Create a Cartesian2 with (1.0, 2.0) + * const v = [1.0, 2.0]; + * const p = Cesium.Cartesian2.fromArray(v); + * + * // Create a Cartesian2 with (1.0, 2.0) using an offset into an array + * const v2 = [0.0, 0.0, 1.0, 2.0]; + * const p2 = Cesium.Cartesian2.fromArray(v2, 2); */ -Cartesian2.equals = function (left, right) { - return ( - left === right || - (defined(left) && - defined(right) && - left.x === right.x && - left.y === right.y) - ); -}; +Cartesian2.fromArray = Cartesian2.unpack; -/** - * @private - */ -Cartesian2.equalsArray = function (cartesian, array, offset) { - return cartesian.x === array[offset] && cartesian.y === array[offset + 1]; -}; +const distanceScratch = new Cartesian2(); -/** - * Compares the provided Cartesians componentwise and returns - * true if they pass an absolute or relative tolerance test, - * false otherwise. - * - * @param {Cartesian2} [left] The first Cartesian. - * @param {Cartesian2} [right] The second Cartesian. - * @param {number} [relativeEpsilon=0] The relative epsilon tolerance to use for equality testing. - * @param {number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing. - * @returns {boolean} true if left and right are within the provided epsilon, false otherwise. - */ -Cartesian2.equalsEpsilon = function ( - left, - right, - relativeEpsilon, - absoluteEpsilon, -) { - return ( - left === right || - (defined(left) && - defined(right) && - CesiumMath.equalsEpsilon( - left.x, - right.x, - relativeEpsilon, - absoluteEpsilon, - ) && - CesiumMath.equalsEpsilon( - left.y, - right.y, - relativeEpsilon, - absoluteEpsilon, - )) - ); -}; +const lerpScratch = new Cartesian2(); + +const angleBetweenScratch = new Cartesian2(); +const angleBetweenScratch2 = new Cartesian2(); + +const mostOrthogonalAxisScratch = new Cartesian2(); /** * An immutable Cartesian2 instance initialized to (0.0, 0.0). @@ -768,56 +823,4 @@ Cartesian2.UNIT_X = Object.freeze(new Cartesian2(1.0, 0.0)); */ Cartesian2.UNIT_Y = Object.freeze(new Cartesian2(0.0, 1.0)); -/** - * Duplicates this Cartesian2 instance. - * - * @param {Cartesian2} [result] The object onto which to store the result. - * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided. - */ -Cartesian2.prototype.clone = function (result) { - return Cartesian2.clone(this, result); -}; - -/** - * Compares this Cartesian against the provided Cartesian componentwise and returns - * true if they are equal, false otherwise. - * - * @param {Cartesian2} [right] The right hand side Cartesian. - * @returns {boolean} true if they are equal, false otherwise. - */ -Cartesian2.prototype.equals = function (right) { - return Cartesian2.equals(this, right); -}; - -/** - * Compares this Cartesian against the provided Cartesian componentwise and returns - * true if they pass an absolute or relative tolerance test, - * false otherwise. - * - * @param {Cartesian2} [right] The right hand side Cartesian. - * @param {number} [relativeEpsilon=0] The relative epsilon tolerance to use for equality testing. - * @param {number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing. - * @returns {boolean} true if they are within the provided epsilon, false otherwise. - */ -Cartesian2.prototype.equalsEpsilon = function ( - right, - relativeEpsilon, - absoluteEpsilon, -) { - return Cartesian2.equalsEpsilon( - this, - right, - relativeEpsilon, - absoluteEpsilon, - ); -}; - -/** - * Creates a string representing this Cartesian in the format '(x, y)'. - * - * @returns {string} A string representing the provided Cartesian in the format '(x, y)'. - */ -Cartesian2.prototype.toString = function () { - return `(${this.x}, ${this.y})`; -}; export default Cartesian2;