core/vgl/vgl_plane_3d.txx
Go to the documentation of this file.
00001 // This is core/vgl/vgl_plane_3d.txx
00002 #ifndef vgl_plane_3d_txx_
00003 #define vgl_plane_3d_txx_
00004 //:
00005 // \file
00006 
00007 #include "vgl_plane_3d.h"
00008 #include <vgl/vgl_homg_plane_3d.h>
00009 #include <vgl/vgl_point_3d.h>
00010 #include <vcl_cassert.h>
00011 #include <vcl_iostream.h>
00012 
00013 //: Construct from homogeneous plane
00014 template <class T>
00015 vgl_plane_3d<T>::vgl_plane_3d(vgl_homg_plane_3d<T> const& p)
00016   : a_(p.a()), b_(p.b()), c_(p.c()), d_(p.d()) {assert (a_||b_||c_);}
00017 
00018 //: Construct from three points
00019 template <class T>
00020 vgl_plane_3d<T>::vgl_plane_3d (vgl_point_3d<T> const& p1,
00021                                vgl_point_3d<T> const& p2,
00022                                vgl_point_3d<T> const& p3)
00023 : a_(p2.y()*p3.z()-p2.z()*p3.y()
00024     +p3.y()*p1.z()-p3.z()*p1.y()
00025     +p1.y()*p2.z()-p1.z()*p2.y())
00026 , b_(p2.z()*p3.x()-p2.x()*p3.z()
00027     +p3.z()*p1.x()-p3.x()*p1.z()
00028     +p1.z()*p2.x()-p1.x()*p2.z())
00029 , c_(p2.x()*p3.y()-p2.y()*p3.x()
00030     +p3.x()*p1.y()-p3.y()*p1.x()
00031     +p1.x()*p2.y()-p1.y()*p2.x())
00032 , d_(p1.x()*(p2.z()*p3.y()-p2.y()*p3.z())
00033     +p2.x()*(p3.z()*p1.y()-p3.y()*p1.z())
00034     +p3.x()*(p1.z()*p2.y()-p1.y()*p2.z()))
00035 {
00036   assert(a_||b_||c_); // points should not be collinear or coinciding
00037 }
00038 
00039 //: Construct from normal and a point
00040 template <class T>
00041 vgl_plane_3d<T>::vgl_plane_3d(vgl_vector_3d<T> const& n,
00042                               vgl_point_3d<T> const& p)
00043  : a_(n.x()), b_(n.y()), c_(n.z()), d_(-(n.x()*p.x()+n.y()*p.y()+n.z()*p.z()))
00044 {
00045   assert(a_||b_||c_); // normal vector should not be the null vector
00046 }
00047 
00048 //: Return true if p is on the plane
00049 template <class T>
00050 bool vgl_plane_3d<T>::contains(vgl_point_3d<T> const& p, T tol) const
00051 {
00052   //to maintain a consistent distance metric the plane should be normalized
00053   vgl_vector_3d<T> n(a_, b_, c_), pv(p.x(), p.y(), p.z());
00054   T dist = (dot_product(n,pv) + d_) / static_cast<T>(length(n));
00055   return dist >= -tol && dist <= tol;
00056 }
00057 
00058 template <class T>
00059 bool vgl_plane_3d<T>::operator==(vgl_plane_3d<T> const& p) const
00060 {
00061   return (this==&p) ||
00062          (   (a()*p.b()==p.a()*b())
00063           && (a()*p.c()==p.a()*c())
00064           && (a()*p.d()==p.a()*d())
00065           && (b()*p.c()==p.b()*c())
00066           && (b()*p.d()==p.b()*d())
00067           && (c()*p.d()==p.c()*d()) );
00068 }
00069 
00070 #define vp(os,v,s) { os<<' '; if ((v)>0) os<<'+'; if ((v)&&!s[0]) os<<(v); else { \
00071                      if ((v)==-1) os<<'-';\
00072                      else if ((v)!=0&&(v)!=1) os<<(v);\
00073                      if ((v)!=0) os<<' '<<s; } }
00074 
00075 template <class T>
00076 vcl_ostream& operator<<(vcl_ostream& os, const vgl_plane_3d<T>& p)
00077 {
00078   os << "<vgl_plane_3d"; vp(os,p.a(),"x"); vp(os,p.b(),"y"); vp(os,p.c(),"z");
00079   vp(os,p.d(),""); return os << " = 0 >";
00080 }
00081 
00082 #undef vp
00083 
00084 template <class T>
00085 vcl_istream& operator>>(vcl_istream& is, vgl_plane_3d<T>& p)
00086 {
00087   if (! is.good()) return is; // (TODO: should throw an exception)
00088   bool paren = false;
00089   bool formatted = false;
00090   T a, b, c, d;
00091   is >> vcl_ws; // jump over any leading whitespace
00092   if (is.eof()) return is; // nothing to be set because of EOF (TODO: should throw an exception)
00093   if (is.peek() == '(') { is.ignore(); paren=true; }
00094   is >> vcl_ws >> a >> vcl_ws;
00095   if (is.eof()) return is;
00096   if (is.peek() == ',') is.ignore();
00097   else if (is.peek() == 'x') { is.ignore(); formatted=true; }
00098   is >> vcl_ws >> b >> vcl_ws;
00099   if (is.eof()) return is;
00100   if (formatted) {
00101     if (is.eof()) return is;
00102     if (is.peek() == 'y') is.ignore();
00103     else                  return is; // formatted input incorrect (TODO: throw an exception)
00104   }
00105   else if (is.peek() == ',') is.ignore();
00106   is >> vcl_ws >> c >> vcl_ws;
00107   if (is.eof()) return is;
00108   if (formatted) {
00109     if (is.eof()) return is;
00110     if (is.peek() == 'z') is.ignore();
00111     else                  return is; // formatted input incorrect (TODO: throw an exception)
00112   }
00113   else if (is.peek() == ',') is.ignore();
00114   is >> vcl_ws >> d >> vcl_ws;
00115   if (paren) {
00116     if (is.eof()) return is;
00117     if (is.peek() == ')') is.ignore();
00118     else                  return is; // closing parenthesis is missing (TODO: throw an exception)
00119   }
00120   if (formatted) {
00121     if (is.eof()) return is;
00122     if (is.peek() == '=') is.ignore();
00123     else                  return is; // closing parenthesis is missing (TODO: throw an exception)
00124     is >> vcl_ws;
00125     if (is.peek() == '0') is.ignore();
00126     else                  return is; // closing parenthesis is missing (TODO: throw an exception)
00127   }
00128   p.set(a,b,c,d);
00129   return is;
00130 }
00131 
00132 #undef VGL_PLANE_3D_INSTANTIATE
00133 #define VGL_PLANE_3D_INSTANTIATE(T) \
00134 template class vgl_plane_3d<T >; \
00135 template vcl_ostream& operator<<(vcl_ostream&, vgl_plane_3d<T >const&); \
00136 template vcl_istream& operator>>(vcl_istream&, vgl_plane_3d<T >&)
00137 
00138 #endif // vgl_plane_3d_txx_