00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef TG_MATH_H
00019 #define TG_MATH_H
00020
00021 #include "Util.h"
00022
00023 #include <cmath>
00024
00025
00026 #ifndef M_PI
00027 # define M_PI 3.14159265358979323846
00028 #endif
00029 #ifndef M_PI_2
00030 # define M_PI_2 1.57079632679489661923
00031 #endif
00032
00033 namespace tagGame
00034 {
00035
00036 typedef double Real;
00037
00038 Real const Inf = HUGE_VAL;
00039
00041 class MathUtil
00042 {
00043 public:
00044
00046 inline static bool isAlmostEq(Real const x, Real const y);
00047
00049 inline static bool isAlmostZero(Real const x);
00050
00052 inline static int round(Real const x);
00053
00055 inline static int sgn(Real const x);
00056
00058 inline static Real radToDeg(Real const t);
00059
00061 inline static Real degToRad(Real const t);
00062
00064 inline static Real clamp(Real const x, Real lower, Real upper);
00065
00069 inline static Real angleClamp(Real const t);
00070
00072 inline static Real uniform01();
00073
00075 inline static int uniform(int n);
00076
00079 inline static Real normal(Real const mean = Real(0), Real const std = Real(1));
00080
00085 inline static Real normalAngle(Real const mean = Real(0), Real const std = Real(70));
00086
00087 protected:
00088 private:
00089 };
00090
00091
00092 bool MathUtil::isAlmostEq(Real const x, Real const y)
00093 {
00094 Real const eps = 0.00001;
00095
00096 return (fabs(x - y) <= eps) || (x == Inf && y == Inf);
00097 }
00098
00099 bool MathUtil::isAlmostZero(Real const x)
00100 {
00101 return isAlmostEq(x, Real(0));
00102 }
00103
00104 int MathUtil::round(Real const x)
00105 {
00106 return int(x + 0.5);
00107 }
00108
00109 int MathUtil::sgn(Real const x)
00110 {
00111 return x < 0 ? -1 : 1;
00112 }
00113
00114 Real MathUtil::radToDeg(Real const x)
00115 {
00116 return x * Real(180) / M_PI;
00117 }
00118
00119 Real MathUtil::degToRad(Real const x)
00120 {
00121 return x * M_PI / Real(180);
00122 }
00123
00124 Real MathUtil::uniform01()
00125 {
00126
00127 return Real(rand())/Real(RAND_MAX);
00128 }
00129
00130 int MathUtil::uniform(int n)
00131 {
00132 TG_ASSERT_MSG(n <= RAND_MAX, "n: " + Util::itos(n) + " must be <= RAND_MAX: " + Util::itos(RAND_MAX));
00133
00134 return rand() % n;
00135 }
00136
00137 Real MathUtil::clamp(Real x, Real lower, Real upper)
00138 {
00139 TG_ASSERT(lower <= upper);
00140
00141 return x < lower ? lower : (upper < x ? upper : x);
00142 }
00143
00144 Real MathUtil::angleClamp(Real const t)
00145 {
00146
00147
00148
00149 Real const x(t == Real(-360) ? t : Real(sgn(t)) * fmod(fabs(t), Real(360)));
00150 TG_ASSERT(Real(-360) <= x && x < Real(360));
00151 return x < Real(-180) ? x + Real(360) : (x >= Real(180) ? x - Real(360) : x);
00152 }
00153
00154 Real MathUtil::normalAngle(Real const mean, Real const std)
00155 {
00156 return angleClamp(normal(mean, std));
00157 }
00158
00159
00160 Real MathUtil::normal(Real const mean, Real const std)
00161 {
00162
00163
00164
00165
00166 static bool validCache(false);
00167 static Real rho(0);
00168 static Real r1(0);
00169
00170
00171 if (!validCache)
00172 {
00173 Real const r0(uniform01());
00174 r1 = uniform01();
00175 rho = sqrt(-Real(2) * log(Real(1) - r0));
00176 validCache = true;
00177
00178 return rho * cos(Real(2) * M_PI * r1) * std + mean;
00179 }
00180 else
00181 {
00182 validCache = false;
00183 }
00184 return rho * sin(Real(2) * M_PI * r1) * std + mean;
00185 }
00186 }
00187
00188 #endif