core/vgl/algo/vgl_intersection.txx
Go to the documentation of this file.
00001 // This is core/vgl/algo/vgl_intersection.txx
00002 #ifndef vgl_algo_intersection_txx_
00003 #define vgl_algo_intersection_txx_
00004 //:
00005 // \file
00006 // \author Gamze Tunali
00007 
00008 #include "vgl_intersection.h"
00009 
00010 #include <vgl/algo/vgl_homg_operators_3d.h>
00011 #include <vgl/vgl_plane_3d.h>
00012 #include <vgl/vgl_homg_plane_3d.h>
00013 #include <vgl/vgl_box_3d.h>
00014 #include <vgl/vgl_point_3d.h>
00015 #include <vgl/vgl_intersection.h>
00016 #include <vgl/vgl_polygon.h>
00017 
00018 #include <vnl/vnl_matrix.h>
00019 #include <vnl/vnl_vector.h>
00020 #include <vnl/algo/vnl_matrix_inverse.h>
00021 #include <vnl/algo/vnl_svd.h>
00022 
00023 #include <vcl_cassert.h>
00024 
00025 template <class T>
00026 vgl_point_3d<T> vgl_intersection(vcl_vector<vgl_plane_3d<T> > const& p)
00027 {
00028   vcl_vector<vgl_homg_plane_3d<T> > planes;
00029   for (unsigned i=0; i<p.size(); ++i) {
00030     planes.push_back(vgl_homg_plane_3d<T> (p[i]));
00031   }
00032 
00033   return vgl_homg_operators_3d<T>::intersection(planes);
00034 }
00035 
00036 
00037 template <class T>
00038 vgl_infinite_line_3d<T>
00039 vgl_intersection(const vcl_list<vgl_plane_3d<T> >& planes)
00040 {
00041   // form the matrix of plane normal monomials
00042   vnl_matrix<double> Q(3,3,0.0);
00043   vnl_vector<double> vd(3,0.0);
00044   unsigned n = planes.size();
00045   for (typename vcl_list<vgl_plane_3d<T> >::const_iterator pit = planes.begin();
00046        pit != planes.end(); ++pit)
00047   {
00048     double a = (*pit).a(), b = (*pit).b(), c = (*pit).c(),
00049       d = (*pit).d();
00050     Q[0][0] += a*a; Q[0][1] += a*b; Q[0][2] += a*c;
00051     Q[1][1] += b*b; Q[1][2] += b*c;
00052     Q[2][2] += c*c;
00053     vd[0]-=a*d; vd[1]-=b*d; vd[2]-=c*d;
00054   }
00055   Q[1][0]=  Q[0][1];   Q[2][0]= Q[0][2];   Q[2][1]=  Q[1][2];
00056   Q/=n;
00057   vd/=n;
00058   vnl_svd<double> svd(Q);
00059   // the direction of the resulting line
00060   vnl_vector<double> t = svd.nullvector();
00061   double tx = t[0], ty = t[1], tz = t[2];
00062   // determine maximum component of t
00063   char component = 'x';
00064   if (ty>tx&&ty>tz)
00065     component = 'y';
00066   if (tz>tx&&tz>ty)
00067     component = 'z';
00068   vgl_point_3d<double> p0d;
00069   switch (component)
00070   {
00071     case 'x':
00072     {
00073       double det = Q[1][1]*Q[2][2] - Q[1][2]*Q[2][1];
00074       double neuy = vd[1]*Q[2][2]  - Q[1][2]*vd[2];
00075       double neuz = Q[1][1]*vd[2]  - vd[1]*Q[2][1];
00076       p0d.set(0.0, neuy/det, neuz/det);
00077       break;
00078     }
00079     case 'y':
00080     {
00081       double det = Q[0][0]*Q[2][2] - Q[0][2]*Q[2][0];
00082       double neux = vd[0]*Q[2][2]  - Q[0][2]*vd[2];
00083       double neuz = Q[0][0]*vd[2]  - vd[0]*Q[2][0];
00084       p0d.set(neux/det, 0.0, neuz/det);
00085       break;
00086     }
00087     case 'z':
00088     {
00089       double det = Q[0][0]*Q[1][1] - Q[0][1]*Q[1][0];
00090       double neux = vd[0]*Q[1][1]  - Q[0][1]*vd[1];
00091       double neuy = Q[0][0]*vd[1]  - vd[0]*Q[1][0];
00092       p0d.set(neux/det, neuy/det, 0.0);
00093       break;
00094     }
00095     default: // this cannot happen
00096       break;
00097   }
00098   vgl_point_3d<T> pt(static_cast<T>(p0d.x()),
00099                      static_cast<T>(p0d.y()),
00100                      static_cast<T>(p0d.z()));
00101 
00102   vgl_vector_3d<T> tv(static_cast<T>(tx),
00103                       static_cast<T>(ty),
00104                       static_cast<T>(tz));
00105 
00106   return vgl_infinite_line_3d<T>(pt, tv);
00107 }
00108 
00109 template <class T>
00110 vgl_infinite_line_3d<T>
00111 vgl_intersection(const vcl_list<vgl_plane_3d<T> >& planes, vcl_vector<T> ws)
00112 {
00113   // form the matrix of plane normal monomials
00114   vnl_matrix<double> Q(3,3,0.0);
00115   vnl_vector<double> vd(3,0.0);
00116   unsigned cnt=0;
00117   T sum_ws=0;
00118   for (typename vcl_list<vgl_plane_3d<T> >::const_iterator pit = planes.begin();
00119        pit != planes.end(); ++pit)
00120   {
00121     double a = (*pit).a(), b = (*pit).b(), c = (*pit).c(), d = (*pit).d();
00122     T w=ws[cnt++];
00123     Q[0][0] += w*a*a;
00124     Q[0][1] += w*a*b; Q[1][1] += w*b*b;
00125     Q[0][2] += w*a*c; Q[1][2] += w*b*c; Q[2][2] += w*c*c;
00126     vd[0]-=w*a*d; vd[1]-=w*b*d; vd[2]-=w*c*d;
00127     sum_ws+=w;
00128   }
00129   Q[1][0]=  Q[0][1];   Q[2][0]= Q[0][2];   Q[2][1]=  Q[1][2];
00130   Q/=sum_ws;
00131   vd/=sum_ws;
00132   vnl_svd<double> svd(Q);
00133   // the direction of the resulting line
00134   vnl_vector<double> t = svd.nullvector();
00135   double tx = t[0], ty = t[1], tz = t[2];
00136   // determine maximum component of t
00137   char component = 'x';
00138   if (ty>tx&&ty>tz)
00139     component = 'y';
00140   if (tz>tx&&tz>ty)
00141     component = 'z';
00142   vgl_point_3d<double> p0d;
00143   switch (component)
00144   {
00145     case 'x':
00146     {
00147       double det = Q[1][1]*Q[2][2] - Q[1][2]*Q[2][1];
00148       double neuy = vd[1]*Q[2][2]  - Q[1][2]*vd[2];
00149       double neuz = Q[1][1]*vd[2]  - vd[1]*Q[2][1];
00150       p0d.set(0.0, neuy/det, neuz/det);
00151       break;
00152     }
00153     case 'y':
00154     {
00155       double det = Q[0][0]*Q[2][2] - Q[0][2]*Q[2][0];
00156       double neux = vd[0]*Q[2][2]  - Q[0][2]*vd[2];
00157       double neuz = Q[0][0]*vd[2]  - vd[0]*Q[2][0];
00158       p0d.set(neux/det, 0.0, neuz/det);
00159       break;
00160     }
00161     case 'z':
00162     {
00163       double det = Q[0][0]*Q[1][1] - Q[0][1]*Q[1][0];
00164       double neux = vd[0]*Q[1][1]  - Q[0][1]*vd[1];
00165       double neuy = Q[0][0]*vd[1]  - vd[0]*Q[1][0];
00166       p0d.set(neux/det, neuy/det, 0.0);
00167       break;
00168     }
00169     default: // this cannot happen
00170       break;
00171   }
00172   vgl_point_3d<T> pt(static_cast<T>(p0d.x()),
00173                      static_cast<T>(p0d.y()),
00174                      static_cast<T>(p0d.z()));
00175 
00176   vgl_vector_3d<T> tv(static_cast<T>(tx),
00177                       static_cast<T>(ty),
00178                       static_cast<T>(tz));
00179 
00180   return vgl_infinite_line_3d<T>(pt, tv);
00181 }
00182 
00183 
00184 template <class T>
00185 bool vgl_intersection(vgl_box_3d<T> const& b, vcl_list<vgl_point_3d<T> >& poly)
00186 {
00187   // check if two bounding boxes intersect
00188   // find the bounding box of the polygon
00189   assert(poly.size() >= 3);
00190 
00191   vgl_box_3d<T> bb;
00192   typename vcl_list<vgl_point_3d<T> >::iterator it=poly.begin();
00193   for (; it != poly.end(); ++it)
00194     bb.add(*it);
00195 
00196   vgl_box_3d<T> inters = vgl_intersection(b, bb);
00197   if (inters.is_empty())
00198     return false;
00199 
00200   // check if the polygon corners inside the box
00201   for (it=poly.begin(); it != poly.end(); ++it) {
00202     if (b.contains(*it))
00203       return true;
00204   }
00205 
00206   it=poly.begin();
00207   // get the first 3 points to create a plane
00208   vgl_point_3d<T> p0=*it; ++it;
00209   vgl_point_3d<T> p1=*it; ++it;
00210   vgl_point_3d<T> p2=*it; ++it;
00211   // create a plane from polygon
00212   vgl_plane_3d<T> poly_plane(p0,p1,p2);
00213   if (!vgl_intersection<T>(b, poly_plane))
00214     return false;
00215 
00216   // now we do a 3D transformation of the polygon and the box center to the plane
00217   // where polygon resides, so that we can do 2D poly-point test
00218   vgl_vector_3d<T> n = poly_plane.normal();
00219   n=normalize(n);
00220   vgl_vector_3d<T> u(p1-p0);
00221   u=normalize(u);
00222   vgl_vector_3d<T> v = cross_product(n,u);
00223 
00224   vnl_matrix<T> M(3,3);
00225   M.put(0,0,u.x());
00226   M.put(1,0,u.y());
00227   M.put(2,0,u.z());
00228   M.put(0,1,v.x());
00229   M.put(1,1,v.y());
00230   M.put(2,1,v.z());
00231   M.put(0,2,n.x());
00232   M.put(1,2,n.y());
00233   M.put(2,2,n.z());
00234 
00235   vnl_matrix_inverse<T> R(M);
00236 
00237   // transform the polygon
00238   vgl_polygon<T> poly2d(1);  // with one sheet
00239   for (it=poly.begin(); it != poly.end(); ++it) {
00240     vgl_vector_3d<T> temp(*it-p0);
00241     vnl_matrix<T> tv(3,1);
00242     tv.put(0,0,temp.x());
00243     tv.put(1,0,temp.y());
00244     tv.put(2,0,temp.z());
00245     vnl_matrix<T> pi = R*tv;
00246     poly2d.push_back(pi.get(0,0), pi.get(1,0));
00247   }
00248 
00249   vgl_point_3d<T> c=b.centroid();
00250   vnl_matrix<T> tv(3,1);
00251   tv.put(0,0,c.x()-p0.x());
00252   tv.put(1,0,c.y()-p0.y());
00253   tv.put(2,0,c.z()-p0.z());
00254   vnl_matrix<T> ci(R*tv);
00255   return poly2d.contains(ci.get(0,0),ci.get(1,0));
00256 }
00257 
00258 #undef VGL_ALGO_INTERSECTION_INSTANTIATE
00259 #define VGL_ALGO_INTERSECTION_INSTANTIATE(T) \
00260 template vgl_point_3d<T > vgl_intersection(const vcl_vector<vgl_plane_3d<T > >&); \
00261 template bool vgl_intersection(vgl_box_3d<T > const&, vcl_list<vgl_point_3d<T > >&); \
00262 template vgl_infinite_line_3d<T > vgl_intersection(const vcl_list<vgl_plane_3d<T > >& planes);\
00263 template vgl_infinite_line_3d<T > vgl_intersection(const vcl_list<vgl_plane_3d<T > >& planes, vcl_vector<T > ws)
00264 
00265 #endif // vgl_algo_intersection_txx_