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