1 //=============================================================================
2 // File : NETGENPlugin_NETGEN_3D.cxx
3 // Moved here from SMESH_NETGEN_3D.cxx
4 // Created : lundi 27 Janvier 2003
5 // Author : Nadir BOUHAMOU (CEA)
7 // Copyright : CEA 2003
9 //=============================================================================
12 #include "NETGENPlugin_NETGEN_3D.hxx"
14 #include "SMESH_Gen.hxx"
15 #include "SMESH_Mesh.hxx"
16 #include "SMESH_ControlsDef.hxx"
17 #include "SMESHDS_Mesh.hxx"
18 #include "SMDS_MeshElement.hxx"
19 #include "SMDS_MeshNode.hxx"
22 #include <TopExp_Explorer.hxx>
24 #include <TopoDS_Shell.hxx>
25 #include <BRepTools.hxx>
27 #include "utilities.h"
39 //=============================================================================
43 //=============================================================================
45 NETGENPlugin_NETGEN_3D::NETGENPlugin_NETGEN_3D(int hypId, int studyId,
47 : SMESH_3D_Algo(hypId, studyId, gen)
49 MESSAGE("NETGENPlugin_NETGEN_3D::NETGENPlugin_NETGEN_3D");
51 // _shapeType = TopAbs_SOLID;
52 _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);// 1 bit /shape type
53 // MESSAGE("_shapeType octal " << oct << _shapeType);
54 _compatibleHypothesis.push_back("MaxElementVolume");
56 _maxElementVolume = 0.;
58 _hypMaxElementVolume = NULL;
61 //=============================================================================
65 //=============================================================================
67 NETGENPlugin_NETGEN_3D::~NETGENPlugin_NETGEN_3D()
69 MESSAGE("NETGENPlugin_NETGEN_3D::~NETGENPlugin_NETGEN_3D");
72 //=============================================================================
76 //=============================================================================
78 bool NETGENPlugin_NETGEN_3D::CheckHypothesis
80 const TopoDS_Shape& aShape,
81 SMESH_Hypothesis::Hypothesis_Status& aStatus)
83 MESSAGE("NETGENPlugin_NETGEN_3D::CheckHypothesis");
85 _hypMaxElementVolume = NULL;
86 _maxElementVolume = DBL_MAX;
88 list<const SMESHDS_Hypothesis*>::const_iterator itl;
89 const SMESHDS_Hypothesis* theHyp;
91 const list<const SMESHDS_Hypothesis*>& hyps = GetUsedHypothesis(aMesh, aShape);
92 int nbHyp = hyps.size();
95 aStatus = SMESH_Hypothesis::HYP_OK;
96 //aStatus = SMESH_Hypothesis::HYP_MISSING;
97 return true; // can work with no hypothesis
101 theHyp = (*itl); // use only the first hypothesis
103 string hypName = theHyp->GetName();
107 if (hypName == "MaxElementVolume")
109 _hypMaxElementVolume = static_cast<const StdMeshers_MaxElementVolume*> (theHyp);
110 ASSERT(_hypMaxElementVolume);
111 _maxElementVolume = _hypMaxElementVolume->GetMaxVolume();
113 aStatus = SMESH_Hypothesis::HYP_OK;
116 aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
121 //=============================================================================
123 *Here we are going to use the NETGEN mesher
125 //=============================================================================
127 bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh& aMesh,
128 const TopoDS_Shape& aShape)
130 MESSAGE("NETGENPlugin_NETGEN_3D::Compute with maxElmentsize = " << _maxElementVolume);
132 SMESHDS_Mesh* meshDS = aMesh.GetMeshDS();
134 // get a shell from aShape
136 if ( aShape.ShapeType() == TopAbs_SOLID ) {
137 aShell = BRepTools::OuterShell( TopoDS::Solid( aShape ));
140 TopExp_Explorer exp(aShape,TopAbs_SHELL);
142 aShell = TopoDS::Shell(exp.Current());
145 if ( aShell.IsNull() || !aMesh.GetSubMesh( aShell )) {
146 INFOS( "NETGENPlugin_NETGEN_3D::Compute(), bad shape");
149 // -------------------------------------------------------------------
150 // get triangles on aShell and make a map of nodes to Netgen node IDs
151 // -------------------------------------------------------------------
153 typedef map< const SMDS_MeshNode*, int> TNodeToIDMap;
154 TNodeToIDMap nodeToNetgenID;
155 list< const SMDS_MeshElement* > triangles;
156 list< bool > isReversed; // orientation of triangles
158 SMESH::Controls::Area areaControl;
159 SMESH::Controls::TSequenceOfXYZ nodesCoords;
161 for (TopExp_Explorer exp(aShape,TopAbs_FACE);exp.More();exp.Next())
163 const TopoDS_Shape& aShapeFace = exp.Current();
164 const SMESHDS_SubMesh * aSubMeshDSFace = meshDS->MeshElements( aShapeFace );
165 if ( aSubMeshDSFace )
167 bool isRev = SMESH_Algo::IsReversedSubMesh( TopoDS::Face(aShapeFace), meshDS );
169 SMDS_ElemIteratorPtr iteratorElem = aSubMeshDSFace->GetElements();
170 while ( iteratorElem->more() ) // loop on elements on a face
173 const SMDS_MeshElement* elem = iteratorElem->next();
174 if ( !elem || elem->NbNodes() != 3 ) {
175 INFOS( "NETGENPlugin_NETGEN_3D::Compute(), bad mesh");
179 triangles.push_back( elem );
180 isReversed.push_back( isRev );
181 // put elem nodes to nodeToNetgenID map
182 SMDS_ElemIteratorPtr triangleNodesIt = elem->nodesIterator();
183 while ( triangleNodesIt->more() ) {
184 const SMDS_MeshNode * node =
185 static_cast<const SMDS_MeshNode *>(triangleNodesIt->next());
186 nodeToNetgenID.insert( make_pair( node, 0 ));
189 // check if a trainge is degenerated
190 areaControl.GetPoints( elem, nodesCoords );
191 double area = areaControl.GetValue( nodesCoords );
192 if ( area <= DBL_MIN ) {
193 MESSAGE( "Warning: Degenerated " << elem );
199 // ---------------------------------
200 // Feed the Netgen with surface mesh
201 // ---------------------------------
203 int Netgen_NbOfNodes = nodeToNetgenID.size();
204 int Netgen_param2ndOrder = 0;
205 double Netgen_paramFine = 1.;
206 double Netgen_paramSize = _maxElementVolume;
208 double Netgen_point[3];
209 int Netgen_triangle[3];
210 int Netgen_tetrahedron[4];
214 Ng_Mesh * Netgen_mesh = Ng_NewMesh();
216 // set nodes and remember thier netgen IDs
217 TNodeToIDMap::iterator n_id = nodeToNetgenID.begin();
218 for ( int id = 0; n_id != nodeToNetgenID.end(); ++n_id )
220 const SMDS_MeshNode* node = n_id->first;
221 Netgen_point [ 0 ] = node->X();
222 Netgen_point [ 1 ] = node->Y();
223 Netgen_point [ 2 ] = node->Z();
225 Ng_AddPoint(Netgen_mesh, Netgen_point);
228 list< const SMDS_MeshElement* >::iterator tria = triangles.begin();
229 list< bool >::iterator reverse = isReversed.begin();
230 for ( ; tria != triangles.end(); ++tria, ++reverse )
233 SMDS_ElemIteratorPtr triangleNodesIt = (*tria)->nodesIterator();
234 while ( triangleNodesIt->more() ) {
235 const SMDS_MeshNode * node =
236 static_cast<const SMDS_MeshNode *>(triangleNodesIt->next());
237 Netgen_triangle[ *reverse ? 2 - i : i ] = nodeToNetgenID[ node ];
240 Ng_AddSurfaceElement(Netgen_mesh, NG_TRIG, Netgen_triangle);
243 // -------------------------
244 // Generate the volume mesh
245 // -------------------------
247 Ng_Meshing_Parameters Netgen_param;
249 Netgen_param.secondorder = Netgen_param2ndOrder;
250 Netgen_param.fineness = Netgen_paramFine;
251 Netgen_param.maxh = Netgen_paramSize;
256 status = Ng_GenerateVolumeMesh(Netgen_mesh, &Netgen_param);
258 MESSAGE("An exception has been caught during the Volume Mesh Generation ...");
259 status = NG_VOLUME_FAILURE;
262 int Netgen_NbOfNodesNew = Ng_GetNP(Netgen_mesh);
264 int Netgen_NbOfTetra = Ng_GetNE(Netgen_mesh);
266 MESSAGE("End of Volume Mesh Generation. status=" << status <<
267 ", nb new nodes: " << Netgen_NbOfNodesNew - Netgen_NbOfNodes <<
268 ", nb tetra: " << Netgen_NbOfTetra);
270 // -------------------------------------------------------------------
271 // Feed back the SMESHDS with the generated Nodes and Volume Elements
272 // -------------------------------------------------------------------
274 bool isOK = ( status == NG_OK && Netgen_NbOfTetra > 0 );
277 // vector of nodes in which node index == netgen ID
278 vector< const SMDS_MeshNode* > nodeVec ( Netgen_NbOfNodesNew + 1 );
279 // insert old nodes into nodeVec
280 for ( n_id = nodeToNetgenID.begin(); n_id != nodeToNetgenID.end(); ++n_id )
281 nodeVec[ n_id->second ] = n_id->first;
282 // create and insert new nodes into nodeVec
283 int nodeIndex = Netgen_NbOfNodes + 1;
284 for ( ; nodeIndex <= Netgen_NbOfNodesNew; ++nodeIndex )
286 Ng_GetPoint( Netgen_mesh, nodeIndex, Netgen_point );
287 SMDS_MeshNode * node = meshDS->AddNode(Netgen_point[0],
290 meshDS->SetNodeInVolume(node, aShell);
291 nodeVec[nodeIndex] = node;
294 // create tetrahedrons
295 for ( int elemIndex = 1; elemIndex <= Netgen_NbOfTetra; ++elemIndex )
297 Ng_GetVolumeElement(Netgen_mesh, elemIndex, Netgen_tetrahedron);
298 SMDS_MeshVolume * elt = meshDS->AddVolume (nodeVec[ Netgen_tetrahedron[0] ],
299 nodeVec[ Netgen_tetrahedron[1] ],
300 nodeVec[ Netgen_tetrahedron[2] ],
301 nodeVec[ Netgen_tetrahedron[3] ]);
302 meshDS->SetMeshElementOnShape(elt, aShell);
306 Ng_DeleteMesh(Netgen_mesh);
312 //=============================================================================
316 //=============================================================================
318 ostream & NETGENPlugin_NETGEN_3D::SaveTo(ostream & save)
323 //=============================================================================
327 //=============================================================================
329 istream & NETGENPlugin_NETGEN_3D::LoadFrom(istream & load)
334 //=============================================================================
338 //=============================================================================
340 ostream & operator << (ostream & save, NETGENPlugin_NETGEN_3D & hyp)
342 return hyp.SaveTo( save );
345 //=============================================================================
349 //=============================================================================
351 istream & operator >> (istream & load, NETGENPlugin_NETGEN_3D & hyp)
353 return hyp.LoadFrom( load );