Salome HOME
7f17292938d6fa850595748d6441a4de990e38b1
[plugins/netgenplugin.git] / src / NETGENPlugin / NETGENPlugin_NETGEN_3D.cxx
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)
6 // Project   : SALOME
7 // Copyright : CEA 2003
8 // $Header$
9 //=============================================================================
10 using namespace std;
11
12 #include "NETGENPlugin_NETGEN_3D.hxx"
13 #include "SMESH_Gen.hxx"
14 #include "SMESH_Mesh.hxx"
15 #include "SMESH_subMesh.hxx"
16
17 #include "SMDS_MeshElement.hxx"
18 #include "SMDS_MeshNode.hxx"
19 #include "SMDS_FacePosition.hxx"
20
21 #include <TopExp.hxx>
22 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
23 #include <TopTools_ListOfShape.hxx>
24 #include <TopTools_ListIteratorOfListOfShape.hxx>
25 #include <TColStd_ListIteratorOfListOfInteger.hxx>
26
27 #include <BRep_Tool.hxx>
28 #include <Geom_Surface.hxx>
29 #include <Geom_Curve.hxx>
30 #include <Geom2d_Curve.hxx>
31
32 #include "utilities.h"
33
34 /*
35   Netgen include files
36 */
37
38 #include "nglib.h"
39
40 //=============================================================================
41 /*!
42  *  
43  */
44 //=============================================================================
45
46 NETGENPlugin_NETGEN_3D::NETGENPlugin_NETGEN_3D(int hypId, int studyId,
47                              SMESH_Gen* gen)
48   : SMESH_3D_Algo(hypId, studyId, gen)
49 {
50   MESSAGE("NETGENPlugin_NETGEN_3D::NETGENPlugin_NETGEN_3D");
51   _name = "NETGEN_3D";
52 //   _shapeType = TopAbs_SOLID;
53   _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);// 1 bit /shape type
54 //   MESSAGE("_shapeType octal " << oct << _shapeType);
55   _compatibleHypothesis.push_back("MaxElementVolume");
56
57   _maxElementVolume = 0.;
58
59   _hypMaxElementVolume = NULL;
60 }
61
62 //=============================================================================
63 /*!
64  *  
65  */
66 //=============================================================================
67
68 NETGENPlugin_NETGEN_3D::~NETGENPlugin_NETGEN_3D()
69 {
70   MESSAGE("NETGENPlugin_NETGEN_3D::~NETGENPlugin_NETGEN_3D");
71 }
72
73 //=============================================================================
74 /*!
75  *  
76  */
77 //=============================================================================
78
79 bool NETGENPlugin_NETGEN_3D::CheckHypothesis
80                          (SMESH_Mesh& aMesh,
81                           const TopoDS_Shape& aShape,
82                           SMESH_Hypothesis::Hypothesis_Status& aStatus)
83 {
84   MESSAGE("NETGENPlugin_NETGEN_3D::CheckHypothesis");
85
86   _hypMaxElementVolume = NULL;
87
88   list<const SMESHDS_Hypothesis*>::const_iterator itl;
89   const SMESHDS_Hypothesis* theHyp;
90
91   const list<const SMESHDS_Hypothesis*>& hyps = GetUsedHypothesis(aMesh, aShape);
92   int nbHyp = hyps.size();
93   if (!nbHyp)
94   {
95     aStatus = SMESH_Hypothesis::HYP_MISSING;
96     return false;  // can't work with no hypothesis
97   }
98
99   itl = hyps.begin();
100   theHyp = (*itl); // use only the first hypothesis
101
102   string hypName = theHyp->GetName();
103 //   int hypId = theHyp->GetID();
104 //   SCRUTE(hypName);
105
106   bool isOk = false;
107
108   if (hypName == "MaxElementVolume")
109   {
110     _hypMaxElementVolume = static_cast<const StdMeshers_MaxElementVolume*> (theHyp);
111     ASSERT(_hypMaxElementVolume);
112     _maxElementVolume = _hypMaxElementVolume->GetMaxVolume();
113     isOk =true;
114     aStatus = SMESH_Hypothesis::HYP_OK;
115   }
116   else
117     aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
118
119   return isOk;
120 }
121
122 //=============================================================================
123 /*!
124  *Here we are going to use the NETGEN mesher
125  */
126 //=============================================================================
127
128 bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh& aMesh,
129                              const TopoDS_Shape& aShape)
130 {
131   MESSAGE("NETGENPlugin_NETGEN_3D::Compute with maxElmentsize = " << _maxElementVolume);
132
133   bool isOk = false;
134   SMESHDS_Mesh* meshDS = aMesh.GetMeshDS();
135   SMESH_subMesh* theSubMesh = aMesh.GetSubMesh(aShape);
136   //const Handle(SMESHDS_SubMesh)& subMeshDS = theSubMesh->GetSubMeshDS();
137
138   map<int, const SMDS_MeshNode*> netgenToDS;
139
140   MESSAGE("NETGENPlugin_NETGEN_3D::Compute Checking the mesh Faces");
141
142   // check if all faces were meshed by a triangle mesher (here MESFISTO_2D)
143
144   vector<SMESH_subMesh*> meshFaces;
145   vector<TopoDS_Shape> shapeFaces;
146
147   for (TopExp_Explorer exp(aShape,TopAbs_FACE);exp.More();exp.Next())
148     {
149       TopoDS_Shape aShapeFace = exp.Current();
150       SMESH_subMesh* aSubMesh = aMesh.GetSubMeshContaining(exp.Current());
151       ASSERT (aSubMesh);
152       int internal_size = meshFaces.size();
153       int index = 0;
154       for (int i = 0;i<internal_size;i++)
155         {
156           if (aSubMesh == meshFaces[i]) index = 1;
157         }
158       if (index == 0) meshFaces.push_back(aSubMesh);
159
160       internal_size = shapeFaces.size();
161       index = 0;
162       for (int i = 0;i<internal_size;i++)
163         {
164           if (aShapeFace == shapeFaces[i]) index = 1;
165         }
166       if (index == 0) shapeFaces.push_back(aShapeFace);
167     }
168
169   int numberOfFaces = meshFaces.size();
170   int numberOfShapeFaces = shapeFaces.size();
171
172   SCRUTE(numberOfFaces);
173   SCRUTE(numberOfShapeFaces);
174
175   MESSAGE("---");
176
177   int NbTotOfTria = 0;
178   int NbTotOfNodesFaces = 0;
179
180   for (int i=0; i<numberOfFaces; i++)
181     {
182       TopoDS_Shape aShapeFace = meshFaces[i]->GetSubShape();
183       TopoDS_Shape aFace = shapeFaces[i];
184       SMESH_Algo* algoFace = _gen->GetAlgo(aMesh, aShapeFace);
185       string algoFaceName = algoFace->GetName();
186       SCRUTE(algoFaceName);
187       if (algoFaceName != "MEFISTO_2D")
188         {
189           SCRUTE(algoFaceName);
190           ASSERT(0);
191           return false;
192         }
193
194       bool orientationMeshFace = (aFace.Orientation() == aShapeFace.Orientation());
195
196       const SMESHDS_SubMesh* aSubMeshDSFace = meshFaces[i]->GetSubMeshDS();
197       SCRUTE(aSubMeshDSFace);
198
199       int nbNodes = aSubMeshDSFace->NbNodes();
200       NbTotOfNodesFaces += nbNodes;
201       int nbTria = aSubMeshDSFace->NbElements();
202       NbTotOfTria += nbTria;
203       int index = 0;
204
205       MESSAGE("NETGENPlugin_NETGEN_3D::Compute The mesh Face " << (i+1) << " has " << nbNodes << " face internal Nodes, " << nbTria << " triangles");
206
207       SCRUTE(orientationMeshFace);
208
209       if (orientationMeshFace)
210         {
211           MESSAGE("The mesh and face have the same orientation");
212         }
213       else
214         {
215           MESSAGE("The mesh and face have different orientations");
216         }
217
218       SMDS_NodeIteratorPtr iteratorNodes = aSubMeshDSFace->GetNodes();
219       SCRUTE(nbNodes);
220       index = 0;
221       while(iteratorNodes->more())
222         {
223           index++;
224           const SMDS_MeshNode * node = iteratorNodes->next();
225 //        int nodeId = node->GetID();
226 //        double nodeX = node->X();
227 //        double nodeY = node->Y();
228 //        double nodeZ = node->Z();
229 //        MESSAGE("NODE -> ID = " << nodeId << " X = " << nodeX << " Y = " << nodeY << " Z = " << nodeZ);
230         }
231
232       SCRUTE(index);
233
234       SMDS_ElemIteratorPtr iteratorTriangle = aSubMeshDSFace->GetElements();
235
236       SCRUTE(nbTria);
237       index = 0;
238       int numberOfDegeneratedTriangle = 0;
239       while(iteratorTriangle->more())
240         {
241           index++;
242           const SMDS_MeshElement * triangle = iteratorTriangle->next();
243           int triangleId = triangle->GetID();
244
245           SMDS_ElemIteratorPtr triangleNodesIt = triangle->nodesIterator();
246
247           const SMDS_MeshNode * node1 = static_cast<const SMDS_MeshNode *>(triangleNodesIt->next());
248           double node1X = node1->X();
249           double node1Y = node1->Y();
250           double node1Z = node1->Z();
251
252           const SMDS_MeshNode * node2 = static_cast<const SMDS_MeshNode *>(triangleNodesIt->next());
253           double node2X = node2->X();
254           double node2Y = node2->Y();
255           double node2Z = node2->Z();
256
257           const SMDS_MeshNode * node3 = static_cast<const SMDS_MeshNode *>(triangleNodesIt->next());
258           double node3X = node3->X();
259           double node3Y = node3->Y();
260           double node3Z = node3->Z();
261
262           int triangleNode1 = node1->GetID();
263           int triangleNode2 = node2->GetID();
264           int triangleNode3 = node3->GetID();
265
266           // Compute the triangle surface
267
268           double vect1 = ((node2Y - node1Y)*(node3Z - node1Z) - (node2Z - node1Z)*(node3Y - node1Y));
269           double vect2 = - ((node2X - node1X)*(node3Z - node1Z) - (node2Z - node1Z)*(node3X - node1X));
270           double vect3 = ((node2X - node1X)*(node3Y - node1Y) - (node2Y - node1Y)*(node3X - node1X));
271           double epsilon = 1.0e-6;
272
273           bool triangleIsDegenerated = ((abs(vect1)<epsilon) && (abs(vect2)<epsilon) && (abs(vect3)<epsilon));
274
275           if (triangleIsDegenerated)
276             {
277 //            MESSAGE("TRIANGLE -> ID = " << triangleId << " N1 = " << triangleNode1 << " N2 = " << triangleNode2 << " N3 = " << triangleNode3 << " is degenerated");
278 //            MESSAGE("NODE -> ID = " << triangleNode1 << " X = " << node1X << " Y = " << node1Y << " Z = " << node1Z);
279 //            MESSAGE("NODE -> ID = " << triangleNode2 << " X = " << node2X << " Y = " << node2Y << " Z = " << node2Z);
280 //            MESSAGE("NODE -> ID = " << triangleNode3 << " X = " << node3X << " Y = " << node3Y << " Z = " << node3Z);
281               numberOfDegeneratedTriangle++;
282             }
283           else
284             {
285 //            MESSAGE("TRIANGLE -> ID = " << triangleId << " N1 = " << triangleNode1 << " N2 = " << triangleNode2 << " N3 = " << triangleNode3 << " is normal");
286             }
287         }
288
289       if (numberOfDegeneratedTriangle > 0)
290         MESSAGE("WARNING THERE IS(ARE) " << numberOfDegeneratedTriangle << " degenerated triangle on this face");
291
292       SCRUTE(index);
293     }
294
295
296
297   SCRUTE(NbTotOfTria);
298   SCRUTE(NbTotOfNodesFaces);
299
300   MESSAGE("NETGENPlugin_NETGEN_3D::Compute Checking the mesh Edges");
301
302   // check if all edges were meshed by a edge mesher (here Regular_1D)
303
304   vector<SMESH_subMesh*> meshEdges;
305   for (TopExp_Explorer exp(aShape,TopAbs_EDGE);exp.More();exp.Next())
306     {
307       SMESH_subMesh* aSubMesh = aMesh.GetSubMeshContaining(exp.Current());
308       ASSERT (aSubMesh);
309       int internal_size = meshEdges.size();
310       int index = 0;
311       for (int i = 0;i<internal_size;i++)
312         {
313           if (aSubMesh == meshEdges[i]) index = 1;
314         }
315       if (index == 0) meshEdges.push_back(aSubMesh);
316     }
317
318   int numberOfEdges = meshEdges.size();
319   SCRUTE(numberOfEdges);
320
321   MESSAGE("---");
322
323   int NbTotOfNodesEdges = 0;
324   int NbTotOfSegs = 0;
325
326   for (int i=0; i<numberOfEdges; i++)
327     {
328       TopoDS_Shape aShapeEdge = meshEdges[i]->GetSubShape();
329       SMESH_Algo* algoEdge = _gen->GetAlgo(aMesh, aShapeEdge);
330       string algoEdgeName = algoEdge->GetName();
331       SCRUTE(algoEdgeName);
332       if (algoEdgeName != "Regular_1D")
333         {
334           SCRUTE(algoEdgeName);
335           ASSERT(0);
336           return false;
337         }
338
339       const SMESHDS_SubMesh* aSubMeshDSEdge = meshEdges[i]->GetSubMeshDS();
340       SCRUTE(aSubMeshDSEdge);
341
342       int nbNodes = aSubMeshDSEdge->NbNodes();
343       NbTotOfNodesEdges += nbNodes;
344       int nbSegs = aSubMeshDSEdge->NbElements();
345       NbTotOfSegs += nbSegs;
346
347       MESSAGE("NETGENPlugin_NETGEN_3D::Compute The mesh Edge " << (i+1) << " has " << nbNodes << " edge internal Nodes, " << nbSegs << " segments");
348
349       SMDS_NodeIteratorPtr iteratorNodes = aSubMeshDSEdge->GetNodes();
350       SCRUTE(nbNodes);
351       int index = 0;
352       while(iteratorNodes->more())
353         {
354           index++;
355           const SMDS_MeshNode * node = iteratorNodes->next();
356 //        int nodeId = node->GetID();
357 //        double nodeX = node->X();
358 //        double nodeY = node->Y();
359 //        double nodeZ = node->Z();
360 //        MESSAGE("NODE -> ID = " << nodeId << " X = " << nodeX << " Y = " << nodeY << " Z = " << nodeZ);
361         }
362
363       SCRUTE(index);
364     }
365
366   SCRUTE(NbTotOfNodesEdges);
367   SCRUTE(NbTotOfSegs);
368
369   MESSAGE("NETGENPlugin_NETGEN_3D::Compute Checking the mesh Vertices");
370
371   vector<SMESH_subMesh*> meshVertices;
372   for (TopExp_Explorer exp(aShape,TopAbs_VERTEX);exp.More();exp.Next())
373     {
374       SMESH_subMesh* aSubMesh = aMesh.GetSubMeshContaining(exp.Current());
375       ASSERT (aSubMesh);
376       int internal_size = meshVertices.size();
377       int index = 0;
378       for (int i = 0;i<internal_size;i++)
379         {
380           if (aSubMesh == meshVertices[i]) index = 1;
381         }
382       if (index == 0) meshVertices.push_back(aSubMesh);
383     }
384
385   int numberOfVertices = meshVertices.size();
386   SCRUTE(numberOfVertices);
387
388   MESSAGE("---");
389
390   int NbTotOfNodesVertices = 0;
391
392   for (int i=0; i<numberOfVertices; i++)
393     {
394       TopoDS_Shape aShapeVertex = meshVertices[i]->GetSubShape();
395
396       const SMESHDS_SubMesh * aSubMeshDSVertex = meshVertices[i]->GetSubMeshDS();
397       SCRUTE(aSubMeshDSVertex);
398
399       int nbNodes = aSubMeshDSVertex->NbNodes();
400       NbTotOfNodesVertices += nbNodes;
401
402       MESSAGE("NETGENPlugin_NETGEN_3D::Compute The mesh Vertex " << (i+1) << " has " << nbNodes << " Nodes");
403
404       SMDS_NodeIteratorPtr iteratorNodes = aSubMeshDSVertex->GetNodes();
405       SCRUTE(nbNodes);
406       int index = 0;
407       while(iteratorNodes->more())
408         {
409           index++;
410           const SMDS_MeshNode * node = iteratorNodes->next();
411 //        int nodeId = node->GetID();
412 //        double nodeX = node->X();
413 //        double nodeY = node->Y();
414 //        double nodeZ = node->Z();
415 //        MESSAGE("NODE -> ID = " << nodeId << " X = " << nodeX << " Y = " << nodeY << " Z = " << nodeZ);
416         }
417
418       SCRUTE(index);
419     }
420
421   SCRUTE(NbTotOfNodesVertices);
422
423   MESSAGE("NETGENPlugin_NETGEN_3D::Compute --> Analysis of all shell mesh");
424
425   vector<SMESH_subMesh*> meshShells;
426   TopoDS_Shell aShell;
427
428   for (TopExp_Explorer exp(aShape,TopAbs_SHELL);exp.More();exp.Next())
429     {
430       SMESH_subMesh* aSubMesh = aMesh.GetSubMesh(exp.Current());
431       ASSERT(aSubMesh);
432       SCRUTE(aSubMesh);
433       aShell = TopoDS::Shell(exp.Current());
434       meshShells.push_back(aSubMesh);
435     }
436
437   int numberOfShells = meshShells.size();
438   SCRUTE(numberOfShells);
439
440   if (numberOfShells == 1)
441     {
442       MESSAGE("NETGENPlugin_NETGEN_3D::Compute Only one shell --> generation of the mesh using directly Netgen");
443
444       /*
445         Prepare the Netgen surface mesh from the SMESHDS
446       */
447
448       MESSAGE("NETGENPlugin_NETGEN_3D::Compute Prepare the Netgen surface mesh from the SMESHDS");
449
450       int spaceDimension = 3;
451       int nbNodesByTri = 3;
452       int nbNodesByTetra = 4;
453
454       int Netgen_NbOfNodes = NbTotOfNodesFaces +
455                              NbTotOfNodesEdges +
456                              NbTotOfNodesVertices;
457       int Netgen_NbOfTria = NbTotOfTria;
458       int Netgen_param2ndOrder = 0;
459       double Netgen_paramFine = 1.;
460       double Netgen_paramSize = _maxElementVolume;
461
462       SCRUTE(Netgen_NbOfNodes);
463       SCRUTE(Netgen_NbOfTria);
464
465       double * Netgen_Coordinates = new double [spaceDimension*
466                                                 Netgen_NbOfNodes];
467       int * listNodeCoresNetgenSmesh = new int [Netgen_NbOfNodes];
468       int * Netgen_Connectivity = new int [nbNodesByTri*Netgen_NbOfTria];
469       double * Netgen_point = new double [spaceDimension];
470       int * Netgen_triangle = new int [nbNodesByTri];
471       int * Netgen_tetrahedron = new int [nbNodesByTetra];
472
473       for (int i=0; i<Netgen_NbOfTria; i++)
474         {
475           for (int j=0; j<nbNodesByTri; j++)
476             Netgen_Connectivity[i*nbNodesByTri+j] = 0;
477         }
478
479       double bigNumber = 1.e20;
480
481       for (int i=0; i<Netgen_NbOfNodes; i++)
482         {
483           listNodeCoresNetgenSmesh[i] = 0;
484           for (int j=0; j<spaceDimension; j++)
485             Netgen_Coordinates[i*spaceDimension+j] = bigNumber;
486         }
487
488       int indexNodes = 0;
489       for (int i=0; i<numberOfVertices; i++)
490         {
491           const SMESHDS_SubMesh * aSubMeshDSVertex =
492             meshVertices[i]->GetSubMeshDS();
493
494           SMDS_NodeIteratorPtr iteratorNodes = aSubMeshDSVertex->GetNodes();
495
496           while(iteratorNodes->more())
497             {
498               const SMDS_MeshNode * node = iteratorNodes->next();
499               int nodeId = node->GetID();
500               double nodeX = node->X();
501               double nodeY = node->Y();
502               double nodeZ = node->Z();
503 //            MESSAGE("NODE -> ID = " << nodeId << " X = " << nodeX << " Y = " << nodeY << " Z = " << nodeZ);
504               listNodeCoresNetgenSmesh[indexNodes] = nodeId;
505               int index = indexNodes*spaceDimension;
506               Netgen_Coordinates[index] = nodeX;
507               Netgen_Coordinates[index+1] = nodeY;
508               Netgen_Coordinates[index+2] = nodeZ;
509               netgenToDS[indexNodes] = node;
510               indexNodes++;
511             }
512         }
513
514       for (int i=0; i<numberOfEdges; i++)
515         {
516           const SMESHDS_SubMesh *  aSubMeshDSEdge =
517             meshEdges[i]->GetSubMeshDS();
518
519           SMDS_NodeIteratorPtr iteratorNodes = aSubMeshDSEdge->GetNodes();
520
521           while(iteratorNodes->more())
522             {
523               const SMDS_MeshNode * node = iteratorNodes->next();
524               int nodeId = node->GetID();
525               double nodeX = node->X();
526               double nodeY = node->Y();
527               double nodeZ = node->Z();
528 //            MESSAGE("NODE -> ID = " << nodeId << " X = " << nodeX << " Y = " << nodeY << " Z = " << nodeZ);
529               listNodeCoresNetgenSmesh[indexNodes] = node->GetID();
530               int index = indexNodes*spaceDimension;
531               Netgen_Coordinates[index] = node->X();
532               Netgen_Coordinates[index+1] = node->Y();
533               Netgen_Coordinates[index+2] = node->Z();
534               netgenToDS[indexNodes] = node;
535               indexNodes++;
536             }
537         }
538
539       for (int i=0; i<numberOfFaces; i++)
540         {
541           const SMESHDS_SubMesh * aSubMeshDSFace =
542             meshFaces[i]->GetSubMeshDS();
543
544           SMDS_NodeIteratorPtr iteratorNodes = aSubMeshDSFace->GetNodes();
545
546           while(iteratorNodes->more())
547             {
548               const SMDS_MeshNode * node = iteratorNodes->next();
549               int nodeId = node->GetID();
550               double nodeX = node->X();
551               double nodeY = node->Y();
552               double nodeZ = node->Z();
553 //            MESSAGE("NODE -> ID = " << nodeId << " X = " << nodeX << " Y = " << nodeY << " Z = " << nodeZ);
554               listNodeCoresNetgenSmesh[indexNodes] = nodeId;
555               int index = indexNodes*spaceDimension;
556               Netgen_Coordinates[index] = nodeX;
557               Netgen_Coordinates[index+1] = nodeY;
558               Netgen_Coordinates[index+2] = nodeZ;
559               netgenToDS[indexNodes] = node;
560               indexNodes++;
561             }
562         }
563
564       SCRUTE(indexNodes);
565
566       for (int i=0; i<Netgen_NbOfNodes; i++)
567         {
568           ASSERT(listNodeCoresNetgenSmesh[i] != 0);
569
570           for (int j=0; j<Netgen_NbOfNodes && j!=i; j++)
571             ASSERT(listNodeCoresNetgenSmesh[i] != listNodeCoresNetgenSmesh[j]);
572
573           for (int j=0; j<spaceDimension; j++)
574             ASSERT(Netgen_Coordinates[i*spaceDimension+j] != bigNumber);
575         }
576
577       int indexTrias = 0;
578       for (int i=0; i<numberOfFaces; i++)
579         {
580           const SMESHDS_SubMesh * aSubMeshDSFace =
581             meshFaces[i]->GetSubMeshDS();
582
583           TopoDS_Shape aFace = shapeFaces[i];
584
585           SMDS_ElemIteratorPtr iteratorTriangle = aSubMeshDSFace->GetElements();
586
587           TopoDS_Shape aShapeFace = meshFaces[i]->GetSubShape();
588
589           bool orientationMeshFace = (aFace.Orientation() == aShapeFace.Orientation());
590
591           SCRUTE(orientationMeshFace);
592
593           if (orientationMeshFace)
594             {
595               MESSAGE("The mesh and face have the same orientation");
596
597               while(iteratorTriangle->more())
598                 {
599                   const SMDS_MeshElement * triangle = iteratorTriangle->next();
600                   int triangleId = triangle->GetID();
601
602                   SMDS_ElemIteratorPtr triangleNodesIt = triangle->nodesIterator();
603
604                   int triangleNode1 = (triangleNodesIt->next())->GetID();
605                   int triangleNode2 = (triangleNodesIt->next())->GetID();
606                   int triangleNode3 = (triangleNodesIt->next())->GetID();
607
608 //                MESSAGE("TRIANGLE -> ID = " << triangleId << " N1 = " << triangleNode1 << " N2 = " << triangleNode2 << " N3 = " << triangleNode3);
609
610                   int N1New = 0;
611                   int N2New = 0;
612                   int N3New = 0;
613                   int index = indexTrias*nbNodesByTri;
614
615                   for (int j=0; j<Netgen_NbOfNodes; j++)
616                     {
617                       int jp1 = j+1;
618
619                       if (triangleNode1 == listNodeCoresNetgenSmesh[j])
620                         N1New = jp1;
621                       else if (triangleNode2 == listNodeCoresNetgenSmesh[j])
622                         N2New = jp1;
623                       else if (triangleNode3 == listNodeCoresNetgenSmesh[j])
624                         N3New = jp1;
625                     }
626
627                   triangleNode1 = N1New;
628                   triangleNode2 = N2New;
629                   triangleNode3 = N3New;
630
631                   Netgen_Connectivity[index] = triangleNode1;
632                   Netgen_Connectivity[index+1] = triangleNode2;
633                   Netgen_Connectivity[index+2] = triangleNode3;
634
635                   indexTrias++;
636                 }
637             }
638           else
639             {
640               MESSAGE("The mesh and face have different orientations");
641
642               while(iteratorTriangle->more())
643                 {
644                   const SMDS_MeshElement * triangle = iteratorTriangle->next();
645                   int triangleId = triangle->GetID();
646
647                   SMDS_ElemIteratorPtr triangleNodesIt = triangle->nodesIterator();
648
649                   int triangleNode1 = (triangleNodesIt->next())->GetID();
650                   int triangleNode3 = (triangleNodesIt->next())->GetID();
651                   int triangleNode2 = (triangleNodesIt->next())->GetID();
652
653 //                MESSAGE("TRIANGLE -> ID = " << triangleId << " N1 = " << triangleNode1 << " N2 = " << triangleNode2 << " N3 = " << triangleNode3);
654
655                   int N1New = 0;
656                   int N2New = 0;
657                   int N3New = 0;
658                   int index = indexTrias*nbNodesByTri;
659
660                   for (int j=0; j<Netgen_NbOfNodes; j++)
661                     {
662                       int jp1 = j+1;
663
664                       if (triangleNode1 == listNodeCoresNetgenSmesh[j])
665                         N1New = jp1;
666                       else if (triangleNode2 == listNodeCoresNetgenSmesh[j])
667                         N2New = jp1;
668                       else if (triangleNode3 == listNodeCoresNetgenSmesh[j])
669                         N3New = jp1;
670                     }
671
672                   triangleNode1 = N1New;
673                   triangleNode2 = N2New;
674                   triangleNode3 = N3New;
675
676                   Netgen_Connectivity[index] = triangleNode1;
677                   Netgen_Connectivity[index+1] = triangleNode2;
678                   Netgen_Connectivity[index+2] = triangleNode3;
679
680                   indexTrias++;
681                 }
682             }
683         }
684
685       SCRUTE(indexTrias);
686
687       int * nodesUsed = new int[Netgen_NbOfNodes];
688
689       for (int i=0; i<Netgen_NbOfNodes; i++) nodesUsed[i] = 0;
690
691       for (int i=0; i<Netgen_NbOfTria; i++)
692         for (int j=0; j<nbNodesByTri; j++)
693           {
694             int Nij = Netgen_Connectivity[i*nbNodesByTri+j];
695
696             ASSERT((Nij>=1) && (Nij<=Netgen_NbOfNodes));
697
698             nodesUsed[Nij-1] = 1;
699             Netgen_Connectivity[i*nbNodesByTri+j] = Nij;
700           }
701
702       for (int i=0; i<Netgen_NbOfNodes; i++)
703         {
704           ASSERT(nodesUsed[i] != 0);
705         }
706
707       delete [] nodesUsed;
708
709       /*
710         Feed the Netgen surface mesh
711       */
712
713       MESSAGE("NETGENPlugin_NETGEN_3D::Compute Feed the Netgen surface mesh");
714
715       Ng_Mesh * Netgen_mesh;
716
717       Ng_Init();
718
719       Netgen_mesh = Ng_NewMesh();
720
721       Ng_Meshing_Parameters Netgen_param;
722
723       for (int i=0; i<Netgen_NbOfNodes; i++)
724         {
725           for (int j=0; j<spaceDimension; j++)
726             Netgen_point[j] = Netgen_Coordinates[i*spaceDimension+j];
727
728           Ng_AddPoint(Netgen_mesh, Netgen_point);
729         }
730
731       for (int i=0; i<Netgen_NbOfTria; i++)
732         {
733           for (int j=0; j<nbNodesByTri; j++)
734             Netgen_triangle[j] = Netgen_Connectivity[i*nbNodesByTri+j];
735
736           Ng_AddSurfaceElement(Netgen_mesh, NG_TRIG, Netgen_triangle);
737         }
738
739       SCRUTE(Netgen_paramSize);
740
741       Netgen_param.secondorder = Netgen_param2ndOrder;
742       Netgen_param.fineness = Netgen_paramFine;
743       Netgen_param.maxh = Netgen_paramSize;
744
745       /*
746         Generate the volume mesh
747       */
748
749       MESSAGE("NETGENPlugin_NETGEN_3D::Compute Generate the volume mesh");
750
751       SCRUTE(Netgen_NbOfNodes);
752       SCRUTE(Netgen_NbOfTria);
753
754       SCRUTE(Ng_GetNP(Netgen_mesh));
755       SCRUTE(Ng_GetNE(Netgen_mesh));
756       SCRUTE(Ng_GetNSE(Netgen_mesh));
757
758       ASSERT(Netgen_NbOfNodes == Ng_GetNP(Netgen_mesh));
759       ASSERT(Ng_GetNE(Netgen_mesh) == 0);
760       ASSERT(Netgen_NbOfTria == Ng_GetNSE(Netgen_mesh));
761
762       Ng_Result status;
763
764       try {
765         status = Ng_GenerateVolumeMesh(Netgen_mesh, &Netgen_param);
766       } catch (...) {
767         MESSAGE("An exception has been caught during the Volume Mesh Generation ...");
768         status = NG_VOLUME_FAILURE;
769       }
770
771       SCRUTE(status);
772
773       int Netgen_NbOfNodesNew = Ng_GetNP(Netgen_mesh);
774
775       int Netgen_NbOfTetra = Ng_GetNE(Netgen_mesh);
776
777       SCRUTE(Netgen_NbOfNodesNew);
778
779       SCRUTE(Netgen_NbOfTetra);
780
781       if ((status != NG_OK) ||
782           (Netgen_NbOfNodesNew <= Netgen_NbOfNodes) ||
783           (Netgen_NbOfTetra <= 0))
784         {
785           MESSAGE("NETGENPlugin_NETGEN_3D::Compute The Volume Mesh Generation has failed ...");
786           SCRUTE(status);
787
788           /*
789             Free the memory needed by to generate the Netgen Mesh
790           */
791
792           MESSAGE("NETGENPlugin_NETGEN_3D::Compute Free the memory needed by to generate the Netgen Mesh");
793
794           delete [] Netgen_Coordinates;
795           delete [] Netgen_Connectivity;
796           delete [] Netgen_point;
797           delete [] Netgen_triangle;
798           delete [] Netgen_tetrahedron;
799
800           delete [] listNodeCoresNetgenSmesh;
801
802           Ng_DeleteMesh(Netgen_mesh);
803           Ng_Exit();
804
805           return false;
806         }
807
808       MESSAGE("NETGENPlugin_NETGEN_3D::Compute End of Volume Mesh Generation");
809       SCRUTE(status);
810
811       double * Netgen_CoordinatesNew = new double [spaceDimension*Netgen_NbOfNodesNew];
812       int * Netgen_ConnectivityNew = new int [nbNodesByTetra*Netgen_NbOfTetra];
813
814       for (int i=0; i<Netgen_NbOfNodesNew; i++)
815         {
816           Ng_GetPoint(Netgen_mesh, (i+1), Netgen_point);
817
818           for (int j=0; j<spaceDimension; j++)
819             Netgen_CoordinatesNew[i*spaceDimension+j] = Netgen_point[j];
820         }
821
822       for (int i=0; i<Netgen_NbOfNodes; i++)
823         for (int j=0; j<spaceDimension; j++)
824           ASSERT(Netgen_CoordinatesNew[i*spaceDimension+j] == Netgen_Coordinates[i*spaceDimension+j])
825
826       for (int i=0; i<Netgen_NbOfTetra; i++)
827         {
828           Ng_GetVolumeElement(Netgen_mesh, (i+1), Netgen_tetrahedron);
829
830           for (int j=0; j<nbNodesByTetra; j++)
831             Netgen_ConnectivityNew[i*nbNodesByTetra+j] = Netgen_tetrahedron[j];
832         }
833
834       /*
835         Feed back the SMESHDS with the generated Nodes and Volume Elements
836       */
837
838       MESSAGE("NETGENPlugin_NETGEN_3D::Compute Feed back the SMESHDS with the generated Nodes and Volume Elements");
839
840       int NbTotOfNodesShell = Netgen_NbOfNodesNew - Netgen_NbOfNodes;
841
842       SCRUTE(NbTotOfNodesShell);
843
844       int * listNodeShellCoresNetgenSmesh = new int [NbTotOfNodesShell];
845
846       for (int i=0; i<NbTotOfNodesShell; i++)
847         listNodeShellCoresNetgenSmesh[i] = 0;
848
849       MESSAGE("NETGENPlugin_NETGEN_3D::Compute --> Adding the New Nodes to SMESHDS");
850
851       for (int i=0; i<NbTotOfNodesShell; i++)
852         {
853           int index = (i+Netgen_NbOfNodes)*spaceDimension;
854
855           SMDS_MeshNode * node =
856             meshDS->AddNode(Netgen_CoordinatesNew[index],
857                             Netgen_CoordinatesNew[index+1],
858                             Netgen_CoordinatesNew[index+2]);
859
860           meshDS->SetNodeInVolume(node, aShell);
861
862           index = i+Netgen_NbOfNodes;
863           netgenToDS[index] = node;
864
865           listNodeShellCoresNetgenSmesh[i] = node->GetID();
866         }
867
868       SCRUTE(Netgen_NbOfNodesNew);
869       
870       SCRUTE(netgenToDS.size());
871
872       for (int i=0; i<NbTotOfNodesShell; i++)
873         {
874           ASSERT(listNodeShellCoresNetgenSmesh[i] != 0);
875
876           for (int j=0; j<NbTotOfNodesShell && j!=i; j++)
877             ASSERT(listNodeShellCoresNetgenSmesh[i] != listNodeShellCoresNetgenSmesh[j]);
878         }
879
880       MESSAGE("NETGENPlugin_NETGEN_3D::Compute --> Adding the New elements (Tetrahedrons) to the SMESHDS");
881
882       for (int i=0; i<Netgen_NbOfTetra; i++)
883         {
884           int index = i*nbNodesByTetra;
885           int tetraNode1 = Netgen_ConnectivityNew[index];
886           int tetraNode2 = Netgen_ConnectivityNew[index+1];
887           int tetraNode3 = Netgen_ConnectivityNew[index+2];
888           int tetraNode4 = Netgen_ConnectivityNew[index+3];
889
890           const SMDS_MeshNode * node1 = netgenToDS[tetraNode1-1];
891           const SMDS_MeshNode * node2 = netgenToDS[tetraNode2-1];
892           const SMDS_MeshNode * node3 = netgenToDS[tetraNode3-1];
893           const SMDS_MeshNode * node4 = netgenToDS[tetraNode4-1];
894
895           index = tetraNode1;
896           if (index <= Netgen_NbOfNodes)
897             tetraNode1 = listNodeCoresNetgenSmesh[index-1];
898           else
899             tetraNode1 = listNodeShellCoresNetgenSmesh[index-Netgen_NbOfNodes-1];
900
901           index = tetraNode2;
902           if (index <= Netgen_NbOfNodes)
903             tetraNode2 = listNodeCoresNetgenSmesh[index-1];
904           else
905             tetraNode2 = listNodeShellCoresNetgenSmesh[index-Netgen_NbOfNodes-1];
906
907           index = tetraNode3;
908           if (index <= Netgen_NbOfNodes)
909             tetraNode3 = listNodeCoresNetgenSmesh[index-1];
910           else
911             tetraNode3 = listNodeShellCoresNetgenSmesh[index-Netgen_NbOfNodes-1];
912
913           index = tetraNode4;
914           if (index <= Netgen_NbOfNodes)
915             tetraNode4 = listNodeCoresNetgenSmesh[index-1];
916           else
917             tetraNode4 = listNodeShellCoresNetgenSmesh[index-Netgen_NbOfNodes-1];
918
919           SMDS_MeshVolume * elt =
920             meshDS->AddVolume(node1,node2,node3,node4);
921
922           meshDS->SetMeshElementOnShape(elt, aShell);
923         }
924
925       /*
926         Free the memory needed by to generate the Netgen Mesh
927       */
928
929       MESSAGE("NETGENPlugin_NETGEN_3D::Compute Free the memory needed by to generate the Netgen Mesh");
930
931       delete [] Netgen_Coordinates;
932       delete [] Netgen_Connectivity;
933       delete [] Netgen_CoordinatesNew;
934       delete [] Netgen_ConnectivityNew;
935       delete [] Netgen_point;
936       delete [] Netgen_triangle;
937       delete [] Netgen_tetrahedron;
938
939       delete [] listNodeCoresNetgenSmesh;
940       delete [] listNodeShellCoresNetgenSmesh;
941
942       Ng_DeleteMesh(Netgen_mesh);
943       Ng_Exit();
944
945       /*
946         Verification
947       */
948
949       {
950         MESSAGE("NETGENPlugin_NETGEN_3D::Compute Verification of the Shell mesh");
951
952         TopoDS_Shape aShapeShell = meshShells[0]->GetSubShape();
953         SMESH_Algo* algoShell = _gen->GetAlgo(aMesh, aShapeShell);
954         string algoShellName = algoShell->GetName();
955         SCRUTE(algoShellName);
956         if (algoShellName != "NETGEN_3D")
957           {
958             SCRUTE(algoShellName);
959             ASSERT(0);
960             return false;
961           }
962
963         const SMESHDS_SubMesh * aSubMeshDSShell = meshShells[0]->GetSubMeshDS();
964         SCRUTE(&aSubMeshDSShell);
965
966         int nbNodes = aSubMeshDSShell->NbNodes();
967         int nbTetra = aSubMeshDSShell->NbElements();
968
969         MESSAGE("NETGENPlugin_NETGEN_3D::Compute The mesh Shell has " << nbNodes << " shell internal Nodes, " << nbTetra << " tetrahedrons");
970
971         SMDS_NodeIteratorPtr iteratorNodes = aSubMeshDSShell->GetNodes();
972
973         SCRUTE(nbNodes);
974
975         int index;
976
977         index = 0;
978
979         while(iteratorNodes->more())
980           {
981             index++;
982             const SMDS_MeshNode * node = iteratorNodes->next();
983             int nodeId = node->GetID();
984             double nodeX = node->X();
985             double nodeY = node->Y();
986             double nodeZ = node->Z();
987 //          MESSAGE("NODE -> ID = " << nodeId << " X = " << nodeX << " Y = " << nodeY << " Z = " << nodeZ);
988           }
989
990         SCRUTE(index);
991
992         SMDS_ElemIteratorPtr iteratorTetra = aSubMeshDSShell->GetElements();
993
994         SCRUTE(nbTetra);
995
996         index = 0;
997         while(iteratorTetra->more())
998           {
999             index++;
1000             const SMDS_MeshElement * tetra = iteratorTetra->next();
1001             int tetraId = tetra->GetID();
1002
1003             SMDS_ElemIteratorPtr tetraNodesIt = tetra->nodesIterator();
1004
1005             int tetraNode1 = (tetraNodesIt->next())->GetID();
1006             int tetraNode2 = (tetraNodesIt->next())->GetID();
1007             int tetraNode3 = (tetraNodesIt->next())->GetID();
1008             int tetraNode4 = (tetraNodesIt->next())->GetID();
1009
1010 //          MESSAGE("TETRAHEDRON -> ID = " << tetraId << " N1 = " << tetraNode1 << " N2 = " << tetraNode2 << " N3 = " << tetraNode3 << " N4 = " << tetraNode4);
1011
1012           }
1013
1014         SCRUTE(index);
1015       }
1016     }
1017   else
1018     {
1019       SCRUTE(numberOfShells);
1020       MESSAGE("NETGENPlugin_NETGEN_3D::Compute ERROR More than one shell ????? ");
1021       return false;
1022     }
1023
1024   return true;
1025 }
1026
1027
1028 //=============================================================================
1029 /*!
1030  *  
1031  */
1032 //=============================================================================
1033
1034 ostream & NETGENPlugin_NETGEN_3D::SaveTo(ostream & save)
1035 {
1036   return save;
1037 }
1038
1039 //=============================================================================
1040 /*!
1041  *  
1042  */
1043 //=============================================================================
1044
1045 istream & NETGENPlugin_NETGEN_3D::LoadFrom(istream & load)
1046 {
1047   return load;
1048 }
1049
1050 //=============================================================================
1051 /*!
1052  *  
1053  */
1054 //=============================================================================
1055
1056 ostream & operator << (ostream & save, NETGENPlugin_NETGEN_3D & hyp)
1057 {
1058   return hyp.SaveTo( save );
1059 }
1060
1061 //=============================================================================
1062 /*!
1063  *  
1064  */
1065 //=============================================================================
1066
1067 istream & operator >> (istream & load, NETGENPlugin_NETGEN_3D & hyp)
1068 {
1069   return hyp.LoadFrom( load );
1070 }