core/vgl/vgl_homg_plane_3d.txx
Go to the documentation of this file.
00001 // This is core/vgl/vgl_homg_plane_3d.txx
00002 #ifndef vgl_homg_plane_3d_txx_
00003 #define vgl_homg_plane_3d_txx_
00004 //:
00005 // \file
00006 
00007 #include "vgl_homg_plane_3d.h"
00008 #include <vcl_cassert.h>
00009 #include <vcl_cmath.h> // for std::sqrt and std::fabs(double)
00010 #include <vcl_iostream.h>
00011 #include <vgl/vgl_plane_3d.h>
00012 #include <vgl/vgl_homg_point_3d.h>
00013 #include <vgl/vgl_homg_line_3d_2_points.h>
00014 
00015 //: Construct from non-homogeneous plane
00016 template <class Type>
00017 vgl_homg_plane_3d<Type>::vgl_homg_plane_3d(vgl_plane_3d<Type> const& pl)
00018   : a_(pl.a()), b_(pl.b()), c_(pl.c()), d_(pl.d()) {}
00019 
00020 //: Construct from three points
00021 template <class Type>
00022 vgl_homg_plane_3d<Type>::vgl_homg_plane_3d (vgl_homg_point_3d<Type> const& p1,
00023                                             vgl_homg_point_3d<Type> const& p2,
00024                                             vgl_homg_point_3d<Type> const& p3)
00025 : a_(p1.w()*(p2.y()*p3.z()-p2.z()*p3.y())
00026     +p2.w()*(p3.y()*p1.z()-p3.z()*p1.y())
00027     +p3.w()*(p1.y()*p2.z()-p1.z()*p2.y()))
00028 , b_(p1.w()*(p2.z()*p3.x()-p2.x()*p3.z())
00029     +p2.w()*(p3.z()*p1.x()-p3.x()*p1.z())
00030     +p3.w()*(p1.z()*p2.x()-p1.x()*p2.z()))
00031 , c_(p1.w()*(p2.x()*p3.y()-p2.y()*p3.x())
00032     +p2.w()*(p3.x()*p1.y()-p3.y()*p1.x())
00033     +p3.w()*(p1.x()*p2.y()-p1.y()*p2.x()))
00034 , d_(p1.x()*(p2.z()*p3.y()-p2.y()*p3.z())
00035     +p2.x()*(p1.y()*p3.z()-p1.z()*p3.y())
00036     +p3.x()*(p1.z()*p2.y()-p1.y()*p2.z()))
00037 {
00038   assert(a_||b_||c_||d_); // points should not be collinear or coinciding
00039 }
00040 
00041 //: Construct from two concurrent lines
00042 template <class Type>
00043 vgl_homg_plane_3d<Type>::vgl_homg_plane_3d(vgl_homg_line_3d_2_points<Type> const& l1,
00044                                            vgl_homg_line_3d_2_points<Type> const& l2)
00045 {
00046   assert(concurrent(l1,l2));
00047   vgl_homg_point_3d<Type> p1 = l1.point_finite();
00048   vgl_homg_point_3d<Type> p2 = l1.point_infinite();
00049   vgl_homg_point_3d<Type> p3 = l2.point_finite();
00050   if (collinear(p1,p2,p3)) p3 = l2.point_infinite();
00051   *this = vgl_homg_plane_3d<Type>(p1,p2,p3);
00052 }
00053 
00054 //: Construct from normal and a point
00055 // This will fail when the given point is at infinity!
00056 template <class Type>
00057 vgl_homg_plane_3d<Type>::vgl_homg_plane_3d(vgl_vector_3d<Type> const& n,
00058                                            vgl_homg_point_3d<Type> const&p)
00059  : a_(n.x()*p.w()), b_(n.y()*p.w()), c_(n.z()*p.w()),
00060    d_(-(n.x()*p.x()+n.y()*p.y()+n.z()*p.z())) {}
00061 
00062 //: divide all coefficients by sqrt(a^2 + b^2 + c^2)
00063 template <class Type>
00064 void vgl_homg_plane_3d<Type>::normalize()
00065 {
00066   double sum = a_*a_ + b_*b_ + c_*c_;
00067   if (sum<1e-12) // don't normalize plane at infinity
00068     return;
00069   double den = vcl_sqrt(sum);
00070   double an= (double)a()/den; a_ = (Type)an;
00071   double bn= (double)b()/den; b_ = (Type)bn;
00072   double cn= (double)c()/den; c_ = (Type)cn;
00073   double dn= (double)d()/den; d_ = (Type)dn;
00074   //standardize so that largest of (|a|,|b|,|c|) is positive
00075   if ((vcl_fabs(an)>=vcl_fabs(bn) && vcl_fabs(an)>=vcl_fabs(cn) && an < 0) ||
00076       (vcl_fabs(bn)>vcl_fabs(an) && vcl_fabs(bn)>=vcl_fabs(cn) && bn < 0) ||
00077       (vcl_fabs(cn)>vcl_fabs(an) && vcl_fabs(cn)>vcl_fabs(bn) && cn < 0))
00078     a_ = -a_, b_ = -b_, c_ = -c_, d_ = -d_;
00079   return;
00080 }
00081 
00082 template <class Type>
00083 bool vgl_homg_plane_3d<Type>::operator==(vgl_homg_plane_3d<Type> const& p) const
00084 {
00085   return (this==&p) ||
00086          (   (a()*p.b()==p.a()*b())
00087           && (a()*p.c()==p.a()*c())
00088           && (a()*p.d()==p.a()*d())
00089           && (b()*p.c()==p.b()*c())
00090           && (b()*p.d()==p.b()*d())
00091           && (c()*p.d()==p.c()*d()) );
00092 }
00093 
00094 template <class Type>
00095 vcl_ostream& operator<<(vcl_ostream& s, const vgl_homg_plane_3d<Type>& p)
00096 {
00097   return s << " <vgl_homg_plane_3d "
00098            << p.a() << " x + "
00099            << p.b() << " y + "
00100            << p.c() << " z + "
00101            << p.d() << " w = 0 >";
00102 }
00103 
00104 template <class Type>
00105 vcl_istream& operator>>(vcl_istream& s, vgl_homg_plane_3d<Type>& p)
00106 {
00107   Type a, b, c, d;
00108   s >> a >> b >> c >> d;
00109   p.set(a,b,c,d);
00110   return s;
00111 }
00112 
00113 #undef VGL_HOMG_PLANE_3D_INSTANTIATE
00114 #define VGL_HOMG_PLANE_3D_INSTANTIATE(T) \
00115 template class vgl_homg_plane_3d<T >; \
00116 template vcl_ostream& operator<<(vcl_ostream&, vgl_homg_plane_3d<T >const&); \
00117 template vcl_istream& operator>>(vcl_istream&, vgl_homg_plane_3d<T >&)
00118 
00119 #endif // vgl_homg_plane_3d_txx_