vgl_intersection.hxx
Go to the documentation of this file.
1 // This is core/vgl/algo/vgl_intersection.hxx
2 #ifndef vgl_algo_intersection_hxx_
3 #define vgl_algo_intersection_hxx_
4 //:
5 // \file
6 // \author Gamze Tunali
7 
8 #include "vgl_intersection.h"
9 
11 #include <vgl/vgl_plane_3d.h>
12 #include <vgl/vgl_homg_plane_3d.h>
13 #include <vgl/vgl_box_3d.h>
14 #include <vgl/vgl_point_3d.h>
15 #include <vgl/vgl_intersection.h>
16 #include <vgl/vgl_polygon.h>
17 
18 #include <vnl/vnl_matrix.h>
19 #include <vnl/vnl_vector.h>
20 #include <vnl/algo/vnl_matrix_inverse.h>
21 #include <vnl/algo/vnl_svd.h>
22 
23 #include <cassert>
24 #ifdef _MSC_VER
25 # include <vcl_msvc_warnings.h>
26 #endif
27 
28 template <class T>
30 {
31  std::vector<vgl_homg_plane_3d<T> > planes;
32  for (unsigned i=0; i<p.size(); ++i) {
33  planes.push_back(vgl_homg_plane_3d<T> (p[i]));
34  }
35 
37 }
38 
39 
40 template <class T>
42 vgl_intersection(const std::list<vgl_plane_3d<T> >& planes)
43 {
44  if (planes.size() == 0)
46 
47  // form the matrix of plane normal monomials
48  vnl_matrix<double> Q(3,3,0.0);
49  vnl_vector<double> vd(3,0.0);
50  unsigned n = planes.size();
51  for (typename std::list<vgl_plane_3d<T> >::const_iterator pit = planes.begin();
52  pit != planes.end(); ++pit)
53  {
54  double a = (*pit).a(), b = (*pit).b(), c = (*pit).c(),d = (*pit).d();
55  Q[0][0] += a*a; Q[0][1] += a*b; Q[0][2] += a*c;
56  Q[1][1] += b*b; Q[1][2] += b*c;
57  Q[2][2] += c*c;
58  vd[0]-=a*d; vd[1]-=b*d; vd[2]-=c*d;
59  }
60  Q[1][0]= Q[0][1]; Q[2][0]= Q[0][2]; Q[2][1]= Q[1][2];
61  Q/=n;
62  vd/=n;
63  vnl_svd<double> svd(Q);
64 
65  // the direction of the resulting line
66  vnl_vector<double> t = svd.nullvector();
67 
68  double tx = t[0], ty = t[1], tz = t[2];
69  double atx = std::fabs(tx), aty = std::fabs(ty), atz = std::fabs(tz);
70  // determine maximum component of t
71  char component = 'x';
72  if (aty>atx&&aty>atz)
73  component = 'y';
74  if (atz>atx&&atz>aty)
75  component = 'z';
77  switch (component)
78  {
79  case 'x':
80  {
81  double det = Q[1][1]*Q[2][2] - Q[1][2]*Q[2][1];
82  double neuy = vd[1]*Q[2][2] - Q[1][2]*vd[2];
83  double neuz = Q[1][1]*vd[2] - vd[1]*Q[2][1];
84  p0d.set(0.0, neuy/det, neuz/det);
85  break;
86  }
87  case 'y':
88  {
89  double det = Q[0][0]*Q[2][2] - Q[0][2]*Q[2][0];
90  double neux = vd[0]*Q[2][2] - Q[0][2]*vd[2];
91  double neuz = Q[0][0]*vd[2] - vd[0]*Q[2][0];
92  p0d.set(neux/det, 0.0, neuz/det);
93  break;
94  }
95  case 'z':
96  default:
97  {
98  double det = Q[0][0]*Q[1][1] - Q[0][1]*Q[1][0];
99  double neux = vd[0]*Q[1][1] - Q[0][1]*vd[1];
100  double neuy = Q[0][0]*vd[1] - vd[0]*Q[1][0];
101  p0d.set(neux/det, neuy/det, 0.0);
102  break;
103  }
104  }
105  vgl_point_3d<T> pt(static_cast<T>(p0d.x()),
106  static_cast<T>(p0d.y()),
107  static_cast<T>(p0d.z()));
108 
109  vgl_vector_3d<T> tv(static_cast<T>(tx),
110  static_cast<T>(ty),
111  static_cast<T>(tz));
112 
113  return vgl_infinite_line_3d<T>(pt, tv);
114 }
115 
116 template <class T>
117 bool
118 vgl_intersection(const std::list<vgl_plane_3d<T> >& planes, std::vector<T> ws,
119  vgl_infinite_line_3d<T>& line, T &residual)
120 {
121  if (planes.size() < 2)
122  return false;
123  // form the matrix of plane normal monomials
124  vnl_matrix<double> Q(3,3,0.0);
125  vnl_vector<double> vd(3,0.0);
126  unsigned cnt=0;
127  T sum_ws=0;
128  for (typename std::list<vgl_plane_3d<T> >::const_iterator pit = planes.begin();
129  pit != planes.end(); ++pit)
130  {
131  double a = (*pit).a(), b = (*pit).b(), c = (*pit).c(), d = (*pit).d();
132  T w=ws[cnt++];
133  Q[0][0] += w*a*a;
134  Q[0][1] += w*a*b; Q[1][1] += w*b*b;
135  Q[0][2] += w*a*c; Q[1][2] += w*b*c; Q[2][2] += w*c*c;
136  vd[0]-=w*a*d; vd[1]-=w*b*d; vd[2]-=w*c*d;
137  sum_ws+=w;
138  }
139  Q[1][0]= Q[0][1]; Q[2][0]= Q[0][2]; Q[2][1]= Q[1][2];
140  Q/=sum_ws;
141  vd/=sum_ws;
142  vnl_svd<double> svd(Q);
143  // the direction of the resulting line
144  vnl_vector<double> t = svd.nullvector();
145  double tx = t[0], ty = t[1], tz = t[2];
146  double atx = std::fabs(tx), aty = std::fabs(ty), atz = std::fabs(tz);
147  // determine maximum component of t
148  char component = 'x';
149  if (aty>atx&&aty>atz)
150  component = 'y';
151  if (atz>atx&&atz>aty)
152  component = 'z';
154  switch (component)
155  {
156  case 'x':
157  {
158  double det = Q[1][1]*Q[2][2] - Q[1][2]*Q[2][1];
159  double neuy = vd[1]*Q[2][2] - Q[1][2]*vd[2];
160  double neuz = Q[1][1]*vd[2] - vd[1]*Q[2][1];
161  p0d.set(0.0, neuy/det, neuz/det);
162  break;
163  }
164  case 'y':
165  {
166  double det = Q[0][0]*Q[2][2] - Q[0][2]*Q[2][0];
167  double neux = vd[0]*Q[2][2] - Q[0][2]*vd[2];
168  double neuz = Q[0][0]*vd[2] - vd[0]*Q[2][0];
169  p0d.set(neux/det, 0.0, neuz/det);
170  break;
171  }
172  case 'z':
173  default:
174  {
175  double det = Q[0][0]*Q[1][1] - Q[0][1]*Q[1][0];
176  double neux = vd[0]*Q[1][1] - Q[0][1]*vd[1];
177  double neuy = Q[0][0]*vd[1] - vd[0]*Q[1][0];
178  p0d.set(neux/det, neuy/det, 0.0);
179  break;
180  }
181  }
182  vgl_point_3d<T> pt(static_cast<T>(p0d.x()),
183  static_cast<T>(p0d.y()),
184  static_cast<T>(p0d.z()));
185 
186  vgl_vector_3d<T> tv(static_cast<T>(tx),
187  static_cast<T>(ty),
188  static_cast<T>(tz));
189  residual=T(0);
190  sum_ws=0;
191  cnt=0;
192  for (typename std::list<vgl_plane_3d<T> >::const_iterator pit = planes.begin();
193  pit != planes.end(); ++pit)
194  {
195  double a = pit->normal().x(), b = pit->normal().y(), c = pit->normal().z();
196  residual+=ws[cnt]*ws[cnt]*T(a*tx+b*ty+c*tz)*T(a*tx+b*ty+c*tz);
197  sum_ws+=ws[cnt]*ws[cnt];
198  cnt++;
199  }
200 
201  if (cnt>0)
202  {
203  residual/=sum_ws;
204  residual=std::sqrt(residual);
205  }
206  line=vgl_infinite_line_3d<T>(pt, tv);
207  return true;
208 }
209 
210 
211 template <class T>
212 bool vgl_intersection(vgl_box_3d<T> const& b, std::list<vgl_point_3d<T> >& poly)
213 {
214  // check if two bounding boxes intersect
215  // find the bounding box of the polygon
216  assert(poly.size() >= 3);
217 
218  vgl_box_3d<T> bb;
219  typename std::list<vgl_point_3d<T> >::iterator it=poly.begin();
220  for (; it != poly.end(); ++it)
221  bb.add(*it);
222 
223  vgl_box_3d<T> inters = vgl_intersection(b, bb);
224  if (inters.is_empty())
225  return false;
226 
227  // check if the polygon corners inside the box
228  for (it=poly.begin(); it != poly.end(); ++it) {
229  if (b.contains(*it))
230  return true;
231  }
232 
233  it=poly.begin();
234  // get the first 3 points to create a plane
235  vgl_point_3d<T> p0=*it; ++it;
236  vgl_point_3d<T> p1=*it; ++it;
237  vgl_point_3d<T> p2=*it; ++it;
238  // create a plane from polygon
239  vgl_plane_3d<T> poly_plane(p0,p1,p2);
240  if (!vgl_intersection<T>(b, poly_plane))
241  return false;
242 
243  // now we do a 3D transformation of the polygon and the box center to the plane
244  // where polygon resides, so that we can do 2D poly-point test
245  vgl_vector_3d<T> n = poly_plane.normal();
246  n=normalize(n);
247  vgl_vector_3d<T> u(p1-p0);
248  u=normalize(u);
250 
251  vnl_matrix<T> M(3,3);
252  M.put(0,0,u.x());
253  M.put(1,0,u.y());
254  M.put(2,0,u.z());
255  M.put(0,1,v.x());
256  M.put(1,1,v.y());
257  M.put(2,1,v.z());
258  M.put(0,2,n.x());
259  M.put(1,2,n.y());
260  M.put(2,2,n.z());
261 
262  vnl_matrix_inverse<T> R(M);
263 
264  // transform the polygon
265  vgl_polygon<T> poly2d(1); // with one sheet
266  for (it=poly.begin(); it != poly.end(); ++it) {
267  vgl_vector_3d<T> temp(*it-p0);
268  vnl_matrix<T> tv(3,1);
269  tv.put(0,0,temp.x());
270  tv.put(1,0,temp.y());
271  tv.put(2,0,temp.z());
272  vnl_matrix<T> pi = R*tv;
273  poly2d.push_back(pi.get(0,0), pi.get(1,0));
274  }
275 
277  vnl_matrix<T> tv(3,1);
278  tv.put(0,0,c.x()-p0.x());
279  tv.put(1,0,c.y()-p0.y());
280  tv.put(2,0,c.z()-p0.z());
281  vnl_matrix<T> ci(R*tv);
282  return poly2d.contains(ci.get(0,0),ci.get(1,0));
283 }
284 
285 #undef VGL_ALGO_INTERSECTION_INSTANTIATE
286 #define VGL_ALGO_INTERSECTION_INSTANTIATE(T) \
287 template vgl_point_3d<T > vgl_intersection(const std::vector<vgl_plane_3d<T > >&); \
288 template bool vgl_intersection(vgl_box_3d<T > const&, std::list<vgl_point_3d<T > >&); \
289 template vgl_infinite_line_3d<T > vgl_intersection(const std::list<vgl_plane_3d<T > >& planes); \
290 template bool vgl_intersection(const std::list<vgl_plane_3d<T > >& planes, std::vector<T > ws,vgl_infinite_line_3d<T >&,T& residual)
291 
292 #endif // vgl_algo_intersection_hxx_
Set of intersection functions.
homogeneous plane in 3D projective space
Set of intersection functions.
bool contains(point_t const &p) const
Returns true if p(x,y) is inside the polygon, else false.
Definition: vgl_polygon.h:81
bool is_empty() const
Return true if this box is empty.
Definition: vgl_box_3d.h:158
static vgl_homg_point_3d< Type > intersection(const vgl_homg_plane_3d< Type > &, const vgl_homg_plane_3d< Type > &, const vgl_homg_plane_3d< Type > &)
Compute best-fit intersection of planes in a point.
Direction vector in Euclidean 2D space, templated by type of element.
Definition: vgl_fwd.h:12
v & normalize(v &a)
Normalise by dividing through by the length, thus returning a length 1 vector.
vgl_vector_3d< T > normal() const
Return the normal direction, i.e., a unit vector orthogonal to this plane.
Definition: vgl_plane_3d.h:116
Contains class to represent a cartesian 3D bounding box.
vgl_point_3d< T > vgl_intersection(const std::vector< vgl_plane_3d< T > > &p)
Return the intersection point of vector of planes.
Type & z()
Definition: vgl_point_3d.h:73
#define v
Definition: vgl_vector_2d.h:74
void add(vgl_point_3d< Type > const &p)
Add a point to this box.
Definition: vgl_box_3d.hxx:373
a point in 3D nonhomogeneous space
T cross_product(v const &a, v const &b)
cross product of two vectors (area of enclosed parallellogram).
T y() const
Definition: vgl_vector_3d.h:37
void push_back(T x, T y)
Add a new point to the last sheet.
Definition: vgl_polygon.hxx:81
Represents a Euclidean 3D plane.
Definition: vgl_fwd.h:23
T x() const
Definition: vgl_vector_3d.h:36
vgl_point_3d< Type > centroid() const
Get the centroid point.
Definition: vgl_box_3d.hxx:148
T z() const
Definition: vgl_vector_3d.h:38
3D homogeneous functions
Type & x()
Definition: vgl_point_3d.h:71
Represents a 3-d line with position defined in the orthogonal plane passing through the origin.
Definition: vgl_fwd.h:20
Direction vector in Euclidean 3D space, templated by type of element.
Definition: vgl_fwd.h:13
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(Type px, Type py, Type pz)
Set x, y and z.
Definition: vgl_point_3d.h:81
a plane in 3D nonhomogeneous space
Represents a cartesian 3D box.
Definition: vgl_box_3d.h:65
Store a polygon.
Definition: vgl_area.h:6
Type & y()
Definition: vgl_point_3d.h:72