core/vgl/vgl_box_3d.h
Go to the documentation of this file.
00001 // This is core/vgl/vgl_box_3d.h
00002 #ifndef vgl_box_3d_h
00003 #define vgl_box_3d_h
00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00005 #pragma interface
00006 #endif
00007 //:
00008 // \file
00009 // \brief Contains class to represent a cartesian 3D bounding box.
00010 // \author Don Hamilton, Peter Tu
00011 // \date   15 Feb 2000
00012 //
00013 // \verbatim
00014 //  Modifications
00015 //   Peter Vanroose, 28 Feb 2000: lots of minor corrections
00016 //   NPC (Manchester)14 Mar 2001: Tidied up the documentation + added binary_io
00017 //   Peter Vanroose, 10 Jul 2001: Deprecated get_*() in favour of *(), and explicit casts
00018 //   Peter Vanroose,  5 Oct 2001: Added operator==() and methods is_empty() and contains()
00019 //   Peter Vanroose,  6 Oct 2001: Added method add(vgl_point_3d<T>) to enlarge a box
00020 //   Peter Vanroose,  7 Oct 2001: Removed deprecated get_*() functions
00021 //   Peter Vanroose,    Feb 2002: brief doxygen comment placed on single line
00022 //   Peter Vanroose, 12 Sep 2002: Added method add(vgl_box_3d<T>) to enlarge a box
00023 //   Peter Vanroose, 13 May 2003: Constructor interface change (compat with vgl_box_2d)
00024 //   Peter Vanroose  15 Oct 2003: Removed deprecated constructors without 5th arg
00025 //   Peter Vanroose  16 Oct 2003: Corner pts given to constructor may now be in any order
00026 //   Peter Vanroose  16 Oct 2003: Added intersect(box1,box2)
00027 //   Gamze Tunali    25 Jan 2007: Moved intersect(box1,box2) to vgl_intersection
00028 //   Peter Vanroose  30 Mar 2007: Commented out deprecated intersect() function
00029 //   Peter Vanroose  22 Jul 2009: Moved vgl_intersection() to vgl_intersection.h
00030 // \endverbatim
00031 
00032 #include <vcl_iosfwd.h>
00033 #include <vcl_vector.h>
00034 #include <vgl/vgl_fwd.h> // forward declare vgl_point_3d
00035 
00036 //: Represents a cartesian 3D box
00037 //  A 3d box with sides aligned with \a x, \a y and \a z axes. Supports operations
00038 //  required of a bounding box for geometric volume tests.
00039 //
00040 //  A box can be empty; this is what the default constructor creates, or what
00041 //  is left after applying the empty() method.  Use the add() methods to enlarge
00042 //  a box, and use the contains() methods to check for inclusion of a point or
00043 //  an other box.
00044 //
00045 //  To make the convex union of two boxes, use box1.add(box2).
00046 //  \verbatim
00047 //                                 MaxPosition
00048 //                       |<--width-->|
00049 //                       O-----------O  ---
00050 //                      /           /|   ^
00051 //                     /           / |   |
00052 //                    O-----------O  | height
00053 //                    |       o   |  |   |
00054 //                    |  centroid |  |   v
00055 //                    |           |  O  ---
00056 //     Y              |           | /   /_____depth
00057 //     |   Z          |           |/   /
00058 //     |  /           O-----------O  ---
00059 //     | /         MinPosition
00060 //     O-----X
00061 // \endverbatim
00062 // \sa vgl_box_2d
00063 
00064 template <class Type>
00065 class vgl_box_3d
00066 {
00067  public:
00068 
00069   //: Default constructor (creates empty box)
00070   vgl_box_3d();
00071 
00072   //: Construct using two corner points
00073   vgl_box_3d(Type const corner1[3],
00074              Type const corner2[3]);
00075 
00076   //: Construct using two corner points
00077   vgl_box_3d(vgl_point_3d<Type> const& corner1,
00078              vgl_point_3d<Type> const& corner2);
00079 
00080   //: Construct from ranges in \a x,y,z (take care with order of inputs).
00081   //  The \a x range is given by the 1st and 4th coordinates,
00082   //  the \a y range is given by the 2nd and 5th coordinates,
00083   //  the \a z range is given by the 3rd and 6th coordinates.
00084   vgl_box_3d(Type xmin, Type ymin, Type zmin,
00085              Type xmax, Type ymax, Type zmax);
00086 
00087   enum point_type { centre=0, min_pos, max_pos };
00088 
00089   //: Construct a box sized width x height x depth at a given reference point.
00090   //  The box will either be centered at ref_point or will have ref_point
00091   //  as its min-position or max-position, as specified by the 5th argument.
00092   vgl_box_3d(Type const ref_point[3],
00093              Type width, Type height, Type depth,
00094              point_type);
00095 
00096   //: Construct a box sized width x height x depth at a given reference point.
00097   //  The box will either be centered at ref_point or will have ref_point
00098   //  as its min-position or max-position, as specified by the 5th argument.
00099   vgl_box_3d(vgl_point_3d<Type> const& ref_point,
00100              Type width, Type height, Type depth,
00101              point_type);
00102 
00103   //: Equality test
00104   inline bool operator==(vgl_box_3d<Type> const& b) const {
00105     // All empty boxes are equal:
00106     if (b.is_empty()) return is_empty();
00107     return min_x() == b.min_x() && min_y() == b.min_y() && min_z() == b.min_z()
00108         && max_x() == b.max_x() && max_y() == b.max_y() && max_z() == b.max_z();
00109   }
00110 
00111   // Data Access---------------------------------------------------------------
00112 
00113   //: Get width of this box (= \a x dimension)
00114   Type width() const;
00115   //: Get height of this box (= \a y dimension)
00116   Type height() const;
00117   //: Get depth of this box (= \a z dimension)
00118   Type depth() const;
00119 
00120   //: Get volume of this box
00121   inline Type volume() const { return width()*height()*depth(); }
00122 
00123   //: Get min \a x
00124   inline Type min_x() const { return min_pos_[0]; }
00125   //: Get min \a y
00126   inline Type min_y() const { return min_pos_[1]; }
00127   //: Get min \a z
00128   inline Type min_z() const { return min_pos_[2]; }
00129 
00130   //: Get max \a x
00131   inline Type max_x() const { return max_pos_[0]; }
00132   //: Get max \a y
00133   inline Type max_y() const { return max_pos_[1]; }
00134   //: Get max \a z
00135   inline Type max_z() const { return max_pos_[2]; }
00136 
00137   //: Get the centroid point
00138   vgl_point_3d<Type> centroid() const;
00139   //: Get \a x component of centroid
00140   Type centroid_x() const;
00141   //: Get \a y component of centroid
00142   Type centroid_y() const;
00143   //: Get \a z component of centroid
00144   Type centroid_z() const;
00145 
00146   //: Return lower left corner of box
00147   vgl_point_3d<Type> min_point() const;
00148 
00149   //: Return upper right corner of box
00150   vgl_point_3d<Type> max_point() const;
00151   
00152   //: Return the 8 vertices of the box
00153   vcl_vector<vgl_point_3d<Type> > vertices() const;
00154 
00155   // Data Control--------------------------------------------------------------
00156 
00157   //: Return true if this box is empty
00158   inline bool is_empty() const {
00159     return min_x() > max_x() || min_y() > max_y() || min_z() > max_z();
00160   }
00161 
00162   //: Add a point to this box.
00163   // Do this by possibly enlarging the box so that the point just falls within the box.
00164   // Adding a point to an empty box makes it a size zero box only containing p.
00165   void add(vgl_point_3d<Type> const& p);
00166 
00167   //: Make the convex union of two boxes.
00168   // Do this by possibly enlarging this box so that the corner points of the
00169   // given box just fall within the box.
00170   // Adding an empty box does not change the current box.
00171   void add(vgl_box_3d<Type> const& b);
00172 
00173   //: Return true iff the point p is inside this box
00174   bool contains(vgl_point_3d<Type> const& p) const;
00175 
00176   //: Return true iff the corner points of b are inside this box
00177   bool contains(vgl_box_3d<Type> const& b) const;
00178 
00179   //: Return true if \a (x,y,z) is inside this box, ie \a x_min <= \a x <= \a x_max etc
00180   inline bool contains(Type const& x, Type const& y, Type const& z) const {
00181     return x >= min_x() && x <= max_x() &&
00182            y >= min_y() && y <= max_y() &&
00183            z >= min_z() && z <= max_z();
00184   }
00185 
00186   //: Make the box empty
00187   void empty();
00188 
00189   //: Set min \a x ordinate of box (other sides unchanged)
00190   inline void set_min_x(Type m) { min_pos_[0]=m; }
00191   //: Set min \a y ordinate of box (other sides unchanged)
00192   inline void set_min_y(Type m) { min_pos_[1]=m; }
00193   //: Set min \a z ordinate of box (other sides unchanged)
00194   inline void set_min_z(Type m) { min_pos_[2]=m; }
00195 
00196   //: Set max \a x ordinate of box (other sides unchanged)
00197   inline void set_max_x(Type m) { max_pos_[0]=m; }
00198   //: Set max \a y ordinate of box (other sides unchanged)
00199   inline void set_max_y(Type m) { max_pos_[1]=m; }
00200   //: Set max \a z ordinate of box (other sides unchanged)
00201   inline void set_max_z(Type m) { max_pos_[2]=m; }
00202 
00203   //: Move box so centroid lies at cx (size unchanged)
00204   void set_centroid_x(Type cx);
00205   //: Move box so centroid lies at cy (size unchanged)
00206   void set_centroid_y(Type cy);
00207   //: Move box so centroid lies at cz (size unchanged)
00208   void set_centroid_z(Type cz);
00209 
00210   //: Set width (x), centroid unchanged
00211   void set_width(Type width);
00212   //: Set height (y), centroid unchanged
00213   void set_height(Type height);
00214   //: Set depth (z), centroid unchanged
00215   void set_depth(Type depth);
00216 
00217 
00218   //: Add to width and height, centroid unchanged.
00219   // Will move each side by \p expand / 2.
00220   void expand_about_centroid(Type expand);
00221   //: Scale width, height and depth, centroid unchanged.
00222   void scale_about_centroid(double s);
00223   //: Scale width, height and depth, keeping scaled position of origin unchanged.
00224   void scale_about_origin(double s);
00225 
00226   //: Modify min corner point. Max corner point only changed if necessary to avoid empty box
00227   void set_min_position(Type const m[3]);
00228   //: Modify max corner point. Min corner point only changed if necessary to avoid empty box
00229   void set_max_position(Type const m[3]);
00230   //: Modify min corner point. Max corner point only changed if necessary to avoid empty box
00231   void set_min_point(vgl_point_3d<Type> const& min_pt);
00232   //: Modify max corner point. Min corner point only changed if necessary to avoid empty box
00233   void set_max_point(vgl_point_3d<Type> const& max_pt);
00234   //: Move box so centroid lies at c (size unchanged)
00235   inline void set_centroid(Type const c[3]) { set_centroid_x(c[0]); set_centroid_y(c[1]); set_centroid_z(c[2]); }
00236   //: Move box so centroid lies at c (size unchanged)
00237   inline void set_centroid(vgl_point_3d<Type> const& c) { set_centroid_x(c.x()); set_centroid_y(c.y()); set_centroid_z(c.z()); }
00238 
00239   // I/O-----------------------------------------------------------------------
00240 
00241   //: Write "<vgl_box_3d x0,y0,z0 to x1,y1,z1>" to stream
00242   vcl_ostream& print(vcl_ostream&) const;
00243 
00244   //: Write "x0 y0 z0 x1 y1 z1(endl)" to stream
00245   vcl_ostream& write(vcl_ostream&) const;
00246 
00247   //: Read x0,y0,z0,x1,y1,z1 from stream
00248   vcl_istream& read(vcl_istream&);
00249 
00250   // INTERNALS-----------------------------------------------------------------
00251  protected:
00252   // Data Members--------------------------------------------------------------
00253   Type min_pos_[3];
00254   Type max_pos_[3];
00255 };
00256 
00257 //: Write box to stream
00258 // \relatesalso vgl_box_3d
00259 template <class Type>
00260 vcl_ostream&  operator<<(vcl_ostream& s, vgl_box_3d<Type> const& p);
00261 
00262 //: Read box from stream
00263 // \relatesalso vgl_box_3d
00264 template <class Type>
00265 vcl_istream&  operator>>(vcl_istream& is,  vgl_box_3d<Type>& p);
00266 
00267 //: Calculate the bounding box of a sequence of points or boxes.
00268 template <class T, class ITER>
00269 void vgl_box_3d_bounds(ITER begin, ITER end, vgl_box_3d<T>& bounding_box)
00270 {
00271   for (; begin != end; ++begin)
00272     bounding_box.add(*begin);
00273 }
00274 
00275 #define VGL_BOX_3D_INSTANTIATE(T) extern "please include vgl/vgl_box_3d.txx first"
00276 
00277 #endif // vgl_box_3d_h