core/vgl/vgl_box_3d.txx
Go to the documentation of this file.
00001 // This is core/vgl/vgl_box_3d.txx
00002 #ifndef vgl_box_3d_txx_
00003 #define vgl_box_3d_txx_
00004 //:
00005 // \file
00006 
00007 #include "vgl_box_3d.h"
00008 #include <vgl/vgl_point_3d.h>
00009 #include <vcl_iostream.h>
00010 #include <vcl_algorithm.h>
00011 #include <vcl_cassert.h>
00012 #include <vcl_cmath.h>
00013 
00014 // Constructors/Destructor---------------------------------------------------
00015 
00016 template <class Type>
00017 vgl_box_3d<Type>::vgl_box_3d()
00018 {
00019   min_pos_[0]=min_pos_[1]=min_pos_[2]=(Type)1;
00020   max_pos_[0]=max_pos_[1]=max_pos_[2]=(Type)0; // empty box
00021 }
00022 
00023 template <class Type>
00024 vgl_box_3d<Type>::vgl_box_3d(Type const corner1[3],
00025                              Type const corner2[3])
00026 {
00027   min_pos_[0]=max_pos_[0]=corner1[0];
00028   min_pos_[1]=max_pos_[1]=corner1[1];
00029   min_pos_[2]=max_pos_[2]=corner1[2];
00030   this->add(corner2);
00031 }
00032 
00033 template <class Type>
00034 vgl_box_3d<Type>::vgl_box_3d(vgl_point_3d<Type> const& corner1,
00035                              vgl_point_3d<Type> const& corner2)
00036 {
00037   min_pos_[0]=max_pos_[0]=corner1.x();
00038   min_pos_[1]=max_pos_[1]=corner1.y();
00039   min_pos_[2]=max_pos_[2]=corner1.z();
00040   this->add(corner2);
00041 }
00042 
00043 template <class Type>
00044 vgl_box_3d<Type>::vgl_box_3d(Type xmin, Type ymin, Type zmin,
00045                              Type xmax, Type ymax, Type zmax)
00046 {
00047   min_pos_[0]=max_pos_[0]=xmin;
00048   min_pos_[1]=max_pos_[1]=ymin;
00049   min_pos_[2]=max_pos_[2]=zmin;
00050   this->add(vgl_point_3d<Type>(xmax,ymax,zmax));
00051   if (xmin > xmax || ymin > ymax || zmin > zmax) this->empty();
00052 }
00053 
00054 template <class Type>
00055 vgl_box_3d<Type>::vgl_box_3d(Type const ref_point[3],
00056                              Type w, Type h, Type d,
00057                              typename vgl_box_3d<Type>::point_type t)
00058 {
00059   if (t == vgl_box_3d<Type>::centre)
00060   {
00061     min_pos_[0]=Type(ref_point[0]-0.5*w);
00062     min_pos_[1]=Type(ref_point[1]-0.5*h);
00063     min_pos_[2]=Type(ref_point[2]-0.5*d);
00064     max_pos_[0]=Type(ref_point[0]+0.5*w);
00065     max_pos_[1]=Type(ref_point[1]+0.5*h);
00066     max_pos_[2]=Type(ref_point[2]+0.5*d);
00067   }
00068   else if (t == vgl_box_3d<Type>::min_pos)
00069   {
00070     min_pos_[0]=ref_point[0];
00071     min_pos_[1]=ref_point[1];
00072     min_pos_[2]=ref_point[2];
00073     max_pos_[0]=ref_point[0]+w;
00074     max_pos_[1]=ref_point[1]+h;
00075     max_pos_[2]=ref_point[2]+d;
00076   }
00077   else if (t == vgl_box_3d<Type>::max_pos)
00078   {
00079     min_pos_[0]=ref_point[0]-w;
00080     min_pos_[1]=ref_point[1]-h;
00081     min_pos_[2]=ref_point[2]-d;
00082     max_pos_[0]=ref_point[0];
00083     max_pos_[1]=ref_point[1];
00084     max_pos_[2]=ref_point[2];
00085   }
00086   else
00087     assert(!"point_type should be one of: centre, min_pos, max_pos");
00088 }
00089 
00090 template <class Type>
00091 vgl_box_3d<Type>::vgl_box_3d(vgl_point_3d<Type> const& ref_point,
00092                              Type w, Type h, Type d,
00093                              typename vgl_box_3d<Type>::point_type t)
00094 {
00095   if (t == vgl_box_3d<Type>::centre)
00096   {
00097     min_pos_[0]=Type(ref_point.x()-0.5*w);
00098     min_pos_[1]=Type(ref_point.y()-0.5*h);
00099     min_pos_[2]=Type(ref_point.z()-0.5*d);
00100     max_pos_[0]=Type(ref_point.x()+0.5*w);
00101     max_pos_[1]=Type(ref_point.y()+0.5*h);
00102     max_pos_[2]=Type(ref_point.z()+0.5*d);
00103   }
00104   else if (t == vgl_box_3d<Type>::min_pos)
00105   {
00106     min_pos_[0]=ref_point.x();
00107     min_pos_[1]=ref_point.y();
00108     min_pos_[2]=ref_point.z();
00109     max_pos_[0]=ref_point.x()+w;
00110     max_pos_[1]=ref_point.y()+h;
00111     max_pos_[2]=ref_point.z()+d;
00112   }
00113   else if (t == vgl_box_3d<Type>::max_pos)
00114   {
00115     min_pos_[0]=ref_point.x()-w;
00116     min_pos_[1]=ref_point.y()-h;
00117     min_pos_[2]=ref_point.z()-d;
00118     max_pos_[0]=ref_point.x();
00119     max_pos_[1]=ref_point.y();
00120     max_pos_[2]=ref_point.z();
00121   }
00122   else
00123     assert(!"point_type should be one of: centre, min_pos, max_pos");
00124 }
00125 
00126 template <class Type>
00127 Type vgl_box_3d<Type>::width() const
00128 {
00129   return (max_pos_[0] > min_pos_[0]) ? max_pos_[0] - min_pos_[0] : 0;
00130 }
00131 
00132 template <class Type>
00133 Type vgl_box_3d<Type>::height() const
00134 {
00135   return (max_pos_[1] > min_pos_[1]) ? max_pos_[1] - min_pos_[1] : 0;
00136 }
00137 
00138 template <class Type>
00139 Type vgl_box_3d<Type>::depth() const
00140 {
00141   return (max_pos_[2] > min_pos_[2]) ? max_pos_[2] - min_pos_[2] : 0;
00142 }
00143 
00144 template <class Type>
00145 vgl_point_3d<Type> vgl_box_3d<Type>::centroid() const
00146 {
00147   return vgl_point_3d<Type>(centroid_x(),centroid_y(),centroid_z());
00148 }
00149 
00150 template <class Type>
00151 Type vgl_box_3d<Type>::centroid_x() const
00152 {
00153   assert(!is_empty());
00154   return Type(0.5*(min_pos_[0]+max_pos_[0]));
00155 }
00156 
00157 template <class Type>
00158 Type vgl_box_3d<Type>::centroid_y() const
00159 {
00160   assert(!is_empty());
00161   return Type(0.5*(min_pos_[1]+max_pos_[1]));
00162 }
00163 
00164 template <class Type>
00165 Type vgl_box_3d<Type>::centroid_z() const
00166 {
00167   assert(!is_empty());
00168   return Type(0.5*(min_pos_[2]+max_pos_[2]));
00169 }
00170 
00171 template <class Type>
00172 void vgl_box_3d<Type>::set_centroid_x(Type cx)
00173 {
00174   assert(!is_empty());
00175   Type delta = cx - centroid_x();
00176   min_pos_[0]= min_pos_[0] + delta;
00177   max_pos_[0]= max_pos_[0] + delta;
00178 }
00179 
00180 template <class Type>
00181 void vgl_box_3d<Type>::set_centroid_y(Type cy)
00182 {
00183   assert(!is_empty());
00184   Type delta = cy - centroid_y();
00185   min_pos_[1]= min_pos_[1] + delta;
00186   max_pos_[1]= max_pos_[1] + delta;
00187 }
00188 
00189 template <class Type>
00190 void vgl_box_3d<Type>::set_centroid_z(Type cz)
00191 {
00192   assert(!is_empty());
00193   Type delta = cz - centroid_z();
00194   min_pos_[2]= min_pos_[2] + delta;
00195   max_pos_[2]= max_pos_[2] + delta;
00196 }
00197 
00198 template <class T>
00199 inline void set_dim_3d(T& minv, T& maxv, T spread);
00200 
00201 // All this code is to avoid drift in the centroid.
00202 VCL_DEFINE_SPECIALIZATION
00203 inline void set_dim_3d(int& minv, int& maxv, int spread)
00204 {
00205   int sum = minv + maxv;
00206   sum = sum | (spread&1); // if width is odd, then make sum odd
00207   minv = int(vcl_floor((sum-spread)/2.0));
00208   maxv = minv+spread;
00209 }
00210 
00211 template <class T>
00212 inline void set_dim_3d(T& minv, T& maxv, T spread)
00213 {
00214   T x = minv + maxv;
00215   minv = T( (x-spread)*0.5 );
00216   maxv = minv + spread;
00217 }
00218 
00219 template <class Type>
00220 void vgl_box_3d<Type>::set_width(Type w)
00221 {
00222   assert(!is_empty());
00223   set_dim_3d(min_pos_[0], max_pos_[0], w);
00224 }
00225 
00226 template <class Type>
00227 void vgl_box_3d<Type>::set_height(Type h)
00228 {
00229   assert(!is_empty());
00230   set_dim_3d(min_pos_[1], max_pos_[1], h);
00231 }
00232 
00233 template <class Type>
00234 void vgl_box_3d<Type>::set_depth(Type d)
00235 {
00236   assert(!is_empty());
00237   set_dim_3d(min_pos_[2], max_pos_[2], d);
00238 }
00239 
00240 //: Add to width and height, centroid unchanged.
00241 // Will move each side by \p expand / 2.
00242 template <class Type>
00243 void vgl_box_3d<Type>::expand_about_centroid(Type expand)
00244 {
00245   assert(!is_empty());
00246   set_dim_3d(min_pos_[0], max_pos_[0], width() + expand );
00247   set_dim_3d(min_pos_[1], max_pos_[1], height() + expand );
00248   set_dim_3d(min_pos_[2], max_pos_[2], depth() + expand );
00249 }
00250 
00251 //: Scale width, height and depth, centroid unchanged.
00252 template <class Type>
00253 void vgl_box_3d<Type>::scale_about_centroid(double s)
00254 {
00255   assert(!is_empty());
00256   set_dim_3d(min_pos_[0], max_pos_[0], static_cast<Type>(width()*s));
00257   set_dim_3d(min_pos_[1], max_pos_[1], static_cast<Type>(height()*s));
00258   set_dim_3d(min_pos_[2], max_pos_[2], static_cast<Type>(depth()*s));
00259 }
00260 
00261 //: Scale width, height and depth, keeping scaled position of origin unchanged.
00262 template <class Type>
00263 void vgl_box_3d<Type>::scale_about_origin(double s)
00264 {
00265   min_pos_[0] = static_cast<Type>(min_pos_[0] * s);
00266   min_pos_[1] = static_cast<Type>(min_pos_[1] * s);
00267   min_pos_[2] = static_cast<Type>(min_pos_[2] * s);
00268   max_pos_[0] = static_cast<Type>(max_pos_[0] * s);
00269   max_pos_[1] = static_cast<Type>(max_pos_[1] * s);
00270   max_pos_[2] = static_cast<Type>(max_pos_[2] * s);
00271 }
00272 
00273 template <class Type>
00274 void vgl_box_3d<Type>::set_min_position(Type const min_position[3])
00275 {
00276   min_pos_[0]=min_position[0];
00277   min_pos_[1]=min_position[1];
00278   min_pos_[2]=min_position[2];
00279   if (max_pos_[0] < min_pos_[0]) max_pos_[0]=min_pos_[0];
00280   if (max_pos_[1] < min_pos_[1]) max_pos_[1]=min_pos_[1];
00281   if (max_pos_[2] < min_pos_[2]) max_pos_[2]=min_pos_[2];
00282 }
00283 
00284 template <class Type>
00285 void vgl_box_3d<Type>::set_max_position(Type const max_position[3])
00286 {
00287   max_pos_[0]=max_position[0];
00288   max_pos_[1]=max_position[1];
00289   max_pos_[2]=max_position[2];
00290   if (max_pos_[0] < min_pos_[0]) min_pos_[0]=max_pos_[0];
00291   if (max_pos_[1] < min_pos_[1]) min_pos_[1]=max_pos_[1];
00292   if (max_pos_[2] < min_pos_[2]) min_pos_[2]=max_pos_[2];
00293 }
00294 
00295 template <class Type>
00296 void vgl_box_3d<Type>::set_min_point(vgl_point_3d<Type> const& min_pt)
00297 {
00298   min_pos_[0]=min_pt.x(); if (max_pos_[0]<min_pos_[0]) max_pos_[0]=min_pos_[0];
00299   min_pos_[1]=min_pt.y(); if (max_pos_[1]<min_pos_[1]) max_pos_[1]=min_pos_[1];
00300   min_pos_[2]=min_pt.z(); if (max_pos_[2]<min_pos_[2]) max_pos_[2]=min_pos_[2];
00301 }
00302 
00303 template <class Type>
00304 void vgl_box_3d<Type>::set_max_point(vgl_point_3d<Type> const& max_pt)
00305 {
00306   max_pos_[0]=max_pt.x(); if (max_pos_[0]<min_pos_[0]) min_pos_[0]=max_pos_[0];
00307   max_pos_[1]=max_pt.y(); if (max_pos_[1]<min_pos_[1]) min_pos_[1]=max_pos_[1];
00308   max_pos_[2]=max_pt.z(); if (max_pos_[2]<min_pos_[2]) min_pos_[2]=max_pos_[2];
00309 }
00310 
00311 template <class Type>
00312 vcl_ostream& vgl_box_3d<Type>::print(vcl_ostream& s) const
00313 {
00314   if (is_empty())
00315     return s << "<vgl_box_3d (empty)>";
00316   else
00317     return s<< "<vgl_box_3d "
00318             << min_pos_[0] << ',' << min_pos_[1] << ',' << min_pos_[2] << " to "
00319             << max_pos_[0] << ',' << max_pos_[1] << ',' << max_pos_[2] << '>';
00320 }
00321 
00322 template <class Type>
00323 vgl_point_3d<Type> vgl_box_3d<Type>::min_point() const
00324 {
00325   assert(!is_empty());
00326   return vgl_point_3d<Type>(min_pos_[0],min_pos_[1],min_pos_[2]);
00327 }
00328 
00329 template <class Type>
00330 vgl_point_3d<Type> vgl_box_3d<Type>::max_point() const
00331 {
00332   assert(!is_empty());
00333   return vgl_point_3d<Type>(max_pos_[0],max_pos_[1],max_pos_[2]);
00334 }
00335 
00336 template <class Type>
00337 vcl_vector<vgl_point_3d<Type> > vgl_box_3d<Type>::vertices() const
00338 {
00339   assert(!is_empty());
00340   vcl_vector<vgl_point_3d<Type> > vertices;
00341   vertices.push_back(vgl_point_3d<Type>(min_pos_[0], min_pos_[1], min_pos_[2]));
00342   vertices.push_back(vgl_point_3d<Type>(max_pos_[0], min_pos_[1], min_pos_[2]));
00343   vertices.push_back(vgl_point_3d<Type>(max_pos_[0], max_pos_[1], min_pos_[2]));
00344   vertices.push_back(vgl_point_3d<Type>(min_pos_[0], max_pos_[1], min_pos_[2]));
00345   vertices.push_back(vgl_point_3d<Type>(min_pos_[0], min_pos_[1], max_pos_[2]));
00346   vertices.push_back(vgl_point_3d<Type>(max_pos_[0], min_pos_[1], max_pos_[2]));
00347   vertices.push_back(vgl_point_3d<Type>(max_pos_[0], max_pos_[1], max_pos_[2]));
00348   vertices.push_back(vgl_point_3d<Type>(min_pos_[0], max_pos_[1], max_pos_[2]));
00349   return vertices;
00350 }
00351 
00352 template <class Type>
00353 vcl_ostream& vgl_box_3d<Type>::write(vcl_ostream& s) const
00354 {
00355   return s << min_pos_[0] << ' ' << min_pos_[1] << ' ' << min_pos_[2] << ' '
00356            << max_pos_[0] << ' ' << max_pos_[1] << ' ' << max_pos_[2] << '\n';
00357 }
00358 
00359 template <class Type>
00360 vcl_istream& vgl_box_3d<Type>::read(vcl_istream& s)
00361 {
00362   return s >> min_pos_[0] >> min_pos_[1] >> min_pos_[2]
00363            >> max_pos_[0] >> max_pos_[1] >> max_pos_[2];
00364 }
00365 
00366 //: Add a point to this box.
00367 // Do this by possibly enlarging the box so that the point just falls within the box.
00368 // Adding a point to an empty box makes it a size zero box only containing p.
00369 template <class Type>
00370 void vgl_box_3d<Type>::add(vgl_point_3d<Type> const& p)
00371 {
00372   if (is_empty())
00373   {
00374     min_pos_[0] = max_pos_[0] = p.x();
00375     min_pos_[1] = max_pos_[1] = p.y();
00376     min_pos_[2] = max_pos_[2] = p.z();
00377   }
00378   else
00379   {
00380     if (p.x() > max_pos_[0]) max_pos_[0] = p.x();
00381     if (p.x() < min_pos_[0]) min_pos_[0] = p.x();
00382     if (p.y() > max_pos_[1]) max_pos_[1] = p.y();
00383     if (p.y() < min_pos_[1]) min_pos_[1] = p.y();
00384     if (p.z() > max_pos_[2]) max_pos_[2] = p.z();
00385     if (p.z() < min_pos_[2]) min_pos_[2] = p.z();
00386   }
00387 }
00388 
00389 //: Make the convex union of two boxes
00390 // Do this by possibly enlarging this box so that the corner points of the
00391 // given box just fall within the box.
00392 // Adding an empty box does not change the current box.
00393 template <class Type>
00394 void vgl_box_3d<Type>::add(vgl_box_3d<Type> const& b)
00395 {
00396   if (b.is_empty()) return;
00397   add(b.min_point());
00398   add(b.max_point());
00399 }
00400 
00401 //: Return true iff the point p is inside this box
00402 template <class Type>
00403 bool vgl_box_3d<Type>::contains(vgl_point_3d<Type> const& p) const
00404 {
00405     return contains(p.x(), p.y(), p.z());
00406 }
00407 
00408 //: Return true iff the corner points of b are inside this box
00409 template <class Type>
00410 bool vgl_box_3d<Type>::contains(vgl_box_3d<Type> const& b) const
00411 {
00412   return
00413     contains(b.min_x(), b.min_y(), b.min_z()) &&
00414     contains(b.max_x(), b.max_y(), b.max_z());
00415 }
00416 
00417 //: Make the box empty
00418 template <class Type>
00419 void vgl_box_3d<Type>::empty()
00420 {
00421   min_pos_[0]=min_pos_[1]=min_pos_[2]=(Type)1;
00422   max_pos_[0]=max_pos_[1]=max_pos_[2]=(Type)0;
00423 }
00424 
00425 //: Write box to stream
00426 template <class Type>
00427 vcl_ostream&  operator<<(vcl_ostream& s, vgl_box_3d<Type> const& p)
00428 {
00429   return p.print(s);
00430 }
00431 
00432 //: Read box from stream
00433 template <class Type>
00434 vcl_istream&  operator>>(vcl_istream& is,  vgl_box_3d<Type>& p)
00435 {
00436   return p.read(is);
00437 }
00438 
00439 #undef VGL_BOX_3D_INSTANTIATE
00440 #define VGL_BOX_3D_INSTANTIATE(Type) \
00441 template class vgl_box_3d<Type >;\
00442 template vcl_ostream& operator<<(vcl_ostream&, vgl_box_3d<Type > const& p);\
00443 template vcl_istream& operator>>(vcl_istream&, vgl_box_3d<Type >& p)
00444 
00445 #endif // vgl_box_3d_txx_