vgl_box_3d.hxx
Go to the documentation of this file.
1 // This is core/vgl/vgl_box_3d.hxx
2 #ifndef vgl_box_3d_hxx_
3 #define vgl_box_3d_hxx_
4 //:
5 // \file
6 
7 #include <iostream>
8 #include <algorithm>
9 #include <cmath>
10 #include "vgl_box_3d.h"
11 #include <vgl/vgl_point_3d.h>
12 #include <cassert>
13 #ifdef _MSC_VER
14 # include <vcl_msvc_warnings.h>
15 #endif
16 
17 // Constructors/Destructor---------------------------------------------------
18 
19 template <class Type>
21 {
22  min_pos_[0]=min_pos_[1]=min_pos_[2]=(Type)1;
23  max_pos_[0]=max_pos_[1]=max_pos_[2]=(Type)0; // empty box
24 }
25 
26 template <class Type>
27 vgl_box_3d<Type>::vgl_box_3d(Type const corner1[3],
28  Type const corner2[3])
29 {
30  min_pos_[0]=max_pos_[0]=corner1[0];
31  min_pos_[1]=max_pos_[1]=corner1[1];
32  min_pos_[2]=max_pos_[2]=corner1[2];
33  this->add(corner2);
34 }
35 
36 template <class Type>
38  vgl_point_3d<Type> const& corner2)
39 {
40  min_pos_[0]=max_pos_[0]=corner1.x();
41  min_pos_[1]=max_pos_[1]=corner1.y();
42  min_pos_[2]=max_pos_[2]=corner1.z();
43  this->add(corner2);
44 }
45 
46 template <class Type>
47 vgl_box_3d<Type>::vgl_box_3d(Type xmin, Type ymin, Type zmin,
48  Type xmax, Type ymax, Type zmax)
49 {
50  min_pos_[0]=max_pos_[0]=xmin;
51  min_pos_[1]=max_pos_[1]=ymin;
52  min_pos_[2]=max_pos_[2]=zmin;
53  this->add(vgl_point_3d<Type>(xmax,ymax,zmax));
54  if (xmin > xmax || ymin > ymax || zmin > zmax) this->empty();
55 }
56 
57 template <class Type>
58 vgl_box_3d<Type>::vgl_box_3d(Type const ref_point[3],
59  Type w, Type h, Type d,
61 {
62  if (t == vgl_box_3d<Type>::centre)
63  {
64  min_pos_[0]=Type(ref_point[0]-0.5*w);
65  min_pos_[1]=Type(ref_point[1]-0.5*h);
66  min_pos_[2]=Type(ref_point[2]-0.5*d);
67  max_pos_[0]=Type(ref_point[0]+0.5*w);
68  max_pos_[1]=Type(ref_point[1]+0.5*h);
69  max_pos_[2]=Type(ref_point[2]+0.5*d);
70  }
71  else if (t == vgl_box_3d<Type>::min_pos)
72  {
73  min_pos_[0]=ref_point[0];
74  min_pos_[1]=ref_point[1];
75  min_pos_[2]=ref_point[2];
76  max_pos_[0]=ref_point[0]+w;
77  max_pos_[1]=ref_point[1]+h;
78  max_pos_[2]=ref_point[2]+d;
79  }
80  else if (t == vgl_box_3d<Type>::max_pos)
81  {
82  min_pos_[0]=ref_point[0]-w;
83  min_pos_[1]=ref_point[1]-h;
84  min_pos_[2]=ref_point[2]-d;
85  max_pos_[0]=ref_point[0];
86  max_pos_[1]=ref_point[1];
87  max_pos_[2]=ref_point[2];
88  }
89  else
90  assert(!"point_type should be one of: centre, min_pos, max_pos");
91 }
92 
93 template <class Type>
95  Type w, Type h, Type d,
97 {
98  if (t == vgl_box_3d<Type>::centre)
99  {
100  min_pos_[0]=Type(ref_point.x()-0.5*w);
101  min_pos_[1]=Type(ref_point.y()-0.5*h);
102  min_pos_[2]=Type(ref_point.z()-0.5*d);
103  max_pos_[0]=Type(ref_point.x()+0.5*w);
104  max_pos_[1]=Type(ref_point.y()+0.5*h);
105  max_pos_[2]=Type(ref_point.z()+0.5*d);
106  }
107  else if (t == vgl_box_3d<Type>::min_pos)
108  {
109  min_pos_[0]=ref_point.x();
110  min_pos_[1]=ref_point.y();
111  min_pos_[2]=ref_point.z();
112  max_pos_[0]=ref_point.x()+w;
113  max_pos_[1]=ref_point.y()+h;
114  max_pos_[2]=ref_point.z()+d;
115  }
116  else if (t == vgl_box_3d<Type>::max_pos)
117  {
118  min_pos_[0]=ref_point.x()-w;
119  min_pos_[1]=ref_point.y()-h;
120  min_pos_[2]=ref_point.z()-d;
121  max_pos_[0]=ref_point.x();
122  max_pos_[1]=ref_point.y();
123  max_pos_[2]=ref_point.z();
124  }
125  else
126  assert(!"point_type should be one of: centre, min_pos, max_pos");
127 }
128 
129 template <class Type>
131 {
132  return (max_pos_[0] > min_pos_[0]) ? max_pos_[0] - min_pos_[0] : 0;
133 }
134 
135 template <class Type>
137 {
138  return (max_pos_[1] > min_pos_[1]) ? max_pos_[1] - min_pos_[1] : 0;
139 }
140 
141 template <class Type>
143 {
144  return (max_pos_[2] > min_pos_[2]) ? max_pos_[2] - min_pos_[2] : 0;
145 }
146 
147 template <class Type>
149 {
150  return vgl_point_3d<Type>(centroid_x(),centroid_y(),centroid_z());
151 }
152 
153 template <class Type>
155 {
156  assert(!is_empty());
157  return Type(0.5*(min_pos_[0]+max_pos_[0]));
158 }
159 
160 template <class Type>
162 {
163  assert(!is_empty());
164  return Type(0.5*(min_pos_[1]+max_pos_[1]));
165 }
166 
167 template <class Type>
169 {
170  assert(!is_empty());
171  return Type(0.5*(min_pos_[2]+max_pos_[2]));
172 }
173 
174 template <class Type>
176 {
177  assert(!is_empty());
178  Type delta = cx - centroid_x();
179  min_pos_[0]= min_pos_[0] + delta;
180  max_pos_[0]= max_pos_[0] + delta;
181 }
182 
183 template <class Type>
185 {
186  assert(!is_empty());
187  Type delta = cy - centroid_y();
188  min_pos_[1]= min_pos_[1] + delta;
189  max_pos_[1]= max_pos_[1] + delta;
190 }
191 
192 template <class Type>
194 {
195  assert(!is_empty());
196  Type delta = cz - centroid_z();
197  min_pos_[2]= min_pos_[2] + delta;
198  max_pos_[2]= max_pos_[2] + delta;
199 }
200 
201 template <class T>
202 inline void set_dim_3d(T& minv, T& maxv, T spread);
203 
204 // All this code is to avoid drift in the centroid.
205 template <>
206 inline void set_dim_3d(int& minv, int& maxv, int spread)
207 {
208  int sum = minv + maxv;
209  sum = sum | (spread&1); // if width is odd, then make sum odd
210  minv = int(std::floor((sum-spread)/2.0));
211  maxv = minv+spread;
212 }
213 
214 template <class T>
215 inline void set_dim_3d(T& minv, T& maxv, T spread)
216 {
217  T x = minv + maxv;
218  minv = T( (x-spread)*0.5 );
219  maxv = minv + spread;
220 }
221 
222 template <class Type>
224 {
225  assert(!is_empty());
226  set_dim_3d(min_pos_[0], max_pos_[0], w);
227 }
228 
229 template <class Type>
231 {
232  assert(!is_empty());
233  set_dim_3d(min_pos_[1], max_pos_[1], h);
234 }
235 
236 template <class Type>
238 {
239  assert(!is_empty());
240  set_dim_3d(min_pos_[2], max_pos_[2], d);
241 }
242 
243 //: Add to width and height, centroid unchanged.
244 // Will move each side by \p expand / 2.
245 template <class Type>
247 {
248  assert(!is_empty());
249  set_dim_3d(min_pos_[0], max_pos_[0], width() + expand );
250  set_dim_3d(min_pos_[1], max_pos_[1], height() + expand );
251  set_dim_3d(min_pos_[2], max_pos_[2], depth() + expand );
252 }
253 
254 //: Scale width, height and depth, centroid unchanged.
255 template <class Type>
257 {
258  assert(!is_empty());
259  set_dim_3d(min_pos_[0], max_pos_[0], static_cast<Type>(width()*s));
260  set_dim_3d(min_pos_[1], max_pos_[1], static_cast<Type>(height()*s));
261  set_dim_3d(min_pos_[2], max_pos_[2], static_cast<Type>(depth()*s));
262 }
263 
264 //: Scale width, height and depth, keeping scaled position of origin unchanged.
265 template <class Type>
267 {
268  min_pos_[0] = static_cast<Type>(min_pos_[0] * s);
269  min_pos_[1] = static_cast<Type>(min_pos_[1] * s);
270  min_pos_[2] = static_cast<Type>(min_pos_[2] * s);
271  max_pos_[0] = static_cast<Type>(max_pos_[0] * s);
272  max_pos_[1] = static_cast<Type>(max_pos_[1] * s);
273  max_pos_[2] = static_cast<Type>(max_pos_[2] * s);
274 }
275 
276 template <class Type>
277 void vgl_box_3d<Type>::set_min_position(Type const min_position[3])
278 {
279  min_pos_[0]=min_position[0];
280  min_pos_[1]=min_position[1];
281  min_pos_[2]=min_position[2];
282  if (max_pos_[0] < min_pos_[0]) max_pos_[0]=min_pos_[0];
283  if (max_pos_[1] < min_pos_[1]) max_pos_[1]=min_pos_[1];
284  if (max_pos_[2] < min_pos_[2]) max_pos_[2]=min_pos_[2];
285 }
286 
287 template <class Type>
288 void vgl_box_3d<Type>::set_max_position(Type const max_position[3])
289 {
290  max_pos_[0]=max_position[0];
291  max_pos_[1]=max_position[1];
292  max_pos_[2]=max_position[2];
293  if (max_pos_[0] < min_pos_[0]) min_pos_[0]=max_pos_[0];
294  if (max_pos_[1] < min_pos_[1]) min_pos_[1]=max_pos_[1];
295  if (max_pos_[2] < min_pos_[2]) min_pos_[2]=max_pos_[2];
296 }
297 
298 template <class Type>
300 {
301  min_pos_[0]=min_pt.x(); if (max_pos_[0]<min_pos_[0]) max_pos_[0]=min_pos_[0];
302  min_pos_[1]=min_pt.y(); if (max_pos_[1]<min_pos_[1]) max_pos_[1]=min_pos_[1];
303  min_pos_[2]=min_pt.z(); if (max_pos_[2]<min_pos_[2]) max_pos_[2]=min_pos_[2];
304 }
305 
306 template <class Type>
308 {
309  max_pos_[0]=max_pt.x(); if (max_pos_[0]<min_pos_[0]) min_pos_[0]=max_pos_[0];
310  max_pos_[1]=max_pt.y(); if (max_pos_[1]<min_pos_[1]) min_pos_[1]=max_pos_[1];
311  max_pos_[2]=max_pt.z(); if (max_pos_[2]<min_pos_[2]) min_pos_[2]=max_pos_[2];
312 }
313 
314 template <class Type>
315 std::ostream& vgl_box_3d<Type>::print(std::ostream& s) const
316 {
317  if (is_empty())
318  return s << "<vgl_box_3d (empty)>";
319  else
320  return s<< "<vgl_box_3d "
321  << min_pos_[0] << ',' << min_pos_[1] << ',' << min_pos_[2] << " to "
322  << max_pos_[0] << ',' << max_pos_[1] << ',' << max_pos_[2] << '>';
323 }
324 
325 template <class Type>
327 {
328  assert(!is_empty());
329  return vgl_point_3d<Type>(min_pos_[0],min_pos_[1],min_pos_[2]);
330 }
331 
332 template <class Type>
334 {
335  assert(!is_empty());
336  return vgl_point_3d<Type>(max_pos_[0],max_pos_[1],max_pos_[2]);
337 }
338 
339 template <class Type>
340 std::vector<vgl_point_3d<Type> > vgl_box_3d<Type>::vertices() const
341 {
342  assert(!is_empty());
343  std::vector<vgl_point_3d<Type> > vertices;
344  vertices.push_back(vgl_point_3d<Type>(min_pos_[0], min_pos_[1], min_pos_[2]));
345  vertices.push_back(vgl_point_3d<Type>(max_pos_[0], min_pos_[1], min_pos_[2]));
346  vertices.push_back(vgl_point_3d<Type>(max_pos_[0], max_pos_[1], min_pos_[2]));
347  vertices.push_back(vgl_point_3d<Type>(min_pos_[0], max_pos_[1], min_pos_[2]));
348  vertices.push_back(vgl_point_3d<Type>(min_pos_[0], min_pos_[1], max_pos_[2]));
349  vertices.push_back(vgl_point_3d<Type>(max_pos_[0], min_pos_[1], max_pos_[2]));
350  vertices.push_back(vgl_point_3d<Type>(max_pos_[0], max_pos_[1], max_pos_[2]));
351  vertices.push_back(vgl_point_3d<Type>(min_pos_[0], max_pos_[1], max_pos_[2]));
352  return vertices;
353 }
354 
355 template <class Type>
356 std::ostream& vgl_box_3d<Type>::write(std::ostream& s) const
357 {
358  return s << min_pos_[0] << ' ' << min_pos_[1] << ' ' << min_pos_[2] << ' '
359  << max_pos_[0] << ' ' << max_pos_[1] << ' ' << max_pos_[2] << '\n';
360 }
361 
362 template <class Type>
363 std::istream& vgl_box_3d<Type>::read(std::istream& s)
364 {
365  return s >> min_pos_[0] >> min_pos_[1] >> min_pos_[2]
366  >> max_pos_[0] >> max_pos_[1] >> max_pos_[2];
367 }
368 
369 //: Add a point to this box.
370 // Do this by possibly enlarging the box so that the point just falls within the box.
371 // Adding a point to an empty box makes it a size zero box only containing p.
372 template <class Type>
374 {
375  if (is_empty())
376  {
377  min_pos_[0] = max_pos_[0] = p.x();
378  min_pos_[1] = max_pos_[1] = p.y();
379  min_pos_[2] = max_pos_[2] = p.z();
380  }
381  else
382  {
383  if (p.x() > max_pos_[0]) max_pos_[0] = p.x();
384  if (p.x() < min_pos_[0]) min_pos_[0] = p.x();
385  if (p.y() > max_pos_[1]) max_pos_[1] = p.y();
386  if (p.y() < min_pos_[1]) min_pos_[1] = p.y();
387  if (p.z() > max_pos_[2]) max_pos_[2] = p.z();
388  if (p.z() < min_pos_[2]) min_pos_[2] = p.z();
389  }
390 }
391 
392 //: Make the convex union of two boxes
393 // Do this by possibly enlarging this box so that the corner points of the
394 // given box just fall within the box.
395 // Adding an empty box does not change the current box.
396 template <class Type>
398 {
399  if (b.is_empty()) return;
400  add(b.min_point());
401  add(b.max_point());
402 }
403 
404 //: Return true iff the point p is inside this box
405 template <class Type>
407 {
408  return contains(p.x(), p.y(), p.z());
409 }
410 
411 //: Return true iff the corner points of b are inside this box
412 template <class Type>
414 {
415  return
416  contains(b.min_x(), b.min_y(), b.min_z()) &&
417  contains(b.max_x(), b.max_y(), b.max_z());
418 }
419 
420 //: Make the box empty
421 template <class Type>
423 {
424  min_pos_[0]=min_pos_[1]=min_pos_[2]=(Type)1;
425  max_pos_[0]=max_pos_[1]=max_pos_[2]=(Type)0;
426 }
427 
428 //: Write box to stream
429 template <class Type>
430 std::ostream& operator<<(std::ostream& s, vgl_box_3d<Type> const& p)
431 {
432  return p.print(s);
433 }
434 
435 //: Read box from stream
436 template <class Type>
437 std::istream& operator>>(std::istream& is, vgl_box_3d<Type>& p)
438 {
439  return p.read(is);
440 }
441 
442 #undef VGL_BOX_3D_INSTANTIATE
443 #define VGL_BOX_3D_INSTANTIATE(Type) \
444 template class vgl_box_3d<Type >;\
445 template std::ostream& operator<<(std::ostream&, vgl_box_3d<Type > const& p);\
446 template std::istream& operator>>(std::istream&, vgl_box_3d<Type >& p)
447 
448 #endif // vgl_box_3d_hxx_
void set_min_position(Type const m[3])
Modify min corner point. Max corner point only changed if necessary to avoid empty box.
Definition: vgl_box_3d.hxx:277
void set_dim_3d(T &minv, T &maxv, T spread)
Definition: vgl_box_3d.hxx:215
bool is_empty() const
Return true if this box is empty.
Definition: vgl_box_3d.h:158
Type centroid_y() const
Get y component of centroid.
Definition: vgl_box_3d.hxx:161
void set_depth(Type depth)
Set depth (z), centroid unchanged.
Definition: vgl_box_3d.hxx:237
void set_width(Type width)
Set width (x), centroid unchanged.
Definition: vgl_box_3d.hxx:223
Type min_z() const
Get min z.
Definition: vgl_box_3d.h:128
Contains class to represent a cartesian 3D bounding box.
Represents a cartesian 3D point.
Definition: vgl_fwd.h:11
std::ostream & write(std::ostream &) const
Write "x0 y0 z0 x1 y1 z1(endl)" to stream.
Definition: vgl_box_3d.hxx:356
void expand_about_centroid(Type expand)
Add to width and height, centroid unchanged.
Definition: vgl_box_3d.hxx:246
std::ostream & operator<<(std::ostream &s, vgl_orient_box_3d< Type > const &p)
Write box to stream.
Type max_z() const
Get max z.
Definition: vgl_box_3d.h:135
void set_max_position(Type const m[3])
Modify max corner point. Min corner point only changed if necessary to avoid empty box.
Definition: vgl_box_3d.hxx:288
Type & z()
Definition: vgl_point_3d.h:73
void set_max_point(vgl_point_3d< Type > const &max_pt)
Modify max corner point. Min corner point only changed if necessary to avoid empty box.
Definition: vgl_box_3d.hxx:307
Type max_y() const
Get max y.
Definition: vgl_box_3d.h:133
void set_height(Type height)
Set height (y), centroid unchanged.
Definition: vgl_box_3d.hxx:230
void add(vgl_point_3d< Type > const &p)
Add a point to this box.
Definition: vgl_box_3d.hxx:373
vgl_point_3d< Type > min_point() const
Return lower left corner of box.
Definition: vgl_box_3d.hxx:326
vgl_box_3d()
Default constructor (creates empty box).
Definition: vgl_box_3d.hxx:20
Type min_x() const
Get min x.
Definition: vgl_box_3d.h:124
void set_centroid_x(Type cx)
Move box so centroid lies at cx (size unchanged).
Definition: vgl_box_3d.hxx:175
Type centroid_z() const
Get z component of centroid.
Definition: vgl_box_3d.hxx:168
void scale_about_centroid(double s)
Scale width, height and depth, centroid unchanged.
Definition: vgl_box_3d.hxx:256
a point in 3D nonhomogeneous space
void set_min_point(vgl_point_3d< Type > const &min_pt)
Modify min corner point. Max corner point only changed if necessary to avoid empty box.
Definition: vgl_box_3d.hxx:299
std::ostream & print(std::ostream &) const
Write "<vgl_box_3d x0,y0,z0 to x1,y1,z1>" to stream.
Definition: vgl_box_3d.hxx:315
std::istream & read(std::istream &)
Read x0,y0,z0,x1,y1,z1 from stream.
Definition: vgl_box_3d.hxx:363
void set_centroid_y(Type cy)
Move box so centroid lies at cy (size unchanged).
Definition: vgl_box_3d.hxx:184
Type depth() const
Get depth of this box (= z dimension).
Definition: vgl_box_3d.hxx:142
void empty()
Make the box empty.
Definition: vgl_box_3d.hxx:422
Type centroid_x() const
Get x component of centroid.
Definition: vgl_box_3d.hxx:154
vgl_point_3d< Type > centroid() const
Get the centroid point.
Definition: vgl_box_3d.hxx:148
std::vector< vgl_point_3d< Type > > vertices() const
Return the 8 vertices of the box.
Definition: vgl_box_3d.hxx:340
Type & x()
Definition: vgl_point_3d.h:71
Type height() const
Get height of this box (= y dimension).
Definition: vgl_box_3d.hxx:136
bool contains(vgl_point_3d< Type > const &p) const
Return true iff the point p is inside this box.
Definition: vgl_box_3d.hxx:406
void set_centroid_z(Type cz)
Move box so centroid lies at cz (size unchanged).
Definition: vgl_box_3d.hxx:193
vgl_point_3d< Type > max_point() const
Return upper right corner of box.
Definition: vgl_box_3d.hxx:333
std::istream & operator>>(std::istream &is, vgl_orient_box_3d< Type > &p)
Read box from stream.
Type min_y() const
Get min y.
Definition: vgl_box_3d.h:126
Type width() const
Get width of this box (= x dimension).
Definition: vgl_box_3d.hxx:130
Represents a cartesian 3D box.
Definition: vgl_box_3d.h:65
Type & y()
Definition: vgl_point_3d.h:72
void scale_about_origin(double s)
Scale width, height and depth, keeping scaled position of origin unchanged.
Definition: vgl_box_3d.hxx:266
Type max_x() const
Get max x.
Definition: vgl_box_3d.h:131