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