Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

vec3.H

Go to the documentation of this file.
00001 #ifndef VEC3_H_IS_INCLUDED
00002 #define VEC3_H_IS_INCLUDED
00003 
00004 /*!
00005  *  \file Vec3.H
00006  *  \brief Contains the defintion of the Vec3 class, a 3D vector class.
00007  *  \ingroup group_MLIB
00008  *
00009  */
00010 
00011 #include <cmath>
00012 #include "global.H"
00013 
00014 namespace mlib {
00015 
00016 /*!
00017  *  \brief A 3D vector class with double precision floating point elements.
00018  *  \ingroup group_MLIB
00019  *
00020  *  This class is designed to be base class of more specific types of 3D vectors.
00021  *  Specifically, 3D vectors in different coordinate systems.  The template
00022  *  argument V is the type of the derived vector class.  This allows the Vec3 to
00023  *  return new vectors of the same type as the derived class.
00024  *
00025  */
00026 template <class V>
00027 class Vec3 {
00028    
00029    protected:
00030    
00031       double _x, _y, _z;
00032 
00033    public:
00034    
00035       //! \name Constructors
00036       //@{
00037 
00038       //! \brief Default constructor.  Creates a zero length vector.
00039       Vec3()                             : _x(0),    _y(0),    _z(0)   {}
00040       //! \brief Constructor that sets the components of the vector to the
00041       //! values specified in the arguments.
00042       Vec3(double x, double y, double z) : _x(x),    _y(y),    _z(z)   {}
00043       
00044       //@}
00045       
00046       //! \name Descriptive interface
00047       //@{
00048          
00049       typedef double value_type;
00050       static int dim() { return 3; }
00051       
00052       //@} 
00053       
00054       //! \name Element Access Functions
00055       //@{
00056    
00057       //! \brief Returns the elements of the vector as an array.
00058       const double *data()             const { return &_x; }
00059    
00060       //! \brief Sets the components of the vector to the values specified in
00061       //! the arguments.
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       //! \name Overloaded Mathematical Operators
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       //! \name Overloaded Comparison Operators
00087       //@{
00088    
00089       //! Provided so that min(V, V) and max(V, V) work.
00090       //! \note Comparison is done by length (not by comparing individual
00091       //! components).
00092       int     operator > (const V &v) const { return length() > v.length();}
00093       //! Provided so that min(V, V) and max(V, V) work.
00094       //! \note Comparison is done by length (not by comparing individual
00095       //! components).
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       //! \name Vector Property Queries
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       //! \brief Is the vector's length equal to zero?
00111       bool    is_null     (double epsSqrd = epsNorSqrdMath()) const  
00112          { return length_sqrd() <= epsSqrd; }
00113          
00114       //@}
00115       
00116       //! \name Two Vector Operations
00117       //@{
00118    
00119       //! \brief Compute the distance between the two vectors.
00120       double  dist       (const V &v) const { return (*this-v).length();      }
00121       //! \brief Compute the distance squared between the two vectors.
00122       double  dist_sqrd  (const V &v) const { return (*this-v).length_sqrd(); }
00123       
00124       //! \brief Compute the angle between the two vectors.
00125       //! The result will be in the range 0 to pi radians.
00126       inline double angle(const V &)        const;
00127       
00128       //! \brief Returns (this * b) / (b * b).
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       //! \brief Returns the projection of this onto b.
00135       inline V projected(const V &b)         const { return b * tlen(b); }
00136    
00137       //! \brief Returns this vector minus its projection onto b.
00138       inline V orthogonalized(const V &b)   const { return *this - projected(b); }
00139       
00140       //@}
00141       
00142       //! \name Vector Comparison Functions
00143       //@{
00144    
00145       //! \brief Are the two vectors equal?
00146       //! \note Checks to see if the distance between the two vectors is less
00147       //! than or equal to epsSqrd.
00148       bool    is_equal    (const V &v, double epsSqrd = epsNorSqrdMath()) const 
00149          { return (dist_sqrd(v) <= epsSqrd); }
00150       
00151       //! \brief Are the two vectors parallel?
00152       inline bool   is_parallel (const V &)  const;
00153       //! \brief Are the two vectors perpendicular?
00154       inline bool   is_perpend  (const V &)  const;
00155          
00156       //@}
00157       
00158       //! \name Single Vector Operations
00159       //@{
00160    
00161       //! \brief Return a unit-length copy of this vector.
00162       inline V      normalized ()            const;
00163    
00164       //! \brief Return a vector perpendicular to this one using an arbitrary
00165       //! axis algorithm.
00166       inline V      perpend   ()            const;
00167       
00168       //@}
00169 
00170 }; // class Vec3
00171 
00172 } // namespace mlib
00173 
00174 /* ---------- inlined member functions using Vec3 template ------ */
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 //! The arbitrary perpendicular vector is found as follows.  First, the minimum
00188 //! length component of the vector is found.  Second, a new vector is created
00189 //! that is the unit vector along the direction of the minimum component.  Third,
00190 //! the perpendicular vector is found by taking the cross product of the vector
00191 //! with the minimum component set to zero and the original vector.  Fourth, the
00192 //! perpendicular vector is normalized.
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    // Get unit-length versions of both vectors:
00261    const V v1 =   normalized();
00262    const V v2 = v.normalized();
00263 
00264    // Take the inverse cosine of the dot product
00265    return Acos(v1*v2);
00266    
00267 }
00268 
00269 /* ---------- inlined global functions using Vec3 template ------ */
00270 
00271 namespace mlib {
00272 
00273 //! \brief Stream insertion operator for Vec3 class.
00274 //! \relates Vec3
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 //! \brief Stream extraction operator for Vec3 class.
00284 //! \relates Vec3
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 //! \brief double by Vec3 multiplication.
00294 //! \relates Vec3
00295 template <typename V>
00296 inline V
00297 operator*(double s, const Vec3<V> &v)
00298 {
00299    return v*s;
00300 }
00301 
00302 
00303 //! \brief Computes the cross product of two Vec3's.
00304 //! \relates Vec3
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 //! \brief Computes the scalar triple product of three Vec3's (or, equivalently,
00316 //! the determinant of the 3x3 matrix with the three Vec3's as rows).
00317 //! \relates Vec3
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 //! \brief Returns the angle between v1 and v2, negated if v1 x v2
00326 //! points in the opposite direction from n.
00327 //! \relates Vec3
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 } // namespace mlib
00336 
00337 #endif // VEC3_H_IS_INCLUDED
00338 
00339 /* end of file Vec3.H */

Generated on Mon Sep 18 11:39:34 2006 for jot by  doxygen 1.4.4