mirror of https://github.com/CesiumGS/cesium.git
148 lines
3.7 KiB
JavaScript
148 lines
3.7 KiB
JavaScript
import DeveloperError from "./DeveloperError.js";
|
|
import CesiumMath from "./Math.js";
|
|
|
|
/**
|
|
* Defines functions for 2nd order polynomial functions of one variable with only real coefficients.
|
|
*
|
|
* @namespace QuadraticRealPolynomial
|
|
*/
|
|
const QuadraticRealPolynomial = {};
|
|
|
|
/**
|
|
* Provides the discriminant of the quadratic equation from the supplied coefficients.
|
|
*
|
|
* @param {number} a The coefficient of the 2nd order monomial.
|
|
* @param {number} b The coefficient of the 1st order monomial.
|
|
* @param {number} c The coefficient of the 0th order monomial.
|
|
* @returns {number} The value of the discriminant.
|
|
*/
|
|
QuadraticRealPolynomial.computeDiscriminant = function (a, b, c) {
|
|
//>>includeStart('debug', pragmas.debug);
|
|
if (typeof a !== "number") {
|
|
throw new DeveloperError("a is a required number.");
|
|
}
|
|
if (typeof b !== "number") {
|
|
throw new DeveloperError("b is a required number.");
|
|
}
|
|
if (typeof c !== "number") {
|
|
throw new DeveloperError("c is a required number.");
|
|
}
|
|
//>>includeEnd('debug');
|
|
|
|
const discriminant = b * b - 4.0 * a * c;
|
|
return discriminant;
|
|
};
|
|
|
|
function addWithCancellationCheck(left, right, tolerance) {
|
|
const difference = left + right;
|
|
if (
|
|
CesiumMath.sign(left) !== CesiumMath.sign(right) &&
|
|
Math.abs(difference / Math.max(Math.abs(left), Math.abs(right))) < tolerance
|
|
) {
|
|
return 0.0;
|
|
}
|
|
|
|
return difference;
|
|
}
|
|
|
|
/**
|
|
* Provides the real valued roots of the quadratic polynomial with the provided coefficients.
|
|
*
|
|
* @param {number} a The coefficient of the 2nd order monomial.
|
|
* @param {number} b The coefficient of the 1st order monomial.
|
|
* @param {number} c The coefficient of the 0th order monomial.
|
|
* @returns {number[]} The real valued roots.
|
|
*/
|
|
QuadraticRealPolynomial.computeRealRoots = function (a, b, c) {
|
|
//>>includeStart('debug', pragmas.debug);
|
|
if (typeof a !== "number") {
|
|
throw new DeveloperError("a is a required number.");
|
|
}
|
|
if (typeof b !== "number") {
|
|
throw new DeveloperError("b is a required number.");
|
|
}
|
|
if (typeof c !== "number") {
|
|
throw new DeveloperError("c is a required number.");
|
|
}
|
|
//>>includeEnd('debug');
|
|
|
|
let ratio;
|
|
if (a === 0.0) {
|
|
if (b === 0.0) {
|
|
// Constant function: c = 0.
|
|
return [];
|
|
}
|
|
|
|
// Linear function: b * x + c = 0.
|
|
return [-c / b];
|
|
} else if (b === 0.0) {
|
|
if (c === 0.0) {
|
|
// 2nd order monomial: a * x^2 = 0.
|
|
return [0.0, 0.0];
|
|
}
|
|
|
|
const cMagnitude = Math.abs(c);
|
|
const aMagnitude = Math.abs(a);
|
|
|
|
if (
|
|
cMagnitude < aMagnitude &&
|
|
cMagnitude / aMagnitude < CesiumMath.EPSILON14
|
|
) {
|
|
// c ~= 0.0.
|
|
// 2nd order monomial: a * x^2 = 0.
|
|
return [0.0, 0.0];
|
|
} else if (
|
|
cMagnitude > aMagnitude &&
|
|
aMagnitude / cMagnitude < CesiumMath.EPSILON14
|
|
) {
|
|
// a ~= 0.0.
|
|
// Constant function: c = 0.
|
|
return [];
|
|
}
|
|
|
|
// a * x^2 + c = 0
|
|
ratio = -c / a;
|
|
|
|
if (ratio < 0.0) {
|
|
// Both roots are complex.
|
|
return [];
|
|
}
|
|
|
|
// Both roots are real.
|
|
const root = Math.sqrt(ratio);
|
|
return [-root, root];
|
|
} else if (c === 0.0) {
|
|
// a * x^2 + b * x = 0
|
|
ratio = -b / a;
|
|
if (ratio < 0.0) {
|
|
return [ratio, 0.0];
|
|
}
|
|
|
|
return [0.0, ratio];
|
|
}
|
|
|
|
// a * x^2 + b * x + c = 0
|
|
const b2 = b * b;
|
|
const four_ac = 4.0 * a * c;
|
|
const radicand = addWithCancellationCheck(b2, -four_ac, CesiumMath.EPSILON14);
|
|
|
|
if (radicand < 0.0) {
|
|
// Both roots are complex.
|
|
return [];
|
|
}
|
|
|
|
const q =
|
|
-0.5 *
|
|
addWithCancellationCheck(
|
|
b,
|
|
CesiumMath.sign(b) * Math.sqrt(radicand),
|
|
CesiumMath.EPSILON14,
|
|
);
|
|
if (b > 0.0) {
|
|
return [q / a, c / q];
|
|
}
|
|
|
|
return [c / q, q / a];
|
|
};
|
|
export default QuadraticRealPolynomial;
|