core/vgl/vgl_vector_3d.txx
Go to the documentation of this file.
00001 // This is core/vgl/vgl_vector_3d.txx
00002 #ifndef vgl_vector_3d_txx_
00003 #define vgl_vector_3d_txx_
00004 //:
00005 // \file
00006 
00007 #include "vgl_vector_3d.h"
00008 #include "vgl_tolerance.txx"
00009 
00010 #include <vcl_cmath.h> // sqrt() , acos()
00011 #include <vcl_iostream.h>
00012 #include <vcl_cassert.h>
00013 #include <vcl_deprecated.h>
00014 
00015 template <class T>
00016 double vgl_vector_3d<T>::length() const
00017 {
00018   return vcl_sqrt( 0.0+sqr_length() );
00019 }
00020 
00021 //: The one-parameter family of unit vectors that are orthogonal to *this, v(s).
00022 // The parameterization is such that 0<=s<1, v(0)==v(1)
00023 template <class T>
00024 vgl_vector_3d<T> vgl_vector_3d<T>::orthogonal_vectors(double s) const
00025 {
00026   VXL_DEPRECATED("vgl_vector_3d<T>::orthogonal_vectors(double s)");
00027   return ::orthogonal_vectors(*this, s);
00028 }
00029 
00030 template<class T>
00031 double angle(vgl_vector_3d<T> const& a, vgl_vector_3d<T> const& b)
00032 {
00033   double ca = cos_angle(a,b);
00034   // Deal with numerical errors giving values slightly outside range.
00035   if (ca>=-1.0)
00036   {
00037     if (ca<=1.0)
00038       return vcl_acos(ca);
00039     else
00040       return 0;
00041   }
00042   else
00043     return vcl_acos(-1.0); // pi
00044 }
00045 
00046 template <class T>
00047 bool orthogonal(vgl_vector_3d<T> const& a, vgl_vector_3d<T> const& b, double eps)
00048 {
00049   T dot = dot_product(a,b); // should be zero
00050   if (eps <= 0 || dot == T(0)) return dot == T(0);
00051   eps *= eps * a.sqr_length() * b.sqr_length();
00052   dot *= dot;
00053   return dot < eps;
00054 }
00055 
00056 template <class T>
00057 bool parallel(vgl_vector_3d<T> const& a, vgl_vector_3d<T> const& b, double eps)
00058 {
00059   double cross = cross_product(a,b).sqr_length(); // should be zero
00060   if (eps <= 0 || cross == 0.0) return cross == 0.0;
00061   eps *= eps * a.sqr_length() * b.sqr_length();
00062   return cross < eps;
00063 }
00064 
00065 template <class T>
00066 vgl_vector_3d<T> orthogonal_vectors(vgl_vector_3d<T> const& a, double s)
00067 {
00068   assert(a.length()>0.0);
00069 
00070   // enforce parameter range
00071   if (s<0.0) s=0.0;
00072   if (s>1.0) s = 1.0;
00073   double tol = static_cast<double>(vgl_tolerance<T>::position);
00074   double nx = static_cast<double>(a.x_);
00075   double ny = static_cast<double>(a.y_);
00076   double nz = static_cast<double>(a.z_);
00077   double two_pi = 2*vcl_acos(-1.0);
00078   double co = vcl_cos(two_pi*s);
00079   double si = vcl_sin(two_pi*s);
00080 
00081   double mnz = vcl_fabs(nz);
00082   if (mnz>tol)  // General case
00083   {
00084     double rx = nx/nz;
00085     double ry = ny/nz;
00086     double q = co*rx +si*ry;
00087     double a = 1.0/vcl_sqrt(1+q*q);
00088     T vx = static_cast<T>(a*co);
00089     T vy = static_cast<T>(a*si);
00090     T vz = -static_cast<T>(rx*vx + ry*vy);
00091     return vgl_vector_3d<T>(vx, vy, vz);
00092   }
00093   else  // Special cases, nz ~ 0
00094   {
00095     double mny = vcl_fabs(ny);
00096     if (mny>tol)
00097     {
00098       double r = nx/ny;
00099       double a = 1/vcl_sqrt(1+co*co*r*r);
00100       T vx = static_cast<T>(a*co);
00101       T vz = static_cast<T>(a*si);
00102       T vy = -static_cast<T>(a*co*r);
00103       return vgl_vector_3d<T>(vx, vy, vz);
00104     }
00105     else
00106     {
00107       // assume mnx>tol provided that input vector was not null
00108       double r = ny/nx;
00109       double a = 1/vcl_sqrt(1+co*co*r*r);
00110       T vy = static_cast<T>(a*co);
00111       T vz = static_cast<T>(a*si);
00112       T vx = -static_cast<T>(a*co*r);
00113       return vgl_vector_3d<T>(vx, vy, vz);
00114     }
00115   }
00116 }
00117 
00118 //: Write "<vgl_vector_3d x,y,z> " to stream
00119 template <class T>
00120 vcl_ostream&  operator<<(vcl_ostream& s, vgl_vector_3d<T> const& p)
00121 {
00122   return s << "<vgl_vector_3d "<< p.x() << ',' << p.y() << ',' << p.z() << "> ";
00123 }
00124 
00125 //: Read from stream, possibly with formatting
00126 //  Either just reads three blank-separated numbers,
00127 //  or reads three comma-separated numbers,
00128 //  or reads three numbers in parenthesized form "(123, 321, 567)"
00129 // \relatesalso vgl_vector_3d
00130 template <class T>
00131 vcl_istream& vgl_vector_3d<T>::read(vcl_istream& is)
00132 {
00133   if (! is.good()) return is; // (TODO: should throw an exception)
00134   bool paren = false;
00135   T tx, ty, tz;
00136   is >> vcl_ws; // jump over any leading whitespace
00137   if (is.eof()) return is; // nothing to be set because of EOF (TODO: should throw an exception)
00138   if (is.peek() == '(') { is.ignore(); paren=true; }
00139   is >> vcl_ws >> tx >> vcl_ws;
00140   if (is.eof()) return is;
00141   if (is.peek() == ',') is.ignore();
00142   is >> vcl_ws >> ty >> vcl_ws;
00143   if (is.eof()) return is;
00144   if (is.peek() == ',') is.ignore();
00145   is >> vcl_ws >> tz >> vcl_ws;
00146   if (paren) {
00147     if (is.eof()) return is;
00148     if (is.peek() == ')') is.ignore();
00149     else                  return is; // closing parenthesis is missing (TODO: throw an exception)
00150   }
00151   set(tx,ty,tz);
00152   return is;
00153 }
00154 
00155 //: Read from stream, possibly with formatting
00156 //  Either just reads three blank-separated numbers,
00157 //  or reads three comma-separated numbers,
00158 //  or reads three numbers in parenthesized form "(123, 321, 567)"
00159 // \relatesalso vgl_vector_3d
00160 template <class T>
00161 vcl_istream&  operator>>(vcl_istream& is, vgl_vector_3d<T>& p)
00162 {
00163   return p.read(is);
00164 }
00165 
00166 #undef VGL_VECTOR_3D_INSTANTIATE
00167 #define VGL_VECTOR_3D_INSTANTIATE(T) \
00168 template class vgl_vector_3d<T >;\
00169 VCL_INSTANTIATE_INLINE(vgl_vector_3d<T >  operator+         (vgl_vector_3d<T > const&, vgl_vector_3d<T > const&));\
00170 VCL_INSTANTIATE_INLINE(vgl_vector_3d<T >  operator-         (vgl_vector_3d<T > const&, vgl_vector_3d<T > const&));\
00171 VCL_INSTANTIATE_INLINE(vgl_vector_3d<T >& operator+=        (vgl_vector_3d<T >&, vgl_vector_3d<T > const&));\
00172 VCL_INSTANTIATE_INLINE(vgl_vector_3d<T >& operator-=        (vgl_vector_3d<T >&, vgl_vector_3d<T > const&));\
00173 VCL_INSTANTIATE_INLINE(vgl_vector_3d<T >  operator+         (vgl_vector_3d<T > const&));\
00174 VCL_INSTANTIATE_INLINE(vgl_vector_3d<T >  operator-         (vgl_vector_3d<T > const&));\
00175 VCL_INSTANTIATE_INLINE(vgl_vector_3d<T >  operator*         (double, vgl_vector_3d<T > const&));\
00176 VCL_INSTANTIATE_INLINE(vgl_vector_3d<T >  operator*         (vgl_vector_3d<T > const&, double));\
00177 VCL_INSTANTIATE_INLINE(vgl_vector_3d<T >  operator/         (vgl_vector_3d<T > const&, double));\
00178 VCL_INSTANTIATE_INLINE(vgl_vector_3d<T >& operator*=        (vgl_vector_3d<T >&, double));\
00179 VCL_INSTANTIATE_INLINE(vgl_vector_3d<T >& operator/=        (vgl_vector_3d<T >&, double));\
00180 VCL_INSTANTIATE_INLINE(T                  dot_product       (vgl_vector_3d<T > const&, vgl_vector_3d<T > const&));\
00181 VCL_INSTANTIATE_INLINE(T                  inner_product     (vgl_vector_3d<T > const&, vgl_vector_3d<T > const&));\
00182 VCL_INSTANTIATE_INLINE(vgl_vector_3d<T >  cross_product     (vgl_vector_3d<T > const&, vgl_vector_3d<T > const&));\
00183 VCL_INSTANTIATE_INLINE(double             cos_angle         (vgl_vector_3d<T > const&, vgl_vector_3d<T > const&));\
00184 template               double             angle             (vgl_vector_3d<T > const&, vgl_vector_3d<T > const&);\
00185 template               bool               orthogonal        (vgl_vector_3d<T > const&, vgl_vector_3d<T > const&, double);\
00186 template               bool               parallel          (vgl_vector_3d<T > const&, vgl_vector_3d<T > const&, double);\
00187 template               vgl_vector_3d<T >  orthogonal_vectors(vgl_vector_3d<T > const&, double);\
00188 VCL_INSTANTIATE_INLINE(double             operator/         (vgl_vector_3d<T > const&, vgl_vector_3d<T > const&));\
00189 VCL_INSTANTIATE_INLINE(vgl_vector_3d<T >& normalize         (vgl_vector_3d<T >&));\
00190 VCL_INSTANTIATE_INLINE(vgl_vector_3d<T >  normalized        (vgl_vector_3d<T > const&));\
00191 template               vcl_ostream&       operator<<        (vcl_ostream&, vgl_vector_3d<T >const&);\
00192 template               vcl_istream&       operator>>        (vcl_istream&, vgl_vector_3d<T >&)
00193 
00194 #endif // vgl_vector_3d_txx_