cesium-native  0.41.0
Math.h
1 #pragma once
2 
3 #include "Library.h"
4 
5 #include <glm/gtc/epsilon.hpp>
6 
7 namespace CesiumUtility {
8 
12 class CESIUMUTILITY_API Math final {
13 public:
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 constexpr double Epsilon14
0.00000000000001
Definition: Math.h:54
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 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 constexpr double TwoPi
two times pi
Definition: Math.h:85
static constexpr double OnePi
pi
Definition: Math.h:80
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 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 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 constexpr bool 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 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 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 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 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 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.