core/vgl/vgl_infinite_line_3d.txx
Go to the documentation of this file.
00001 // This is core/vgl/vgl_infinite_line_3d.txx
00002 #ifndef vgl_infinite_line_3d_txx_
00003 #define vgl_infinite_line_3d_txx_
00004 
00005 #include "vgl_infinite_line_3d.h"
00006 #include <vcl_cassert.h>
00007 #include <vcl_iostream.h>
00008 #include <vcl_cmath.h> // for fabs
00009 template <class Type>
00010 vgl_infinite_line_3d<Type>::vgl_infinite_line_3d(vgl_point_3d<Type> const& p1,
00011                                                  vgl_point_3d<Type> const& p2)
00012 {
00013   vgl_vector_3d<Type> dir = p2-p1;
00014   vgl_infinite_line_3d<Type> l(p1, dir);
00015   x0_ = l.x0();
00016   t_ = dir;
00017 }
00018 
00019 template <class Type>
00020 void vgl_infinite_line_3d<Type>::
00021 compute_uv_vectors(vgl_vector_3d<Type>& u, vgl_vector_3d<Type>& v) const
00022 {
00023   // define the plane coordinate system (u, v)
00024   // v is given by the cross product of t with x, unless t is nearly
00025   // parallel to x, in which case v is given by z X t.
00026   vgl_vector_3d<Type> x(Type(1), Type(0), Type(0));
00027   v = cross_product(t_,x);
00028   Type vmag = static_cast<Type>(v.length());
00029   double vmagd = static_cast<double>(vmag);
00030   if (vmagd < 1.0e-8) {
00031     vgl_vector_3d<Type> z(Type(0), Type(0), Type(1));
00032     v = cross_product(z, t_);
00033     vmag = static_cast<Type>(v.length());
00034     assert(vmag>Type(0));
00035     v/=vmag;
00036   }
00037   else v/=vmag;
00038   // The other plane coordinate vector is perpendicular to both t and v
00039   u = cross_product(v,t_);
00040   Type umag = static_cast<Type>(u.length());
00041   u/=umag;
00042 }
00043 
00044 template <class Type>
00045 vgl_infinite_line_3d<Type>::
00046 vgl_infinite_line_3d(vgl_point_3d<Type> const& p,
00047                      vgl_vector_3d<Type> const& dir)
00048 {
00049   // reconcile direction so that tangent is in the positive hemisphere
00050   double ttx = vcl_fabs(static_cast<double>(dir.x()));
00051   double tty = vcl_fabs(static_cast<double>(dir.y()));
00052   double ttz = vcl_fabs(static_cast<double>(dir.z()));
00053   double max_comp = ttx;
00054   double sign = static_cast<double>(dir.x());
00055   if (max_comp < tty) {
00056     max_comp = tty;
00057     sign = static_cast<double>(dir.y());
00058   }
00059   if (max_comp < ttz) {
00060     max_comp = ttz;
00061     sign = static_cast<double>(dir.z());
00062   }
00063   // switch sense if max component is negative
00064   Type sense = static_cast<Type>(sign/max_comp);
00065   t_ = normalized(dir*sense);
00066   // Define the plane perpendicular to the line passing through the origin
00067   // the plane normal is t_ the distance of the plane from the origin is 0
00068   // it follows that the intersection of the line with the perpendicular plane
00069   // is as follows:
00070   Type mag = static_cast<Type>(t_.length());
00071   assert(mag>Type(0));
00072   vgl_vector_3d<Type> pv(p.x(), p.y(), p.z());
00073   Type dp = dot_product(pv, t_);
00074   Type k = -dp/(mag*mag);
00075   // The intersection point
00076   vgl_vector_3d<Type> p0 = pv + k*t_, u, v;
00077   this->compute_uv_vectors(u, v);
00078   // The location of the intersection point in plane coordinates can now be computed
00079   Type u0 = dot_product(u, p0), v0 = dot_product(v, p0);
00080   x0_.set(u0, v0);
00081 }
00082 
00083 // the point on the line closest to the origin
00084 template <class Type>
00085 vgl_point_3d<Type> vgl_infinite_line_3d<Type>::point() const
00086 {
00087   // u,v plane coordinate vectors
00088   vgl_vector_3d<Type> u, v, pv;
00089   this->compute_uv_vectors(u, v);
00090   pv = x0_.x()*u + x0_.y()*v;
00091   return vgl_point_3d<Type>(pv.x(), pv.y(), pv.z());
00092 }
00093 
00094 template <class Type>
00095 bool vgl_infinite_line_3d<Type>::contains(const vgl_point_3d<Type>& p ) const
00096 {
00097   vgl_point_3d<Type> point1 = this->point();
00098   vgl_point_3d<Type> point2 = this->point_t(Type(1));
00099   double seg = 1.0;
00100   double len1 = static_cast<double>((point1 - p).length());
00101   double len2 = static_cast<double>((point2 - p).length());
00102   // two cases: point inside (point1, point2) segment;
00103   //            point outside (point1, point2) segment
00104   double r = seg -(len1 + len2);
00105   if (len1>seg||len2>seg)
00106     r = seg - vcl_fabs(len1-len2);
00107   return r < 1e-8 && r > -1e-8;
00108 }
00109 
00110 // stream operators
00111 template <class Type>
00112 vcl_ostream& operator<<(vcl_ostream& s, vgl_infinite_line_3d<Type> const & p)
00113 {
00114   return s << "<vgl_infinite_line_3d: origin" << p.x0() << " dir " << p.direction() << " >";
00115 }
00116 
00117 template <class Type>
00118 vcl_istream& operator>>(vcl_istream& s, vgl_infinite_line_3d<Type>& p)
00119 {
00120   vgl_vector_2d<Type> x_0;
00121   vgl_vector_3d<Type> dir;
00122   s >> x_0 >> dir;
00123   p.set(x_0, dir);
00124   return s;
00125 }
00126 
00127 #undef VGL_INFINITE_LINE_3D_INSTANTIATE
00128 #define VGL_INFINITE_LINE_3D_INSTANTIATE(Type) \
00129 template class vgl_infinite_line_3d<Type >;\
00130 template vcl_istream& operator>>(vcl_istream&, vgl_infinite_line_3d<Type >&);\
00131 template vcl_ostream& operator<<(vcl_ostream&, vgl_infinite_line_3d<Type > const&)
00132 
00133 #endif // vgl_infinite_line_3d_txx_