00001
00002
00003
00004
00005
00006
00007
00008 #include "intersection.h"
00009
00010
00011 #include <math.h>
00012 #include <stdio.h>
00013 #include <iostream>
00014
00015 using namespace std;
00016
00017
00018 int Intersection::debug = 0;
00019 const char* Intersection::rcsid = "@(#) $Id: intersection.cpp,v 1.4 2006/05/24 16:52:39 sean Exp $ $Copyright: (c)2001 National Biocomputation Center, Stanford University $";
00020
00021
00022 Intersection* Intersection::pinstance = NULL;
00023
00024
00025
00026
00027 Intersection* Intersection::Instance()
00028 {
00029 if (pinstance == NULL) {
00030 pinstance = new Intersection();
00031 }
00032 return pinstance;
00033 }
00034
00035
00036 Intersection::Intersection()
00037 {
00038 if (debug) std::cerr << "Intersection::constructor()\n";
00039 }
00040
00041
00042 Intersection::~Intersection()
00043 {
00044 if (debug) std::cerr << "Intersection::destructor()\n";
00045 }
00046
00047
00048 bool Intersection::intersects(Face *face0, Face *face1) {
00049 float V0[3];
00050 float V1[3];
00051 float V2[3];
00052 float U0[3];
00053 float U1[3];
00054 float U2[3];
00055
00056
00057 V0[0] = face0->getNodeLink(0)->p.x;
00058 V0[1] = face0->getNodeLink(0)->p.y;
00059 V0[2] = face0->getNodeLink(0)->p.z;
00060 V1[0] = face0->getNodeLink(1)->p.x;
00061 V1[1] = face0->getNodeLink(1)->p.y;
00062 V1[2] = face0->getNodeLink(1)->p.z;
00063 V2[0] = face0->getNodeLink(2)->p.x;
00064 V2[1] = face0->getNodeLink(2)->p.y;
00065 V2[2] = face0->getNodeLink(2)->p.z;
00066
00067 U0[0] = face1->getNodeLink(0)->p.x;
00068 U0[1] = face1->getNodeLink(0)->p.y;
00069 U0[2] = face1->getNodeLink(0)->p.z;
00070 U1[0] = face1->getNodeLink(1)->p.x;
00071 U1[1] = face1->getNodeLink(1)->p.y;
00072 U1[2] = face1->getNodeLink(1)->p.z;
00073 U2[0] = face1->getNodeLink(2)->p.x;
00074 U2[1] = face1->getNodeLink(2)->p.y;
00075 U2[2] = face1->getNodeLink(2)->p.z;
00076
00077
00078 return NoDivTriTriIsect(V0, V1, V2, U0, U1, U2);
00079 }
00080
00081
00082 bool Intersection::intersects(Face *face0, Point3D *min, Point3D *max) {
00083 float boxcenter[3];
00084 float boxhalfsize[3];
00085 float triverts[3][3];
00086
00087
00088 boxcenter[0] = (min->x + max->x) / 2;
00089 boxcenter[1] = (min->y + max->y) / 2;
00090 boxcenter[2] = (min->z + max->z) / 2;
00091 boxhalfsize[0] = (max->x - min->x) / 2;
00092 boxhalfsize[1] = (max->y - min->y) / 2;
00093 boxhalfsize[2] = (max->z - min->z) / 2;
00094
00095 triverts[0][0] = face0->getNodeLink(0)->p.x;
00096 triverts[0][1] = face0->getNodeLink(0)->p.y;
00097 triverts[0][2] = face0->getNodeLink(0)->p.z;
00098 triverts[1][0] = face0->getNodeLink(1)->p.x;
00099 triverts[1][1] = face0->getNodeLink(1)->p.y;
00100 triverts[1][2] = face0->getNodeLink(1)->p.z;
00101 triverts[2][0] = face0->getNodeLink(2)->p.x;
00102 triverts[2][1] = face0->getNodeLink(2)->p.y;
00103 triverts[2][2] = face0->getNodeLink(2)->p.z;
00104
00105
00106 return triBoxOverlap(boxcenter, boxhalfsize, triverts);
00107 }
00108
00109
00110
00111
00112 #define SORT(a,b) \
00113 if(a>b) \
00114 { \
00115 float c; \
00116 c=a; \
00117 a=b; \
00118 b=c; \
00119 }
00120
00121
00122 #define CROSS(dest,v1,v2){ \
00123 dest[0]=v1[1]*v2[2]-v1[2]*v2[1]; \
00124 dest[1]=v1[2]*v2[0]-v1[0]*v2[2]; \
00125 dest[2]=v1[0]*v2[1]-v1[1]*v2[0];}
00126
00127 #define DOT(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2])
00128
00129 #define SUB(dest,v1,v2){ \
00130 dest[0]=v1[0]-v2[0]; \
00131 dest[1]=v1[1]-v2[1]; \
00132 dest[2]=v1[2]-v2[2];}
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 #define FABS(x) (float(fabs(x)))
00155
00156
00157
00158
00159
00160 #define USE_EPSILON_TEST TRUE
00161 #define EPSILON_TRI_TRI 0.000001
00162
00163
00164
00165
00166 #define EDGE_EDGE_TEST(V0,U0,U1) \
00167 Bx=U0[i0]-U1[i0]; \
00168 By=U0[i1]-U1[i1]; \
00169 Cx=V0[i0]-U0[i0]; \
00170 Cy=V0[i1]-U0[i1]; \
00171 f=Ay*Bx-Ax*By; \
00172 d=By*Cx-Bx*Cy; \
00173 if((f>0 && d>=0 && d<=f) || (f<0 && d<=0 && d>=f)) \
00174 { \
00175 e=Ax*Cy-Ay*Cx; \
00176 if(f>0) \
00177 { \
00178 if(e>=0 && e<=f) return 1; \
00179 } \
00180 else \
00181 { \
00182 if(e<=0 && e>=f) return 1; \
00183 } \
00184 }
00185
00186 #define EDGE_AGAINST_TRI_EDGES(V0,V1,U0,U1,U2) \
00187 { \
00188 float Ax,Ay,Bx,By,Cx,Cy,e,d,f; \
00189 Ax=V1[i0]-V0[i0]; \
00190 Ay=V1[i1]-V0[i1]; \
00191 \
00192 EDGE_EDGE_TEST(V0,U0,U1); \
00193 \
00194 EDGE_EDGE_TEST(V0,U1,U2); \
00195 \
00196 EDGE_EDGE_TEST(V0,U2,U0); \
00197 }
00198
00199 #define POINT_IN_TRI(V0,U0,U1,U2) \
00200 { \
00201 float a,b,c,d0,d1,d2; \
00202 \
00203 \
00204 a=U1[i1]-U0[i1]; \
00205 b=-(U1[i0]-U0[i0]); \
00206 c=-a*U0[i0]-b*U0[i1]; \
00207 d0=a*V0[i0]+b*V0[i1]+c; \
00208 \
00209 a=U2[i1]-U1[i1]; \
00210 b=-(U2[i0]-U1[i0]); \
00211 c=-a*U1[i0]-b*U1[i1]; \
00212 d1=a*V0[i0]+b*V0[i1]+c; \
00213 \
00214 a=U0[i1]-U2[i1]; \
00215 b=-(U0[i0]-U2[i0]); \
00216 c=-a*U2[i0]-b*U2[i1]; \
00217 d2=a*V0[i0]+b*V0[i1]+c; \
00218 if(d0*d1>0.0) \
00219 { \
00220 if(d0*d2>0.0) return 1; \
00221 } \
00222 }
00223
00224 int Intersection::coplanar_tri_tri(float N[3],float V0[3],float V1[3],float V2[3],
00225 float U0[3],float U1[3],float U2[3])
00226 {
00227 float A[3];
00228 short i0,i1;
00229
00230
00231 A[0]=FABS(N[0]);
00232 A[1]=FABS(N[1]);
00233 A[2]=FABS(N[2]);
00234 if(A[0]>A[1])
00235 {
00236 if(A[0]>A[2])
00237 {
00238 i0=1;
00239 i1=2;
00240 }
00241 else
00242 {
00243 i0=0;
00244 i1=1;
00245 }
00246 }
00247 else
00248 {
00249 if(A[2]>A[1])
00250 {
00251 i0=0;
00252 i1=1;
00253 }
00254 else
00255 {
00256 i0=0;
00257 i1=2;
00258 }
00259 }
00260
00261
00262 EDGE_AGAINST_TRI_EDGES(V0,V1,U0,U1,U2);
00263 EDGE_AGAINST_TRI_EDGES(V1,V2,U0,U1,U2);
00264 EDGE_AGAINST_TRI_EDGES(V2,V0,U0,U1,U2);
00265
00266
00267 POINT_IN_TRI(V0,U0,U1,U2);
00268 POINT_IN_TRI(U0,V0,V1,V2);
00269
00270 return 0;
00271 }
00272
00273
00274
00275 #define NEWCOMPUTE_INTERVALS(VV0,VV1,VV2,D0,D1,D2,D0D1,D0D2,A,B,C,X0,X1) \
00276 { \
00277 if(D0D1>0.0f) \
00278 { \
00279 \
00280 \
00281 A=VV2; B=(VV0-VV2)*D2; C=(VV1-VV2)*D2; X0=D2-D0; X1=D2-D1; \
00282 } \
00283 else if(D0D2>0.0f)\
00284 { \
00285 \
00286 A=VV1; B=(VV0-VV1)*D1; C=(VV2-VV1)*D1; X0=D1-D0; X1=D1-D2; \
00287 } \
00288 else if(D1*D2>0.0f || D0!=0.0f) \
00289 { \
00290 \
00291 A=VV0; B=(VV1-VV0)*D0; C=(VV2-VV0)*D0; X0=D0-D1; X1=D0-D2; \
00292 } \
00293 else if(D1!=0.0f) \
00294 { \
00295 A=VV1; B=(VV0-VV1)*D1; C=(VV2-VV1)*D1; X0=D1-D0; X1=D1-D2; \
00296 } \
00297 else if(D2!=0.0f) \
00298 { \
00299 A=VV2; B=(VV0-VV2)*D2; C=(VV1-VV2)*D2; X0=D2-D0; X1=D2-D1; \
00300 } \
00301 else \
00302 { \
00303 \
00304 return coplanar_tri_tri(N1,V0,V1,V2,U0,U1,U2); \
00305 } \
00306 }
00307
00308
00309
00310 int Intersection::NoDivTriTriIsect(float V0[3],float V1[3],float V2[3],
00311 float U0[3],float U1[3],float U2[3])
00312 {
00313 float E1[3],E2[3];
00314 float N1[3],N2[3],d1,d2;
00315 float du0,du1,du2,dv0,dv1,dv2;
00316 float D[3];
00317 float isect1[2], isect2[2];
00318 float du0du1,du0du2,dv0dv1,dv0dv2;
00319 short index;
00320 float vp0,vp1,vp2;
00321 float up0,up1,up2;
00322 float bb,cc,max;
00323
00324
00325 SUB(E1,V1,V0);
00326 SUB(E2,V2,V0);
00327 CROSS(N1,E1,E2);
00328 d1=-DOT(N1,V0);
00329
00330
00331
00332 du0=DOT(N1,U0)+d1;
00333 du1=DOT(N1,U1)+d1;
00334 du2=DOT(N1,U2)+d1;
00335
00336
00337 #if USE_EPSILON_TEST==TRUE
00338 if(FABS(du0)<EPSILON_TRI_TRI) du0=0.0;
00339 if(FABS(du1)<EPSILON_TRI_TRI) du1=0.0;
00340 if(FABS(du2)<EPSILON_TRI_TRI) du2=0.0;
00341 #endif
00342 du0du1=du0*du1;
00343 du0du2=du0*du2;
00344
00345 if(du0du1>0.0f && du0du2>0.0f)
00346 return 0;
00347
00348
00349 SUB(E1,U1,U0);
00350 SUB(E2,U2,U0);
00351 CROSS(N2,E1,E2);
00352 d2=-DOT(N2,U0);
00353
00354
00355
00356 dv0=DOT(N2,V0)+d2;
00357 dv1=DOT(N2,V1)+d2;
00358 dv2=DOT(N2,V2)+d2;
00359
00360 #if USE_EPSILON_TEST==TRUE
00361 if(FABS(dv0)<EPSILON_TRI_TRI) dv0=0.0;
00362 if(FABS(dv1)<EPSILON_TRI_TRI) dv1=0.0;
00363 if(FABS(dv2)<EPSILON_TRI_TRI) dv2=0.0;
00364 #endif
00365
00366 dv0dv1=dv0*dv1;
00367 dv0dv2=dv0*dv2;
00368
00369 if(dv0dv1>0.0f && dv0dv2>0.0f)
00370 return 0;
00371
00372
00373 CROSS(D,N1,N2);
00374
00375
00376 max=(float)FABS(D[0]);
00377 index=0;
00378 bb=(float)FABS(D[1]);
00379 cc=(float)FABS(D[2]);
00380 if(bb>max) max=bb,index=1;
00381 if(cc>max) max=cc,index=2;
00382
00383
00384 vp0=V0[index];
00385 vp1=V1[index];
00386 vp2=V2[index];
00387
00388 up0=U0[index];
00389 up1=U1[index];
00390 up2=U2[index];
00391
00392
00393 float a,b,c,x0,x1;
00394 NEWCOMPUTE_INTERVALS(vp0,vp1,vp2,dv0,dv1,dv2,dv0dv1,dv0dv2,a,b,c,x0,x1);
00395
00396
00397 float d,e,f,y0,y1;
00398 NEWCOMPUTE_INTERVALS(up0,up1,up2,du0,du1,du2,du0du1,du0du2,d,e,f,y0,y1);
00399
00400 float xx,yy,xxyy,tmp;
00401 xx=x0*x1;
00402 yy=y0*y1;
00403 xxyy=xx*yy;
00404
00405 tmp=a*xxyy;
00406 isect1[0]=tmp+b*x1*yy;
00407 isect1[1]=tmp+c*x0*yy;
00408
00409 tmp=d*xxyy;
00410 isect2[0]=tmp+e*xx*y1;
00411 isect2[1]=tmp+f*xx*y0;
00412
00413 SORT(isect1[0],isect1[1]);
00414 SORT(isect2[0],isect2[1]);
00415
00416 if(isect1[1]<isect2[0] || isect2[1]<isect1[0]) return 0;
00417 return 1;
00418 }
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435 #define X 0
00436 #define Y 1
00437 #define Z 2
00438
00439 #define FINDMINMAX(x0,x1,x2,min,max) \
00440 min = max = x0; \
00441 if(x1<min) min=x1;\
00442 if(x1>max) max=x1;\
00443 if(x2<min) min=x2;\
00444 if(x2>max) max=x2;
00445
00446 int Intersection::planeBoxOverlap(float normal[3], float vert[3], float maxbox[3])
00447 {
00448 int q;
00449 float vmin[3],vmax[3],v;
00450 for(q=X;q<=Z;q++)
00451 {
00452 v=vert[q];
00453 if(normal[q]>0.0f)
00454 {
00455 vmin[q]=-maxbox[q] - v;
00456 vmax[q]= maxbox[q] - v;
00457 }
00458 else
00459 {
00460 vmin[q]= maxbox[q] - v;
00461 vmax[q]=-maxbox[q] - v;
00462 }
00463 }
00464 if(DOT(normal,vmin)>0.0f) return 0;
00465 if(DOT(normal,vmax)>=0.0f) return 1;
00466
00467 return 0;
00468 }
00469
00470
00471
00472 #define AXISTEST_X01(a, b, fa, fb) \
00473 p0 = a*v0[Y] - b*v0[Z]; \
00474 p2 = a*v2[Y] - b*v2[Z]; \
00475 if(p0<p2) {min=p0; max=p2;} else {min=p2; max=p0;} \
00476 rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z]; \
00477 if(min>rad || max<-rad) return 0;
00478
00479 #define AXISTEST_X2(a, b, fa, fb) \
00480 p0 = a*v0[Y] - b*v0[Z]; \
00481 p1 = a*v1[Y] - b*v1[Z]; \
00482 if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \
00483 rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z]; \
00484 if(min>rad || max<-rad) return 0;
00485
00486
00487 #define AXISTEST_Y02(a, b, fa, fb) \
00488 p0 = -a*v0[X] + b*v0[Z]; \
00489 p2 = -a*v2[X] + b*v2[Z]; \
00490 if(p0<p2) {min=p0; max=p2;} else {min=p2; max=p0;} \
00491 rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z]; \
00492 if(min>rad || max<-rad) return 0;
00493
00494 #define AXISTEST_Y1(a, b, fa, fb) \
00495 p0 = -a*v0[X] + b*v0[Z]; \
00496 p1 = -a*v1[X] + b*v1[Z]; \
00497 if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \
00498 rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z]; \
00499 if(min>rad || max<-rad) return 0;
00500
00501
00502
00503 #define AXISTEST_Z12(a, b, fa, fb) \
00504 p1 = a*v1[X] - b*v1[Y]; \
00505 p2 = a*v2[X] - b*v2[Y]; \
00506 if(p2<p1) {min=p2; max=p1;} else {min=p1; max=p2;} \
00507 rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y]; \
00508 if(min>rad || max<-rad) return 0;
00509
00510 #define AXISTEST_Z0(a, b, fa, fb) \
00511 p0 = a*v0[X] - b*v0[Y]; \
00512 p1 = a*v1[X] - b*v1[Y]; \
00513 if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \
00514 rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y]; \
00515 if(min>rad || max<-rad) return 0;
00516
00517 int Intersection::triBoxOverlap(float boxcenter[3],float boxhalfsize[3],float triverts[3][3])
00518 {
00519
00520
00521
00522
00523
00524
00525
00526
00527 float v0[3],v1[3],v2[3];
00528
00529 float min,max,p0,p1,p2,rad,fex,fey,fez;
00530 float normal[3],e0[3],e1[3],e2[3];
00531
00532
00533
00534 SUB(v0,triverts[0],boxcenter);
00535 SUB(v1,triverts[1],boxcenter);
00536 SUB(v2,triverts[2],boxcenter);
00537
00538
00539 SUB(e0,v1,v0);
00540 SUB(e1,v2,v1);
00541 SUB(e2,v0,v2);
00542
00543
00544
00545 fex = fabsf(e0[X]);
00546 fey = fabsf(e0[Y]);
00547 fez = fabsf(e0[Z]);
00548 AXISTEST_X01(e0[Z], e0[Y], fez, fey);
00549 AXISTEST_Y02(e0[Z], e0[X], fez, fex);
00550 AXISTEST_Z12(e0[Y], e0[X], fey, fex);
00551
00552 fex = fabsf(e1[X]);
00553 fey = fabsf(e1[Y]);
00554 fez = fabsf(e1[Z]);
00555 AXISTEST_X01(e1[Z], e1[Y], fez, fey);
00556 AXISTEST_Y02(e1[Z], e1[X], fez, fex);
00557 AXISTEST_Z0(e1[Y], e1[X], fey, fex);
00558
00559 fex = fabsf(e2[X]);
00560 fey = fabsf(e2[Y]);
00561 fez = fabsf(e2[Z]);
00562 AXISTEST_X2(e2[Z], e2[Y], fez, fey);
00563 AXISTEST_Y1(e2[Z], e2[X], fez, fex);
00564 AXISTEST_Z12(e2[Y], e2[X], fey, fex);
00565
00566
00567
00568
00569
00570
00571
00572
00573 FINDMINMAX(v0[X],v1[X],v2[X],min,max);
00574 if(min>boxhalfsize[X] || max<-boxhalfsize[X]) return 0;
00575
00576
00577 FINDMINMAX(v0[Y],v1[Y],v2[Y],min,max);
00578 if(min>boxhalfsize[Y] || max<-boxhalfsize[Y]) return 0;
00579
00580
00581 FINDMINMAX(v0[Z],v1[Z],v2[Z],min,max);
00582 if(min>boxhalfsize[Z] || max<-boxhalfsize[Z]) return 0;
00583
00584
00585
00586
00587 CROSS(normal,e0,e1);
00588
00589 if(!planeBoxOverlap(normal,v0,boxhalfsize)) return 0;
00590
00591 return 1;
00592 }
00593
00594
00595