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