mFES - molecular Finite Element Solver  0.4
Model.h
Go to the documentation of this file.
00001 
00012 //#include <solve.hpp>
00013 #include <iostream>
00014 #include <fstream>
00015 #include <string>
00016 #include <sstream>
00017 #include <boost/timer.hpp>
00018 
00019 #include "LSMS.h"
00020 #include "Voxel.h"
00021 #include "VCG.h"
00022 
00023 
00024 using namespace std;
00025 using namespace vcg;
00026 
00027 
00028 namespace nglib {
00029         #include <nglib.h>
00030 }
00031 using namespace nglib;
00032 
00033 
00034 typedef boost::property_tree::ptree INI;
00035 
00056 class Model {
00057 public:
00060   static bool exclusionSurface;
00061 
00078   void calcIonLayer(vector<Atom> &atomList, INI &ini, string fname = "exclusion.vol"){
00079     LSMS lmSurface;
00080     mMesh mSurface;
00081     int mask = 1;
00082     
00085     if (!boost::filesystem::exists( "exclusion.stl" )){
00086       cout << "Calculating ion exclusion layer " << fname << "..." << endl;
00087       boost::timer t;
00088       ofstream time;
00091       time.open ("times");
00093       if (lmSurface.calcMC(mSurface, atomList, ini, "exclusion")){            
00095         clean(mSurface);
00098         smooth(mSurface, ini);
00101         tri::io::ExporterSTL<mMesh>::Save(mSurface,"exclusion.stl",false);
00102 
00104         double currentTime = t.elapsed();
00105         time << "exclusion_surface " << currentTime << " s" << endl;
00106         cout << "mFES: ion exclusion layer " << fname << "surface calculation took " << currentTime << " seconds." <<endl;
00107         time.close();
00108       }
00109     }
00110   }
00111 
00112 
00128   void calcModel(vector<Atom> &atomList, INI &ini, string fname = "", bool cavity = false){
00129 
00131     LSMS lmSurface;
00133     mMesh mSurface;
00134           
00136     string volume_vol = ini.get<string>("model.volume_vol");
00138     string surface_stl = ini.get<string>("model.surface_stl");
00142     string generator = ini.get<string>("model.generator");
00144     int generatorResolution = atoi(ini.get<string>("model.grid_resolution").c_str());
00145 
00147     string generatorResidue = ini.get_optional<string>("model.generator_residue").get_value_or("standard");
00150     int generatorModelResolution = atoi(ini.get_optional<string>("model.grid_residue_resolution").get_value_or("256").c_str());
00151 
00153     boost::optional<string> ionc = ini.get_optional<string>("experiment.ionc");
00154     
00157     if(ionc){
00158       string ionc = ini.get<string>("experiment.ionc");
00159       if (atof(ionc.c_str()) != 0){
00160         exclusionSurface = true;
00161       }
00162     }
00163     
00164 
00165     int mask = 1;
00166     if (generator == "standard" && cavity && !boost::filesystem::exists( "cavity.vol" )){
00169       cout << "Calculating cavities..." << endl;
00170 
00172       boost::timer t;
00173       ofstream time;
00174       time.open ("times");
00175       
00177       if (lmSurface.calcMC(mSurface, atomList, ini, "cavity")){
00179         clean(mSurface);
00180         smooth(mSurface, ini);
00181         
00183         if (surface_stl != "" )
00184           tri::io::ExporterSTL<mMesh>::Save(mSurface,"cavity.stl",false);
00185         
00186         double currentTime = t.elapsed();
00187         time << "cavity_surface " << currentTime << " s" << endl;
00188         cout << "mFES: cavity model surface calculation took " << currentTime << " seconds." <<endl;
00189         
00190         t.restart();
00193         convert(mSurface, ini, "cavity.vol", "cavity");
00194 
00196         currentTime = t.elapsed();
00197         time << "cavity_volume " << currentTime << " s" << endl;
00198         cout << "mFES: cavity model VOL meshing took " << currentTime << " seconds." <<endl;
00199       }
00200       time.close();
00201       
00202     } else if ( fname == "" && !boost::filesystem::exists( volume_vol ) ){
00203       // Protein model is calculated
00204       boost::timer t;
00205       ofstream time;
00206       time.open ("times");
00207 
00209       if (boost::filesystem::exists( surface_stl )) {
00211         cout << surface_stl << " found. " << endl;
00212         tri::io::ImporterSTL<mMesh>::Open(mSurface, surface_stl.c_str(), mask);
00213       } else {
00215         if (generator == "standard"){
00218           LSMS tSurface;
00219           mMesh tmSurface;
00222           tSurface.calcMC(tmSurface, atomList, ini);
00224           clean(tmSurface);
00225           smooth(tmSurface, ini);
00228           if (surface_stl == "" )
00229             surface_stl = "protein.stl";
00230           
00232           tri::io::ExporterSTL<mMesh>::Save(tmSurface,surface_stl.c_str(),false);
00236           tri::io::ImporterSTL<mMesh>::Open(mSurface, surface_stl.c_str(), mask);
00237         } else {
00239           Voxel vSurface;
00242           if (!boost::filesystem::exists( "protein.stl" )){
00245             vSurface.calcSurface(mSurface, atomList, ini, "protein.stl", generatorResolution);
00246             
00248             clean(mSurface);
00249             
00250           } 
00253           tri::io::ImporterSTL<mMesh>::Open(mSurface, string("protein.stl").c_str(), mask);                          
00254         }
00255         
00256       }
00257 
00259       double currentTime = t.elapsed();
00260       time << "protein_surface " << currentTime << " s" << endl;
00261       cout << "mFES: protein model surface calculation took " << currentTime << " seconds." <<endl;
00262             
00263       t.restart();
00267       convert(mSurface, ini);
00268       currentTime = t.elapsed();
00269       time << "protein_volume " << currentTime << " s" << endl;
00270       cout << "mFES: protein model VOL meshing took " << currentTime << " seconds." <<endl;
00271       time.close();
00272       
00273     } else if (fname != ""){
00276       string exclusionstlFile = fname+"_exclusion.stl";
00277       string exclusionGroups = ini.get<string>("pka.explicit_models");
00278 
00282       if (!boost::filesystem::exists( exclusionstlFile.c_str() ) ){
00283         cout << "group model calculation " << fname << endl;
00284         
00285         if (generatorResidue == "standard"){
00288           lmSurface.calcMC(mSurface, atomList, ini, "residue_exclusion");
00289           clean(mSurface);
00290           smooth(mSurface, ini);
00293           tri::io::ExporterSTL<mMesh>::Save(mSurface,exclusionstlFile.c_str(),false);
00294         } else {
00297           Voxel vSurface;
00298           vSurface.calcSurface(mSurface, atomList, ini, exclusionstlFile, generatorModelResolution, true);
00299           clean(mSurface);
00301           tri::io::ImporterSTL<mMesh>::Open(mSurface, exclusionstlFile.c_str(), mask);
00302         }
00303         
00304       }
00305       
00308       if ( !boost::filesystem::exists( fname )  ){
00309         string stlFile = fname+".stl";
00310         ofstream time;
00311 
00312         time.open ("times", ios::app);
00313         boost::timer t;
00314         // group model calculation
00315         if ( !boost::filesystem::exists( stlFile )){
00316 
00319           if (generatorResidue == "standard"){
00320             lmSurface.calcMC(mSurface, atomList, ini, "residue");
00321             clean(mSurface);
00322             smooth(mSurface, ini);
00325             tri::io::ExporterSTL<mMesh>::Save(mSurface,stlFile.c_str(),false);
00326           } else {
00329             Voxel vSurface;
00330             vSurface.calcSurface(mSurface, atomList, ini, stlFile, generatorModelResolution);
00331             clean(mSurface);
00332             tri::io::ImporterSTL<mMesh>::Open(mSurface, stlFile.c_str(), mask);
00333           }
00334           
00335           double currentTime = t.elapsed();
00336           time << "model_surface " << currentTime << " s" << endl;
00337           cout << "mFES: residue model surface calculation took " << currentTime << " seconds." <<endl;
00338           
00339           t.restart();
00343           convert(mSurface, ini, fname, "residue");
00346           currentTime = t.elapsed();
00347           time << "model_volume " << currentTime << " s" << endl;
00348           cout << "mFES: residue model VOL meshing took " << currentTime << " seconds." <<endl;
00349           time.close();
00350         }
00351         else {
00355           cout << "model surface found: " << stlFile << endl;
00356           tri::io::ImporterSTL<mMesh>::Open(mSurface, stlFile.c_str(), mask);
00357           t.restart();
00361           convert(mSurface, ini, fname, "residue");
00362           double currentTime = t.elapsed();
00363           time << "model_volume " << currentTime << " s" << endl;
00364           cout << "mFES: residue model VOL meshing took " << currentTime << " seconds." <<endl;
00365           time.close();
00366         }
00367       }
00368     }    
00369   }
00370 
00371 
00372  private:
00373 
00386   void printMeshingOptions(Ng_Meshing_Parameters &mp, string prefix){
00387     cout << endl;
00388     cout << prefix << endl;
00389     cout << "========================" << endl;
00390     cout << "options.localh = " << mp.uselocalh << endl;
00391     cout << "options.meshsize = " << mp.maxh << endl;
00392     cout << "options.minmeshsize = " << mp.minh << endl;
00393     cout << "meshoptions.fineness = " << mp.fineness << endl;
00394     cout << "meshoptions.blockfill = " << mp.blockfill << endl;
00395     cout << "meshoptions.filldist = " << mp.filldist << endl;
00396     cout << "options.grading = " << mp.grading << endl;
00397     cout << "options.curvaturesafety = " << mp.elementspercurve << endl;
00398     cout << "options.segmentsperedge = " << mp.elementsperedge << endl;
00399     cout << "options.secondorder = " << mp.second_order << endl;
00400     cout << "options.quad = " << mp.quad_dominated << endl;
00401     cout << "stloptions.resthcloseedgeenable = " << mp.closeedgeenable << endl;
00402     cout << "stloptions.resthcloseedgefac = " << mp.closeedgefact << endl;
00403     cout << "options.optsteps2d = " << mp.optsteps_2d << endl;
00404     cout << "options.optsteps3d = " << mp.optsteps_3d << endl;
00405     cout << "options.inverttets = " << mp.invert_tets << endl;
00406     cout << "options.inverttrigs = " << mp.invert_trigs << endl;
00407     cout << "options.checkoverlap = " << mp.check_overlap << endl << endl;
00408   }
00409 
00424   void setMeshingOptions(Ng_Meshing_Parameters &mp, string optFile){
00426     ifstream in(optFile.c_str());
00427     if (!in) {
00428       in.close();
00429       cout << "Cannot open mesh options file:" << optFile << endl;
00430       exit(0);
00431     }
00432     string pqrline;
00433     string variable;
00434     string value;
00435     
00436     while( !in.eof() ) {
00437       getline(in, pqrline);
00438       
00439       istringstream ss(pqrline);
00441       ss >> variable >> value;
00442       
00445       if (variable == "meshoptions.blockfill"){
00446         mp.blockfill = atoi(value.c_str());
00447       }
00448       
00449       if (variable == "meshoptions.filldist"){
00450         mp.filldist = atof(value.c_str());
00451       }
00452       
00453       
00454       if (variable == "options.localh"){
00456         mp.uselocalh = atoi(value.c_str());
00457         continue;
00458       }
00459       
00460       if (variable == "options.meshsize"){
00462         mp.maxh = atof(value.c_str());
00463         continue;
00464       }
00465       
00466       if (variable == "options.minmeshsize"){
00468         mp.minh = atof(value.c_str());
00469         continue;
00470       }
00471       
00472       if (variable == "meshoptions.fineness"){
00474         mp.fineness = atof(value.c_str());
00475         continue;
00476       }
00477       
00478       if (variable == "options.grading"){
00480         mp.grading = atof(value.c_str());
00481         continue;
00482       }
00483       
00484       
00485       if (variable == "options.curvaturesafety"){
00487         mp.elementspercurve = atoi(value.c_str());
00488         continue;
00489       }
00490       
00491       if (variable == "options.segmentsperedge"){
00493         mp.elementsperedge = atof(value.c_str());
00494         continue;
00495       }
00496       
00497       if (variable == "options.secondorder"){
00499         mp.second_order = atoi(value.c_str());
00500         continue;
00501       }
00502       
00503       if (variable == "options.quad"){
00505         mp.quad_dominated = atoi(value.c_str());
00506         continue;
00507       }
00508       
00509 //                      if (variable == "options.meshsizefilename"){
00510 //                              //!< Optional external mesh size file
00511 //                              mp.meshsize_filename = value.c_str();
00512 //                              continue;
00513 //                      }
00514 
00515       if (variable == "stloptions.resthcloseedgeenable"){
00517         mp.closeedgeenable = atoi(value.c_str());
00518         continue;
00519       }
00520       
00521       if (variable == "stloptions.resthcloseedgefac"){
00523         mp.closeedgefact = atof(value.c_str());
00524         continue;
00525       }
00526       
00527       if (variable == "options.optsteps2d"){
00529         mp.optsteps_2d = atoi(value.c_str());
00530         continue;
00531       }
00532       
00533       if (variable == "options.optsteps3d"){
00535         mp.optsteps_3d = atoi(value.c_str());
00536         continue;
00537       }
00538       
00539       if (variable == "options.inverttets"){
00541         mp.invert_tets = atoi(value.c_str());
00542         continue;
00543       }
00544       
00545       if (variable == "options.inverttrigs"){
00547         mp.invert_trigs = atoi(value.c_str());
00548         continue;
00549       }
00550       
00551       if (variable == "options.checkoverlap"){
00553         mp.check_overlap = atoi(value.c_str());
00555         mp.check_overlapping_boundary = atoi(value.c_str());
00556       }
00557       
00558       
00559     }
00560     // optimize by default is 1, because if number of
00561     // optsteps is 0, then no optimization made
00562     
00563     in.close();
00564   }
00565   
00587   int convert(mMesh &mSurface, INI &ini, string fname = "", string mode = "protein")
00588   {
00589     
00591     Ng_STL_Geometry *stl_geom = Ng_STL_NewGeometry();
00592     
00594     Ng_Init();
00595     
00597     ngVolume = Ng_NewMesh();
00598           
00599     int np, ne;
00600     
00602     
00603     double p1[3];
00604     double p2[3];
00605     double p3[3];
00606     double n[3];
00607     
00608     mMesh::FaceIterator   fi;
00609     
00610     Point3f p;
00611     int triangles = 0;
00612     for(fi=mSurface.face.begin(); fi!=mSurface.face.end(); ++fi) if( !(*fi).IsD() ){
00613         // For each triangle write the normal, the three coords and a short set to zero
00614         p.Import(vcg::NormalizedNormal(*fi));
00615         n[0] = p[0]; n[1] = p[1]; n[2] = p[2];
00616         
00617         p.Import((*fi).V(0)->P());
00618         p1[0] = p[0]; p1[1] = p[1]; p1[2] = p[2];
00619         p.Import((*fi).V(1)->P());
00620         p2[0] = p[0]; p2[1] = p[1]; p2[2] = p[2];
00621         p.Import((*fi).V(2)->P());
00622         p3[0] = p[0]; p3[1] = p[1]; p3[2] = p[2];
00623         triangles++;
00624         Ng_STL_AddTriangle(stl_geom, p1, p2, p3, n);
00625       }
00626     
00627     cout << triangles << " triangles in surface" << endl;
00628     if(!stl_geom) {
00629       cout << "Error reading VCG STL File" << endl;
00630       exit(1);
00631     }
00632     cout << "Successfully loaded VCG STL File" << endl;
00633     
00635     string debug = ini.get<string>("model.debug");
00636     string jobname = ini.get<string>("general.jobname");
00637     string meshMoleculeSurface, meshMoleculeVolume;
00638     if (mode == "protein" || mode == "cavity" ){
00639       meshMoleculeSurface = ini.get<string>("meshing.molecule_surface");
00640       meshMoleculeVolume  = ini.get<string>("meshing.molecule_volume");
00641     } else if (mode == "residue") {
00642       meshMoleculeSurface = ini.get<string>("meshing.residue_surface");
00643       meshMoleculeVolume  = ini.get<string>("meshing.residue_volume");
00644     }
00645     cout << "using: " << meshMoleculeSurface << endl;
00646     cout << "using: " << meshMoleculeVolume << endl;
00647     
00648     Ng_Meshing_Parameters mp;
00649     setMeshingOptions(mp, meshMoleculeSurface);
00650     mp.optsurfmeshenable = 1;
00651     mp.optvolmeshenable  = 1;
00652     
00653     printMeshingOptions(mp, "Meshing options for molecular surface");
00654     
00655     cout << "Initialise the STL Geometry structure...." << endl;
00656     ngSurface = Ng_STL_InitSTLGeometry(stl_geom);
00657     if(ngSurface != NG_OK) {
00658       cout << "Error Initialising the STL Geometry....Aborting!!" << endl;
00659       exit(1);
00660     }
00661     
00662     cout << "Start Edge Meshing...." << endl;
00663     ngSurface = Ng_STL_MakeEdges(stl_geom, ngVolume, &mp);
00664     if(ngSurface != NG_OK) {
00665       cout << "Error in Edge Meshing....Aborting!!" << endl;
00666       exit(1);
00667     }
00668     
00669     cout << "Start Surface Meshing...." << endl;
00670     ngSurface = Ng_STL_GenerateSurfaceMesh(stl_geom, ngVolume, &mp);
00671     if(ngSurface != NG_OK) {
00672       cout << "Error in Surface Meshing....Aborting!!" << endl;
00673       exit(1);
00674     }
00675     
00676     if (ini.get_optional<string>("meshing.second_order_surface").get_value_or("no") == "yes"){
00677       cout << "Generating second order geometry mesh" << endl;
00678       Ng_STL_Generate_SecondOrder(stl_geom, ngVolume);
00679     }
00680           
00681     if (debug == "analyze" && mode == "protein"){
00682       stringstream fileName;
00683       fileName << jobname << "_surface_so.vol";
00684       Ng_SaveMesh(ngVolume,fileName.str().c_str());
00685     }
00686     
00687     if (mode == "protein" && boost::filesystem::exists( "cavity.vol" )){
00688       string cavity = "cavity.vol";
00689       Ng_Mesh* cSurface;
00690       cSurface = nglib::Ng_LoadMesh(cavity.c_str());
00691       
00692       Ng_SetProperties(ngVolume, 1, 1, 1, 0);
00693       Ng_SetProperties(cSurface, 1, 1, 1, 0);
00694       
00695       
00696       cout << "Merging Mesh with cavity....." << endl;
00697       ngSurface = Ng_MergeMesh( ngVolume, cSurface );
00698       if(ngSurface != NG_OK) {
00699         cout << "Error in cavity merging....Aborting!!" << endl;
00700         exit(1);
00701       }
00702       
00703     }
00704     
00705     // Example: Set up a global refinement if using a local h file
00706     // float globalH = 1e6;
00707     // cout << "setting global H to " << globalH << endl;
00708     // Ng_RestrictMeshSizeGlobal(ngVolume, globalH);
00709     
00710     setMeshingOptions(mp, meshMoleculeVolume);
00711     mp.optsurfmeshenable = 1;
00712     mp.optvolmeshenable  = 1;
00713     
00714     printMeshingOptions(mp, "Meshing options for molecular volume");
00715     
00716     cout << "Start Volume Meshing of molecule...." << endl;
00717     ngSurface = Ng_GenerateVolumeMesh (ngVolume, &mp);
00718     if(ngSurface != NG_OK) {
00719       cout << "Error in Volume Meshing....Aborting!!" << endl;
00720       exit(1);
00721     }
00722 
00723     // Example: Saving a volume file (VOL, NETGEN format) in current state
00724     // Ng_SaveMesh(ngVolume,"meshed.vol");
00725 
00726 
00727     // Example: Generate a second order surface mesh
00728     // if (ini.get<string>("meshing.second_order_surface") == "yes")
00729     //    Ng_STL_Generate_SecondOrder (stl_geom, ngVolume);
00730 
00732     if (exclusionSurface){
00733       
00734       string exclusionVol = "exclusion.vol";
00735       string exclusionStl = "exclusion.stl";
00736       
00737       if (fname != "")
00738         exclusionVol = fname+"_exclusion.vol";
00739       if (fname != "")
00740         exclusionStl = fname+"_exclusion.stl";
00741       
00742       Ng_Mesh *exclusionVolume;
00743       exclusionVolume = Ng_NewMesh();
00744       setMeshingOptions(mp, meshMoleculeSurface);
00745       mp.optsurfmeshenable = 1;
00746       mp.optvolmeshenable  = 0;
00747       
00748       if (!boost::filesystem::exists( exclusionVol )){
00749         Ng_STL_Geometry *exclusion_geom = Ng_STL_NewGeometry();
00750         
00751         cout << "Loading exclusion " <<  exclusionStl << endl;
00752         exclusion_geom = Ng_STL_LoadGeometry( exclusionStl.c_str());
00753         if(!exclusion_geom)
00754           {
00755             cout << "Error reading in STL File: " << exclusionStl << endl;
00756             return 1;
00757           }
00758         cout << "Successfully loaded STL File: " << exclusionStl << endl;
00759         
00760         cout << "Initialise the STL Geometry structure for ion exclusion layer...." << endl;
00761         ngSurface = Ng_STL_InitSTLGeometry(exclusion_geom);
00762         if(ngSurface != NG_OK) {
00763           cout << "Error Initialising the STL Geometry for ion exclusion layer....Aborting!!" << endl;
00764           exit(1);
00765         }
00766         
00767         cout << "Start Edge Meshing...." << endl;
00768         ngSurface = Ng_STL_MakeEdges(exclusion_geom, exclusionVolume, &mp);
00769         if(ngSurface != NG_OK) {
00770           cout << "Error in Edge Meshing ion exclusion layer....Aborting!!" << endl;
00771           exit(1);
00772         }
00773         
00774         cout << "Start Surface Meshing...." << endl;
00775         ngSurface = Ng_STL_GenerateSurfaceMesh(exclusion_geom, exclusionVolume, &mp);
00776         if(ngSurface != NG_OK) {
00777           cout << "Error in Surface Meshing ion exclusion layer....Aborting!!" << endl;
00778           exit(1);
00779         }
00780         Ng_SaveMesh(exclusionVolume,exclusionVol.c_str());
00781         
00782       } else {
00783         exclusionVolume = nglib::Ng_LoadMesh(exclusionVol.c_str());
00784       }
00785       
00786       Ng_SetProperties(ngVolume, 1, 1, 1, 0);
00787       Ng_SetProperties(exclusionVolume, 1, 1, 1, 0);
00788       
00789       cout << "Merging Mesh with ion exclusion layer....." << endl;
00790       ngSurface = Ng_MergeMesh( exclusionVolume, ngVolume );
00791       if(ngSurface != NG_OK) {
00792         cout << "Error in exclusion layer merging....Aborting!!" << endl;
00793         exit(1);
00794       }
00795                     
00796       mp.optsurfmeshenable = 1;
00797       mp.optvolmeshenable  = 1;
00798       
00799       cout << "Start Volume meshing of exclusion layer...." << endl;
00800       ngSurface = Ng_GenerateVolumeMesh (exclusionVolume, &mp);
00801       if(ngSurface != NG_OK) {
00802         cout << "Error in Volume Meshing of exclusion layer....Aborting!!" << endl;
00803         exit(1);
00804       }
00805       cout << "Meshing successfully completed....!!" << endl;
00806 
00807       Ng_Mesh* bSurface;
00808       
00809       cout << "Loading boundary settings ....." << endl;
00810       string boundary = ini.get<string>("model.boundary");
00811       bSurface = nglib::Ng_LoadMesh(boundary.c_str());
00812       
00813       Ng_SetProperties(bSurface, 1, 1, 1, 0);
00814       
00815       cout << "Merging Mesh with boundary....." << endl;
00816       ngSurface = Ng_MergeMesh( bSurface, exclusionVolume );
00817       if(ngSurface != NG_OK) {
00818         cout << "Error in Surface merging with ion exclusion....Aborting!!" << endl;
00819         exit(1);
00820       }
00821       
00822       cout << "Merging complete" << endl;
00823       
00824       string meshBoundaryVolume = ini.get<string>("meshing.boundary_volume");
00825       setMeshingOptions(mp, meshBoundaryVolume);
00826       
00827       mp.optsurfmeshenable = 1;
00828       mp.optvolmeshenable  = 1;
00829       printMeshingOptions(mp, "Meshing options for boundary volume");
00830       
00831       
00832       cout << "Start Volume meshing of whole model...." << endl;
00833       ngSurface = Ng_GenerateVolumeMesh (bSurface, &mp);
00834       if(ngSurface != NG_OK) {
00835         cout << "Error in Volume Meshing....Aborting!!" << endl;
00836         exit(1);
00837       }
00838       
00839       // volume mesh output
00840       np = Ng_GetNP(bSurface);
00841       cout << "Points: " << np << endl;
00842       
00843       ne = Ng_GetNE(bSurface);
00844       cout << "Elements: " << ne << endl;
00845       
00846       string volumeVol = ini.get<string>("model.volume_vol");
00847       
00848       if (fname != "")
00849         volumeVol = fname;
00850       
00851       if (volumeVol != ""){
00852         cout << "Saving Mesh in VOL Format...." << endl;
00853         Ng_SaveMesh(bSurface,volumeVol.c_str());        
00854       }
00855     } else {
00856 
00858       Ng_Mesh* bSurface;
00859       
00860       if (mode != "cavity"){
00861         cout << "Loading boundary settings ....." << endl;
00862         string boundary = ini.get<string>("model.boundary");
00863         bSurface = nglib::Ng_LoadMesh(boundary.c_str());
00864         
00865         if (ini.get_optional<string>("meshing.second_order_surface").get_value_or("no") == "yes"){
00866           cout << "Generating second order for volume mesh" << endl;
00867           Ng_Generate_SecondOrder(bSurface);
00868         }
00869         
00870         Ng_SetProperties(ngVolume, 1, 1, 1, 0);
00871         Ng_SetProperties(bSurface, 1, 1, 1, 0);
00872         
00873         cout << "Merging Mesh with boundary....." << endl;
00874         ngSurface = Ng_MergeMesh( bSurface, ngVolume );
00875         if(ngSurface != NG_OK) {
00876           cout << "Error in Surface merging....Aborting!!" << endl;
00877           exit(1);
00878         }
00879               
00880         cout << "Merging complete" << endl;
00881         
00882         
00883         string refineFile = ini.get_optional<string>("model.refine_file").get_value_or("");
00884 
00887         if (refineFile != ""){
00888           // global refinement
00889           // void Ng_RestrictMeshSizeGlobal (Ng_Mesh * mesh, double h);
00890           cout << "Setting local refinement ....." << endl;
00891           ifstream in(refineFile.c_str());
00892           if (!in) {
00893             in.close();
00894             cout << "Cannot open refinement file:" << refineFile << endl;
00895             exit(0);
00896           }
00897           
00898           string currentLine;
00899           double p[3]; double h;
00900           unsigned int refPoints = 0;
00901           while( !in.eof() ) {
00902             getline(in, currentLine);
00903             if (currentLine != ""){
00904               istringstream ss(currentLine);
00905               ss >> p[0] >> p[1] >> p[2] >> h;
00906               Ng_RestrictMeshSizePoint (bSurface, p, h);
00907               refPoints++;
00908             }
00909           }
00910           cout << refPoints << " local refinement point(s) set." << endl;
00911         }
00912 
00914         string meshBoundaryVolume = ini.get<string>("meshing.boundary_volume");
00915         setMeshingOptions(mp, meshBoundaryVolume);
00916         mp.optsurfmeshenable = 1;
00917         mp.optvolmeshenable  = 1;
00918         printMeshingOptions(mp, "Meshing options for boundary volume");
00919         
00920 
00922         cout << "Start Volume meshing of whole model...." << endl;
00923         ngSurface = Ng_GenerateVolumeMesh (bSurface, &mp);
00924         if(ngSurface != NG_OK) {
00925           cout << "Error in Volume Meshing....Aborting!!" << endl;
00926           exit(1);
00927         }
00928       } else {
00929         bSurface = ngVolume;
00930         Ng_SetProperties(ngVolume, 2, 2, 2, 1);
00931         
00932       }
00933       
00934       
00935       if (ini.get_optional<string>("meshing.second_order_surface").get_value_or("no") == "yes"){
00936         cout << "Last second order meshing" << endl;
00937         Ng_Generate_SecondOrder(bSurface);
00938       }
00939           
00940       cout << "Meshing successfully completed....!!" << endl;
00941           
00942       // volume mesh output
00943       np = Ng_GetNP(bSurface);
00944       cout << "Points: " << np << endl;
00945       
00946       ne = Ng_GetNE(bSurface);
00947       cout << "Elements: " << ne << endl;
00948       
00949       string volumeVol = ini.get<string>("model.volume_vol");
00950       
00952       if (fname != "")
00953         volumeVol = fname;
00954 
00955       if (volumeVol != ""){
00956         cout << "Saving Mesh in VOL Format...." << endl;
00957         Ng_SaveMesh(bSurface,volumeVol.c_str());
00958       }
00959     }
00960     
00961     return 1;
00962     
00963   }
00964 
00965 
00977   void clean(mMesh &mSurface){
00978     // some cleaning to get rid of bad file formats like stl that duplicate vertexes..
00979     int dup = tri::Clean<mMesh>::RemoveDuplicateVertex(mSurface);
00980     int unref = tri::Clean<mMesh>::RemoveUnreferencedVertex(mSurface);
00981     printf("Removed %i duplicate and %i unreferenced vertices from mesh\n",dup,unref);
00982     tri::UpdateTopology<mMesh>::VertexFace(mSurface);
00983   }
00984   
01001   void smooth(mMesh &mSurface, INI &ini){
01002     
01003     string line = ini.get<string>("model.smoothing");
01004     istringstream ss(line);
01005     string mode = "";
01006     unsigned int steps = 0;
01007     string progress = "*";
01008     
01009     while (ss >> mode >> steps){
01010       if (mode == "t"){
01011         cout << "taubin smoothing steps: " << steps << endl;
01012         for (unsigned int i = 0; i < steps; i++){
01013           cout << "\r" << i+1 << "/" << steps << flush;
01014           tri::UpdateNormal<mMesh>::PerFace(mSurface);
01015           tri::Smooth<mMesh>::VertexCoordTaubin(mSurface,1,TAUBIN_LAMBDA,TAUBIN_MU);
01016         }
01017       } else if (mode == "lap"){
01018         cout << "laplace smoothing steps: " << steps << endl;
01019         for (unsigned int i = 0; i < steps; i++){
01020           cout << "\r" << i+1 << "/" << steps << flush;
01021           tri::UpdateNormal<mMesh>::PerFace(mSurface);
01022           tri::Smooth<mMesh>::VertexCoordLaplacian(mSurface,1);
01023         }
01024       } else if (mode == "hc"){
01025         cout << "hc laplace smoothing steps: " << steps << endl;
01026         for (unsigned int i = 0; i < steps; i++){
01027           cout << "\r" << i+1 << "/" << steps << flush;
01028           tri::UpdateNormal<mMesh>::PerFace(mSurface);
01029           tri::Smooth<mMesh>::VertexCoordLaplacianHC(mSurface,1);
01030         }
01031       } else if (mode == "aw"){
01032         cout << "angle weighted laplace smoothing steps: " << steps << endl;
01033         for (unsigned int i = 0; i < steps; i++){
01034           cout << "\r" << i+1 << "/" << steps << flush;
01035           tri::UpdateNormal<mMesh>::PerFace(mSurface);
01036           tri::Smooth<mMesh>::VertexCoordLaplacianAngleWeighted(mSurface,1, CF_LAMBDA);
01037         }
01038       } else if (mode == "lapsd"){
01039         cout << "scale dependent laplace smoothing steps: " << steps << endl;
01040         for (unsigned int i = 0; i < steps; i++){
01041           cout << "\r" << i+1 << "/" << steps << flush;
01042           tri::UpdateNormal<mMesh>::PerFace(mSurface);
01043           // tri::UpdateNormal<mMesh>::PerFaceNormalized(mSurface);
01044           tri::Smooth<mMesh>::VertexCoordScaleDependentLaplacian_Fujiwara(mSurface,1, 0.0025);
01045         }       
01046       }
01047       cout << endl;
01048                         
01049     }
01050     
01051     // Example code to test for self intersections, Abort here if true?
01052     //          vector<mMesh::FaceType *> SelfIntersectList;
01053     // tri::Clean<mMesh>::SelfIntersections(mSurface, SelfIntersectList);
01054     //      int SelfIntersections = SelfIntersectList.size();
01055     //  cout << SelfIntersections << " intersections found." << endl;
01056     //          if (SelfIntersections > 0)
01057     //  cout << "This surface will probably not mesh! Keep care." << endl;
01058     
01059   }
01060   
01061   Ng_Result ngSurface;
01062   Ng_Mesh *ngVolume;
01063   
01064 };
01065 
01066 bool Model::exclusionSurface = false;