00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef __ETL__ANGLE_H
00029 #define __ETL__ANGLE_H
00030
00031
00032
00033 #include <cstdio>
00034 #include <cmath>
00035 #include <functional>
00036
00037
00038
00039 #ifndef PI
00040 # define PI (3.1415926535897932384626433832795029L)
00041 # define HALF_PI (PI/2)
00042 #endif
00043
00044 #define ANGLE_EPSILON (1.0e-6)
00045
00046
00047
00048
00049
00050 _ETL_BEGIN_NAMESPACE
00051
00052
00058 class angle
00059 {
00060 public:
00061 typedef float value_type;
00062
00063 protected:
00064 typedef value_type unit;
00065
00066 unit v;
00067
00068 public:
00069
00070
00071
00072
00073
00074 const angle &
00075 operator+=(const angle &rhs)
00076 { v+=rhs.v; return *this; }
00077
00078 const angle &
00079 operator-=(const angle &rhs)
00080 { v-=rhs.v; return *this; }
00081
00082 const angle &
00083 operator*=(const unit &rhs)
00084 { v*=rhs; return *this; }
00085
00086 const angle &
00087 operator/=(const unit &rhs)
00088 { v/=rhs; return *this; }
00089
00091 angle
00092 operator+(const angle &rhs)const
00093 { return angle(*this)+=rhs; }
00094
00096
00097 angle
00098 operator-(const angle &rhs)const
00099 { return angle(*this)-=rhs; }
00100
00102
00104 angle
00105 operator*(const unit &rhs)const
00106 { return angle(*this)*=rhs; }
00107
00108 angle
00109 operator/(const unit &rhs)const
00110 { return angle(*this)/=rhs; }
00111
00113 angle
00114 operator-()const
00115 {
00116 angle ret;
00117 ret.v=-v;
00118 return ret;
00119 }
00120
00121 #ifdef ETL_NOT_USED
00123
00126 angle
00127 operator~()const
00128 {
00129 angle ret;
00130 ret.v = v+PI;
00131 return ret.mod();
00132 }
00133 #endif // ETL_NOT_USED
00134
00135 #ifdef ETL_WRAP_ANGLES
00136
00139 bool
00140 operator<(const angle &rhs)const
00141 { return dist(rhs).v<(value_type)0.0; }
00142
00146 bool
00147 operator>(const angle &rhs)const
00148 { return dist(rhs).v>(value_type)0.0; }
00149
00155 bool
00156 operator<=(const angle &rhs)const
00157 { return dist(rhs).v<=(value_type)0.0; }
00158
00164 bool
00165 operator>=(const angle &rhs)const
00166 { return dist(rhs).v>=(value_type)0.0; }
00167
00171 bool
00172 operator==(const angle &rhs)const
00173 { return std::abs(dist(rhs).v)<ANGLE_EPSILON; }
00174
00178 bool
00179 operator!=(const angle &rhs)const
00180 { return std::abs(dist(rhs).v)>ANGLE_EPSILON; }
00181 #else // ETL_WRAP_ANGLES
00182
00185 bool
00186 operator<(const angle &rhs)const
00187 { return v < rhs.v; }
00188
00192 bool
00193 operator>(const angle &rhs)const
00194 { return v > rhs.v; }
00195
00199 bool
00200 operator<=(const angle &rhs)const
00201 { return v <= rhs.v; }
00202
00206 bool
00207 operator>=(const angle &rhs)const
00208 { return v >= rhs.v; }
00209
00212 bool
00213 operator==(const angle &rhs)const
00214 { return std::abs(v - rhs.v)<ANGLE_EPSILON; }
00215
00218 bool
00219 operator!=(const angle &rhs)const
00220 { return std::abs(v - rhs.v)>ANGLE_EPSILON; }
00221 #endif // ETL_WRAP_ANGLES
00222
00224
00226 angle
00227 abs()const
00228 {
00229 angle ret;
00230 ret.v=std::abs(v);
00231 return ret;
00232 }
00233
00234 #ifdef ETL_WRAP_ANGLES
00236
00240 angle
00241 dist(const angle &rhs)const
00242 {
00243 angle ret;
00244 ret.v=v-rhs.v;
00245 ret.v-=rot_floor(ret.v+PI);
00246 return ret;
00247 }
00248
00250
00252 angle
00253 mod()const
00254 {
00255 angle ret(*this);
00256 ret.v-=rot_floor(ret.v);
00257 return ret;
00258 }
00259 #else // ETL_WRAP_ANGLES
00261
00265 angle
00266 dist(const angle &rhs)const
00267 { return angle(*this)-=rhs; }
00268
00270
00272 angle
00273 mod()const
00274 {
00275 angle ret(*this);
00276 return ret;
00277 }
00278 #endif // ETL_WRAP_ANGLES
00279
00281 static angle
00282 zero()
00283 {
00284 angle ret;
00285 ret.v=0;
00286 return ret;
00287 }
00288
00290 static angle
00291 one()
00292 {
00293 angle ret;
00294 ret.v=PI*2;
00295 return ret;
00296 }
00297
00299 static angle
00300 half()
00301 {
00302 angle ret;
00303 ret.v=PI;
00304 return ret;
00305 }
00306
00307 bool operator!()const { return std::abs(mod().v) < ANGLE_EPSILON; }
00308
00309 private:
00310
00311 #ifdef ETL_WRAP_ANGLES
00312 static value_type rot_floor(value_type x)
00313 { return static_cast<value_type>(std::floor(x/(PI*2))*PI*2); }
00314 #endif // ETL_WRAP_ANGLES
00315
00316 public:
00317
00318
00319
00320
00321 class rad;
00322 class deg;
00323 class rot;
00324
00325
00326
00327
00328
00329 class sin;
00330 class cos;
00331 class tan;
00332
00333
00334
00335
00336
00337 friend class rad;
00338 friend class deg;
00339 friend class rot;
00340 friend class sin;
00341 friend class cos;
00342 friend class tan;
00343
00344
00345
00346
00347
00348 #ifndef ETL_NO_DEPRECATED
00349 typedef rad radians;
00350 typedef deg degrees;
00351 typedef rot rotations;
00352 #endif
00353 };
00354
00355
00361 class angle::rad : public angle
00362 {
00363 public:
00364 explicit rad(const value_type &x) { v=x; }
00365 rad(const angle &a):angle(a) { }
00366 rad mod()const { return angle::mod(); }
00367 rad dist(const angle &rhs)const { return angle::dist(rhs); }
00368 value_type get()const { return v; }
00369 #ifndef ETL_NO_DEPRECATED
00370
00371 #endif
00372 };
00373
00374
00375
00381 class angle::deg : public angle
00382 {
00383 public:
00384 explicit deg(const value_type &x) { v=x*((PI*2)/360); }
00385 deg(const angle &a):angle(a) { }
00386 deg mod()const { return angle::mod(); }
00387 deg dist(const angle &rhs)const { return angle::dist(rhs); }
00388 value_type get()const { return v*360/(PI*2); }
00389 #ifndef ETL_NO_DEPRECATED
00390
00391 #endif
00392 };
00393
00394
00395
00401 class angle::rot : public angle
00402 {
00403 public:
00404 explicit rot(const value_type &x) { v=x*(PI*2); }
00405 rot(const angle &a):angle(a) { }
00406 rot mod()const { return angle::mod(); }
00407 rot dist(const angle &rhs)const { return angle::dist(rhs); }
00408 value_type get()const { return v/(PI*2); }
00409 #ifndef ETL_NO_DEPRECATED
00410
00411 #endif
00412 };
00413
00414
00415
00421 class angle::sin : public angle
00422 {
00423 public:
00424 explicit sin(const value_type &x) { v=static_cast<value_type>(std::asin(x)); }
00425 sin(const angle &a):angle(a) { }
00426 sin mod()const { return angle::mod(); }
00427 sin dist(const angle &rhs)const { return angle::dist(rhs); }
00428 value_type get()const { return static_cast<value_type>(std::sin(v)); }
00429 #ifndef ETL_NO_DEPRECATED
00430
00431 #endif
00432 };
00433
00434
00435
00441 class angle::cos : public angle
00442 {
00443 public:
00444 explicit cos(const value_type &x) { v=(value_type)(std::acos(x)); }
00445 cos(const angle &a):angle(a) { }
00446 cos mod()const { return angle::mod(); }
00447 cos dist(const angle &rhs)const { return angle::dist(rhs); }
00448 value_type get()const { return (value_type)std::cos(v); }
00449 #ifndef ETL_NO_DEPRECATED
00450
00451 #endif
00452 };
00453
00454
00455
00461 class angle::tan : public angle
00462 {
00463 public:
00464 explicit tan(const value_type &x) { v=(value_type)(std::atan(x)); }
00465 tan(const value_type &y,const value_type &x) { v=(value_type)(std::atan2(y,x)); }
00466 tan(const angle &a):angle(a) { }
00467 tan mod()const { return angle::mod(); }
00468 tan dist(const angle &rhs)const { return angle::dist(rhs); }
00469 value_type get()const { return (value_type)std::tan(v); }
00470 #ifndef ETL_NO_DEPRECATED
00471
00472 #endif
00473 };
00474
00475
00476 _ETL_END_NAMESPACE
00477
00478
00479
00480 template <typename T>
00481 struct affine_combo<etl::angle, T>
00482 {
00483 typedef T time_type;
00484
00485
00486
00487
00488 etl::angle operator()(const etl::angle &a,const etl::angle &b,const time_type &t)const
00489 {
00490 return b.dist(a)*(float)t+a;
00491 }
00492
00493 etl::angle reverse(const etl::angle &x, const etl::angle &b, const time_type &t)const
00494 {
00495 return x.dist(b*(float)t)*(float)(time_type(1)/(time_type(1)-t));
00496 }
00497 };
00498
00499 template <>
00500 struct distance_func<etl::angle> : public std::binary_function<etl::angle, etl::angle, etl::angle>
00501 {
00502 etl::angle operator()(const etl::angle &a,const etl::angle &b)const
00503 {
00504 etl::angle delta=b.dist(a);
00505
00506
00507 return delta;
00508 }
00509
00510 etl::angle cook(const etl::angle &x)const { return x; }
00511 etl::angle uncook(const etl::angle &x)const { return x; }
00512 };
00513
00514
00515
00516 #endif