1 // This is core/vgl/vgl_box_2d.h
2 #ifndef vgl_box_2d_h
3 #define vgl_box_2d_h
4 //:
5 // \file
6 // \brief Contains class to represent a cartesian 2D bounding box.
7 // \author Don Hamilton, Peter Tu
8 // \date   15 Feb 2000
9 //
10 // \verbatim
11 //  Modifications
12 //   IMS (Manchester)14 Mar 2001: Tidied up the documentation + added binary_io
13 //   Amitha Perera   10 Jul 2001: Deprecated get_*() in favour of *(), as agreed in Zurich.
14 //   Peter Vanroose   5 Oct 2001: Added operator==() and is_empty()
15 //   Peter Vanroose   6 Oct 2001: Added method add(vgl_point_2d<T>) to enlarge a box
16 //   Peter Vanroose   7 Oct 2001: Removed deprecated get_*() functions
17 //   Peter Vanroose     Feb 2002: brief doxygen comment placed on single line
18 //   Peter Vanroose  12 Sep 2002: Added method add(vgl_box_2d<T>) to enlarge a box
19 //   Peter Vanroose  22 Apr 2003: Interface change (centroid constructor): now in correspondence with vgl_box_3d<T>
20 //   Peter Vanroose  13 May 2003: Constructor interface change (backward compat)
21 //   Peter Vanroose  15 Oct 2003: Removed deprecated constructors without 4th arg
22 //   Peter Vanroose  16 Oct 2003: Corner pts given to constructor may now be in any order
23 //   Gamze Tunali    25 Jan 2007: Moved intersect(box1,box2) to vgl_intersection
24 //   Peter Vanroose  30 Mar 2007: Commented out deprecated intersect() function
25 //   Peter Vanroose  22 Jul 2009: Moved vgl_intersection() to vgl_intersection.h
26 // \endverbatim
27 
28 #include <iosfwd>
29 #ifdef _MSC_VER
30 #  include <vcl_msvc_warnings.h>
31 #endif
32 #include "vgl_fwd.h" // forward declare vgl_point_2d
33 
34 //: Represents a cartesian 2D box
35 //  A 2d box with sides aligned with the \a x and \a y axes.
36 //  Also supports operations required of a bounding box for geometric region
37 //  tests.
38 //
39 //  A box can be empty; this is what the default constructor creates, or what
40 //  is left after applying the empty() method.  Use the add() methods to enlarge
41 //  a box, and use the contains() methods to check for inclusion of a point or
42 //  an other box.
43 //
44 //  To make the convex union of two boxes, use box1.add(box2).
45 //  \verbatim
46 //                                  MaxPosition
47 //                    O-------------O
48 //                    |             |
49 //                    |             |
50 //                    |  Centroid   |
51 //                    |      o      |
52 //                    |             |
53 //        Y           |             |
54 //        |           |             |
55 //        |           O-------------O
56 //        |       MinPosition
57 //        O------X
58 // \endverbatim
59 // If you are using a vgl_box_2d<int> to indicate a window on an image, do not forget
60 // that your axes will be flipped. You could think of the window as follows.
61 //  \verbatim
62 //        O------X
63 //        |       MinPosition
64 //        |             O-------------O
65 //        |             |             |
66 //        Y             |             |
67 //                      |  Centroid   |
68 //                      |      o      |
69 //                      |             |
70 //                      |             |
71 //                      |             |
72 //                      O-------------O
73 //                               MaxPosition
74 // \endverbatim
75 // \sa vgl_box_3d
76 //  Note: area is not defined on the box class to keep a clean interface
77 //  see vgl_area<T>
78 template <class Type>
79 class vgl_box_2d
80 {
81  public:
82 
83   //: Default constructor (creates empty box)
84   vgl_box_2d();
85 
86   //: Construct using two corner points
87   vgl_box_2d(Type const corner1[2],
88              Type const corner2[2]);
89 
90   //: Construct using two corner points
91   vgl_box_2d(vgl_point_2d<Type> const& corner1,
92              vgl_point_2d<Type> const& corner2);
93 
94   //: Construct using ranges in \a x (first two args) and \a y (last two)
95   vgl_box_2d(Type xmin, Type xmax, Type ymin, Type ymax);
96 
97   enum point_type { centre=0, min_pos, max_pos };
98 
99   //: Construct a box sized width x height at a given reference point.
100   //  The box will either be centered at ref_point or will have ref_point
101   //  as its min-position or max-position, as specified by the 4th argument.
102   vgl_box_2d(Type const ref_point[2],
103              Type width, Type height,
104              point_type);
105 
106   //: Construct a box sized width x height at a given reference point.
107   //  The box will either be centered at ref_point or will have ref_point
108   //  as its min-position or max-position, as specified by the 4th argument.
109   vgl_box_2d(vgl_point_2d<Type> const& ref_point,
110              Type width, Type height,
111              point_type);
112 
113   //: Equality test
114   inline bool operator==(vgl_box_2d<Type> const& b) const {
115     // All empty boxes are equal:
116     if (b.is_empty()) return is_empty();
117     return  min_x() == b.min_x() && min_y() == b.min_y()
118          && max_x() == b.max_x() && max_y() == b.max_y();
119   }
120 
121   // Data Access---------------------------------------------------------------
122 
123   //: Get width of this box (= \a x dimension)
124   Type width() const;
125   //: Get height of this box (= \a y dimension)
126   Type height() const;
127 
128   //: Get "volume" (=area) of this box
volume()129   Type volume() const { return width()*height(); }
130 
131   //: Get min \a x
min_x()132   inline Type min_x() const { return min_pos_[0]; }
133   //: Get min \a y
min_y()134   inline Type min_y() const { return min_pos_[1]; }
135   //: Get max \a x
max_x()136   inline Type max_x() const { return max_pos_[0]; }
137   //: Get max \a y
max_y()138   inline Type max_y() const { return max_pos_[1]; }
139 
140   //: Get the centroid point
141   vgl_point_2d<Type> centroid() const;
142   //: Get \a x component of centroid
143   Type centroid_x() const;
144   //: Get \a y component of centroid
145   Type centroid_y() const;
146 
147   //: Return lower left corner of box
148   vgl_point_2d<Type> min_point() const;
149 
150   //: Return upper right corner of box
151   vgl_point_2d<Type> max_point() const;
152 
153   // Data Control--------------------------------------------------------------
154 
155   //: Return true if this box is empty
is_empty()156   inline bool is_empty() const {
157     return min_x() > max_x() || min_y() > max_y();
158   }
159 
160   //: Add a point to this box.
161   // Do this by possibly enlarging the box so that the point just falls within the box.
162   // Adding a point to an empty box makes it a size zero box only containing p.
163   void add(vgl_point_2d<Type> const& p);
164 
165   //: Make the convex union of two boxes.
166   // Do this by possibly enlarging this box so that the corner points of the
167   // given box just fall within the box.
168   // Adding an empty box does not change the current box.
169   void add(vgl_box_2d<Type> const& b);
170 
171   //: Return true iff the point p is inside this box
172   bool contains(vgl_point_2d<Type> const& p) const;
173 
174   //: Return true iff the corner points of b are inside this box
175   bool contains(vgl_box_2d<Type> const& b) const;
176 
177   //: Return true if \a (x,y) inside box, ie \a x_min <= \a x <= \a x_max etc
contains(Type const & x,Type const & y)178   inline bool contains(Type const& x, Type const& y) const {
179     return x >= min_x() && x <= max_x() && y >= min_y() && y <= max_y();
180   }
181 
182   //: Make the box empty
183   void empty();
184 
185   //: Set left side of box (other side ordinates unchanged)
set_min_x(Type m)186   inline void set_min_x(Type m) { min_pos_[0]=m; }
187   //: Set bottom of box (other side ordinates unchanged)
set_min_y(Type m)188   inline void set_min_y(Type m) { min_pos_[1]=m; }
189   //: Set right side (other side ordinates unchanged)
set_max_x(Type m)190   inline void set_max_x(Type m) { max_pos_[0]=m; }
191   //: Set top (other side ordinates unchanged)
set_max_y(Type m)192   inline void set_max_y(Type m) { max_pos_[1]=m; }
193 
194   //: Move box so centroid lies at cx (width and height unchanged)
195   void set_centroid_x(Type cx);
196   //: Move box so centroid lies at cy (width and height unchanged)
197   void set_centroid_y(Type cy);
198 
199   //: Modify width, retaining centroid at current position
200   void set_width(Type width);
201   //: Modify height, retaining centroid at current position
202   void set_height(Type height);
203 
204   //: Add to width and height, centroid unchanged.
205   // Will move each side by \p expand / 2.
206   void expand_about_centroid(Type expand);
207   //: Scale width and height, centroid unchanged.
208   void scale_about_centroid(double s);
209   //: Scale width and height, keeping scaled position of origin unchanged.
210   void scale_about_origin(double s);
211 
212   //: Modify bottom left. Top right only changed if necessary to avoid empty box
213   void setmin_position(Type const min_position[2]);
214   //: Modify top right. Bottom left only changed if necessary to avoid empty box
215   void setmax_position(Type const max_position[2]);
216   //: Modify bottom left. Top right only changed if necessary to avoid empty box
217   void set_min_point(vgl_point_2d<Type> const& min_pt);
218   //: Modify top right. Bottom left only changed if necessary to avoid empty box
219   void set_max_point(vgl_point_2d<Type> const& max_pt);
220 
221   //: Move box so centroid lies at c (width, height unchanged)
set_centroid(Type const c[2])222   inline void set_centroid(Type const c[2]) { set_centroid_x(c[0]); set_centroid_y(c[1]); }
223   //: Move box so centroid lies at c (width, height unchanged)
set_centroid(vgl_point_2d<Type> const & c)224   inline void set_centroid(vgl_point_2d<Type> const& c) { set_centroid_x(c.x()); set_centroid_y(c.y()); }
225 
226   // I/O-----------------------------------------------------------------------
227 
228   //: Write "<vgl_box_2d x0,y0 to x1,y1>" to stream
229   std::ostream& print(std::ostream&) const;
230 
231   //: Write "x0 y0 x1 y1(endl)" to stream
232   std::ostream& write(std::ostream&) const;
233 
234   //: Read x0,y0,x1,y1 from stream
235   std::istream& read(std::istream&);
236 
237   // INTERNALS-----------------------------------------------------------------
238  protected:
239   // Data Members--------------------------------------------------------------
240   Type min_pos_[2];
241   Type max_pos_[2];
242 };
243 
244 //: Write box to stream
245 // \relatesalso vgl_box_2d
246 template <class Type>
247 std::ostream&  operator<<(std::ostream& s, vgl_box_2d<Type> const& p);
248 
249 //: Read box from stream
250 // \relatesalso vgl_box_2d
251 template <class Type>
252 std::istream&  operator>>(std::istream& is,  vgl_box_2d<Type>& p);
253 
254 //: Calculate the bounding box of a sequence of points or boxes.
255 template <class T, class ITER>
vgl_box_2d_bounds(ITER begin,ITER end,vgl_box_2d<T> & bounding_box)256 void vgl_box_2d_bounds(ITER begin, ITER end, vgl_box_2d<T>& bounding_box)
257 {
258   for (; begin != end; ++begin)
259     bounding_box.add(*begin);
260 }
261 
262 #define VGL_BOX_2D_INSTANTIATE(T) extern "please include vgl/vgl_box_2d.hxx first"
263 
264 #endif // vgl_box_2d_h
265