00001
00002 #ifndef vgl_plane_3d_txx_
00003 #define vgl_plane_3d_txx_
00004
00005
00006
00007 #include "vgl_plane_3d.h"
00008 #include <vgl/vgl_homg_plane_3d.h>
00009 #include <vgl/vgl_point_3d.h>
00010 #include <vgl/vgl_point_2d.h>
00011 #include <vgl/vgl_closest_point.h>
00012 #include <vgl/vgl_distance.h>
00013
00014 #include <vcl_cmath.h>
00015 #include <vcl_cassert.h>
00016 #include <vcl_iostream.h>
00017
00018
00019 template <class T>
00020 vgl_plane_3d<T>::vgl_plane_3d(vgl_homg_plane_3d<T> const& p)
00021 : a_(p.a()), b_(p.b()), c_(p.c()), d_(p.d()) {assert (a_||b_||c_);}
00022
00023
00024 template <class T>
00025 vgl_plane_3d<T>::vgl_plane_3d (vgl_point_3d<T> const& p1,
00026 vgl_point_3d<T> const& p2,
00027 vgl_point_3d<T> const& p3)
00028 : a_(p2.y()*p3.z()-p2.z()*p3.y()
00029 +p3.y()*p1.z()-p3.z()*p1.y()
00030 +p1.y()*p2.z()-p1.z()*p2.y())
00031 , b_(p2.z()*p3.x()-p2.x()*p3.z()
00032 +p3.z()*p1.x()-p3.x()*p1.z()
00033 +p1.z()*p2.x()-p1.x()*p2.z())
00034 , c_(p2.x()*p3.y()-p2.y()*p3.x()
00035 +p3.x()*p1.y()-p3.y()*p1.x()
00036 +p1.x()*p2.y()-p1.y()*p2.x())
00037 , d_(p1.x()*(p2.z()*p3.y()-p2.y()*p3.z())
00038 +p2.x()*(p3.z()*p1.y()-p3.y()*p1.z())
00039 +p3.x()*(p1.z()*p2.y()-p1.y()*p2.z()))
00040 {
00041 assert(a_||b_||c_);
00042 }
00043
00044
00045 template <class T>
00046 vgl_plane_3d<T>::vgl_plane_3d(vgl_vector_3d<T> const& n,
00047 vgl_point_3d<T> const& p)
00048 : a_(n.x()), b_(n.y()), c_(n.z()), d_(-(n.x()*p.x()+n.y()*p.y()+n.z()*p.z()))
00049 {
00050 assert(a_||b_||c_);
00051 }
00052
00053
00054 template <class T>
00055 bool vgl_plane_3d<T>::contains(vgl_point_3d<T> const& p, T tol) const
00056 {
00057
00058 vgl_vector_3d<T> n(a_, b_, c_), pv(p.x(), p.y(), p.z());
00059 T dist = (dot_product(n,pv) + d_) / static_cast<T>(length(n));
00060 return dist >= -tol && dist <= tol;
00061 }
00062
00063 template <class T>
00064 bool vgl_plane_3d<T>::operator==(vgl_plane_3d<T> const& p) const
00065 {
00066 return (this==&p) ||
00067 ( (a()*p.b()==p.a()*b())
00068 && (a()*p.c()==p.a()*c())
00069 && (a()*p.d()==p.a()*d())
00070 && (b()*p.c()==p.b()*c())
00071 && (b()*p.d()==p.b()*d())
00072 && (c()*p.d()==p.c()*d()) );
00073 }
00074
00075 #define vp(os,v,s) { os<<' '; if ((v)>0) os<<'+'; if ((v)&&!s[0]) os<<(v); else { \
00076 if ((v)==-1) os<<'-';\
00077 else if ((v)!=0&&(v)!=1) os<<(v);\
00078 if ((v)!=0) os<<' '<<s; } }
00079
00080 template <class T>
00081 vcl_ostream& operator<<(vcl_ostream& os, const vgl_plane_3d<T>& p)
00082 {
00083 os << "<vgl_plane_3d"; vp(os,p.a(),"x"); vp(os,p.b(),"y"); vp(os,p.c(),"z");
00084 vp(os,p.d(),""); return os << " = 0 >";
00085 }
00086
00087 #undef vp
00088
00089 template <class T>
00090 vcl_istream& operator>>(vcl_istream& is, vgl_plane_3d<T>& p)
00091 {
00092 if (! is.good()) return is;
00093 bool paren = false;
00094 bool formatted = false;
00095 T a, b, c, d;
00096 is >> vcl_ws;
00097 if (is.eof()) return is;
00098 if (is.peek() == '(') { is.ignore(); paren=true; }
00099 is >> vcl_ws >> a >> vcl_ws;
00100 if (is.eof()) return is;
00101 if (is.peek() == ',') is.ignore();
00102 else if (is.peek() == 'x') { is.ignore(); formatted=true; }
00103 is >> vcl_ws >> b >> vcl_ws;
00104 if (is.eof()) return is;
00105 if (formatted) {
00106 if (is.eof()) return is;
00107 if (is.peek() == 'y') is.ignore();
00108 else return is;
00109 }
00110 else if (is.peek() == ',') is.ignore();
00111 is >> vcl_ws >> c >> vcl_ws;
00112 if (is.eof()) return is;
00113 if (formatted) {
00114 if (is.eof()) return is;
00115 if (is.peek() == 'z') is.ignore();
00116 else return is;
00117 }
00118 else if (is.peek() == ',') is.ignore();
00119 is >> vcl_ws >> d >> vcl_ws;
00120 if (paren) {
00121 if (is.eof()) return is;
00122 if (is.peek() == ')') is.ignore();
00123 else return is;
00124 }
00125 if (formatted) {
00126 if (is.eof()) return is;
00127 if (is.peek() == '=') is.ignore();
00128 else return is;
00129 is >> vcl_ws;
00130 if (is.peek() == '0') is.ignore();
00131 else return is;
00132 }
00133 p.set(a,b,c,d);
00134 return is;
00135 }
00136
00137 template <class T>
00138 void vgl_plane_3d<T>::
00139 plane_coord_vectors(vgl_vector_3d<T>& uvec, vgl_vector_3d<T>& vvec) const
00140 {
00141 vgl_vector_3d<T> Y((T)0, (T)1, (T)0);
00142 vgl_vector_3d<T> n = this->normal();
00143 T dp = (T)1 - vcl_fabs(dot_product(n, Y));
00144 T tol = ((T)1)/((T)10);
00145 if (dp>tol)
00146 {
00147 uvec = normalized(cross_product(Y, n));
00148 vvec = normalized(cross_product(n, uvec));
00149 }
00150 else {
00151 vgl_vector_3d<T> Z((T)0, (T)0, (T)1);
00152 uvec = normalized(cross_product(n, Z));
00153 vvec = normalized(cross_product(uvec, n));
00154 }
00155 }
00156
00157 template <class T>
00158 bool vgl_plane_3d<T>::plane_coords(vgl_point_3d<T> const& p3d,
00159 vgl_point_2d<T>& p2d, T tol) const
00160 {
00161
00162 vgl_point_3d<T> pt_on_plane = vgl_closest_point(p3d, *this);
00163 double dist = vgl_distance(p3d, pt_on_plane), dtol = static_cast<double>(tol);
00164 if (dist>dtol)
00165 return false;
00166
00167
00168 vgl_vector_3d<T> Y((T)0, (T)1, (T)0);
00169 vgl_point_3d<T> origin_pt = vgl_closest_point_origin(*this);
00170 vgl_vector_3d<T> p = pt_on_plane - origin_pt;
00171 vgl_vector_3d<T> uvec, vvec;
00172 this->plane_coord_vectors(uvec, vvec);
00173 T u = dot_product(uvec, p), v = dot_product(vvec, p);
00174 p2d.set(u, v);
00175 return true;
00176 }
00177
00178 template <class T>
00179 vgl_point_3d<T>
00180 vgl_plane_3d<T>::world_coords(vgl_point_2d<T> const& p2d) const
00181 {
00182 vgl_point_3d<T> origin_pt = vgl_closest_point_origin(*this);
00183 vgl_vector_3d<T> uvec, vvec;
00184 this->plane_coord_vectors(uvec, vvec);
00185 vgl_point_3d<T> p3d = origin_pt + uvec*p2d.x() + vvec*p2d.y();
00186 return p3d;
00187 }
00188
00189 #undef VGL_PLANE_3D_INSTANTIATE
00190 #define VGL_PLANE_3D_INSTANTIATE(T) \
00191 template class vgl_plane_3d<T >; \
00192 template vcl_ostream& operator<<(vcl_ostream&, vgl_plane_3d<T >const&); \
00193 template vcl_istream& operator>>(vcl_istream&, vgl_plane_3d<T >&)
00194
00195 #endif // vgl_plane_3d_txx_