core/vgl/vgl_vector_3d.h
Go to the documentation of this file.
00001 // This is core/vgl/vgl_vector_3d.h
00002 #ifndef vgl_vector_3d_h_
00003 #define vgl_vector_3d_h_
00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00005 #pragma interface
00006 #endif
00007 //:
00008 // \file
00009 // \brief direction vector in Euclidean 3D space
00010 // \author Peter Vanroose
00011 // \date 27 June, 2001
00012 //
00013 // \verbatim
00014 // Modifications
00015 // 2001-07-05 Peter Vanroose  Added orthogonal(); operator* now accepts double
00016 // 2009-05-21 Peter Vanroose  istream operator>> re-implemented
00017 // \endverbatim
00018 
00019 #include <vcl_iosfwd.h>
00020 
00021 //----------------------------------------------------------------------
00022 
00023 //: Direction vector in Euclidean 3D space, templated by type of element
00024 // (typically float or double).  A vgl_vector_3d<T> represents the
00025 // difference (or connecting vector) between two vgl_point_3d<T>s.
00026 //
00027 // Use this class to do arithmetic (adding and scaling) in 3d geometric space.
00028 //
00029 template <class T>
00030 class vgl_vector_3d
00031 {
00032  public:
00033   T x_; // Data is public
00034   T y_;
00035   T z_;
00036   inline T x() const { return x_; }
00037   inline T y() const { return y_; }
00038   inline T z() const { return z_; }
00039 
00040   //: Creates the vector (0,0,0) of zero length.
00041   inline vgl_vector_3d() : x_(0) , y_(0) , z_(0) {}
00042 
00043   //: Creates the vector \a (vx,vy,vz).
00044   inline vgl_vector_3d(T vx, T vy, T vz) : x_(vx) , y_(vy) , z_(vz) {}
00045 
00046   //: Creates the vector \a (vx,vy,vz).
00047   inline vgl_vector_3d(const T v[3]) : x_(v[0]), y_(v[1]), z_(v[2]) {}
00048 
00049 #if 0 // The defaults do exactly what they should do...
00050   //: Copy constructor
00051   inline vgl_vector_3d (vgl_vector_3d<T>const&v):x_(v.x()),y_(v.y()),z_(v.z()){}
00052   //: Assignment operator
00053   inline vgl_vector_3d<T>& operator=(vgl_vector_3d<T> const& v) {
00054     x_=v.x(); y_=v.y(); z_=v.z(); return *this; }
00055   //: Destructor
00056   inline ~vgl_vector_3d () {}
00057 #endif
00058 
00059   //: Assignment
00060   inline void set(T vx, T vy, T vz) { x_=vx; y_=vy; z_=vz; }
00061 
00062   //: Set \a x, \a y and \a z
00063   inline void set (T const v[3]) { x_ = v[0]; y_ = v[1]; z_ = v[2]; }
00064 
00065   //: Comparison
00066   inline bool operator==(vgl_vector_3d<T>const& v) const {
00067     return x_==v.x() && y_==v.y() && z_==v.z(); }
00068   inline bool operator!=(vgl_vector_3d<T>const& v)const{return !operator==(v);}
00069 
00070   //: Return the length of this vector.
00071   double length() const; // return sqrt( sqr_length() );
00072 
00073   //: Return the squared length of this vector.
00074   inline T sqr_length() const { return x()*x()+y()*y()+z()*z(); }
00075 
00076 
00077   //: One-parameter family of unit vectors that are orthogonal to *this, v(s).
00078   // To get two orthogonal vectors call this function twice with s=0 and
00079   // s=0.25 for example.
00080   // \param s 0<=s<=1, v(0)==v(1)
00081   // \note This function is not continuous near z==0. (Under the Hairy Ball
00082   // theorem no such smooth function can exist.)
00083   // \note This vector need not be normalized but it should have non-zero length.
00084   // \deprecated Use global function orthogonal_vectors(vgl_vector_3d<T > const& a, double s) instead.
00085   vgl_vector_3d<T> orthogonal_vectors(double s) const;
00086 
00087   //: Read from stream, possibly with formatting
00088   //  Either just reads three blank-separated numbers,
00089   //  or reads three comma-separated numbers,
00090   //  or reads three numbers in parenthesized form "(123, 321, 567)"
00091   // \relatesalso vgl_point_3d
00092   vcl_istream& read(vcl_istream& is);
00093 };
00094 
00095 #define v vgl_vector_3d<T>
00096 
00097 //  +-+-+ vector_3d simple I/O +-+-+
00098 
00099 //: Write "<vgl_vector_3d x,y,z> " to stream
00100 // \relatesalso vgl_vector_3d
00101 template <class T> vcl_ostream&  operator<<(vcl_ostream& s, v const& p);
00102 
00103 //: Read from stream, possibly with formatting
00104 //  Either just reads three blank-separated numbers,
00105 //  or reads three comma-separated numbers,
00106 //  or reads three numbers in parenthesized form "(123, 321, 567)"
00107 // \relatesalso vgl_vector_3d
00108 template <class T> vcl_istream& operator>>(vcl_istream& s, v& p);
00109 
00110 
00111 //  +-+-+ vector_3d geometry and algebra +-+-+
00112 
00113 //: Return the length of a vector.
00114 // \relatesalso vgl_vector_3d
00115 template <class T> inline double length(v const& a) { return a.length(); }
00116 
00117 //: Return the squared length of a vector.
00118 // \relatesalso vgl_vector_3d
00119 template <class T> inline T sqr_length(v const& a) { return a.sqr_length(); }
00120 
00121 //: c=a+b: add two vectors.
00122 // \relatesalso vgl_vector_3d
00123 template <class T> inline v      operator+(v const& a, v const& b) { return v(a.x()+b.x(), a.y()+b.y(), a.z()+b.z()); }
00124 
00125 //: c=a-b: subtract two vectors.
00126 // \relatesalso vgl_vector_3d
00127 template <class T> inline v      operator-(v const& a, v const& b) { return v(a.x()-b.x(), a.y()-b.y(), a.z()-b.z()); }
00128 
00129 //: a+=b: add b to a and return a.
00130 // \relatesalso vgl_vector_3d
00131 template <class T> inline v&     operator+=(v& a, v const& b) { a.x_+=b.x_; a.y_+=b.y_; a.z_+=b.z_; return a; }
00132 
00133 //: a-=b: subtract b from a and return a.
00134 // \relatesalso vgl_vector_3d
00135 template <class T> inline v&     operator-=(v& a, v const& b) { a.x_-=b.x_; a.y_-=b.y_; a.z_-=b.z_; return a; }
00136 
00137 //: +b: unary plus operator (no-op).
00138 // \relatesalso vgl_vector_3d
00139 template <class T> inline v      operator+(v const& b) { return b; }
00140 
00141 //: -a: unary minus operator (additive inverse).
00142 // \relatesalso vgl_vector_3d
00143 template <class T> inline v      operator-(v const& b) { return v(-b.x(), -b.y(), -b.z()); }
00144 
00145 //: c=f*b: return a scaled version of the vector.
00146 // \relatesalso vgl_vector_3d
00147 template <class T> inline v      operator*(double s, v const& b) { return v(T(s*b.x()), T(s*b.y()), T(s*b.z())); }
00148 
00149 //: c=a*f: return a scaled version of the vector.
00150 // \relatesalso vgl_vector_3d
00151 template <class T> inline v      operator*(v const& a, double s) { return v(T(a.x()*s), T(a.y()*s), T(a.z()*s)); }
00152 
00153 //: c=b/f: return an inversely scaled version of the vector (scale must be nonzero).
00154 //  Note that the argument type is double, not T, to avoid rounding errors
00155 //  when type T has no multiplicative inverses (like T=int).
00156 // \relatesalso vgl_vector_3d
00157 template <class T> inline v      operator/(v const& a, double s) { return v(T(a.x()/s), T(a.y()/s), T(a.z()/s)); }
00158 
00159 //: a*=f: scale the vector.
00160 // \relatesalso vgl_vector_3d
00161 template <class T> inline v&     operator*=(v& a, double s) { a.set(T(a.x()*s), T(a.y()*s), T(a.z()*s)); return a; }
00162 
00163 //: a/=f: inversely scale the vector (scale must be nonzero).
00164 // \relatesalso vgl_vector_3d
00165 template <class T> inline v&     operator/=(v& a, double s) { a.set(T(a.x()/s), T(a.y()/s), T(a.z()/s)); return a; }
00166 
00167 //: dot product or inner product of two vectors.
00168 // \relatesalso vgl_vector_3d
00169 template <class T> inline T      dot_product(v const& a, v const& b) { return a.x()*b.x()+a.y()*b.y()+a.z()*b.z(); }
00170 
00171 //: dot product or inner product of two vectors.
00172 // \relatesalso vgl_vector_3d
00173 template <class T> inline T      inner_product(v const& a, v const& b) { return a.x()*b.x()+a.y()*b.y()+a.z()*b.z(); }
00174 
00175 //: cross product of two vectors (is orthogonal to both)
00176 // \relatesalso vgl_vector_3d
00177 template <class T> inline v      cross_product(v const& a, v const& b)
00178 { return v(a.y()*b.z()-a.z()*b.y(), a.z()*b.x()-a.x()*b.z(), a.x()*b.y()-a.y()*b.x()); }
00179 
00180 //: cosine of the angle between two vectors.
00181 // \relatesalso vgl_vector_3d
00182 template <class T> inline double cos_angle(v const& a, v const& b) { return inner_product(a,b)/(a.length()*b.length()); }
00183 
00184 //: smallest angle between two vectors (in radians, between 0 and Pi).
00185 // \relatesalso vgl_vector_3d
00186 template <class T>        double angle(v const& a, v const& b); // return acos(cos_angle(a,b));
00187 
00188 //: are two vectors orthogonal, i.e., is their dot product zero?
00189 // If the third argument is specified, it is taken as the "tolerance", i.e.
00190 // in that case this function returns true if the vectors are almost orthogonal.
00191 // \relatesalso vgl_vector_3d
00192 template <class T>        bool orthogonal(v const& a, v const& b, double eps=0.0);
00193 
00194 //: are two vectors parallel, i.e., is one a scalar multiple of the other?
00195 // If the third argument is specified, it is taken as the "tolerance", i.e.
00196 // in that case this function returns true if the vectors are almost parallel.
00197 // \relatesalso vgl_vector_3d
00198 template <class T>        bool parallel(v const& a, v const& b, double eps=0.0);
00199 
00200 //: f=a/b: return the ratio of two vectors, if they are parallel.
00201 //  (If not, return a "least squares" approximation.)
00202 //  Note that the return type is double, not T, since the ratio of e.g.
00203 //  two vgl_vector_3d<int> need not be an int.
00204 // \relatesalso vgl_vector_3d
00205 template <class T> inline double operator/(v const& a, v const& b)
00206 { return dot_product(a,b)/(double)dot_product(b,b); }
00207 
00208 //: Normalise by dividing through by the length, thus returning a length 1 vector.
00209 //  If a is zero length, return (0,0).
00210 // \relatesalso vgl_vector_3d
00211 template <class T> inline v&     normalize(v& a) { double l=a.length(); return l?a/=l:a; }
00212 
00213 //: Return a normalised version of a.
00214 //  If a is zero length, return (0,0).
00215 // \relatesalso vgl_vector_3d
00216 template <class T> inline v      normalized(v const& a) { double l=a.length(); return l?a/l:a; }
00217 
00218 //: One-parameter family of unit vectors that are orthogonal to \a a, v(s).
00219 // To get two orthogonal vectors call this function twice with s=0 and
00220 // s=0.25 for example.
00221 // \param s 0<=s<=1, v(0)==v(1)
00222 // \note This function is not continuous near z==0. (Under the Hairy Ball
00223 // theorem no such smooth function can exist.)
00224 // \note This vector need not be normalized but it should have non-zero length.
00225 template <class T> v             orthogonal_vectors(v const& a, double s);
00226 
00227 #undef v
00228 
00229 #define VGL_VECTOR_3D_INSTANTIATE(T) extern "please include vgl/vgl_vector_3d.txx first"
00230 
00231 #endif // vgl_vector_3d_h_