00001
00002 #ifndef vgl_algo_intersection_txx_
00003 #define vgl_algo_intersection_txx_
00004
00005
00006
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 if (planes.size() == 0)
00042 return vgl_infinite_line_3d<T>(vgl_vector_2d<T>(0,0),vgl_vector_3d<T>(0,0,0));
00043
00044
00045 vnl_matrix<double> Q(3,3,0.0);
00046 vnl_vector<double> vd(3,0.0);
00047 unsigned n = planes.size();
00048 for (typename vcl_list<vgl_plane_3d<T> >::const_iterator pit = planes.begin();
00049 pit != planes.end(); ++pit)
00050 {
00051 double a = (*pit).a(), b = (*pit).b(), c = (*pit).c(),d = (*pit).d();
00052 Q[0][0] += a*a; Q[0][1] += a*b; Q[0][2] += a*c;
00053 Q[1][1] += b*b; Q[1][2] += b*c;
00054 Q[2][2] += c*c;
00055 vd[0]-=a*d; vd[1]-=b*d; vd[2]-=c*d;
00056 }
00057 Q[1][0]= Q[0][1]; Q[2][0]= Q[0][2]; Q[2][1]= Q[1][2];
00058 Q/=n;
00059 vd/=n;
00060 vnl_svd<double> svd(Q);
00061
00062
00063 vnl_vector<double> t = svd.nullvector();
00064
00065 double tx = t[0], ty = t[1], tz = t[2];
00066
00067
00068 char component = 'x';
00069 if (ty>tx&&ty>tz)
00070 component = 'y';
00071 if (tz>tx&&tz>ty)
00072 component = 'z';
00073 vgl_point_3d<double> p0d;
00074 switch (component)
00075 {
00076 case 'x':
00077 {
00078 double det = Q[1][1]*Q[2][2] - Q[1][2]*Q[2][1];
00079 double neuy = vd[1]*Q[2][2] - Q[1][2]*vd[2];
00080 double neuz = Q[1][1]*vd[2] - vd[1]*Q[2][1];
00081 p0d.set(0.0, neuy/det, neuz/det);
00082 break;
00083 }
00084 case 'y':
00085 {
00086 double det = Q[0][0]*Q[2][2] - Q[0][2]*Q[2][0];
00087 double neux = vd[0]*Q[2][2] - Q[0][2]*vd[2];
00088 double neuz = Q[0][0]*vd[2] - vd[0]*Q[2][0];
00089 p0d.set(neux/det, 0.0, neuz/det);
00090 break;
00091 }
00092 case 'z':
00093 default:
00094 {
00095 double det = Q[0][0]*Q[1][1] - Q[0][1]*Q[1][0];
00096 double neux = vd[0]*Q[1][1] - Q[0][1]*vd[1];
00097 double neuy = Q[0][0]*vd[1] - vd[0]*Q[1][0];
00098 p0d.set(neux/det, neuy/det, 0.0);
00099 break;
00100 }
00101 }
00102 vgl_point_3d<T> pt(static_cast<T>(p0d.x()),
00103 static_cast<T>(p0d.y()),
00104 static_cast<T>(p0d.z()));
00105
00106 vgl_vector_3d<T> tv(static_cast<T>(tx),
00107 static_cast<T>(ty),
00108 static_cast<T>(tz));
00109
00110 return vgl_infinite_line_3d<T>(pt, tv);
00111 }
00112
00113 template <class T>
00114 bool
00115 vgl_intersection(const vcl_list<vgl_plane_3d<T> >& planes, vcl_vector<T> ws,
00116 vgl_infinite_line_3d<T>& line, T &residual)
00117 {
00118 if (planes.size() < 2)
00119 return false;
00120
00121 vnl_matrix<double> Q(3,3,0.0);
00122 vnl_vector<double> vd(3,0.0);
00123 unsigned cnt=0;
00124 T sum_ws=0;
00125 for (typename vcl_list<vgl_plane_3d<T> >::const_iterator pit = planes.begin();
00126 pit != planes.end(); ++pit)
00127 {
00128 double a = (*pit).a(), b = (*pit).b(), c = (*pit).c(), d = (*pit).d();
00129 T w=ws[cnt++];
00130 Q[0][0] += w*a*a;
00131 Q[0][1] += w*a*b; Q[1][1] += w*b*b;
00132 Q[0][2] += w*a*c; Q[1][2] += w*b*c; Q[2][2] += w*c*c;
00133 vd[0]-=w*a*d; vd[1]-=w*b*d; vd[2]-=w*c*d;
00134 sum_ws+=w;
00135 }
00136 Q[1][0]= Q[0][1]; Q[2][0]= Q[0][2]; Q[2][1]= Q[1][2];
00137 Q/=sum_ws;
00138 vd/=sum_ws;
00139 vnl_svd<double> svd(Q);
00140
00141 vnl_vector<double> t = svd.nullvector();
00142 double tx = t[0], ty = t[1], tz = t[2];
00143
00144 char component = 'x';
00145 if (ty>tx&&ty>tz)
00146 component = 'y';
00147 if (tz>tx&&tz>ty)
00148 component = 'z';
00149 vgl_point_3d<double> p0d;
00150 switch (component)
00151 {
00152 case 'x':
00153 {
00154 double det = Q[1][1]*Q[2][2] - Q[1][2]*Q[2][1];
00155 double neuy = vd[1]*Q[2][2] - Q[1][2]*vd[2];
00156 double neuz = Q[1][1]*vd[2] - vd[1]*Q[2][1];
00157 p0d.set(0.0, neuy/det, neuz/det);
00158 break;
00159 }
00160 case 'y':
00161 {
00162 double det = Q[0][0]*Q[2][2] - Q[0][2]*Q[2][0];
00163 double neux = vd[0]*Q[2][2] - Q[0][2]*vd[2];
00164 double neuz = Q[0][0]*vd[2] - vd[0]*Q[2][0];
00165 p0d.set(neux/det, 0.0, neuz/det);
00166 break;
00167 }
00168 case 'z':
00169 default:
00170 {
00171 double det = Q[0][0]*Q[1][1] - Q[0][1]*Q[1][0];
00172 double neux = vd[0]*Q[1][1] - Q[0][1]*vd[1];
00173 double neuy = Q[0][0]*vd[1] - vd[0]*Q[1][0];
00174 p0d.set(neux/det, neuy/det, 0.0);
00175 break;
00176 }
00177 }
00178 vgl_point_3d<T> pt(static_cast<T>(p0d.x()),
00179 static_cast<T>(p0d.y()),
00180 static_cast<T>(p0d.z()));
00181
00182 vgl_vector_3d<T> tv(static_cast<T>(tx),
00183 static_cast<T>(ty),
00184 static_cast<T>(tz));
00185 residual=T(0);
00186 sum_ws=0;
00187 cnt=0;
00188 for (typename vcl_list<vgl_plane_3d<T> >::const_iterator pit = planes.begin();
00189 pit != planes.end(); ++pit)
00190 {
00191 double a = pit->normal().x(), b = pit->normal().y(), c = pit->normal().z();
00192 residual+=ws[cnt]*ws[cnt]*T(a*tx+b*ty+c*tz)*T(a*tx+b*ty+c*tz);
00193 sum_ws+=ws[cnt]*ws[cnt];
00194 cnt++;
00195 }
00196
00197 if (cnt>0)
00198 {
00199 residual/=sum_ws;
00200 residual=vcl_sqrt(residual);
00201 }
00202 line=vgl_infinite_line_3d<T>(pt, tv);
00203 return true;
00204 }
00205
00206
00207 template <class T>
00208 bool vgl_intersection(vgl_box_3d<T> const& b, vcl_list<vgl_point_3d<T> >& poly)
00209 {
00210
00211
00212 assert(poly.size() >= 3);
00213
00214 vgl_box_3d<T> bb;
00215 typename vcl_list<vgl_point_3d<T> >::iterator it=poly.begin();
00216 for (; it != poly.end(); ++it)
00217 bb.add(*it);
00218
00219 vgl_box_3d<T> inters = vgl_intersection(b, bb);
00220 if (inters.is_empty())
00221 return false;
00222
00223
00224 for (it=poly.begin(); it != poly.end(); ++it) {
00225 if (b.contains(*it))
00226 return true;
00227 }
00228
00229 it=poly.begin();
00230
00231 vgl_point_3d<T> p0=*it; ++it;
00232 vgl_point_3d<T> p1=*it; ++it;
00233 vgl_point_3d<T> p2=*it; ++it;
00234
00235 vgl_plane_3d<T> poly_plane(p0,p1,p2);
00236 if (!vgl_intersection<T>(b, poly_plane))
00237 return false;
00238
00239
00240
00241 vgl_vector_3d<T> n = poly_plane.normal();
00242 n=normalize(n);
00243 vgl_vector_3d<T> u(p1-p0);
00244 u=normalize(u);
00245 vgl_vector_3d<T> v = cross_product(n,u);
00246
00247 vnl_matrix<T> M(3,3);
00248 M.put(0,0,u.x());
00249 M.put(1,0,u.y());
00250 M.put(2,0,u.z());
00251 M.put(0,1,v.x());
00252 M.put(1,1,v.y());
00253 M.put(2,1,v.z());
00254 M.put(0,2,n.x());
00255 M.put(1,2,n.y());
00256 M.put(2,2,n.z());
00257
00258 vnl_matrix_inverse<T> R(M);
00259
00260
00261 vgl_polygon<T> poly2d(1);
00262 for (it=poly.begin(); it != poly.end(); ++it) {
00263 vgl_vector_3d<T> temp(*it-p0);
00264 vnl_matrix<T> tv(3,1);
00265 tv.put(0,0,temp.x());
00266 tv.put(1,0,temp.y());
00267 tv.put(2,0,temp.z());
00268 vnl_matrix<T> pi = R*tv;
00269 poly2d.push_back(pi.get(0,0), pi.get(1,0));
00270 }
00271
00272 vgl_point_3d<T> c=b.centroid();
00273 vnl_matrix<T> tv(3,1);
00274 tv.put(0,0,c.x()-p0.x());
00275 tv.put(1,0,c.y()-p0.y());
00276 tv.put(2,0,c.z()-p0.z());
00277 vnl_matrix<T> ci(R*tv);
00278 return poly2d.contains(ci.get(0,0),ci.get(1,0));
00279 }
00280
00281 #undef VGL_ALGO_INTERSECTION_INSTANTIATE
00282 #define VGL_ALGO_INTERSECTION_INSTANTIATE(T) \
00283 template vgl_point_3d<T > vgl_intersection(const vcl_vector<vgl_plane_3d<T > >&); \
00284 template bool vgl_intersection(vgl_box_3d<T > const&, vcl_list<vgl_point_3d<T > >&); \
00285 template vgl_infinite_line_3d<T > vgl_intersection(const vcl_list<vgl_plane_3d<T > >& planes); \
00286 template bool vgl_intersection(const vcl_list<vgl_plane_3d<T > >& planes, vcl_vector<T > ws,vgl_infinite_line_3d<T >&,T& residual)
00287
00288 #endif // vgl_algo_intersection_txx_