1 //=============================================================================
2 // File : SMESH_NETGEN_3D.cxx
3 // Created : lundi 27 Janvier 2003
4 // Author : Nadir BOUHAMOU (CEA)
6 // Copyright : CEA 2003
8 //=============================================================================
11 #include "SMESH_NETGEN_3D.hxx"
12 #include "SMESH_MEFISTO_2D.hxx"
13 #include "SMESH_Gen.hxx"
14 #include "SMESH_Mesh.hxx"
16 #include "SMDS_MeshElement.hxx"
17 #include "SMDS_MeshNode.hxx"
18 #include "SMDS_FacePosition.hxx"
21 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
22 #include <TopTools_ListOfShape.hxx>
23 #include <TopTools_ListIteratorOfListOfShape.hxx>
24 #include <TColStd_ListIteratorOfListOfInteger.hxx>
26 #include <BRep_Tool.hxx>
27 #include <Geom_Surface.hxx>
28 #include <Geom_Curve.hxx>
29 #include <Geom2d_Curve.hxx>
31 #include "utilities.h"
39 //=============================================================================
43 //=============================================================================
45 SMESH_NETGEN_3D::SMESH_NETGEN_3D(int hypId, int studyId,
47 : SMESH_3D_Algo(hypId, studyId, gen)
49 MESSAGE("SMESH_NETGEN_3D::SMESH_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 SMESH_NETGEN_3D::~SMESH_NETGEN_3D()
69 MESSAGE("SMESH_NETGEN_3D::~SMESH_NETGEN_3D");
72 //=============================================================================
76 //=============================================================================
78 bool SMESH_NETGEN_3D::CheckHypothesis(SMESH_Mesh& aMesh,
79 const TopoDS_Shape& aShape)
81 MESSAGE("SMESH_NETGEN_3D::CheckHypothesis");
83 _hypMaxElementVolume = NULL;
85 list<const SMESHDS_Hypothesis*>::const_iterator itl;
86 const SMESHDS_Hypothesis* theHyp;
88 const list<const SMESHDS_Hypothesis*>& hyps = GetUsedHypothesis(aMesh, aShape);
89 int nbHyp = hyps.size();
90 if (nbHyp != 1) return false; // only one compatible hypothesis allowed
95 string hypName = theHyp->GetName();
96 int hypId = theHyp->GetID();
101 if (hypName == "MaxElementVolume")
103 _hypMaxElementVolume = static_cast<const SMESH_MaxElementVolume*> (theHyp);
104 ASSERT(_hypMaxElementVolume);
105 _maxElementVolume = _hypMaxElementVolume->GetMaxVolume();
112 //=============================================================================
114 *Here we are going to use the NETGEN mesher
116 //=============================================================================
118 bool SMESH_NETGEN_3D::Compute(SMESH_Mesh& aMesh,
119 const TopoDS_Shape& aShape)
120 throw (SALOME_Exception)
122 MESSAGE("SMESH_NETGEN_3D::Compute with maxElmentsize = " << _maxElementVolume);
125 SMESHDS_Mesh* meshDS = aMesh.GetMeshDS();
126 SMESH_subMesh* theSubMesh = aMesh.GetSubMesh(aShape);
127 //const Handle(SMESHDS_SubMesh)& subMeshDS = theSubMesh->GetSubMeshDS();
129 map<int, const SMDS_MeshNode*> netgenToDS;
131 MESSAGE("SMESH_NETGEN_3D::Compute Checking the mesh Faces");
133 // check if all faces were meshed by a triangle mesher (here MESFISTO_2D)
135 vector<SMESH_subMesh*> meshFaces;
136 vector<TopoDS_Shape> shapeFaces;
138 for (TopExp_Explorer exp(aShape,TopAbs_FACE);exp.More();exp.Next())
140 TopoDS_Shape aShapeFace = exp.Current();
141 SMESH_subMesh* aSubMesh = aMesh.GetSubMeshContaining(exp.Current());
143 int internal_size = meshFaces.size();
145 for (int i = 0;i<internal_size;i++)
147 if (aSubMesh == meshFaces[i]) index = 1;
149 if (index == 0) meshFaces.push_back(aSubMesh);
151 internal_size = shapeFaces.size();
153 for (int i = 0;i<internal_size;i++)
155 if (aShapeFace == shapeFaces[i]) index = 1;
157 if (index == 0) shapeFaces.push_back(aShapeFace);
160 int numberOfFaces = meshFaces.size();
161 int numberOfShapeFaces = shapeFaces.size();
163 SCRUTE(numberOfFaces);
164 SCRUTE(numberOfShapeFaces);
169 int NbTotOfNodesFaces = 0;
171 for (int i=0; i<numberOfFaces; i++)
173 TopoDS_Shape aShapeFace = meshFaces[i]->GetSubShape();
174 TopoDS_Shape aFace = shapeFaces[i];
175 SMESH_Algo* algoFace = _gen->GetAlgo(aMesh, aShapeFace);
176 string algoFaceName = algoFace->GetName();
177 SCRUTE(algoFaceName);
178 if (algoFaceName != "MEFISTO_2D")
180 SCRUTE(algoFaceName);
185 bool orientationMeshFace = (aFace.Orientation() == aShapeFace.Orientation());
187 const SMESHDS_SubMesh* aSubMeshDSFace = meshFaces[i]->GetSubMeshDS();
188 SCRUTE(aSubMeshDSFace);
190 int nbNodes = aSubMeshDSFace->NbNodes();
191 NbTotOfNodesFaces += nbNodes;
192 int nbTria = aSubMeshDSFace->NbElements();
193 NbTotOfTria += nbTria;
196 MESSAGE("SMESH_NETGEN_3D::Compute The mesh Face " << (i+1) << " has " << nbNodes << " face internal Nodes, " << nbTria << " triangles");
198 SCRUTE(orientationMeshFace);
200 if (orientationMeshFace)
202 MESSAGE("The mesh and face have the same orientation");
206 MESSAGE("The mesh and face have different orientations");
209 SMDS_Iterator<const SMDS_MeshNode *> * iteratorNodes = aSubMeshDSFace->GetNodes();
212 while(iteratorNodes->more())
215 const SMDS_MeshNode * node = iteratorNodes->next();
216 // int nodeId = node->GetID();
217 // double nodeX = node->X();
218 // double nodeY = node->Y();
219 // double nodeZ = node->Z();
220 // MESSAGE("NODE -> ID = " << nodeId << " X = " << nodeX << " Y = " << nodeY << " Z = " << nodeZ);
222 delete iteratorNodes;
226 SMDS_Iterator<const SMDS_MeshElement *> * iteratorTriangle = aSubMeshDSFace->GetElements();
230 int numberOfDegeneratedTriangle = 0;
231 while(iteratorTriangle->more())
234 const SMDS_MeshElement * triangle = iteratorTriangle->next();
235 int triangleId = triangle->GetID();
237 SMDS_Iterator<const SMDS_MeshElement *> * triangleNodesIt = triangle->nodesIterator();
239 const SMDS_MeshNode * node1 = static_cast<const SMDS_MeshNode *>(triangleNodesIt->next());
240 double node1X = node1->X();
241 double node1Y = node1->Y();
242 double node1Z = node1->Z();
244 const SMDS_MeshNode * node2 = static_cast<const SMDS_MeshNode *>(triangleNodesIt->next());
245 double node2X = node2->X();
246 double node2Y = node2->Y();
247 double node2Z = node2->Z();
249 const SMDS_MeshNode * node3 = static_cast<const SMDS_MeshNode *>(triangleNodesIt->next());
250 double node3X = node3->X();
251 double node3Y = node3->Y();
252 double node3Z = node3->Z();
254 int triangleNode1 = node1->GetID();
255 int triangleNode2 = node2->GetID();
256 int triangleNode3 = node3->GetID();
258 // Compute the triangle surface
260 double vect1 = ((node2Y - node1Y)*(node3Z - node1Z) - (node2Z - node1Z)*(node3Y - node1Y));
261 double vect2 = - ((node2X - node1X)*(node3Z - node1Z) - (node2Z - node1Z)*(node3X - node1X));
262 double vect3 = ((node2X - node1X)*(node3Y - node1Y) - (node2Y - node1Y)*(node3X - node1X));
263 double epsilon = 1.0e-6;
265 bool triangleIsDegenerated = ((abs(vect1)<epsilon) && (abs(vect2)<epsilon) && (abs(vect3)<epsilon));
267 if (triangleIsDegenerated)
269 // MESSAGE("TRIANGLE -> ID = " << triangleId << " N1 = " << triangleNode1 << " N2 = " << triangleNode2 << " N3 = " << triangleNode3 << " is degenerated");
270 // MESSAGE("NODE -> ID = " << triangleNode1 << " X = " << node1X << " Y = " << node1Y << " Z = " << node1Z);
271 // MESSAGE("NODE -> ID = " << triangleNode2 << " X = " << node2X << " Y = " << node2Y << " Z = " << node2Z);
272 // MESSAGE("NODE -> ID = " << triangleNode3 << " X = " << node3X << " Y = " << node3Y << " Z = " << node3Z);
273 numberOfDegeneratedTriangle++;
277 // MESSAGE("TRIANGLE -> ID = " << triangleId << " N1 = " << triangleNode1 << " N2 = " << triangleNode2 << " N3 = " << triangleNode3 << " is normal");
281 delete iteratorTriangle;
283 if (numberOfDegeneratedTriangle > 0)
284 MESSAGE("WARNING THERE IS(ARE) " << numberOfDegeneratedTriangle << " degenerated triangle on this face");
292 SCRUTE(NbTotOfNodesFaces);
294 MESSAGE("SMESH_NETGEN_3D::Compute Checking the mesh Edges");
296 // check if all edges were meshed by a edge mesher (here Regular_1D)
298 vector<SMESH_subMesh*> meshEdges;
299 for (TopExp_Explorer exp(aShape,TopAbs_EDGE);exp.More();exp.Next())
301 SMESH_subMesh* aSubMesh = aMesh.GetSubMeshContaining(exp.Current());
303 int internal_size = meshEdges.size();
305 for (int i = 0;i<internal_size;i++)
307 if (aSubMesh == meshEdges[i]) index = 1;
309 if (index == 0) meshEdges.push_back(aSubMesh);
312 int numberOfEdges = meshEdges.size();
313 SCRUTE(numberOfEdges);
317 int NbTotOfNodesEdges = 0;
320 for (int i=0; i<numberOfEdges; i++)
322 TopoDS_Shape aShapeEdge = meshEdges[i]->GetSubShape();
323 SMESH_Algo* algoEdge = _gen->GetAlgo(aMesh, aShapeEdge);
324 string algoEdgeName = algoEdge->GetName();
325 SCRUTE(algoEdgeName);
326 if (algoEdgeName != "Regular_1D")
328 SCRUTE(algoEdgeName);
333 const SMESHDS_SubMesh* aSubMeshDSEdge = meshEdges[i]->GetSubMeshDS();
334 SCRUTE(aSubMeshDSEdge);
336 int nbNodes = aSubMeshDSEdge->NbNodes();
337 NbTotOfNodesEdges += nbNodes;
338 int nbSegs = aSubMeshDSEdge->NbElements();
339 NbTotOfSegs += nbSegs;
341 MESSAGE("SMESH_NETGEN_3D::Compute The mesh Edge " << (i+1) << " has " << nbNodes << " edge internal Nodes, " << nbSegs << " segments");
343 SMDS_Iterator<const SMDS_MeshNode *> * iteratorNodes = aSubMeshDSEdge->GetNodes();
346 while(iteratorNodes->more())
349 const SMDS_MeshNode * node = iteratorNodes->next();
350 // int nodeId = node->GetID();
351 // double nodeX = node->X();
352 // double nodeY = node->Y();
353 // double nodeZ = node->Z();
354 // MESSAGE("NODE -> ID = " << nodeId << " X = " << nodeX << " Y = " << nodeY << " Z = " << nodeZ);
356 delete iteratorNodes;
361 SCRUTE(NbTotOfNodesEdges);
364 MESSAGE("SMESH_NETGEN_3D::Compute Checking the mesh Vertices");
366 vector<SMESH_subMesh*> meshVertices;
367 for (TopExp_Explorer exp(aShape,TopAbs_VERTEX);exp.More();exp.Next())
369 SMESH_subMesh* aSubMesh = aMesh.GetSubMeshContaining(exp.Current());
371 int internal_size = meshVertices.size();
373 for (int i = 0;i<internal_size;i++)
375 if (aSubMesh == meshVertices[i]) index = 1;
377 if (index == 0) meshVertices.push_back(aSubMesh);
380 int numberOfVertices = meshVertices.size();
381 SCRUTE(numberOfVertices);
385 int NbTotOfNodesVertices = 0;
387 for (int i=0; i<numberOfVertices; i++)
389 TopoDS_Shape aShapeVertex = meshVertices[i]->GetSubShape();
391 const SMESHDS_SubMesh * aSubMeshDSVertex = meshVertices[i]->GetSubMeshDS();
392 SCRUTE(aSubMeshDSVertex);
394 int nbNodes = aSubMeshDSVertex->NbNodes();
395 NbTotOfNodesVertices += nbNodes;
397 MESSAGE("SMESH_NETGEN_3D::Compute The mesh Vertex " << (i+1) << " has " << nbNodes << " Nodes");
399 SMDS_Iterator<const SMDS_MeshNode *> * iteratorNodes = aSubMeshDSVertex->GetNodes();
402 while(iteratorNodes->more())
405 const SMDS_MeshNode * node = iteratorNodes->next();
406 // int nodeId = node->GetID();
407 // double nodeX = node->X();
408 // double nodeY = node->Y();
409 // double nodeZ = node->Z();
410 // MESSAGE("NODE -> ID = " << nodeId << " X = " << nodeX << " Y = " << nodeY << " Z = " << nodeZ);
412 delete iteratorNodes;
417 SCRUTE(NbTotOfNodesVertices);
419 MESSAGE("SMESH_NETGEN_3D::Compute --> Analysis of all shell mesh");
421 vector<SMESH_subMesh*> meshShells;
424 for (TopExp_Explorer exp(aShape,TopAbs_SHELL);exp.More();exp.Next())
426 SMESH_subMesh* aSubMesh = aMesh.GetSubMesh(exp.Current());
429 aShell = TopoDS::Shell(exp.Current());
430 meshShells.push_back(aSubMesh);
433 int numberOfShells = meshShells.size();
434 SCRUTE(numberOfShells);
436 if (numberOfShells == 1)
438 MESSAGE("SMESH_NETGEN_3D::Compute Only one shell --> generation of the mesh using directly Netgen");
441 Prepare the Netgen surface mesh from the SMESHDS
444 MESSAGE("SMESH_NETGEN_3D::Compute Prepare the Netgen surface mesh from the SMESHDS");
446 int spaceDimension = 3;
447 int nbNodesByTri = 3;
448 int nbNodesByTetra = 4;
450 int Netgen_NbOfNodes = NbTotOfNodesFaces +
452 NbTotOfNodesVertices;
453 int Netgen_NbOfTria = NbTotOfTria;
454 int Netgen_param2ndOrder = 0;
455 double Netgen_paramFine = 1.;
456 double Netgen_paramSize = _maxElementVolume;
458 SCRUTE(Netgen_NbOfNodes);
459 SCRUTE(Netgen_NbOfTria);
461 double * Netgen_Coordinates = new double [spaceDimension*
463 int * listNodeCoresNetgenSmesh = new int [Netgen_NbOfNodes];
464 int * Netgen_Connectivity = new int [nbNodesByTri*Netgen_NbOfTria];
465 double * Netgen_point = new double [spaceDimension];
466 int * Netgen_triangle = new int [nbNodesByTri];
467 int * Netgen_tetrahedron = new int [nbNodesByTetra];
469 for (int i=0; i<Netgen_NbOfTria; i++)
471 for (int j=0; j<nbNodesByTri; j++)
472 Netgen_Connectivity[i*nbNodesByTri+j] = 0;
475 double bigNumber = 1.e20;
477 for (int i=0; i<Netgen_NbOfNodes; i++)
479 listNodeCoresNetgenSmesh[i] = 0;
480 for (int j=0; j<spaceDimension; j++)
481 Netgen_Coordinates[i*spaceDimension+j] = bigNumber;
485 for (int i=0; i<numberOfVertices; i++)
487 const SMESHDS_SubMesh * aSubMeshDSVertex =
488 meshVertices[i]->GetSubMeshDS();
490 SMDS_Iterator<const SMDS_MeshNode *> * iteratorNodes = aSubMeshDSVertex->GetNodes();
492 while(iteratorNodes->more())
494 const SMDS_MeshNode * node = iteratorNodes->next();
495 int nodeId = node->GetID();
496 double nodeX = node->X();
497 double nodeY = node->Y();
498 double nodeZ = node->Z();
499 // MESSAGE("NODE -> ID = " << nodeId << " X = " << nodeX << " Y = " << nodeY << " Z = " << nodeZ);
500 listNodeCoresNetgenSmesh[indexNodes] = nodeId;
501 int index = indexNodes*spaceDimension;
502 Netgen_Coordinates[index] = nodeX;
503 Netgen_Coordinates[index+1] = nodeY;
504 Netgen_Coordinates[index+2] = nodeZ;
505 netgenToDS[indexNodes] = node;
508 delete iteratorNodes;
511 for (int i=0; i<numberOfEdges; i++)
513 const SMESHDS_SubMesh * aSubMeshDSEdge =
514 meshEdges[i]->GetSubMeshDS();
516 SMDS_Iterator<const SMDS_MeshNode *> * iteratorNodes = aSubMeshDSEdge->GetNodes();
518 while(iteratorNodes->more())
520 const SMDS_MeshNode * node = iteratorNodes->next();
521 int nodeId = node->GetID();
522 double nodeX = node->X();
523 double nodeY = node->Y();
524 double nodeZ = node->Z();
525 // MESSAGE("NODE -> ID = " << nodeId << " X = " << nodeX << " Y = " << nodeY << " Z = " << nodeZ);
526 listNodeCoresNetgenSmesh[indexNodes] = node->GetID();
527 int index = indexNodes*spaceDimension;
528 Netgen_Coordinates[index] = node->X();
529 Netgen_Coordinates[index+1] = node->Y();
530 Netgen_Coordinates[index+2] = node->Z();
531 netgenToDS[indexNodes] = node;
534 delete iteratorNodes;
537 for (int i=0; i<numberOfFaces; i++)
539 const SMESHDS_SubMesh * aSubMeshDSFace =
540 meshFaces[i]->GetSubMeshDS();
542 SMDS_Iterator<const SMDS_MeshNode *> * iteratorNodes = aSubMeshDSFace->GetNodes();
544 while(iteratorNodes->more())
546 const SMDS_MeshNode * node = iteratorNodes->next();
547 int nodeId = node->GetID();
548 double nodeX = node->X();
549 double nodeY = node->Y();
550 double nodeZ = node->Z();
551 // MESSAGE("NODE -> ID = " << nodeId << " X = " << nodeX << " Y = " << nodeY << " Z = " << nodeZ);
552 listNodeCoresNetgenSmesh[indexNodes] = nodeId;
553 int index = indexNodes*spaceDimension;
554 Netgen_Coordinates[index] = nodeX;
555 Netgen_Coordinates[index+1] = nodeY;
556 Netgen_Coordinates[index+2] = nodeZ;
557 netgenToDS[indexNodes] = node;
560 delete iteratorNodes;
565 for (int i=0; i<Netgen_NbOfNodes; i++)
567 ASSERT(listNodeCoresNetgenSmesh[i] != 0);
569 for (int j=0; j<Netgen_NbOfNodes && j!=i; j++)
570 ASSERT(listNodeCoresNetgenSmesh[i] != listNodeCoresNetgenSmesh[j]);
572 for (int j=0; j<spaceDimension; j++)
573 ASSERT(Netgen_Coordinates[i*spaceDimension+j] != bigNumber);
577 for (int i=0; i<numberOfFaces; i++)
579 const SMESHDS_SubMesh * aSubMeshDSFace =
580 meshFaces[i]->GetSubMeshDS();
582 TopoDS_Shape aFace = shapeFaces[i];
584 SMDS_Iterator<const SMDS_MeshElement *> * iteratorTriangle = aSubMeshDSFace->GetElements();
586 TopoDS_Shape aShapeFace = meshFaces[i]->GetSubShape();
588 bool orientationMeshFace = (aFace.Orientation() == aShapeFace.Orientation());
590 SCRUTE(orientationMeshFace);
592 if (orientationMeshFace)
594 MESSAGE("The mesh and face have the same orientation");
596 while(iteratorTriangle->more())
598 const SMDS_MeshElement * triangle = iteratorTriangle->next();
599 int triangleId = triangle->GetID();
601 SMDS_Iterator<const SMDS_MeshElement *> * triangleNodesIt = triangle->nodesIterator();
603 int triangleNode1 = (triangleNodesIt->next())->GetID();
604 int triangleNode2 = (triangleNodesIt->next())->GetID();
605 int triangleNode3 = (triangleNodesIt->next())->GetID();
607 // MESSAGE("TRIANGLE -> ID = " << triangleId << " N1 = " << triangleNode1 << " N2 = " << triangleNode2 << " N3 = " << triangleNode3);
612 int index = indexTrias*nbNodesByTri;
614 for (int j=0; j<Netgen_NbOfNodes; j++)
618 if (triangleNode1 == listNodeCoresNetgenSmesh[j])
620 else if (triangleNode2 == listNodeCoresNetgenSmesh[j])
622 else if (triangleNode3 == listNodeCoresNetgenSmesh[j])
626 triangleNode1 = N1New;
627 triangleNode2 = N2New;
628 triangleNode3 = N3New;
630 Netgen_Connectivity[index] = triangleNode1;
631 Netgen_Connectivity[index+1] = triangleNode2;
632 Netgen_Connectivity[index+2] = triangleNode3;
636 delete iteratorTriangle;
640 MESSAGE("The mesh and face have different orientations");
642 while(iteratorTriangle->more())
644 const SMDS_MeshElement * triangle = iteratorTriangle->next();
645 int triangleId = triangle->GetID();
647 SMDS_Iterator<const SMDS_MeshElement *> * triangleNodesIt = triangle->nodesIterator();
649 int triangleNode1 = (triangleNodesIt->next())->GetID();
650 int triangleNode3 = (triangleNodesIt->next())->GetID();
651 int triangleNode2 = (triangleNodesIt->next())->GetID();
653 // MESSAGE("TRIANGLE -> ID = " << triangleId << " N1 = " << triangleNode1 << " N2 = " << triangleNode2 << " N3 = " << triangleNode3);
658 int index = indexTrias*nbNodesByTri;
660 for (int j=0; j<Netgen_NbOfNodes; j++)
664 if (triangleNode1 == listNodeCoresNetgenSmesh[j])
666 else if (triangleNode2 == listNodeCoresNetgenSmesh[j])
668 else if (triangleNode3 == listNodeCoresNetgenSmesh[j])
672 triangleNode1 = N1New;
673 triangleNode2 = N2New;
674 triangleNode3 = N3New;
676 Netgen_Connectivity[index] = triangleNode1;
677 Netgen_Connectivity[index+1] = triangleNode2;
678 Netgen_Connectivity[index+2] = triangleNode3;
682 delete iteratorTriangle;
688 int * nodesUsed = new int[Netgen_NbOfNodes];
690 for (int i=0; i<Netgen_NbOfNodes; i++) nodesUsed[i] = 0;
692 for (int i=0; i<Netgen_NbOfTria; i++)
693 for (int j=0; j<nbNodesByTri; j++)
695 int Nij = Netgen_Connectivity[i*nbNodesByTri+j];
697 ASSERT((Nij>=1) && (Nij<=Netgen_NbOfNodes));
699 nodesUsed[Nij-1] = 1;
700 Netgen_Connectivity[i*nbNodesByTri+j] = Nij;
703 for (int i=0; i<Netgen_NbOfNodes; i++)
705 ASSERT(nodesUsed[i] != 0);
711 Feed the Netgen surface mesh
714 MESSAGE("SMESH_NETGEN_3D::Compute Feed the Netgen surface mesh");
716 Ng_Mesh * Netgen_mesh;
720 Netgen_mesh = Ng_NewMesh();
722 Ng_Meshing_Parameters Netgen_param;
724 for (int i=0; i<Netgen_NbOfNodes; i++)
726 for (int j=0; j<spaceDimension; j++)
727 Netgen_point[j] = Netgen_Coordinates[i*spaceDimension+j];
729 Ng_AddPoint(Netgen_mesh, Netgen_point);
732 for (int i=0; i<Netgen_NbOfTria; i++)
734 for (int j=0; j<nbNodesByTri; j++)
735 Netgen_triangle[j] = Netgen_Connectivity[i*nbNodesByTri+j];
737 Ng_AddSurfaceElement(Netgen_mesh, NG_TRIG, Netgen_triangle);
740 SCRUTE(Netgen_paramSize);
742 Netgen_param.secondorder = Netgen_param2ndOrder;
743 Netgen_param.fineness = Netgen_paramFine;
744 Netgen_param.maxh = Netgen_paramSize;
747 Generate the volume mesh
750 MESSAGE("SMESH_NETGEN_3D::Compute Generate the volume mesh");
752 SCRUTE(Netgen_NbOfNodes);
753 SCRUTE(Netgen_NbOfTria);
755 SCRUTE(Ng_GetNP(Netgen_mesh));
756 SCRUTE(Ng_GetNE(Netgen_mesh));
757 SCRUTE(Ng_GetNSE(Netgen_mesh));
759 ASSERT(Netgen_NbOfNodes == Ng_GetNP(Netgen_mesh));
760 ASSERT(Ng_GetNE(Netgen_mesh) == 0);
761 ASSERT(Netgen_NbOfTria == Ng_GetNSE(Netgen_mesh));
765 status = Ng_GenerateVolumeMesh(Netgen_mesh, &Netgen_param);
769 int Netgen_NbOfNodesNew = Ng_GetNP(Netgen_mesh);
771 int Netgen_NbOfTetra = Ng_GetNE(Netgen_mesh);
773 SCRUTE(Netgen_NbOfNodesNew);
775 SCRUTE(Netgen_NbOfTetra);
777 if ((status != NG_OK) ||
778 (Netgen_NbOfNodesNew <= Netgen_NbOfNodes) ||
779 (Netgen_NbOfTetra <= 0))
781 MESSAGE("SMESH_NETGEN_3D::Compute The Volume Mesh Generation has failed ...");
785 Free the memory needed by to generate the Netgen Mesh
788 MESSAGE("SMESH_NETGEN_3D::Compute Free the memory needed by to generate the Netgen Mesh");
790 delete [] Netgen_Coordinates;
791 delete [] Netgen_Connectivity;
792 delete [] Netgen_point;
793 delete [] Netgen_triangle;
794 delete [] Netgen_tetrahedron;
796 delete [] listNodeCoresNetgenSmesh;
798 Ng_DeleteMesh(Netgen_mesh);
804 MESSAGE("SMESH_NETGEN_3D::Compute End of Volume Mesh Generation");
807 double * Netgen_CoordinatesNew = new double [spaceDimension*Netgen_NbOfNodesNew];
808 int * Netgen_ConnectivityNew = new int [nbNodesByTetra*Netgen_NbOfTetra];
810 for (int i=0; i<Netgen_NbOfNodesNew; i++)
812 Ng_GetPoint(Netgen_mesh, (i+1), Netgen_point);
814 for (int j=0; j<spaceDimension; j++)
815 Netgen_CoordinatesNew[i*spaceDimension+j] = Netgen_point[j];
818 for (int i=0; i<Netgen_NbOfNodes; i++)
819 for (int j=0; j<spaceDimension; j++)
820 ASSERT(Netgen_CoordinatesNew[i*spaceDimension+j] == Netgen_Coordinates[i*spaceDimension+j])
822 for (int i=0; i<Netgen_NbOfTetra; i++)
824 Ng_GetVolumeElement(Netgen_mesh, (i+1), Netgen_tetrahedron);
826 for (int j=0; j<nbNodesByTetra; j++)
827 Netgen_ConnectivityNew[i*nbNodesByTetra+j] = Netgen_tetrahedron[j];
831 Feed back the SMESHDS with the generated Nodes and Volume Elements
834 MESSAGE("SMESH_NETGEN_3D::Compute Feed back the SMESHDS with the generated Nodes and Volume Elements");
836 int NbTotOfNodesShell = Netgen_NbOfNodesNew - Netgen_NbOfNodes;
838 SCRUTE(NbTotOfNodesShell);
840 int * listNodeShellCoresNetgenSmesh = new int [NbTotOfNodesShell];
842 for (int i=0; i<NbTotOfNodesShell; i++)
843 listNodeShellCoresNetgenSmesh[i] = 0;
845 MESSAGE("SMESH_NETGEN_3D::Compute --> Adding the New Nodes to SMESHDS");
847 for (int i=0; i<NbTotOfNodesShell; i++)
849 int index = (i+Netgen_NbOfNodes)*spaceDimension;
851 SMDS_MeshNode * node =
852 meshDS->AddNode(Netgen_CoordinatesNew[index],
853 Netgen_CoordinatesNew[index+1],
854 Netgen_CoordinatesNew[index+2]);
856 meshDS->SetNodeInVolume(node, aShell);
858 index = i+Netgen_NbOfNodes;
859 netgenToDS[index] = node;
861 listNodeShellCoresNetgenSmesh[i] = node->GetID();
864 SCRUTE(Netgen_NbOfNodesNew);
866 SCRUTE(netgenToDS.size());
868 for (int i=0; i<NbTotOfNodesShell; i++)
870 ASSERT(listNodeShellCoresNetgenSmesh[i] != 0);
872 for (int j=0; j<NbTotOfNodesShell && j!=i; j++)
873 ASSERT(listNodeShellCoresNetgenSmesh[i] != listNodeShellCoresNetgenSmesh[j]);
876 MESSAGE("SMESH_NETGEN_3D::Compute --> Adding the New elements (Tetrahedrons) to the SMESHDS");
878 for (int i=0; i<Netgen_NbOfTetra; i++)
880 int index = i*nbNodesByTetra;
881 int tetraNode1 = Netgen_ConnectivityNew[index];
882 int tetraNode2 = Netgen_ConnectivityNew[index+1];
883 int tetraNode3 = Netgen_ConnectivityNew[index+2];
884 int tetraNode4 = Netgen_ConnectivityNew[index+3];
886 const SMDS_MeshNode * node1 = netgenToDS[tetraNode1-1];
887 const SMDS_MeshNode * node2 = netgenToDS[tetraNode2-1];
888 const SMDS_MeshNode * node3 = netgenToDS[tetraNode3-1];
889 const SMDS_MeshNode * node4 = netgenToDS[tetraNode4-1];
892 if (index <= Netgen_NbOfNodes)
893 tetraNode1 = listNodeCoresNetgenSmesh[index-1];
895 tetraNode1 = listNodeShellCoresNetgenSmesh[index-Netgen_NbOfNodes-1];
898 if (index <= Netgen_NbOfNodes)
899 tetraNode2 = listNodeCoresNetgenSmesh[index-1];
901 tetraNode2 = listNodeShellCoresNetgenSmesh[index-Netgen_NbOfNodes-1];
904 if (index <= Netgen_NbOfNodes)
905 tetraNode3 = listNodeCoresNetgenSmesh[index-1];
907 tetraNode3 = listNodeShellCoresNetgenSmesh[index-Netgen_NbOfNodes-1];
910 if (index <= Netgen_NbOfNodes)
911 tetraNode4 = listNodeCoresNetgenSmesh[index-1];
913 tetraNode4 = listNodeShellCoresNetgenSmesh[index-Netgen_NbOfNodes-1];
915 SMDS_MeshVolume * elt =
916 meshDS->AddVolume(node1,node2,node3,node4);
918 meshDS->SetMeshElementOnShape(elt, aShell);
922 Free the memory needed by to generate the Netgen Mesh
925 MESSAGE("SMESH_NETGEN_3D::Compute Free the memory needed by to generate the Netgen Mesh");
927 delete [] Netgen_Coordinates;
928 delete [] Netgen_Connectivity;
929 delete [] Netgen_CoordinatesNew;
930 delete [] Netgen_ConnectivityNew;
931 delete [] Netgen_point;
932 delete [] Netgen_triangle;
933 delete [] Netgen_tetrahedron;
935 delete [] listNodeCoresNetgenSmesh;
936 delete [] listNodeShellCoresNetgenSmesh;
938 Ng_DeleteMesh(Netgen_mesh);
946 MESSAGE("SMESH_NETGEN_3D::Compute Verification of the Shell mesh");
948 TopoDS_Shape aShapeShell = meshShells[0]->GetSubShape();
949 SMESH_Algo* algoShell = _gen->GetAlgo(aMesh, aShapeShell);
950 string algoShellName = algoShell->GetName();
951 SCRUTE(algoShellName);
952 if (algoShellName != "NETGEN_3D")
954 SCRUTE(algoShellName);
959 const SMESHDS_SubMesh * aSubMeshDSShell = meshShells[0]->GetSubMeshDS();
960 SCRUTE(&aSubMeshDSShell);
962 int nbNodes = aSubMeshDSShell->NbNodes();
963 int nbTetra = aSubMeshDSShell->NbElements();
965 MESSAGE("SMESH_NETGEN_3D::Compute The mesh Shell has " << nbNodes << " shell internal Nodes, " << nbTetra << " tetrahedrons");
967 SMDS_Iterator<const SMDS_MeshNode *> * iteratorNodes = aSubMeshDSShell->GetNodes();
975 while(iteratorNodes->more())
978 const SMDS_MeshNode * node = iteratorNodes->next();
979 int nodeId = node->GetID();
980 double nodeX = node->X();
981 double nodeY = node->Y();
982 double nodeZ = node->Z();
983 // MESSAGE("NODE -> ID = " << nodeId << " X = " << nodeX << " Y = " << nodeY << " Z = " << nodeZ);
985 delete iteratorNodes;
989 SMDS_Iterator<const SMDS_MeshElement *> * iteratorTetra = aSubMeshDSShell->GetElements();
994 while(iteratorTetra->more())
997 const SMDS_MeshElement * tetra = iteratorTetra->next();
998 int tetraId = tetra->GetID();
1000 SMDS_Iterator<const SMDS_MeshElement *> * tetraNodesIt = tetra->nodesIterator();
1002 int tetraNode1 = (tetraNodesIt->next())->GetID();
1003 int tetraNode2 = (tetraNodesIt->next())->GetID();
1004 int tetraNode3 = (tetraNodesIt->next())->GetID();
1005 int tetraNode4 = (tetraNodesIt->next())->GetID();
1007 // MESSAGE("TETRAHEDRON -> ID = " << tetraId << " N1 = " << tetraNode1 << " N2 = " << tetraNode2 << " N3 = " << tetraNode3 << " N4 = " << tetraNode4);
1010 delete iteratorTetra;
1017 SCRUTE(numberOfShells);
1018 MESSAGE("SMESH_NETGEN_3D::Compute ERROR More than one shell ????? ");
1026 //=============================================================================
1030 //=============================================================================
1032 ostream & SMESH_NETGEN_3D::SaveTo(ostream & save)
1034 return save << this;
1037 //=============================================================================
1041 //=============================================================================
1043 istream & SMESH_NETGEN_3D::LoadFrom(istream & load)
1045 return load >> (*this);
1048 //=============================================================================
1052 //=============================================================================
1054 ostream & operator << (ostream & save, SMESH_NETGEN_3D & hyp)
1059 //=============================================================================
1063 //=============================================================================
1065 istream & operator >> (istream & load, SMESH_NETGEN_3D & hyp)