Files Classes Functions Hierarchy
00001 #ifndef TETRAHEDRON_H 00002 #define TETRAHEDRON_H 00003 00004 #include <cassert> 00005 00006 #include <halfspaceD3.h> 00007 #include <gausselim.h> 00008 #include <mathlib.h> 00009 #include <point.h> 00010 #include <triangle.h> 00011 #include <triangle3D.h> 00012 #include <typedefs.h> 00013 00020 template< typename PT, typename PD > 00021 class tetrahedron 00022 { 00023 public: 00024 00025 typedef PT PTtype; 00026 typedef PD PDtype; 00027 00029 PT pi[4]; 00030 00032 tetrahedron() {} 00035 tetrahedron 00036 ( 00037 PT const & p0_, 00038 PT const & p1_, 00039 PT const & p2_, 00040 PT const & p3_ 00041 ); 00042 00045 void construct 00046 ( 00047 PT const & p0_, 00048 PT const & p1_, 00049 PT const & p2_, 00050 PT const & p3_ 00051 ); 00052 00056 void constructUnordered 00057 ( 00058 PT const & p0_, 00059 PT const & p1_, 00060 PT const & p2_, 00061 PT const & p3_ 00062 ); 00063 00065 void centroid(PT & x) const; 00066 00071 void equilaterali(PT & x, uint i) const; 00072 00074 void circumcenter(PT & x) const; 00076 void circumcenter(PT & x, uintc i) const; 00077 00078 void verticiespoint(PT & x, uintc i) const; 00079 00081 void triangleverticiespoint(PT & x, uintc i) const; 00082 00085 //PT const bisectangle(uintc i) const; 00086 00087 00091 void trianglei 00092 ( 00093 triangle3D<PT,PD> & x, 00094 uintc i 00095 ) const; 00096 00097 00098 00101 boolc valid() const; 00102 00103 00104 typedef void (triangle3D<PT,PD>::*Fptr)(PT&) const; 00105 00109 void applytoself( tetrahedron<PT,PD> & tet, Fptr fn ) const; 00110 void applytoself( tetrahedron<PT,PD> & tet, Fptr fn, uintc n ) const; 00111 /* 00112 { 00113 triangle3D<PT,PD> ti[4]; 00114 PT qi[4]; 00115 for (uint i=0; i<4; ++i) 00116 { 00117 trianglei(ti[i],i); 00118 (ti[i].*fn)(qi[i]); 00119 } 00120 tet.constructUnordered(qi[0],qi[1],qi[2],qi[3]); 00121 } 00122 */ 00123 00124 00125 }; 00126 00127 00128 //--------------------------------------------------------- 00129 // Implementation 00130 00131 template< typename PT, typename PD > 00132 void tetrahedron<PT,PD>::applytoself 00133 ( 00134 tetrahedron<PT,PD> & tet, 00135 tetrahedron<PT,PD>::Fptr fn, 00136 uintc n 00137 ) const 00138 { 00139 if (n==0) 00140 return; 00141 00142 applytoself(tet,fn); 00143 00144 for (uint i=1; i<n; ++i) 00145 { 00146 tetrahedron<PT,PD> tet2(tet); 00147 tet2.applytoself(tet,fn); 00148 } 00149 } 00150 00151 00152 template< typename PT, typename PD > 00153 void tetrahedron<PT,PD>::applytoself 00154 ( 00155 tetrahedron<PT,PD> & tet, 00156 tetrahedron<PT,PD>::Fptr fn 00157 ) const 00158 { 00159 triangle3D<PT,PD> ti[4]; 00160 PT qi[4]; 00161 for (uint i=0; i<4; ++i) 00162 { 00163 trianglei(ti[i],i); 00164 (ti[i].*fn)(qi[i]); 00165 } 00166 tet.constructUnordered(qi[0],qi[1],qi[2],qi[3]); 00167 } 00168 00169 template< typename PT, typename PD > 00170 void tetrahedron<PT,PD>::equilaterali(PT & x, uint i) const 00171 { 00172 triangle3D<PT,PD> w; 00173 trianglei(w,i); 00174 PT a; 00175 w.centroid(a); 00176 PT b; 00177 w.normal(b); 00178 PT a2(a-w.pi[0]); 00179 // The distance between point 1 and 2, squared. 00180 PD l0 = (w.pi[1]-w.pi[2]).dot(); 00181 00182 // Currently must solve in doubles. 00183 PD t0; 00184 PD t1; 00185 //double t0; 00186 //double t1; 00187 solvequadratic(t0,t1,b.dot(),a2.dot(b)*2.0,a2.dot()-l0); 00188 PD t=t0; 00189 if (t<0) 00190 t=t1; 00191 assert(t>0); 00192 00193 x = a+b*t; 00194 } 00195 00196 template< typename PT, typename PD > 00197 void tetrahedron<PT,PD>::trianglei 00198 ( 00199 triangle3D<PT,PD> & x, 00200 uintc i 00201 ) const 00202 { 00203 PT q; 00204 switch (i) 00205 { 00206 case 0: x.construct(pi[3],pi[2],pi[1]); break; 00207 case 1: x.construct(pi[0],pi[2],pi[3]); break; 00208 case 2: x.construct(pi[1],pi[0],pi[3]); break; 00209 case 3: x.construct(pi[0],pi[1],pi[2]); break; 00210 default: assert(false); return; 00211 } 00212 00213 #ifndef NDEBUG 00214 halfspaceD3<PT,PD> h(x.pi[2],x.pi[1],x.pi[0]); 00215 assert( h.isInside(pi[i]) ); 00216 #endif 00217 } 00218 00219 template< typename PT, typename PD > 00220 void tetrahedron<PT,PD>::centroid(PT & x) const 00221 { 00222 x = pi[0]; 00223 x += pi[1]; 00224 x += pi[2]; 00225 x += pi[3]; 00226 x *= 0.25; 00227 } 00228 00229 template< typename PT, typename PD > 00230 boolc tetrahedron<PT,PD>::valid() const 00231 { 00232 PT a0(pi[1]-pi[0]); 00233 PT a1(pi[2]-pi[0]); 00234 PT a2; 00235 crossproduct::evalxyz(a2,a1,a0); 00236 00237 PT q(pi[3]-pi[0]); 00238 bool res = (q.x*a2.x+q.y*a2.y+q.z*a2.z>0); 00239 00240 return res; 00241 } 00242 00243 template< typename PT, typename PD > 00244 void tetrahedron<PT,PD>::circumcenter(PT & x) const 00245 { 00246 // Translate the points : p[0] is at the origin. 00247 PT p[4]; 00248 for (uint i=0; i<4; ++i) 00249 { 00250 p[i] = pi[i]; 00251 p[i] -= pi[0]; 00252 }; 00253 00254 PD e[] = 00255 { 00256 p[1].x, p[1].y, p[1].z, p[1].dot()*0.5, 00257 p[2].x, p[2].y, p[2].z, p[2].dot()*0.5, 00258 p[3].x, p[3].y, p[3].z, p[3].dot()*0.5 00259 }; 00260 00261 //gausselim<PD,3> g(e,1E-15); 00262 gausselim<PD> g(e,3); 00263 //cout << "Initial system" << endl; 00264 // g.print(); 00265 g.eval(); 00266 //cout << "Solve system." << endl; 00267 //g.print(); 00268 00269 PD s[3]; 00270 g.columnC(s); 00271 00272 x = pi[0]; 00273 x.x += s[0]; 00274 x.y += s[1]; 00275 x.z += s[2]; 00276 00277 // return pi[0]+(PT)(s[0],s[1],s[2]); 00278 } 00279 00280 00281 template< typename PT, typename PD > 00282 void tetrahedron<PT,PD>::circumcenter(PT & x, uintc i ) const 00283 { 00284 assert(false); 00285 /* 00286 // <TODO> 00287 // T N3(hi[i].nml); 00288 00289 T a(pi[(i+1)%4]); 00290 T b(pi[(i+2)%4]); 00291 T c(pi[(i+3)%4]); 00292 00293 crossprod< T > cross; 00294 T N1,N2; 00295 cross( N1, a-b, N3 ); 00296 cross( N2, c-b, N3 ); 00297 00298 T mba = (b+a)*0.5; 00299 T mbc = (b+c)*0.5; 00300 00301 T t0, t1; 00302 00303 d2matsolve 00304 ( 00305 t0, t1, 00306 N1.x, -N2.x, 00307 N1.y, -N2.y, 00308 mbc.x - mba.x, 00309 mbc.y - mba.y 00310 ); 00311 00312 return N1*t0 + mba; 00313 */ 00314 } 00315 00316 00317 /* 00318 template< typename PT, typename PD > 00319 PT const tetrahedron<PT,PD>::bisectangle(uintc i) const 00320 { 00321 PT A,B,C; 00322 PT X; 00323 00324 switch(i) 00325 { 00326 case 0: 00327 A = pi[1]; 00328 B = pi[2]; 00329 C = pi[3]; 00330 X = pi[0]; 00331 break; 00332 00333 case 1: 00334 A = pi[0]; 00335 B = pi[2]; 00336 C = pi[3]; 00337 X = pi[1]; 00338 break; 00339 00340 case 2: 00341 A = pi[0]; 00342 B = pi[1]; 00343 C = pi[3]; 00344 X = pi[2]; 00345 break; 00346 00347 case 3: 00348 A = pi[0]; 00349 B = pi[1]; 00350 C = pi[2]; 00351 X = pi[3]; 00352 break; 00353 00354 default: 00355 assert(false); 00356 } 00357 00358 PD a,b,c; 00359 a = sqrt((A - X).dot()); 00360 b = sqrt((B - X).dot()); 00361 c = sqrt((C - X).dot()); 00362 00363 //cout << SHOW(A) << endl; 00364 //cout << SHOW(B) << endl; 00365 //cout << SHOW(C) << endl; 00366 //cout << SHOW(X) << endl; 00367 00368 //cout << SHOW(a) << " " SHOW(b) << " " << SHOW(c) << " " << endl; 00369 assert(false); 00370 00371 PD den = 1.0 / ( (a + b + c ) * 2.0 ); 00372 //cout << SHOW(den); 00373 PT Z = (A*(b+c)+B*(a+c)+C*(a+b))*den; 00374 //cout << SHOW(b+c) << " " << SHOW(a+c) << " " << SHOW(a+b); 00375 //cout << SHOW((a+b+c)*2.0) << endl; 00376 //cout << SHOW(Z) << endl; 00377 00378 return Z; 00379 } 00380 */ 00381 00382 00383 00384 00385 template< typename PT, typename PD > 00386 void tetrahedron<PT,PD>::verticiespoint(PT & x, uintc i) const 00387 { 00388 PT a,b,c,d; 00389 00390 // Let d be the opposite point. 00391 // Choose a as vector vertex. 00392 00393 switch(i) 00394 { 00395 case 0: 00396 a=pi[3]; b=pi[2]; c=pi[1]; d=pi[0]; 00397 break; 00398 00399 case 1: 00400 a=pi[0]; b=pi[2]; c=pi[3]; d=pi[1]; 00401 break; 00402 00403 case 2: 00404 a=pi[0]; b=pi[1]; c=pi[3]; d=pi[2]; 00405 //cout << SHOW(a) << endl; 00406 //cout << SHOW(b) << endl; 00407 //cout << SHOW(c) << endl; 00408 break; 00409 00410 case 3: 00411 a=pi[0]; b=pi[1]; c=pi[2]; d=pi[3]; 00412 break; 00413 00414 default: 00415 assert(false); 00416 } 00417 00418 // ab 00419 PT A(b-a); 00420 // ac 00421 PT B(c-a); 00422 00423 PT N; 00424 crossproduct::eval(N,A,B); 00425 //crossprod< T >()(N,A,B); 00426 assert(N.dot()!=0.0); 00427 00428 x = N*( N.dot(a-d) / N.dot() )+ d; 00429 } 00430 00431 00432 00433 00434 00435 00436 00437 00438 template< typename PT, typename PD > 00439 void tetrahedron<PT,PD>::triangleverticiespoint(PT & x, uintc i) const 00440 { 00441 PT a,b,c; 00442 00443 switch(i) 00444 { 00445 case 0: 00446 a=pi[1]; b=pi[2]; c=pi[3]; 00447 break; 00448 00449 case 1: 00450 a=pi[0]; b=pi[2]; c=pi[3]; 00451 break; 00452 00453 case 2: 00454 a=pi[0]; b=pi[1]; c=pi[3]; 00455 //cout << SHOW(a) << endl; 00456 //cout << SHOW(b) << endl; 00457 //cout << SHOW(c) << endl; 00458 break; 00459 00460 case 3: 00461 a=pi[0]; b=pi[1]; c=pi[2]; 00462 break; 00463 00464 default: 00465 assert(false); 00466 } 00467 00468 PT ab = b - a; 00469 PT ac = c - a; 00470 00471 //cout << SHOW(ab) << endl; 00472 //cout << SHOW(ac) << endl; 00473 00474 PT w; 00475 crossproduct::eval(w,ab,ac); 00476 //crossprod< T > cross; 00477 //cross(w,ab,ac); 00478 00479 PT act; 00480 PT abt; 00481 crossproduct::eval(act,w,ac); 00482 crossproduct::eval(abt,w,ab); 00483 //cross(act,w,ac); 00484 //cross(abt,w,ab); 00485 00486 PT t0, t1; 00487 00488 // Usually only one solving is necessary. 00489 // However if the determinant is zero, try 00490 // all the other combinations, one should be ok. 00491 00492 // Assuming that the object is a tetrahedron: all the 00493 // four points are unique. 00494 00495 bool test = 00496 d2matsolve 00497 ( 00498 t0, t1, 00499 abt.x, -act.x, 00500 abt.y, -act.y, 00501 b.x - c.x, 00502 b.y - c.y 00503 ); 00504 00505 if (!test) 00506 { 00507 test = 00508 d2matsolve 00509 ( 00510 t0, t1, 00511 abt.x, -act.x, 00512 abt.z, -act.z, 00513 b.x - c.x, 00514 b.z - c.z 00515 ); 00516 } 00517 00518 if (!test) 00519 { 00520 test = 00521 d2matsolve 00522 ( 00523 t0, t1, 00524 abt.y, -act.y, 00525 abt.z, -act.z, 00526 b.y - c.y, 00527 b.z - c.z 00528 ); 00529 } 00530 00531 x = c + abt * t0; 00532 } 00533 00534 00535 template< typename PT, typename PD > 00536 tetrahedron<PT,PD>::tetrahedron 00537 ( 00538 PT const & p0, 00539 PT const & p1, 00540 PT const & p2, 00541 PT const & p3 00542 ) 00543 { 00544 construct(p0,p1,p2,p3); 00545 } 00546 00547 template< typename PT, typename PD > 00548 void tetrahedron<PT,PD>::construct 00549 ( 00550 PT const & p0, 00551 PT const & p1, 00552 PT const & p2, 00553 PT const & p3 00554 ) 00555 { 00556 pi[0] = p0; 00557 pi[1] = p1; 00558 pi[2] = p2; 00559 pi[3] = p3; 00560 00561 assert(valid()); 00562 } 00563 00564 template< typename PT, typename PD > 00565 void tetrahedron<PT,PD>::constructUnordered 00566 ( 00567 PT const & p0, 00568 PT const & p1, 00569 PT const & p2, 00570 PT const & p3 00571 ) 00572 { 00573 pi[0] = p0; 00574 pi[1] = p1; 00575 pi[2] = p2; 00576 pi[3] = p3; 00577 00578 if (valid()==false) 00579 { 00580 pi[0] = p2; 00581 pi[2] = p0; 00582 00583 assert(valid()); 00584 } 00585 } 00586 00587 00588 #endif 00589 00590
1.5.8