00001
00002 #ifndef bvgl_intersection_txx_
00003 #define bvgl_intersection_txx_
00004
00005
00006
00007
00008
00009
00010
00011 #include "bvgl_intersection.h"
00012 #include <vcl_limits.h>
00013 #include <vcl_cassert.h>
00014 #include <vcl_cmath.h>
00015 #include <vcl_algorithm.h>
00016 #include <vcl_vector.h>
00017
00018
00019 namespace bvgl_intersection_helpers
00020 {
00021
00022 enum Axes { X=0, Y=1, Z=2 };
00023
00024 template <typename T>
00025 inline void cross(T dest[3], T a[3], T b[3]) {
00026 dest[0]=a[1]*b[2]-a[2]*b[1];
00027 dest[1]=a[2]*b[0]-a[0]*b[2];
00028 dest[2]=a[0]*b[1]-a[1]*b[0];
00029 }
00030
00031 template <typename T>
00032 inline T dot(T a[3], T b[3]) { return a[0]*b[0]+a[1]*b[1]+a[2]*b[2]; }
00033
00034 template <typename T>
00035 inline void subtract(T dest[3], T a[3], T b[3]) {
00036 dest[0] = a[0]-b[0];
00037 dest[1] = a[1]-b[1];
00038 dest[2] = a[2]-b[2];
00039 }
00040
00041 template <typename T>
00042 inline void findMinMax(T x0, T x1, T x2, T& min, T&max) {
00043 min = max = x0;
00044 if (x1 < min) min = x1;
00045 if (x1 > max) max = x1;
00046 if (x2 < min) min = x2;
00047 if (x2 > max) max = x2;
00048 }
00049
00050 template <typename T>
00051 bool planeBoxIntersect(T normal[3], T d, T maxbox[3]) {
00052 T vmin[3],vmax[3];
00053 for (int q=X;q<=Z;q++) {
00054 if (normal[q]>0.0f) {
00055 vmin[q]=-maxbox[q];
00056 vmax[q]=maxbox[q];
00057 }
00058 else {
00059 vmin[q]=maxbox[q];
00060 vmax[q]=-maxbox[q];
00061 }
00062 }
00063 return dot(normal,vmin)+d <= 0.0f
00064 && dot(normal,vmax)+d >= 0.0f;
00065 }
00066
00067 template<int Axis0, int Axis1, typename T>
00068 inline bool axisTest(T edge[3], T fedge[3], T v0[3], T v1[3], T boxhalfsize[3]) {
00069 T p0 = edge[Axis1]*v0[Axis0] - edge[Axis0]*v0[Axis1];
00070 T p1 = edge[Axis1]*v1[Axis0] - edge[Axis0]*v1[Axis1];
00071 T min = vcl_min(p0, p1);
00072 T max = vcl_max(p0, p1);
00073 T rad = fedge[Axis1]*boxhalfsize[Axis0] + fedge[Axis0]*boxhalfsize[Axis1];
00074 return min <= rad && max >= -rad;
00075 }
00076 }
00077
00078
00079
00080 template <typename T>
00081 bool bvgl_intersection(vgl_box_3d<T> const& A, bvgl_triangle_3d<T> const& B)
00082 {
00083
00084 using namespace bvgl_intersection_helpers;
00085
00086
00087 T boxcenter[3] = { A.centroid_x(), A.centroid_y(), A.centroid_z() };
00088 T boxhalfsize[3] = { A.width()/2.0, A.height()/2.0, A.depth()/2.0 };
00089 T triverts[3][3] = { { B[0].x(), B[0].y(), B[0].z() },
00090 { B[1].x(), B[1].y(), B[1].z() },
00091 { B[2].x(), B[2].y(), B[2].z() } };
00092
00093
00094 T v0[3],v1[3],v2[3];
00095 subtract(v0,triverts[0],boxcenter);
00096 subtract(v1,triverts[1],boxcenter);
00097 subtract(v2,triverts[2],boxcenter);
00098
00099
00100 T e0[3],e1[3],e2[3];
00101 subtract(e0,v1,v0);
00102 subtract(e1,v2,v1);
00103 subtract(e2,v0,v2);
00104
00105
00106 T min, max;
00107 findMinMax(v0[X],v1[X],v2[X],min,max);
00108 if (min>boxhalfsize[X] || max<-boxhalfsize[X])
00109 return false;
00110 findMinMax(v0[Y],v1[Y],v2[Y],min,max);
00111 if (min>boxhalfsize[Y] || max<-boxhalfsize[Y])
00112 return false;
00113 findMinMax(v0[Z],v1[Z],v2[Z],min,max);
00114 if (min>boxhalfsize[Z] || max<-boxhalfsize[Z])
00115 return false;
00116
00117
00118 T normal[3];
00119 cross(normal,e0,e1);
00120 T d = -dot(normal,v0);
00121 if (!planeBoxIntersect(normal,d,boxhalfsize))
00122 return false;
00123
00124
00125 T fe[3] = { vcl_fabs(e0[X]), vcl_fabs(e0[Y]), vcl_fabs(e0[Z]) };
00126 if (!axisTest<Y,Z>(e0, fe, v0, v2, boxhalfsize) ||
00127 !axisTest<X,Z>(e0, fe, v0, v2, boxhalfsize) ||
00128 !axisTest<X,Y>(e0, fe, v1, v2, boxhalfsize) )
00129 return false;
00130
00131 fe[X]=vcl_fabs(e1[X]); fe[Y]=vcl_fabs(e1[Y]); fe[Z]=vcl_fabs(e1[Z]);
00132 if (!axisTest<Y,Z>(e1, fe, v0, v2, boxhalfsize) ||
00133 !axisTest<X,Z>(e1, fe, v0, v2, boxhalfsize) ||
00134 !axisTest<X,Y>(e1, fe, v0, v1, boxhalfsize) )
00135 return false;
00136
00137 fe[X]=vcl_fabs(e2[X]); fe[Y]=vcl_fabs(e2[Y]); fe[Z]=vcl_fabs(e2[Z]);
00138 if (!axisTest<Y,Z>(e2, fe, v0, v1, boxhalfsize) ||
00139 !axisTest<X,Z>(e2, fe, v0, v1, boxhalfsize) ||
00140 !axisTest<X,Y>(e2, fe, v1, v2, boxhalfsize) )
00141 return false;
00142
00143
00144 return true;
00145 }
00146
00147
00148
00149
00150 #undef BVGL_INTERSECTION_INSTANTIATE
00151 #define BVGL_INTERSECTION_INSTANTIATE(T) \
00152 template bool bvgl_intersection(vgl_box_3d<T > const& A, bvgl_triangle_3d<T > const& B)
00153
00154 #endif // bvgl_intersection_txx_