1 // Copyright (C) 2012-2015 ALNEOS
2 // Copyright (C) 2016-2023 EDF
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>
35 #include <StdMeshers_QuadToTriaAdaptor.hxx>
38 #include <BRep_Tool.hxx>
39 #include <GeomAPI_ProjectPointOnCurve.hxx>
46 #include <TopExp_Explorer.hxx>
50 #include <MTriangle.h>
51 #include <MQuadrangle.h>
52 #if GMSH_MAJOR_VERSION >=4
53 #include <GmshGlobal.h>
54 #include <gmsh/Context.h>
57 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
67 SBoundingBox3d _bounds;
71 //================================================================================
73 * \brief Retrieve ShapeBounds from a compound GEdge
75 //================================================================================
77 bool getBoundsOfShapes( GEdge* gEdge,
78 std::vector< ShapeBounds > & topoEdges )
81 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
82 for ( size_t i = 0; i < gEdge->compound.size(); ++i )
84 GEdge* gE = static_cast< GEdge* >( gEdge->compound[ i ]);
85 topoEdges.push_back( ShapeBounds{ gE->bounds(), *((TopoDS_Edge*)gE->getNativePtr()) });
88 for ( size_t i = 0; i < gEdge->_compound.size(); ++i )
90 GEdge* gE = static_cast< GEdge* >( gEdge->_compound[ i ]);
91 topoEdges.push_back( ShapeBounds{ gE->bounds(), *((TopoDS_Edge*)gE->getNativePtr()) });
94 return topoEdges.size();
97 //================================================================================
99 * \brief Retrieve ShapeBounds from a compound GFace
101 //================================================================================
103 bool getBoundsOfShapes( GFace* gFace,
104 std::vector< ShapeBounds > & topoFaces )
107 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
108 for ( size_t i = 0; i < gFace->compound.size(); ++i )
110 GFace* gF = static_cast< GFace* >( gFace->compound[ i ]);
111 topoFaces.push_back( ShapeBounds{ gF->bounds(), *((TopoDS_Face*)gF->getNativePtr()) });
114 for ( size_t i = 0; i < gFace->_compound.size(); ++i )
116 GFace* gF = static_cast< GFace* >( gFace->_compound[ i ]);
117 topoFaces.push_back( ShapeBounds{ gF->bounds(), *((TopoDS_Face*)gF->getNativePtr()) });
120 return topoFaces.size();
122 //================================================================================
124 * \brief Find a shape whose bounding box includes a given point
126 //================================================================================
128 TopoDS_Shape getShapeAtPoint( const SPoint3& point, const std::vector< ShapeBounds > & shapes )
131 float distmin = std::numeric_limits<float>::max();
132 for ( size_t i = 0; i < shapes.size(); ++i )
134 float dist = GMSHPlugin_Mesher::DistBoundingBox( shapes[i]._bounds, point );
137 shape = shapes[i]._shape;
146 double segmentSize( const UVPtStructVec& nodeParam, size_t i )
148 double l1 = SMESH_NodeXYZ( nodeParam[i].node ).Distance( nodeParam[i-1].node );
149 double l2 = SMESH_NodeXYZ( nodeParam[i].node ).Distance( nodeParam[i+1].node );
150 return 0.5 * ( l1 + l2 );
154 //=============================================================================
158 //=============================================================================
160 GMSHPlugin_Mesher::GMSHPlugin_Mesher (SMESH_Mesh* mesh,
161 const TopoDS_Shape& aShape,
169 // il faudra peut être mettre un truc par defaut si l'utilisateur ne rentre rien en para
170 //defaultParameters();
173 //void GMSHPlugin_Mesher::defaultParameters(){}
175 void GMSHPlugin_Mesher::SetParameters(const GMSHPlugin_Hypothesis* hyp)
179 _algo2d = hyp->Get2DAlgo();
180 _algo3d = hyp->Get3DAlgo();
181 _recomb2DAlgo = hyp->GetRecomb2DAlgo();
182 _recombineAll = hyp->GetRecombineAll();
183 _subdivAlgo = hyp->GetSubdivAlgo();
184 _remeshAlgo = hyp->GetRemeshAlgo();
185 _remeshPara = hyp->GetRemeshPara();
186 _smouthSteps = hyp->GetSmouthSteps();
187 _sizeFactor = hyp->GetSizeFactor();
188 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=10
189 _meshCurvatureSize = hyp->GetMeshCurvatureSize();
191 _minSize = hyp->GetMinSize();
192 _maxSize = hyp->GetMaxSize();
193 _secondOrder = hyp->GetSecondOrder();
194 _useIncomplElem = hyp->GetUseIncomplElem();
195 _verbLvl = hyp->GetVerbosityLevel();
196 _compounds = hyp->GetCompoundOnEntries();
197 // 6 in the enum corresponds to 99 in gmsh
206 _recombineAll = false;
212 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=10
213 _meshCurvatureSize = 0;
217 _secondOrder = false;
218 _useIncomplElem = true;
224 //================================================================================
226 * \brief Set maximum number of threads to be used by Gmsh
228 //================================================================================
230 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
231 void GMSHPlugin_Mesher::SetMaxThreadsGmsh()
233 MESSAGE("GMSHPlugin_Mesher::SetMaxThreadsGmsh");
234 // compound meshing (_compounds.size() > 0) and quad meshing (_algo2d >= 5) will
235 // not be multi-threaded
236 if (_compounds.size() > 0 || _algo2d >= 5){
240 _maxThreads = omp_get_max_threads();
244 //================================================================================
246 * \brief Initialize GMSH model
248 //================================================================================
249 void GMSHPlugin_Mesher::FillGMSHMesh()
252 gmsh::model::add("mesh");
254 SMESHDS_Mesh* meshDS = _mesh->GetMeshDS();
259 std::vector<int> aTrinagle(3, 0);
261 const int invalid_ID = -1;
264 typedef map< const SMDS_MeshNode*, int, TIDCompare > TNodeToIDMap;
265 typedef TNodeToIDMap::value_type TN2ID;
266 typedef map<std::pair<int, int>, int> TLineToIDMap;
267 TNodeToIDMap aNodeToID;
268 TLineToIDMap aLineToID;
270 TopAbs_ShapeEnum aMainType = _mesh->GetShapeToMesh().ShapeType();
271 bool aCheckReverse = (aMainType == TopAbs_COMPOUND || aMainType == TopAbs_COMPSOLID);
273 SMESH_MesherHelper aHelper(*_mesh);
274 SMESH_ProxyMesh::Ptr aProxyMesh(new SMESH_ProxyMesh(*_mesh));
275 if (_mesh->NbQuadrangles() > 0)
277 StdMeshers_QuadToTriaAdaptor* Adaptor = new StdMeshers_QuadToTriaAdaptor;
278 Adaptor->Compute(*_mesh, _shape, aProxyMesh.get());
279 aProxyMesh.reset(Adaptor);
282 std::map<const SMDS_MeshElement*, bool, TIDCompare> listElements;
283 for (TopExp_Explorer exFa(_shape, TopAbs_FACE); exFa.More(); exFa.Next())
285 const TopoDS_Shape& aShapeFace = exFa.Current();
286 int faceID = meshDS->ShapeToIndex(aShapeFace);
289 if (aCheckReverse && aHelper.NbAncestors(aShapeFace, *_mesh, _shape.ShapeType()) > 1)
290 // IsReversedSubMesh() can work wrong on strongly curved faces,
291 // so we use it as less as possible
292 isRev = aHelper.IsReversedSubMesh(TopoDS::Face(aShapeFace));
294 const SMESHDS_SubMesh* aSubMeshDSFace = aProxyMesh->GetSubMesh(aShapeFace);
295 if (!aSubMeshDSFace) continue;
297 SMDS_ElemIteratorPtr iteratorElem = aSubMeshDSFace->GetElements();
298 if (aHelper.IsQuadraticSubMesh(_shape) &&
299 dynamic_cast<const SMESH_ProxyMesh::SubMesh*>(aSubMeshDSFace))
301 // add medium nodes of proxy triangles to helper
302 while (iteratorElem->more())
303 aHelper.AddTLinks(static_cast<const SMDS_MeshFace*>(iteratorElem->next()));
305 iteratorElem = aSubMeshDSFace->GetElements();
307 while (iteratorElem->more()) // loop on elements on a geom face
310 const SMDS_MeshElement* elem = iteratorElem->next();
313 if (elem->NbCornerNodes() != 3)
315 listElements[elem] = isRev;
319 for (auto const& ls : listElements)
321 // Add nodes of triangles and triangles them-selves to netgen mesh
322 // add three nodes of
323 bool hasDegen = false;
324 for (int iN = 0; iN < 3; ++iN)
326 const SMDS_MeshNode* aNode = ls.first->GetNode(iN);
327 const int shapeID = aNode->getshapeId();
328 if (aNode->GetPosition()->GetTypeOfPosition() == SMDS_TOP_EDGE &&
329 aHelper.IsDegenShape(shapeID))
331 // ignore all nodes on degeneraged edge and use node on its vertex instead
332 TopoDS_Shape vertex = TopoDS_Iterator(meshDS->IndexToShape(shapeID)).Value();
333 aNode = SMESH_Algo::VertexNode(TopoDS::Vertex(vertex), meshDS);
336 int& ngID = aNodeToID.insert(TN2ID(aNode, invalid_ID)).first->second;
337 if (ngID == invalid_ID)
340 gmsh::model::occ::addPoint(aNode->X(), aNode->Y(), aNode->Z(), 1.e-2, ngID);
342 aTrinagle[ls.second ? 2 - iN : iN] = ngID;
345 if (hasDegen && (aTrinagle[0] == aTrinagle[1] ||
346 aTrinagle[0] == aTrinagle[2] ||
347 aTrinagle[2] == aTrinagle[1]))
351 std::vector<int> LinesID(3, 0);
352 for (int anIndex = 0; anIndex < 3; ++anIndex)
354 int aNextIndex = (anIndex + 1) % 3;
355 if (aLineToID.find({ aTrinagle[anIndex], aTrinagle[aNextIndex] }) == aLineToID.end()
356 && aLineToID.find({ aTrinagle[aNextIndex], aTrinagle[anIndex] }) == aLineToID.end())
358 LinesID[anIndex] = aLineToID.insert({ { aTrinagle[aNextIndex], aTrinagle[anIndex] }, ++aNbOfLines }).first->second;
359 gmsh::model::occ::addLine(aTrinagle[anIndex], aTrinagle[aNextIndex], LinesID[anIndex]);
363 LinesID[anIndex] = aLineToID.find({ aTrinagle[anIndex], aTrinagle[aNextIndex] })->second;
364 if (LinesID[anIndex] == 0)
365 LinesID[anIndex] = aLineToID.find({ aTrinagle[aNextIndex], aTrinagle[anIndex] })->second;
369 if (!aProxyMesh->IsTemporary(ls.first))
370 swap(aTrinagle[1], aTrinagle[2]);
372 int aTag = gmsh::model::occ::addCurveLoop(LinesID);
375 // Generate 1D and 2D mesh
376 _gModel->mesh( /*dim=*/ 1);
377 Set1DSubMeshes(_gModel);
378 _gModel->mesh( /*dim=*/ 2);
381 //================================================================================
383 * \brief Set Gmsh Options
385 //================================================================================
386 void GMSHPlugin_Mesher::SetGmshOptions()
388 MESSAGE("GMSHPlugin_Mesher::SetGmshOptions");
390 printf("We chose _algo2d %d \n", _algo2d );
391 printf("We chose _algo3d %d \n", _algo3d );
392 printf("We chose _recomb2DAlgo %d \n", _recomb2DAlgo );
393 printf("We chose _recombineAll %d \n", (_recombineAll)?1:0);
394 printf("We chose _subdivAlgo %d \n", _subdivAlgo );
395 printf("We chose _remeshAlgo %d \n", _remeshAlgo );
396 printf("We chose _remeshPara %d \n", _remeshPara );
397 printf("We chose _smouthSteps %e \n", _smouthSteps );
398 printf("We chose _sizeFactor %e \n", _sizeFactor );
399 printf("We chose _minSize %e \n", _minSize );
400 printf("We chose _maxSize %e \n", _maxSize );
401 printf("We chose _secondOrder %d \n", (_secondOrder)?1:0);
402 printf("We chose _useIncomplElem %d \n", (_useIncomplElem)?1:0);
403 printf("We are in dimension %d \n", (_is2d)?2:3);
406 std::map <int,double> mapAlgo2d;
407 mapAlgo2d[0]=2; // Automatic
408 mapAlgo2d[1]=1; // MeshAdapt
409 mapAlgo2d[2]=5; // Delaunay
410 mapAlgo2d[3]=6; // Frontal-Delaunay
411 mapAlgo2d[4]=8; // DelQuad (Frontal-Delaunay for Quads)
412 mapAlgo2d[5]=9; // Packing of parallelograms
413 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=10
414 mapAlgo2d[6]=11;// Quasistructured quads with cross-fields
417 std::map <int,double> mapAlgo3d;
418 mapAlgo3d[0]=1; // Delaunay
419 mapAlgo3d[1]=4; // Frontal
420 mapAlgo3d[2]=7; // MMG3D
421 mapAlgo3d[3]=9; // R-tree
422 mapAlgo3d[4]=10;// HXT
425 ok = GmshSetOption("Mesh", "Algorithm" , mapAlgo2d[_algo2d]) ;
429 ok = GmshSetOption("Mesh", "Algorithm3D" , mapAlgo3d[_algo3d]) ;
432 ok = GmshSetOption("Mesh", "RecombinationAlgorithm" , (double)_recomb2DAlgo) ;
434 ok = GmshSetOption("Mesh", "RecombineAll" , (_recombineAll)?1.:0.) ;
436 ok = GmshSetOption("Mesh", "SubdivisionAlgorithm" , (double)_subdivAlgo) ;
438 ok = GmshSetOption("Mesh", "RemeshAlgorithm" , (double)_remeshAlgo) ;
440 ok = GmshSetOption("Mesh", "RemeshParametrization" , (double)_remeshPara) ;
442 ok = GmshSetOption("Mesh", "Smoothing" , (double)_smouthSteps) ;
444 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=10
445 ok = GmshSetOption("Mesh", "MeshSizeFromCurvature" , _meshCurvatureSize) ;
448 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
449 ok = GmshSetOption("Mesh", "MeshSizeFactor" , _sizeFactor) ;
451 ok = GmshSetOption("Mesh", "MeshSizeMin" , _minSize) ;
453 ok = GmshSetOption("Mesh", "MeshSizeMax" , _maxSize) ;
456 ok = GmshSetOption("Mesh", "CharacteristicLengthFactor" , _sizeFactor) ;
458 ok = GmshSetOption("Mesh", "CharacteristicLengthMin" , _minSize) ;
460 ok = GmshSetOption("Mesh", "CharacteristicLengthMax" , _maxSize) ;
463 ok = GmshSetOption("Mesh", "ElementOrder" , (_secondOrder)?2.:1.) ;
467 ok = GmshSetOption("Mesh", "SecondOrderIncomplete" ,(_useIncomplElem)?1.:0.);
471 ok = GmshSetOption("General", "Verbosity" , (double) _verbLvl ) ; // Verbosity level
474 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
475 /*ok = GmshSetOption("Mesh", "MaxNumThreads1D" , 0. ) ; // Coarse-grain algo threads
477 ok = GmshSetOption("Mesh", "MaxNumThreads2D" , 0. ) ; // Coarse-grain algo threads
479 ok = GmshSetOption("Mesh", "MaxNumThreads3D" , 0. ) ; // Fine-grain algo threads HXT
482 ok = GmshSetOption("General", "NumThreads" , _maxThreads ) ; // system default i.e. OMP_NUM_THREADS
485 if ( GMSHPlugin_Hypothesis::Algo3D::hxt == _algo3d ){
486 MESSAGE("GMSHPlugin_Mesher::SetGmshOptions: HXT algorithm is being used. Setting number of threads to 1.");
487 ok = GmshSetOption("Mesh", "MaxNumThreads3D" , 1. );
494 //================================================================================
496 * \brief Create and add Compounds into GModel _gModel.
498 //================================================================================
500 void GMSHPlugin_Mesher::CreateGmshCompounds()
502 MESSAGE("GMSHPlugin_Mesher::CreateGmshCompounds");
504 SMESH_Gen_i* smeshGen_i = SMESH_Gen_i::GetSMESHGen();
506 OCC_Internals* occgeo = _gModel->getOCCInternals();
507 bool toSynchronize = false;
509 for(std::set<std::string>::const_iterator its = _compounds.begin();its != _compounds.end(); ++its )
511 GEOM::GEOM_Object_var aGeomObj;
512 TopoDS_Shape geomShape = TopoDS_Shape();
513 SALOMEDS::SObject_var aSObj = SMESH_Gen_i::GetSMESHGen()->getStudyServant()->FindObjectID( (*its).c_str() );
514 SALOMEDS::GenericAttribute_var anAttr;
515 if (!aSObj->_is_nil() && aSObj->FindAttribute(anAttr, "AttributeIOR"))
517 SALOMEDS::AttributeIOR_var anIOR = SALOMEDS::AttributeIOR::_narrow(anAttr);
518 CORBA::String_var aVal = anIOR->Value();
519 CORBA::Object_var obj = SMESH_Gen_i::GetSMESHGen()->getStudyServant()->ConvertIORToObject(aVal);
520 aGeomObj = GEOM::GEOM_Object::_narrow(obj);
522 geomShape = smeshGen_i->GeomObjectToShape( aGeomObj.in() );
523 if ( geomShape.IsNull() )
526 TopAbs_ShapeEnum geomType = geomShape.ShapeType();
527 if ( geomType == TopAbs_COMPOUND)// voir s'il ne faut pas mettre une erreur dans le cas contraire
529 MESSAGE("shapeType == TopAbs_COMPOUND");
530 TopoDS_Iterator it(geomShape);
533 TopAbs_ShapeEnum shapeType = it.Value().ShapeType();
534 std::vector< std::pair< int, int > > dimTags;
535 for ( ; it.More(); it.Next())
537 const TopoDS_Shape& topoShape = it.Value();
538 ASSERT(topoShape.ShapeType() == shapeType);
539 if ( _mesh->GetMeshDS()->ShapeToIndex( topoShape ) > 0 )
540 occgeo->importShapes( &topoShape, false, dimTags );
543 TopoDS_Shape face = TopExp_Explorer( _shape, shapeType ).Current();
544 SMESH_subMesh* sm = _mesh->GetSubMesh( face );
545 sm->GetComputeError() =
546 SMESH_ComputeError::New
547 ( COMPERR_WARNING, "Compound shape does not belong to the main geometry. Ignored");
550 std::vector<int> tags;
551 int dim = ( shapeType == TopAbs_EDGE ) ? 1 : 2;
552 for ( size_t i = 0; i < dimTags.size(); ++i )
554 if ( dimTags[i].first == dim )
555 tags.push_back( dimTags[i].second );
559 _gModel->getGEOInternals()->setCompoundMesh( dim, tags );
560 toSynchronize = true;
563 _gModel->getGEOInternals()->synchronize(_gModel);
568 //================================================================================
570 * \brief For a compound mesh set the mesh components to be transmitted to SMESH
572 //================================================================================
574 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
575 void GMSHPlugin_Mesher::SetCompoundMeshVisibility()
578 // Loop over all faces, if the face belongs to a compound entry then
579 // for all (boundary) edges whithin the face visibility is set to 0,
580 // if the face doesn't belong to a compound entry then visibility is
581 // set to 1 for all its (boundary) edges. Later, in FillSMesh() func
582 // getVisibility() (returns either 1 or 0) is used to decide weather
583 // the mesh of edge should be transmitted to SMESH or not.
585 for ( GModel::fiter itF = _gModel->firstFace(); itF != _gModel->lastFace(); ++itF )
587 std::vector< GEdge *> faceEdges = (*itF)->edges();
589 for ( auto itE = faceEdges.begin(); itE != faceEdges.end(); ++itE )
591 if ( ((*itF)->compound.size()) )
592 (*itE)->setVisibility(0);
594 (*itE)->setVisibility(1);
599 // Loop over all edges, if the edge belongs to a compound entry then
600 // for all (boundary) vertices whithin the edge visibility is set to
601 // 0, if the edge doesn't belong to a compound entry then visibility
602 // is set to 1 for all its (boundary) vertices. Later, in FillSMesh()
603 // func getVisibility() (returns either 1 or 0) is used to decide we-
604 // ather the mesh of vertices should be transmitted to SMESH or not.
606 for ( GModel::eiter itE = _gModel->firstEdge(); itE != _gModel->lastEdge(); ++itE )
608 std::vector<GVertex *> bndVerticies = (*itE)->vertices();
610 for( auto itV = bndVerticies.begin(); itV != bndVerticies.end(); ++itV )
612 if(((*itE)->compound.size()))
613 (*itV)->setVisibility(0);
615 (*itV)->setVisibility(1);
622 //================================================================================
624 * \brief Get a node by a GMSH mesh vertex
626 //================================================================================
628 const SMDS_MeshNode* GMSHPlugin_Mesher::Node( const MVertex* v )
630 std::map< const MVertex *, const SMDS_MeshNode* >::iterator v2n = _nodeMap.find( v );
631 if ( v2n != _nodeMap.end() )
637 //================================================================================
639 * \brief Return a corresponding sub-mesh if a shape is meshed
641 //================================================================================
643 SMESHDS_SubMesh* GMSHPlugin_Mesher::HasSubMesh( const TopoDS_Shape& s )
645 if ( SMESHDS_SubMesh* sm = _mesh->GetMeshDS()->MeshElements( s ))
647 if ( s.ShapeType() == TopAbs_VERTEX )
648 return ( sm->NbNodes() > 0 ) ? sm : nullptr;
650 return ( sm->NbElements() > 0 ) ? sm : nullptr;
655 //================================================================================
657 * \brief Write mesh from GModel instance to SMESH instance
659 //================================================================================
661 void GMSHPlugin_Mesher::FillSMesh()
663 SMESHDS_Mesh* meshDS = _mesh->GetMeshDS();
666 for ( GModel::viter it = _gModel->firstVertex(); it != _gModel->lastVertex(); ++it)
668 GVertex *gVertex = *it;
670 // GET topoVertex CORRESPONDING TO gVertex
671 TopoDS_Vertex topoVertex = *((TopoDS_Vertex*)gVertex->getNativePtr());
673 if (gVertex->getVisibility() == 0) // belongs to a compound
675 SMESH_subMesh* sm = _mesh->GetSubMesh(topoVertex);
676 sm->SetIsAlwaysComputed(true); // prevent from displaying errors
680 // FILL SMESH FOR topoVertex
682 for( size_t i = 0; i < gVertex->mesh_vertices.size(); i++)
684 MVertex *v = gVertex->mesh_vertices[i];
685 if(v->getIndex() >= 0)
687 if ( SMESHDS_SubMesh* sm = HasSubMesh( topoVertex ))
689 const SMDS_MeshNode *node = sm->GetNodes()->next();
690 _nodeMap.insert({ v, node });
694 SMDS_MeshNode *node = meshDS->AddNode( v->x(),v->y(),v->z() );
695 meshDS->SetNodeOnVertex( node, topoVertex );
696 _nodeMap.insert({ v, node });
700 // WE DON'T ADD 0D ELEMENTS because it does not follow the salome meshers philosophy
702 // for(unsigned int i = 0; i < gVertex->getNumMeshElements(); i++)
704 // MElement *e = gVertex->getMeshElement(i);
705 // std::vector<MVertex*> verts;
706 // e->getVertices(verts);
707 // ASSERT(verts.size()==1);
708 // SMDS_Mesh0DElement* zeroDElement = 0;
709 // zeroDElement = meshDS->Add0DElementWithID(verts[0]->getNum(),e->getNum());
710 // meshDS->SetMeshElementOnShape(zeroDElement, topoVertex);
715 for(GModel::eiter it = _gModel->firstEdge(); it != _gModel->lastEdge(); ++it)
719 // GET topoEdge CORRESPONDING TO gEdge
720 TopoDS_Edge topoEdge;
721 std::vector< ShapeBounds > topoEdges;
722 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
723 if(gEdge->haveParametrization())
725 if ( gEdge->geomType() != GEntity::CompoundCurve )
728 topoEdge = *((TopoDS_Edge*)gEdge->getNativePtr());
729 if (gEdge->getVisibility() == 0) // belongs to a compound
731 SMESH_subMesh* sm = _mesh->GetSubMesh(topoEdge);
732 sm->SetIsAlwaysComputed(true); // prevent from displaying errors
735 if ( HasSubMesh( topoEdge ))
736 continue; // a meshed sub-mesh
738 bool isCompound = getBoundsOfShapes( gEdge, topoEdges );
740 // FILL SMESH FOR topoEdge
742 for ( size_t i = 0; i < gEdge->mesh_vertices.size(); i++ )
744 MVertex *v = gEdge->mesh_vertices[i];
745 if ( v->getIndex() >= 0 )
747 SMDS_MeshNode *node = meshDS->AddNode( v->x(),v->y(),v->z() );
750 topoEdge = TopoDS::Edge( getShapeAtPoint( v->point(), topoEdges ));
752 // Based on BLSURFPlugin_BLSURF
753 gp_Pnt point3D( v->x(),v->y(),v->z() );
754 Standard_Real p0 = 0.0;
755 Standard_Real p1 = 1.0;
757 Handle(Geom_Curve) curve = BRep_Tool::Curve(topoEdge, loc, p0, p1);
759 if ( !curve.IsNull() )
761 if ( !loc.IsIdentity() )
762 point3D.Transform( loc.Transformation().Inverted() );
764 GeomAPI_ProjectPointOnCurve proj(point3D, curve, p0, p1);
767 if ( proj.NbPoints() > 0 )
768 pa = (double)proj.LowerDistanceParameter();
770 meshDS->SetNodeOnEdge( node, topoEdge, pa );
774 meshDS->SetNodeOnEdge( node, topoEdge );
776 //END on BLSURFPlugin_BLSURF
779 _nodeMap.insert({ v, node });
784 for ( GModel::eiter it = _gModel->firstEdge(); it != _gModel->lastEdge(); ++it )
787 if ( gEdge->getVisibility() == 0) // belongs to a compound
790 TopoDS_Edge topoEdge;
791 std::vector< ShapeBounds > topoEdges;
792 bool isCompound = getBoundsOfShapes( gEdge, topoEdges );
794 topoEdge = *((TopoDS_Edge*)gEdge->getNativePtr());
796 if ( HasSubMesh( topoEdge ))
797 continue; // a meshed sub-mesh
800 std::vector<MVertex*> verts(3);
801 for ( size_t i = 0; i < gEdge->getNumMeshElements(); i++ )
803 MElement *e = gEdge->getMeshElement(i);
805 e->getVertices(verts);
807 // if a node wasn't set, it is assigned here
808 for ( size_t j = 0; j < verts.size(); j++ )
810 if ( verts[j]->onWhat()->getVisibility() == 0 )
812 SMDS_MeshNode *node = meshDS->AddNode(verts[j]->x(),verts[j]->y(),verts[j]->z() );
814 gp_Pnt point3D( verts[j]->x(),verts[j]->y(),verts[j]->z() );
815 Standard_Real p0 = 0.0;
816 Standard_Real p1 = 1.0;
818 Handle(Geom_Curve) curve = BRep_Tool::Curve(topoEdge, loc, p0, p1);
820 if ( !curve.IsNull() )
822 if ( !loc.IsIdentity() )
823 point3D.Transform( loc.Transformation().Inverted() );
825 GeomAPI_ProjectPointOnCurve proj(point3D, curve, p0, p1);
828 if ( proj.NbPoints() > 0 )
829 pa = (double)proj.LowerDistanceParameter();
831 meshDS->SetNodeOnEdge( node, topoEdge, pa );
835 meshDS->SetNodeOnEdge( node, topoEdge );
838 verts[j]->setEntity(gEdge);
839 _nodeMap.insert({ verts[j], node });
843 SMDS_MeshEdge* edge = 0;
844 switch (verts.size())
847 edge = meshDS->AddEdge(Node( verts[0]),
851 edge = meshDS->AddEdge(Node( verts[0]),
860 topoEdge = TopoDS::Edge( getShapeAtPoint( e->barycenter(), topoEdges ));
862 meshDS->SetMeshElementOnShape( edge, topoEdge );
867 for ( GModel::fiter it = _gModel->firstFace(); it != _gModel->lastFace(); ++it)
871 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
872 // Gmsh since version 4.3 is now producing extra surface and mesh when
873 // compounds are involved. Since in Gmsh meshing procedure needs acess
874 // to each of the original topology and the meshed topology. Hence we
875 // bypass the additional mesh in case of compounds. Note, similar cri-
876 // teria also occurs in the following 'for' loop.
877 if ( _compounds.size() && gFace->geomType() == GEntity::DiscreteSurface )
881 // GET topoFace CORRESPONDING TO gFace
882 TopoDS_Face topoFace;
883 std::vector< ShapeBounds > topoFaces;
885 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
886 if(gFace->haveParametrization())
888 if ( gFace->geomType() != GEntity::CompoundSurface )
891 topoFace = *((TopoDS_Face*)gFace->getNativePtr());
892 if (gFace->getVisibility() == 0) // belongs to a compound
894 SMESH_subMesh* sm = _mesh->GetSubMesh(topoFace);
895 sm->SetIsAlwaysComputed(true); // prevent from displaying errors
898 if ( HasSubMesh( topoFace ))
899 continue; // a meshed sub-mesh
901 bool isCompound = getBoundsOfShapes( gFace, topoFaces );
903 // FILL SMESH FOR topoFace
905 for ( size_t i = 0; i < gFace->mesh_vertices.size(); i++ )
907 MVertex *v = gFace->mesh_vertices[i];
908 if ( v->getIndex() >= 0 )
910 SMDS_MeshNode *node = meshDS->AddNode( v->x(),v->y(),v->z() );
913 topoFace = TopoDS::Face( getShapeAtPoint( v->point(), topoFaces ));
915 meshDS->SetNodeOnFace( node, topoFace );
916 _nodeMap.insert({ v, node });
921 for ( GModel::fiter it = _gModel->firstFace(); it != _gModel->lastFace(); ++it)
925 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
926 if ( _compounds.size() && gFace->geomType() == GEntity::DiscreteSurface )
929 bool isCompound = (!gFace->haveParametrization());
931 bool isCompound = ( gFace->geomType() == GEntity::CompoundSurface );
934 if ( !isCompound && gFace->getVisibility() == 0 )
935 continue; // belongs to a compound
937 TopoDS_Face topoFace;
938 std::vector< ShapeBounds > topoFaces;
940 getBoundsOfShapes( gFace, topoFaces );
942 topoFace = *((TopoDS_Face*)gFace->getNativePtr());
944 if ( HasSubMesh( topoFace ))
945 continue; // a meshed sub-mesh
948 std::vector<MVertex*> verts;
949 for ( size_t i = 0; i < gFace->getNumMeshElements(); i++ )
951 MElement *e = gFace->getMeshElement(i);
953 e->getVertices(verts);
954 SMDS_MeshFace* face = 0;
956 // if a node wasn't set, it is assigned here
957 for ( size_t j = 0; j < verts.size(); j++)
959 if(verts[j]->onWhat()->getVisibility() == 0)
961 SMDS_MeshNode *node = meshDS->AddNode(verts[j]->x(),verts[j]->y(),verts[j]->z());
962 meshDS->SetNodeOnFace( node, topoFace );
963 _nodeMap.insert({ verts[j], node });
964 verts[j]->setEntity(gFace);
967 switch (verts.size())
970 face = meshDS->AddFace(Node( verts[0]),
975 face = meshDS->AddFace(Node( verts[0]),
981 face = meshDS->AddFace(Node( verts[0]),
989 face = meshDS->AddFace(Node( verts[0]),
999 face = meshDS->AddFace(Node( verts[0]),
1015 topoFace = TopoDS::Face( getShapeAtPoint( e->barycenter(), topoFaces ));
1017 meshDS->SetMeshElementOnShape(face, topoFace);
1022 for ( GModel::riter it = _gModel->firstRegion(); it != _gModel->lastRegion(); ++it)
1024 GRegion *gRegion = *it;
1025 if (gRegion->getVisibility() == 0)
1028 // GET topoSolid CORRESPONDING TO gRegion
1029 TopoDS_Solid topoSolid = *((TopoDS_Solid*)gRegion->getNativePtr());
1031 // FILL SMESH FOR topoSolid
1034 for( size_t i = 0; i < gRegion->mesh_vertices.size(); i++)
1036 MVertex *v = gRegion->mesh_vertices[i];
1037 if(v->getIndex() >= 0)
1039 SMDS_MeshNode *node = meshDS->AddNode( v->x(),v->y(),v->z() );
1040 meshDS->SetNodeInVolume( node, topoSolid );
1041 _nodeMap.insert({ v, node });
1046 std::vector<MVertex*> verts;
1047 for( size_t i = 0; i < gRegion->getNumMeshElements(); i++)
1049 MElement *e = gRegion->getMeshElement(i);
1051 e->getVertices(verts);
1052 SMDS_MeshVolume* volume = 0;
1053 switch (verts.size()){
1055 volume = meshDS->AddVolume(Node( verts[0]),
1061 volume = meshDS->AddVolume(Node( verts[0]),
1068 volume = meshDS->AddVolume(Node( verts[0]),
1076 volume = meshDS->AddVolume(Node( verts[0]),
1086 volume = meshDS->AddVolume(Node( verts[0]),
1098 volume = meshDS->AddVolume(Node( verts[0] ),
1112 case 14: // same as case 13, because no pyra14 in smesh
1113 volume = meshDS->AddVolume(Node( verts[0] ),
1128 volume = meshDS->AddVolume(Node( verts[0] ),
1144 case 18: // same as case 15, because no penta18 in smesh
1145 volume = meshDS->AddVolume(Node( verts[0] ),
1162 volume = meshDS->AddVolume(Node( verts[0] ),
1184 volume = meshDS->AddVolume(Node( verts[0] ),
1216 meshDS->SetMeshElementOnShape(volume, topoSolid);
1223 //================================================================================
1225 * \brief Find if SPoint point is in SBoundingBox3d bounds
1227 //================================================================================
1229 float GMSHPlugin_Mesher::DistBoundingBox(const SBoundingBox3d& bounds, const SPoint3& point)
1231 SPoint3 min = bounds.min();
1232 SPoint3 max = bounds.max();
1236 if (point.x() < min.x())
1237 x = min.x()-point.x();
1238 else if (point.x() > max.x())
1239 x = point.x()-max.x();
1243 if (point.y() < min.y())
1244 y = min.y()-point.y();
1245 else if (point.y() > max.y())
1246 y = point.y()-max.y();
1250 if (point.z() < min.z())
1251 z = min.z()-point.z();
1252 else if (point.z() > max.z())
1253 z = point.z()-max.z();
1259 //================================================================================
1261 * \brief Reimplemented GmshMessage call. Actions done if errors occurs
1262 * during gmsh meshing. We define here what to display and what to do.
1264 //================================================================================
1265 void GMSHPlugin_Mesher::mymsg::operator()(std::string level, std::string msg)
1267 //MESSAGE("level="<< level.c_str() << ", msg=" << msg.c_str()<< "\n");
1268 printf("level=%s msg=%s\n", level.c_str(), msg.c_str());
1270 if(level == "Fatal" || level == "Error")
1272 std::ostringstream oss;
1273 if (level == "Fatal")
1274 oss << "Fatal error during Generation of Gmsh Mesh\n";
1276 oss << "Error during Generation of Gmsh Mesh\n";
1277 oss << " " << msg.c_str() << "\n";
1278 GEntity *e = _gModel->getCurrentMeshEntity();
1281 oss << " error occurred while meshing entity:\n" <<
1282 " tag=" << e->tag() << "\n" <<
1283 " dimension=" << e->dim() << "\n" <<
1284 " native pointer=" << e->getNativePtr();
1285 //if(e->geomType() != GEntity::CompoundCurve and e->geomType() != GEntity::CompoundSurface)
1287 //SMESH_subMesh *sm = _mesh->GetSubMesh(*((TopoDS_Shape*)e->getNativePtr()));
1288 //SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
1289 //SMESH_Comment comment;
1290 //comment << SMESH_Comment(oss.str);
1291 //std::string str = oss.str();
1292 //smError.reset( new SMESH_ComputeError( str ));
1294 // plutot que de faire de la merde ici, on pourait simplement
1295 // remplir une liste pour dire sur quelles entités gmsh se plante
1296 // (puis faire le fillsmesh)
1297 // puis faire une nouvelle routine qui réécrit les messages d'erreur
1298 // probleme : gmsh peut planté en Fatal, dans ce cas pas de fillsmesh
1301 if (level == "Fatal")
1303 CTX::instance()->lock = 0;
1307 printf("%s\n", oss.str().c_str());
1311 //=============================================================================
1313 * Here we are going to use the GMSH mesher
1315 //=============================================================================
1317 bool GMSHPlugin_Mesher::Compute()
1319 MESSAGE("GMSHPlugin_Mesher::Compute");
1323 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
1324 SetMaxThreadsGmsh();
1326 //RNV: to avoid modification of PATH and PYTHONPATH
1327 char* argv[] = {"-noenv"};
1328 GmshInitialize(1,argv);
1330 _gModel = new GModel();
1332 GmshSetMessageHandler(&msg);
1333 _gModel->importOCCShape((void*)&_shape);
1334 if (_compounds.size() > 0) CreateGmshCompounds();
1338 HideComputedEntities(_gModel);
1343 Set2DSubMeshes(_gModel);
1345 _gModel->mesh( /*dim=*/ 3);
1349 //CTX::instance()->mesh.maxNumThreads1D=1;
1351 _gModel->mesh( /*dim=*/ 1);
1353 Set1DSubMeshes(_gModel);
1355 //_gModel->writeUNV("/tmp/1D.unv", 1,0,0);
1356 //CTX::instance()->mesh.maxNumThreads2D=1;
1358 _gModel->mesh( /*dim=*/ 2);
1362 Set2DSubMeshes(_gModel);
1364 //CTX::instance()->mesh.maxNumThreads3D=1;
1366 _gModel->mesh( /*dim=*/ 3);
1368 RestoreVisibility(_gModel);
1370 #ifdef WITH_SMESH_CANCEL_COMPUTE
1374 catch (std::string& str)
1377 std::cerr << "GMSH: exception caught: " << str << std::endl;
1383 std::cerr << "GMSH: Unknown exception caught: " << std::endl;
1384 MESSAGE("Unrecoverable error during Generation of Gmsh Mesh");
1389 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
1390 if (_compounds.size() > 0)
1391 SetCompoundMeshVisibility();
1395 GmshSetMessageHandler(nullptr);
1398 MESSAGE("GMSHPlugin_Mesher::Compute:End");
1402 //================================================================================
1404 * \brief Set 1D sub-meshes to GModel. GMSH 1D mesh is made by now.
1405 * \param [inout] _gModel - GMSH model
1407 //================================================================================
1409 void GMSHPlugin_Mesher::Set1DSubMeshes( GModel* gModel )
1411 SMESHDS_Mesh* meshDS = _mesh->GetMeshDS();
1413 for(GModel::eiter it = gModel->firstEdge(); it != gModel->lastEdge(); ++it)
1417 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
1418 if ( !gEdge->haveParametrization())
1420 if ( gEdge->geomType() == GEntity::CompoundCurve )
1424 TopoDS_Edge topoEdge = *((TopoDS_Edge*)gEdge->getNativePtr());
1425 if ( !HasSubMesh( topoEdge ))
1426 continue; // empty sub-mesh
1428 gEdge->deleteMesh();
1430 // get node parameters on topoEdge
1431 StdMeshers_FaceSide side( TopoDS_Face(), topoEdge, _mesh, /*fwd=*/true, /*skpMedium=*/true);
1432 const UVPtStructVec& nodeParam = side.GetUVPtStruct();
1433 if ( nodeParam.empty() )
1434 throw std::string("Pb with StdMeshers_FaceSide::GetUVPtStruct()");
1436 // get GMSH mesh vertices on VERTEX'es
1437 std::vector<MVertex *> mVertices( nodeParam.size(), nullptr );
1438 GVertex * gV0 = gEdge->getBeginVertex(), *gV1 = gEdge->getEndVertex();
1439 mVertices[0] = gV0->mesh_vertices[ 0 ];
1440 mVertices.back() = gV1->mesh_vertices[ 0 ];
1441 TopoDS_Vertex v01 = *((TopoDS_Vertex*) gV0->getNativePtr());
1442 TopoDS_Shape v02 = SMESH_MesherHelper::GetSubShapeByNode( nodeParam[0].node, meshDS );
1443 bool reverse = !v01.IsSame( v02 );
1444 if ( mVertices[0] == mVertices.back() )
1445 reverse = ( nodeParam[0].param > nodeParam.back().param );
1446 const SMDS_MeshNode* n0 = reverse ? nodeParam.back().node : nodeParam[0].node;
1447 const SMDS_MeshNode* n1 = reverse ? nodeParam[0].node : nodeParam.back().node;
1448 _nodeMap.insert({ mVertices[ 0 ], n0 });
1449 _nodeMap.insert({ mVertices.back(), n1 });
1451 // create GMSH mesh vertices on gEdge
1452 for ( size_t i = 1; i < nodeParam.size() - 1; ++i )
1454 size_t iN = reverse ? ( nodeParam.size() - 1 - i ) : i;
1455 SMESH_NodeXYZ xyz = nodeParam[ iN ].node;
1456 double lc = segmentSize( nodeParam, iN );
1457 // SVector3 der = gEdge->firstDer(nodeParam[ iN ].param);
1458 // double lc = norm(der) / segmentSize( nodeParam, i );
1460 mVertices[ i ] = new MEdgeVertex( xyz.X(), xyz.Y(), xyz.Z(),
1461 gEdge, nodeParam[ iN ].param, 0, lc);
1462 gEdge->mesh_vertices.push_back( mVertices[ i ]);
1463 _nodeMap.insert({ mVertices[ i ], nodeParam[ iN ].node });
1465 // create GMSH mesh edges
1466 for ( size_t i = 1; i < mVertices.size(); ++i )
1468 gEdge->lines.push_back( new MLine( mVertices[ i - 1 ],
1472 cout << endl << "EDGE " << gEdge->tag() <<
1473 ( topoEdge.Orientation() == TopAbs_FORWARD ? " F" : " R") << endl;
1474 MVertex* mv = gV0->mesh_vertices[ 0 ];
1475 cout << "V0: " << mv->x() << ", " << mv->y() << ", " << mv->z() << ", "<<endl;
1476 for ( size_t i = 0; i < gEdge->mesh_vertices.size(); ++i )
1478 MEdgeVertex* mv = (MEdgeVertex*) gEdge->mesh_vertices[i];
1479 cout << i << ": " << mv->x() << ", " << mv->y() << ", " << mv->z() << ", ";
1481 mv->getParameter(0, t );
1482 cout << ":\t t = "<< t << " lc = " << mv->getLc() << endl;
1484 mv = gV1->mesh_vertices[ 0 ];
1485 cout << "V1: " << mv->x() << ", " << mv->y() << ", " << mv->z() << ", "<<endl;
1491 //================================================================================
1493 * \brief Set 2D sub-meshes to GModel. GMSH 2D mesh is made by now.
1494 * \param [inout] _gModel - GMSH model
1496 //================================================================================
1498 void GMSHPlugin_Mesher::Set2DSubMeshes( GModel* gModel )
1500 if ( _nodeMap.empty() )
1501 return; // no sub-meshes
1503 SMESH_MesherHelper helper( *_mesh );
1505 std::map< const SMDS_MeshNode* , const MVertex * > nodes2mvertMap;
1506 for ( auto & v2n : _nodeMap )
1507 nodes2mvertMap.insert({ v2n.second, v2n.first });
1509 std::vector<MVertex *> mVertices;
1511 for(GModel::fiter it = gModel->firstFace(); it != gModel->lastFace(); ++it)
1515 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
1516 if ( !gFace->haveParametrization())
1518 if ( gFace->geomType() == GEntity::CompoundSurface )
1522 TopoDS_Face topoFace = *((TopoDS_Face*)gFace->getNativePtr());
1523 SMESHDS_SubMesh* sm = HasSubMesh( topoFace );
1526 //_gModel->writeUNV("/tmp/befDEl.unv", 1,0,0);
1528 gFace->deleteMesh();
1530 bool reverse = false;
1531 if ( gFace->getRegion(0) )
1533 //GRegion * gRegion = gFace->getRegion(0);
1534 TopoDS_Shape topoSolid = *((TopoDS_Shape*)gFace->getNativePtr());
1535 TopAbs_Orientation faceOriInSolid = helper.GetSubShapeOri( topoSolid, topoFace );
1536 if ( faceOriInSolid >= 0 )
1538 helper.IsReversedSubMesh( TopoDS::Face( topoFace.Oriented( faceOriInSolid )));
1541 for ( SMDS_ElemIteratorPtr fIt = sm->GetElements(); fIt->more(); )
1543 const SMDS_MeshElement* f = fIt->next();
1545 int nbN = f->NbCornerNodes();
1547 throw std::string("Polygon sub-meshes not supported");
1549 mVertices.resize( nbN );
1550 for ( int i = 0; i < nbN; ++i )
1552 const SMDS_MeshNode* n = f->GetNode( i );
1553 MVertex * mv = nullptr;
1554 auto n2v = nodes2mvertMap.find( n );
1555 if ( n2v != nodes2mvertMap.end() )
1557 mv = const_cast< MVertex*>( n2v->second );
1561 if ( n->GetPosition()->GetDim() < 2 )
1562 throw std::string("Wrong mapping of edge nodes to GMSH nodes");
1563 SMESH_NodeXYZ xyz = n;
1565 gp_XY uv = helper.GetNodeUV( topoFace, n, nullptr, &ok );
1566 mv = new MFaceVertex( xyz.X(), xyz.Y(), xyz.Z(), gFace, uv.X(), uv.Y() );
1567 gFace->mesh_vertices.push_back( mv );
1568 nodes2mvertMap.insert({ n, mv });
1569 _nodeMap.insert ({ mv, n });
1571 mVertices[ i ] = mv;
1573 // create GMSH mesh faces
1577 gFace->triangles.push_back (new MTriangle(mVertices[0], mVertices[2], mVertices[1]));
1579 gFace->triangles.push_back (new MTriangle(mVertices[0], mVertices[1], mVertices[2]));
1583 gFace->quadrangles.push_back (new MQuadrangle(mVertices[0], mVertices[3],
1584 mVertices[2], mVertices[1]));
1586 gFace->quadrangles.push_back (new MQuadrangle(mVertices[0], mVertices[1],
1587 mVertices[2], mVertices[3]));
1592 } // loop on GMSH faces
1597 //================================================================================
1599 * \brief Set visibility 0 to already computed geom entities
1600 * to prevent their meshing
1602 //================================================================================
1604 void GMSHPlugin_Mesher::HideComputedEntities( GModel* gModel )
1606 CTX::instance()->mesh.meshOnlyVisible = true;
1608 for(GModel::eiter it = gModel->firstEdge(); it != gModel->lastEdge(); ++it)
1612 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
1613 if ( !gEdge->haveParametrization())
1615 if ( gEdge->geomType() == GEntity::CompoundCurve )
1619 TopoDS_Edge topoEdge = *((TopoDS_Edge*)gEdge->getNativePtr());
1620 if ( HasSubMesh( topoEdge ))
1621 gEdge->setVisibility(0);
1625 for(GModel::fiter it = gModel->firstFace(); it != gModel->lastFace(); ++it)
1629 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
1630 if ( !gFace->haveParametrization())
1632 if ( gFace->geomType() == GEntity::CompoundSurface )
1636 TopoDS_Face topoFace = *((TopoDS_Face*)gFace->getNativePtr());
1637 if ( HasSubMesh( topoFace ))
1638 gFace->setVisibility(0);
1642 //================================================================================
1644 * \brief Restore visibility of all geom entities
1646 //================================================================================
1648 void GMSHPlugin_Mesher::RestoreVisibility( GModel* gModel )
1650 for(GModel::eiter it = gModel->firstEdge(); it != gModel->lastEdge(); ++it)
1653 gEdge->setVisibility(1);
1655 for(GModel::fiter it = gModel->firstFace(); it != gModel->lastFace(); ++it)
1658 gFace->setVisibility(1);
1663 void GMSHPlugin_Mesher::toPython( GModel* )
1665 const char* pyFile = "/tmp/gMesh.py";
1666 ofstream outfile( pyFile, ios::out );
1667 if ( !outfile ) return;
1669 outfile << "import salome, SMESH" << std::endl
1670 << "from salome.smesh import smeshBuilder" << std::endl
1671 << "smesh = smeshBuilder.New()" << std::endl
1672 << "mesh = smesh.Mesh()" << std::endl << std::endl;
1674 outfile << "## VERTICES" << endl;
1675 for ( GModel::viter it = _gModel->firstVertex(); it != _gModel->lastVertex(); ++it)
1677 GVertex *gVertex = *it;
1679 for(unsigned int i = 0; i < gVertex->mesh_vertices.size(); i++)
1681 MVertex *v = gVertex->mesh_vertices[i];
1682 if ( v->getIndex() >= 0)
1684 outfile << "n" << v->getNum() << " = mesh.AddNode("
1685 << v->x() << ", " << v->y() << ", " << v->z()<< ")"
1686 << " ## tag = " << gVertex->tag() << endl;
1691 for(GModel::eiter it = _gModel->firstEdge(); it != _gModel->lastEdge(); ++it)
1694 outfile << "## GEdge " << gEdge->tag() << endl;
1696 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
1697 if(gEdge->haveParametrization())
1699 if ( gEdge->geomType() != GEntity::CompoundCurve )
1701 for ( size_t i = 0; i < gEdge->mesh_vertices.size(); i++ )
1703 MVertex *v = gEdge->mesh_vertices[i];
1704 if ( v->getIndex() >= 0 )
1706 outfile << "n" << v->getNum() << " = mesh.AddNode("
1707 << v->x() << ", " << v->y() << ", " << v->z()<< ")"
1708 << " ## tag = " << gEdge->tag() << endl;
1713 for ( GModel::fiter it = _gModel->firstFace(); it != _gModel->lastFace(); ++it)
1716 if ( _compounds.size() && gFace->geomType() == GEntity::DiscreteSurface )
1718 outfile << "## GFace " << gFace->tag() << endl;
1720 for ( size_t i = 0; i < gFace->mesh_vertices.size(); i++ )
1722 MVertex *v = gFace->mesh_vertices[i];
1723 if ( v->getIndex() >= 0 )
1725 outfile << "n" << v->getNum() << " = mesh.AddNode("
1726 << v->x() << ", " << v->y() << ", " << v->z()<< ")"
1727 << " ## tag = " << gFace->tag() << endl;
1732 std::vector<MVertex*> verts(3);
1733 for(GModel::eiter it = _gModel->firstEdge(); it != _gModel->lastEdge(); ++it)
1736 outfile << "## GEdge " << gEdge->tag() << endl;
1738 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
1739 if(gEdge->haveParametrization())
1741 if ( gEdge->geomType() != GEntity::CompoundCurve )
1743 for ( size_t i = 0; i < gEdge->getNumMeshElements(); i++ )
1745 MElement *e = gEdge->getMeshElement(i);
1747 e->getVertices(verts);
1749 outfile << "e" << e->getNum() << " = mesh.AddEdge(["
1750 << "n" << verts[0]->getNum() << ","
1751 << "n" << verts[1]->getNum();
1752 if ( verts.size() == 3 )
1753 outfile << "n" << verts[2]->getNum();
1754 outfile << "])"<< endl;
1758 for ( GModel::fiter it = _gModel->firstFace(); it != _gModel->lastFace(); ++it)
1761 if ( _compounds.size() && gFace->geomType() == GEntity::DiscreteSurface )
1763 outfile << "## GFace " << gFace->tag() << endl;
1765 for ( size_t i = 0; i < gFace->getNumMeshElements(); i++ )
1767 MElement *e = gFace->getMeshElement(i);
1769 e->getVertices(verts);
1771 outfile << "f" << e->getNum() << " = mesh.AddFace([";
1772 for ( size_t j = 0; j < verts.size(); j++)
1774 outfile << "n" << verts[j]->getNum();
1775 if ( j < verts.size()-1 )
1778 outfile << "])" << endl;
1781 std::cout << "Write " << pyFile << std::endl;