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