vgl_fit_oriented_box_2d.hxx
Go to the documentation of this file.
1 #include <limits>
3 #include <vnl/vnl_math.h>
4 #include <vgl/vgl_box_2d.h>
5 #include <vgl/vgl_area.h>
6 
7 template <class T>
8 vgl_fit_oriented_box_2d<T>::vgl_fit_oriented_box_2d(vgl_polygon<T> const& poly, double dtheta):fixed_theta_(false), fit_valid_(false), dtheta_(dtheta){
9  // extract points
10  pts_.clear();
11  size_t ns = poly.num_sheets();
12  for(size_t is = 0; is<ns; ++is)
13  for(size_t i = 0; i<poly[is].size(); ++i)
14  pts_.push_back(poly[is][i]);
15 }
16 template <class T>
18 
19  vgl_oriented_box_2d<T> min_area_obox;
20  T min_area = std::numeric_limits<T>::max();
21  size_t n = pts_.size();
22  if(n<2){
23  std::cout << "insufficient number of points to fit obox " << n << std::endl;
24  return;
25  }
26  vgl_point_2d<T>& vs = pts_[0];
27  // +- 90 degrees
28  T T_pi_2 = static_cast<T>(vnl_math::pi_over_2);
29  T low_theta = -T_pi_2, high_theta = T_pi_2;
30  if(fixed_theta_){
31  //theta rotates the poly edge to align with the x axis
32  //thus theta is negative the orientation of the box
33  low_theta = -theta_rad;
34  high_theta = -theta_rad;
35  }
36  T min_theta = T(0);
37  for(T theta = low_theta; theta <= high_theta; theta += dtheta_){
38  T c = cos(theta), s = sin(theta);
39  vgl_box_2d<T> box;
40  for(size_t j = 0; j<n; ++j){
41  vgl_vector_2d<T> vp = pts_[j]-vs;
42  vgl_point_2d<T> rpp((c*vp.x()-s*vp.y()),(s*vp.x() + c*vp.y()));
43  box.add(rpp);
44  }
45  T area = vgl_area(box);
46  if(area < min_area){
47  min_area = area;
48  min_theta = theta;
49  T w = box.width(), h = box.height();
50  vgl_point_2d<T> cent = box.centroid();
51  //select major axis such that width > height
52  T width = w, height = h;
53  vgl_point_2d<T> pmaj0(cent.x()-width/2.0, cent.y()), pmaj1(cent.x()+width/2.0, cent.y());
54  if(w<h){
55  width = h;
56  height = w;
57  pmaj0.set(cent.x(), cent.y()-width/2.0); pmaj1.set(cent.x(), cent.y()+width/2.0);
58  }
59  // rotate major axis about vs
60  c = cos(-theta); s = sin(-theta);
61  T pmaj0x = pmaj0.x(), pmaj0y = pmaj0.y();
62  T pmaj1x = pmaj1.x(), pmaj1y = pmaj1.y();
63  vgl_point_2d<T> pmaj0r(c*pmaj0x - s*pmaj0y, s*pmaj0x + c*pmaj0y);
64  vgl_point_2d<T> pmaj1r(c*pmaj1x - s*pmaj1y, s*pmaj1x + c*pmaj1y);
65 
66  // add back rotation center
67  vgl_vector_2d<T> offset(vs.x(), vs.y());
68  pmaj0r += offset; pmaj1r += offset;
69  min_area_obox = vgl_oriented_box_2d<T>(pmaj0r, pmaj1r, height);
70  }
71  }
72  obox_ = min_area_obox;
73 }
74 
75 template <class T>
77  fixed_theta_ = false;
78  if(!fit_valid_){
79  fit_obox();
80  fit_valid_ = true;
81  }
82  return obox_;
83 }
84 #undef VGL_FIT_ORIENTED_BOX_2D_INSTANTIATE
85 #define VGL_FIT_ORIENTED_BOX_2D_INSTANTIATE(T) \
86 template class vgl_fit_oriented_box_2d<T >
vgl_fit_oriented_box_2d()
default constructor.
Direction vector in Euclidean 2D space, templated by type of element.
Definition: vgl_fwd.h:12
Type width() const
Get width of this box (= x dimension).
Definition: vgl_box_2d.hxx:128
#define vp(os, v, s)
void set(Type px, Type py)
Set x and y.
Definition: vgl_point_2d.h:79
Type & y()
Definition: vgl_point_2d.h:72
vgl_oriented_box_2d< T > fitted_box()
brute force search.
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::vector< vgl_point_2d< T > > pts_
void fit_obox(T theta_rad=T(0))
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
Fit an oriented box to a set of 2d points.
unsigned int num_sheets() const
Definition: vgl_polygon.h:116
Store a polygon.
Definition: vgl_area.h:6
T vgl_area(vgl_polygon< T > const &poly)
The area of a polygon.
Type & x()
Definition: vgl_point_2d.h:71