1 // Copyright (C) 2012-2015 ALNEOS
2 // Copyright (C) 2016-2022 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_MeshElement.hxx>
25 #include <SMDS_MeshNode.hxx>
26 #include <SMESHDS_Mesh.hxx>
27 #include <SMESH_Comment.hxx>
28 #include <SMESH_ComputeError.hxx>
29 #include <SMESH_Gen_i.hxx>
30 #include <SMESH_Mesh.hxx>
31 #include <SMESH_MesherHelper.hxx>
32 #include <SMESH_subMesh.hxx>
33 #include <StdMeshers_FaceSide.hxx>
34 #include <utilities.h>
39 #include <TopExp_Explorer.hxx>
43 #include <MTriangle.h>
44 #include <MQuadrangle.h>
45 #if GMSH_MAJOR_VERSION >=4
46 #include <GmshGlobal.h>
47 #include <gmsh/Context.h>
50 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
60 SBoundingBox3d _bounds;
64 //================================================================================
66 * \brief Retrieve ShapeBounds from a compound GEdge
68 //================================================================================
70 bool getBoundsOfShapes( GEdge* gEdge,
71 std::vector< ShapeBounds > & topoEdges )
74 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
75 for ( size_t i = 0; i < gEdge->compound.size(); ++i )
77 GEdge* gE = static_cast< GEdge* >( gEdge->compound[ i ]);
78 topoEdges.push_back( ShapeBounds{ gE->bounds(), *((TopoDS_Edge*)gE->getNativePtr()) });
81 for ( size_t i = 0; i < gEdge->_compound.size(); ++i )
83 GEdge* gE = static_cast< GEdge* >( gEdge->_compound[ i ]);
84 topoEdges.push_back( ShapeBounds{ gE->bounds(), *((TopoDS_Edge*)gE->getNativePtr()) });
87 return topoEdges.size();
90 //================================================================================
92 * \brief Retrieve ShapeBounds from a compound GFace
94 //================================================================================
96 bool getBoundsOfShapes( GFace* gFace,
97 std::vector< ShapeBounds > & topoFaces )
100 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
101 for ( size_t i = 0; i < gFace->compound.size(); ++i )
103 GFace* gF = static_cast< GFace* >( gFace->compound[ i ]);
104 topoFaces.push_back( ShapeBounds{ gF->bounds(), *((TopoDS_Face*)gF->getNativePtr()) });
107 for ( size_t i = 0; i < gFace->_compound.size(); ++i )
109 GFace* gF = static_cast< GFace* >( gFace->_compound[ i ]);
110 topoFaces.push_back( ShapeBounds{ gF->bounds(), *((TopoDS_Face*)gF->getNativePtr()) });
113 return topoFaces.size();
115 //================================================================================
117 * \brief Find a shape whose bounding box includes a given point
119 //================================================================================
121 TopoDS_Shape getShapeAtPoint( const SPoint3& point, const std::vector< ShapeBounds > & shapes )
124 float distmin = std::numeric_limits<float>::max();
125 for ( size_t i = 0; i < shapes.size(); ++i )
127 float dist = GMSHPlugin_Mesher::DistBoundingBox( shapes[i]._bounds, point );
130 shape = shapes[i]._shape;
139 double segmentSize( const UVPtStructVec& nodeParam, size_t i )
141 double l1 = SMESH_NodeXYZ( nodeParam[i].node ).Distance( nodeParam[i-1].node );
142 double l2 = SMESH_NodeXYZ( nodeParam[i].node ).Distance( nodeParam[i+1].node );
143 return 0.5 * ( l1 + l2 );
147 //=============================================================================
151 //=============================================================================
153 GMSHPlugin_Mesher::GMSHPlugin_Mesher (SMESH_Mesh* mesh,
154 const TopoDS_Shape& aShape,
160 // il faudra peut être mettre un truc par defaut si l'utilisateur ne rentre rien en para
161 //defaultParameters();
164 //void GMSHPlugin_Mesher::defaultParameters(){}
166 void GMSHPlugin_Mesher::SetParameters(const GMSHPlugin_Hypothesis* hyp)
170 _algo2d = hyp->Get2DAlgo();
171 _algo3d = hyp->Get3DAlgo();
172 _recomb2DAlgo = hyp->GetRecomb2DAlgo();
173 _recombineAll = hyp->GetRecombineAll();
174 _subdivAlgo = hyp->GetSubdivAlgo();
175 _remeshAlgo = hyp->GetRemeshAlgo();
176 _remeshPara = hyp->GetRemeshPara();
177 _smouthSteps = hyp->GetSmouthSteps();
178 _sizeFactor = hyp->GetSizeFactor();
179 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=10
180 _meshCurvatureSize = hyp->GetMeshCurvatureSize();
182 _minSize = hyp->GetMinSize();
183 _maxSize = hyp->GetMaxSize();
184 _secondOrder = hyp->GetSecondOrder();
185 _useIncomplElem = hyp->GetUseIncomplElem();
186 _compounds = hyp->GetCompoundOnEntries();
193 _recombineAll = false;
199 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=10
200 _meshCurvatureSize = 0;
204 _secondOrder = false;
205 _useIncomplElem = true;
211 //================================================================================
213 * \brief Set maximum number of threads to be used by Gmsh
215 //================================================================================
217 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
218 void GMSHPlugin_Mesher::SetMaxThreadsGmsh()
220 MESSAGE("GMSHPlugin_Mesher::SetMaxThreadsGmsh");
221 // compound meshing (_compounds.size() > 0) and quad meshing (_algo2d >= 5) will
222 // not be multi-threaded
223 if (_compounds.size() > 0 || _algo2d >= 5){
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
264 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=10
265 mapAlgo2d[6]=11;// Quasistructured quads with cross-fields
268 std::map <int,double> mapAlgo3d;
269 mapAlgo3d[0]=1; // Delaunay
270 mapAlgo3d[1]=4; // Frontal
271 mapAlgo3d[2]=7; // MMG3D
272 mapAlgo3d[3]=9; // R-tree
273 mapAlgo3d[4]=10;// HXT
276 ok = GmshSetOption("Mesh", "Algorithm" , mapAlgo2d[_algo2d]) ;
280 ok = GmshSetOption("Mesh", "Algorithm3D" , mapAlgo3d[_algo3d]) ;
283 ok = GmshSetOption("Mesh", "RecombinationAlgorithm" , (double)_recomb2DAlgo) ;
285 ok = GmshSetOption("Mesh", "RecombineAll" , (_recombineAll)?1.:0.) ;
287 ok = GmshSetOption("Mesh", "SubdivisionAlgorithm" , (double)_subdivAlgo) ;
289 ok = GmshSetOption("Mesh", "RemeshAlgorithm" , (double)_remeshAlgo) ;
291 ok = GmshSetOption("Mesh", "RemeshParametrization" , (double)_remeshPara) ;
293 ok = GmshSetOption("Mesh", "Smoothing" , (double)_smouthSteps) ;
295 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=10
296 ok = GmshSetOption("Mesh", "MeshSizeFromCurvature" , _meshCurvatureSize) ;
299 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
300 ok = GmshSetOption("Mesh", "MeshSizeFactor" , _sizeFactor) ;
302 ok = GmshSetOption("Mesh", "MeshSizeMin" , _minSize) ;
304 ok = GmshSetOption("Mesh", "MeshSizeMax" , _maxSize) ;
307 ok = GmshSetOption("Mesh", "CharacteristicLengthFactor" , _sizeFactor) ;
309 ok = GmshSetOption("Mesh", "CharacteristicLengthMin" , _minSize) ;
311 ok = GmshSetOption("Mesh", "CharacteristicLengthMax" , _maxSize) ;
314 ok = GmshSetOption("Mesh", "ElementOrder" , (_secondOrder)?2.:1.) ;
318 ok = GmshSetOption("Mesh", "SecondOrderIncomplete" ,(_useIncomplElem)?1.:0.);
322 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
323 /*ok = GmshSetOption("Mesh", "MaxNumThreads1D" , 0. ) ; // Coarse-grain algo threads
325 ok = GmshSetOption("Mesh", "MaxNumThreads2D" , 0. ) ; // Coarse-grain algo threads
327 ok = GmshSetOption("Mesh", "MaxNumThreads3D" , 0. ) ; // Fine-grain algo threads HXT
330 ok = GmshSetOption("General", "NumThreads" , _maxThreads ) ; // system default i.e. OMP_NUM_THREADS
335 //================================================================================
337 * \brief Create and add Compounds into GModel _gModel.
339 //================================================================================
341 void GMSHPlugin_Mesher::CreateGmshCompounds()
343 MESSAGE("GMSHPlugin_Mesher::CreateGmshCompounds");
345 SMESH_Gen_i* smeshGen_i = SMESH_Gen_i::GetSMESHGen();
347 OCC_Internals* occgeo = _gModel->getOCCInternals();
348 bool toSynchronize = false;
350 for(std::set<std::string>::const_iterator its = _compounds.begin();its != _compounds.end(); ++its )
352 GEOM::GEOM_Object_var aGeomObj;
353 TopoDS_Shape geomShape = TopoDS_Shape();
354 SALOMEDS::SObject_var aSObj = SMESH_Gen_i::GetSMESHGen()->getStudyServant()->FindObjectID( (*its).c_str() );
355 SALOMEDS::GenericAttribute_var anAttr;
356 if (!aSObj->_is_nil() && aSObj->FindAttribute(anAttr, "AttributeIOR"))
358 SALOMEDS::AttributeIOR_var anIOR = SALOMEDS::AttributeIOR::_narrow(anAttr);
359 CORBA::String_var aVal = anIOR->Value();
360 CORBA::Object_var obj = SMESH_Gen_i::GetSMESHGen()->getStudyServant()->ConvertIORToObject(aVal);
361 aGeomObj = GEOM::GEOM_Object::_narrow(obj);
363 geomShape = smeshGen_i->GeomObjectToShape( aGeomObj.in() );
364 if ( geomShape.IsNull() )
367 TopAbs_ShapeEnum geomType = geomShape.ShapeType();
368 if ( geomType == TopAbs_COMPOUND)// voir s'il ne faut pas mettre une erreur dans le cas contraire
370 MESSAGE("shapeType == TopAbs_COMPOUND");
371 TopoDS_Iterator it(geomShape);
374 TopAbs_ShapeEnum shapeType = it.Value().ShapeType();
375 std::vector< std::pair< int, int > > dimTags;
376 for ( ; it.More(); it.Next())
378 const TopoDS_Shape& topoShape = it.Value();
379 ASSERT(topoShape.ShapeType() == shapeType);
380 if ( _mesh->GetMeshDS()->ShapeToIndex( topoShape ) > 0 )
381 occgeo->importShapes( &topoShape, false, dimTags );
384 TopoDS_Shape face = TopExp_Explorer( _shape, shapeType ).Current();
385 SMESH_subMesh* sm = _mesh->GetSubMesh( face );
386 sm->GetComputeError() =
387 SMESH_ComputeError::New
388 ( COMPERR_WARNING, "Compound shape does not belong to the main geometry. Ignored");
391 std::vector<int> tags;
392 int dim = ( shapeType == TopAbs_EDGE ) ? 1 : 2;
393 for ( size_t i = 0; i < dimTags.size(); ++i )
395 if ( dimTags[i].first == dim )
396 tags.push_back( dimTags[i].second );
400 _gModel->getGEOInternals()->setCompoundMesh( dim, tags );
401 toSynchronize = true;
404 _gModel->getGEOInternals()->synchronize(_gModel);
409 //================================================================================
411 * \brief For a compound mesh set the mesh components to be transmitted to SMESH
413 //================================================================================
415 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
416 void GMSHPlugin_Mesher::SetCompoundMeshVisibility()
419 // Loop over all faces, if the face belongs to a compound entry then
420 // for all (boundary) edges whithin the face visibility is set to 0,
421 // if the face doesn't belong to a compound entry then visibility is
422 // set to 1 for all its (boundary) edges. Later, in FillSMesh() func
423 // getVisibility() (returns either 1 or 0) is used to decide weather
424 // the mesh of edge should be transmitted to SMESH or not.
426 for ( GModel::fiter itF = _gModel->firstFace(); itF != _gModel->lastFace(); ++itF )
428 std::vector< GEdge *> faceEdges = (*itF)->edges();
430 for ( auto itE = faceEdges.begin(); itE != faceEdges.end(); ++itE )
432 if ( ((*itF)->compound.size()) )
433 (*itE)->setVisibility(0);
435 (*itE)->setVisibility(1);
440 // Loop over all edges, if the edge belongs to a compound entry then
441 // for all (boundary) vertices whithin the edge visibility is set to
442 // 0, if the edge doesn't belong to a compound entry then visibility
443 // is set to 1 for all its (boundary) vertices. Later, in FillSMesh()
444 // func getVisibility() (returns either 1 or 0) is used to decide we-
445 // ather the mesh of vertices should be transmitted to SMESH or not.
447 for ( GModel::eiter itE = _gModel->firstEdge(); itE != _gModel->lastEdge(); ++itE )
449 std::vector<GVertex *> bndVerticies = (*itE)->vertices();
451 for( auto itV = bndVerticies.begin(); itV != bndVerticies.end(); ++itV )
453 if(((*itE)->compound.size()))
454 (*itV)->setVisibility(0);
456 (*itV)->setVisibility(1);
463 //================================================================================
465 * \brief Get a node ID by a GMSH mesh veretx
467 //================================================================================
469 smIdType GMSHPlugin_Mesher::NodeID( const MVertex* v, bool checkMap )
473 std::map< const MVertex *, const SMDS_MeshNode* >::iterator v2n = _nodeMap.find( v );
474 if ( v2n != _nodeMap.end() )
475 return v2n->second->GetID();
477 return _nodeNumShift + v->getNum();
480 //================================================================================
482 * \brief Get a node by a GMSH mesh veretx
484 //================================================================================
486 const SMDS_MeshNode* GMSHPlugin_Mesher::Node( const MVertex* v, bool checkMap )
490 std::map< const MVertex *, const SMDS_MeshNode* >::iterator v2n = _nodeMap.find( v );
491 if ( v2n != _nodeMap.end() )
494 return _mesh->GetMeshDS()->FindNode( _nodeNumShift + v->getNum() );
497 //================================================================================
499 * \brief Return a corresponding sub-mesh if a shape is meshed
501 //================================================================================
503 SMESHDS_SubMesh* GMSHPlugin_Mesher::HasSubMesh( const TopoDS_Shape& s )
505 if ( SMESHDS_SubMesh* sm = _mesh->GetMeshDS()->MeshElements( s ))
507 if ( s.ShapeType() == TopAbs_VERTEX )
508 return ( sm->NbNodes() > 0 ) ? sm : nullptr;
510 return ( sm->NbElements() > 0 ) ? sm : nullptr;
515 //================================================================================
517 * \brief Write mesh from GModel instance to SMESH instance
519 //================================================================================
521 void GMSHPlugin_Mesher::FillSMesh()
523 SMESHDS_Mesh* meshDS = _mesh->GetMeshDS();
526 for ( GModel::viter it = _gModel->firstVertex(); it != _gModel->lastVertex(); ++it)
528 GVertex *gVertex = *it;
530 // GET topoVertex CORRESPONDING TO gVertex
531 TopoDS_Vertex topoVertex = *((TopoDS_Vertex*)gVertex->getNativePtr());
533 if (gVertex->getVisibility() == 0) // belongs to a compound
535 SMESH_subMesh* sm = _mesh->GetSubMesh(topoVertex);
536 sm->SetIsAlwaysComputed(true); // prevent from displaying errors
539 if ( HasSubMesh( topoVertex ))
540 continue; // a meshed sub-mesh
542 // FILL SMESH FOR topoVertex
544 for( size_t i = 0; i < gVertex->mesh_vertices.size(); i++)
546 MVertex *v = gVertex->mesh_vertices[i];
547 if(v->getIndex() >= 0)
549 SMDS_MeshNode *node = meshDS->AddNodeWithID(v->x(),v->y(),v->z(), NodeID(v));
550 meshDS->SetNodeOnVertex( node, topoVertex );
553 // WE DON'T ADD 0D ELEMENTS because it does not follow the salome meshers philosophy
555 // for(unsigned int i = 0; i < gVertex->getNumMeshElements(); i++)
557 // MElement *e = gVertex->getMeshElement(i);
558 // std::vector<MVertex*> verts;
559 // e->getVertices(verts);
560 // ASSERT(verts.size()==1);
561 // SMDS_Mesh0DElement* zeroDElement = 0;
562 // zeroDElement = meshDS->Add0DElementWithID(verts[0]->getNum(),e->getNum());
563 // meshDS->SetMeshElementOnShape(zeroDElement, topoVertex);
568 for(GModel::eiter it = _gModel->firstEdge(); it != _gModel->lastEdge(); ++it)
572 // GET topoEdge CORRESPONDING TO gEdge
573 TopoDS_Edge topoEdge;
574 std::vector< ShapeBounds > topoEdges;
575 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
576 if(gEdge->haveParametrization())
578 if ( gEdge->geomType() != GEntity::CompoundCurve )
581 topoEdge = *((TopoDS_Edge*)gEdge->getNativePtr());
582 if (gEdge->getVisibility() == 0) // belongs to a compound
584 SMESH_subMesh* sm = _mesh->GetSubMesh(topoEdge);
585 sm->SetIsAlwaysComputed(true); // prevent from displaying errors
588 if ( HasSubMesh( topoEdge ))
589 continue; // a meshed sub-mesh
591 bool isCompound = getBoundsOfShapes( gEdge, topoEdges );
593 // FILL SMESH FOR topoEdge
595 for ( size_t i = 0; i < gEdge->mesh_vertices.size(); i++ )
597 MVertex *v = gEdge->mesh_vertices[i];
598 if ( v->getIndex() >= 0 )
600 SMDS_MeshNode *node = meshDS->AddNodeWithID(v->x(),v->y(),v->z(),NodeID(v));
603 topoEdge = TopoDS::Edge( getShapeAtPoint( v->point(), topoEdges ));
605 meshDS->SetNodeOnEdge( node, topoEdge );
610 for ( GModel::eiter it = _gModel->firstEdge(); it != _gModel->lastEdge(); ++it )
613 if ( gEdge->getVisibility() == 0) // belongs to a compound
616 TopoDS_Edge topoEdge;
617 std::vector< ShapeBounds > topoEdges;
618 bool isCompound = getBoundsOfShapes( gEdge, topoEdges );
620 topoEdge = *((TopoDS_Edge*)gEdge->getNativePtr());
622 if ( HasSubMesh( topoEdge ))
623 continue; // a meshed sub-mesh
626 std::vector<MVertex*> verts(3);
627 for ( size_t i = 0; i < gEdge->getNumMeshElements(); i++ )
629 MElement *e = gEdge->getMeshElement(i);
631 e->getVertices(verts);
633 // if a node wasn't set, it is assigned here
634 for ( size_t j = 0; j < verts.size(); j++ )
636 if ( verts[j]->onWhat()->getVisibility() == 0 )
638 SMDS_MeshNode *node = meshDS->AddNodeWithID(verts[j]->x(),verts[j]->y(),verts[j]->z(),
640 meshDS->SetNodeOnEdge( node, topoEdge );
641 verts[j]->setEntity(gEdge);
645 SMDS_MeshEdge* edge = 0;
646 switch (verts.size())
649 edge = meshDS->AddEdge(Node( verts[0]),
653 edge = meshDS->AddEdge(Node( verts[0]),
662 topoEdge = TopoDS::Edge( getShapeAtPoint( e->barycenter(), topoEdges ));
664 meshDS->SetMeshElementOnShape( edge, topoEdge );
669 for ( GModel::fiter it = _gModel->firstFace(); it != _gModel->lastFace(); ++it)
673 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
674 // Gmsh since version 4.3 is now producing extra surface and mesh when
675 // compounds are involved. Since in Gmsh meshing procedure needs acess
676 // to each of the original topology and the meshed topology. Hence we
677 // bypass the additional mesh in case of compounds. Note, similar cri-
678 // teria also occurs in the following 'for' loop.
679 if ( _compounds.size() && gFace->geomType() == GEntity::DiscreteSurface )
683 // GET topoFace CORRESPONDING TO gFace
684 TopoDS_Face topoFace;
685 std::vector< ShapeBounds > topoFaces;
687 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
688 if(gFace->haveParametrization())
690 if ( gFace->geomType() != GEntity::CompoundSurface )
693 topoFace = *((TopoDS_Face*)gFace->getNativePtr());
694 if (gFace->getVisibility() == 0) // belongs to a compound
696 SMESH_subMesh* sm = _mesh->GetSubMesh(topoFace);
697 sm->SetIsAlwaysComputed(true); // prevent from displaying errors
700 if ( HasSubMesh( topoFace ))
701 continue; // a meshed sub-mesh
703 bool isCompound = getBoundsOfShapes( gFace, topoFaces );
705 // FILL SMESH FOR topoFace
707 for ( size_t i = 0; i < gFace->mesh_vertices.size(); i++ )
709 MVertex *v = gFace->mesh_vertices[i];
710 if ( v->getIndex() >= 0 )
712 SMDS_MeshNode *node = meshDS->AddNodeWithID(v->x(),v->y(),v->z(),NodeID(v));
715 topoFace = TopoDS::Face( getShapeAtPoint( v->point(), topoFaces ));
717 meshDS->SetNodeOnFace( node, topoFace );
722 for ( GModel::fiter it = _gModel->firstFace(); it != _gModel->lastFace(); ++it)
726 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
727 if ( _compounds.size() && gFace->geomType() == GEntity::DiscreteSurface )
730 bool isCompound = (!gFace->haveParametrization());
732 bool isCompound = ( gFace->geomType() == GEntity::CompoundSurface );
735 if ( !isCompound && gFace->getVisibility() == 0 )
736 continue; // belongs to a compound
738 TopoDS_Face topoFace;
739 std::vector< ShapeBounds > topoFaces;
741 getBoundsOfShapes( gFace, topoFaces );
743 topoFace = *((TopoDS_Face*)gFace->getNativePtr());
745 if ( HasSubMesh( topoFace ))
746 continue; // a meshed sub-mesh
748 // check if there is a meshed sub-mesh on FACE boundary
749 bool hasSubMesh = false;
750 for ( TopExp_Explorer edgeIt( topoFace, TopAbs_EDGE ); edgeIt.More(); edgeIt.Next() )
752 if (( hasSubMesh = HasSubMesh( edgeIt.Current() )))
757 std::vector<MVertex*> verts;
758 for ( size_t i = 0; i < gFace->getNumMeshElements(); i++ )
760 MElement *e = gFace->getMeshElement(i);
762 e->getVertices(verts);
763 SMDS_MeshFace* face = 0;
765 // if a node wasn't set, it is assigned here
766 for ( size_t j = 0; j < verts.size(); j++)
768 if(verts[j]->onWhat()->getVisibility() == 0)
770 SMDS_MeshNode *node = meshDS->AddNodeWithID(verts[j]->x(),verts[j]->y(),verts[j]->z(),NodeID(verts[j]));
771 meshDS->SetNodeOnFace( node, topoFace );
772 verts[i]->setEntity(gFace);
775 switch (verts.size())
778 face = meshDS->AddFace(Node( verts[0], hasSubMesh),
779 Node( verts[1], hasSubMesh),
780 Node( verts[2], hasSubMesh));
783 face = meshDS->AddFace(Node( verts[0], hasSubMesh),
784 Node( verts[1], hasSubMesh),
785 Node( verts[2], hasSubMesh),
786 Node( verts[3], hasSubMesh));
789 face = meshDS->AddFace(Node( verts[0], hasSubMesh),
790 Node( verts[1], hasSubMesh),
791 Node( verts[2], hasSubMesh),
792 Node( verts[3], hasSubMesh),
793 Node( verts[4], hasSubMesh),
794 Node( verts[5], hasSubMesh));
797 face = meshDS->AddFace(Node( verts[0], hasSubMesh),
798 Node( verts[1], hasSubMesh),
799 Node( verts[2], hasSubMesh),
800 Node( verts[3], hasSubMesh),
801 Node( verts[4], hasSubMesh),
802 Node( verts[5], hasSubMesh),
803 Node( verts[6], hasSubMesh),
804 Node( verts[7], hasSubMesh));
807 face = meshDS->AddFace(Node( verts[0], hasSubMesh),
808 Node( verts[1], hasSubMesh),
809 Node( verts[2], hasSubMesh),
810 Node( verts[3], hasSubMesh),
811 Node( verts[4], hasSubMesh),
812 Node( verts[5], hasSubMesh),
813 Node( verts[6], hasSubMesh),
814 Node( verts[7], hasSubMesh),
815 Node( verts[8], hasSubMesh));
823 topoFace = TopoDS::Face( getShapeAtPoint( e->barycenter(), topoFaces ));
825 meshDS->SetMeshElementOnShape(face, topoFace);
830 for ( GModel::riter it = _gModel->firstRegion(); it != _gModel->lastRegion(); ++it)
832 GRegion *gRegion = *it;
833 if (gRegion->getVisibility() == 0)
836 // GET topoSolid CORRESPONDING TO gRegion
837 TopoDS_Solid topoSolid = *((TopoDS_Solid*)gRegion->getNativePtr());
839 // check if there is a meshed sub-mesh on SOLID boundary
840 bool hasSubMesh = false;
841 for ( TopExp_Explorer faceIt( topoSolid, TopAbs_FACE ); faceIt.More(); faceIt.Next() )
843 if (( hasSubMesh = HasSubMesh( faceIt.Current() )))
847 // FILL SMESH FOR topoSolid
850 for( size_t i = 0; i < gRegion->mesh_vertices.size(); i++)
852 MVertex *v = gRegion->mesh_vertices[i];
853 if(v->getIndex() >= 0)
855 SMDS_MeshNode *node = meshDS->AddNodeWithID(v->x(),v->y(),v->z(),NodeID(v));
856 meshDS->SetNodeInVolume( node, topoSolid );
861 std::vector<MVertex*> verts;
862 for( size_t i = 0; i < gRegion->getNumMeshElements(); i++)
864 MElement *e = gRegion->getMeshElement(i);
866 e->getVertices(verts);
867 SMDS_MeshVolume* volume = 0;
868 switch (verts.size()){
870 volume = meshDS->AddVolume(Node( verts[0], hasSubMesh ),
871 Node( verts[2], hasSubMesh ),
872 Node( verts[1], hasSubMesh ),
873 Node( verts[3], hasSubMesh));
876 volume = meshDS->AddVolume(Node( verts[0], hasSubMesh ),
877 Node( verts[3], hasSubMesh ),
878 Node( verts[2], hasSubMesh ),
879 Node( verts[1], hasSubMesh ),
880 Node( verts[4], hasSubMesh));
883 volume = meshDS->AddVolume(Node( verts[0], hasSubMesh ),
884 Node( verts[2], hasSubMesh ),
885 Node( verts[1], hasSubMesh ),
886 Node( verts[3], hasSubMesh ),
887 Node( verts[5], hasSubMesh ),
888 Node( verts[4], hasSubMesh));
891 volume = meshDS->AddVolume(Node( verts[0], hasSubMesh ),
892 Node( verts[3], hasSubMesh ),
893 Node( verts[2], hasSubMesh ),
894 Node( verts[1], hasSubMesh ),
895 Node( verts[4], hasSubMesh ),
896 Node( verts[7], hasSubMesh ),
897 Node( verts[6], hasSubMesh ),
898 Node( verts[5], hasSubMesh));
901 volume = meshDS->AddVolume(Node( verts[0], hasSubMesh ),
902 Node( verts[2], hasSubMesh ),
903 Node( verts[1], hasSubMesh ),
904 Node( verts[3], hasSubMesh ),
905 Node( verts[6], hasSubMesh ),
906 Node( verts[5], hasSubMesh ),
907 Node( verts[4], hasSubMesh ),
908 Node( verts[7], hasSubMesh ),
909 Node( verts[8], hasSubMesh ),
910 Node( verts[9], hasSubMesh));
913 volume = meshDS->AddVolume(Node( verts[0], hasSubMesh ),
914 Node( verts[3], hasSubMesh ),
915 Node( verts[2], hasSubMesh ),
916 Node( verts[1], hasSubMesh ),
917 Node( verts[4], hasSubMesh ),
918 Node( verts[6], hasSubMesh ),
919 Node( verts[10],hasSubMesh ),
920 Node( verts[8], hasSubMesh ),
921 Node( verts[5], hasSubMesh ),
922 Node( verts[7], hasSubMesh ),
923 Node( verts[12],hasSubMesh ),
924 Node( verts[11],hasSubMesh ),
925 Node( verts[9], hasSubMesh));
927 case 14: // same as case 13, because no pyra14 in smesh
928 volume = meshDS->AddVolume(Node( verts[0], hasSubMesh ),
929 Node( verts[3], hasSubMesh ),
930 Node( verts[2], hasSubMesh ),
931 Node( verts[1], hasSubMesh ),
932 Node( verts[4], hasSubMesh ),
933 Node( verts[6], hasSubMesh ),
934 Node( verts[10],hasSubMesh ),
935 Node( verts[8], hasSubMesh ),
936 Node( verts[5], hasSubMesh ),
937 Node( verts[7], hasSubMesh ),
938 Node( verts[12],hasSubMesh ),
939 Node( verts[11],hasSubMesh ),
940 Node( verts[9], hasSubMesh));
943 volume = meshDS->AddVolume(Node( verts[0], hasSubMesh ),
944 Node( verts[2], hasSubMesh ),
945 Node( verts[1], hasSubMesh ),
946 Node( verts[3], hasSubMesh ),
947 Node( verts[5], hasSubMesh ),
948 Node( verts[4], hasSubMesh ),
949 Node( verts[7], hasSubMesh ),
950 Node( verts[9], hasSubMesh ),
951 Node( verts[6], hasSubMesh ),
952 Node( verts[13],hasSubMesh ),
953 Node( verts[14],hasSubMesh ),
954 Node( verts[12],hasSubMesh ),
955 Node( verts[8], hasSubMesh ),
956 Node( verts[11],hasSubMesh ),
957 Node( verts[10],hasSubMesh));
959 case 18: // same as case 15, because no penta18 in smesh
960 volume = meshDS->AddVolume(Node( verts[0], hasSubMesh ),
961 Node( verts[2], hasSubMesh ),
962 Node( verts[1], hasSubMesh ),
963 Node( verts[3], hasSubMesh ),
964 Node( verts[5], hasSubMesh ),
965 Node( verts[4], hasSubMesh ),
966 Node( verts[7], hasSubMesh ),
967 Node( verts[9], hasSubMesh ),
968 Node( verts[6], hasSubMesh ),
969 Node( verts[13],hasSubMesh ),
970 Node( verts[14],hasSubMesh ),
971 Node( verts[12],hasSubMesh ),
972 Node( verts[8], hasSubMesh ),
973 Node( verts[11],hasSubMesh ),
974 Node( verts[10],hasSubMesh));
977 volume = meshDS->AddVolume(Node( verts[0], hasSubMesh ),
978 Node( verts[3], hasSubMesh ),
979 Node( verts[2], hasSubMesh ),
980 Node( verts[1], hasSubMesh ),
981 Node( verts[4], hasSubMesh ),
982 Node( verts[7], hasSubMesh ),
983 Node( verts[6], hasSubMesh ),
984 Node( verts[5], hasSubMesh ),
985 Node( verts[9], hasSubMesh ),
986 Node( verts[13],hasSubMesh ),
987 Node( verts[11],hasSubMesh ),
988 Node( verts[8] ,hasSubMesh ),
989 Node( verts[17],hasSubMesh ),
990 Node( verts[19],hasSubMesh ),
991 Node( verts[18],hasSubMesh ),
992 Node( verts[16],hasSubMesh ),
993 Node( verts[10],hasSubMesh ),
994 Node( verts[15],hasSubMesh ),
995 Node( verts[14],hasSubMesh ),
996 Node( verts[12],hasSubMesh));
999 volume = meshDS->AddVolume(Node( verts[0], hasSubMesh ),
1000 Node( verts[3], hasSubMesh ),
1001 Node( verts[2], hasSubMesh ),
1002 Node( verts[1], hasSubMesh ),
1003 Node( verts[4], hasSubMesh ),
1004 Node( verts[7], hasSubMesh ),
1005 Node( verts[6], hasSubMesh ),
1006 Node( verts[5], hasSubMesh ),
1007 Node( verts[9], hasSubMesh ),
1008 Node( verts[13],hasSubMesh ),
1009 Node( verts[11],hasSubMesh ),
1010 Node( verts[8] ,hasSubMesh ),
1011 Node( verts[17],hasSubMesh ),
1012 Node( verts[19],hasSubMesh ),
1013 Node( verts[18],hasSubMesh ),
1014 Node( verts[16],hasSubMesh ),
1015 Node( verts[10],hasSubMesh ),
1016 Node( verts[15],hasSubMesh ),
1017 Node( verts[14],hasSubMesh ),
1018 Node( verts[12],hasSubMesh ),
1019 Node( verts[20],hasSubMesh ),
1020 Node( verts[22],hasSubMesh ),
1021 Node( verts[24],hasSubMesh ),
1022 Node( verts[23],hasSubMesh ),
1023 Node( verts[21],hasSubMesh ),
1024 Node( verts[25],hasSubMesh ),
1025 Node( verts[26],hasSubMesh ));
1031 meshDS->SetMeshElementOnShape(volume, topoSolid);
1038 //================================================================================
1040 * \brief Find if SPoint point is in SBoundingBox3d bounds
1042 //================================================================================
1044 float GMSHPlugin_Mesher::DistBoundingBox(const SBoundingBox3d& bounds, const SPoint3& point)
1046 SPoint3 min = bounds.min();
1047 SPoint3 max = bounds.max();
1051 if (point.x() < min.x())
1052 x = min.x()-point.x();
1053 else if (point.x() > max.x())
1054 x = point.x()-max.x();
1058 if (point.y() < min.y())
1059 y = min.y()-point.y();
1060 else if (point.y() > max.y())
1061 y = point.y()-max.y();
1065 if (point.z() < min.z())
1066 z = min.z()-point.z();
1067 else if (point.z() > max.z())
1068 z = point.z()-max.z();
1074 //================================================================================
1076 * \brief Reimplemented GmshMessage call. Actions done if errors occurs
1077 * during gmsh meshing. We define here what to display and what to do.
1079 //================================================================================
1080 void GMSHPlugin_Mesher::mymsg::operator()(std::string level, std::string msg)
1082 //MESSAGE("level="<< level.c_str() << ", msg=" << msg.c_str()<< "\n");
1083 printf("level=%s msg=%s\n", level.c_str(), msg.c_str());
1085 if(level == "Fatal" || level == "Error")
1087 std::ostringstream oss;
1088 if (level == "Fatal")
1089 oss << "Fatal error during Generation of Gmsh Mesh\n";
1091 oss << "Error during Generation of Gmsh Mesh\n";
1092 oss << " " << msg.c_str() << "\n";
1093 GEntity *e = _gModel->getCurrentMeshEntity();
1096 oss << " error occurred while meshing entity:\n" <<
1097 " tag=" << e->tag() << "\n" <<
1098 " dimension=" << e->dim() << "\n" <<
1099 " native pointer=" << e->getNativePtr();
1100 //if(e->geomType() != GEntity::CompoundCurve and e->geomType() != GEntity::CompoundSurface)
1102 //SMESH_subMesh *sm = _mesh->GetSubMesh(*((TopoDS_Shape*)e->getNativePtr()));
1103 //SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
1104 //SMESH_Comment comment;
1105 //comment << SMESH_Comment(oss.str);
1106 //std::string str = oss.str();
1107 //smError.reset( new SMESH_ComputeError( str ));
1109 // plutot que de faire de la merde ici, on pourait simplement
1110 // remplir une liste pour dire sur quelles entités gmsh se plante
1111 // (puis faire le fillsmesh)
1112 // puis faire une nouvelle routine qui réécrit les messages d'erreur
1113 // probleme : gmsh peut planté en Fatal, dans ce cas pas de fillsmesh
1116 if (level == "Fatal")
1118 CTX::instance()->lock = 0;
1122 printf("%s\n", oss.str().c_str());
1126 //=============================================================================
1128 * Here we are going to use the GMSH mesher
1130 //=============================================================================
1132 bool GMSHPlugin_Mesher::Compute()
1134 MESSAGE("GMSHPlugin_Mesher::Compute");
1138 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
1139 SetMaxThreadsGmsh();
1143 _gModel = new GModel();
1145 GmshSetMessageHandler(&msg);
1146 _gModel->importOCCShape((void*)&_shape);
1147 if (_compounds.size() > 0) CreateGmshCompounds();
1150 //Msg::SetVerbosity(100);
1151 //CTX::instance()->mesh.maxNumThreads1D=1;
1153 HideComputedEntities( _gModel );
1155 _gModel->mesh( /*dim=*/ 1 );
1157 Set1DSubMeshes( _gModel );
1159 //_gModel->writeUNV("/tmp/1D.unv", 1,0,0);
1160 //CTX::instance()->mesh.maxNumThreads2D=1;
1162 _gModel->mesh( /*dim=*/ 2 );
1166 Set2DSubMeshes( _gModel );
1168 //CTX::instance()->mesh.maxNumThreads3D=1;
1170 _gModel->mesh( /*dim=*/ 3 );
1172 RestoreVisibility( _gModel );
1174 #ifdef WITH_SMESH_CANCEL_COMPUTE
1178 catch (std::string& str)
1181 std::cerr << "GMSH: exception caught: " << str << std::endl;
1187 std::cerr << "GMSH: Unknown exception caught: " << std::endl;
1188 MESSAGE("Unrecoverable error during Generation of Gmsh Mesh");
1193 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
1194 if (_compounds.size() > 0)
1195 SetCompoundMeshVisibility();
1199 GmshSetMessageHandler(nullptr);
1202 MESSAGE("GMSHPlugin_Mesher::Compute:End");
1206 //================================================================================
1208 * \brief Set 1D sub-meshes to GModel. GMSH 1D mesh is made by now.
1209 * \param [inout] _gModel - GMSH model
1211 //================================================================================
1213 void GMSHPlugin_Mesher::Set1DSubMeshes( GModel* gModel )
1215 SMESHDS_Mesh* meshDS = _mesh->GetMeshDS();
1216 if ( meshDS->MaxNodeID() > meshDS->NbNodes() ) // holes in node numeration => compact
1218 meshDS->setMyModified();
1220 meshDS->CompactMesh();
1222 _nodeNumShift = meshDS->NbNodes();
1225 for(GModel::eiter it = gModel->firstEdge(); it != gModel->lastEdge(); ++it)
1229 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
1230 if ( !gEdge->haveParametrization())
1232 if ( gEdge->geomType() == GEntity::CompoundCurve )
1236 TopoDS_Edge topoEdge = *((TopoDS_Edge*)gEdge->getNativePtr());
1237 if ( !HasSubMesh( topoEdge ))
1238 continue; // empty sub-mesh
1240 gEdge->deleteMesh();
1242 // get node parameters on topoEdge
1243 StdMeshers_FaceSide side( TopoDS_Face(), topoEdge, _mesh, /*fwd=*/true, /*skpMedium=*/true);
1244 const UVPtStructVec& nodeParam = side.GetUVPtStruct();
1245 if ( nodeParam.empty() )
1246 throw std::string("Pb with StdMeshers_FaceSide::GetUVPtStruct()");
1248 // get GMSH mesh vertices on VERTEX'es
1249 std::vector<MVertex *> mVertices( nodeParam.size(), nullptr );
1250 GVertex * gV0 = gEdge->getBeginVertex(), *gV1 = gEdge->getEndVertex();
1251 mVertices[0] = gV0->mesh_vertices[ 0 ];
1252 mVertices.back() = gV1->mesh_vertices[ 0 ];
1253 TopoDS_Vertex v01 = *((TopoDS_Vertex*) gV0->getNativePtr());
1254 TopoDS_Shape v02 = SMESH_MesherHelper::GetSubShapeByNode( nodeParam[0].node, meshDS );
1255 bool reverse = !v01.IsSame( v02 );
1256 if ( mVertices[0] == mVertices.back() )
1257 reverse = ( nodeParam[0].param > nodeParam.back().param );
1258 const SMDS_MeshNode* n0 = reverse ? nodeParam.back().node : nodeParam[0].node;
1259 const SMDS_MeshNode* n1 = reverse ? nodeParam[0].node : nodeParam.back().node;
1260 _nodeMap.insert({ mVertices[ 0 ], n0 });
1261 _nodeMap.insert({ mVertices.back(), n1 });
1263 // create GMSH mesh vertices on gEdge
1264 for ( size_t i = 1; i < nodeParam.size() - 1; ++i )
1266 size_t iN = reverse ? ( nodeParam.size() - 1 - i ) : i;
1267 SMESH_NodeXYZ xyz = nodeParam[ iN ].node;
1268 double lc = segmentSize( nodeParam, iN );
1269 // SVector3 der = gEdge->firstDer(nodeParam[ iN ].param);
1270 // double lc = norm(der) / segmentSize( nodeParam, i );
1272 mVertices[ i ] = new MEdgeVertex( xyz.X(), xyz.Y(), xyz.Z(),
1273 gEdge, nodeParam[ iN ].param, 0, lc);
1274 gEdge->mesh_vertices.push_back( mVertices[ i ]);
1275 _nodeMap.insert({ mVertices[ i ], nodeParam[ iN ].node });
1277 // create GMSH mesh edges
1278 for ( size_t i = 1; i < mVertices.size(); ++i )
1280 gEdge->lines.push_back( new MLine( mVertices[ i - 1 ],
1284 cout << endl << "EDGE " << gEdge->tag() <<
1285 ( topoEdge.Orientation() == TopAbs_FORWARD ? " F" : " R") << endl;
1286 MVertex* mv = gV0->mesh_vertices[ 0 ];
1287 cout << "V0: " << mv->x() << ", " << mv->y() << ", " << mv->z() << ", "<<endl;
1288 for ( size_t i = 0; i < gEdge->mesh_vertices.size(); ++i )
1290 MEdgeVertex* mv = (MEdgeVertex*) gEdge->mesh_vertices[i];
1291 cout << i << ": " << mv->x() << ", " << mv->y() << ", " << mv->z() << ", ";
1293 mv->getParameter(0, t );
1294 cout << ":\t t = "<< t << " lc = " << mv->getLc() << endl;
1296 mv = gV1->mesh_vertices[ 0 ];
1297 cout << "V1: " << mv->x() << ", " << mv->y() << ", " << mv->z() << ", "<<endl;
1303 //================================================================================
1305 * \brief Set 2D sub-meshes to GModel. GMSH 2D mesh is made by now.
1306 * \param [inout] _gModel - GMSH model
1308 //================================================================================
1310 void GMSHPlugin_Mesher::Set2DSubMeshes( GModel* gModel )
1312 if ( _nodeMap.empty() )
1313 return; // no sub-meshes
1315 SMESH_MesherHelper helper( *_mesh );
1317 std::map< const SMDS_MeshNode* , const MVertex * > nodes2mvertMap;
1318 for ( auto & v2n : _nodeMap )
1319 nodes2mvertMap.insert({ v2n.second, v2n.first });
1321 std::vector<MVertex *> mVertices;
1323 for(GModel::fiter it = gModel->firstFace(); it != gModel->lastFace(); ++it)
1327 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
1328 if ( !gFace->haveParametrization())
1330 if ( gFace->geomType() == GEntity::CompoundSurface )
1334 TopoDS_Face topoFace = *((TopoDS_Face*)gFace->getNativePtr());
1335 SMESHDS_SubMesh* sm = HasSubMesh( topoFace );
1338 //_gModel->writeUNV("/tmp/befDEl.unv", 1,0,0);
1340 gFace->deleteMesh();
1342 bool reverse = false;
1343 if ( gFace->getRegion(0) )
1345 //GRegion * gRegion = gFace->getRegion(0);
1346 TopoDS_Shape topoSolid = *((TopoDS_Shape*)gFace->getNativePtr());
1347 TopAbs_Orientation faceOriInSolid = helper.GetSubShapeOri( topoSolid, topoFace );
1348 if ( faceOriInSolid >= 0 )
1350 helper.IsReversedSubMesh( TopoDS::Face( topoFace.Oriented( faceOriInSolid )));
1353 for ( SMDS_ElemIteratorPtr fIt = sm->GetElements(); fIt->more(); )
1355 const SMDS_MeshElement* f = fIt->next();
1357 int nbN = f->NbCornerNodes();
1359 throw std::string("Polygon sub-meshes not supported");
1361 mVertices.resize( nbN );
1362 for ( int i = 0; i < nbN; ++i )
1364 const SMDS_MeshNode* n = f->GetNode( i );
1365 MVertex * mv = nullptr;
1366 auto n2v = nodes2mvertMap.find( n );
1367 if ( n2v != nodes2mvertMap.end() )
1369 mv = const_cast< MVertex*>( n2v->second );
1373 if ( n->GetPosition()->GetDim() < 2 )
1374 throw std::string("Wrong mapping of edge nodes to GMSH nodes");
1375 SMESH_NodeXYZ xyz = n;
1377 gp_XY uv = helper.GetNodeUV( topoFace, n, nullptr, &ok );
1378 mv = new MFaceVertex( xyz.X(), xyz.Y(), xyz.Z(), gFace, uv.X(), uv.Y() );
1379 gFace->mesh_vertices.push_back( mv );
1380 nodes2mvertMap.insert({ n, mv });
1381 _nodeMap.insert ({ mv, n });
1383 mVertices[ i ] = mv;
1385 // create GMSH mesh faces
1389 gFace->triangles.push_back (new MTriangle(mVertices[0], mVertices[2], mVertices[1]));
1391 gFace->triangles.push_back (new MTriangle(mVertices[0], mVertices[1], mVertices[2]));
1395 gFace->quadrangles.push_back (new MQuadrangle(mVertices[0], mVertices[3],
1396 mVertices[2], mVertices[1]));
1398 gFace->quadrangles.push_back (new MQuadrangle(mVertices[0], mVertices[1],
1399 mVertices[2], mVertices[3]));
1404 } // loop on GMSH faces
1409 //================================================================================
1411 * \brief Set visibility 0 to already computed geom entities
1412 * to prevent their meshing
1414 //================================================================================
1416 void GMSHPlugin_Mesher::HideComputedEntities( GModel* gModel )
1418 CTX::instance()->mesh.meshOnlyVisible = true;
1420 for(GModel::eiter it = gModel->firstEdge(); it != gModel->lastEdge(); ++it)
1424 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
1425 if ( !gEdge->haveParametrization())
1427 if ( gEdge->geomType() == GEntity::CompoundCurve )
1431 TopoDS_Edge topoEdge = *((TopoDS_Edge*)gEdge->getNativePtr());
1432 if ( HasSubMesh( topoEdge ))
1433 gEdge->setVisibility(0);
1437 for(GModel::fiter it = gModel->firstFace(); it != gModel->lastFace(); ++it)
1441 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
1442 if ( !gFace->haveParametrization())
1444 if ( gFace->geomType() == GEntity::CompoundSurface )
1448 TopoDS_Face topoFace = *((TopoDS_Face*)gFace->getNativePtr());
1449 if ( HasSubMesh( topoFace ))
1450 gFace->setVisibility(0);
1454 //================================================================================
1456 * \brief Restore visibility of all geom entities
1458 //================================================================================
1460 void GMSHPlugin_Mesher::RestoreVisibility( GModel* gModel )
1462 for(GModel::eiter it = gModel->firstEdge(); it != gModel->lastEdge(); ++it)
1465 gEdge->setVisibility(1);
1467 for(GModel::fiter it = gModel->firstFace(); it != gModel->lastFace(); ++it)
1470 gFace->setVisibility(1);
1475 void GMSHPlugin_Mesher::toPython( GModel* )
1477 const char* pyFile = "/tmp/gMesh.py";
1478 ofstream outfile( pyFile, ios::out );
1479 if ( !outfile ) return;
1481 outfile << "import salome, SMESH" << std::endl
1482 << "from salome.smesh import smeshBuilder" << std::endl
1483 << "smesh = smeshBuilder.New()" << std::endl
1484 << "mesh = smesh.Mesh()" << std::endl << std::endl;
1486 outfile << "## VERTICES" << endl;
1487 for ( GModel::viter it = _gModel->firstVertex(); it != _gModel->lastVertex(); ++it)
1489 GVertex *gVertex = *it;
1491 for(unsigned int i = 0; i < gVertex->mesh_vertices.size(); i++)
1493 MVertex *v = gVertex->mesh_vertices[i];
1494 if ( v->getIndex() >= 0)
1496 outfile << "n" << v->getNum() << " = mesh.AddNode("
1497 << v->x() << ", " << v->y() << ", " << v->z()<< ")"
1498 << " ## tag = " << gVertex->tag() << endl;
1503 for(GModel::eiter it = _gModel->firstEdge(); it != _gModel->lastEdge(); ++it)
1506 outfile << "## GEdge " << gEdge->tag() << endl;
1508 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
1509 if(gEdge->haveParametrization())
1511 if ( gEdge->geomType() != GEntity::CompoundCurve )
1513 for ( size_t i = 0; i < gEdge->mesh_vertices.size(); i++ )
1515 MVertex *v = gEdge->mesh_vertices[i];
1516 if ( v->getIndex() >= 0 )
1518 outfile << "n" << v->getNum() << " = mesh.AddNode("
1519 << v->x() << ", " << v->y() << ", " << v->z()<< ")"
1520 << " ## tag = " << gEdge->tag() << endl;
1525 for ( GModel::fiter it = _gModel->firstFace(); it != _gModel->lastFace(); ++it)
1528 if ( _compounds.size() && gFace->geomType() == GEntity::DiscreteSurface )
1530 outfile << "## GFace " << gFace->tag() << endl;
1532 for ( size_t i = 0; i < gFace->mesh_vertices.size(); i++ )
1534 MVertex *v = gFace->mesh_vertices[i];
1535 if ( v->getIndex() >= 0 )
1537 outfile << "n" << v->getNum() << " = mesh.AddNode("
1538 << v->x() << ", " << v->y() << ", " << v->z()<< ")"
1539 << " ## tag = " << gFace->tag() << endl;
1544 std::vector<MVertex*> verts(3);
1545 for(GModel::eiter it = _gModel->firstEdge(); it != _gModel->lastEdge(); ++it)
1548 outfile << "## GEdge " << gEdge->tag() << endl;
1550 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
1551 if(gEdge->haveParametrization())
1553 if ( gEdge->geomType() != GEntity::CompoundCurve )
1555 for ( size_t i = 0; i < gEdge->getNumMeshElements(); i++ )
1557 MElement *e = gEdge->getMeshElement(i);
1559 e->getVertices(verts);
1561 outfile << "e" << e->getNum() << " = mesh.AddEdge(["
1562 << "n" << verts[0]->getNum() << ","
1563 << "n" << verts[1]->getNum();
1564 if ( verts.size() == 3 )
1565 outfile << "n" << verts[2]->getNum();
1566 outfile << "])"<< endl;
1570 for ( GModel::fiter it = _gModel->firstFace(); it != _gModel->lastFace(); ++it)
1573 if ( _compounds.size() && gFace->geomType() == GEntity::DiscreteSurface )
1575 outfile << "## GFace " << gFace->tag() << endl;
1577 for ( size_t i = 0; i < gFace->getNumMeshElements(); i++ )
1579 MElement *e = gFace->getMeshElement(i);
1581 e->getVertices(verts);
1583 outfile << "f" << e->getNum() << " = mesh.AddFace([";
1584 for ( size_t j = 0; j < verts.size(); j++)
1586 outfile << "n" << verts[j]->getNum();
1587 if ( j < verts.size()-1 )
1590 outfile << "])" << endl;
1593 std::cout << "Write " << pyFile << std::endl;