Home | History | Annotate | Download | only in dvr
      1 #ifndef ANDROID_DVR_NUMERIC_H_
      2 #define ANDROID_DVR_NUMERIC_H_
      3 
      4 #include <cmath>
      5 #include <limits>
      6 #include <random>
      7 #include <type_traits>
      8 
      9 #include <private/dvr/eigen.h>
     10 #include <private/dvr/types.h>
     11 
     12 namespace android {
     13 namespace dvr {
     14 
     15 template <typename FT>
     16 static inline FT ToDeg(FT f) {
     17   return f * static_cast<FT>(180.0 / M_PI);
     18 }
     19 
     20 template <typename FT>
     21 static inline FT ToRad(FT f) {
     22   return f * static_cast<FT>(M_PI / 180.0);
     23 }
     24 
     25 // Adjusts `x` to the periodic range `[lo, hi]` (to normalize angle values
     26 // for example).
     27 template <typename T>
     28 T NormalizePeriodicRange(T x, T lo, T hi) {
     29   T range_size = hi - lo;
     30 
     31   while (x < lo) {
     32     x += range_size;
     33   }
     34 
     35   while (x > hi) {
     36     x -= range_size;
     37   }
     38 
     39   return x;
     40 }
     41 
     42 // Normalizes a measurement in radians.
     43 // @param x the angle to be normalized
     44 // @param centre the point around which to normalize the range
     45 // @return the value of x, normalized to the range [centre - 180, centre + 180]
     46 template <typename T>
     47 T NormalizeDegrees(T x, T centre = static_cast<T>(180.0)) {
     48   return NormalizePeriodicRange(x, centre - static_cast<T>(180.0),
     49                                 centre + static_cast<T>(180.0));
     50 }
     51 
     52 // Normalizes a measurement in radians.
     53 // @param x the angle to be normalized
     54 // @param centre the point around which to normalize the range
     55 // @return the value of x, normalized to the range
     56 //         [centre - M_PI, centre + M_PI]
     57 // @remark the centre parameter is to make it possible to specify a different
     58 //         periodic range. This is useful if you are planning on comparing two
     59 //         angles close to 0 or M_PI, so that one might not accidentally end
     60 //         up on the other side of the range
     61 template <typename T>
     62 T NormalizeRadians(T x, T centre = static_cast<T>(M_PI)) {
     63   return NormalizePeriodicRange(x, centre - static_cast<T>(M_PI),
     64                                 centre + static_cast<T>(M_PI));
     65 }
     66 
     67 static inline vec2i Round(const vec2& v) {
     68   return vec2i(roundf(v.x()), roundf(v.y()));
     69 }
     70 
     71 static inline vec2i Scale(const vec2i& v, float scale) {
     72   return vec2i(roundf(static_cast<float>(v.x()) * scale),
     73                roundf(static_cast<float>(v.y()) * scale));
     74 }
     75 
     76 // Re-maps `x` from `[lba,uba]` to `[lbb,ubb]`.
     77 template <typename T>
     78 T ConvertRange(T x, T lba, T uba, T lbb, T ubb) {
     79   return (((x - lba) * (ubb - lbb)) / (uba - lba)) + lbb;
     80 }
     81 
     82 template <typename R1, typename R2>
     83 static inline vec2 MapPoint(const vec2& pt, const R1& from, const R2& to) {
     84   vec2 normalized((pt - vec2(from.p1)).array() / vec2(from.GetSize()).array());
     85   return (normalized * vec2(to.GetSize())) + vec2(to.p1);
     86 }
     87 
     88 template <typename T>
     89 inline bool IsZero(const T& v,
     90                    const T& tol = std::numeric_limits<T>::epsilon()) {
     91   return std::abs(v) <= tol;
     92 }
     93 
     94 template <typename T>
     95 inline bool IsEqual(const T& a, const T& b,
     96                     const T& tol = std::numeric_limits<T>::epsilon()) {
     97   return std::abs(b - a) <= tol;
     98 }
     99 
    100 template <typename T>
    101 T Square(const T& x) {
    102   return x * x;
    103 }
    104 
    105 template <typename T>
    106 T RandomInRange(T lo, T hi,
    107                 typename
    108                 std::enable_if<std::is_floating_point<T>::value>::type* = 0) {
    109   std::random_device rd;
    110   std::mt19937 gen(rd());
    111   std::uniform_real_distribution<T> distro(lo, hi);
    112   return distro(gen);
    113 }
    114 
    115 template <typename T>
    116 T RandomInRange(T lo, T hi,
    117                 typename
    118                 std::enable_if<std::is_integral<T>::value>::type* = 0) {
    119   std::random_device rd;
    120   std::mt19937 gen(rd());
    121   std::uniform_int_distribution<T> distro(lo, hi);
    122   return distro(gen);
    123 }
    124 
    125 template <typename Derived1, typename Derived2>
    126 Derived1 RandomInRange(
    127     const Eigen::MatrixBase<Derived1>& lo,
    128     const Eigen::MatrixBase<Derived2>& hi) {
    129   EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Derived1, Derived2);
    130 
    131   Derived1 result = Eigen::MatrixBase<Derived1>::Zero();
    132 
    133   for (int row = 0; row < result.rows(); ++row) {
    134     for (int col = 0; col < result.cols(); ++col) {
    135       result(row, col) = RandomInRange(lo(row, col), hi(row, col));
    136     }
    137   }
    138 
    139   return result;
    140 }
    141 
    142 template <typename T>
    143 T RandomRange(T x) {
    144   return RandomInRange(-x, x);
    145 }
    146 
    147 template <typename T>
    148 T Clamp(T x, T lo, T hi) {
    149   return std::min(std::max(x, lo), hi);
    150 }
    151 
    152 inline mat3 ScaleMatrix(const vec2& scale_xy) {
    153   return mat3(Eigen::Scaling(scale_xy[0], scale_xy[1], 1.0f));
    154 }
    155 
    156 inline mat3 TranslationMatrix(const vec2& translation) {
    157   return mat3(Eigen::Translation2f(translation));
    158 }
    159 
    160 inline mat4 TranslationMatrix(const vec3& translation) {
    161   return mat4(Eigen::Translation3f(translation));
    162 }
    163 
    164 inline vec2 TransformPoint(const mat3& m, const vec2& p) {
    165   return m.linear() * p + m.translation();
    166 }
    167 
    168 inline vec2 TransformVector(const mat3& m, const vec2& p) {
    169   return m.linear() * p;
    170 }
    171 
    172 }  // namespace dvr
    173 }  // namespace android
    174 
    175 #endif  // ANDROID_DVR_NUMERIC_H_
    176