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