core/vgl/algo/vgl_orient_box_3d.txx
Go to the documentation of this file.
00001 // This is core/vgl/algo/vgl_orient_box_3d.txx
00002 #ifndef vgl_orient_box_3d_txx_
00003 #define vgl_orient_box_3d_txx_
00004 //:
00005 // \file
00006 
00007 #include "vgl_orient_box_3d.h"
00008 #include <vgl/vgl_vector_3d.h>
00009 #include <vnl/vnl_det.h>
00010 #include <vcl_iostream.h>
00011 
00012 template <class Type>
00013 vgl_orient_box_3d<Type>::vgl_orient_box_3d(vgl_box_3d<Type> box)
00014 : box_(box)
00015 {
00016   vnl_vector_fixed<double,3> axis;
00017   axis[0] = 0.0; axis[1] = 0.0; axis[2]=1.0;
00018   double angle = 0.0;
00019 
00020   orient_ = vnl_quaternion<double> (axis, angle);
00021 }
00022 
00023 template <class Type>
00024 vgl_orient_box_3d<Type>::vgl_orient_box_3d(vgl_box_3d<Type> box, vnl_quaternion<double> orient)
00025 : box_(box), orient_(orient)
00026 {
00027 }
00028 
00029 //: constructor from four corner points.
00030 //  The three directions from the first of these to the three other points must be mutually orthogonal.
00031 template <class Type>
00032 vgl_orient_box_3d<Type>::vgl_orient_box_3d(vgl_point_3d<Type> const& p0,
00033                                            vgl_point_3d<Type> const& px,
00034                                            vgl_point_3d<Type> const& py,
00035                                            vgl_point_3d<Type> const& pz)
00036 {
00037   // The normalized main axes of the box:
00038   vgl_vector_3d<Type> vx = px - p0, vy = py - p0, vz = pz - p0;
00039   double lx = vx.length(), ly = vy.length(), lz = vz.length();
00040   // the quaternion rotation matrix:
00041   vnl_matrix_fixed<double,3,3> rotation;
00042   // first row: coordinates of first orthonormal basis vector (etc):
00043   rotation(0,0) = vx.x()/lx; rotation(0,1) = vx.y()/lx; rotation(0,2) = vx.z()/lx;
00044   rotation(1,0) = vy.x()/ly; rotation(1,1) = vy.y()/ly; rotation(1,2) = vy.z()/ly;
00045   rotation(2,0) = vz.x()/lz; rotation(2,1) = vz.y()/lz; rotation(2,2) = vz.z()/lz;
00046   // If the transformation matrix has negative determinant, invert px and py:
00047   double det = vnl_det(rotation);
00048   if (det < 0) {
00049     double t = rotation(0,0); rotation(0,0) = rotation(1,0); rotation(1,0) = t;
00050            t = rotation(0,1); rotation(0,1) = rotation(1,1); rotation(1,1) = t;
00051            t = rotation(0,2); rotation(0,2) = rotation(1,2); rotation(1,2) = t;
00052   }
00053   orient_ = vnl_quaternion<double>(rotation);
00054 
00055   // And finally the vgl_box_3d: it is the inversely rotated version of the given 4 points around the centroid:
00056   vnl_vector_fixed<double,3> centroid(-0.5*p0.x()+0.5*px.x()+0.5*py.x()+0.5*pz.x(),
00057                                       -0.5*p0.y()+0.5*px.y()+0.5*py.y()+0.5*pz.y(),
00058                                       -0.5*p0.z()+0.5*px.z()+0.5*py.z()+0.5*pz.z());
00059   vnl_vector_fixed<double,3> p0_to_centroid = vnl_vector_fixed<double,3>(p0.x(),p0.y(),p0.z()) - centroid;
00060   vnl_vector_fixed<double,3> corner_0 = centroid + rotation * p0_to_centroid;
00061   vgl_point_3d<Type> corner0(corner_0[0], corner_0[1], corner_0[2]);
00062   vnl_vector_fixed<double,3> corner_1 = centroid - rotation * p0_to_centroid;
00063   vgl_point_3d<Type> corner1(corner_1[0], corner_1[1], corner_1[2]);
00064   box_ = vgl_box_3d<Type>(corner0, corner1);
00065 }
00066 
00067 //: returns the 8 corner points of the box
00068 template <class Type>
00069 vcl_vector<vgl_point_3d<Type> > vgl_orient_box_3d<Type>::corners()
00070 {
00071   vcl_vector<vgl_point_3d<Type> > corner_points(8);
00072 
00073   //get the min and max of the aab and find the other corners
00074   corner_points[0] = box_.min_point();
00075   corner_points[7] = box_.max_point();
00076 
00077   corner_points[1] = vgl_point_3d<Type> (corner_points[0].x()+width(),
00078                                          corner_points[0].y(),
00079                                          corner_points[0].z());
00080   corner_points[2] = vgl_point_3d<Type> (corner_points[0].x(),
00081                                          corner_points[0].y(),
00082                                          corner_points[0].z()+depth());
00083   corner_points[3] = vgl_point_3d<Type> (corner_points[1].x(),
00084                                          corner_points[1].y(),
00085                                          corner_points[1].z()+depth());
00086   corner_points[4] = vgl_point_3d<Type> (corner_points[0].x(),
00087                                          corner_points[0].y()+height(),
00088                                          corner_points[0].z());
00089   corner_points[5] = vgl_point_3d<Type> (corner_points[1].x(),
00090                                          corner_points[1].y()+height(),
00091                                          corner_points[1].z());
00092   corner_points[6] = vgl_point_3d<Type> (corner_points[2].x(),
00093                                          corner_points[2].y()+height(),
00094                                          corner_points[2].z());
00095   // rotate the corner points
00096   for (unsigned int i=0; i < corner_points.size(); i++) {
00097     vnl_vector_fixed<double,3> p;
00098     p[0] = corner_points[i].x() - box_.centroid_x();
00099     p[1] = corner_points[i].y() - box_.centroid_y();
00100     p[2] = corner_points[i].z() - box_.centroid_z();
00101     p = orient_.rotate(p);
00102     corner_points[i] = vgl_point_3d<Type> (Type(p[0]) + box_.centroid_x(),
00103                                            Type(p[1]) + box_.centroid_y(),
00104                                            Type(p[2]) + box_.centroid_z());
00105   }
00106   return corner_points;
00107 }
00108 
00109 //: Return true if \a (x,y,z) is inside this box
00110 template <class Type>
00111 bool vgl_orient_box_3d<Type>::contains(Type const& x,
00112                                        Type const& y,
00113                                        Type const& z) const
00114 {
00115   // first transform the point to the coordinate system of AABB
00116   vnl_quaternion<double> reverse_rot = orient_.inverse();
00117 
00118   vnl_vector_fixed<double,3> p;
00119   p[0] = x - box_.centroid_x();
00120   p[1] = y - box_.centroid_y();
00121   p[2] = z - box_.centroid_z();
00122   p = reverse_rot.rotate(p);
00123   Type xt = static_cast<Type>(p[0] + box_.centroid_x());
00124   Type yt = static_cast<Type>(p[1] + box_.centroid_y());
00125   Type zt = static_cast<Type>(p[2] + box_.centroid_z());
00126   return box_.contains(xt, yt, zt);
00127 }
00128 
00129 template <class Type>
00130 vcl_ostream& vgl_orient_box_3d<Type>::print(vcl_ostream& s) const
00131 {
00132   return s <<  "<vgl_orient_box_3d " << box_ << " dir=" << orient_  << '>' << vcl_endl;
00133 }
00134 
00135 template <class Type>
00136 vcl_istream& vgl_orient_box_3d<Type>::read(vcl_istream& s)
00137 {
00138   return s >> box_ >> orient_ ;
00139 }
00140 
00141 //: Write box to stream
00142 template <class Type>
00143 vcl_ostream&  operator<<(vcl_ostream& s, vgl_orient_box_3d<Type> const& p)
00144 {
00145   return p.print(s);
00146 }
00147 
00148 //: Read box from stream
00149 template <class Type>
00150 vcl_istream&  operator>>(vcl_istream& is,  vgl_orient_box_3d<Type>& p)
00151 {
00152   return p.read(is);
00153 }
00154 
00155 #undef VGL_ORIENT_BOX_3D_INSTANTIATE
00156 #define VGL_ORIENT_BOX_3D_INSTANTIATE(T) \
00157 template class vgl_orient_box_3d<T >;\
00158 template vcl_ostream& operator<<(vcl_ostream&, vgl_orient_box_3d<T > const& p);\
00159 template vcl_istream& operator>>(vcl_istream&, vgl_orient_box_3d<T >& p)
00160 
00161 #endif // vgl_orient_box_3d_txx_