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