1 // Copyright (C) 2012-2015 ALNEOS
2 // Copyright (C) 2016-2021 EDF R&D
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 // See http://www.alneos.com/ or email : contact@alneos.fr
19 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 #include "GMSHPlugin_Mesher.hxx"
22 #include "GMSHPlugin_Hypothesis_2D.hxx"
24 #include <SMDS_FaceOfNodes.hxx>
25 #include <SMDS_MeshElement.hxx>
26 #include <SMDS_MeshNode.hxx>
27 #include <SMESHDS_Mesh.hxx>
28 #include <SMESH_Block.hxx>
29 #include <SMESH_Comment.hxx>
30 #include <SMESH_ComputeError.hxx>
31 #include <SMESH_File.hxx>
32 #include <SMESH_Gen_i.hxx>
33 #include <SMESH_Mesh.hxx>
34 #include <SMESH_MesherHelper.hxx>
35 #include <SMESH_subMesh.hxx>
36 #include <utilities.h>
41 #include <BRep_Tool.hxx>
42 #include <Bnd_B3d.hxx>
43 #include <GCPnts_AbscissaPoint.hxx>
44 #include <GeomAdaptor_Curve.hxx>
45 #include <NCollection_Map.hxx>
46 #include <OSD_File.hxx>
47 #include <OSD_Path.hxx>
48 #include <Standard_ErrorHandler.hxx>
49 #include <Standard_ProgramError.hxx>
50 #include <TCollection_AsciiString.hxx>
52 #include <TopExp_Explorer.hxx>
53 #include <TopTools_DataMapIteratorOfDataMapOfShapeInteger.hxx>
54 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
55 #include <TopTools_DataMapOfShapeInteger.hxx>
56 #include <TopTools_DataMapOfShapeShape.hxx>
57 #include <TopTools_ListIteratorOfListOfShape.hxx>
58 #include <TopTools_MapOfShape.hxx>
61 #if GMSH_MAJOR_VERSION >=4
62 #include <GmshGlobal.h>
63 #include <gmsh/Context.h>
66 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
76 SBoundingBox3d _bounds;
80 //================================================================================
82 * \brief Retrieve ShapeBounds from a compound GEdge
84 //================================================================================
86 bool getBoundsOfShapes( GEdge* gEdge,
87 std::vector< ShapeBounds > & topoEdges )
90 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
91 for ( size_t i = 0; i < gEdge->compound.size(); ++i )
93 GEdge* gE = static_cast< GEdge* >( gEdge->compound[ i ]);
94 topoEdges.push_back( ShapeBounds{ gE->bounds(), *((TopoDS_Edge*)gE->getNativePtr()) });
97 for ( size_t i = 0; i < gEdge->_compound.size(); ++i )
99 GEdge* gE = static_cast< GEdge* >( gEdge->_compound[ i ]);
100 topoEdges.push_back( ShapeBounds{ gE->bounds(), *((TopoDS_Edge*)gE->getNativePtr()) });
103 return topoEdges.size();
106 //================================================================================
108 * \brief Retrieve ShapeBounds from a compound GFace
110 //================================================================================
112 bool getBoundsOfShapes( GFace* gFace,
113 std::vector< ShapeBounds > & topoFaces )
116 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
117 for ( size_t i = 0; i < gFace->compound.size(); ++i )
119 GFace* gF = static_cast< GFace* >( gFace->compound[ i ]);
120 topoFaces.push_back( ShapeBounds{ gF->bounds(), *((TopoDS_Face*)gF->getNativePtr()) });
123 for ( size_t i = 0; i < gFace->_compound.size(); ++i )
125 GFace* gF = static_cast< GFace* >( gFace->_compound[ i ]);
126 topoFaces.push_back( ShapeBounds{ gF->bounds(), *((TopoDS_Face*)gF->getNativePtr()) });
129 return topoFaces.size();
131 //================================================================================
133 * \brief Find a shape whose bounding box includes a given point
135 //================================================================================
137 TopoDS_Shape getShapeAtPoint( const SPoint3& point, const std::vector< ShapeBounds > & shapes )
140 float distmin = std::numeric_limits<float>::max();
141 for ( size_t i = 0; i < shapes.size(); ++i )
143 float dist = GMSHPlugin_Mesher::DistBoundingBox( shapes[i]._bounds, point );
146 shape = shapes[i]._shape;
156 //=============================================================================
160 //=============================================================================
162 GMSHPlugin_Mesher::GMSHPlugin_Mesher (SMESH_Mesh* mesh,
163 const TopoDS_Shape& aShape)
167 // il faudra peut être mettre un truc par defaut si l'utilisateur ne rentre rien en para
168 //defaultParameters();
171 //void GMSHPlugin_Mesher::defaultParameters(){}
173 void GMSHPlugin_Mesher::SetParameters(const GMSHPlugin_Hypothesis* hyp)
177 _algo2d = hyp->Get2DAlgo();
178 _algo3d = hyp->Get3DAlgo();
179 _recomb2DAlgo = hyp->GetRecomb2DAlgo();
180 _recombineAll = hyp->GetRecombineAll();
181 _subdivAlgo = hyp->GetSubdivAlgo();
182 _remeshAlgo = hyp->GetRemeshAlgo();
183 _remeshPara = hyp->GetRemeshPara();
184 _smouthSteps = hyp->GetSmouthSteps();
185 _sizeFactor = hyp->GetSizeFactor();
186 _minSize = hyp->GetMinSize();
187 _maxSize = hyp->GetMaxSize();
188 _secondOrder = hyp->GetSecondOrder();
189 _useIncomplElem = hyp->GetUseIncomplElem();
190 _is2d = hyp->GetIs2d();
191 _compounds = hyp->GetCompoundOnEntries();
198 _recombineAll = false;
206 _secondOrder = false;
207 _useIncomplElem = true;
214 //================================================================================
216 * \brief Set maximum number of threads to be used by Gmsh
218 //================================================================================
220 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
221 void GMSHPlugin_Mesher::SetMaxThreadsGmsh()
223 MESSAGE("GMSHPlugin_Mesher::SetMaxThreadsGmsh");
224 if (_compounds.size() > 0)
227 _maxThreads = omp_get_max_threads();
231 //================================================================================
233 * \brief Set Gmsh Options
235 //================================================================================
237 void GMSHPlugin_Mesher::SetGmshOptions()
239 MESSAGE("GMSHPlugin_Mesher::SetGmshOptions");
241 printf("We chose _algo2d %d \n", _algo2d );
242 printf("We chose _algo3d %d \n", _algo3d );
243 printf("We chose _recomb2DAlgo %d \n", _recomb2DAlgo );
244 printf("We chose _recombineAll %d \n", (_recombineAll)?1:0);
245 printf("We chose _subdivAlgo %d \n", _subdivAlgo );
246 printf("We chose _remeshAlgo %d \n", _remeshAlgo );
247 printf("We chose _remeshPara %d \n", _remeshPara );
248 printf("We chose _smouthSteps %e \n", _smouthSteps );
249 printf("We chose _sizeFactor %e \n", _sizeFactor );
250 printf("We chose _minSize %e \n", _minSize );
251 printf("We chose _maxSize %e \n", _maxSize );
252 printf("We chose _secondOrder %d \n", (_secondOrder)?1:0);
253 printf("We chose _useIncomplElem %d \n", (_useIncomplElem)?1:0);
254 printf("We are in dimension %d \n", (_is2d)?2:3);
257 std::map <int,double> mapAlgo2d;
258 mapAlgo2d[0]=2; // Automatic
259 mapAlgo2d[1]=1; // MeshAdapt
260 mapAlgo2d[2]=5; // Delaunay
261 mapAlgo2d[3]=6; // Frontal-Delaunay
262 mapAlgo2d[4]=8; // DelQuad (Frontal-Delaunay for Quads)
263 mapAlgo2d[5]=9; // Packing of parallelograms
265 std::map <int,double> mapAlgo3d;
266 mapAlgo3d[0]=1; // Delaunay
267 mapAlgo3d[1]=4; // Frontal
268 mapAlgo3d[2]=7; // MMG3D
269 mapAlgo3d[3]=9; // R-tree
270 mapAlgo3d[4]=10;// HXT
273 ok = GmshSetOption("Mesh", "Algorithm" , mapAlgo2d[_algo2d]) ;
277 ok = GmshSetOption("Mesh", "Algorithm3D" , mapAlgo3d[_algo3d]) ;
280 ok = GmshSetOption("Mesh", "RecombinationAlgorithm" , (double)_recomb2DAlgo) ;
282 ok = GmshSetOption("Mesh", "RecombineAll" , (_recombineAll)?1.:0.) ;
284 ok = GmshSetOption("Mesh", "SubdivisionAlgorithm" , (double)_subdivAlgo) ;
286 ok = GmshSetOption("Mesh", "RemeshAlgorithm" , (double)_remeshAlgo) ;
288 ok = GmshSetOption("Mesh", "RemeshParametrization" , (double)_remeshPara) ;
290 ok = GmshSetOption("Mesh", "Smoothing" , (double)_smouthSteps) ;
292 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
293 ok = GmshSetOption("Mesh", "MeshSizeFactor" , _sizeFactor) ;
295 ok = GmshSetOption("Mesh", "MeshSizeMin" , _minSize) ;
297 ok = GmshSetOption("Mesh", "MeshSizeMax" , _maxSize) ;
300 ok = GmshSetOption("Mesh", "CharacteristicLengthFactor" , _sizeFactor) ;
302 ok = GmshSetOption("Mesh", "CharacteristicLengthMin" , _minSize) ;
304 ok = GmshSetOption("Mesh", "CharacteristicLengthMax" , _maxSize) ;
307 ok = GmshSetOption("Mesh", "ElementOrder" , (_secondOrder)?2.:1.) ;
311 ok = GmshSetOption("Mesh", "SecondOrderIncomplete" ,(_useIncomplElem)?1.:0.);
315 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
316 /*ok = GmshSetOption("Mesh", "MaxNumThreads1D" , 0. ) ; // Coarse-grain algo threads
318 ok = GmshSetOption("Mesh", "MaxNumThreads2D" , 0. ) ; // Coarse-grain algo threads
320 ok = GmshSetOption("Mesh", "MaxNumThreads3D" , 0. ) ; // Fine-grain algo threads HXT
323 ok = GmshSetOption("General", "NumThreads" , _maxThreads ) ; // system default i.e. OMP_NUM_THREADS
328 //================================================================================
330 * \brief Create and add Compounds into GModel _gModel.
332 //================================================================================
334 void GMSHPlugin_Mesher::CreateGmshCompounds()
336 MESSAGE("GMSHPlugin_Mesher::CreateGmshCompounds");
338 SMESH_Gen_i* smeshGen_i = SMESH_Gen_i::GetSMESHGen();
340 OCC_Internals* occgeo = _gModel->getOCCInternals();
341 bool toSynchronize = false;
343 for(std::set<std::string>::const_iterator its = _compounds.begin();its != _compounds.end(); ++its )
345 GEOM::GEOM_Object_var aGeomObj;
346 TopoDS_Shape geomShape = TopoDS_Shape();
347 SALOMEDS::SObject_var aSObj = SMESH_Gen_i::GetSMESHGen()->getStudyServant()->FindObjectID( (*its).c_str() );
348 SALOMEDS::GenericAttribute_var anAttr;
349 if (!aSObj->_is_nil() && aSObj->FindAttribute(anAttr, "AttributeIOR"))
351 SALOMEDS::AttributeIOR_var anIOR = SALOMEDS::AttributeIOR::_narrow(anAttr);
352 CORBA::String_var aVal = anIOR->Value();
353 CORBA::Object_var obj = SMESH_Gen_i::GetSMESHGen()->getStudyServant()->ConvertIORToObject(aVal);
354 aGeomObj = GEOM::GEOM_Object::_narrow(obj);
356 geomShape = smeshGen_i->GeomObjectToShape( aGeomObj.in() );
357 if ( geomShape.IsNull() )
360 TopAbs_ShapeEnum geomType = geomShape.ShapeType();
361 if ( geomType == TopAbs_COMPOUND)// voir s'il ne faut pas mettre une erreur dans le cas contraire
363 MESSAGE("shapeType == TopAbs_COMPOUND");
364 TopoDS_Iterator it(geomShape);
367 TopAbs_ShapeEnum shapeType = it.Value().ShapeType();
368 std::vector< std::pair< int, int > > dimTags;
369 for ( ; it.More(); it.Next())
371 const TopoDS_Shape& topoShape = it.Value();
372 ASSERT(topoShape.ShapeType() == shapeType);
373 if ( _mesh->GetMeshDS()->ShapeToIndex( topoShape ) > 0 )
374 occgeo->importShapes( &topoShape, false, dimTags );
377 TopoDS_Shape face = TopExp_Explorer( _shape, shapeType ).Current();
378 SMESH_subMesh* sm = _mesh->GetSubMesh( face );
379 sm->GetComputeError() =
380 SMESH_ComputeError::New
381 ( COMPERR_WARNING, "Compound shape does not belong to the main geometry. Ignored");
384 std::vector<int> tags;
385 int dim = ( shapeType == TopAbs_EDGE ) ? 1 : 2;
386 for ( size_t i = 0; i < dimTags.size(); ++i )
388 if ( dimTags[i].first == dim )
389 tags.push_back( dimTags[i].second );
393 _gModel->getGEOInternals()->setCompoundMesh( dim, tags );
394 toSynchronize = true;
397 _gModel->getGEOInternals()->synchronize(_gModel);
402 //================================================================================
404 * \brief For a compound mesh set the mesh components to be transmitted to SMESH
406 //================================================================================
408 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
409 void GMSHPlugin_Mesher::SetCompoundMeshVisibility()
412 // Loop over all faces, if the face belongs to a compound entry then
413 // for all (boundary) edges whithin the face visibility is set to 0,
414 // if the face doesn't belong to a compound entry then visibility is
415 // set to 1 for all its (boundary) edges. Later, in FillSMesh() func
416 // getVisibility() (returns either 1 or 0) is used to decide weather
417 // the mesh of edge should be transmitted to SMESH or not.
419 for ( GModel::fiter itF = _gModel->firstFace(); itF != _gModel->lastFace(); ++itF )
421 std::vector< GEdge *> faceEdges = (*itF)->edges();
423 for ( auto itE = faceEdges.begin(); itE != faceEdges.end(); ++itE )
425 if ( ((*itF)->compound.size()) )
426 (*itE)->setVisibility(0);
428 (*itE)->setVisibility(1);
433 // Loop over all edges, if the edge belongs to a compound entry then
434 // for all (boundary) vertices whithin the edge visibility is set to
435 // 0, if the edge doesn't belong to a compound entry then visibility
436 // is set to 1 for all its (boundary) vertices. Later, in FillSMesh()
437 // func getVisibility() (returns either 1 or 0) is used to decide we-
438 // ather the mesh of vertices should be transmitted to SMESH or not.
440 for ( GModel::eiter itE = _gModel->firstEdge(); itE != _gModel->lastEdge(); ++itE )
442 std::vector<GVertex *> bndVerticies = (*itE)->vertices();
444 for( auto itV = bndVerticies.begin(); itV != bndVerticies.end(); ++itV )
446 if(((*itE)->compound.size()))
447 (*itV)->setVisibility(0);
449 (*itV)->setVisibility(1);
456 //================================================================================
458 * \brief Write mesh from GModel instance to SMESH instance
460 //================================================================================
462 void GMSHPlugin_Mesher::FillSMesh()
464 SMESHDS_Mesh* meshDS = _mesh->GetMeshDS();
467 for ( GModel::viter it = _gModel->firstVertex(); it != _gModel->lastVertex(); ++it)
469 GVertex *gVertex = *it;
471 // GET topoVertex CORRESPONDING TO gVertex
472 TopoDS_Vertex topoVertex = *((TopoDS_Vertex*)gVertex->getNativePtr());
474 if (gVertex->getVisibility() == 0) // belongs to a compound
476 SMESH_subMesh* sm = _mesh->GetSubMesh(topoVertex);
477 sm->SetIsAlwaysComputed(true); // prevent from displaying errors
481 // FILL SMESH FOR topoVertex
483 for(unsigned int i = 0; i < gVertex->mesh_vertices.size(); i++)
485 MVertex *v = gVertex->mesh_vertices[i];
486 if(v->getIndex() >= 0)
488 SMDS_MeshNode *node = meshDS->AddNodeWithID(v->x(),v->y(),v->z(),v->getNum());
489 meshDS->SetNodeOnVertex( node, topoVertex );
492 // WE DON'T ADD 0D ELEMENTS because it does not follow the salome meshers philosophy
494 // for(unsigned int i = 0; i < gVertex->getNumMeshElements(); i++)
496 // MElement *e = gVertex->getMeshElement(i);
497 // std::vector<MVertex*> verts;
498 // e->getVertices(verts);
499 // ASSERT(verts.size()==1);
500 // SMDS_Mesh0DElement* zeroDElement = 0;
501 // zeroDElement = meshDS->Add0DElementWithID(verts[0]->getNum(),e->getNum());
502 // meshDS->SetMeshElementOnShape(zeroDElement, topoVertex);
507 for(GModel::eiter it = _gModel->firstEdge(); it != _gModel->lastEdge(); ++it)
511 // GET topoEdge CORRESPONDING TO gEdge
512 TopoDS_Edge topoEdge;
513 std::vector< ShapeBounds > topoEdges;
514 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
515 if(gEdge->haveParametrization())
517 if ( gEdge->geomType() != GEntity::CompoundCurve )
520 topoEdge = *((TopoDS_Edge*)gEdge->getNativePtr());
521 if (gEdge->getVisibility() == 0) // belongs to a compound
523 SMESH_subMesh* sm = _mesh->GetSubMesh(topoEdge);
524 sm->SetIsAlwaysComputed(true); // prevent from displaying errors
528 bool isCompound = getBoundsOfShapes( gEdge, topoEdges );
530 // FILL SMESH FOR topoEdge
532 for ( size_t i = 0; i < gEdge->mesh_vertices.size(); i++ )
534 MVertex *v = gEdge->mesh_vertices[i];
535 if ( v->getIndex() >= 0 )
537 SMDS_MeshNode *node = meshDS->AddNodeWithID(v->x(),v->y(),v->z(),v->getNum());
540 topoEdge = TopoDS::Edge( getShapeAtPoint( v->point(), topoEdges ));
542 meshDS->SetNodeOnEdge( node, topoEdge );
547 for ( GModel::eiter it = _gModel->firstEdge(); it != _gModel->lastEdge(); ++it )
550 if ( gEdge->getVisibility() == 0) // belongs to a compound
553 TopoDS_Edge topoEdge;
554 std::vector< ShapeBounds > topoEdges;
555 bool isCompound = getBoundsOfShapes( gEdge, topoEdges );
557 topoEdge = *((TopoDS_Edge*)gEdge->getNativePtr());
560 std::vector<MVertex*> verts(3);
561 for ( size_t i = 0; i < gEdge->getNumMeshElements(); i++ )
563 MElement *e = gEdge->getMeshElement(i);
565 e->getVertices(verts);
567 // if a node wasn't set, it is assigned here
568 for ( size_t j = 0; j < verts.size(); j++ )
570 if ( verts[j]->onWhat()->getVisibility() == 0 )
572 SMDS_MeshNode *node = meshDS->AddNodeWithID(verts[i]->x(),verts[j]->y(),verts[j]->z(),verts[j]->getNum());
573 meshDS->SetNodeOnEdge( node, topoEdge );
574 verts[j]->setEntity(gEdge);
578 SMDS_MeshEdge* edge = 0;
579 switch (verts.size())
582 edge = meshDS->AddEdgeWithID(verts[0]->getNum(),
583 verts[1]->getNum(),e->getNum());
586 edge = meshDS->AddEdgeWithID(verts[0]->getNum(),
588 verts[2]->getNum(),e->getNum());
595 topoEdge = TopoDS::Edge( getShapeAtPoint( e->barycenter(), topoEdges ));
597 meshDS->SetMeshElementOnShape( edge, topoEdge );
602 for ( GModel::fiter it = _gModel->firstFace(); it != _gModel->lastFace(); ++it)
606 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
607 // Gmsh since version 4.3 is now producing extra surface and mesh when
608 // compounds are involved. Since in Gmsh meshing procedure needs acess
609 // to each of the original topology and the meshed topology. Hence we
610 // bypass the additional mesh in case of compounds. Note, similar cri-
611 // teria also occus in the following 'for' loop.
612 if ( _compounds.size() && gFace->geomType() == GEntity::DiscreteSurface )
616 // GET topoFace CORRESPONDING TO gFace
617 TopoDS_Face topoFace;
618 std::vector< ShapeBounds > topoFaces;
620 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
621 if(gFace->haveParametrization())
623 if ( gFace->geomType() != GEntity::CompoundSurface )
626 topoFace = *((TopoDS_Face*)gFace->getNativePtr());
627 if (gFace->getVisibility() == 0) // belongs to a compound
629 SMESH_subMesh* sm = _mesh->GetSubMesh(topoFace);
630 sm->SetIsAlwaysComputed(true); // prevent from displaying errors
634 bool isCompound = getBoundsOfShapes( gFace, topoFaces );
636 // FILL SMESH FOR topoFace
638 for ( size_t i = 0; i < gFace->mesh_vertices.size(); i++ )
640 MVertex *v = gFace->mesh_vertices[i];
641 if ( v->getIndex() >= 0 )
643 SMDS_MeshNode *node = meshDS->AddNodeWithID(v->x(),v->y(),v->z(),v->getNum());
646 topoFace = TopoDS::Face( getShapeAtPoint( v->point(), topoFaces ));
648 meshDS->SetNodeOnFace( node, topoFace );
653 for ( GModel::fiter it = _gModel->firstFace(); it != _gModel->lastFace(); ++it)
657 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
658 if ( _compounds.size() && gFace->geomType() == GEntity::DiscreteSurface )
661 bool isCompound = (!gFace->haveParametrization());
663 bool isCompound = ( gFace->geomType() == GEntity::CompoundSurface );
666 if ( !isCompound && gFace->getVisibility() == 0 )
667 continue; // belongs to a compound
669 TopoDS_Face topoFace;
670 std::vector< ShapeBounds > topoFaces;
672 getBoundsOfShapes( gFace, topoFaces );
674 topoFace = *((TopoDS_Face*)gFace->getNativePtr());
677 std::vector<MVertex*> verts;
678 for ( size_t i = 0; i < gFace->getNumMeshElements(); i++ )
680 MElement *e = gFace->getMeshElement(i);
682 e->getVertices(verts);
683 SMDS_MeshFace* face = 0;
685 // if a node wasn't set, it is assigned here
686 for ( size_t j = 0; j < verts.size(); j++)
688 if(verts[j]->onWhat()->getVisibility() == 0)
690 SMDS_MeshNode *node = meshDS->AddNodeWithID(verts[j]->x(),verts[j]->y(),verts[j]->z(),verts[j]->getNum());
691 meshDS->SetNodeOnFace( node, topoFace );
692 verts[i]->setEntity(gFace);
695 switch (verts.size())
698 face = meshDS->AddFaceWithID(verts[0]->getNum(),
700 verts[2]->getNum(),e->getNum());
703 face = meshDS->AddFaceWithID(verts[0]->getNum(),
706 verts[3]->getNum(),e->getNum());
709 face = meshDS->AddFaceWithID(verts[0]->getNum(),
714 verts[5]->getNum(),e->getNum());
717 face = meshDS->AddFaceWithID(verts[0]->getNum(),
724 verts[7]->getNum(),e->getNum());
727 face = meshDS->AddFaceWithID(verts[0]->getNum(),
735 verts[8]->getNum(),e->getNum());
743 topoFace = TopoDS::Face( getShapeAtPoint( e->barycenter(), topoFaces ));
745 meshDS->SetMeshElementOnShape(face, topoFace);
750 for ( GModel::riter it = _gModel->firstRegion(); it != _gModel->lastRegion(); ++it)
752 GRegion *gRegion = *it;
753 if (gRegion->getVisibility() == 0)
756 // GET topoSolid CORRESPONDING TO gRegion
757 TopoDS_Solid topoSolid = *((TopoDS_Solid*)gRegion->getNativePtr());
759 // FILL SMESH FOR topoSolid
762 for(unsigned int i = 0; i < gRegion->mesh_vertices.size(); i++)
764 MVertex *v = gRegion->mesh_vertices[i];
765 if(v->getIndex() >= 0)
767 SMDS_MeshNode *node = meshDS->AddNodeWithID(v->x(),v->y(),v->z(),v->getNum());
768 meshDS->SetNodeInVolume( node, topoSolid );
773 std::vector<MVertex*> verts;
774 for(unsigned int i = 0; i < gRegion->getNumMeshElements(); i++)
776 MElement *e = gRegion->getMeshElement(i);
778 e->getVertices(verts);
779 SMDS_MeshVolume* volume = 0;
780 switch (verts.size()){
782 volume = meshDS->AddVolumeWithID(verts[0]->getNum(),
785 verts[3]->getNum(),e->getNum());
788 volume = meshDS->AddVolumeWithID(verts[0]->getNum(),
792 verts[4]->getNum(),e->getNum());
795 volume = meshDS->AddVolumeWithID(verts[0]->getNum(),
800 verts[4]->getNum(),e->getNum());
803 volume = meshDS->AddVolumeWithID(verts[0]->getNum(),
810 verts[5]->getNum(),e->getNum());
813 volume = meshDS->AddVolumeWithID(verts[0]->getNum(),
822 verts[9]->getNum(),e->getNum());
825 volume = meshDS->AddVolumeWithID(verts[0]->getNum(),
837 verts[9]->getNum(),e->getNum());
839 case 14: // same as case 13, because no pyra14 in smesh
840 volume = meshDS->AddVolumeWithID(verts[0]->getNum(),
852 verts[9]->getNum(),e->getNum());
855 volume = meshDS->AddVolumeWithID(verts[0]->getNum(),
869 verts[10]->getNum(),e->getNum());
871 case 18: // same as case 15, because no penta18 in smesh
872 volume = meshDS->AddVolumeWithID(verts[0]->getNum(),
886 verts[10]->getNum(),e->getNum());
889 volume = meshDS->AddVolumeWithID(verts[0]->getNum(),
908 verts[12]->getNum(),e->getNum());
911 volume = meshDS->AddVolumeWithID(verts[0]->getNum(),
944 meshDS->SetMeshElementOnShape(volume, topoSolid);
951 //================================================================================
953 * \brief Find if SPoint point is in SBoundingBox3d bounds
955 //================================================================================
957 float GMSHPlugin_Mesher::DistBoundingBox(const SBoundingBox3d& bounds, const SPoint3& point)
959 SPoint3 min = bounds.min();
960 SPoint3 max = bounds.max();
964 if (point.x() < min.x())
965 x = min.x()-point.x();
966 else if (point.x() > max.x())
967 x = point.x()-max.x();
971 if (point.y() < min.y())
972 y = min.y()-point.y();
973 else if (point.y() > max.y())
974 y = point.y()-max.y();
978 if (point.z() < min.z())
979 z = min.z()-point.z();
980 else if (point.z() > max.z())
981 z = point.z()-max.z();
987 //================================================================================
989 * \brief Reimplemented GmshMessage call. Actions done if errors occurs
990 * during gmsh meshing. We define here what to display and what to do.
992 //================================================================================
993 void GMSHPlugin_Mesher::mymsg::operator()(std::string level, std::string msg)
995 //MESSAGE("level="<< level.c_str() << ", msg=" << msg.c_str()<< "\n");
996 printf("level=%s msg=%s\n", level.c_str(), msg.c_str());
998 if(level == "Fatal" || level == "Error")
1000 std::ostringstream oss;
1001 if (level == "Fatal")
1002 oss << "Fatal error during Generation of Gmsh Mesh\n";
1004 oss << "Error during Generation of Gmsh Mesh\n";
1005 oss << " " << msg.c_str() << "\n";
1006 GEntity *e = _gModel->getCurrentMeshEntity();
1009 oss << " error occurred while meshing entity:\n" <<
1010 " tag=" << e->tag() << "\n" <<
1011 " dimension=" << e->dim() << "\n" <<
1012 " native pointer=" << e->getNativePtr();
1013 //if(e->geomType() != GEntity::CompoundCurve and e->geomType() != GEntity::CompoundSurface)
1015 //SMESH_subMesh *sm = _mesh->GetSubMesh(*((TopoDS_Shape*)e->getNativePtr()));
1016 //SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
1017 //SMESH_Comment comment;
1018 //comment << SMESH_Comment(oss.str);
1019 //std::string str = oss.str();
1020 //smError.reset( new SMESH_ComputeError( str ));
1022 // plutot que de faire de la merde ici, on pourait simplement
1023 // remplir une liste pour dire sur quelles entités gmsh se plante
1024 // (puis faire le fillsmesh)
1025 // puis faire une nouvelle routine qui réécrit les messages d'erreur
1026 // probleme : gmsh peut planté en Fatal, dans ce cas pas de fillsmesh
1029 if (level == "Fatal")
1031 CTX::instance()->lock = 0;
1035 printf("%s\n", oss.str().c_str());
1039 //=============================================================================
1041 * Here we are going to use the GMSH mesher
1043 //=============================================================================
1045 bool GMSHPlugin_Mesher::Compute()
1047 MESSAGE("GMSHPlugin_Mesher::Compute");
1051 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
1052 SetMaxThreadsGmsh();
1056 _gModel = new GModel();
1058 GmshSetMessageHandler(&msg);
1059 _gModel->importOCCShape((void*)&_shape);
1060 if (_compounds.size() > 0) CreateGmshCompounds();
1061 MESSAGE("GModel::Mesh");
1064 _gModel->mesh((_is2d)?2:3);
1065 #ifdef WITH_SMESH_CANCEL_COMPUTE
1069 catch (std::string& str)
1077 MESSAGE("Unrecoverable error during Generation of Gmsh Mesh");
1082 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
1083 if (_compounds.size() > 0)
1084 SetCompoundMeshVisibility();
1088 GmshSetMessageHandler(nullptr);
1091 MESSAGE("GMSHPlugin_Mesher::Compute:End");