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
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
00060 vnl_vector<double> t = svd.nullvector();
00061 double tx = t[0], ty = t[1], tz = t[2];
00062
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:
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
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
00134 vnl_vector<double> t = svd.nullvector();
00135 double tx = t[0], ty = t[1], tz = t[2];
00136
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:
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
00188
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
00201 for (it=poly.begin(); it != poly.end(); ++it) {
00202 if (b.contains(*it))
00203 return true;
00204 }
00205
00206 it=poly.begin();
00207
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
00212 vgl_plane_3d<T> poly_plane(p0,p1,p2);
00213 if (!vgl_intersection<T>(b, poly_plane))
00214 return false;
00215
00216
00217
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
00238 vgl_polygon<T> poly2d(1);
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_