SparseGridTopology.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                               SOFA :: Modules                               *
00020 *                                                                             *
00021 * Authors: The SOFA Team and external contributors (see Authors.txt)          *
00022 *                                                                             *
00023 * Contact information: contact@sofa-framework.org                             *
00024 ******************************************************************************/
00025 #include <fstream>
00026 #include <string>
00027 
00028 #include <sofa/component/MechanicalObject.h>
00029 #include <sofa/simulation/tree/GNode.h>
00030 #include <sofa/component/topology/SparseGridTopology.h>
00031 #include <sofa/core/componentmodel/topology/BaseMeshTopology.h>
00032 #include <sofa/core/ObjectFactory.h>
00033 #include <sofa/helper/io/Mesh.h>
00034 #include <sofa/helper/fixed_array.h>
00035 #include <sofa/helper/polygon_cube_intersection/polygon_cube_intersection.h>
00036 #include <sofa/helper/system/FileRepository.h>
00037 #include <sofa/defaulttype/VecTypes.h>
00038 
00039 
00040 using std::cerr;
00041 using std::endl;
00042 using std::pair;
00043 
00044 namespace sofa
00045 {
00046 
00047   namespace component
00048   {
00049 
00050     namespace topology
00051     {
00052 
00053       SOFA_DECL_CLASS(SparseGridTopology)
00054 
00055       int SparseGridTopologyClass = core::RegisterObject("Sparse grid in 3D")
00056                                     .addAlias("SparseGrid")
00057                                     .add< SparseGridTopology >()
00058                                     ;
00059       
00060       
00061 //    const float SparseGridTopology::WEIGHT[8][8] =
00062 //    {
00063 //        { 1, .5, .5, .25,  .5,.25,.25, .125 }, // fine cube 0 from coarser corner 0 -> what weight for a vertex?
00064 //        { .5,1,.25,.5,.25,.5,.125,.25 },
00065 //        {.5,.25,1,.5,.25,.125,.5,.25},
00066 //        {.25,.5,.5,1,.125,.25,.25,.5},
00067 //        {.5,.25,.25,.125,1,.5,.5,.25},
00068 //        {.25,.5,.125,.25,.5,1,.25,.5},
00069 //        {.25,.125,.5,.25,.5,.25,1,.5},
00070 //        {.125,.25,.25,.5,.25,.5,.5,1}
00071 //    };
00072       
00073       
00074       const float SparseGridTopology::WEIGHT27[8][27] =
00075       {
00076       // each weight of the jth fine vertex to the ith coarse vertex
00077       {1.0, 0.5, 0.0, 0.5, 0.25, 0.0, 0.0, 0.0, 0.0, 0.5, 0.25, 0.0, 0.25, 0.125, 0.0,  0.0, 0.0,  0.0, 0.0, 0.0, 0.0, 0.0, 0.0,  0.0, 0.0, 0.0, 0.0}, 
00078       {0.0, 0.0, 0.0, 0.0, 0.0,  0.0, 0.0, 0.0, 0.0, 0.5, 0.25, 0.0, 0.25, 0.125, 0.0,  0.0, 0.0,  0.0, 1.0, 0.5, 0.0, 0.5, 0.25, 0.0, 0.0, 0.0, 0.0},
00079       {0.0, 0.0, 0.0, 0.5, 0.25, 0.0, 1.0, 0.5, 0.0, 0.0, 0.0,  0.0, 0.25, 0.125, 0.0,  0.5, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,  0.0, 0.0, 0.0, 0.0},
00080       {0.0, 0.0, 0.0, 0.0, 0.0,  0.0, 0.0, 0.0, 0.0, 0.0, 0.0,  0.0, 0.25, 0.125, 0.0,  0.5, 0.25, 0.0, 0.0, 0.0, 0.0, 0.5, 0.25, 0.0, 1.0, 0.5, 0.0},
00081       {0.0, 0.5, 1.0, 0.0, 0.25, 0.5, 0.0, 0.0, 0.0, 0.0, 0.25, 0.5, 0.0,  0.125, 0.25, 0.0, 0.0,  0.0, 0.0, 0.0, 0.0, 0.0, 0.0,  0.0, 0.0, 0.0, 0.0},
00082       {0.0, 0.0, 0.0, 0.0, 0.0,  0.0, 0.0, 0.0, 0.0, 0.0, 0.25, 0.5, 0.0,  0.125, 0.25, 0.0, 0.0,  0.0, 0.0, 0.5, 1.0, 0.0, 0.25, 0.5, 0.0, 0.0, 0.0},
00083       {0.0, 0.0, 0.0, 0.0, 0.25, 0.5, 0.0, 0.5, 1.0, 0.0, 0.0,  0.0, 0.0,  0.125, 0.25, 0.0, 0.25, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0,  0.0, 0.0, 0.0, 0.0},
00084       {0.0, 0.0, 0.0, 0.0, 0.0,  0.0, 0.0, 0.0, 0.0, 0.0, 0.0,  0.0, 0.0,  0.125, 0.25, 0.0, 0.25, 0.5, 0.0, 0.0, 0.0, 0.0, 0.25, 0.5, 0.0, 0.5, 1.0}
00085       };
00086       
00087       const int SparseGridTopology::cornerIndicesFromFineToCoarse[8][8]=
00088       {
00089           // fine vertices forming the ith coarse cube (with XYZ order)
00090           {  0,  9,  3, 12,  1, 10,  4, 13},  
00091           {  9, 18, 12, 21, 10, 19, 13, 22},
00092           {  3, 12,  6, 15,  4, 13,  7, 16},
00093           { 12, 21, 15, 24, 13, 22, 16, 25},
00094           {  1, 10,  4, 13,  2, 11,  5, 14},
00095           { 10, 19, 13, 22, 11, 20, 14, 23},
00096           {  4, 13,  7, 16,  5, 14,  8, 17},
00097           { 13, 22, 16, 25, 14, 23, 17, 26} 
00098       };
00099               
00100               
00101       SparseGridTopology::SparseGridTopology(bool _isVirtual)
00102         : 
00103       n(initData(&n, Vec3i(2,2,2), "n", "grid resolution")), 
00104       _min(initData(&_min, Vector3(0,0,0), "min","Min")),
00105       _max(initData(&_max, Vector3(0,0,0), "max","Max")),
00106       _nbVirtualFinerLevels( initData(&_nbVirtualFinerLevels, 0, "nbVirtualFinerLevels", "create virtual (not in the animation tree) finer sparse grids in order to dispose of finest information (usefull to compute better mechanical properties for example)")),
00107       dataResolution(initData(&dataResolution, Vec3i(0,0,0), "dataResolution", "Dimension of the voxel File")),
00108       voxelSize(initData(&voxelSize, Vector3(1.0f,1.0f,1.0f), "voxelSize", "Dimension of one voxel")),
00109       marchingCubeStep(initData(&marchingCubeStep, (unsigned int) 1, "marchingCubeStep", "Step of the Marching Cube algorithm")),     
00110       convolutionSize(initData(&convolutionSize, (unsigned int) 0, "convolutionSize", "Dimension of the convolution kernel to smooth the voxels. 0 if no smoothing is required."))
00111       {
00112           isVirtual = _isVirtual;
00113           _alreadyInit = false;
00114           _finerSparseGrid = NULL;
00115           _coarserSparseGrid = NULL;
00116           _usingMC = false;
00117       }
00118 
00119 
00120     bool SparseGridTopology::load(const char* filename)
00121     {
00122     std::string f(filename);
00123     if ( sofa::helper::system::DataRepository.findFile ( f ) )
00124       this->d_filename.setValue( f );
00125 //      cerr<<"SparseGridTopology::load : "<<filename<<"    "<<this->filename.getValue()<<endl;
00126         return true;
00127     }
00128 
00129 
00130 
00131       void SparseGridTopology::init()
00132       {
00133           if(_alreadyInit) return;
00134           _alreadyInit = true;
00135           
00136           this->MeshTopology::init();
00137           invalidate();
00138           
00139           Vec3i grid = n.getValue();
00140           
00141           if(grid[0] < 2) grid[0]= 2;
00142           if(grid[1] < 2) grid[1]= 2;
00143           if(grid[2] < 2) grid[2]= 2;
00144         
00145           n.setValue(grid);
00146           
00147           if( _nbVirtualFinerLevels.getValue() )
00148               buildVirtualFinerLevels();
00149           
00150           
00151           if( _finerSparseGrid != NULL )
00152               buildFromFiner();
00153           else
00154               buildAsFinest();                
00155                  
00156           _nodeAdjacency.resize(seqPoints.size() );
00157           for(unsigned i=0;i<seqPoints.size();++i)
00158               _nodeAdjacency[i].assign(-1);
00159           
00160           for(unsigned i=0;i<seqHexas.getValue().size();++i)
00161           {
00162               _nodeAdjacency[ seqHexas.getValue()[i][0] ][RIGHT] = seqHexas.getValue()[i][1];
00163               _nodeAdjacency[ seqHexas.getValue()[i][0] ][UP] = seqHexas.getValue()[i][2];
00164               _nodeAdjacency[ seqHexas.getValue()[i][0] ][BEHIND] = seqHexas.getValue()[i][4];
00165               
00166               _nodeAdjacency[ seqHexas.getValue()[i][1] ][LEFT] = seqHexas.getValue()[i][0];
00167               _nodeAdjacency[ seqHexas.getValue()[i][1] ][UP] = seqHexas.getValue()[i][3];
00168               _nodeAdjacency[ seqHexas.getValue()[i][1] ][BEHIND] = seqHexas.getValue()[i][5];
00169               
00170               _nodeAdjacency[ seqHexas.getValue()[i][2] ][RIGHT] = seqHexas.getValue()[i][3];
00171               _nodeAdjacency[ seqHexas.getValue()[i][2] ][DOWN] = seqHexas.getValue()[i][0];
00172               _nodeAdjacency[ seqHexas.getValue()[i][2] ][BEHIND] = seqHexas.getValue()[i][6];
00173               
00174               _nodeAdjacency[ seqHexas.getValue()[i][3] ][LEFT] = seqHexas.getValue()[i][2];
00175               _nodeAdjacency[ seqHexas.getValue()[i][3] ][DOWN] = seqHexas.getValue()[i][1];
00176               _nodeAdjacency[ seqHexas.getValue()[i][3] ][BEHIND] = seqHexas.getValue()[i][7];
00177               
00178               _nodeAdjacency[ seqHexas.getValue()[i][4] ][RIGHT] = seqHexas.getValue()[i][5];
00179               _nodeAdjacency[ seqHexas.getValue()[i][4] ][UP] = seqHexas.getValue()[i][6];
00180               _nodeAdjacency[ seqHexas.getValue()[i][4] ][BEFORE] = seqHexas.getValue()[i][0];
00181               
00182               _nodeAdjacency[ seqHexas.getValue()[i][5] ][LEFT] = seqHexas.getValue()[i][4];
00183               _nodeAdjacency[ seqHexas.getValue()[i][5] ][UP] = seqHexas.getValue()[i][7];
00184               _nodeAdjacency[ seqHexas.getValue()[i][5] ][BEFORE] = seqHexas.getValue()[i][1];
00185               
00186               _nodeAdjacency[ seqHexas.getValue()[i][6] ][RIGHT] = seqHexas.getValue()[i][7];
00187               _nodeAdjacency[ seqHexas.getValue()[i][6] ][DOWN] = seqHexas.getValue()[i][4];
00188               _nodeAdjacency[ seqHexas.getValue()[i][6] ][BEFORE] = seqHexas.getValue()[i][2];
00189               
00190               _nodeAdjacency[ seqHexas.getValue()[i][7] ][LEFT] = seqHexas.getValue()[i][6];
00191               _nodeAdjacency[ seqHexas.getValue()[i][7] ][DOWN] = seqHexas.getValue()[i][5];
00192               _nodeAdjacency[ seqHexas.getValue()[i][7] ][BEFORE] = seqHexas.getValue()[i][3];
00193           }
00194           
00195           
00196 //        _nodeCubesAdjacency.clear();        
00197           _nodeCubesAdjacency.resize(seqPoints.size() );
00198           for(unsigned i=0;i<seqHexas.getValue().size();++i)
00199           {
00200               for(int j=0;j<8;++j)
00201               {
00202                   _nodeCubesAdjacency[ seqHexas.getValue()[i][j] ].push_back( i );
00203               }
00204           }
00205           
00206 //        cerr<<"_nodeCubesAdjacency :"<<_nodeCubesAdjacency<<endl;
00207           
00208 //        cerr<<"SparseGridTopology::init() :   "<<this->getName()<<"    cubes size = ";
00209 //        cerr<<seqHexas.getValue().size()<<"       ";
00210 //        cerr<<_types.size()<<endl;
00211           
00212       }
00213 
00214 
00215       
00216       void SparseGridTopology::buildAsFinest(  )
00217       {
00218           //          cerr<<"SparseGridTopology::buildAsFinest(  )\n";
00219           std::string _filename=d_filename.getValue();
00220                   if (_filename.empty())
00221           {
00222               std::cerr << "SparseGridTopology: no filename specified." << std::endl;
00223               return;
00224           }
00225           if (! sofa::helper::system::DataRepository.findFile ( _filename ))
00226             return;
00227 
00228           // initialize the following datafields: 
00229           // xmin, xmax, ymin, ymax, zmin, zmax, evtl. nx, ny, nz
00230           // _regularGrid, _indicesOfRegularCubeInSparseGrid, _types
00231           // seqPoints, seqHexas.getValue(), nbPoints
00232           if(_filename.length() > 4 && _filename.compare(_filename.length()-4, 4, ".obj")==0)
00233           {
00234               //            std::cout << "SparseGridTopology: using mesh "<<_filename<<std::endl;
00235               buildFromTriangleMesh(_filename);
00236           }
00237           else if(_filename.length() > 6 && _filename.compare(_filename.length()-6, 6, ".trian")==0)
00238           {
00239               //            std::cout << "SparseGridTopology: using mesh "<<_filename<<std::endl;
00240               buildFromTriangleMesh(_filename);
00241           }
00242           else if(_filename.length() > 4 && _filename.compare(_filename.length()-4, 4, ".raw")==0)
00243           {
00244               //            std::cout << "SparseGridTopology: using mesh "<<_filename<<std::endl;
00245             _usingMC = true;
00246             
00247             buildFromRawVoxelFile(_filename);
00248           }
00249           else if(_filename.length() > 6 && _filename.compare(_filename.length()-6, 6, ".voxel")==0)
00250           {
00251               buildFromVoxelFile(_filename);
00252           }      
00253       }
00254 
00255       void SparseGridTopology::buildFromVoxelFile(const std::string& filename)
00256       {     
00257         if (dataVoxels.getValue().size() == 0)
00258         {
00259           std::ifstream file( filename.c_str() );
00260           if ( file == NULL ) 
00261           {
00262         std::cerr << "SparseGridTopology: failed to open file " << filename << std::endl;
00263         return;
00264           }
00265 
00266           int fileNx, fileNy, fileNz;
00267           int nx, ny,nz;
00268           int xmin, ymin, zmin, xmax, ymax, zmax;
00269           float dx, dy, dz;
00270 
00271           file >> fileNx >> fileNy >> fileNz;
00272           file >> dx >> dy >> dz;
00273 
00274           // note that nx, ny, nz are the numbers of vertices in the regular grid 
00275           // whereas fileNx, fileNy, fileNz are the numbers of voxels in each direction, 
00276           // corresponding to the number of cubes in the regular grid and thus nx = fileNx + 1
00277           nx = fileNx+1;
00278           ny = fileNy+1;
00279           nz = fileNz+1;
00280 
00281           xmin = 0;
00282           ymin = 0;
00283           zmin = 0;
00284           
00285           xmax =(int)( dx * fileNx);
00286           ymax =(int)( dy * fileNy);
00287           zmax =(int)( dz * fileNz);
00288           
00289           n.setValue(Vec3i(nx,ny,nz));
00290           _min.setValue(Vector3((SReal)xmin, (SReal)ymin, (SReal)zmin));
00291           _max.setValue(Vector3((SReal)xmax, (SReal)ymax, (SReal)zmax));
00292           
00293 
00294 
00295           int value;
00296           int numVoxels = 0;
00297           dataVoxels.beginEdit()->resize(fileNx * fileNy * fileNz, (unsigned char) 0);
00298           for(int z=0; z<fileNz; ++z)
00299         for(int y=0; y<fileNy; ++y)
00300           for(int x=0; x<fileNx; ++x)
00301           {
00302         file >> value;
00303         if (value != 0)
00304         {         
00305           setVoxel(x + fileNx * y + fileNx * fileNy * z,1);
00306           numVoxels++;
00307         }
00308           }
00309 
00310           file.close();
00311         }
00312         _regularGrid.setSize(getNx(), getNy(), getNz());
00313         _regularGrid.setPos(getXmin(), getXmax(), getYmin(), getYmax(), getZmin(), getZmax());
00314         int nbCubesRG = _regularGrid.getNbHexas();
00315         _indicesOfRegularCubeInSparseGrid.resize(nbCubesRG, -1); // to redirect an indice of a cube in the regular grid to its indice in the sparse grid
00316                 
00317         
00318         vector<Type> regularGridTypes(nbCubesRG, OUTSIDE); // to compute filling types (OUTSIDE, INSIDE, BOUNDARY)
00319     
00320           // fill the regularGridTypes vector
00321           // at the moment, no BOUNDARY type voxels are generated at the finest level
00322         for(int i=0; i<nbCubesRG; ++i)
00323         {
00324           if(dataVoxels.getValue()[i] != 0.0f)
00325           {
00326             regularGridTypes[i] = INSIDE;
00327           }
00328         }
00329 
00330         buildFromRegularGridTypes(_regularGrid, regularGridTypes );
00331       }
00332 
00333       
00334       
00335       //Building from a RAW file
00336       void SparseGridTopology::buildFromRawVoxelFile(const std::string& filename)
00337       {         
00338 //        cerr<<"SparseGridTopology::buildFromRawVoxelFile(const std::string& filename)\n";
00339           
00340           
00341         _regularGrid.setSize(getNx(),getNy(),getNz());      
00342         const int nbCubesRG = _regularGrid.getNbHexas();        
00343                 
00344         _indicesOfRegularCubeInSparseGrid.resize(nbCubesRG, -1); // to redirect an indice of a cube in the regular grid to its indice in the sparse grid
00345         vector<Type> regularGridTypes(nbCubesRG, OUTSIDE); // to compute filling types (OUTSIDE, INSIDE, BOUNDARY)
00346         
00347         //Loading from file
00348         if (dataVoxels.getValue().size() == 0)
00349         {
00350           FILE *file = fopen( filename.c_str(), "r" );
00351           if (!file) { std::cerr<< "FILE " << filename << " not found\n";return;}
00352         //Get the voxels from the file
00353           dataVoxels.beginEdit()->resize(dataResolution.getValue()[0]*dataResolution.getValue()[1]*dataResolution.getValue()[2]/8, (unsigned char)0);
00354 
00355           unsigned char value;          
00356           const Vector3 transform(                (getNx()-1)/(float)dataResolution.getValue()[0],
00357           (getNy()-1)/(float)dataResolution.getValue()[1],
00358            (getNz()-1)/(float)dataResolution.getValue()[2]);
00359         
00360           for (unsigned int i=0;i<dataVoxels.beginEdit()->size()*8; i++)
00361           { 
00362                 value=getc(file);
00363                 if ((int)value != 0) 
00364                 {       
00365                     setVoxel(i,1);
00366                     
00367                     const int z = i/(dataResolution.getValue()[0]*dataResolution.getValue()[1]);
00368                     const int y = (  (i%(dataResolution.getValue()[0]*dataResolution.getValue()[1]))
00369                                 /(dataResolution.getValue()[0])                         );
00370                     const int x = i%dataResolution.getValue()[0];
00371                     
00372                     unsigned int indexGrid = 
00373                         (unsigned int)(z*transform[2])*(getNy()-1)*(getNx()-1) 
00374                         + (unsigned int)(y*transform[1])*(getNx()-1) 
00375                         + (unsigned int)(x*transform[0]);
00376             
00377                     regularGridTypes[indexGrid] = INSIDE;
00378                 
00379                 }
00380           }
00381           fclose(file);
00382         }           
00383         unsigned int max_dim_voxels = std::max(dataResolution.getValue()[0],std::max(dataResolution.getValue()[1],dataResolution.getValue()[2]));
00384         _min.setValue(voxelSize.getValue()*max_dim_voxels*(-0.5));
00385         _max.setValue(voxelSize.getValue()*max_dim_voxels*0.5);
00386         
00387         _regularGrid.setPos(getXmin(),getXmax(),getYmin(),getYmax(),getZmin(),getZmax());
00388         buildFromRegularGridTypes(_regularGrid, regularGridTypes);
00389         if (!isVirtual)
00390           updateMesh();
00391         
00392       }
00393       
00394       
00395       
00396       void SparseGridTopology::updateMesh()
00397       {
00398         if (!_usingMC || dataVoxels.beginEdit()->size() == 0) return;
00399                 
00400         unsigned int max_dim_voxels = std::max(dataResolution.getValue()[0],std::max(dataResolution.getValue()[1],dataResolution.getValue()[2]));
00401         _min.setValue(voxelSize.getValue()*max_dim_voxels*(-0.5));
00402         _max.setValue(voxelSize.getValue()*max_dim_voxels*0.5);
00403 
00404         //Creating if needed collision models and visual models
00405         using sofa::simulation::tree::GNode;
00406         
00407         sofa::helper::vector< sofa::core::componentmodel::topology::BaseMeshTopology * > list_meshf;
00408         sofa::helper::vector< sofa::helper::vector< Vec3f >* > list_Xf;
00409         sofa::helper::vector< sofa::core::componentmodel::topology::BaseMeshTopology * > list_meshd;
00410         sofa::helper::vector< sofa::helper::vector< Vec3d >* > list_Xd;
00411         
00412           //Get Collision Model
00413           sofa::helper::vector< sofa::core::componentmodel::topology::BaseMeshTopology* > m_temp;
00414           this->getContext()->get< sofa::core::componentmodel::topology::BaseMeshTopology >(&m_temp, BaseContext::SearchDown);
00415           
00416           sofa::core::componentmodel::topology::BaseMeshTopology* collisionTopology=NULL;
00417           for (unsigned int i=0;i<m_temp.size();++i)
00418           {
00419         if (m_temp[i] != this) {collisionTopology = m_temp[i];break;}
00420           }
00421 //        std::cout << m_temp << " " <<  (m_temp != this) << " " << m_temp->getNbTriangles()  << " !!!! test to enter \n";
00422           if (   collisionTopology != NULL && collisionTopology->getNbTriangles() == 0)
00423           {
00424 #ifndef SOFA_FLOAT
00425         MechanicalObject< Vec3dTypes > *mecha_tempd = collisionTopology->getContext()->get< MechanicalObject< Vec3dTypes > >();
00426         if (mecha_tempd != NULL && mecha_tempd->getX()->size() < 2) //a triangle mesh has minimum 3elements
00427         {         
00428           
00429           list_meshd.push_back(collisionTopology);
00430           list_Xd.push_back(mecha_tempd->getX());
00431         }
00432 #endif
00433 #ifndef SOFA_DOUBLE 
00434         MechanicalObject< Vec3fTypes > *mecha_tempf = collisionTopology->getContext()->get< MechanicalObject< Vec3fTypes > >();
00435         if (mecha_tempf != NULL && mecha_tempf->getX()->size() < 2) //a triangle mesh has minimum 3elements
00436         {         
00437           
00438           list_meshf.push_back(collisionTopology);
00439           list_Xf.push_back(mecha_tempf->getX());
00440         }
00441 #endif 
00442           }
00443 
00444         if (list_meshf.empty() && list_meshd.empty() ) 
00445             return;              //No Marching Cube to run
00446 
00447         //Configuration of the Marching Cubes algorithm
00448 
00449         marchingCubes.setDataResolution(Vec3i(dataResolution.getValue()[0], 
00450                                     dataResolution.getValue()[1], 
00451                                     dataResolution.getValue()[2]));
00452         marchingCubes.setDataVoxelSize(voxelSize.getValue());
00453         marchingCubes.setStep(marchingCubeStep.getValue());
00454         marchingCubes.setConvolutionSize(convolutionSize.getValue()); //apply Smoothing if convolutionSize > 0
00455 
00456         if (! list_meshf.empty())
00457           constructCollisionModels(list_meshf, list_Xf);     
00458         else
00459           constructCollisionModels(list_meshd, list_Xd);     
00460       }
00461       
00462       void SparseGridTopology::getMesh(sofa::helper::io::Mesh &m)
00463       {
00464         if (!dataVoxels.getValue().empty())
00465           marchingCubes.run(&dataVoxels.getValue()[0], 0.5f, m);
00466       }
00467       
00468       template< class T >
00469       void SparseGridTopology::constructCollisionModels(const sofa::helper::vector< sofa::core::componentmodel::topology::BaseMeshTopology * > &list_mesh,
00470                                 const sofa::helper::vector< sofa::helper::vector< Vec<3,T> >* > &list_X) const
00471       { 
00472           sofa::helper::vector< unsigned int>   triangles;
00473           vector< Vector3 >     vertices;   
00474 
00475           marchingCubes.run(&dataVoxels.getValue()[0], 0.5f, triangles, vertices); 
00476 
00477           for (unsigned int i=0;i<list_mesh.size();++i)
00478           {
00479               list_mesh[i]->clear();
00480               list_X[i]->resize(vertices.size());         
00481           }
00482 
00483           for (unsigned int id_point=0;id_point<vertices.size();++id_point)
00484           {       
00485               const Vector3 point(vertices[id_point]);
00486               for (unsigned int j=0; j<list_mesh.size(); ++j)
00487               {
00488                   (*list_X[j])[id_point] = point;
00489               }
00490           }
00491 
00492           //Fill the facets
00493           for (unsigned int id_vertex=0; id_vertex<triangles.size(); id_vertex+=3)
00494           {
00495               for (unsigned int j=0; j<list_mesh.size(); ++j)
00496               {
00497                   list_mesh[j]->addTriangle(triangles[id_vertex],triangles[id_vertex+1], triangles[id_vertex+2]);
00498               }
00499           }
00500       }
00501           
00502           
00503       void SparseGridTopology::buildFromTriangleMesh(const std::string& filename)
00504       {     
00505           helper::io::Mesh* mesh = helper::io::Mesh::Create(filename.c_str());
00506 
00507           if(mesh == NULL)
00508           {
00509               std::cerr << "SparseGridTopology: loading mesh " << filename << " failed." <<std::endl;
00510               return;
00511           }
00512 
00513           // if not given sizes -> bounding box
00514           if( _min.getValue()== Vector3() && _max.getValue()== Vector3())
00515           {
00516               SReal xMin, xMax, yMin, yMax, zMin, zMax;
00517               computeBoundingBox(mesh->getVertices(), xMin, xMax, yMin, yMax, zMin, zMax);
00518 
00519               // increase the box a little
00520               Vector3 diff ( xMax-xMin, yMax - yMin, zMax - zMin );
00521               diff /= 100.0;
00522 
00523               _min.setValue(Vector3( xMin - diff[0], yMin - diff[1], zMin - diff[2] ));           
00524               _max.setValue(Vector3( xMax + diff[0], yMax + diff[1], zMax + diff[2] ));
00525           }
00526  
00527           _regularGrid.setSize(getNx(),getNy(),getNz());
00528           _regularGrid.setPos(getXmin(),getXmax(),getYmin(),getYmax(),getZmin(),getZmax());
00529 
00530           vector<Type> regularGridTypes; // to compute filling types (OUTSIDE, INSIDE, BOUNDARY)
00531           voxelizeTriangleMesh(mesh, _regularGrid, regularGridTypes);
00532          
00533           buildFromRegularGridTypes(_regularGrid, regularGridTypes);
00534 
00535           delete mesh;
00536       }
00537 
00538       void SparseGridTopology::voxelizeTriangleMesh(helper::io::Mesh* mesh, 
00539           RegularGridTopology& regularGrid, 
00540           vector<Type>& regularGridTypes) const
00541       {
00542           regularGridTypes.resize(regularGrid.getNbHexas(), INSIDE);
00543 
00544           //            // find all initial mesh edges to compute intersection with cubes
00545           //             const helper::vector< helper::vector < helper::vector <int> > >& facets = mesh->getFacets();
00546           //             std::set< SegmentForIntersection,ltSegmentForIntersection > segmentsForIntersection;
00547           //             for (unsigned int i=0;i<facets.size();i++)
00548           //             {
00549           //               const helper::vector<int>& facet = facets[i][0];
00550           //               for (unsigned int j=2; j<facet.size(); j++) // Triangularize
00551           //               {
00552           //                 segmentsForIntersection.insert( SegmentForIntersection( vertices[facet[0]],vertices[facet[j]] ) );
00553           //                 segmentsForIntersection.insert( SegmentForIntersection( vertices[facet[0]],vertices[facet[j-1]] ) );
00554           //                 segmentsForIntersection.insert( SegmentForIntersection( vertices[facet[j]],vertices[facet[j-1]] ) );
00555           //               }
00556           //             }
00557 
00558 
00559           for(int i=0;i<regularGrid.getNbHexas();++i) // all possible cubes (even empty)
00560           {
00561               Hexa c = regularGrid.getHexaCopy(i);
00562               CubeCorners corners;
00563               for(int j=0;j<8;++j)
00564                   corners[j] = regularGrid.getPoint( c[j] );
00565 
00566               //               CubeForIntersection cubeForIntersection( corners );
00567               // 
00568               //               for(std::set< SegmentForIntersection,ltSegmentForIntersection >::iterator it=segmentsForIntersection.begin();it!=segmentsForIntersection.end();++it)
00569               //                 {
00570               //                   if(intersectionSegmentBox( *it, cubeForIntersection ))
00571               //                   {
00572               //                     _types.push_back(BOUNDARY);
00573               //                    regularGridTypes[i]=BOUNDARY;
00574               // 
00575               //                     for(int k=0;k<8;++k)
00576               //                       cubeCornerPositionIndiceMap[corners[k]] = 0;
00577               // 
00578               //                    cubeCorners.push_back(corners);
00579               //                    _indicesOfRegularCubeInSparseGrid[i] = cubeCorners.size()-1;
00580               // 
00581               //                     break;
00582               //                   }
00583               //                 }
00584 
00585 #ifdef SOFA_NEW_HEXA
00586               Vector3 cubeDiagonal = corners[6] - corners[0];
00587 #else
00588               Vector3 cubeDiagonal = corners[7] - corners[0];
00589 #endif
00590               Vector3 cubeCenter = corners[0] + cubeDiagonal*.5;
00591 
00592 
00593               bool notAlreadyIntersected = true;
00594 
00595               const helper::vector< helper::vector < helper::vector <int> > >& facets = mesh->getFacets();  
00596               const helper::vector<Vector3>& vertices = mesh->getVertices();
00597               for (unsigned int f=0;f<facets.size() && notAlreadyIntersected;f++)
00598               {
00599                   const helper::vector<int>& facet = facets[f][0];
00600                   for (unsigned int j=2; j<facet.size()&& notAlreadyIntersected; j++) // Triangularize
00601                   {
00602                       const Vector3& A = vertices[facet[0]];
00603                       const Vector3& B = vertices[facet[j-1]];
00604                       const Vector3& C = vertices[facet[j]];
00605 
00606                       // Scale the triangle to the unit cube matching
00607                       float points[3][3];
00608                       for (unsigned short w=0;w<3;++w)
00609                       {
00610                           points[0][w] = (float) ((A[w]-cubeCenter[w])/cubeDiagonal[w]);
00611                           points[1][w] = (float) ((B[w]-cubeCenter[w])/cubeDiagonal[w]);
00612                           points[2][w] = (float) ((C[w]-cubeCenter[w])/cubeDiagonal[w]);
00613                       }
00614 
00615                       float normal[3];
00616                       helper::polygon_cube_intersection::get_polygon_normal(normal,3,points);
00617 
00618                       if (helper::polygon_cube_intersection::fast_polygon_intersects_cube(3,points,normal,0,0))
00619                       {
00620                           regularGridTypes[i]=BOUNDARY;                 
00621                           notAlreadyIntersected=false;
00622                       }
00623                   }
00624               }
00625           }
00626 
00627 
00628           // TODO: regarder les cellules pleines, et les ajouter
00629 
00630           vector<bool> alreadyTested(regularGrid.getNbHexas());
00631           for(int w=0;w<regularGrid.getNbHexas();++w)
00632               alreadyTested[w]=false;
00633 
00634           // x==0 and x=nx-2
00635           for(int y=0;y<regularGrid.getNy()-1;++y)
00636               for(int z=0;z<regularGrid.getNz()-1;++z)
00637               {
00638                   propagateFrom( 0, y, z, regularGrid, regularGridTypes, alreadyTested );
00639                   propagateFrom( regularGrid.getNx()-2, y, z, regularGrid, regularGridTypes, alreadyTested );
00640               }
00641           // y==0 and y=ny-2
00642           for(int x=0;x<regularGrid.getNx()-1;++x)
00643               for(int z=0;z<regularGrid.getNz()-1;++z)
00644               {
00645                   propagateFrom( x, 0, z, regularGrid, regularGridTypes, alreadyTested );
00646                   propagateFrom( x, regularGrid.getNy()-2, z, regularGrid, regularGridTypes, alreadyTested );
00647               }
00648           // z==0 and z==Nz-2
00649           for(int y=0;y<regularGrid.getNy()-1;++y)
00650               for(int x=0;x<regularGrid.getNx()-1;++x)
00651               {
00652                   propagateFrom( x, y, 0, regularGrid, regularGridTypes, alreadyTested );
00653                   propagateFrom( x, y, regularGrid.getNz()-2, regularGrid, regularGridTypes, alreadyTested );
00654               }
00655       }
00656 
00657       void SparseGridTopology::buildFromRegularGridTypes(RegularGridTopology& regularGrid, const vector<Type>& regularGridTypes)
00658       {
00659           vector< CubeCorners > cubeCorners; // saving temporary positions of all cube corners
00660           MapBetweenCornerPositionAndIndice cubeCornerPositionIndiceMap; // to compute cube corner indice values
00661 
00662           _indicesOfRegularCubeInSparseGrid.resize( _regularGrid.getNbHexas(), -1 ); // to redirect an indice of a cube in the regular grid to its indice in the sparse grid          
00663           int cubeCntr = 0;
00664           // add BOUNDARY cubes to valid cells
00665           for(int w=0; w<regularGrid.getNbHexas(); ++w)
00666               if( regularGridTypes[w] == BOUNDARY )
00667               {             
00668                   _types.push_back(BOUNDARY);
00669                   _indicesOfRegularCubeInSparseGrid[w] = cubeCntr++;
00670                   _indicesOfCubeinRegularGrid.push_back( w );
00671                   
00672 
00673                   Hexa c = regularGrid.getHexaCopy(w);
00674                   CubeCorners corners;
00675                   for(int j=0;j<8;++j)
00676                   {
00677                       corners[j] = regularGrid.getPoint( c[j] );
00678                       cubeCornerPositionIndiceMap[corners[j]] = 0;
00679                   }
00680                   cubeCorners.push_back(corners);
00681               }
00682               
00683           // add INSIDE cubes to valid cells
00684           for(int w=0; w<regularGrid.getNbHexas(); ++w)
00685               if( regularGridTypes[w] == INSIDE )
00686               {             
00687                   _types.push_back(INSIDE);
00688                   _indicesOfRegularCubeInSparseGrid[w] = cubeCntr++;
00689                   _indicesOfCubeinRegularGrid.push_back( w );
00690 
00691                   Hexa c = regularGrid.getHexaCopy(w);
00692                   CubeCorners corners;
00693                   for(int j=0;j<8;++j)
00694                   {
00695                       corners[j] = regularGrid.getPoint( c[j] );
00696                       cubeCornerPositionIndiceMap[corners[j]] = 0;
00697                   }
00698                   cubeCorners.push_back(corners);
00699               }       
00700 
00701           // compute corner indices
00702           int cornerCounter=0;
00703           for(MapBetweenCornerPositionAndIndice::iterator it = cubeCornerPositionIndiceMap.begin();
00704               it!=cubeCornerPositionIndiceMap.end(); ++it, ++cornerCounter)
00705           {
00706               (*it).second = cornerCounter;
00707               seqPoints.push_back( (*it).first );
00708           }
00709           nbPoints = cubeCornerPositionIndiceMap.size();
00710 
00711           SeqHexas& hexas = *seqHexas.beginEdit();
00712           for( unsigned w=0; w<cubeCorners.size(); ++w)
00713           {
00714               Hexa c;
00715               for(int j=0;j<8;++j)
00716                   c[j] = cubeCornerPositionIndiceMap[cubeCorners[w][j]];
00717 
00718               hexas.push_back(c);
00719           }
00720           seqHexas.endEdit();
00721           
00722       }
00723 
00724       void SparseGridTopology::computeBoundingBox(const helper::vector<Vector3>& vertices,
00725           SReal& xmin, SReal& xmax,
00726           SReal& ymin, SReal& ymax,
00727           SReal& zmin, SReal& zmax) const
00728       {
00729           // bounding box computation
00730           xmin = vertices[0][0];
00731           ymin = vertices[0][1];
00732           zmin = vertices[0][2];
00733           xmax = vertices[0][0];
00734           ymax = vertices[0][1];
00735           zmax = vertices[0][2];
00736 
00737           for(unsigned w=1;w<vertices.size();++w)
00738           {
00739               if( vertices[w][0] > xmax ) 
00740                   xmax = vertices[w][0];
00741               else if( vertices[w][0] < xmin)
00742                   xmin = vertices[w][0];
00743 
00744               if( vertices[w][1] > ymax ) 
00745                   ymax = vertices[w][1];
00746               else if( vertices[w][1] < ymin ) 
00747                   ymin = vertices[w][1];
00748 
00749               if( vertices[w][2] > zmax ) 
00750                   zmax = vertices[w][2];
00751               else if( vertices[w][2] < zmin ) 
00752                   zmin = vertices[w][2];
00753           }
00754       } 
00755     
00756     void SparseGridTopology::buildFromFiner(  )
00757     {
00758 //      cerr<<"SparseGridTopology::buildFromFiner(  )\n";
00759         
00760                 
00761         setNx( _finerSparseGrid->getNx()/2+1 );
00762         setNy( _finerSparseGrid->getNy()/2+1 );
00763         setNz( _finerSparseGrid->getNz()/2+1 );
00764         
00765         _regularGrid.setSize(getNx(),getNy(),getNz());
00766 
00767         setMin(_finerSparseGrid->getMin());
00768 
00769         // the cube size of the coarser mesh is twice the cube size of the finer mesh
00770         // if the finer mesh contains an odd number of cubes in any direction, 
00771         // the coarser mesh will be a half cube size larger in that direction
00772         Vector3 dx = _finerSparseGrid->_regularGrid.getDx();
00773         Vector3 dy = _finerSparseGrid->_regularGrid.getDy();
00774         Vector3 dz = _finerSparseGrid->_regularGrid.getDz();
00775         setXmax(getXmin() + (getNx()-1) * (SReal)2.0 * dx[0]);
00776         setYmax(getYmin() + (getNy()-1) * (SReal)2.0 * dy[1]); 
00777         setZmax(getZmin() + (getNz()-1) * (SReal)2.0 * dz[2]); 
00778         
00779         
00780         _regularGrid.setPos(getXmin(), getXmax(), getYmin(), getYmax(), getZmin(), getZmax());
00781         
00782         _indicesOfRegularCubeInSparseGrid.resize( _regularGrid.getNbHexas(), -1 ); // to redirect an indice of a cube in the regular grid to its indice in the sparse grid
00783         
00784         vector< CubeCorners > cubeCorners; // saving temporary positions of all cube corners
00785         MapBetweenCornerPositionAndIndice cubeCornerPositionIndiceMap; // to compute cube corner indice values
00786         
00787         
00788         for(int i=0;i<getNx()-1;i++)
00789             for(int j=0;j<getNy()-1;j++)
00790                 for(int k=0;k<getNz()-1;k++)
00791         {
00792             int x = 2*i;
00793             int y = 2*j;
00794             int z = 2*k;
00795             
00796             fixed_array<int,8> fineIndices;
00797             for(int idx=0; idx<8; ++idx)
00798             {
00799                 const int idxX = x + (idx & 1);
00800                 const int idxY = y + (idx & 2)/2;
00801                 const int idxZ = z + (idx & 4)/4;
00802                 if(idxX < _finerSparseGrid->getNx()-1 && idxY < _finerSparseGrid->getNy()-1 && idxZ < _finerSparseGrid->getNz()-1)
00803                     fineIndices[idx] = _finerSparseGrid->_indicesOfRegularCubeInSparseGrid[ _finerSparseGrid->_regularGrid.cube(idxX,idxY,idxZ) ];
00804                 else
00805                     fineIndices[idx] = -1;
00806             }
00807 
00808             bool inside = true;
00809             bool outside = true;
00810             for( int w=0;w<8 && (inside || outside);++w)
00811             {
00812                 if( fineIndices[w] == -1 ) inside=false;
00813                 else
00814                 {
00815                     
00816                     if( _finerSparseGrid->getType( fineIndices[w] ) == BOUNDARY ) { inside=false;outside=false; }
00817                     else if( _finerSparseGrid->getType( fineIndices[w] ) == INSIDE ) {outside=false;}
00818                 }
00819             }
00820             
00821             if(outside) continue;
00822             if( inside )
00823             {
00824                 _types.push_back(INSIDE);
00825             }
00826             else
00827             {
00828                 _types.push_back(BOUNDARY);
00829             }
00830             
00831             
00832             int coarseRegularIndice = _regularGrid.cube( i,j,k );
00833             Hexa c = _regularGrid.getHexaCopy( coarseRegularIndice );
00834             
00835             CubeCorners corners;
00836             for(int w=0;w<8;++w)
00837             {
00838                 corners[w] = _regularGrid.getPoint( c[w] );
00839                 cubeCornerPositionIndiceMap[corners[w]] = 0;
00840             }
00841             
00842             cubeCorners.push_back(corners);
00843         
00844             _indicesOfRegularCubeInSparseGrid[coarseRegularIndice] = cubeCorners.size()-1;
00845             _indicesOfCubeinRegularGrid.push_back( coarseRegularIndice );
00846             
00847 //          _hierarchicalCubeMap[cubeCorners.size()-1]=fineIndices;
00848             _hierarchicalCubeMap.push_back( fineIndices );
00849         }
00850         
00851         
00852         // compute corner indices
00853         int cornerCounter=0;
00854         for(MapBetweenCornerPositionAndIndice::iterator it=cubeCornerPositionIndiceMap.begin();it!=cubeCornerPositionIndiceMap.end();++it,++cornerCounter)
00855         {
00856             (*it).second = cornerCounter;
00857             seqPoints.push_back( (*it).first );
00858         }
00859         nbPoints = cubeCornerPositionIndiceMap.size();
00860 
00861           SeqHexas& hexas = *seqHexas.beginEdit();
00862         for( unsigned w=0;w<cubeCorners.size();++w)
00863         {
00864             Hexa c;
00865             for(int j=0;j<8;++j)
00866                 c[j] = cubeCornerPositionIndiceMap[cubeCorners[w][j]];
00867 
00868             hexas.push_back(c);
00869         }
00870           seqHexas.endEdit();
00871         
00872         
00873         // for interpolation and restriction
00874         _hierarchicalPointMap.resize(seqPoints.size());
00875         _finerSparseGrid->_inverseHierarchicalPointMap.resize(_finerSparseGrid->seqPoints.size());
00876         _finerSparseGrid->_inversePointMap.resize(_finerSparseGrid->seqPoints.size()); _finerSparseGrid->_inversePointMap.fill(-1);
00877         _pointMap.resize(seqPoints.size()); _pointMap.fill(-1);
00878         for( unsigned w=0;w<seqHexas.getValue().size();++w)
00879         {
00880             const fixed_array<int, 8>& child = _hierarchicalCubeMap[w];
00881             
00882             
00883             
00884             helper::vector<int> fineCorners(27);
00885             fineCorners.fill(-1);
00886             for(int fineCube=0;fineCube<8;++fineCube)
00887             {
00888                 if( child[fineCube] == -1 ) continue;
00889                 
00890                 const Hexa& cube = _finerSparseGrid->getHexa(child[fineCube]);
00891 
00892                 for(int vertex=0;vertex<8;++vertex)
00893                 {
00894 //                  if( fineCorners[cornerIndicesFromFineToCoarse[fineCube][vertex]]!=-1 && fineCorners[cornerIndicesFromFineToCoarse[fineCube][vertex]]!=cube[vertex] )
00895 //                      cerr<<"couille fineCorners\n";
00896                     fineCorners[cornerIndicesFromFineToCoarse[fineCube][vertex]]=cube[vertex];
00897                 }
00898                 
00899             }
00900 
00901             
00902             for(int coarseCornerLocalIndice=0;coarseCornerLocalIndice<8;++coarseCornerLocalIndice)
00903             {
00904                 for( int fineVertexLocalIndice=0;fineVertexLocalIndice<27;++fineVertexLocalIndice)
00905                 {
00906                     if( fineCorners[fineVertexLocalIndice] == -1 ) continue; // this fine vertex is not in any fine cube
00907                     
00908                     int coarseCornerGlobalIndice = seqHexas.getValue()[w][coarseCornerLocalIndice];
00909                     int fineVertexGlobalIndice = fineCorners[fineVertexLocalIndice];
00910 
00911                     if( WEIGHT27[coarseCornerLocalIndice][fineVertexLocalIndice] )
00912                     {
00913                         _hierarchicalPointMap[coarseCornerGlobalIndice][fineVertexGlobalIndice] = WEIGHT27[coarseCornerLocalIndice][fineVertexLocalIndice];
00914 //                      _hierarchicalPointMap[coarseCornerGlobalIndice].push_back( std::pair<int,float>(fineVertexGlobalIndice, WEIGHT27[coarseCornerLocalIndice][fineVertexLocalIndice]) );
00915                     
00916                     
00917                         _finerSparseGrid->_inverseHierarchicalPointMap[fineVertexGlobalIndice][coarseCornerGlobalIndice] = WEIGHT27[coarseCornerLocalIndice][fineVertexLocalIndice];
00918                         
00919                         if( WEIGHT27[coarseCornerLocalIndice][fineVertexLocalIndice] == 1.0 )
00920                         {
00921                             _finerSparseGrid->_inversePointMap[fineVertexGlobalIndice] = coarseCornerGlobalIndice;
00922 //                          cerr<<getPX(coarseCornerGlobalIndice)<<" "<<getPY(coarseCornerGlobalIndice)<<" "<<getPZ(coarseCornerGlobalIndice)<<" ----- ";
00923 //                          cerr<<_finerSparseGrid->getPX(fineVertexGlobalIndice)<<" "<<_finerSparseGrid->getPY(fineVertexGlobalIndice)<<" "<<_finerSparseGrid->getPZ(fineVertexGlobalIndice)<<endl;
00924                         }
00925                     }
00926                 }
00927             }
00928             
00929         }
00930         
00931         
00932         for( unsigned i=0;i<_finerSparseGrid->_inversePointMap.size();++i)
00933         {
00934             if(_finerSparseGrid->_inversePointMap[i] != -1)
00935                 _pointMap[ _finerSparseGrid->_inversePointMap[i] ] = i;
00936         }
00937 
00938 //      for(unsigned i=0;i<_finerSparseGrid->seqPoints.size();++i)
00939 //      {
00940 //          cerr<<i<<" : "<<_finerSparseGrid->seqPoints[i]<<endl;
00941 //      }
00942 //      
00943 //      for(unsigned i=0;i<_finerSparseGrid->seqHexas.getValue().size();++i)
00944 //      {
00945 //          cerr<<i<<" : "<<_finerSparseGrid->seqHexas.getValue()[i]<<endl;
00946 //          
00947 //      }
00948         
00949         
00950         
00951         
00952 // //       afficher la _hierarchicalPointMap
00953 //      for(unsigned i=0;i<_hierarchicalPointMap.size();++i)
00954 //      {
00955 //          cerr<<"POINT "<<i<<" "<<seqPoints[i]<<" : "<<_hierarchicalPointMap[i].size()<<" : ";
00956 //          for(std::map<int,float>::iterator it = _hierarchicalPointMap[i].begin();it != _hierarchicalPointMap[i].end() ; ++it )
00957 //          {
00958 //              cerr<<(*it).first<<", "<<(*it).second<<" # ";
00959 //          }
00960 //          cerr<<endl;
00961 //      }
00962 // //       
00963 // //       // //       afficher la _inverseHierarchicalPointMap
00964         
00965 //      cerr<<"_inverseHierarchicalPointMap :"<<endl;
00966 //      for(unsigned i=0;i<_finerSparseGrid->_inverseHierarchicalPointMap.size();++i)
00967 //      {
00968 //          cerr<<"POINT "<<i<<" "<<seqPoints[i]<<" : "<<_finerSparseGrid->_inverseHierarchicalPointMap[i].size()<<" : ";
00969 //          for(std::map<int,float>::iterator it = _finerSparseGrid->_inverseHierarchicalPointMap[i].begin();it != _finerSparseGrid->_inverseHierarchicalPointMap[i].end() ; ++it )
00970 //          {
00971 //              cerr<<(*it).first<<", "<<(*it).second<<" # ";
00972 //          }
00973 //          cerr<<endl;
00974 //      }
00975         
00976 //      cerr<<"_inversePointMap :"<<endl;
00977 //      for(unsigned i=0;i<_finerSparseGrid->_inversePointMap.size();++i)
00978 //      {
00979 //          cerr<<"POINT "<<i<<" -> "<<_finerSparseGrid->_inversePointMap[i]<<endl;
00980 //      }
00981         
00982         
00983 //      for(int o=0;o<_hierarchicalPointMap.size();++o)
00984 //      {
00985 //          cerr<<o<<" : ";
00986 //          for(std::set<int>::iterator it=_hierarchicalPointMap[o].begin();it!=_hierarchicalPointMap[o].end();++it)
00987 //              cerr<<*it<<" ";
00988 //          cerr<<endl;
00989 //      }
00990         
00991         
00992 //      cerr<<"seqHexas.getValue() : "<<seqHexas.getValue()<<endl;
00993 //      cerr<<"seqPoints : "<<seqPoints<<endl;
00994         
00995         
00996         
00997         _finerSparseGrid->_coarserSparseGrid = this;
00998         _finerSparseGrid->_inverseHierarchicalCubeMap.resize( _finerSparseGrid->seqHexas.getValue().size(), -1);
00999         for( unsigned i=0;i<_hierarchicalCubeMap.size();++i)
01000             for(int w=0;w<8;++w)
01001             {
01002                 if(_hierarchicalCubeMap[i][w] != -1)
01003                     _finerSparseGrid->_inverseHierarchicalCubeMap[ _hierarchicalCubeMap[i][w] ] = i;
01004             }   
01005     }
01006 
01007     
01008     
01009     
01010     
01011     
01012     void SparseGridTopology::buildVirtualFinerLevels()
01013     {
01014         int nb = _nbVirtualFinerLevels.getValue();
01015         
01016         _virtualFinerLevels.resize(nb);
01017         
01018         int newnx=n.getValue()[0],newny=n.getValue()[1],newnz=n.getValue()[2];
01019         for( int i=0;i<nb;++i)
01020         {
01021             newnx = (newnx-1)*2+1;
01022             newny = (newny-1)*2+1;
01023             newnz = (newnz-1)*2+1;
01024         }
01025         
01026         _virtualFinerLevels[0] = new SparseGridTopology(true);
01027         _virtualFinerLevels[0]->setNx( newnx );
01028         _virtualFinerLevels[0]->setNy( newny );
01029         _virtualFinerLevels[0]->setNz( newnz );
01030         _virtualFinerLevels[0]->load(this->d_filename.getValue().c_str());
01031         _virtualFinerLevels[0]->init();
01032         
01033         cerr<<"SparseGridTopology "<<getName()<<" buildVirtualFinerLevels : ";
01034         cerr<<"("<<newnx<<"x"<<newny<<"x"<<newnz<<") -> "<< _virtualFinerLevels[0]->getNbHexas() <<" elements , ";
01035         
01036         for(int i=1;i<nb;++i)
01037         {
01038             _virtualFinerLevels[i] = new SparseGridTopology(true);
01039             
01040 
01041             _virtualFinerLevels[i]->setFinerSparseGrid(_virtualFinerLevels[i-1]);
01042             
01043             _virtualFinerLevels[i]->init();
01044             
01045             
01046             cerr<<"("<<_virtualFinerLevels[i]->getNx()<<"x"<<_virtualFinerLevels[i]->getNy()<<"x"<<_virtualFinerLevels[i]->getNz()<<") -> "<< _virtualFinerLevels[i]->getNbHexas() <<" elements , ";
01047         }
01048         
01049         cerr<<endl;
01050         
01051         this->setFinerSparseGrid(_virtualFinerLevels[nb-1]);
01052         
01053         
01054     }
01055     
01056     
01057     
01058 
01062 
01063 
01064     
01065     
01068     int SparseGridTopology::findCube(const Vector3& pos, SReal& fx, SReal &fy, SReal &fz)
01069     {
01070         int indiceInRegularGrid = _regularGrid.findCube( pos,fx,fy,fz);
01071         if( indiceInRegularGrid == -1 )
01072             return -1;
01073         else
01074             return _indicesOfRegularCubeInSparseGrid[indiceInRegularGrid];
01075     }
01076 
01079     int SparseGridTopology::findNearestCube(const Vector3& pos, SReal& fx, SReal &fy, SReal &fz)
01080     {     
01081             if (seqHexas.getValue().size() == 0) return -1;
01082             int indice = 0;
01083             float lgmin = 99999999.0f;
01084 
01085             for(unsigned w=0;w<seqHexas.getValue().size();++w)
01086             {
01087                 if(!_usingMC && _types[w]!=BOUNDARY )continue;
01088                 
01089                 const Hexa& c = getHexa( w );
01090                 int c0 = c[0];
01091 #ifdef SOFA_NEW_HEXA            
01092                 int c7 = c[6];
01093 #else
01094                 int c7 = c[7];
01095 #endif          
01096                 Vector3 p0((SReal)getPX(c0), (SReal)getPY(c0), (SReal)getPZ(c0));
01097                 Vector3 p7((SReal)getPX(c7), (SReal)getPY(c7), (SReal)getPZ(c7));
01098                 
01099                 Vector3 barycenter = (p0+p7) * .5;
01100 
01101                 float lg = (float)((pos-barycenter).norm());
01102                 if( lg < lgmin )
01103                 {
01104                     lgmin = lg;
01105                     indice = w;
01106                 }
01107             }
01108             
01109             const Hexa& c = getHexa( indice );
01110             int c0 = c[0];
01111 #ifdef SOFA_NEW_HEXA            
01112             int c7 = c[6];
01113 #else
01114             int c7 = c[7];
01115 #endif
01116             Vector3 p0((SReal)getPX(c0), (SReal)getPY(c0), (SReal)getPZ(c0));
01117             Vector3 p7((SReal)getPX(c7), (SReal)getPY(c7), (SReal)getPZ(c7));
01118             
01119             Vector3 relativePos = pos-p0;
01120             Vector3 diagonal = p7 - p0;
01121             
01122             fx = relativePos[0] / diagonal[0];
01123             fy = relativePos[1] / diagonal[1];
01124             fz = relativePos[2] / diagonal[2];
01125             
01126             return indice;
01127     }
01128     
01129     
01130     
01131     
01132     helper::fixed_array<int,6> SparseGridTopology::findneighboorCubes( int indice )
01133     {
01134         cerr<<"SparseGridTopology::findneighboorCubes : "<<indice<<" -> "<<_indicesOfCubeinRegularGrid[indice]<<endl;
01135         cerr<<_indicesOfRegularCubeInSparseGrid[ _indicesOfCubeinRegularGrid[indice] ] <<endl;
01136         helper::fixed_array<int,6> result;
01137         Vector3 c = _regularGrid.getCubeCoordinate( _indicesOfCubeinRegularGrid[indice] );
01138         cerr<<c<<endl;
01139         result[0] = c[0]<=0 ? -1 : _indicesOfRegularCubeInSparseGrid[ _regularGrid.getCubeIndex( (int)c[0]-1,(int)c[1],(int)c[2] )];
01140         result[1] = c[0]>=getNx()-2 ? -1 : _indicesOfRegularCubeInSparseGrid[ _regularGrid.getCubeIndex( (int)c[0]+1,(int)c[1],(int)c[2] )];
01141         result[2] = c[1]<=0 ? -1 : _indicesOfRegularCubeInSparseGrid[ _regularGrid.getCubeIndex( (int)c[0],(int)c[1]-1,(int)c[2] )];
01142         result[3] = c[1]>=getNy()-2 ? -1 : _indicesOfRegularCubeInSparseGrid[ _regularGrid.getCubeIndex( (int)c[0],(int)c[1]+1,(int)c[2] )];
01143         result[4] = c[2]<=0 ? -1 : _indicesOfRegularCubeInSparseGrid[ _regularGrid.getCubeIndex( (int)c[0],(int)c[1],(int)c[2]-1 )];
01144         result[5] = c[2]>=getNz()-2 ? -1 : _indicesOfRegularCubeInSparseGrid[ _regularGrid.getCubeIndex( (int)c[0],(int)c[1],(int)c[2]+1 )];
01145         return result;
01146     }
01147     
01148     
01149     
01150     SparseGridTopology::Type SparseGridTopology::getType( int i )
01151     {
01152         return _types[i];
01153     }
01154     
01158 
01159 
01160 
01161     void SparseGridTopology::updateEdges()
01162     {
01163       std::map<pair<int,int>,bool> edgesMap;
01164       for(unsigned i=0;i<seqHexas.getValue().size();++i)
01165       {
01166         Hexa c = seqHexas.getValue()[i];
01167         // horizontal
01168         edgesMap[pair<int,int>(c[0],c[1])]=0;
01169         edgesMap[pair<int,int>(c[2],c[3])]=0;
01170         edgesMap[pair<int,int>(c[4],c[5])]=0;
01171         edgesMap[pair<int,int>(c[6],c[7])]=0;
01172         // vertical
01173         edgesMap[pair<int,int>(c[0],c[2])]=0;
01174         edgesMap[pair<int,int>(c[1],c[3])]=0;
01175         edgesMap[pair<int,int>(c[4],c[6])]=0;
01176         edgesMap[pair<int,int>(c[5],c[7])]=0;
01177         // profondeur
01178         edgesMap[pair<int,int>(c[0],c[4])]=0;
01179         edgesMap[pair<int,int>(c[1],c[5])]=0;
01180         edgesMap[pair<int,int>(c[2],c[6])]=0;
01181         edgesMap[pair<int,int>(c[3],c[7])]=0;
01182       }
01183 
01184 
01185       SeqEdges& edges = *seqEdges.beginEdit();
01186       edges.clear();
01187       edges.reserve(edgesMap.size());
01188       for( std::map<pair<int,int>,bool>::iterator it=edgesMap.begin();it!=edgesMap.end();++it)
01189         edges.push_back( Edge( (*it).first.first,  (*it).first.second ));
01190       seqEdges.endEdit();
01191     }
01192 
01193     void SparseGridTopology::updateQuads()
01194     {
01195       std::map<fixed_array<int,4>,bool> quadsMap;
01196       for(unsigned i=0;i<seqHexas.getValue().size();++i)
01197       {
01198         Hexa c = seqHexas.getValue()[i];
01199 
01200         fixed_array<int,4> v;
01201         v[0]=c[0];v[1]=c[1];v[2]=c[3];v[3]=c[2];
01202         quadsMap[v]=0;
01203         v[0]=c[4];v[1]=c[5];v[2]=c[7];v[3]=c[6];
01204         quadsMap[v]=0;
01205         v[0]=c[0];v[1]=c[1];v[2]=c[5];v[3]=c[4];
01206         quadsMap[v]=0;
01207         v[0]=c[2];v[1]=c[3];v[2]=c[7];v[3]=c[6];
01208         quadsMap[v]=0;
01209         v[0]=c[0];v[1]=c[4];v[2]=c[6];v[3]=c[2];
01210         quadsMap[v]=0;
01211         v[0]=c[1];v[1]=c[5];v[2]=c[7];v[3]=c[3];
01212         quadsMap[v]=0;
01213 
01214       }
01215       SeqQuads& quads = *seqQuads.beginEdit();
01216       quads.clear();
01217       quads.reserve(quadsMap.size());
01218       for( std::map<fixed_array<int,4>,bool>::iterator it=quadsMap.begin();it!=quadsMap.end();++it)
01219           quads.push_back( Quad( (*it).first[0],  (*it).first[1],(*it).first[2],(*it).first[3] ));
01220       seqQuads.endEdit();
01221     }
01222 
01223     void SparseGridTopology::updateHexas()
01224     {
01225       //                    seqHexas.getValue().clear();
01226       //                    seqHexas.getValue().reserve(_cubes.size());
01227 
01228       //                                seqHexas.getValue().push_back(Hexa(point(x  ,y  ,z  ),point(x+1,y  ,z  ),
01229       //                                        point(x  ,y+1,z  ),point(x+1,y+1,z  ),
01230       //                                        point(x  ,y  ,z+1),point(x+1,y  ,z+1),
01231       //                                        point(x  ,y+1,z+1),point(x+1,y+1,z+1)));
01232     }
01233 
01234 
01237 
01238 //     bool SparseGridTopology::intersectionSegmentBox( const SegmentForIntersection& seg, const CubeForIntersection& cube  )
01239 //     {
01240 //       Vector3 afAWdU, afADdU, afAWxDdU;
01241 //       SReal fRhs;
01242 // 
01243 // 
01244 //       Vector3 kDiff = seg.center - cube.center;
01245 // 
01246 //       afAWdU[0] = fabs( seg.dir* cube.dir[0]);
01247 //       afADdU[0] = fabs( kDiff * cube.dir[0] );
01248 //       fRhs = cube.norm[0] + seg.norm*afAWdU[0];
01249 //       if (afADdU[0] > fRhs)
01250 //       {
01251 //         return false;
01252 //       }
01253 // 
01254 //       afAWdU[1] = fabs(seg.dir*cube.dir[1]);
01255 //       afADdU[1] = fabs(kDiff*cube.dir[1]);
01256 //       fRhs = cube.norm[1] + seg.norm*afAWdU[1];
01257 //       if (afADdU[1] > fRhs)
01258 //       {
01259 //         return false;
01260 //       }
01261 // 
01262 //       afAWdU[2] = fabs(seg.dir*cube.dir[2]);
01263 //       afADdU[2] = fabs(kDiff*cube.dir[2]);
01264 //       fRhs = cube.norm[2] + seg.norm*afAWdU[2];
01265 //       if (afADdU[2] > fRhs)
01266 //       {
01267 //         return false;
01268 //       }
01269 // 
01270 //       Vector3 kWxD = seg.dir.cross(kDiff);
01271 // 
01272 //       afAWxDdU[0] = fabs(kWxD*cube.dir[0]);
01273 //       fRhs = cube.norm[1]*afAWdU[2] + cube.norm[2]*afAWdU[1];
01274 //       if (afAWxDdU[0] > fRhs)
01275 //       {
01276 //         return false;
01277 //       }
01278 // 
01279 //       afAWxDdU[1] = fabs(kWxD*cube.dir[1]);
01280 //       fRhs = cube.norm[0]*afAWdU[2] + cube.norm[2]*afAWdU[0];
01281 //       if (afAWxDdU[1] > fRhs)
01282 //       {
01283 //         return false;
01284 //       }
01285 // 
01286 //       afAWxDdU[2] = fabs(kWxD*cube.dir[2]);
01287 //       fRhs = cube.norm[0]*afAWdU[1] +cube.norm[1]*afAWdU[0];
01288 //       if (afAWxDdU[2] > fRhs)
01289 //       {
01290 //         return false;
01291 //       }
01292 // 
01293 //       return true;
01294 //     }
01295     
01296     
01297     void SparseGridTopology::propagateFrom( const int i, const int j, const int k,  
01298                                             RegularGridTopology& regularGrid, 
01299                                             vector<Type>& regularGridTypes, 
01300                                             vector<bool>& alreadyTested  ) const
01301     {
01302         assert( i>=0 && i<=regularGrid.getNx()-2 && j>=0 && j<=regularGrid.getNy()-2 && k>=0 && k<=regularGrid.getNz()-2 );
01303         
01304         unsigned indice = regularGrid.cube( i, j, k );
01305         
01306         if( alreadyTested[indice] || regularGridTypes[indice] == BOUNDARY )
01307             return;
01308 
01309         alreadyTested[indice] = true;
01310         regularGridTypes[indice] = OUTSIDE;
01311         
01312         if(i>0) propagateFrom( i-1, j, k, regularGrid, regularGridTypes, alreadyTested );
01313         if(i<regularGrid.getNx()-2) propagateFrom( i+1, j, k, regularGrid, regularGridTypes, alreadyTested );
01314         if(j>0) propagateFrom( i, j-1, k, regularGrid, regularGridTypes, alreadyTested );
01315         if(j<regularGrid.getNy()-2) propagateFrom( i, j+1, k, regularGrid, regularGridTypes, alreadyTested );
01316         if(k>0) propagateFrom( i, j, k-1, regularGrid, regularGridTypes, alreadyTested );
01317         if(k<regularGrid.getNz()-2) propagateFrom( i, j, k+1, regularGrid, regularGridTypes, alreadyTested );
01318     }
01319     
01320     
01321     
01322     
01324     
01325     
01326   } // namespace topology
01327 
01328 } // namespace component
01329 
01330 } // namespace sofa

Generated on Sun Nov 23 03:45:50 2008 for Sofa by  doxygen 1.5.7.1