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