00001 #ifndef VEC3_H_IS_INCLUDED
00002 #define VEC3_H_IS_INCLUDED
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <cmath>
00012 #include "global.H"
00013
00014 namespace mlib {
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 template <class V>
00027 class Vec3 {
00028
00029 protected:
00030
00031 double _x, _y, _z;
00032
00033 public:
00034
00035
00036
00037
00038
00039 Vec3() : _x(0), _y(0), _z(0) {}
00040
00041
00042 Vec3(double x, double y, double z) : _x(x), _y(y), _z(z) {}
00043
00044
00045
00046
00047
00048
00049 typedef double value_type;
00050 static int dim() { return 3; }
00051
00052
00053
00054
00055
00056
00057
00058 const double *data() const { return &_x; }
00059
00060
00061
00062 void set(double x, double y, double z) { _x=x; _y=y; _z=z; }
00063
00064 double operator [](int index) const { return (&_x)[index]; }
00065 double& operator [](int index) { return (&_x)[index]; }
00066
00067
00068
00069
00070
00071
00072 V operator + (const V &v) const { return V(_x+v._x,_y+v._y,_z+v._z); }
00073 V operator - (const V &v) const { return V(_x-v._x,_y-v._y,_z-v._z); }
00074 double operator * (const V &v) const { return _x*v._x+_y*v._y+_z*v._z; }
00075 V operator - () const { return V(-_x, -_y, -_z); }
00076 V operator * (double s) const { return V(_x*s, _y*s, _z*s); }
00077 V operator / (double s) const { return V(_x/s, _y/s, _z/s); }
00078
00079 void operator +=(const V &v) { _x += v._x; _y += v._y; _z += v._z;}
00080 void operator -=(const V &v) { _x -= v._x; _y -= v._y; _z -= v._z;}
00081 void operator *=(double s) { _x *= s; _y *= s; _z *= s; }
00082 void operator /=(double s) { _x /= s; _y /= s; _z /= s; }
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092 int operator > (const V &v) const { return length() > v.length();}
00093
00094
00095
00096 int operator < (const V &v) const { return length() < v.length();}
00097
00098 bool operator ==(const V &v) const{ return v[0]==_x&&v[1]==_y&&v[2]==_z;}
00099 bool operator !=(const V &v) const{ return v[0]!=_x||v[1]!=_y||v[2]!=_z;}
00100
00101
00102
00103
00104
00105
00106 double length () const { return sqrt(_x*_x+_y*_y+_z*_z); }
00107 double length_sqrd () const { return _x*_x+_y*_y+_z*_z; }
00108 double length_rect () const { return fabs(_x)+fabs(_y)+fabs(_z);}
00109
00110
00111 bool is_null (double epsSqrd = epsNorSqrdMath()) const
00112 { return length_sqrd() <= epsSqrd; }
00113
00114
00115
00116
00117
00118
00119
00120 double dist (const V &v) const { return (*this-v).length(); }
00121
00122 double dist_sqrd (const V &v) const { return (*this-v).length_sqrd(); }
00123
00124
00125
00126 inline double angle(const V &) const;
00127
00128
00129 inline double tlen(const V &b) const {
00130 double bb = b.length_sqrd();
00131 return isZero(bb) ? 0 : (*this * b)/bb;
00132 }
00133
00134
00135 inline V projected(const V &b) const { return b * tlen(b); }
00136
00137
00138 inline V orthogonalized(const V &b) const { return *this - projected(b); }
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 bool is_equal (const V &v, double epsSqrd = epsNorSqrdMath()) const
00149 { return (dist_sqrd(v) <= epsSqrd); }
00150
00151
00152 inline bool is_parallel (const V &) const;
00153
00154 inline bool is_perpend (const V &) const;
00155
00156
00157
00158
00159
00160
00161
00162 inline V normalized () const;
00163
00164
00165
00166 inline V perpend () const;
00167
00168
00169
00170 };
00171
00172 }
00173
00174
00175
00176 template <class V>
00177 inline V
00178 mlib::Vec3<V>::normalized() const
00179 {
00180 const double l = length();
00181 if (l > gEpsZeroMath)
00182 return V(_x/l, _y/l, _z/l);
00183 return V();
00184 }
00185
00186
00187
00188
00189
00190
00191
00192
00193 template <class V>
00194 inline V
00195 mlib::Vec3<V>::perpend() const
00196 {
00197
00198 double min_component = fabs((*this)[2]);
00199
00200 V b = V(0.0, 0.0, 1.0);
00201
00202 if(std::fabs((*this)[0]) < min_component){
00203
00204 min_component = fabs((*this)[0]);
00205
00206 b = V(1.0, 0.0, 0.0);
00207
00208 }
00209
00210 if(std::fabs((*this)[1]) < min_component){
00211
00212 b = V(0.0, 1.0, 0.0);
00213
00214 }
00215
00216 V a((*this)[0], (*this)[1], (*this)[2]);
00217
00218 return cross(b, a).normalized();
00219
00220 }
00221
00222
00223 template <class V>
00224 inline bool
00225 mlib::Vec3<V>::is_parallel(const V &v) const
00226 {
00227 const V a = normalized();
00228
00229 if (a == V())
00230 return false;
00231
00232 const V b = v.normalized();
00233
00234 if (b == V())
00235 return false;
00236
00237 return (a-b).length_sqrd() <= epsNorSqrdMath() ||
00238 (a+b).length_sqrd() <= epsNorSqrdMath();
00239 }
00240
00241
00242 template <class V>
00243 inline bool
00244 mlib::Vec3<V>::is_perpend(const V &v) const
00245 {
00246 const V a = normalized();
00247 const V b = v.normalized();
00248
00249 if (a == V() || b == V())
00250 return false;
00251
00252 return fabs(a * b) < epsNorMath();
00253 }
00254
00255 template <class V>
00256 inline double
00257 mlib::Vec3<V>::angle(const V& v) const
00258 {
00259
00260
00261 const V v1 = normalized();
00262 const V v2 = v.normalized();
00263
00264
00265 return Acos(v1*v2);
00266
00267 }
00268
00269
00270
00271 namespace mlib {
00272
00273
00274
00275 template <class V>
00276 inline ostream &
00277 operator<<(ostream &os, const Vec3<V> &v)
00278 {
00279 return os << "{ " << v[0] << " " << v[1] << " " << v[2] << " } ";
00280 }
00281
00282
00283
00284
00285 template <class V>
00286 inline istream &
00287 operator>>(istream &is, Vec3<V> &v)
00288 {
00289 char dummy;
00290 return is >> dummy >> v[0] >> v[1] >> v[2] >> dummy;
00291 }
00292
00293
00294
00295 template <typename V>
00296 inline V
00297 operator*(double s, const Vec3<V> &v)
00298 {
00299 return v*s;
00300 }
00301
00302
00303
00304
00305 template <class V>
00306 inline V
00307 cross(const V &v1, const V &v2)
00308 {
00309 return V(v1[1]*v2[2]-v1[2]*v2[1],
00310 v1[2]*v2[0]-v1[0]*v2[2],
00311 v1[0]*v2[1]-v1[1]*v2[0]);
00312 }
00313
00314
00315
00316
00317
00318 template <class V>
00319 inline double
00320 det(const V &a, const V &b, const V &c)
00321 {
00322 return a * cross(b,c);
00323 }
00324
00325
00326
00327
00328 template <class V>
00329 inline double
00330 signed_angle(const V &v1, const V &v2, const V& n)
00331 {
00332 return Sign(det(n,v1,v2)) * v1.angle(v2);
00333 }
00334
00335 }
00336
00337 #endif // VEC3_H_IS_INCLUDED
00338
00339