proj home

Files   Classes   Functions   Hierarchy  

tetrahedron.h

Go to the documentation of this file.
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 

Generated on Fri Mar 4 00:49:30 2011 for Chelton Evans Source by  doxygen 1.5.8