cesium-native 0.43.0
Loading...
Searching...
No Matches
Math.h
1#pragma once
2
3#include "Library.h"
4
5#include <glm/gtc/epsilon.hpp>
6
7namespace CesiumUtility {
8
12class CESIUMUTILITY_API Math final {
13public:
15 static constexpr double Epsilon1 = 1e-1;
16
18 static constexpr double Epsilon2 = 1e-2;
19
21 static constexpr double Epsilon3 = 1e-3;
22
24 static constexpr double Epsilon4 = 1e-4;
25
27 static constexpr double Epsilon5 = 1e-5;
28
30 static constexpr double Epsilon6 = 1e-6;
31
33 static constexpr double Epsilon7 = 1e-7;
34
36 static constexpr double Epsilon8 = 1e-8;
37
39 static constexpr double Epsilon9 = 1e-9;
40
42 static constexpr double Epsilon10 = 1e-10;
43
45 static constexpr double Epsilon11 = 1e-11;
46
48 static constexpr double Epsilon12 = 1e-12;
49
51 static constexpr double Epsilon13 = 1e-13;
52
54 static constexpr double Epsilon14 = 1e-14;
55
57 static constexpr double Epsilon15 = 1e-15;
58
60 static constexpr double Epsilon16 = 1e-16;
61
63 static constexpr double Epsilon17 = 1e-17;
64
66 static constexpr double Epsilon18 = 1e-18;
67
69 static constexpr double Epsilon19 = 1e-19;
70
72 static constexpr double Epsilon20 = 1e-20;
73
75 static constexpr double Epsilon21 = 1e-21;
76
80 static constexpr double OnePi = 3.14159265358979323846;
81
85 static constexpr double TwoPi = OnePi * 2.0;
86
90 static constexpr double PiOverTwo = OnePi / 2.0;
91
105 template <glm::length_t L, typename T, glm::qualifier Q>
106 static constexpr glm::vec<L, T, Q> relativeEpsilonToAbsolute(
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));
111 }
112
122 static constexpr double relativeEpsilonToAbsolute(
123 double a,
124 double b,
125 double relativeEpsilon) noexcept {
126 return relativeEpsilon * glm::max(glm::abs(a), glm::abs(b));
127 }
128
141 template <glm::length_t L, typename T, glm::qualifier Q>
142 static bool constexpr equalsEpsilon(
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);
147 }
148
157 static constexpr bool
158 equalsEpsilon(double left, double right, double relativeEpsilon) noexcept {
159 return equalsEpsilon(left, right, relativeEpsilon, relativeEpsilon);
160 }
161
183 static constexpr bool equalsEpsilon(
184 double left,
185 double right,
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);
191 }
192
216 template <glm::length_t L, typename T, glm::qualifier Q>
217 static constexpr bool equalsEpsilon(
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) ||
225 glm::lessThanEqual(
226 diff,
227 relativeEpsilonToAbsolute(left, right, relativeEpsilon)) ==
228 glm::vec<L, bool, Q>(true);
229 }
230
240 static constexpr double sign(double value) noexcept {
241 if (value == 0.0 || value != value) {
242 // zero or NaN
243 return value;
244 }
245 return value > 0 ? 1 : -1;
246 }
247
258 static constexpr double signNotZero(double value) noexcept {
259 return value < 0.0 ? -1.0 : 1.0;
260 }
261
269 static double negativePiToPi(double angle) noexcept {
270 if (angle >= -Math::OnePi && angle <= Math::OnePi) {
271 // Early exit if the input is already inside the range. This avoids
272 // unnecessary math which could introduce floating point error.
273 return angle;
274 }
275 return Math::zeroToTwoPi(angle + Math::OnePi) - Math::OnePi;
276 }
277
285 static double zeroToTwoPi(double angle) noexcept {
286 if (angle >= 0 && angle <= Math::TwoPi) {
287 // Early exit if the input is already inside the range. This avoids
288 // unnecessary math which could introduce floating point error.
289 return angle;
290 }
291 const double mod = Math::mod(angle, Math::TwoPi);
292 if (glm::abs(mod) < Math::Epsilon14 && glm::abs(angle) > Math::Epsilon14) {
293 return Math::TwoPi;
294 }
295 return mod;
296 }
297
305 static double mod(double m, double n) noexcept {
306 if (Math::sign(m) == Math::sign(n) && glm::abs(m) < glm::abs(n)) {
307 // Early exit if the input does not need to be modded. This avoids
308 // unnecessary math which could introduce floating point error.
309 return m;
310 }
311 return fmod(fmod(m, n) + n, n);
312 }
313
320 static constexpr double degreesToRadians(double angleDegrees) noexcept {
321 return angleDegrees * Math::OnePi / 180.0;
322 }
323
330 static constexpr double radiansToDegrees(double angleRadians) noexcept {
331 return angleRadians * 180.0 / Math::OnePi;
332 }
333
344 static double lerp(double p, double q, double time) noexcept {
345 return glm::mix(p, q, time);
346 }
347
356 static constexpr double clamp(double value, double min, double max) noexcept {
357 return glm::clamp(value, min, max);
358 };
359
370 static double toSNorm(double value, double rangeMaximum = 255.0) noexcept {
371 return glm::round(
372 (Math::clamp(value, -1.0, 1.0) * 0.5 + 0.5) * rangeMaximum);
373 };
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;
387 }
388
400 static double convertLongitudeRange(double angle) noexcept {
401 constexpr double twoPi = Math::TwoPi;
402
403 const double simplified = angle - glm::floor(angle / twoPi) * twoPi;
404
405 if (simplified < -Math::OnePi) {
406 return simplified + twoPi;
407 }
408 if (simplified >= Math::OnePi) {
409 return simplified - twoPi;
410 }
411
412 return simplified;
413 };
414
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) {
429 return down;
430 } else {
431 return up;
432 }
433 }
434
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) {
449 return up;
450 } else {
451 return down;
452 }
453 }
454
460 template <typename T, glm::qualifier Q>
461 static glm::vec<3, T, Q> perpVec(const glm::vec<3, T, Q>& v) {
462 // This constructs a vector whose dot product with v will be 0, hence
463 // perpendicular to v. As seen in the "Physically Based Rendering".
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);
466 }
467 return glm::vec<3, T, Q>(0, v.z, -v.y) / std::sqrt(v.y * v.y + v.z * v.z);
468 }
469
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) {
478 // If we take the dot and cross products of the two vectors and store
479 // them in a quaternion, that quaternion represents twice the required
480 // rotation. We get the correct quaternion by "averaging" with the zero
481 // rotation quaternion, in a way analagous to finding the half vector
482 // between two 3D vectors.
483 auto cosRot = dot(vec1, vec2);
484 auto rotAxis = cross(vec1, vec2);
485 auto rotAxisLen2 = dot(rotAxis, rotAxis);
486 // Not using epsilon for these tests. If abs(cosRot) < 1.0, we can still
487 // create a sensible rotation.
488 if (cosRot >= 1 || (rotAxisLen2 == 0 && cosRot > 0)) {
489 // zero rotation
490 return glm::qua<T, Q>(1, 0, 0, 0);
491 }
492 if (cosRot <= -1 || (rotAxisLen2 == 0 && cosRot < 0)) {
493 auto perpAxis = CesiumUtility::Math::perpVec(vec1);
494 // rotation by pi radians
495 return glm::qua<T, Q>(0, perpAxis);
496 }
497
498 glm::qua<T, Q> sumQuat(cosRot + 1, rotAxis);
499 return normalize(sumQuat);
500 }
501};
502
503} // namespace CesiumUtility
Mathematical constants and functions.
Definition Math.h:12
static double mod(double m, double n) noexcept
The modulo operation that also works for negative dividends.
Definition Math.h:305
static constexpr double radiansToDegrees(double angleRadians) noexcept
Converts radians to degrees.
Definition Math.h:330
static constexpr double degreesToRadians(double angleDegrees) noexcept
Converts degrees to radians.
Definition Math.h:320
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.
Definition Math.h:217
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.
Definition Math.h:477
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.
Definition Math.h:106
static glm::vec< 3, T, Q > perpVec(const glm::vec< 3, T, Q > &v)
Construct a vector perpendicular to the argument.
Definition Math.h:461
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.
Definition Math.h:183
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].
Definition Math.h:370
static constexpr double sign(double value) noexcept
Returns the sign of the value.
Definition Math.h:240
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.
Definition Math.h:142
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...
Definition Math.h:425
static double negativePiToPi(double angle) noexcept
Produces an angle in the range -Pi <= angle <= Pi which is equivalent to the provided angle.
Definition Math.h:269
static double zeroToTwoPi(double angle) noexcept
Produces an angle in the range 0 <= angle <= 2Pi which is equivalent to the provided angle.
Definition Math.h:285
static constexpr bool equalsEpsilon(double left, double right, double relativeEpsilon) noexcept
Checks whether two values are equal up to a given relative epsilon.
Definition Math.h:158
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...
Definition Math.h:445
static constexpr double clamp(double value, double min, double max) noexcept
Constrain a value to lie between two values.
Definition Math.h:356
static double lerp(double p, double q, double time) noexcept
Computes the linear interpolation of two values.
Definition Math.h:344
static double convertLongitudeRange(double angle) noexcept
Definition Math.h:400
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.
Definition Math.h:258
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.
Definition Math.h:122
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....
Definition Math.h:385
Utility classes for Cesium.