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