mFES - molecular Finite Element Solver  0.4
Voxel.h
Go to the documentation of this file.
00001 #ifndef VOXEL_H
00002 #define VOXEL_H
00003 
00004 // c++ -O2 -fopenmp voxel.cpp help.cpp adtree.cpp optmem.cpp -I../../libsrc/include
00005 // c++ -O2 -fopenmp voxel.cpp help.cpp adtree.cpp optmem.cpp -I/home/parallels/ngsolve/sources/netgen-5.1/libsrc/include -o voxel
00006 // tar -czf voxel.tar.gz *.cpp *.pqr
00007 
00008 
00009 #include <gprim.hpp>
00010 #include <lib/Voxel/adtree.h>
00011 #include <lib/Voxel/help.h>
00012 #include <lib/Voxel/optmem.h>
00013 
00014 using namespace netgen;
00015 
00016 
00017 class Voxel {
00018 
00019 public:
00020 
00021         Voxel(){
00022                 rball = 1.4;
00023         };
00024         ~Voxel(){};
00025 
00026         int calcSurface(mMesh &mSurface, vector<Atom> &atomList, INI& ini, string fileName, int gridSize = 64, bool exclusion = false)
00027 {
00028   //    int gridSize = atoi(ini.get<string>("model.grid_resolution").c_str());
00029         rball = atof(ini.get<string>("experiment.probe_radius").c_str());
00030 
00031         float extendR = 0;
00032         if (exclusion){
00033           float ionc = atof(ini.get<string>("experiment.ionc").c_str());
00034           if (ionc > 0){
00035             extendR = atof(ini.get<string>("experiment.ionr").c_str());
00036           }
00037         }
00038 
00039   int nx = gridSize;   // number of intervals
00040   int ny = gridSize;
00041   int nz = gridSize;
00042 
00043   Array<Point<3> > gridpoints(long(nx+1)*(ny+1)*(nz+1));
00044   Array<float> values(long(nx+1)*(ny+1)*(nz+1));
00045   Array<Vec<3> > dvalues(long(nx+1)*(ny+1)*(nz+1));
00046 
00047   clock_t t1 = clock();
00048   rmax = 0;
00049 
00050   for (unsigned int i = 0; i < atomList.size(); i++)
00051     {
00052           Point3<float> coord = atomList.at(i).getCoord();
00053           double r = atomList.at(i).getRadius()+extendR;
00054           pnts.Append (Point<3>(coord.X(),coord.Y(),coord.Z()));
00055           rad.Append (r);
00056           if (r > rmax) rmax = r;
00057     }
00058   rmax += extendR;
00059 
00060   int increase = ceil(rmax)+1; //ceil(rmax); // 5 also works?
00061   cout << "rmax = " << rmax << endl;
00062 
00063   clock_t t2 = clock();
00064 
00065   netgen::Box<3> box;
00066   box.Set (pnts[0]);
00067   for (int i = 1; i < pnts.Size(); i++) box.Add (pnts[i]);
00068   box.Increase (increase);
00069   Point<3> pmin = box.PMin();
00070   Point<3> pmax = box.PMax();
00071 
00072 
00073   searchtree = new Point3dTree (pmin, pmax);
00074   for (int i = 0; i < pnts.Size(); i++)
00075     searchtree -> Insert (pnts[i], i);
00076 
00077 
00078   for (int ix = 0; ix <= nx; ix++)
00079     for (int iy = 0; iy <= ny; iy++)
00080       for (int iz = 0; iz <= nz; iz++)
00081         {
00082           int ind = ix + (nx+1) * (iy + (ny+1)*iz);
00083           gridpoints[ind] = Point<3> (pmin(0) + (pmax(0)-pmin(0))*ix/(nx),
00084                                       pmin(1) + (pmax(1)-pmin(1))*iy/(ny),
00085                                       pmin(2) + (pmax(2)-pmin(2))*iz/(nz));
00086         }
00087 
00088   double diag = sqrt ( sqr ((pmax(0)-pmin(0)) / nx) +
00089                         sqr ((pmax(1)-pmin(1)) / ny) +
00090                         sqr ((pmax(2)-pmin(2)) / nz));
00091     
00092   SetValues (pmin, pmax, diag, gridpoints, values, dvalues);
00093 
00094     // smoothing ...
00095     // not always working without intersection e.g. (2lzt, no opt, ARG-61)
00096     int smoothingsteps = 0;
00097 
00098     for (int j = 0; j < smoothingsteps; j++)
00099 
00100         for (int ix = 1; ix < nx; ix++)
00101 
00102             for (int iy = 1; iy < ny; iy++)
00103 
00104                 for (int iz = 1; iz < nz; iz++)
00105 
00106                 {
00107 
00108                     int ind = ix + (nx+1) * (iy + (ny+1)*iz);
00109 
00110                     int i2[] = { ind+1, ind-1, ind+nx+1, ind-(nx+1), ind+(nx+1)*(ny+1), ind-(nx+1)*(ny+1) };
00111 
00112                     double sum = 0.0;
00113 
00114                     int cnt = 0;
00115 
00116                     for (int j = 0; j < 6; j++)
00117 
00118                         if (values[i2[j]] < 1e9)
00119 
00120                         {
00121 
00122                             sum += values[i2[j]];
00123 
00124                             cnt++;
00125 
00126                         }
00127 
00128                     if (cnt)
00129                         values[ind] = sum/cnt;
00130                 }
00131     
00132     
00133   clock_t t3 = clock();
00134 
00135   double h = Dist(pmin, pmax)/nx;
00136   for (int i = 0; i < values.Size(); i++)
00137     if (fabs (values[i]) < 0.02 * dvalues[i].Length() * h)
00138      {
00139         gridpoints[i] -= (values[i]/dvalues[i].Length2()) * dvalues[i];
00140         values[i] = 0;
00141      }
00142 
00143   stlout.open (fileName.c_str());
00144   stlout << "solid" << endl;
00145   stlout.precision(12);
00146   MakeSTL (pmin, pmax, nx, ny, nz, gridpoints, values, dvalues);
00147   stlout << "endsolid" << endl;
00148 
00149   clock_t t4 = clock();
00150 
00151   cout << "load: " << double(t2-t1) / CLOCKS_PER_SEC << " secs" << endl;
00152   cout << "find f: " << double(t3-t2) / CLOCKS_PER_SEC << " secs" << endl;
00153   cout << "write stl (" << fileName <<"): " << double(t4-t3) / CLOCKS_PER_SEC << " secs" << endl;
00154 
00155   stlout.close();
00156   return 0;
00157 }
00158 
00159 private:
00160 
00161         double rball;
00162         double rmax;
00163         ofstream stlout;
00164 
00165         Array<Point<3> > pnts;
00166         Array<double> rad;
00167         Point3dTree * searchtree;
00168 
00169 void SetValues (Point<3> pmin, Point<3> pmax, double diag,
00170                 // int nx, int ny, int nz,
00171                 Array<Point<3> > & gridpoints,
00172                 Array<float> & values,
00173                 Array<Vec<3> >  & dvalues)
00174 {
00175   int cnt = 0;
00176 
00177   int cnt3a = 0, cnt3b = 0, cnt3c = 0;
00178 
00179   cout << "Setting up level-set function" << endl;
00180 
00181 #pragma omp parallel
00182   {
00183     Array<int> indices1, indices;
00184 
00185 
00186 #pragma omp for
00187     for (int i = 0; i < gridpoints.Size(); i++)
00188       {
00189 
00190 #pragma omp atomic
00191         cnt++;
00192 
00193 
00194         if (cnt % 1000 == 0)
00195           {
00196 #pragma omp critical(print)
00197             {
00198               cout << "\r" << int (100 * double(cnt)/gridpoints.Size()) << " %" << flush;
00199             }
00200           }
00201         /*
00202           int ind = ix + (nx+1) * (iy + (ny+1)*iz);
00203           Point<3> p(pmin(0) + (pmax(0)-pmin(0))*ix/nx,
00204           pmin(1) + (pmax(1)-pmin(1))*iy/ny,
00205           pmin(2) + (pmax(2)-pmin(2))*iz/nz);
00206         */
00207         int ind = i;
00208         int extend = 6;
00209 //        if (rmax > 5)
00210 //              extend = 2*rmax;
00211 
00212         Point<3> p = gridpoints[ind];
00213 
00214         searchtree -> GetIntersecting (p - Vec<3>(extend,extend,extend), p+Vec<3>(extend,extend,extend), indices1);
00215         double minf = 1e10;
00216         Vec<3> df;
00217 
00218 
00219         indices.SetSize(0);
00220         for (int j = 0; j < indices1.Size(); j++)
00221           if (Dist2 (pnts[indices1[j]], p) < sqr(rad[indices1[j]]+2*rball))
00222             indices.Append (indices1[j]);
00223 
00224         for (int jj = 0; jj < indices.Size(); jj++)
00225           {
00226             int j = indices[jj];
00227             // double fj = rad[j] * (Dist2 (p, pnts[j]) / sqr(rad[j]) - 1);
00228             double fj = Dist (p, pnts[j]) - rad[j];
00229             if (fj < minf)
00230               {
00231                 minf = fj;
00232                 df = 1.0/Dist(p,pnts[j]) * (p-pnts[j]);
00233               }
00234           }
00235           
00236           
00237 
00238           if (minf < -diag)
00239 
00240           {
00241 
00242               values[ind] = minf;
00243 
00244               dvalues[ind] = df;
00245 
00246               continue;
00247 
00248           }
00249 
00250           
00251 
00252 
00253 
00254         for (int jj = 0; jj < indices.Size(); jj++)
00255           for (int kk = 0; kk < jj; kk++)
00256             {
00257               int j = indices[jj];
00258               int k = indices[kk];
00259 
00260               double r1 = rad[j];
00261               double r2 = rad[k];
00262 
00263               Point<3> c1 = pnts[j];
00264               Point<3> c2 = pnts[k];
00265 
00266               Vec<3> ex = c2-c1;
00267               double dist2 = ex.Length2();
00268               if (dist2 > sqr(r1+r2+2*rball)) continue;
00269               double dist = sqrt(dist2);
00270               ex /= dist;
00271 
00272               double px = ex * (p - c1);
00273               if (px <= -rball || px > dist+rball+r2) continue;
00274 
00275               double py = sqrt ( Dist2(p,c1) - px*px );
00276 
00277               double tx = 1.0 / (2*dist) * (sqr(dist)+(r1-r2)*(2*rball+r1+r2));
00278               double ty = sqrt (sqr(r1+rball) - tx*tx);
00279 
00280               // if ( (py / px < ty / tx) &&  (py / (dist-px) < ty / (dist-tx)))
00281               if ( (py * tx < ty * px) && ( (dist-tx)*py < ty * (dist-px) ) )
00282                 {
00283                   // double fj = rball * (1-(sqr(px-tx)+sqr(py-ty)) / sqr(rball));
00284                   double fj = rball - sqrt(sqr(px-tx)+sqr(py-ty));
00285 
00286                   double x0 = tx - ty/(ty-py) * (tx-px);
00287                   Point<3> p0 = c1+x0*ex;
00288                   Vec<3> dir = p - p0;
00289                   dir.Normalize();
00290                   if (fj < minf)
00291                     {
00292                       minf = fj;
00293                       df = dir;
00294                     }
00295                 }
00296             }
00297 
00298           if ((minf < -diag) || (minf > diag + rball))
00299 
00300           {
00301 
00302               values[ind] = minf;
00303 
00304               dvalues[ind] = df;
00305 
00306               continue;
00307 
00308           }
00309           
00310         for (int jj = 0; jj < indices.Size(); jj++)
00311           for (int kk = 0; kk < jj; kk++)
00312             for (int ll = 0; ll < kk; ll++)
00313               {
00314 #pragma omp atomic
00315                 cnt3a++;
00316 
00317                 int j = indices[jj];
00318                 int k = indices[kk];
00319                 int l = indices[ll];
00320 
00321                 double r1 = rad[j];
00322                 double r2 = rad[k];
00323                 double r3 = rad[l];
00324 
00325                 Point<3> c1 = pnts[j];
00326                 Point<3> c2 = pnts[k];
00327                 Point<3> c3 = pnts[l];
00328 
00329                 if (Dist2(c1, p) > sqr(r1+2*rball)) continue;
00330                 if (Dist2(c2, p) > sqr(r2+2*rball)) continue;
00331                 if (Dist2(c3, p) > sqr(r3+2*rball)) continue;
00332 
00333 
00334                 Vec<3> t1 = c2-c1;
00335                 Vec<3> t2 = c3-c1;
00336                 Vec<3> n = Cross(t1, t2);
00337                 n.Normalize();
00338 
00339                 Mat<2> mat;
00340                 Vec<2> rhs, sol;
00341                 mat(0,0) = t1*t1;
00342                 mat(0,1) = mat(1,0) = t1*t2;
00343                 mat(1,1) = t2*t2;
00344 
00345                 rhs(0) = 0.5 * (sqr(r1+rball) - sqr(r2+rball) + Dist2(c1,c2));
00346                 rhs(1) = 0.5 * (sqr(r1+rball) - sqr(r3+rball) + Dist2(c1,c3));
00347 
00348                 mat.Solve (rhs, sol);
00349 
00350                 Point<3> cp = c1 + sol(0) * t1 + sol(1) * t2;
00351                 if ( sqr(r1+rball) <= Dist2(c1,cp) ) continue;
00352 
00353                 double lamn = sqrt ( sqr(r1+rball) - Dist2(c1,cp) );
00354                 // c = cp +/- lamn n
00355 
00356                 Vec<2> rhs2, sol2;
00357                 rhs2(0) = t1 * (p-c1);
00358                 rhs2(1) = t2 * (p-c1);
00359                 mat.Solve (rhs2, sol2);
00360                 double lamn2 = n * (p-c1);
00361 
00362 #pragma omp atomic
00363                     cnt3b++;
00364 
00365 
00366                 if ( sol2(0) > sol(0) * fabs(lamn2)/lamn &&
00367                      sol2(1) > sol(1) * fabs(lamn2)/lamn &&
00368                      (1-sol2(0)-sol2(1)) > (1-sol(0)-sol(1)) * fabs(lamn2)/lamn)
00369 
00370                   {
00371 #pragma omp atomic
00372                     cnt3c++;
00373 
00374 
00375                     Point<3> sp1 = cp + lamn * n;
00376                     Point<3> sp2 = cp - lamn * n;
00377 
00378 
00379                     /*
00380                     double fj = max (rball - Dist(sp1, p), rball - Dist(sp2, p));
00381                     if (fj < minf)
00382                       {
00383                         minf = fj;
00384 
00385                         Vec<3> dir;
00386                         if (lamn2 > 0)
00387                           dir = sp1-p;
00388                         else
00389                           dir = sp2-p;
00390                         dir.Normalize();
00391                         df = dir;
00392                       }
00393                     */
00394                     if (lamn2 > 0)
00395                       {
00396                         Vec<3> dir = sp1-p;
00397                         double len = dir.Length();
00398                         double fj = rball - len;
00399                         if (fj < minf)
00400                           {
00401                             dir.Normalize();
00402                             minf = fj;
00403                             df = dir;
00404                           }
00405                       }
00406                     else
00407                       {
00408                         Vec<3> dir = sp2-p;
00409                         double len = dir.Length();
00410                         double fj = rball - len;
00411                         if (fj < minf)
00412                           {
00413                             dir.Normalize();
00414                             minf = fj;
00415                             df = dir;
00416                           }
00417                       }
00418 
00419                   }
00420               }
00421 
00422           if ((minf < -diag) || (minf > diag + rball))
00423 
00424           {
00425 
00426               values[ind] = minf;
00427 
00428               dvalues[ind] = df;
00429 
00430               continue;
00431 
00432           }
00433           
00434           
00435 
00436           // if (false)
00437 
00438           for (int jj = 0; jj < indices.Size(); jj++)
00439 
00440               for (int kk = 0; kk < jj; kk++)
00441 
00442                   for (int ll = 0; ll < kk; ll++)
00443 
00444                       for (int mm = 0; mm < ll; mm++)
00445 
00446                       {
00447 
00448                           int j = indices[jj];
00449 
00450                           int k = indices[kk];
00451 
00452                           int l = indices[ll];
00453 
00454                           int m = indices[mm];
00455 
00456                           
00457 
00458                           double r1 = rad[j];
00459 
00460                           double r2 = rad[k];
00461 
00462                           double r3 = rad[l];
00463 
00464                           double r4 = rad[m];
00465 
00466                           
00467 
00468                           Point<3> c1 = pnts[j];
00469 
00470                           Point<3> c2 = pnts[k];
00471 
00472                           Point<3> c3 = pnts[l];
00473 
00474                           Point<3> c4 = pnts[m];
00475 
00476                           
00477 
00478                           if (Dist2(c1, p) > sqr(r1+2*rball)) continue;
00479 
00480                           if (Dist2(c2, p) > sqr(r2+2*rball)) continue;
00481 
00482                           if (Dist2(c3, p) > sqr(r3+2*rball)) continue;
00483 
00484                           if (Dist2(c4, p) > sqr(r4+2*rball)) continue;
00485 
00486                           
00487 
00488                           
00489 
00490                           Vec<3> v1 = c2-c1;
00491 
00492                           Vec<3> v2 = c3-c1;
00493 
00494                           Vec<3> v3 = c4-c1;
00495 
00496                           
00497 
00498                           Mat<3> mat;
00499 
00500                           Vec<3> rhs, sol;
00501 
00502                           for (int j = 0; j < 3; j++)
00503 
00504                           {
00505 
00506                               mat(j,0) = v1(j);
00507 
00508                               mat(j,1) = v2(j);
00509 
00510                               mat(j,2) = v3(j);
00511 
00512                               rhs(j) = p(j)-c1(j);
00513 
00514                           }
00515 
00516                           mat.Solve (rhs, sol);
00517 
00518                           
00519 
00520                           if (sol(0) < 0 || sol(1) < 0 || sol(2) < 0 || sol(0)+sol(1)+sol(2) > 1)
00521 
00522                               continue;
00523 
00524                           
00525 
00526                           if (fabs (Det(mat)) < 1e-10)
00527 
00528                           {
00529 
00530                               /*
00531 
00532                                cout << "indices = " << indices << endl;
00533 
00534                                cout << "points = " << pnts << endl;
00535 
00536                                cout << "ci = " << c1 << ", " << c2 << ", " << c3 << ", " << c4 << endl;
00537 
00538                                cout << "vi = " << v1 << ", " << v2 << ", " << v3 << endl;
00539 
00540                                */
00541 
00542                               continue;
00543 
00544                           }
00545 
00546                           
00547 
00548                           /*
00549 
00550                            cout << "ci = " << c1 << ", " << c2 << ", " << c3 << ", " << c4 << endl;
00551 
00552                            cout << "p = " << p << ", sol = " << sol << endl;
00553 
00554                            cout << "det = " << Det(mat) << endl;
00555 
00556                            */
00557 
00558                           
00559 
00560                           Point<3> pts[4] = { c1, c2, c3, c4 };
00561 
00562                           double rs[4] = { r1, r2, r3, r4 };
00563 
00564                           
00565 
00566                           double vmax = -1e99;
00567 
00568                           Vec<3> vdir;
00569 
00570                           
00571 
00572                           for (int i = 0; i < 4; i++)
00573 
00574                           {
00575 
00576                               Point<3> fc1 = pts[i];
00577 
00578                               Point<3> fc2 = pts[(i+1)%4];
00579 
00580                               Point<3> fc3 = pts[(i+2)%4];
00581 
00582                               
00583 
00584                               double fr1 = rs[i];
00585 
00586                               double fr2 = rs[(i+1)%4];
00587 
00588                               double fr3 = rs[(i+2)%4];
00589 
00590                               
00591 
00592                               
00593 
00594                               Vec<3> t1 = fc2-fc1;
00595 
00596                               Vec<3> t2 = fc3-fc1;
00597 
00598                               Vec<3> n = Cross(t1, t2);
00599 
00600                               n.Normalize();
00601 
00602                               
00603 
00604                               if (n * (pts[(i+3)%4]-fc1) > 0) n *= -1;
00605 
00606                               
00607 
00608                               Mat<2> mat;
00609 
00610                               Vec<2> rhs, sol;
00611 
00612                               mat(0,0) = t1*t1;
00613 
00614                               mat(0,1) = mat(1,0) = t1*t2;
00615 
00616                               mat(1,1) = t2*t2;
00617 
00618                               
00619 
00620                               rhs(0) = 0.5 * (sqr(fr1+rball) - sqr(fr2+rball) + Dist2(fc1,fc2));
00621 
00622                               rhs(1) = 0.5 * (sqr(fr1+rball) - sqr(fr3+rball) + Dist2(fc1,fc3));
00623 
00624                               
00625 
00626                               mat.Solve (rhs, sol);
00627 
00628                               
00629 
00630                               Point<3> cp = fc1 + sol(0) * t1 + sol(1) * t2;
00631 
00632                               if ( sqr(fr1+rball) <= Dist2(fc1,cp) )
00633 
00634                               {
00635 
00636                                   vmax = 1e99;
00637 
00638                                   continue;
00639 
00640                               }
00641 
00642                               
00643 
00644                               double lamn = sqrt ( sqr(fr1+rball) - Dist2(fc1,cp) );
00645 
00646                               // c = cp +/- lamn n
00647 
00648                               
00649 
00650                               Point<3> sp1 = cp + lamn * n;
00651 
00652                               
00653 
00654                               // cout << "dist i = " << Dist (sp1, fc1) << ", " << Dist(sp1, fc2) << ", " << Dist(sp1, fc3) << endl;
00655 
00656                               // cout << "ri+rball = " << fr1+rball << ", " << r2+rball << ", " << r3+rball << endl << endl;
00657 
00658                               
00659 
00660                               Vec<3> dir = sp1-p;
00661 
00662                               double len = dir.Length();
00663 
00664                               double fj = rball - len;
00665 
00666                               
00667 
00668                               if (fj > vmax)
00669 
00670                               {
00671 
00672                                   vmax = fj;
00673 
00674                                   dir.Normalize();
00675 
00676                                   vdir = dir;
00677 
00678                               }
00679 
00680                           }
00681 
00682                           
00683 
00684                           
00685 
00686                           if (vmax < minf)
00687 
00688                           {
00689 
00690                               minf = vmax;
00691 
00692                               df = vdir;
00693 
00694                           }
00695 
00696                       }
00697 
00698           
00699 
00700           
00701 
00702           
00703 
00704 
00705 
00706         values[ind] = minf;
00707         dvalues[ind] = df;
00708       }
00709   }
00710 
00711   cout << "\r" << "100 %" << endl;
00712   // cout << "cnt trip-balls: " << cnt3a << " " << cnt3b << " " << cnt3c << endl;
00713 }
00714 
00715 
00716 
00717 void WriteTrig (Point<3> p1, Point<3> p2, Point<3> p3, Vec<3> n)
00718 {
00719 
00720   if (Dist (p1, p2) < 1e-10) return;
00721   if (Dist (p1, p3) < 1e-10) return;
00722   if (Dist (p2, p3) < 1e-10) return;
00723 
00724   Vec<3> nt = Cross(p2-p1,p3-p1);
00725   if (nt.Length() < 1e-5 * (p2-p1).Length() * (p3-p1).Length())
00726     {
00727       // if (nt.Length() < 1e-12 * (p2-p1).Length() * (p3-p1).Length()) return;
00728       cout << "flat trig: " << nt.Length() / ((p2-p1).Length() * (p3-p1).Length()) << endl;
00729     }
00730 
00731   if (nt * n < 0) Swap (p2, p3);
00732 
00733   stlout << "facet normal " << n(0) << " " << n(1) << " " << n(2) << "\n";
00734   stlout << "  outer loop" << "\n";
00735   stlout << "    vertex " << p1(0) << " " << p1(1) << " " << p1(2) << "\n";
00736   stlout << "    vertex " << p2(0) << " " << p2(1) << " " << p2(2) << "\n";
00737   stlout << "    vertex " << p3(0) << " " << p3(1) << " " << p3(2) << "\n";
00738   stlout << "  endloop" << "\n";
00739   stlout << "endfacet" << "\n";
00740 }
00741 
00742 double CutEdge (double f1, double f2)
00743 {
00744   if (fabs (f1) < 1e-10) return 0;
00745   return f1/(f1-f2);
00746 }
00747 
00748 void MakeTetSTL (Point<3> pnts[], double valtet[4], Vec<3> dvaltet[4])
00749 {
00750   int npos = 0;
00751   for (int j = 0; j < 4; j++)
00752     if (valtet[j] > 0) npos++;
00753 
00754   if (npos == 0 || npos == 4) return;
00755 
00756     /*
00757 
00758      int nzero = 0;
00759 
00760      for (int j = 0; j < 4; j++)
00761 
00762      if (fabs (valtet[j]) < 1e-10) nzero++;
00763 
00764      if (nzero >= 2)
00765 
00766      {
00767 
00768      cout << nzero << " vertex-values 0 on tet:" << endl;
00769 
00770      for (int j = 0; j < 4; j++)
00771 
00772      cout << pnts[j] << ": " << valtet[j] << endl;
00773 
00774      }
00775 
00776      */
00777     
00778   const int edges[6][2] =
00779     { { 0, 1 }, { 0, 2 }, { 0, 3 },
00780       { 2, 3 }, { 1, 3 }, { 1, 2 } };
00781 
00782   double lame[6] = { -1 };
00783   Point<3> cutp[4];
00784   int cutpi = 0;
00785   for (int j = 0; j < 6; j++)
00786     {
00787       int pi1 = edges[j][0];
00788       int pi2 = edges[j][1];
00789       if ((valtet[pi1] > 0) != (valtet[pi2] > 0))
00790         {
00791           Vec<3> ve = pnts[pi2]-pnts[pi1];
00792           double lam = CutEdge (valtet[pi1], valtet[pi2]);
00793           cutp[cutpi] = pnts[pi1] + lam * (pnts[pi2]-pnts[pi1]);
00794           cutpi++;
00795         }
00796     }
00797 
00798 
00799   // calc grad f (normal vector)
00800   Mat<3,3> mat;
00801   for (int i = 0; i < 3; i++)
00802     for (int j = 0; j < 3; j++)
00803       mat(i,j) = pnts[i](j) - pnts[3](j);
00804   Vec<3> rhs, sol;
00805   for (int i = 0; i < 3; i++)
00806     rhs(i) = valtet[i] - valtet[3];
00807   mat.Solve (rhs, sol);
00808 
00809   if (npos == 1 || npos == 3)   // cut 3 edges
00810     WriteTrig (cutp[0], cutp[1], cutp[2], sol);
00811 
00812   if (npos == 2)   // cut 4 edges
00813     {
00814       WriteTrig (cutp[0], cutp[1], cutp[2], sol);
00815       WriteTrig (cutp[0], cutp[2], cutp[3], sol);
00816     }
00817 }
00818 
00819 
00820 void MakeCubeSTL (//Point<3> p1, Point<3> p2,
00821                   Point<3> pointcube[8],
00822                   double valcube[8], Vec<3> dvalcube[8])
00823 {
00824   const int tets[6][4] =
00825     { { 0, 1, 2, 4 },
00826       { 1, 2, 4, 5 },
00827       { 2, 4, 5, 6 },
00828       { 1, 3, 2, 5 },
00829       { 3, 2, 5, 6 },
00830       { 3, 6, 5, 7 } };
00831 
00832   double valtet[4];
00833   Vec<3> dvaltet[4];
00834   Point<3> pnts[4];
00835 
00836   for (int j = 0; j < 6; j++)
00837     {
00838       for (int k = 0; k < 4; k++)
00839         {
00840           valtet[k] = valcube[tets[j][k]];
00841           dvaltet[k] = dvalcube[tets[j][k]];
00842           pnts[k] = pointcube[tets[j][k]];
00843         }
00844 
00845       MakeTetSTL (pnts, valtet, dvaltet);
00846     }
00847 }
00848 
00849 
00850 
00851 void MakeSTL (Point<3> pmin, Point<3> pmax,
00852               int nx, int ny, int nz,
00853               Array<Point<3> > & gridpoints,
00854               Array<float> & values,
00855               Array<Vec<3> > & dvalues)
00856 {
00857   double valcube[8];
00858   Vec<3> dvalcube[8];
00859   Point<3> pointcube[8];
00860 
00861   cout << "Writing stl file" << endl;
00862   for (int ix = 0; ix < nx; ix++)
00863     {
00864       cout << "\r" << ix << "/" << nx << flush;
00865       for (int iy = 0; iy < ny; iy++)
00866         for (int iz = 0; iz < nz; iz++)
00867           {
00868             for (int jx = 0, jj = 0; jx < 2; jx++)
00869               for (int jy = 0; jy < 2; jy++)
00870                 for (int jz = 0; jz < 2; jz++, jj++)
00871                   {
00872                     int ind = ix+jx + (nx+1) * (iy+jy + (ny+1)*(iz+jz));
00873                     valcube[jj] = values[ind];
00874                     dvalcube[jj] = dvalues[ind];
00875                     pointcube[jj] = gridpoints[ind];
00876                   }
00877 
00878             int npos = 0;
00879             for (int j = 0; j < 8; j++)
00880               if (valcube[j] > 0) npos++;
00881             if (npos == 0 || npos == 8) continue;
00882 
00883             MakeCubeSTL (pointcube, valcube, dvalcube);
00884           }
00885     }
00886   cout << "\r" << nx << "/" << nx << endl;
00887 }
00888 
00889 
00890 };
00891 
00892 
00893 
00894 #endif