5#include <glm/gtc/epsilon.hpp>
12class CESIUMUTILITY_API
Math final {
15 static constexpr double Epsilon1 = 1e-1;
18 static constexpr double Epsilon2 = 1e-2;
21 static constexpr double Epsilon3 = 1e-3;
24 static constexpr double Epsilon4 = 1e-4;
27 static constexpr double Epsilon5 = 1e-5;
30 static constexpr double Epsilon6 = 1e-6;
33 static constexpr double Epsilon7 = 1e-7;
36 static constexpr double Epsilon8 = 1e-8;
39 static constexpr double Epsilon9 = 1e-9;
42 static constexpr double Epsilon10 = 1e-10;
45 static constexpr double Epsilon11 = 1e-11;
48 static constexpr double Epsilon12 = 1e-12;
51 static constexpr double Epsilon13 = 1e-13;
54 static constexpr double Epsilon14 = 1e-14;
57 static constexpr double Epsilon15 = 1e-15;
60 static constexpr double Epsilon16 = 1e-16;
63 static constexpr double Epsilon17 = 1e-17;
66 static constexpr double Epsilon18 = 1e-18;
69 static constexpr double Epsilon19 = 1e-19;
72 static constexpr double Epsilon20 = 1e-20;
75 static constexpr double Epsilon21 = 1e-21;
80 static constexpr double OnePi = 3.14159265358979323846;
85 static constexpr double TwoPi = OnePi * 2.0;
90 static constexpr double PiOverTwo = OnePi / 2.0;
105 template <glm::length_t L,
typename T, glm::qualifier Q>
107 const glm::vec<L, T, Q>& a,
108 const glm::vec<L, T, Q>& b,
109 double relativeEpsilon)
noexcept {
110 return relativeEpsilon * glm::max(glm::abs(a), glm::abs(b));
125 double relativeEpsilon)
noexcept {
126 return relativeEpsilon * glm::max(glm::abs(a), glm::abs(b));
141 template <glm::length_t L,
typename T, glm::qualifier Q>
143 const glm::vec<L, T, Q>& left,
144 const glm::vec<L, T, Q>& right,
145 double relativeEpsilon)
noexcept {
146 return Math::equalsEpsilon(left, right, relativeEpsilon, relativeEpsilon);
157 static constexpr bool
159 return equalsEpsilon(left, right, relativeEpsilon, relativeEpsilon);
186 double relativeEpsilon,
187 double absoluteEpsilon)
noexcept {
188 const double diff = glm::abs(left - right);
189 return diff <= absoluteEpsilon ||
190 diff <= relativeEpsilonToAbsolute(left, right, relativeEpsilon);
216 template <glm::length_t L,
typename T, glm::qualifier Q>
218 const glm::vec<L, T, Q>& left,
219 const glm::vec<L, T, Q>& right,
220 double relativeEpsilon,
221 double absoluteEpsilon)
noexcept {
222 const glm::vec<L, T, Q> diff = glm::abs(left - right);
223 return glm::lessThanEqual(diff, glm::vec<L, T, Q>(absoluteEpsilon)) ==
224 glm::vec<L, bool, Q>(
true) ||
227 relativeEpsilonToAbsolute(left, right, relativeEpsilon)) ==
228 glm::vec<L, bool, Q>(
true);
240 static constexpr double sign(
double value)
noexcept {
241 if (value == 0.0 || value != value) {
245 return value > 0 ? 1 : -1;
259 return value < 0.0 ? -1.0 : 1.0;
270 if (angle >= -Math::OnePi && angle <= Math::OnePi) {
275 return Math::zeroToTwoPi(angle + Math::OnePi) - Math::OnePi;
286 if (angle >= 0 && angle <= Math::TwoPi) {
291 const double mod = Math::mod(angle, Math::TwoPi);
292 if (glm::abs(mod) < Math::Epsilon14 && glm::abs(angle) > Math::Epsilon14) {
305 static double mod(
double m,
double n)
noexcept {
306 if (Math::sign(m) == Math::sign(n) && glm::abs(m) < glm::abs(n)) {
311 return fmod(fmod(m, n) + n, n);
321 return angleDegrees * Math::OnePi / 180.0;
331 return angleRadians * 180.0 / Math::OnePi;
344 static double lerp(
double p,
double q,
double time)
noexcept {
345 return glm::mix(p, q, time);
356 static constexpr double clamp(
double value,
double min,
double max)
noexcept {
357 return glm::clamp(value, min, max);
370 static double toSNorm(
double value,
double rangeMaximum = 255.0) noexcept {
372 (Math::clamp(value, -1.0, 1.0) * 0.5 + 0.5) * rangeMaximum);
384 static constexpr double
385 fromSNorm(
double value,
double rangeMaximum = 255.0) noexcept {
386 return (Math::clamp(value, 0.0, rangeMaximum) / rangeMaximum) * 2.0 - 1.0;
401 constexpr double twoPi = Math::TwoPi;
403 const double simplified = angle - glm::floor(angle / twoPi) * twoPi;
405 if (simplified < -Math::OnePi) {
406 return simplified + twoPi;
408 if (simplified >= Math::OnePi) {
409 return simplified - twoPi;
425 static double roundUp(
double value,
double tolerance)
noexcept {
426 const double up = glm::ceil(value);
427 const double down = glm::floor(value);
428 if (value - down < tolerance) {
445 static double roundDown(
double value,
double tolerance)
noexcept {
446 const double up = glm::ceil(value);
447 const double down = glm::floor(value);
448 if (up - value < tolerance) {
460 template <
typename T, glm::qualifier Q>
461 static glm::vec<3, T, Q>
perpVec(
const glm::vec<3, T, Q>& v) {
464 if (std::abs(v.x) > std::abs(v.y)) {
465 return glm::vec<3, T, Q>(-v.z, 0, v.x) / std::sqrt(v.x * v.x + v.z * v.z);
467 return glm::vec<3, T, Q>(0, v.z, -v.y) / std::sqrt(v.y * v.y + v.z * v.z);
475 template <
typename T, glm::qualifier Q>
476 static glm::qua<T, Q>
477 rotation(
const glm::vec<3, T, Q>& vec1,
const glm::vec<3, T, Q>& vec2) {
483 auto cosRot = dot(vec1, vec2);
484 auto rotAxis = cross(vec1, vec2);
485 auto rotAxisLen2 = dot(rotAxis, rotAxis);
488 if (cosRot >= 1 || (rotAxisLen2 == 0 && cosRot > 0)) {
490 return glm::qua<T, Q>(1, 0, 0, 0);
492 if (cosRot <= -1 || (rotAxisLen2 == 0 && cosRot < 0)) {
495 return glm::qua<T, Q>(0, perpAxis);
498 glm::qua<T, Q> sumQuat(cosRot + 1, rotAxis);
499 return normalize(sumQuat);
Mathematical constants and functions.
static double mod(double m, double n) noexcept
The modulo operation that also works for negative dividends.
static constexpr double radiansToDegrees(double angleRadians) noexcept
Converts radians to degrees.
static constexpr double degreesToRadians(double angleDegrees) noexcept
Converts degrees to radians.
static constexpr bool equalsEpsilon(const glm::vec< L, T, Q > &left, const glm::vec< L, T, Q > &right, double relativeEpsilon, double absoluteEpsilon) noexcept
Determines if two values are equal using an absolute or relative tolerance test.
static glm::qua< T, Q > rotation(const glm::vec< 3, T, Q > &vec1, const glm::vec< 3, T, Q > &vec2)
Compute the rotation between two unit vectors.
static constexpr glm::vec< L, T, Q > relativeEpsilonToAbsolute(const glm::vec< L, T, Q > &a, const glm::vec< L, T, Q > &b, double relativeEpsilon) noexcept
Converts a relative to an absolute epsilon, for the epsilon-equality check between two values.
static glm::vec< 3, T, Q > perpVec(const glm::vec< 3, T, Q > &v)
Construct a vector perpendicular to the argument.
static constexpr bool equalsEpsilon(double left, double right, double relativeEpsilon, double absoluteEpsilon) noexcept
Determines if two values are equal using an absolute or relative tolerance test.
static double toSNorm(double value, double rangeMaximum=255.0) noexcept
Converts a scalar value in the range [-1.0, 1.0] to a SNORM in the range [0, rangeMaximum].
static constexpr double sign(double value) noexcept
Returns the sign of the value.
static bool constexpr equalsEpsilon(const glm::vec< L, T, Q > &left, const glm::vec< L, T, Q > &right, double relativeEpsilon) noexcept
Checks whether two values are equal up to a given relative epsilon.
static double roundUp(double value, double tolerance) noexcept
Rounds a value up to the nearest integer, like ceil, except that if the value is very close to the lo...
static double negativePiToPi(double angle) noexcept
Produces an angle in the range -Pi <= angle <= Pi which is equivalent to the provided angle.
static double zeroToTwoPi(double angle) noexcept
Produces an angle in the range 0 <= angle <= 2Pi which is equivalent to the provided angle.
static constexpr bool equalsEpsilon(double left, double right, double relativeEpsilon) noexcept
Checks whether two values are equal up to a given relative epsilon.
static double roundDown(double value, double tolerance) noexcept
Rounds a value down to the nearest integer, like floor, except that if the value is very close to the...
static constexpr double clamp(double value, double min, double max) noexcept
Constrain a value to lie between two values.
static double lerp(double p, double q, double time) noexcept
Computes the linear interpolation of two values.
static double convertLongitudeRange(double angle) noexcept
static constexpr double signNotZero(double value) noexcept
Returns 1.0 if the given value is positive or zero, and -1.0 if it is negative.
static constexpr double relativeEpsilonToAbsolute(double a, double b, double relativeEpsilon) noexcept
Converts a relative to an absolute epsilon, for the epsilon-equality check between two values.
static constexpr double fromSNorm(double value, double rangeMaximum=255.0) noexcept
Converts a SNORM value in the range [0, rangeMaximum] to a scalar in the range [-1....
Utility classes for Cesium.