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

vec2.H

Go to the documentation of this file.
00001 #ifndef VEC2_H_IS_INCLUDED
00002 #define VEC2_H_IS_INCLUDED
00003 
00004 /*!
00005  *  \file Vec2.H
00006  *  \brief Contains the definition of the Vec2 class, a 2D vector class.
00007  *  \ingroup group_MLIB
00008  *
00009  */
00010 
00011 #include <cmath>
00012 #include "mlib/global.H"
00013 #include "mlib/point3.H"
00014 
00015 namespace mlib {
00016 
00017 /*!
00018  *  \brief A 2D vector class with double precision floating point elements.
00019  *  \ingroup group_MLIB
00020  *
00021  *  This class is designed to be base class of more specific types of 2D vectors.
00022  *  Specifically, 2D vectors in different coordinate systems.  The template
00023  *  argument V is the type of the derived vector class.  This allows the Vec2 to
00024  *  return new vectors of the same type as the derived class.
00025  *
00026  */
00027 template <class V>
00028 class Vec2 {
00029    
00030    protected:
00031    
00032       double _x, _y;
00033 
00034    public:
00035    
00036       //! \name Constructors
00037       //@{
00038 
00039       Vec2()                   : _x(0)   , _y(0)    {} 
00040       Vec2(double x, double y) : _x(x)   , _y(y)    {}
00041       
00042       //@}
00043       
00044       //! \name Descriptive interface
00045       //@{
00046          
00047       typedef double value_type;
00048       static int dim() { return 2; }
00049       
00050       //@} 
00051    
00052       //! \name Overloaded Mathematical Operators
00053       //@{
00054       
00055       V       operator + (const V &v)    const { return V(_x+v._x, _y+v._y); }
00056       V       operator - (const V &v)    const { return V(_x-v._x, _y-v._y); }
00057       double  operator * (const V &v)    const { return _x*v._x+_y*v._y;         }
00058       V       operator - ()              const { return V(-_x, -_y);         }
00059    
00060       V       operator * (double s)      const { return V(_x*s, _y*s); }
00061       V       operator / (double s)      const { return V(_x/s, _y/s); }
00062       
00063       void     operator +=(const V &v)         { _x += v._x; _y += v._y;       }
00064       void     operator -=(const V &v)         { _x -= v._x; _y -= v._y;       }
00065       void     operator *=(double s)           { _x *= s; _y *= s; }
00066       void     operator /=(double s)           { _x /= s; _y /= s; }
00067       
00068       //@}
00069       
00070       //! \name Element Access Functions
00071       //@{
00072    
00073       double  operator [](int index)     const { return (&_x)[index];     }
00074       double& operator [](int index)           { return (&_x)[index];     }
00075       
00076       //@}
00077       
00078       //! \name Vector Property Queries
00079       //@{
00080    
00081       double  length     ()              const { return sqrt(_x*_x+_y*_y); }
00082       double  length_sqrd ()              const { return _x*_x+_y*_y;       }
00083       
00084       bool     is_exact_null()             const { return _x == 0 && _y == 0; }
00085       
00086       //! \brief Tells if the vector is basically the zero vector.
00087       bool is_null (double epsSqrdMath = epsNorSqrdMath()) const {
00088          return length_sqrd() <= epsSqrdMath;
00089       }
00090       
00091       //@}
00092       
00093       //! \name Single Vector Operations
00094       //@{
00095    
00096       //! \brief Returns a unit-length copy of this vector.
00097       V       normalized ()              const;
00098    
00099       //! \brief Returns a copy of the vector rotated 90 degrees CCW.
00100       V       perpend    ()              const { return V(-_y, _x); }
00101       
00102       //@}
00103       
00104       //! \name Two Vector Operations
00105       //@{
00106    
00107       double  dist       (const V &v)    const { return (*this-v).length();     }
00108       double  dist_sqrd   (const V &v)    const { return (*this-v).length_sqrd(); }
00109       
00110       //! \brief Returns the signed angle between this vector and the
00111       //! given one.
00112       //! 
00113       //! I.e., returns the angle by which to rotate
00114       //! this vector counter-clockwise to align with the given
00115       //! vector. The result will be negative if the smallest
00116       //! rotation to get to the given vector is in the clockwise
00117       //! direction. The result will lie between -pi and pi radians:
00118       double signed_angle(const V&) const;
00119    
00120       //! \brief Returns the unsigned angle between the two vectors.
00121       //! The result will lie between 0 and pi radians.
00122       double angle(const V& v) const;
00123    
00124       //! \brief Return (this * b) / (b * b).
00125       inline double tlen(const V &b) const {
00126          double bb = b.length_sqrd();
00127          return isZero(bb) ? 0 : (*this * b)/bb;
00128       }
00129    
00130       //! \brief Returns the projection of this onto b.
00131       inline V projected(const V &b)         const { return b * tlen(b); }
00132    
00133       //! \brief Returns this vector minus its projection onto b.
00134       inline V orthogonalized(const V &b)   const { return *this - projected(b); }
00135       
00136       //@}
00137       
00138       //! \name Vector Comparison Functions
00139       //@{
00140    
00141       bool     is_equal   (const V &v, double epsSqrd = epsNorSqrdMath()) const
00142          { return dist_sqrd(v)<=epsSqrd;}
00143       bool     is_parallel(const V&)      const;
00144       
00145       //@}
00146 
00147       //! \name Overloaded Comparison Operators
00148       //@{
00149       
00150       bool     operator ==(const V &v)   const { return v._x == _x && v._y == _y;}
00151       bool     operator !=(const V &v)   const { return v._x != _x || v._y != _y;}
00152       
00153       //@}
00154 
00155 }; // class Vec2<V>
00156 
00157 } // namespace mlib
00158 
00159 /* ---------- inlined member functions using Vec2 template ------ */
00160 
00161 template<class V>
00162 inline V 
00163 mlib::Vec2<V>::normalized() const 
00164 { 
00165    const double l = length(); 
00166    return (l > gEpsZeroMath ? V(_x/l, _y/l) : V(0,0));
00167 }
00168 
00169 template<class V>
00170 inline double 
00171 mlib::Vec2<V>::signed_angle(const V& v) const
00172 {
00173 
00174    // Get unit-length versions of both vectors:
00175    const V v1 =   normalized();
00176    const V v2 = v.normalized();
00177 
00178    // Do the math:
00179    return Sign(det(v1,v2)) * Acos(v1*v2);
00180 }
00181 
00182 template<class V>
00183 inline double 
00184 mlib::Vec2<V>::angle(const V& v) const
00185 {
00186 
00187    return fabs(signed_angle(v));
00188    
00189 }
00190 
00191 template<class V>
00192 inline bool 
00193 mlib::Vec2<V>::is_parallel(const V &v) const 
00194 { 
00195    const V a =   normalized();
00196    const V b = v.normalized();
00197 
00198    if (a.is_exact_null() || b.is_exact_null())
00199       return false;
00200 
00201    return (a-b).length_sqrd() <= epsNorSqrdMath() || 
00202       (a+b).length_sqrd() <= epsNorSqrdMath();
00203 }
00204 
00205 /* ---------- inlined global functions using Vec2 template ------ */
00206 
00207 namespace mlib {
00208 
00209 //! \brief Returns the 'z' coordinate of the cross product of the
00210 //! two vectors.
00211 //! \relates Vec2
00212 template <class V>
00213 inline double 
00214 det(const Vec2<V>& v1, const Vec2<V>& v2) 
00215 {
00216 
00217    return v1[0]*v2[1]-v1[1]*v2[0];
00218    
00219 }
00220 
00221 //! \brief Stream insertion operator for Vec2 class.
00222 //! \relates Vec2
00223 template <class V>
00224 inline ostream &
00225 operator <<(ostream &os, const Vec2<V>& v) 
00226 { 
00227    return os <<"{"<<v[0]<<","<<v[1]<<"}";
00228 }
00229 
00230 //! \brief double by Vec2 multiplication.
00231 //! \relates Vec2
00232 template <typename V>
00233 inline V
00234 operator*(double s, const Vec2<V> &v)
00235 {
00236    return v*s;
00237 }
00238 
00239 //! \brief Finds the angle between the two (undirected) lines
00240 //! defined by the given vectors. The result is between 0
00241 //! and pi/2 radians.
00242 //!
00243 //! \note Because of how this is templated, it also works
00244 //! with 3D vectors (Vec3 class).
00245 //! \relates Vec2
00246 template <class V>
00247 inline double 
00248 line_angle(const V& v1, const V& v2)
00249 {
00250 
00251    double a = v1.angle(v2);
00252    return (a <= M_PI_2) ? a : (M_PI - a);
00253    
00254 }
00255 
00256 } // namespace mlib
00257 
00258 #endif // VEC2_H_IS_INCLUDED
00259 
00260 /* end of file Vec2.H */

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