00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 const float SparseGridTopology::WEIGHT27[8][27] =
00075 {
00076
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
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
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
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
00207
00208
00209
00210
00211
00212 }
00213
00214
00215
00216 void SparseGridTopology::buildAsFinest( )
00217 {
00218
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
00229
00230
00231
00232 if(_filename.length() > 4 && _filename.compare(_filename.length()-4, 4, ".obj")==0)
00233 {
00234
00235 buildFromTriangleMesh(_filename);
00236 }
00237 else if(_filename.length() > 6 && _filename.compare(_filename.length()-6, 6, ".trian")==0)
00238 {
00239
00240 buildFromTriangleMesh(_filename);
00241 }
00242 else if(_filename.length() > 4 && _filename.compare(_filename.length()-4, 4, ".raw")==0)
00243 {
00244
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
00275
00276
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);
00316
00317
00318 vector<Type> regularGridTypes(nbCubesRG, OUTSIDE);
00319
00320
00321
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
00336 void SparseGridTopology::buildFromRawVoxelFile(const std::string& filename)
00337 {
00338
00339
00340
00341 _regularGrid.setSize(getNx(),getNy(),getNz());
00342 const int nbCubesRG = _regularGrid.getNbHexas();
00343
00344 _indicesOfRegularCubeInSparseGrid.resize(nbCubesRG, -1);
00345 vector<Type> regularGridTypes(nbCubesRG, OUTSIDE);
00346
00347
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
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
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
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
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)
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)
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;
00446
00447
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());
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
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
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
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;
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
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559 for(int i=0;i<regularGrid.getNbHexas();++i)
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
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
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++)
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
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
00629
00630 vector<bool> alreadyTested(regularGrid.getNbHexas());
00631 for(int w=0;w<regularGrid.getNbHexas();++w)
00632 alreadyTested[w]=false;
00633
00634
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
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
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;
00660 MapBetweenCornerPositionAndIndice cubeCornerPositionIndiceMap;
00661
00662 _indicesOfRegularCubeInSparseGrid.resize( _regularGrid.getNbHexas(), -1 );
00663 int cubeCntr = 0;
00664
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
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
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
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
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
00770
00771
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 );
00783
00784 vector< CubeCorners > cubeCorners;
00785 MapBetweenCornerPositionAndIndice cubeCornerPositionIndiceMap;
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
00848 _hierarchicalCubeMap.push_back( fineIndices );
00849 }
00850
00851
00852
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
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
00895
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;
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
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
00923
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
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
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
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
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
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
01226
01227
01228
01229
01230
01231
01232 }
01233
01234
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
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 }
01327
01328 }
01329
01330 }