vgl_oriented_box_2d.hxx
Go to the documentation of this file.
1 #include <cmath>
2 #include <iostream>
3 #include <string>
4 #include <cassert>
5 #include "vgl_oriented_box_2d.h"
6 #include "vgl_closest_point.h"
7 #include <vgl/vgl_box_2d.h>
8 #include <vgl/vgl_vector_2d.h>
9 #include <vgl/vgl_line_2d.h>
10 #include <vgl/vgl_tolerance.h>
11 template <class T>
12 vgl_oriented_box_2d<T>::vgl_oriented_box_2d(T width, T height, vgl_point_2d<T> const& center, T angle_in_rad)
13 {
14  if(width<height){
15  std::cout << "width must be greater than height!!!" << std::endl;
16  half_height_ = T(0);
17  return;
18  }
19  half_height_ = height/T(2);
20  T half_width = width/T(2);
21  T cx = center.x(), cy = center.y();
22  T c = cos(angle_in_rad), s = sin(angle_in_rad);
23  // major axis points translated to the origin (subtract center)
24  T p0x = - half_width, p1x = half_width;
25  T p0rx = c*p0x , p0ry = s*p0x ;
26  T p1rx = c*p1x , p1ry = s*p1x ;
27  // add center back in
28  p0rx += cx; p1rx += cx;
29  p0ry += cy; p1ry += cy;
30  vgl_point_2d<T> p0r(p0rx, p0ry), p1r(p1rx, p1ry);
31  major_axis_.set(p0r, p1r);
32 }
33 
34 template <class T>
36  *this = vgl_oriented_box_2d<T>(box, T(0));
37 }
38 
39 template <class T>
41  T w = box.width(), h = box.height();
42  T width = w, height = h;
43  T ang = angle_in_rad;
44  if(w<h){
45  width = h;
46  height = w;
47  ang += T(3.1415926535897932384626433832795)/T(2);
48  }
49  *this = vgl_oriented_box_2d<T>(width, height, box.centroid(), ang);
50 }
51 
52 template <class T>
54  vgl_vector_2d<T> v01 = p1-p0, v02 = p2-p0;
55  T len_01 = v01.length(), len_02 = v02.length();
56  if(len_01>len_02){
57  v02/=len_02;
58  half_height_ = len_02/T(2);
59  vgl_point_2d<T> p0p = p0 + half_height_*v02;
60  vgl_point_2d<T> p1p = p1 + half_height_*v02;
61  major_axis_.set( p0p, p1p);
62  return;
63  }
64  v01/=len_01;
65  half_height_ = len_01/T(2);
66  vgl_point_2d<T> p0p = p0 + half_height_*v01;
67  vgl_point_2d<T> p2p = p2 + half_height_*v01;
68  major_axis_.set( p0p, p2p);
69 }
70 
71 template <class T>
73  vgl_point_2d<T> const& min_p1, vgl_point_2d<T> const& min_p2){
74  vgl_vector_2d<T> dir = maj_p2 - maj_p1;
75  assert(dir.length()>T(0));
76  vgl_vector_2d<T> perp(-dir.y(), dir.x());
77  perp /= perp.length();
78  vgl_vector_2d<T> min_dir = min_p2 - min_p1;
79  assert(min_dir.length()>T(0));
80  half_height_ = fabs(dot_product(min_dir, perp))/T(2);
81  // construct the perpendicular through maj_p1
82  vgl_line_2d<T> pline(maj_p1, perp);
83  vgl_point_2d<T> cp1 = vgl_closest_point(pline, min_p1);
84  vgl_point_2d<T> cp2 = vgl_closest_point(pline, min_p2);
85  vgl_point_2d<T> maj_p1_c((cp1.x()+cp2.x())/T(2), (cp1.y()+cp2.y())/T(2));
86  vgl_point_2d<T> maj_p2_c = maj_p1_c + dir;
87  major_axis_.set(maj_p1_c, maj_p2_c);
88 }
89 
90 // axis-aligned bounding box
91 template <class T>
93  vgl_box_2d<T> ret;
94  std::vector<vgl_point_2d<T> > corns = this->corners();
95  for(typename std::vector<vgl_point_2d<T> >::iterator cit = corns.begin();
96  cit != corns.end(); ++cit)
97  ret.add(*cit);
98  return ret;
99 }
100 template <class T>
101 std::pair<T, T> vgl_oriented_box_2d<T>::width_height() const{
102  vgl_vector_2d<T> v = major_axis_.point2() - major_axis_.point1();
103  T len = v.length();
104  std::pair<T, T> ret(len, T(2)*half_height_);
105  return ret;
106 }
107 
108 template <class T>
109 std::vector<vgl_point_2d<T> > vgl_oriented_box_2d<T>::corners() const{
110  const vgl_point_2d<T>& pmaj0 = major_axis_.point1();
111  const vgl_point_2d<T>& pmaj1 = major_axis_.point2();
112  vgl_vector_2d<T> v = pmaj1-pmaj0;
113  T len = v.length();
114  v/=len;
115  //perpendicular vector
116  vgl_vector_2d<T> perp(-v.y(), v.x());
117  // generate the corner points in counter-clockwise order
118  vgl_point_2d<T> p0 = pmaj0 - half_height_*perp;
119  vgl_point_2d<T> p1 = pmaj1 - half_height_*perp;
120  vgl_point_2d<T> p2 = pmaj1 + half_height_*perp;
121  vgl_point_2d<T> p3 = pmaj0 + half_height_*perp;
122  std::vector<vgl_point_2d<T> > corns;
123  corns.push_back(p0); corns.push_back(p1);
124  corns.push_back(p2); corns.push_back(p3);
125  return corns;
126 }
127 template <class T>
129  const vgl_point_2d<T>& pmaj0 = major_axis_.point1();
130  const vgl_point_2d<T>& pmaj1 = major_axis_.point2();
131  vgl_point_2d<T> c((pmaj0.x() + pmaj1.x())/T(2),(pmaj0.y() + pmaj1.y())/T(2));
132  return c;
133 }
134 template <class T>
135 std::ostream& operator<<(std::ostream& os, const vgl_oriented_box_2d<T>& obox){
136  os << "major axis: " << obox.major_axis() << " half_height: " << obox.height()/T(2)<< "\n";
137  return os;
138 }
139 template <class T>
140 std::istream& operator>>(std::istream& is, vgl_oriented_box_2d<T>& obox){
141  //is.skipws;
143  T half_height = T(0);
144  std::string temp;
145  is >> temp >> temp;
146  is >> maj >> temp >> half_height;
147  obox.set(maj, half_height);
148  return is;
149 }
150 template <class T>
152  vgl_point_2d<T> c = this->centroid();
153  vgl_vector_2d<T> vp = p-c;
154  vgl_vector_2d<T> dir = major_axis_.direction();
155  vgl_vector_2d<T> norm(-dir.y(), dir.x());
156  T mag = (major_axis_.point2()-major_axis_.point1()).length();
157  // orthogonal obox coordinate vector
158  T u = dot_product(dir, vp)/mag;
159  T v = dot_product(norm,vp)/(T(2)*half_height_);
160  return vgl_point_2d<T>(u, v);
161 }
162 template <class T>
165  vgl_point_2d<T> uv = this->transform_to_obox(p);
166  T half = T(1)/T(2);
167  half += tol;
168  if(uv.x()<-half || uv.x()>half)
169  return false;
170  if(uv.y()<-half || uv.y()>half)
171  return false;
172  return true;
173 }
174 template <class T>
176  if(*this == ob)
177  return true;
178  T ob_half_height = ob.height()/T(2);
179  if(fabs(ob_half_height - half_height_) > tol)
180  return false;
181  const vgl_line_segment_2d<T>& ma = ob.major_axis();
182  const vgl_point_2d<T>& obp1 = ma.point1();
183  const vgl_point_2d<T>& obp2 = ma.point2();
184  const vgl_point_2d<T>& tp1 = major_axis_.point1();
185  const vgl_point_2d<T>& tp2 = major_axis_.point2();
186  vgl_vector_2d<T> p1p1 = obp1-tp1;
187  vgl_vector_2d<T> p2p2 = obp2-tp2;
188  if(p1p1.length()<tol && p2p2.length()<tol)
189  return true;
190  vgl_vector_2d<T> p1p2 = obp1-tp2;
191  vgl_vector_2d<T> p2p1 = obp2-tp1;
192  if(p1p2.length()<tol && p2p1.length()<tol)
193  return true;
194  return false;
195 }
196 template <class T>
198  const vgl_point_2d<T>& tp1 = major_axis_.point1();
199  const vgl_point_2d<T>& tp2 = major_axis_.point2();
200  vgl_vector_2d<T> v = tp2-tp1;
201  v /= v.length();
202  return atan2(v.y(), v.x());
203 }
204 template <class T>
205 static vgl_point_2d<T> rotate_point(vgl_point_2d<T> cent, vgl_point_2d<T> p, T ang_rad){
206  vgl_vector_2d<T> v = p-cent;
207  T c = cos(ang_rad), s = sin(ang_rad);
208  T vrx = v.x()*c - v.y()*s;
209  T vry = v.x()*s + v.y()*c;
210  vgl_vector_2d<T> pr(vrx, vry);
211  return cent + pr;
212 }
213 
214 template <class T>
216  vgl_point_2d<T> rot_maj_p1 =
217  rotate_point(rot_center, major_axis_.point1(), angle_rad);
218  vgl_point_2d<T> rot_maj_p2 =
219  rotate_point(rot_center, major_axis_.point2(), angle_rad);
220  return vgl_oriented_box_2d<T>(rot_maj_p1, rot_maj_p2, T(2)*half_height_);
221 }
222 template <class T>
224  vgl_vector_2d<T> t(tx, ty);
225  vgl_point_2d<T> trans_maj_p1 = major_axis_.point1() + t;
226  vgl_point_2d<T> trans_maj_p2 = major_axis_.point2() + t;
227  return vgl_oriented_box_2d<T>(trans_maj_p1, trans_maj_p2, T(2)*half_height_);
228 }
229 
230 #undef VGL_ORIENTED_BOX_2D_INSTANTIATE
231 #define VGL_ORIENTED_BOX_2D_INSTANTIATE(T) \
232 template class vgl_oriented_box_2d<T >; \
233 template std::ostream& operator<<(std::ostream&, const vgl_oriented_box_2d<T >&); \
234 template std::istream& operator>>(std::istream&, vgl_oriented_box_2d<T >&)
T dot_product(v const &a, v const &b)
dot product or inner product of two vectors.
T angle_in_rad() const
: orientedation of major axis on the range +- pi (as returned by atan2).
vgl_oriented_box_2d()
default constructor.
Direction vector in Euclidean 2D space, templated by type of element.
Definition: vgl_fwd.h:12
vgl_oriented_box_2d< T > translate(T tx, T ty) const
translate by displacement (tx, ty).
T y() const
Definition: vgl_vector_2d.h:36
vgl_point_2d< Type > point2() const
The other end-point of the line segment.
double length() const
Return the length of this vector.
std::ostream & operator<<(std::ostream &s, vgl_orient_box_3d< Type > const &p)
Write box to stream.
void set(T vx, T vy)
Assignment.
Definition: vgl_vector_2d.h:55
Type width() const
Get width of this box (= x dimension).
Definition: vgl_box_2d.hxx:128
double length(v const &a)
Return the length of a vector.
Definition: vgl_vector_2d.h:94
#define v
Definition: vgl_vector_2d.h:74
#define vp(os, v, s)
Set of closest-point functions.
std::pair< T, T > width_height() const
return width (first) and height (second).
vgl_box_2d< T > enclosing_box() const
axis-aligned bounding box for *this.
vgl_point_2d< T > vgl_closest_point(vgl_line_2d< T > const &l, vgl_point_2d< T > const &p)
Return the point on the given line closest to the given point.
void set(Type px, Type py)
Set x and y.
Definition: vgl_point_2d.h:79
Type & y()
Definition: vgl_point_2d.h:72
T height() const
height - length of minor axis.
bool contains(T const &x, T const &y) const
Return true if (x,y) is inside this box.
void set(vgl_line_segment_2d< T > const &major, T half_height)
direction vector in Euclidean 2D space
Contains class to represent a cartesian 2D bounding box.
vgl_point_2d< T > centroid() const
center (midpoint of major axis).
std::vector< vgl_point_2d< T > > corners() const
corners of the orienteded rectangle.
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.
vgl_line_segment_2d< T > major_axis() const
major axis.
Type height() const
Get height of this box (= y dimension).
Definition: vgl_box_2d.hxx:134
void add(vgl_point_2d< Type > const &p)
Add a point to this box.
Definition: vgl_box_2d.hxx:317
T x() const
Definition: vgl_vector_2d.h:35
bool near_equal(vgl_oriented_box_2d< T > const &ob, T tol=vgl_tolerance< T >::position) const
vgl_point_2d< T > transform_to_obox(vgl_point_2d< T > const &p) const
map a point to the (u, v) coordinate system of the orienteded box.
An orienteded box in 2-d.
vgl_point_2d< Type > point1() const
One end-point of the line segment.
Type & x()
Definition: vgl_point_2d.h:71
vgl_oriented_box_2d< T > rotate(vgl_point_2d< T > const &rot_center, T angle_rad) const
rotate by angle in radians.