core/vgl/vgl_intersection.txx
Go to the documentation of this file.
00001 // This is core/vgl/vgl_intersection.txx
00002 #ifndef vgl_intersection_txx_
00003 #define vgl_intersection_txx_
00004 //:
00005 // \file
00006 // \author Gamze Tunali
00007 
00008 #include "vgl_intersection.h"
00009 
00010 #include <vcl_limits.h>
00011 #include <vcl_cassert.h>
00012 #include <vcl_cmath.h>
00013 #include <vgl/vgl_point_2d.h>
00014 #include <vgl/vgl_line_2d.h>
00015 #include <vgl/vgl_line_3d_2_points.h>
00016 #include <vgl/vgl_line_segment_2d.h>
00017 #include <vgl/vgl_line_segment_3d.h>
00018 #include <vgl/vgl_vector_3d.h>
00019 #include <vgl/vgl_box_2d.h>
00020 #include <vgl/vgl_box_3d.h>
00021 #include <vgl/vgl_polygon.h>
00022 #include <vgl/vgl_plane_3d.h>
00023 #include <vgl/vgl_distance.h>
00024 #include <vgl/vgl_tolerance.h>
00025 #include <vgl/vgl_lineseg_test.h>
00026 #include <vcl_vector.h>
00027 
00028 static double eps = 1.0e-8; // tolerance for intersections
00029 inline bool vgl_near_zero(double x) { return x < eps && x > -eps; }
00030 inline bool vgl_near_eq(double x, double y) { return vgl_near_zero(x-y); }
00031 
00032 //: Return the intersection of two boxes (which is itself is a box, possibly the empty box)
00033 // \relatesalso vgl_box_2d
00034 template <class T>
00035 vgl_box_2d<T> vgl_intersection(vgl_box_2d<T> const& b1,vgl_box_2d<T> const& b2)
00036 {
00037   T xmin = b1.min_x() > b2.min_x() ? b1.min_x() : b2.min_x();
00038   T ymin = b1.min_y() > b2.min_y() ? b1.min_y() : b2.min_y();
00039   T xmax = b1.max_x() < b2.max_x() ? b1.max_x() : b2.max_x();
00040   T ymax = b1.max_y() < b2.max_y() ? b1.max_y() : b2.max_y();
00041   return vgl_box_2d<T>(xmin,xmax,ymin,ymax);
00042 }
00043 
00044 //: Return true if line intersects box. If so, compute intersection points.
00045 // \relatesalso vgl_box_3d
00046 // \relatesalso vgl_infinite_line_3d
00047 template <class T>
00048 bool vgl_intersection(vgl_box_3d<T> const& box,
00049                       vgl_infinite_line_3d<T> const& line_3d,
00050                       vgl_point_3d<T>& p0,
00051                       vgl_point_3d<T>& p1)
00052 {
00053   vgl_point_3d<T> lpt = line_3d.point();
00054   vgl_vector_3d<T> di = line_3d.direction();
00055   vgl_point_3d<double> dpt(static_cast<double>(lpt.x()),
00056                            static_cast<double>(lpt.y()),
00057                            static_cast<double>(lpt.z()));
00058   vgl_vector_3d<double> dir(static_cast<double>(di.x()),
00059                             static_cast<double>(di.y()),
00060                             static_cast<double>(di.z()));
00061   vgl_infinite_line_3d<double> dline_3d(dpt, dir);
00062   // expand box by epsilon tolerance
00063   double xmin = box.min_x()-eps, xmax = box.max_x()+eps,
00064          ymin = box.min_y()-eps, ymax = box.max_y()+eps,
00065          zmin = box.min_z()-eps, zmax = box.max_z()+eps;
00066   vgl_point_3d<double> minp(xmin, ymin, zmin), maxp(xmax, ymax, zmax);
00067   // find intersection point of the line with each of the six box planes
00068   vgl_vector_3d<double> vxmin(-1.0, 0.0, 0.0), vxmax(1.0, 0.0, 0.0),
00069                         vymin(0.0, -1.0, 0.0), vymax(0.0, 1.0, 0.0),
00070                         vzmin(0.0, 0.0, -1.0), vzmax(0.0, 0.0, 1.0);
00071   vgl_plane_3d<double> pl_xmin(vxmin, minp),
00072                        pl_xmax(vxmax, maxp),
00073                        pl_ymin(vymin, minp),
00074                        pl_ymax(vymax, maxp),
00075                        pl_zmin(vzmin, minp),
00076                        pl_zmax(vzmax, maxp);
00077   vgl_point_3d<double> pt_xmin(.0,.0,.0), pt_xmax(.0,.0,.0), // dummy initializ.
00078                        pt_ymin(.0,.0,.0), pt_ymax(.0,.0,.0), // to avoid
00079                        pt_zmin(.0,.0,.0), pt_zmax(.0,.0,.0); // compiler warning
00080   bool xmin_good = vgl_intersection(dline_3d, pl_xmin, pt_xmin);
00081   bool xmax_good = vgl_intersection(dline_3d, pl_xmax, pt_xmax);
00082   bool ymin_good = vgl_intersection(dline_3d, pl_ymin, pt_ymin);
00083   bool ymax_good = vgl_intersection(dline_3d, pl_ymax, pt_ymax);
00084   bool zmin_good = vgl_intersection(dline_3d, pl_zmin, pt_zmin);
00085   bool zmax_good = vgl_intersection(dline_3d, pl_zmax, pt_zmax);
00086   // Go through the six cases and return the two intersection points
00087   // that lie on box faces. Find the pair that are farthest apart.
00088   // There could be multiple intersections if the line passes through the
00089   // corners of the box.
00090   unsigned npts = 0;
00091   vgl_point_3d<double> dp0=pt_xmin, dp1=pt_xmax; // keep this initialisation!
00092 
00093   // y-z face at xmin
00094   if (xmin_good &&
00095       pt_xmin.y()>=ymin && pt_xmin.y()<=ymax &&
00096       pt_xmin.z()>=zmin && pt_xmin.z()<=zmax)
00097   {
00098     // dp0 = pt_xmin; // not needed: already set when dp0 was initialised
00099     ++npts;
00100   }
00101   // y-z face at xmax
00102   if (xmax_good &&
00103       pt_xmax.y()>=ymin && pt_xmax.y()<=ymax &&
00104       pt_xmax.z()>=zmin && pt_xmax.z()<=zmax)
00105   {
00106     if  (npts == 0) dp0 = pt_xmax;
00107     // else         dp1 = pt_xmax; // not needed: already set when dp1 was initialised
00108     ++npts;
00109   }
00110   // x-z face at ymin
00111   if (ymin_good &&
00112       pt_ymin.x()>=xmin && pt_ymin.x()<=xmax &&
00113       pt_ymin.z()>=zmin && pt_ymin.z()<=zmax)
00114   {
00115     if      (npts == 0) { dp0 = pt_ymin; ++npts; }
00116     else if (npts == 1) { dp1 = pt_ymin; ++npts; }
00117     else /* npts == 2*/ if (sqr_length(pt_ymin-dp0)>sqr_length(dp1-dp0)) dp1 = pt_ymin;
00118   }
00119   // x-z face at ymax
00120   if (ymax_good &&
00121       pt_ymax.x()>=xmin && pt_ymax.x()<=xmax &&
00122       pt_ymax.z()>=zmin && pt_ymax.z()<=zmax)
00123   {
00124     if      (npts == 0) { dp0 = pt_ymax; ++npts; }
00125     else if (npts == 1) { dp1 = pt_ymax; ++npts; }
00126     else /* npts == 2*/ if (sqr_length(pt_ymax-dp0)>sqr_length(dp1-dp0)) dp1 = pt_ymax;
00127   }
00128   // x-y face at zmin
00129   if (zmin_good &&
00130       pt_zmin.x()>=xmin && pt_zmin.x()<=xmax &&
00131       pt_zmin.y()>=ymin && pt_zmin.y()<=ymax)
00132   {
00133     if      (npts == 0) { dp0 = pt_zmin; ++npts; }
00134     else if (npts == 1) { dp1 = pt_zmin; ++npts; }
00135     else /* npts == 2*/ if (sqr_length(pt_zmin-dp0)>sqr_length(dp1-dp0)) dp1 = pt_zmin;
00136   }
00137 
00138   // x-y face at zmax
00139   if (zmax_good &&
00140       pt_zmax.x()>=xmin && pt_zmax.x()<=xmax &&
00141       pt_zmax.y()>=ymin && pt_zmax.y()<=ymax)
00142   {
00143     if      (npts == 0) { dp0 = pt_zmax; ++npts; }
00144     else if (npts == 1) { dp1 = pt_zmax; ++npts; }
00145     else /* npts == 2*/ if (sqr_length(pt_zmax-dp0)>sqr_length(dp1-dp0)) dp1 = pt_zmax;
00146   }
00147 
00148   if (npts==2) {
00149     p0.set(static_cast<T>(dp0.x()),
00150            static_cast<T>(dp0.y()),
00151            static_cast<T>(dp0.z()));
00152     p1.set(static_cast<T>(dp1.x()),
00153            static_cast<T>(dp1.y()),
00154            static_cast<T>(dp1.z()));
00155     return true;
00156   }
00157   else
00158     return false;
00159 }
00160 
00161 //: Return true if a box and plane intersect in 3D
00162 // \relatesalso vgl_plane_3d
00163 // \relatesalso vgl_box_3d
00164 template <class T>
00165 bool vgl_intersection(vgl_box_3d<T> const& b, vgl_plane_3d<T> const& plane)
00166 {
00167   // find the box corners
00168   vcl_vector<vgl_point_3d<T> > corners;
00169   corners.push_back(b.min_point());
00170   corners.push_back(vgl_point_3d<T> (b.min_x()+b.width(), b.min_y(), b.min_z()));
00171   corners.push_back(vgl_point_3d<T> (b.min_x()+b.width(), b.min_y()+b.height(), b.min_z()));
00172   corners.push_back(vgl_point_3d<T> (b.min_x(), b.min_y()+b.height(), b.min_z()));
00173   corners.push_back(vgl_point_3d<T> (b.min_x(), b.min_y(), b.max_z()));
00174   corners.push_back(vgl_point_3d<T> (b.min_x()+b.width(), b.min_y(), b.max_z()));
00175   corners.push_back(b.max_point());
00176   corners.push_back(vgl_point_3d<T> (b.min_x(), b.min_y()+b.height(), b.max_z()));
00177 
00178   // find the signed distance from the box corners to the plane
00179   int pos=0, neg=0;
00180   for (unsigned c=0; c<corners.size(); c++) {
00181     vgl_point_3d<T> corner=corners[c];
00182     double d=(plane.a()*corner.x());
00183     d+=(plane.b()*corner.y());
00184     d+=(plane.c()*corner.z());
00185     d+=plane.d();
00186     if (d > 0)
00187       pos++;
00188     else if (d<0)
00189       neg++;
00190   }
00191   return neg!=8 && pos!=8; // completely inside polygon plane
00192 }
00193 
00194 //: Return the intersection of two boxes (which is itself either a box, or empty)
00195 // \relatesalso vgl_box_3d
00196 template <class T>
00197 vgl_box_3d<T> vgl_intersection(vgl_box_3d<T> const& b1,vgl_box_3d<T> const& b2)
00198 {
00199   T xmin = b1.min_x() > b2.min_x() ? b1.min_x() : b2.min_x();
00200   T ymin = b1.min_y() > b2.min_y() ? b1.min_y() : b2.min_y();
00201   T zmin = b1.min_z() > b2.min_z() ? b1.min_z() : b2.min_z();
00202   T xmax = b1.max_x() < b2.max_x() ? b1.max_x() : b2.max_x();
00203   T ymax = b1.max_y() < b2.max_y() ? b1.max_y() : b2.max_y();
00204   T zmax = b1.max_z() < b2.max_z() ? b1.max_z() : b2.max_z();
00205   return vgl_box_3d<T>(xmin,ymin,zmin,xmax,ymax,zmax);
00206 }
00207 
00208 //: compute the intersection of an infinite line with *this box.
00209 //  p0 and p1 are the intersection points
00210 // In the normal case (no degeneracies) there are six possible intersection combinations:
00211 // \verbatim
00212 //
00213 //                C01 /    CY     \ C11
00214 //                   /     |       \           .
00215 //       ymax  -----/------|--------\-----
00216 //            |    /       |         \    |
00217 //            |   /        |          \   |
00218 //            |  /         |           \  | \  .
00219 //            | /          |            \ |  \_ Bounding Box
00220 //            |/           |             \|
00221 //            /            |              \    .
00222 //           /|            |              |\   .
00223 //           ---------------------------------- CX
00224 //          \ |            |              /
00225 //           \|            |             /|
00226 //            \            |            / |
00227 //            |\           |           /  |
00228 //            | \          |          /   |
00229 //            |  \         |         /    |
00230 //       xmin  ---\--------|--------/-----   xmax
00231 //       ymin      \       |       /
00232 //              C00 \             / C10
00233 // \endverbatim
00234 
00235 template <class Type>
00236 bool vgl_intersection(const vgl_box_2d<Type>& box,
00237                       const vgl_line_2d<Type>& line,
00238                       vgl_point_2d<Type>& p0,
00239                       vgl_point_2d<Type>& p1)
00240 {
00241   double a = line.a(), b = line.b(), c = line.c();
00242   double xmin=box.min_x(), xmax=box.max_x();
00243   double ymin=box.min_y(), ymax=box.max_y();
00244 
00245   // Run through the cases
00246   //
00247   if (vgl_near_zero(a))// The line is y = -c/b
00248   {
00249     float y0 = static_cast<float>(-c/b);
00250     // The box edge is collinear with line?
00251     if (vgl_near_eq(ymin,y0))
00252     {
00253       p0.set(static_cast<Type>(xmin), static_cast<Type>(ymin));
00254       p1.set(static_cast<Type>(xmax), static_cast<Type>(ymin));
00255       return true;
00256     }
00257     if (vgl_near_eq(ymax,y0))
00258     {
00259       p0.set(static_cast<Type>(xmin), static_cast<Type>(ymax));
00260       p1.set(static_cast<Type>(xmax), static_cast<Type>(ymax));
00261       return true;
00262     }
00263 
00264     if ((ymin > y0) || (y0 > ymax)) // The line does not intersect the box
00265       return false;
00266     else // The line does intersect
00267     {
00268       p0.set(static_cast<Type>(xmin), static_cast<Type>(y0));
00269       p1.set(static_cast<Type>(xmax), static_cast<Type>(y0));
00270       return true;
00271     }
00272   }
00273 
00274   if (vgl_near_zero(b))// The line is x = -c/a
00275   {
00276     float x0 = static_cast<float>(-c/a);
00277     // The box edge is collinar with l?
00278     if (vgl_near_eq(xmin,x0))
00279     {
00280       p0.set(static_cast<Type>(xmin), static_cast<Type>(ymin));
00281       p1.set(static_cast<Type>(xmin), static_cast<Type>(ymax));
00282       return true;
00283     }
00284     if (vgl_near_eq(xmax,x0))
00285     {
00286       p0.set(static_cast<Type>(xmax), static_cast<Type>(ymin));
00287       p1.set(static_cast<Type>(xmax), static_cast<Type>(ymax));
00288       return true;
00289     }
00290 
00291     if (xmin <= x0 && x0 <= xmax) // The line intersects the box
00292     {
00293       p0.set(static_cast<Type>(x0), static_cast<Type>(ymin));
00294       p1.set(static_cast<Type>(x0), static_cast<Type>(ymax));
00295       return true;
00296     }
00297     else
00298       return false;
00299   }
00300 
00301   // The normal case with no degeneracies
00302   //
00303   // Intersection with x = xmin
00304   float y_xmin_int = static_cast<float>(-(c + a*xmin)/b);
00305   bool inside_xmin = (y_xmin_int >= ymin) && (y_xmin_int <= ymax);
00306 
00307   // Intersection with x = xmax
00308   float y_xmax_int = static_cast<float>(-(c + a*xmax)/b);
00309   bool inside_xmax = (y_xmax_int >= ymin) && (y_xmax_int <= ymax);
00310 
00311   // Intersection with y = ymin
00312   float x_ymin_int = static_cast<float>(-(c + b*ymin)/a);
00313   bool inside_ymin = (x_ymin_int >= xmin) && (x_ymin_int <= xmax);
00314 
00315   // Intersection with y = ymax
00316   float x_ymax_int = static_cast<float>(-(c + b*ymax)/a);
00317   bool inside_ymax = (x_ymax_int >= xmin) && (x_ymax_int <= xmax);
00318 
00319   // Case CX
00320   if (inside_xmin && inside_xmax &&
00321       !(vgl_near_eq(y_xmin_int,ymin) && vgl_near_eq(y_xmax_int,ymax)))
00322   {
00323     p0.set(static_cast<Type>(xmin), static_cast<Type>(y_xmin_int));
00324     p1.set(static_cast<Type>(xmax), static_cast<Type>(y_xmax_int));
00325     return true;
00326   }
00327 
00328   // Case CY
00329   if (inside_ymin && inside_ymax &&
00330       !(vgl_near_eq(x_ymin_int,xmin) && vgl_near_eq(x_ymax_int,xmax)))
00331   {
00332     p0.set(static_cast<Type>(x_ymin_int), static_cast<Type>(ymin));
00333     p1.set(static_cast<Type>(x_ymax_int), static_cast<Type>(ymax));
00334     return true;
00335   }
00336 
00337   // Case C00
00338   if (inside_xmin && inside_ymin &&
00339       !(inside_xmax && inside_ymax))
00340   {
00341     p0.set(static_cast<Type>(xmin), static_cast<Type>(y_xmin_int));
00342     p1.set(static_cast<Type>(x_ymin_int), static_cast<Type>(ymin));
00343     return true;
00344   }
00345 
00346   // Case C01
00347   if (inside_xmin && inside_ymax &&
00348       !(inside_xmax && inside_ymin))
00349   {
00350     p0.set(static_cast<Type>(xmin), static_cast<Type>(y_xmin_int));
00351     p1.set(static_cast<Type>(x_ymax_int), static_cast<Type>(ymax));
00352     return true;
00353   }
00354 
00355   // Case C10
00356   if (inside_ymin && inside_xmax &&
00357       !(inside_xmin && inside_ymax))
00358   {
00359     p0.set(static_cast<Type>(x_ymin_int), static_cast<Type>(ymin));
00360     p1.set(static_cast<Type>(xmax), static_cast<Type>(y_xmax_int));
00361     return true;
00362   }
00363 
00364   // Case C11
00365   if (inside_ymax && inside_xmax &&
00366       !(inside_xmin && inside_ymin))
00367   {
00368     p0.set(static_cast<Type>(x_ymax_int), static_cast<Type>(ymax));
00369     p1.set(static_cast<Type>(xmax), static_cast<Type>(y_xmax_int));
00370     return true;
00371   }
00372   // Exactly passing through diagonal of BB
00373   if (inside_xmin && inside_xmax && inside_ymin && inside_ymax)
00374   {
00375     if (a>0) // 45 degrees
00376     {
00377       p0.set(static_cast<Type>(xmin), static_cast<Type>(ymin));
00378       p1.set(static_cast<Type>(xmax), static_cast<Type>(ymax));
00379       return true;
00380     }
00381     else // 135 degrees
00382     {
00383       p0.set(static_cast<Type>(xmin), static_cast<Type>(ymax));
00384       p1.set(static_cast<Type>(xmax), static_cast<Type>(ymin));
00385       return true;
00386     }
00387   }
00388   return false;
00389 }
00390 
00391 //: Returns the number of intersections of a line segment with a box, up to two are returned in p0 and p1.
00392 template <class Type>
00393 unsigned vgl_intersection(const vgl_box_2d<Type>& box,
00394                           const vgl_line_segment_2d<Type>& line_seg,
00395                           vgl_point_2d<Type>& p0,
00396                           vgl_point_2d<Type>& p1)
00397 {
00398   vgl_line_2d<Type> line(line_seg.a(), line_seg.b(), line_seg.c());
00399   vgl_point_2d<Type> pi0, pi1;
00400   // if no intersection just return
00401   if (!vgl_intersection<Type>(box, line, pi0, pi1))
00402     return 0;
00403   unsigned nint = 0;
00404   // check if intersection points are interior to the line segment
00405   if (vgl_lineseg_test_point<Type>(pi0, line_seg)) {
00406     p0 = pi0;
00407     nint++;
00408   }
00409   if (vgl_lineseg_test_point<Type>(pi1, line_seg)) {
00410     p1 = pi1;
00411     nint++;
00412   }
00413   return nint;
00414 }
00415 
00416 //: Return the intersection point of two concurrent lines
00417 template <class T>
00418 vgl_point_3d<T> vgl_intersection(vgl_line_3d_2_points<T> const& l1,
00419                                  vgl_line_3d_2_points<T> const& l2)
00420 {
00421   assert(concurrent(l1,l2));
00422   T a0=l1.point1().x(),a1=l1.point2().x(),a2=l2.point1().x(),a3=l2.point2().x(),
00423     b0=l1.point1().y(),b1=l1.point2().y(),b2=l2.point1().y(),b3=l2.point2().y(),
00424     c0=l1.point1().z(),c1=l1.point2().z(),c2=l2.point1().z(),c3=l2.point2().z();
00425   T t1 = (b3-b2)*(a1-a0)-(a3-a2)*(b1-b0), t2 = (b0-b2)*(a1-a0)-(a0-a2)*(b1-b0);
00426   if (vcl_abs(t1) < 0.000001)
00427   {
00428     t1 = (c3-c2)*(a1-a0)-(a3-a2)*(c1-c0), t2 = (c0-c2)*(a1-a0)-(a0-a2)*(c1-c0);
00429     if (vcl_abs(t1) < 0.000001)
00430       t1 = (c3-c2)*(b1-b0)-(b3-b2)*(c1-c0), t2 = (c0-c2)*(b1-b0)-(b0-b2)*(c1-c0);
00431   }
00432 
00433   return vgl_point_3d<T>(((t1-t2)*a2+t2*a3)/t1,
00434                          ((t1-t2)*b2+t2*b3)/t1,
00435                          ((t1-t2)*c2+t2*c3)/t1);
00436 }
00437 
00438 //: Return the intersection point of segments of two concurrent lines
00439 // \relatesalso vgl_line_segment_3d
00440 template <class T>
00441 bool vgl_intersection(vgl_line_segment_3d<T> const& l1,
00442                       vgl_line_segment_3d<T> const& l2,
00443                       vgl_point_3d<T>& i_pnt)
00444 {
00445   vgl_line_3d_2_points<T> l21(l1.point1(),l1.point2());
00446   vgl_line_3d_2_points<T> l22(l2.point1(),l2.point2());
00447   if (!concurrent(l21, l22))
00448     return false;
00449   i_pnt = vgl_intersection(l21, l22);
00450 
00451   double l1_len =   length(l1.point1() - l1.point2());
00452   double l1_idist = length(l1.point1() - i_pnt) + length(l1.point2() - i_pnt);
00453   double l2_len =   length(l2.point1() - l2.point2());
00454   double l2_idist = length(l2.point1() - i_pnt) + length(l2.point2() - i_pnt);
00455   return vgl_near_zero(l1_len - l1_idist) && vgl_near_zero(l2_len - l2_idist);
00456 }
00457 
00458 //: Return the intersection point of segments of two concurrent lines
00459 // \relatesalso vgl_line_segment_3d
00460 // \relatesalso vgl_line_3d_2_points
00461 template <class T>
00462 bool vgl_intersection(vgl_line_3d_2_points<T> const& l1,
00463                       vgl_line_segment_3d<T> const& l2,
00464                       vgl_point_3d<T>& i_pnt)
00465 {
00466   vgl_line_3d_2_points<T> l22(l2.point1(),l2.point2());
00467   if (!concurrent(l1, l22))
00468     return false;
00469   i_pnt = vgl_intersection(l1, l22);
00470 
00471   double l1_len =   length(l1.point1() - l1.point2());
00472   double l1_idist = length(l1.point1() - i_pnt) + length(l1.point2() - i_pnt);
00473   double l2_len =   length(l2.point1() - l2.point2());
00474   double l2_idist = length(l2.point1() - i_pnt) + length(l2.point2() - i_pnt);
00475 
00476   return vgl_near_zero(l1_len - l1_idist) && vgl_near_zero(l2_len - l2_idist);
00477 }
00478 
00479 //: Return the intersection point of two lines, if concurrent.
00480 // \relatesalso vgl_infinite_line_3d
00481 template <class T>
00482 bool vgl_intersection(vgl_infinite_line_3d<T> const& l1,
00483                       vgl_infinite_line_3d<T> const& l2,
00484                       vgl_point_3d<T>& i_pnt)
00485 {
00486   vgl_line_3d_2_points<T> l21(l1.point(),l1.point_t(T(1)));
00487   vgl_line_3d_2_points<T> l22(l2.point(),l2.point_t(T(1)));
00488   if (!concurrent(l21, l22))
00489     return false;
00490   i_pnt = vgl_intersection(l21, l22);
00491   return l1.contains(i_pnt) && l2.contains(i_pnt);
00492 }
00493 
00494 //: Return the intersection point of a line and a plane.
00495 // \relatesalso vgl_line_3d_2_points
00496 // \relatesalso vgl_plane_3d
00497 template <class T>
00498 vgl_point_3d<T> vgl_intersection(vgl_line_3d_2_points<T> const& line,
00499                                  vgl_plane_3d<T> const& plane)
00500 {
00501   vgl_vector_3d<T> dir = line.direction();
00502 
00503   vgl_point_3d<T> pt;
00504 
00505   double denom = plane.a()*dir.x() +
00506                  plane.b()*dir.y() +
00507                  plane.c()*dir.z();
00508 
00509   if (denom == 0)
00510   {
00511     const T inf = vcl_numeric_limits<T>::infinity();
00512     // Line is either parallel or coplanar
00513     // If the distance from a line endpoint to the plane is zero, coplanar
00514     if (vgl_distance(line.point1(), plane)==0.0)
00515       pt.set(inf,inf,inf);
00516     else
00517       pt.set(inf,0,0);
00518   }
00519   else
00520   {
00521     // Infinite line intersects plane
00522     double numer = - plane.a()*line.point1().x()
00523                    - plane.b()*line.point1().y()
00524                    - plane.c()*line.point1().z()
00525                    - plane.d();
00526 
00527     dir *= numer/denom;
00528     pt = line.point1() + dir;
00529   }
00530 
00531   return pt;
00532 }
00533 
00534 //: Return the intersection point of a line and a plane.
00535 // \relatesalso vgl_line_segment_3d
00536 // \relatesalso vgl_plane_3d
00537 template <class T>
00538 bool vgl_intersection(vgl_line_segment_3d<T> const& line,
00539                       vgl_plane_3d<T> const& plane,
00540                       vgl_point_3d<T> & i_pt)
00541 {
00542   vgl_vector_3d<T> dir = line.direction();
00543 
00544   // The calculation of both denom and numerator are both very dodgy numerically, especially if
00545   // denom or numerator is small compared to the summands. It would be good to find a more
00546   // numerically stable solution. IMS.
00547   const double tol = vcl_numeric_limits<T>::epsilon() * 10e3;
00548 
00549   double denom = plane.a()*dir.x() +
00550                  plane.b()*dir.y() +
00551                  plane.c()*dir.z();
00552 
00553   if (vcl_abs(denom) < tol)
00554   {
00555     // Line is either parallel or coplanar
00556     // If the distance from a line endpoint to the plane is zero, coplanar
00557     if (vgl_distance(line.point1(), plane)!=0.0)
00558       return false;
00559 
00560     const T inf = vcl_numeric_limits<T>::infinity();
00561     i_pt.set(inf,inf,inf);
00562     return true;
00563   }
00564 
00565   double numer = - plane.a()*line.point1().x()
00566                  - plane.b()*line.point1().y()
00567                  - plane.c()*line.point1().z()
00568                  - plane.d();
00569 
00570   double t = numer/denom; // 0<t<1 between two points
00571   if (t < 0 || t > 1.0) return false;
00572 
00573   i_pt = line.point1() + t * dir;
00574   return true;
00575 }
00576 
00577 template <class T>
00578 bool vgl_intersection(vgl_infinite_line_3d<T> const& line,
00579                       vgl_plane_3d<T> const& plane,
00580                       vgl_point_3d<T> & i_pt)
00581 {
00582   vgl_vector_3d<T> dir = line.direction();
00583   vgl_point_3d<T> pt = line.point();
00584   // The calculation of both denom and numerator are both very dodgy numerically, especially if
00585   // denom or numerator is small compared to the summands. It would be good to find a more
00586   // numerically stable solution. IMS.
00587   const double tol = vcl_numeric_limits<T>::epsilon() * 10e3;
00588 
00589   double denom = plane.a()*dir.x() +
00590                  plane.b()*dir.y() +
00591                  plane.c()*dir.z();
00592 
00593   if (vcl_abs(denom) < tol)
00594   {
00595     // Line is either parallel or coplanar
00596     // If the distance from a line endpoint to the plane is zero, coplanar
00597     if (vgl_distance(pt, plane)!=0.0)
00598       return false;
00599 
00600     const T inf = vcl_numeric_limits<T>::infinity();
00601     i_pt.set(inf,inf,inf);
00602     return true;
00603   }
00604 
00605   double numer = - plane.a()*pt.x()
00606                  - plane.b()*pt.y()
00607                  - plane.c()*pt.z()
00608                  - plane.d();
00609 
00610   double t = numer/denom;
00611   i_pt = pt + t * dir;
00612   return true;
00613 }
00614 
00615 template <class T>
00616 bool vgl_intersection( const vgl_line_2d<T> &line0,
00617                        const vgl_line_2d<T> &line1,
00618                        vgl_point_2d<T>      &intersection_point )
00619 {
00620   T a0, b0, c0,  a1, b1, c1;
00621   a0 = line0.a(); b0 = line0.b(); c0 = line0.c();
00622   a1 = line1.a(); b1 = line1.b(); c1 = line1.c();
00623 
00624   T delta, delta_x, delta_y, x, y;
00625   delta = a0*b1 - a1*b0;
00626   if ( vcl_abs(delta) <= vgl_tolerance<T>::position ) // Lines are parallel
00627     return false;
00628   delta_x = -c0*b1 + b0*c1; delta_y = -a0*c1 + a1*c0;
00629   x = delta_x / delta; y = delta_y / delta;
00630 
00631   //   intersection_point.set( (Type)x, (Type)y );
00632   intersection_point.set( x, y );
00633   return true;
00634 }
00635 
00636 //: Return the intersection line of two planes. Returns false if planes
00637 // are effectively parallel
00638 // \relatesalso vgl_infinite_line_3d
00639 // \relatesalso vgl_plane_3d
00640 template <class T>
00641 bool vgl_intersection(vgl_plane_3d<T> const& plane0,
00642                       vgl_plane_3d<T> const& plane1,
00643                       vgl_infinite_line_3d<T>& line)
00644 {
00645   double n0x = static_cast<double>(plane0.a());
00646   double n0y = static_cast<double>(plane0.b());
00647   double n0z = static_cast<double>(plane0.c());
00648   double n1x = static_cast<double>(plane1.a());
00649   double n1y = static_cast<double>(plane1.b());
00650   double n1z = static_cast<double>(plane1.c());
00651   vgl_vector_3d<double> n0(n0x, n0y, n0z);
00652   vgl_vector_3d<double> n1(n1x, n1y, n1z);
00653   // t is the direction vector of the line
00654   vgl_vector_3d<double> t = cross_product(n0, n1);
00655   double mag = t.length();
00656   if (vgl_near_zero(mag))
00657     return false;
00658   t/=mag; // create unit vector
00659   double tx = vcl_fabs(static_cast<double>(t.x_));
00660   double ty = vcl_fabs(static_cast<double>(t.y_));
00661   double tz = vcl_fabs(static_cast<double>(t.z_));
00662   // determine maximum component of t
00663   char component = 'x';
00664   if (ty>tx&&ty>tz)
00665     component = 'y';
00666   if (tz>tx&&tz>ty)
00667     component = 'z';
00668   double d0 = static_cast<double>(plane0.d());
00669   double d1 = static_cast<double>(plane1.d());
00670   vgl_point_3d<double> p0d;
00671   switch (component)
00672   {
00673     // x is the largest component of t
00674     case 'x':
00675     {
00676       double det = n0y*n1z-n1y*n0z;
00677       if (vgl_near_zero(det))
00678         return false;
00679       double neuy = d1*n0z - d0*n1z;
00680       double neuz = d0*n1y - d1*n0y;
00681       p0d.set(0.0, neuy/det, neuz/det);
00682       break;
00683     }
00684     case 'y':
00685     {
00686       double det = n0x*n1z-n1x*n0z;
00687       if (vgl_near_zero(det))
00688         return false;
00689       double neux = d1*n0z - d0*n1z;
00690       double neuz = d0*n1x - d1*n0x;
00691       p0d.set(neux/det, 0.0, neuz/det);
00692       break;
00693     }
00694     case 'z':
00695     {
00696       double det = n0x*n1y-n1x*n0y;
00697       if (vgl_near_zero(det))
00698         return false;
00699       double neux = d1*n0y - d0*n1y;
00700       double neuy = d0*n1x - d1*n0x;
00701       p0d.set(neux/det, neuy/det, 0.0);
00702       break;
00703     }
00704     default: // this cannot happen
00705       break;
00706   }
00707   vgl_point_3d<T> p0(static_cast<T>(p0d.x()),
00708                      static_cast<T>(p0d.y()),
00709                      static_cast<T>(p0d.z()));
00710   vgl_vector_3d<T> tt(static_cast<T>(t.x()),
00711                       static_cast<T>(t.y()),
00712                       static_cast<T>(t.z()));
00713   line = vgl_infinite_line_3d<T>(p0, tt);
00714   return true;
00715 }
00716 
00717 //: Return the intersection point of three planes.
00718 // \relatesalso vgl_plane_3d
00719 template <class T>
00720 vgl_point_3d<T> vgl_intersection(const vgl_plane_3d<T>& p1,
00721                                  const vgl_plane_3d<T>& p2,
00722                                  const vgl_plane_3d<T>& p3)
00723 {
00724   vgl_point_3d<T> p(p1, p2, p3);
00725   return p;
00726 }
00727 
00728 //: Return true if any point on [p1,p2] is within tol of [q1,q2]
00729 //  Tests two line segments for intersection or near intersection
00730 //  (within given tolerance).
00731 // \author Dan jackson
00732 template <class T>
00733 bool vgl_intersection(vgl_point_2d<T> const& p1,
00734                       vgl_point_2d<T> const& p2,
00735                       vgl_point_2d<T> const& q1,
00736                       vgl_point_2d<T> const& q2,
00737                       double tol)
00738 {
00739   vgl_vector_2d<T> u = p2 - p1;
00740   vgl_vector_2d<T> v(-u.y(),u.x());
00741   double uq1 = dot_product(q1 - p1,u);
00742   double vq1 = dot_product(q1 - p1,v);
00743   double tol2 = tol*tol;
00744   double L2 = sqr_length(u);
00745 
00746   // Check if q1 is in central band (either side of line p1-p2
00747   if (uq1 > 0 && uq1 < L2)
00748   {
00749     // Check if q1 is within tol of the line, ie |vq1/L| < tol
00750     if (vq1*vq1 <=tol2*L2) return true;
00751   }
00752   else
00753   {
00754     // Check if q1 is within tol of either end of line
00755     if ( (q1-p1).sqr_length() <= tol2 || (q1-p2).sqr_length() <= tol2 )
00756       return true;
00757   }
00758 
00759   // Repeat test for q2
00760   double uq2 = dot_product(q2 - p1,u);
00761   double vq2 = dot_product(q2 - p1,v);
00762 
00763   // Check if q2 is in central band (either side of line p1-p2
00764   if (uq2 > 0 && uq2 < L2)
00765   {
00766     // Check if q1 is within tol of the line, ie |vq1/L| < tol
00767     if (vq2*vq2 <=tol2*L2)
00768       return true;
00769   }
00770   else
00771   {
00772     // Check if q1 is within tol of either end of line
00773     if ( (q2-p1).sqr_length() <= tol2 || (q2-p2).sqr_length() <= tol2 )
00774       return true;
00775   }
00776 
00777   // The points q1 and q2 do not lie within the tolerance region
00778   // around line segment (p1,p2)
00779   // Now repeat the test the other way around,
00780   // testing whether points p1 and p2 lie in tolerance region
00781   // of line (q1,q2)
00782 
00783   u = q2 - q1;
00784   v.set(-u.y(),u.x());
00785   L2 = sqr_length(u);
00786 
00787   double up1 = dot_product(p1 - q1,u);
00788   double vp1 = dot_product(p1 - q1,v);
00789 
00790   // Check if p1 is in central band either side of line q1-q2
00791   if (up1 > 0 && up1 < L2)
00792   {
00793     // Check if p1 is within tol of the line, ie |vp1/L| < tol
00794     if (vp1*vp1 <=tol2*L2)
00795       return true;
00796   }
00797   else
00798   {
00799     // Check if p1 is within tol of either end of line
00800     if ( (p1-q1).sqr_length() <= tol2 || (p1-q2).sqr_length() <= tol2 )
00801       return true;
00802   }
00803 
00804   double up2 = dot_product(p2 - q1,u);
00805   double vp2 = dot_product(p2 - q1,v);
00806 
00807   // Check if p2 is in central band either side of line q1-q2
00808   if (up2 > 0 && up2 < L2)
00809   {
00810     // Check if p1 is within tol of the line, ie |vp1/L| < tol
00811     if (vp2*vp2 <=tol2*L2)
00812       return true;
00813   }
00814   else
00815   {
00816     // Check if p2 is within tol of either end of line
00817     if ( (p2-q1).sqr_length() <= tol2 || (p2-q2).sqr_length() <= tol2)
00818       return true;
00819   }
00820 
00821   // Now check for actual intersection
00822   return vq1*vq2 < 0 && vp1*vp2 < 0;
00823 }
00824 
00825 template <class T>
00826 bool vgl_intersection(const vgl_box_2d<T>& b,
00827                       const vgl_polygon<T>& poly)
00828 {
00829   // easy checks first
00830   // check if any poly vertices are inside the box
00831   unsigned ns = poly.num_sheets();
00832   bool hit = false;
00833   for ( unsigned s = 0; s<ns&&!hit; ++s) {
00834     unsigned n = poly[s].size();
00835     for (unsigned i = 0; i<n&&!hit; ++i) {
00836       vgl_point_2d<T> p = poly[s][i];
00837       hit = b.contains(p.x(), p.y());
00838     }
00839   }
00840   if (hit) return true;
00841   // check if any box vertices are inside the polygon
00842   T minx = b.min_x(), maxx = b.max_x();
00843   T miny = b.min_y(), maxy = b.max_y();
00844   hit = poly.contains(minx, miny) || poly.contains(maxx, maxy) ||
00845     poly.contains(minx, maxy) || poly.contains(maxx, miny);
00846   if (hit) return true;
00847   // check if any polygon edges intersect the box
00848   for (unsigned s = 0; s<ns&&!hit; ++s)
00849   {
00850     unsigned n = poly[s].size();
00851     vgl_point_2d<T> ia, ib;
00852     vgl_point_2d<T> last = poly[s][0];
00853     for (unsigned i = 1; i<n&&!hit; ++i)
00854     {
00855       vgl_point_2d<T> p = poly[s][i];
00856       vgl_line_segment_2d<T> l(last, p);
00857       hit = vgl_intersection<T>(b, l, ia, ib)>0;
00858       last = p;
00859     }
00860     if (!hit) {
00861       vgl_point_2d<T> start = poly[s][0];
00862       vgl_line_segment_2d<T> ll(last, start);
00863       hit = vgl_intersection<T>(b,ll, ia, ib)>0;
00864     }
00865   }
00866   return hit;
00867 }
00868 
00869 //: Return the points from the list that lie inside the box
00870 // \relatesalso vgl_point_2d
00871 // \relatesalso vgl_box_2d
00872 template <class T>
00873 vcl_vector<vgl_point_2d<T> > vgl_intersection(vgl_box_2d<T> const& b, vcl_vector<vgl_point_2d<T> > const& p)
00874 {
00875   vcl_vector<vgl_point_2d<T> > r;
00876   typename vcl_vector<vgl_point_2d<T> >::const_iterator i;
00877   for (i = p.begin(); i != p.end(); ++i)
00878     if (vgl_intersection(b, *i))
00879       r.push_back(*i);
00880   return r;
00881 }
00882 
00883 //: Return the points from the list that lie inside the box
00884 // \relatesalso vgl_point_2d
00885 // \relatesalso vgl_box_2d
00886 template <class T>
00887 vcl_vector<vgl_point_2d<T> > vgl_intersection(vcl_vector<vgl_point_2d<T> > const& p, vgl_box_2d<T> const& b)
00888 {
00889   vcl_vector<vgl_point_2d<T> > r;
00890   typename vcl_vector<vgl_point_2d<T> >::const_iterator i;
00891   for (i = p.begin(); i != p.end(); ++i)
00892     if (vgl_intersection(b, *i))
00893       r.push_back(*i);
00894   return r;
00895 }
00896 
00897 //: Return the points from the list that lie inside the box
00898 // \relatesalso vgl_point_3d
00899 // \relatesalso vgl_box_3d
00900 template <class T>
00901 vcl_vector<vgl_point_3d<T> > vgl_intersection(vgl_box_3d<T> const& b, vcl_vector<vgl_point_3d<T> > const& p)
00902 {
00903   vcl_vector<vgl_point_3d<T> > r;
00904   typename vcl_vector<vgl_point_3d<T> >::const_iterator i;
00905   for (i = p.begin(); i != p.end(); ++i)
00906     if (vgl_intersection(b, *i))
00907       r.push_back(*i);
00908   return r;
00909 }
00910 
00911 //: Return the points from the list that lie inside the box
00912 // \relatesalso vgl_point_3d
00913 // \relatesalso vgl_box_3d
00914 template <class T>
00915 vcl_vector<vgl_point_3d<T> > vgl_intersection(vcl_vector<vgl_point_3d<T> > const& p, vgl_box_3d<T> const& b)
00916 {
00917   vcl_vector<vgl_point_3d<T> > r;
00918   typename vcl_vector<vgl_point_3d<T> >::const_iterator i;
00919   for (i = p.begin(); i != p.end(); ++i)
00920     if (vgl_intersection(b, *i))
00921       r.push_back(*i);
00922   return r;
00923 }
00924 
00925 //: Instantiate those functions which are suitable for integer instantiation.
00926 #undef VGL_INTERSECTION_BOX_INSTANTIATE
00927 #define VGL_INTERSECTION_BOX_INSTANTIATE(T) \
00928 template vgl_box_2d<T > vgl_intersection(vgl_box_2d<T > const&,vgl_box_2d<T > const&); \
00929 template vgl_box_3d<T > vgl_intersection(vgl_box_3d<T > const&,vgl_box_3d<T > const&); \
00930 template vcl_vector<vgl_point_2d<T > > vgl_intersection(vgl_box_2d<T > const&,vcl_vector<vgl_point_2d<T > > const&); \
00931 template vcl_vector<vgl_point_2d<T > > vgl_intersection(vcl_vector<vgl_point_2d<T > > const&,vgl_box_2d<T > const&); \
00932 template vcl_vector<vgl_point_3d<T > > vgl_intersection(vgl_box_3d<T > const&,vcl_vector<vgl_point_3d<T > > const&); \
00933 template vcl_vector<vgl_point_3d<T > > vgl_intersection(vcl_vector<vgl_point_3d<T > > const&,vgl_box_3d<T > const&); \
00934 template bool vgl_intersection(vgl_box_2d<T > const&,vgl_line_2d<T > const&,vgl_point_2d<T >&,vgl_point_2d<T >&); \
00935 template bool vgl_intersection(vgl_box_3d<T > const&,vgl_plane_3d<T > const&); \
00936 template bool vgl_intersection(vgl_box_3d<T > const&,vgl_infinite_line_3d<T > const&,vgl_point_3d<T >&,vgl_point_3d<T >&)
00937 
00938 #undef VGL_INTERSECTION_INSTANTIATE
00939 #define VGL_INTERSECTION_INSTANTIATE(T) \
00940 template vgl_point_3d<T > vgl_intersection(vgl_line_3d_2_points<T > const&,vgl_line_3d_2_points<T > const&); \
00941 template bool vgl_intersection(vgl_line_segment_3d<T > const&,vgl_line_segment_3d<T > const&,vgl_point_3d<T >&); \
00942 template bool vgl_intersection(vgl_line_3d_2_points<T > const&,vgl_line_segment_3d<T > const&,vgl_point_3d<T >&); \
00943 template vgl_point_3d<T > vgl_intersection(vgl_line_3d_2_points<T > const&,vgl_plane_3d<T > const&); \
00944 template bool vgl_intersection(vgl_line_segment_3d<T > const&,vgl_plane_3d<T > const&,vgl_point_3d<T >&); \
00945 template bool vgl_intersection(vgl_infinite_line_3d<T > const&,vgl_plane_3d<T > const&,vgl_point_3d<T >&); \
00946 template bool vgl_intersection(vgl_infinite_line_3d<T > const&,vgl_infinite_line_3d<T > const&,vgl_point_3d<T >&); \
00947 template vgl_point_3d<T > vgl_intersection(vgl_plane_3d<T > const&,vgl_plane_3d<T > const&,vgl_plane_3d<T > const&); \
00948 template unsigned vgl_intersection(vgl_box_2d<T > const&,vgl_line_segment_2d<T > const&,vgl_point_2d<T >&,vgl_point_2d<T >&); \
00949 template bool vgl_intersection(vgl_line_2d<T > const&,vgl_line_2d<T > const&,vgl_point_2d<T >&); \
00950 template bool vgl_intersection(vgl_point_2d<T > const&,vgl_point_2d<T > const&,vgl_point_2d<T > const&,vgl_point_2d<T > const&,double); \
00951 template bool vgl_intersection(vgl_box_2d<T > const&,vgl_polygon<T > const&); \
00952 template bool vgl_intersection(vgl_plane_3d<T > const&,vgl_plane_3d<T > const&,vgl_line_segment_3d<T > &); \
00953 template bool vgl_intersection(vgl_plane_3d<T > const&,vgl_plane_3d<T > const&,vgl_infinite_line_3d<T >&); \
00954 VGL_INTERSECTION_BOX_INSTANTIATE(T)
00955 
00956 #endif // vgl_intersection_txx_