]> SALOME platform Git repositories - plugins/ghs3dplugin.git/blob - src/GHS3DPlugin_GHS3D.cxx
Salome HOME
0020461: EDF 1102 GHS3DPLUGIN: Bad detection of volumes with Ghs3d mesh
[plugins/ghs3dplugin.git] / src / GHS3DPlugin_GHS3D.cxx
1 //  Copyright (C) 2004-2008  CEA/DEN, EDF R&D
2 //
3 //  This library is free software; you can redistribute it and/or
4 //  modify it under the terms of the GNU Lesser General Public
5 //  License as published by the Free Software Foundation; either
6 //  version 2.1 of the License.
7 //
8 //  This library is distributed in the hope that it will be useful,
9 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 //  Lesser General Public License for more details.
12 //
13 //  You should have received a copy of the GNU Lesser General Public
14 //  License along with this library; if not, write to the Free Software
15 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 //=============================================================================
20 // File      : GHS3DPlugin_GHS3D.cxx
21 // Created   : 
22 // Author    : Edward AGAPOV, modified by Lioka RAZAFINDRAZAKA (CEA) 09/02/2007
23 // Project   : SALOME
24 // $Header$
25 //=============================================================================
26 //
27 using namespace std;
28
29 #include "GHS3DPlugin_GHS3D.hxx"
30 #include "GHS3DPlugin_Hypothesis.hxx"
31
32 #include "SMESH_Gen.hxx"
33 #include "SMESH_Mesh.hxx"
34 #include "SMESH_Comment.hxx"
35 #include "SMESH_MesherHelper.hxx"
36 #include "SMESH_MeshEditor.hxx"
37
38 #include "SMDS_MeshElement.hxx"
39 #include "SMDS_MeshNode.hxx"
40 #include "SMDS_FaceOfNodes.hxx"
41 #include "SMDS_VolumeOfNodes.hxx"
42
43 #include <BRepAdaptor_Surface.hxx>
44 #include <BRepBndLib.hxx>
45 #include <BRepClass3d_SolidClassifier.hxx>
46 #include <BRepTools.hxx>
47 #include <BRep_Tool.hxx>
48 #include <Bnd_Box.hxx>
49 #include <GeomAPI_ProjectPointOnSurf.hxx>
50 #include <OSD_File.hxx>
51 #include <Precision.hxx>
52 #include <Quantity_Parameter.hxx>
53 #include <Standard_ErrorHandler.hxx>
54 #include <Standard_Failure.hxx>
55 #include <TopExp.hxx>
56 #include <TopExp_Explorer.hxx>
57 #include <TopTools_IndexedMapOfShape.hxx>
58 #include <TopTools_ListIteratorOfListOfShape.hxx>
59 #include <TopoDS.hxx>
60 //#include <BRepClass_FaceClassifier.hxx>
61 #include <TopTools_MapOfShape.hxx>
62 #include <BRepGProp.hxx>
63 #include <GProp_GProps.hxx>
64
65 #include "utilities.h"
66
67 #ifndef WIN32
68 #include <sys/sysinfo.h>
69 #endif
70
71 //#include <Standard_Stream.hxx>
72
73
74 #define castToNode(n) static_cast<const SMDS_MeshNode *>( n );
75
76 #ifdef _DEBUG_
77 #define DUMP(txt) \
78 //  cout << txt
79 #else
80 #define DUMP(txt)
81 #endif
82
83 extern "C"
84 {
85 #ifndef WNT
86 #include <unistd.h>
87 #include <sys/mman.h>
88 #endif
89 #include <sys/stat.h>
90 #include <fcntl.h>
91 }
92
93 #define HOLE_ID -1
94
95 //=============================================================================
96 /*!
97  *  
98  */
99 //=============================================================================
100
101 GHS3DPlugin_GHS3D::GHS3DPlugin_GHS3D(int hypId, int studyId, SMESH_Gen* gen)
102   : SMESH_3D_Algo(hypId, studyId, gen)
103 {
104   MESSAGE("GHS3DPlugin_GHS3D::GHS3DPlugin_GHS3D");
105   _name = "GHS3D_3D";
106   _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);// 1 bit /shape type
107   _onlyUnaryInput = false; // Compute() will be called on a compound of solids
108   _iShape=0;
109   _nbShape=0;
110   _compatibleHypothesis.push_back("GHS3D_Parameters");
111   _requireShape = false; // can work without shape
112 }
113
114 //=============================================================================
115 /*!
116  *  
117  */
118 //=============================================================================
119
120 GHS3DPlugin_GHS3D::~GHS3DPlugin_GHS3D()
121 {
122   MESSAGE("GHS3DPlugin_GHS3D::~GHS3DPlugin_GHS3D");
123 }
124
125 //=============================================================================
126 /*!
127  *  
128  */
129 //=============================================================================
130
131 bool GHS3DPlugin_GHS3D::CheckHypothesis ( SMESH_Mesh&         aMesh,
132                                           const TopoDS_Shape& aShape,
133                                           Hypothesis_Status&  aStatus )
134 {
135   aStatus = SMESH_Hypothesis::HYP_OK;
136
137   // there is only one compatible Hypothesis so far
138   _hyp = 0;
139   _keepFiles = false;
140   const list <const SMESHDS_Hypothesis * >& hyps = GetUsedHypothesis(aMesh, aShape);
141   if ( !hyps.empty() )
142     _hyp = static_cast<const GHS3DPlugin_Hypothesis*> ( hyps.front() );
143   if ( _hyp )
144     _keepFiles = _hyp->GetKeepFiles();
145
146   return true;
147 }
148
149 //=======================================================================
150 //function : findShape
151 //purpose  : 
152 //=======================================================================
153
154 static TopoDS_Shape findShape(const SMDS_MeshNode *aNode[],
155                               TopoDS_Shape        aShape,
156                               const TopoDS_Shape  shape[],
157                               double**            box,
158                               const int           nShape,
159                               TopAbs_State *      state = 0)
160 {
161   gp_XYZ aPnt(0,0,0);
162   int j, iShape, nbNode = 4;
163
164   for ( j=0; j<nbNode; j++ ) {
165     gp_XYZ p ( aNode[j]->X(), aNode[j]->Y(), aNode[j]->Z() );
166     if ( aNode[j]->GetPosition()->GetTypeOfPosition() == SMDS_TOP_3DSPACE ) {
167       aPnt = p;
168       break;
169     }
170     aPnt += p;
171   }
172
173   BRepClass3d_SolidClassifier SC (aShape, aPnt, Precision::Confusion());
174   if (state) *state = SC.State();
175   if ( SC.State() != TopAbs_IN || aShape.IsNull() || aShape.ShapeType() != TopAbs_SOLID) {
176     for (iShape = 0; iShape < nShape; iShape++) {
177       aShape = shape[iShape];
178       if ( !( aPnt.X() < box[iShape][0] || box[iShape][1] < aPnt.X() ||
179               aPnt.Y() < box[iShape][2] || box[iShape][3] < aPnt.Y() ||
180               aPnt.Z() < box[iShape][4] || box[iShape][5] < aPnt.Z()) ) {
181         BRepClass3d_SolidClassifier SC (aShape, aPnt, Precision::Confusion());
182         if (state) *state = SC.State();
183         if (SC.State() == TopAbs_IN)
184           break;
185       }
186     }
187   }
188   return aShape;
189 }
190
191 //=======================================================================
192 //function : readMapIntLine
193 //purpose  : 
194 //=======================================================================
195
196 static char* readMapIntLine(char* ptr, int tab[]) {
197   long int intVal;
198   cout << endl;
199
200   for ( int i=0; i<17; i++ ) {
201     intVal = strtol(ptr, &ptr, 10);
202     if ( i < 3 )
203       tab[i] = intVal;
204   }
205   return ptr;
206 }
207
208 //=======================================================================
209 //function : countShape
210 //purpose  :
211 //=======================================================================
212
213 template < class Mesh, class Shape >
214 static int countShape( Mesh* mesh, Shape shape ) {
215   TopExp_Explorer expShape ( mesh->ShapeToMesh(), shape );
216   int nbShape = 0;
217   for ( ; expShape.More(); expShape.Next() ) {
218       nbShape++;
219   }
220   return nbShape;
221 }
222
223 //=======================================================================
224 //function : writeFaces
225 //purpose  : 
226 //=======================================================================
227
228 static bool writeFaces (ofstream &            theFile,
229                         SMESHDS_Mesh *        theMesh,
230                         const map <int,int> & theSmdsToGhs3dIdMap)
231 {
232   // record structure:
233   //
234   // NB_ELEMS DUMMY_INT
235   // Loop from 1 to NB_ELEMS
236   // NB_NODES NODE_NB_1 NODE_NB_2 ... (NB_NODES + 1) times: DUMMY_INT
237
238   int nbShape = countShape( theMesh, TopAbs_FACE );
239
240   int *tabID;             tabID    = new int[nbShape];
241   TopoDS_Shape *tabShape; tabShape = new TopoDS_Shape[nbShape];
242   TopoDS_Shape aShape;
243   SMESHDS_SubMesh* theSubMesh;
244   const SMDS_MeshElement* aFace;
245   const char* space    = "  ";
246   const int   dummyint = 0;
247   map<int,int>::const_iterator itOnMap;
248   SMDS_ElemIteratorPtr itOnSubMesh, itOnSubFace;
249   int shapeID, nbNodes, aSmdsID;
250   bool idFound;
251
252   cout << "    " << theMesh->NbFaces() << " shapes of 2D dimension" << endl;
253   cout << endl;
254
255   theFile << space << theMesh->NbFaces() << space << dummyint << endl;
256
257   TopExp_Explorer expface( theMesh->ShapeToMesh(), TopAbs_FACE );
258   for ( int i = 0; expface.More(); expface.Next(), i++ ) {
259     tabID[i] = 0;
260     aShape   = expface.Current();
261     shapeID  = theMesh->ShapeToIndex( aShape );
262     idFound  = false;
263     for ( int j=0; j<=i; j++) {
264       if ( shapeID == tabID[j] ) {
265         idFound = true;
266         break;
267       }
268     }
269     if ( ! idFound ) {
270       tabID[i]    = shapeID;
271       tabShape[i] = aShape;
272     }
273   }
274   for ( int i =0; i < nbShape; i++ ) {
275     if ( tabID[i] != 0 ) {
276       aShape      = tabShape[i];
277       shapeID     = tabID[i];
278       theSubMesh  = theMesh->MeshElements( aShape );
279       if ( !theSubMesh ) continue;
280       itOnSubMesh = theSubMesh->GetElements();
281       while ( itOnSubMesh->more() ) {
282         aFace   = itOnSubMesh->next();
283         nbNodes = aFace->NbNodes();
284
285         theFile << space << nbNodes;
286
287         itOnSubFace = aFace->nodesIterator();
288         while ( itOnSubFace->more() ) {
289           // find GHS3D ID
290           aSmdsID = itOnSubFace->next()->GetID();
291           itOnMap = theSmdsToGhs3dIdMap.find( aSmdsID );
292           ASSERT( itOnMap != theSmdsToGhs3dIdMap.end() );
293
294           theFile << space << (*itOnMap).second;
295         }
296
297         // (NB_NODES + 1) times: DUMMY_INT
298         for ( int j=0; j<=nbNodes; j++)
299           theFile << space << dummyint;
300
301         theFile << endl;
302       }
303     }
304   }
305
306   delete [] tabID;
307   delete [] tabShape;
308
309   return true;
310 }
311
312 //=======================================================================
313 //function : writeFaces
314 //purpose  : Write Faces in case if generate 3D mesh w/o geometry
315 //=======================================================================
316
317 static bool writeFaces (ofstream &            theFile,
318                         SMESHDS_Mesh *        theMesh,
319                         vector <const SMDS_MeshNode*> & theNodeByGhs3dId)
320 {
321   // record structure:
322   //
323   // NB_ELEMS DUMMY_INT
324   // Loop from 1 to NB_ELEMS
325   //   NB_NODES NODE_NB_1 NODE_NB_2 ... (NB_NODES + 1) times: DUMMY_INT
326
327
328   int nbFaces = 0;
329   list< const SMDS_MeshElement* > faces;
330   list< const SMDS_MeshElement* >::iterator f;
331   map< const SMDS_MeshNode*,int >::iterator it;
332   SMDS_ElemIteratorPtr nodeIt;
333   const SMDS_MeshElement* elem;
334   int nbNodes;
335
336   const char* space    = "  ";
337   const int   dummyint = 0;
338
339   //get all faces from mesh
340   SMDS_FaceIteratorPtr eIt = theMesh->facesIterator();
341   while ( eIt->more() ) {
342     const SMDS_MeshElement* elem = eIt->next();
343     if ( !elem )
344       return false;
345     faces.push_back( elem );
346     nbFaces++;
347   }
348
349   if ( nbFaces == 0 )
350     return false;
351   
352   cout << "The initial 2D mesh contains " << nbFaces << " faces and ";
353
354   // NB_ELEMS DUMMY_INT
355   theFile << space << nbFaces << space << dummyint << endl;
356
357   // Loop from 1 to NB_ELEMS
358
359   map<const SMDS_MeshNode*,int> aNodeToGhs3dIdMap;
360   f = faces.begin();
361   for ( ; f != faces.end(); ++f )
362   {
363     // NB_NODES PER FACE
364     elem = *f;
365     nbNodes = elem->NbNodes();
366     theFile << space << nbNodes;
367
368     // NODE_NB_1 NODE_NB_2 ...
369     nodeIt = elem->nodesIterator();
370     while ( nodeIt->more() )
371     {
372       // find GHS3D ID
373       const SMDS_MeshNode* node = castToNode( nodeIt->next() );
374       int newId = aNodeToGhs3dIdMap.size() + 1; // ghs3d ids count from 1
375       it = aNodeToGhs3dIdMap.insert( make_pair( node, newId )).first;
376       theFile << space << it->second;
377     }
378
379     // (NB_NODES + 1) times: DUMMY_INT
380     for ( int i=0; i<=nbNodes; i++)
381       theFile << space << dummyint;
382
383     theFile << endl;
384   }
385
386   // put nodes to theNodeByGhs3dId vector
387   theNodeByGhs3dId.resize( aNodeToGhs3dIdMap.size() );
388   map<const SMDS_MeshNode*,int>::const_iterator n2id = aNodeToGhs3dIdMap.begin();
389   for ( ; n2id != aNodeToGhs3dIdMap.end(); ++ n2id)
390   {
391     theNodeByGhs3dId[ n2id->second - 1 ] = n2id->first; // ghs3d ids count from 1
392   }
393
394   return true;
395 }
396
397 //=======================================================================
398 //function : writePoints
399 //purpose  : 
400 //=======================================================================
401
402 static bool writePoints (ofstream &                       theFile,
403                          SMESHDS_Mesh *                   theMesh,
404                          map <int,int> &                  theSmdsToGhs3dIdMap,
405                          map <int,const SMDS_MeshNode*> & theGhs3dIdToNodeMap)
406 {
407   // record structure:
408   //
409   // NB_NODES
410   // Loop from 1 to NB_NODES
411   //   X Y Z DUMMY_INT
412
413   int nbNodes = theMesh->NbNodes();
414   if ( nbNodes == 0 )
415     return false;
416
417   const char* space    = "  ";
418   const int   dummyint = 0;
419
420   int aGhs3dID = 1;
421   SMDS_NodeIteratorPtr it = theMesh->nodesIterator();
422   const SMDS_MeshNode* node;
423
424   // NB_NODES
425   theFile << space << nbNodes << endl;
426   cout << endl;
427   cout << "The initial 2D mesh contains :" << endl;
428   cout << "    " << nbNodes << " vertices" << endl;
429
430   // Loop from 1 to NB_NODES
431
432   while ( it->more() )
433   {
434     node = it->next();
435     theSmdsToGhs3dIdMap.insert( make_pair( node->GetID(), aGhs3dID ));
436     theGhs3dIdToNodeMap.insert( make_pair( aGhs3dID, node ));
437     aGhs3dID++;
438
439     // X Y Z DUMMY_INT
440     theFile
441       << space << node->X()
442       << space << node->Y()
443       << space << node->Z()
444       << space << dummyint;
445
446     theFile << endl;
447   }
448
449   return true;
450 }
451
452 //=======================================================================
453 //function : writePoints
454 //purpose  : 
455 //=======================================================================
456
457 static bool writePoints (ofstream &                            theFile,
458                          SMESHDS_Mesh *                        theMesh,
459                          const vector <const SMDS_MeshNode*> & theNodeByGhs3dId)
460 {
461   // record structure:
462   //
463   // NB_NODES
464   // Loop from 1 to NB_NODES
465   //   X Y Z DUMMY_INT
466
467   //int nbNodes = theMesh->NbNodes();
468   int nbNodes = theNodeByGhs3dId.size();
469   if ( nbNodes == 0 )
470     return false;
471
472   const char* space    = "  ";
473   const int   dummyint = 0;
474
475   const SMDS_MeshNode* node;
476
477   // NB_NODES
478   theFile << space << nbNodes << endl;
479   cout << nbNodes << " nodes" << endl;
480
481   // Loop from 1 to NB_NODES
482
483   vector<const SMDS_MeshNode*>::const_iterator nodeIt = theNodeByGhs3dId.begin();
484   vector<const SMDS_MeshNode*>::const_iterator after  = theNodeByGhs3dId.end();
485   for ( ; nodeIt != after; ++nodeIt )
486   {
487     node = *nodeIt;
488
489     // X Y Z DUMMY_INT
490     theFile
491       << space << node->X()
492       << space << node->Y()
493       << space << node->Z()
494       << space << dummyint;
495
496     theFile << endl;
497   }
498
499   return true;
500 }
501
502 //=======================================================================
503 //function : findShapeID
504 //purpose  : find the solid corresponding to GHS3D sub-domain following
505 //           the technique proposed in GHS3D manual in chapter
506 //           "B.4 Subdomain (sub-region) assignment"
507 //=======================================================================
508
509 static int findShapeID(SMESH_Mesh&          mesh,
510                        const SMDS_MeshNode* node1,
511                        const SMDS_MeshNode* node2,
512                        const SMDS_MeshNode* node3,
513                        const bool           toMeshHoles)
514 {
515   const int invalidID = 0;
516   SMESHDS_Mesh* meshDS = mesh.GetMeshDS();
517
518   // face the nodes belong to
519   const SMDS_MeshElement * face = meshDS->FindFace(node1,node2,node3);
520   if ( !face )
521     return invalidID;
522
523   // geom face the face assigned to
524   SMESH_MeshEditor editor(&mesh);
525   int geomFaceID = editor.FindShape( face );
526   if ( !geomFaceID )
527     return invalidID;
528   TopoDS_Shape shape = meshDS->IndexToShape( geomFaceID );
529   if ( shape.IsNull() || shape.ShapeType() != TopAbs_FACE )
530     return invalidID;
531   TopoDS_Face geomFace = TopoDS::Face( shape );
532
533   // solids bounded by geom face
534   TopTools_IndexedMapOfShape solids, shells;
535   TopTools_ListIteratorOfListOfShape ansIt = mesh.GetAncestors(geomFace);
536   for ( ; ansIt.More(); ansIt.Next() ) {
537     switch ( ansIt.Value().ShapeType() ) {
538     case TopAbs_SOLID:
539       solids.Add( ansIt.Value() ); break;
540     case TopAbs_SHELL:
541       shells.Add( ansIt.Value() ); break;
542     default:;
543     }
544   }
545   // analyse found solids
546   if ( solids.Extent() == 0 || shells.Extent() == 0)
547     return invalidID;
548
549   const TopoDS_Solid& solid1 = TopoDS::Solid( solids(1) );
550   if ( solids.Extent() == 1 )
551   {
552     if ( toMeshHoles )
553       return meshDS->ShapeToIndex( solid1 );
554
555     // - Are we at a hole boundary face?
556     if ( shells(1).IsSame( BRepTools::OuterShell( solid1 )) )
557     { // - No, but maybe a hole is bound by two shapes? Does shells(1) touches another shell?
558       bool touch = false;
559       TopExp_Explorer eExp( shells(1), TopAbs_EDGE );
560       // check if any edge of shells(1) belongs to another shell
561       for ( ; eExp.More() && !touch; eExp.Next() ) {
562         ansIt = mesh.GetAncestors( eExp.Current() );
563         for ( ; ansIt.More() && !touch; ansIt.Next() ) {
564           if ( ansIt.Value().ShapeType() == TopAbs_SHELL )
565             touch = ( !ansIt.Value().IsSame( shells(1) ));
566         }
567       }
568       if (!touch)
569         return meshDS->ShapeToIndex( solid1 );
570     }
571   }
572   // find orientation of geom face within the first solid
573   TopExp_Explorer fExp( solid1, TopAbs_FACE );
574   for ( ; fExp.More(); fExp.Next() )
575     if ( geomFace.IsSame( fExp.Current() )) {
576       geomFace = TopoDS::Face( fExp.Current() );
577       break;
578     }
579   if ( !fExp.More() )
580     return invalidID; // face not found
581
582   // normale to triangle
583   gp_Pnt node1Pnt ( node1->X(), node1->Y(), node1->Z() );
584   gp_Pnt node2Pnt ( node2->X(), node2->Y(), node2->Z() );
585   gp_Pnt node3Pnt ( node3->X(), node3->Y(), node3->Z() );
586   gp_Vec vec12( node1Pnt, node2Pnt );
587   gp_Vec vec13( node1Pnt, node3Pnt );
588   gp_Vec meshNormal = vec12 ^ vec13;
589   if ( meshNormal.SquareMagnitude() < DBL_MIN )
590     return invalidID;
591
592   // find UV of node1 on geomFace
593   SMESH_MesherHelper helper( mesh ); helper.SetSubShape( geomFace );
594   const SMDS_MeshNode* nNotOnSeamEdge = 0;
595   if ( helper.IsSeamShape( node1->GetPosition()->GetShapeId() ))
596     if ( helper.IsSeamShape( node2->GetPosition()->GetShapeId() ))
597       nNotOnSeamEdge = node3;
598     else
599       nNotOnSeamEdge = node2;
600   bool checkUV = true;
601   gp_XY uv = helper.GetNodeUV( geomFace, node1, nNotOnSeamEdge, &checkUV );
602   // check that uv is correct
603   BRepAdaptor_Surface surface( geomFace );
604   double tol = BRep_Tool::Tolerance( geomFace );
605   if ( checkUV && node1Pnt.Distance( surface.Value( uv.X(), uv.Y() )) > 2 * tol ) {
606 //     GeomAPI_ProjectPointOnSurf projector( node1Pnt, surface.Surface().Surface(), 2 * tol );
607 //     if ( !projector.IsDone() || projector.NbPoints() < 1 || projector.LowerDistance() > 2 * tol)
608       return invalidID;
609 //     Quantity_Parameter U,V;
610 //     projector.LowerDistanceParameters(U,V);
611 //     if ( node1Pnt.Distance( surface.Value( U, V )) > 2 * tol )
612 //       return invalidID;
613 //     uv.SetCoord( U,V );
614   }
615   // normale to geomFace at UV
616   gp_Vec du, dv;
617   surface.D1( uv.X(), uv.Y(), node1Pnt, du, dv );
618   gp_Vec geomNormal = du ^ dv;
619   if ( geomNormal.SquareMagnitude() < DBL_MIN )
620     return findShapeID( mesh, node2, node3, node1, toMeshHoles );
621   if ( geomFace.Orientation() == TopAbs_REVERSED )
622     geomNormal.Reverse();
623
624   // compare normals
625   bool isReverse = ( meshNormal * geomNormal ) < 0;
626   if ( !isReverse )
627     return meshDS->ShapeToIndex( solid1 );
628
629   if ( solids.Extent() == 1 )
630     return HOLE_ID; // we are inside a hole
631   else
632     return meshDS->ShapeToIndex( solids(2) );
633 }
634                        
635 //=======================================================================
636 //function : readResultFile
637 //purpose  : 
638 //=======================================================================
639
640 static bool readResultFile(const int                       fileOpen,
641                            SMESH_Mesh&                     theMesh,
642                            TopoDS_Shape                    tabShape[],
643                            double**                        tabBox,
644                            const int                       nbShape,
645                            map <int,const SMDS_MeshNode*>& theGhs3dIdToNodeMap,
646                            bool                            toMeshHoles)
647 {
648   struct stat status;
649   size_t      length;
650
651   char *ptr, *mapPtr;
652   char *tetraPtr;
653   char *shapePtr;
654
655   SMESHDS_Mesh* theMeshDS = theMesh.GetMeshDS();
656
657   int fileStat;
658   int nbElems, nbNodes, nbInputNodes;
659   int nodeId/*, triangleId*/;
660   int nbTriangle;
661   int ID, shapeID, ghs3dShapeID;
662   int IdShapeRef = 1;
663   int compoundID =
664     nbShape ? theMeshDS->ShapeToIndex( tabShape[0] ) : theMeshDS->ShapeToIndex( theMeshDS->ShapeToMesh() );
665
666   int *tab, *tabID, *nodeID, *nodeAssigne;
667   double *coord;
668   const SMDS_MeshNode **node;
669
670   tab    = new int[3];
671   //tabID  = new int[nbShape];
672   nodeID = new int[4];
673   coord  = new double[3];
674   node   = new const SMDS_MeshNode*[4];
675
676   TopoDS_Shape aSolid;
677   SMDS_MeshNode * aNewNode;
678   map <int,const SMDS_MeshNode*>::iterator itOnNode;
679   SMDS_MeshElement* aTet;
680 #ifdef _DEBUG_
681   set<int> shapeIDs;
682 #endif
683
684   // Read the file state
685   fileStat = fstat(fileOpen, &status);
686   length   = status.st_size;
687
688   // Mapping the result file into memory
689   ptr = (char *) mmap(0,length,PROT_READ,MAP_PRIVATE,fileOpen,0);
690   mapPtr = ptr;
691
692   ptr      = readMapIntLine(ptr, tab);
693   tetraPtr = ptr;
694
695   nbElems      = tab[0];
696   nbNodes      = tab[1];
697   nbInputNodes = tab[2];
698
699   nodeAssigne = new int[ nbNodes+1 ];
700
701   if (nbShape > 0)
702     aSolid = tabShape[0];
703
704   // Reading the nodeId
705   for (int i=0; i < 4*nbElems; i++)
706     nodeId = strtol(ptr, &ptr, 10);
707
708   // Reading the nodeCoor and update the nodeMap
709   for (int iNode=1; iNode <= nbNodes; iNode++) {
710     for (int iCoor=0; iCoor < 3; iCoor++)
711       coord[ iCoor ] = strtod(ptr, &ptr);
712     nodeAssigne[ iNode ] = 1;
713     if ( iNode > nbInputNodes ) {
714       nodeAssigne[ iNode ] = 0;
715       aNewNode = theMeshDS->AddNode( coord[0],coord[1],coord[2] );
716       theGhs3dIdToNodeMap.insert(theGhs3dIdToNodeMap.end(), make_pair( iNode, aNewNode ));
717     }
718   }
719
720   // Reading the number of triangles which corresponds to the number of sub-domains
721   nbTriangle = strtol(ptr, &ptr, 10);
722
723   tabID = new int[nbTriangle];
724   for (int i=0; i < nbTriangle; i++) {
725     tabID[i] = 0;
726     // find the solid corresponding to GHS3D sub-domain following
727     // the technique proposed in GHS3D manual in chapter
728     // "B.4 Subdomain (sub-region) assignment"
729     int nodeId1 = strtol(ptr, &ptr, 10);
730     int nodeId2 = strtol(ptr, &ptr, 10);
731     int nodeId3 = strtol(ptr, &ptr, 10);
732     if ( nbTriangle > 1 ) {
733       const SMDS_MeshNode* n1 = theGhs3dIdToNodeMap[ nodeId1 ];
734       const SMDS_MeshNode* n2 = theGhs3dIdToNodeMap[ nodeId2 ];
735       const SMDS_MeshNode* n3 = theGhs3dIdToNodeMap[ nodeId3 ];
736       try {
737         OCC_CATCH_SIGNALS;
738         tabID[i] = findShapeID( theMesh, n1, n2, n3, toMeshHoles );
739         // -- 0020330: Pb with ghs3d as a submesh
740         // check that found shape is to be meshed
741         if ( tabID[i] > 0 ) {
742           const TopoDS_Shape& foundShape = theMeshDS->IndexToShape( tabID[i] );
743           bool isToBeMeshed = false;
744           for ( int iS = 0; !isToBeMeshed && iS < nbShape; ++iS )
745             isToBeMeshed = foundShape.IsSame( tabShape[ iS ]);
746           if ( !isToBeMeshed )
747             tabID[i] = HOLE_ID;
748         }
749         // END -- 0020330: Pb with ghs3d as a submesh
750 #ifdef _DEBUG_
751         cout << i+1 << " subdomain: findShapeID() returns " << tabID[i] << endl;
752 #endif
753       } catch ( Standard_Failure ) {
754       } catch (...) {}
755     }
756   }
757
758   shapePtr = ptr;
759
760   if ( nbTriangle <= nbShape ) // no holes
761     toMeshHoles = true; // not avoid creating tetras in holes
762
763   // Associating the tetrahedrons to the shapes
764   shapeID = compoundID;
765   for (int iElem = 0; iElem < nbElems; iElem++) {
766     for (int iNode = 0; iNode < 4; iNode++) {
767       ID = strtol(tetraPtr, &tetraPtr, 10);
768       itOnNode = theGhs3dIdToNodeMap.find(ID);
769       node[ iNode ] = itOnNode->second;
770       nodeID[ iNode ] = ID;
771     }
772     // We always run GHS3D with "to mesh holes'==TRUE but we must not create
773     // tetras within holes depending on hypo option,
774     // so we first check if aTet is inside a hole and then create it 
775     //aTet = theMeshDS->AddVolume( node[1], node[0], node[2], node[3] );
776     if ( nbTriangle > 1 ) {
777       shapeID = HOLE_ID; // negative shapeID means not to create tetras if !toMeshHoles
778       ghs3dShapeID = strtol(shapePtr, &shapePtr, 10) - IdShapeRef;
779       if ( tabID[ ghs3dShapeID ] == 0 ) {
780         TopAbs_State state;
781         aSolid = findShape(node, aSolid, tabShape, tabBox, nbShape, &state);
782         if ( toMeshHoles || state == TopAbs_IN )
783           shapeID = theMeshDS->ShapeToIndex( aSolid );
784         tabID[ ghs3dShapeID ] = shapeID;
785       }
786       else
787         shapeID = tabID[ ghs3dShapeID ];
788     }
789     else if ( nbShape > 1 ) {
790       // Case where nbTriangle == 1 while nbShape == 2 encountered
791       // with compound of 2 boxes and "To mesh holes"==False,
792       // so there are no subdomains specified for each tetrahedron.
793       // Try to guess a solid by a node already bound to shape
794       shapeID = 0;
795       for ( int i=0; i<4 && shapeID==0; i++ ) {
796         if ( nodeAssigne[ nodeID[i] ] == 1 &&
797              node[i]->GetPosition()->GetTypeOfPosition() == SMDS_TOP_3DSPACE &&
798              node[i]->GetPosition()->GetShapeId() > 1 )
799         {
800           shapeID = node[i]->GetPosition()->GetShapeId();
801         }
802       }
803       if ( shapeID==0 ) {
804         aSolid = findShape(node, aSolid, tabShape, tabBox, nbShape);
805         shapeID = theMeshDS->ShapeToIndex( aSolid );
806       }
807     }
808     // set new nodes and tetrahedron onto the shape
809     for ( int i=0; i<4; i++ ) {
810       if ( nodeAssigne[ nodeID[i] ] == 0 ) {
811         if ( shapeID != HOLE_ID )
812           theMeshDS->SetNodeInVolume( node[i], shapeID );
813         nodeAssigne[ nodeID[i] ] = shapeID;
814       }
815     }
816     if ( toMeshHoles || shapeID != HOLE_ID ) {
817       aTet = theMeshDS->AddVolume( node[1], node[0], node[2], node[3] );
818       theMeshDS->SetMeshElementOnShape( aTet, shapeID );
819     }
820 #ifdef _DEBUG_
821     shapeIDs.insert( shapeID );
822 #endif
823   }
824   // Remove nodes of tetras inside holes if !toMeshHoles
825   if ( !toMeshHoles ) {
826     itOnNode = theGhs3dIdToNodeMap.find( nbInputNodes );
827     for ( ; itOnNode != theGhs3dIdToNodeMap.end(); ++itOnNode) {
828       ID = itOnNode->first;
829       if ( nodeAssigne[ ID ] == HOLE_ID )
830         theMeshDS->RemoveFreeNode( itOnNode->second, 0 );
831     }
832   }
833
834   if ( nbElems )
835     cout << nbElems << " tetrahedrons have been associated to " << nbShape << " shapes" << endl;
836   munmap(mapPtr, length);
837   close(fileOpen);
838
839   delete [] tab;
840   delete [] tabID;
841   delete [] nodeID;
842   delete [] coord;
843   delete [] node;
844   delete [] nodeAssigne;
845
846 #ifdef _DEBUG_
847   if ( shapeIDs.size() != nbShape ) {
848     cout << "Only " << shapeIDs.size() << " solids of " << nbShape << " found" << endl;
849     for (int i=0; i<nbShape; i++) {
850       shapeID = theMeshDS->ShapeToIndex( tabShape[i] );
851       if ( shapeIDs.find( shapeID ) == shapeIDs.end() )
852         cout << "  Solid #" << shapeID << " not found" << endl;
853     }
854   }
855 #endif
856
857   return true;
858 }
859
860 //=======================================================================
861 //function : readResultFile
862 //purpose  : 
863 //=======================================================================
864
865 static bool readResultFile(const int                      fileOpen,
866                            SMESHDS_Mesh*                  theMeshDS,
867                            TopoDS_Shape                   aSolid,
868                            vector <const SMDS_MeshNode*>& theNodeByGhs3dId) {
869
870   struct stat  status;
871   size_t       length;
872
873   char *ptr, *mapPtr;
874   char *tetraPtr;
875   char *shapePtr;
876
877   int fileStat;
878   int nbElems, nbNodes, nbInputNodes;
879   int nodeId, triangleId;
880   int nbTriangle;
881   int ID, shapeID;
882
883   int *tab;
884   double *coord;
885   const SMDS_MeshNode **node;
886
887   tab   = new int[3];
888   coord = new double[3];
889   node  = new const SMDS_MeshNode*[4];
890
891   SMDS_MeshNode * aNewNode;
892   map <int,const SMDS_MeshNode*>::iterator IdNode;
893   SMDS_MeshElement* aTet;
894
895   // Read the file state
896   fileStat = fstat(fileOpen, &status);
897   length   = status.st_size;
898
899   // Mapping the result file into memory
900   ptr = (char *) mmap(0,length,PROT_READ,MAP_PRIVATE,fileOpen,0);
901   mapPtr = ptr;
902
903   ptr      = readMapIntLine(ptr, tab);
904   tetraPtr = ptr;
905
906   nbElems      = tab[0];
907   nbNodes      = tab[1];
908   nbInputNodes = tab[2];
909
910   theNodeByGhs3dId.resize( nbNodes );
911
912   // Reading the nodeId
913   for (int i=0; i < 4*nbElems; i++)
914     nodeId = strtol(ptr, &ptr, 10);
915
916   // Reading the nodeCoor and update the nodeMap
917   shapeID = theMeshDS->ShapeToIndex( aSolid );
918   for (int iNode=0; iNode < nbNodes; iNode++) {
919     for (int iCoor=0; iCoor < 3; iCoor++)
920       coord[ iCoor ] = strtod(ptr, &ptr);
921     if ((iNode+1) > nbInputNodes) {
922       aNewNode = theMeshDS->AddNode( coord[0],coord[1],coord[2] );
923       theMeshDS->SetNodeInVolume( aNewNode, shapeID );
924       theNodeByGhs3dId[ iNode ] = aNewNode;
925     }
926   }
927
928   // Reading the triangles
929   nbTriangle = strtol(ptr, &ptr, 10);
930
931   for (int i=0; i < 3*nbTriangle; i++)
932     triangleId = strtol(ptr, &ptr, 10);
933
934   shapePtr = ptr;
935
936   // Associating the tetrahedrons to the shapes
937   for (int iElem = 0; iElem < nbElems; iElem++) {
938     for (int iNode = 0; iNode < 4; iNode++) {
939       ID = strtol(tetraPtr, &tetraPtr, 10);
940       node[ iNode ] = theNodeByGhs3dId[ ID-1 ];
941     }
942     aTet = theMeshDS->AddVolume( node[1], node[0], node[2], node[3] );
943     shapeID = theMeshDS->ShapeToIndex( aSolid );
944     theMeshDS->SetMeshElementOnShape( aTet, shapeID );
945   }
946   if ( nbElems )
947     cout << nbElems << " tetrahedrons have been associated to " << nbTriangle << " shapes" << endl;
948   munmap(mapPtr, length);
949   close(fileOpen);
950
951   delete [] tab;
952   delete [] coord;
953   delete [] node;
954
955   return true;
956 }
957
958 //=============================================================================
959 /*!
960  *Here we are going to use the GHS3D mesher
961  */
962 //=============================================================================
963
964 bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
965                                 const TopoDS_Shape& theShape)
966 {
967   bool Ok(false);
968   SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
969
970   // we count the number of shapes
971   // _nbShape = countShape( meshDS, TopAbs_SOLID ); -- 0020330: Pb with ghs3d as a submesh
972   _nbShape = 0;
973   TopExp_Explorer expBox ( theShape, TopAbs_SOLID );
974   for ( ; expBox.More(); expBox.Next() )
975     _nbShape++;
976
977   // create bounding box for every shape inside the compound
978
979   int iShape = 0;
980   TopoDS_Shape* tabShape;
981   double**      tabBox;
982   tabShape = new TopoDS_Shape[_nbShape];
983   tabBox   = new double*[_nbShape];
984   for (int i=0; i<_nbShape; i++)
985     tabBox[i] = new double[6];
986   Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
987
988   // TopExp_Explorer expBox (meshDS->ShapeToMesh(), TopAbs_SOLID); -- 0020330:...ghs3d as a submesh
989   for (expBox.ReInit(); expBox.More(); expBox.Next()) {
990     tabShape[iShape] = expBox.Current();
991     Bnd_Box BoundingBox;
992     BRepBndLib::Add(expBox.Current(), BoundingBox);
993     BoundingBox.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
994     tabBox[iShape][0] = Xmin; tabBox[iShape][1] = Xmax;
995     tabBox[iShape][2] = Ymin; tabBox[iShape][3] = Ymax;
996     tabBox[iShape][4] = Zmin; tabBox[iShape][5] = Zmax;
997     iShape++;
998   }
999
1000   // a unique working file name
1001   // to avoid access to the same files by eg different users
1002   TCollection_AsciiString aGenericName
1003     = (char*) GHS3DPlugin_Hypothesis::GetFileName(_hyp).c_str();
1004
1005   TCollection_AsciiString aFacesFileName, aPointsFileName, aResultFileName;
1006   TCollection_AsciiString aBadResFileName, aBbResFileName, aLogFileName;
1007   aFacesFileName  = aGenericName + ".faces";  // in faces
1008   aPointsFileName = aGenericName + ".points"; // in points
1009   aResultFileName = aGenericName + ".noboite";// out points and volumes
1010   aBadResFileName = aGenericName + ".boite";  // out bad result
1011   aBbResFileName  = aGenericName + ".bb";     // out vertex stepsize
1012   aLogFileName    = aGenericName + ".log";    // log
1013
1014   // -----------------
1015   // make input files
1016   // -----------------
1017
1018   ofstream aFacesFile  ( aFacesFileName.ToCString()  , ios::out);
1019   ofstream aPointsFile ( aPointsFileName.ToCString() , ios::out);
1020
1021   Ok =
1022 #ifdef WIN32
1023     aFacesFile->is_open() && aPointsFile->is_open();
1024 #else
1025     aFacesFile.rdbuf()->is_open() && aPointsFile.rdbuf()->is_open();
1026 #endif
1027   if (!Ok) {
1028     INFOS( "Can't write into " << aFacesFileName);
1029     return error(SMESH_Comment("Can't write into ") << aFacesFileName);
1030   }
1031   map <int,int> aSmdsToGhs3dIdMap;
1032   map <int,const SMDS_MeshNode*> aGhs3dIdToNodeMap;
1033
1034   Ok = writePoints( aPointsFile, meshDS, aSmdsToGhs3dIdMap, aGhs3dIdToNodeMap ) &&
1035        writeFaces ( aFacesFile,  meshDS, aSmdsToGhs3dIdMap );
1036
1037   aFacesFile.close();
1038   aPointsFile.close();
1039
1040   if ( ! Ok ) {
1041     if ( !_keepFiles ) {
1042       OSD_File( aFacesFileName ).Remove();
1043       OSD_File( aPointsFileName ).Remove();
1044     }
1045     return error(COMPERR_BAD_INPUT_MESH);
1046   }
1047   OSD_File( aResultFileName ).Remove(); // needed for boundary recovery module usage
1048
1049   // -----------------
1050   // run ghs3d mesher
1051   // -----------------
1052
1053   TCollection_AsciiString cmd( (char*)GHS3DPlugin_Hypothesis::CommandToRun( _hyp ).c_str() );
1054   cmd += TCollection_AsciiString(" -f ") + aGenericName;  // file to read
1055   cmd += TCollection_AsciiString(" 1>" ) + aLogFileName;  // dump into file
1056
1057   cout << endl;
1058   cout << "Ghs3d execution..." << endl;
1059   cout << cmd << endl;
1060
1061   system( cmd.ToCString() ); // run
1062
1063   cout << endl;
1064   cout << "End of Ghs3d execution !" << endl;
1065
1066   // --------------
1067   // read a result
1068   // --------------
1069
1070   // Mapping the result file
1071
1072   int fileOpen;
1073   fileOpen = open( aResultFileName.ToCString(), O_RDONLY);
1074   if ( fileOpen < 0 ) {
1075     cout << endl;
1076     cout << "Can't open the " << aResultFileName.ToCString() << " GHS3D output file" << endl;
1077     cout << "Log: " << aLogFileName << endl;
1078     Ok = false;
1079   }
1080   else {
1081     bool toMeshHoles =
1082       _hyp ? _hyp->GetToMeshHoles(true) : GHS3DPlugin_Hypothesis::DefaultMeshHoles();
1083     Ok = readResultFile( fileOpen, theMesh, tabShape, tabBox, _nbShape, aGhs3dIdToNodeMap,
1084                          toMeshHoles );
1085   }
1086
1087   // ---------------------
1088   // remove working files
1089   // ---------------------
1090
1091   if ( Ok )
1092   {
1093     if ( !_keepFiles )
1094       OSD_File( aLogFileName ).Remove();
1095   }
1096   else if ( OSD_File( aLogFileName ).Size() > 0 )
1097   {
1098     // get problem description from the log file
1099     _Ghs2smdsConvertor conv( aGhs3dIdToNodeMap );
1100     storeErrorDescription( aLogFileName, conv );
1101   }
1102   else
1103   {
1104     // the log file is empty
1105     OSD_File( aLogFileName ).Remove();
1106     INFOS( "GHS3D Error, command '" << cmd.ToCString() << "' failed" );
1107     error(COMPERR_ALGO_FAILED, "ghs3d: command not found" );
1108   }
1109
1110   if ( !_keepFiles ) {
1111     OSD_File( aFacesFileName ).Remove();
1112     OSD_File( aPointsFileName ).Remove();
1113     OSD_File( aResultFileName ).Remove();
1114     OSD_File( aBadResFileName ).Remove();
1115     OSD_File( aBbResFileName ).Remove();
1116   }
1117   cout << "<" << aResultFileName.ToCString() << "> GHS3D output file ";
1118   if ( !Ok )
1119     cout << "not ";
1120   cout << "treated !" << endl;
1121   cout << endl;
1122
1123   _nbShape = 0;    // re-initializing _nbShape for the next Compute() method call
1124   delete [] tabShape;
1125   delete [] tabBox;
1126
1127   return Ok;
1128 }
1129
1130 //=============================================================================
1131 /*!
1132  *Here we are going to use the GHS3D mesher w/o geometry
1133  */
1134 //=============================================================================
1135 bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
1136                                 SMESH_MesherHelper* aHelper)
1137 {
1138   MESSAGE("GHS3DPlugin_GHS3D::Compute()");
1139
1140   SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
1141   TopoDS_Shape theShape = aHelper->GetSubShape();
1142
1143   // a unique working file name
1144   // to avoid access to the same files by eg different users
1145   TCollection_AsciiString aGenericName
1146     = (char*) GHS3DPlugin_Hypothesis::GetFileName(_hyp).c_str();
1147
1148   TCollection_AsciiString aFacesFileName, aPointsFileName, aResultFileName;
1149   TCollection_AsciiString aBadResFileName, aBbResFileName, aLogFileName;
1150   aFacesFileName  = aGenericName + ".faces";  // in faces
1151   aPointsFileName = aGenericName + ".points"; // in points
1152   aResultFileName = aGenericName + ".noboite";// out points and volumes
1153   aBadResFileName = aGenericName + ".boite";  // out bad result
1154   aBbResFileName  = aGenericName + ".bb";     // out vertex stepsize
1155   aLogFileName    = aGenericName + ".log";    // log
1156
1157   // -----------------
1158   // make input files
1159   // -----------------
1160
1161   ofstream aFacesFile  ( aFacesFileName.ToCString()  , ios::out);
1162   ofstream aPointsFile  ( aPointsFileName.ToCString()  , ios::out);
1163   bool Ok =
1164 #ifdef WIN32
1165     aFacesFile->is_open() && aPointsFile->is_open();
1166 #else
1167     aFacesFile.rdbuf()->is_open() && aPointsFile.rdbuf()->is_open();
1168 #endif
1169
1170   if (!Ok)
1171     return error( SMESH_Comment("Can't write into ") << aPointsFileName);
1172
1173   vector <const SMDS_MeshNode*> aNodeByGhs3dId;
1174
1175   Ok = (writeFaces ( aFacesFile, meshDS, aNodeByGhs3dId ) &&
1176         writePoints( aPointsFile, meshDS, aNodeByGhs3dId));
1177   
1178   aFacesFile.close();
1179   aPointsFile.close();
1180   
1181   if ( ! Ok ) {
1182     if ( !_keepFiles ) {
1183       OSD_File( aFacesFileName ).Remove();
1184       OSD_File( aPointsFileName ).Remove();
1185     }
1186     return error(COMPERR_BAD_INPUT_MESH);
1187   }
1188   OSD_File( aResultFileName ).Remove(); // needed for boundary recovery module usage
1189
1190   // -----------------
1191   // run ghs3d mesher
1192   // -----------------
1193
1194   TCollection_AsciiString cmd =
1195     (char*)GHS3DPlugin_Hypothesis::CommandToRun( _hyp, false ).c_str();
1196   cmd += TCollection_AsciiString(" -f ") + aGenericName;  // file to read
1197   cmd += TCollection_AsciiString(" 1>" ) + aLogFileName;  // dump into file
1198   
1199   system( cmd.ToCString() ); // run
1200
1201   // --------------
1202   // read a result
1203   // --------------
1204   int fileOpen;
1205   fileOpen = open( aResultFileName.ToCString(), O_RDONLY);
1206   if ( fileOpen < 0 ) {
1207     cout << endl;
1208     cout << "Error when opening the " << aResultFileName.ToCString() << " file" << endl;
1209     cout << "Log: " << aLogFileName << endl;
1210     cout << endl;
1211     Ok = false;
1212   }
1213   else {
1214     Ok = readResultFile( fileOpen, meshDS, theShape ,aNodeByGhs3dId );
1215   }
1216   
1217   // ---------------------
1218   // remove working files
1219   // ---------------------
1220
1221   if ( Ok )
1222   {
1223     if ( !_keepFiles )
1224       OSD_File( aLogFileName ).Remove();
1225   }
1226   else if ( OSD_File( aLogFileName ).Size() > 0 )
1227   {
1228     // get problem description from the log file
1229     _Ghs2smdsConvertor conv( aNodeByGhs3dId );
1230     storeErrorDescription( aLogFileName, conv );
1231   }
1232   else {
1233     // the log file is empty
1234     OSD_File( aLogFileName ).Remove();
1235     INFOS( "GHS3D Error, command '" << cmd.ToCString() << "' failed" );
1236     error(COMPERR_ALGO_FAILED, "ghs3d: command not found" );
1237   }
1238
1239   if ( !_keepFiles )
1240   {
1241     OSD_File( aFacesFileName ).Remove();
1242     OSD_File( aPointsFileName ).Remove();
1243     OSD_File( aResultFileName ).Remove();
1244     OSD_File( aBadResFileName ).Remove();
1245     OSD_File( aBbResFileName ).Remove();
1246   }
1247   
1248   return Ok;
1249 }
1250
1251 //================================================================================
1252 /*!
1253  * \brief Provide human readable text by error code reported by ghs3d
1254  */
1255 //================================================================================
1256
1257 static string translateError(const int errNum)
1258 {
1259   switch ( errNum ) {
1260   case 0:
1261     return "The surface mesh includes a face of type other than edge, "
1262       "triangle or quadrilateral. This face type is not supported.";
1263   case 1:
1264     return "Not enough memory for the face table.";
1265   case 2:
1266     return "Not enough memory.";
1267   case 3:
1268     return "Not enough memory.";
1269   case 4:
1270     return "Face is ignored.";
1271   case 5:
1272     return "End of file. Some data are missing in the file.";
1273   case 6:
1274     return "Read error on the file. There are wrong data in the file.";
1275   case 7:
1276     return "the metric file is inadequate (dimension other than 3).";
1277   case 8:
1278     return "the metric file is inadequate (values not per vertices).";
1279   case 9:
1280     return "the metric file contains more than one field.";
1281   case 10:
1282     return "the number of values in the \".bb\" (metric file) is incompatible with the expected"
1283       "value of number of mesh vertices in the \".noboite\" file.";
1284   case 12:
1285     return "Too many sub-domains.";
1286   case 13:
1287     return "the number of vertices is negative or null.";
1288   case 14:
1289     return "the number of faces is negative or null.";
1290   case 15:
1291     return "A face has a null vertex.";
1292   case 22:
1293     return "incompatible data.";
1294   case 131:
1295     return "the number of vertices is negative or null.";
1296   case 132:
1297     return "the number of vertices is negative or null (in the \".mesh\" file).";
1298   case 133:
1299     return "the number of faces is negative or null.";
1300   case 1000:
1301     return "A face appears more than once in the input surface mesh.";
1302   case 1001:
1303     return "An edge appears more than once in the input surface mesh.";
1304   case 1002:
1305     return "A face has a vertex negative or null.";
1306   case 1003:
1307     return "NOT ENOUGH MEMORY.";
1308   case 2000:
1309     return "Not enough available memory.";
1310   case 2002:
1311     return "Some initial points cannot be inserted. The surface mesh is probably very bad "
1312       "in terms of quality or the input list of points is wrong.";
1313   case 2003:
1314     return "Some vertices are too close to one another or coincident.";
1315   case 2004:
1316     return "Some vertices are too close to one another or coincident.";
1317   case 2012:
1318     return "A vertex cannot be inserted.";
1319   case 2014:
1320     return "There are at least two points considered as coincident.";
1321   case 2103:
1322     return "Some vertices are too close to one another or coincident.";
1323   case 3000:
1324     return "The surface mesh regeneration step has failed.";
1325   case 3009:
1326     return "Constrained edge cannot be enforced.";
1327   case 3019:
1328     return "Constrained face cannot be enforced.";
1329   case 3029:
1330     return "Missing faces.";
1331   case 3100:
1332     return "No guess to start the definition of the connected component(s).";
1333   case 3101:
1334     return "The surface mesh includes at least one hole. The domain is not well defined.";
1335   case 3102:
1336     return "Impossible to define a component.";
1337   case 3103:
1338     return "The surface edge intersects another surface edge.";
1339   case 3104:
1340     return "The surface edge intersects the surface face.";
1341   case 3105:
1342     return "One boundary point lies within a surface face.";
1343   case 3106:
1344     return "One surface edge intersects a surface face.";
1345   case 3107:
1346     return "One boundary point lies within a surface edge.";
1347   case 3108:
1348     return "Insufficient memory ressources detected due to a bad quality surface mesh leading "
1349       "to too many swaps.";
1350   case 3109:
1351     return "Edge is unique (i.e., bounds a hole in the surface).";
1352   case 3122:
1353     return "Presumably, the surface mesh is not compatible with the domain being processed.";
1354   case 3123:
1355     return "Too many components, too many sub-domain.";
1356   case 3209:
1357     return "The surface mesh includes at least one hole. "
1358       "Therefore there is no domain properly defined.";
1359   case 3300:
1360     return "Statistics.";
1361   case 3400:
1362     return "Statistics.";
1363   case 3500:
1364     return "Warning, it is dramatically tedious to enforce the boundary items.";
1365   case 4000:
1366     return "Not enough memory at this time, nevertheless, the program continues. "
1367       "The expected mesh will be correct but not really as large as required.";
1368   case 4002:
1369     return "see above error code, resulting quality may be poor.";
1370   case 4003:
1371     return "Not enough memory at this time, nevertheless, the program continues (warning).";
1372   case 8000:
1373     return "Unknown face type.";
1374   case 8005:
1375   case 8006:
1376     return "End of file. Some data are missing in the file.";
1377   case 9000:
1378     return "A too small volume element is detected.";
1379   case 9001:
1380     return "There exists at least a null or negative volume element.";
1381   case 9002:
1382     return "There exist null or negative volume elements.";
1383   case 9003:
1384     return "A too small volume element is detected. A face is considered being degenerated.";
1385   case 9100:
1386     return "Some element is suspected to be very bad shaped or wrong.";
1387   case 9102:
1388     return "A too bad quality face is detected. This face is considered degenerated.";
1389   case 9112:
1390     return "A too bad quality face is detected. This face is degenerated.";
1391   case 9122:
1392     return "Presumably, the surface mesh is not compatible with the domain being processed.";
1393   case 9999:
1394     return "Abnormal error occured, contact hotline.";
1395   case 23600:
1396     return "Not enough memory for the face table.";
1397   case 23601:
1398     return "The algorithm cannot run further. "
1399       "The surface mesh is probably very bad in terms of quality.";
1400   case 23602:
1401     return "Bad vertex number.";
1402   }
1403   return "";
1404 }
1405
1406 //================================================================================
1407 /*!
1408  * \brief Retrieve from a string given number of integers
1409  */
1410 //================================================================================
1411
1412 static char* getIds( char* ptr, int nbIds, vector<int>& ids )
1413 {
1414   ids.clear();
1415   ids.reserve( nbIds );
1416   while ( nbIds )
1417   {
1418     while ( !isdigit( *ptr )) ++ptr;
1419     if ( ptr[-1] == '-' ) --ptr;
1420     ids.push_back( strtol( ptr, &ptr, 10 ));
1421     --nbIds;
1422   }
1423   return ptr;
1424 }
1425
1426 //================================================================================
1427 /*!
1428  * \brief Retrieve problem description form a log file
1429  *  \retval bool - always false
1430  */
1431 //================================================================================
1432
1433 bool GHS3DPlugin_GHS3D::storeErrorDescription(const TCollection_AsciiString& logFile,
1434                                               const _Ghs2smdsConvertor &     toSmdsConvertor )
1435 {
1436   // open file
1437 #ifdef WNT
1438   int file = ::_open (logFile.ToCString(), _O_RDONLY|_O_BINARY);
1439 #else
1440   int file = ::open (logFile.ToCString(), O_RDONLY);
1441 #endif
1442   if ( file < 0 )
1443     return error( SMESH_Comment("See ") << logFile << " for problem description");
1444
1445   // get file size
1446 //   struct stat status;
1447 //   fstat(file, &status);
1448 //   size_t length = status.st_size;
1449   off_t length = lseek( file, 0, SEEK_END);
1450   lseek( file, 0, SEEK_SET);
1451
1452   // read file
1453   vector< char > buf( length );
1454   int nBytesRead = ::read (file, & buf[0], length);
1455   ::close (file);
1456   char* ptr = & buf[0];
1457   char* bufEnd = ptr + nBytesRead;
1458
1459   SMESH_Comment errDescription;
1460
1461   enum { NODE = 1, EDGE, TRIA, VOL, ID = 1 };
1462
1463   // look for errors "ERR #"
1464
1465   set<string> foundErrorStr; // to avoid reporting same error several times
1466   set<int>    elemErrorNums; // not to report different types of errors with bad elements
1467   while ( ++ptr < bufEnd )
1468   {
1469     if ( strncmp( ptr, "ERR ", 4 ) != 0 )
1470       continue;
1471
1472     list<const SMDS_MeshElement*> badElems;
1473     vector<int> nodeIds;
1474
1475     ptr += 4;
1476     char* errBeg = ptr;
1477     int   errNum = strtol(ptr, &ptr, 10);
1478     switch ( errNum ) { // we treat errors enumerated in [SALOME platform 0019316] issue
1479     case 0015:
1480       // The face number (numfac) with vertices (f 1, f 2, f 3) has a null vertex.
1481       ptr = getIds(ptr, NODE, nodeIds);
1482       ptr = getIds(ptr, TRIA, nodeIds);
1483       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
1484       break;
1485     case 1000: // ERR  1000 :  1 3 2
1486       // Face (f 1, f 2, f 3) appears more than once in the input surface mesh.
1487       ptr = getIds(ptr, TRIA, nodeIds);
1488       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
1489       break;
1490     case 1001:
1491       // Edge (e1, e2) appears more than once in the input surface mesh
1492       ptr = getIds(ptr, EDGE, nodeIds);
1493       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
1494       break;
1495     case 1002:
1496       // Face (f 1, f 2, f 3) has a vertex negative or null
1497       ptr = getIds(ptr, TRIA, nodeIds);
1498       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
1499       break;
1500     case 2004:
1501       // Vertex v1 and vertex v2 are too close to one another or coincident (warning).
1502       ptr = getIds(ptr, NODE, nodeIds);
1503       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
1504       ptr = getIds(ptr, NODE, nodeIds);
1505       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
1506       break;
1507     case 2012:
1508       // Vertex v1 cannot be inserted (warning).
1509       ptr = getIds(ptr, NODE, nodeIds);
1510       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
1511       break;
1512     case 2014:
1513       // There are at least two points whose distance is dist, i.e., considered as coincident
1514     case 2103: // ERR  2103 :  16 WITH  3
1515       // Vertex v1 and vertex v2 are too close to one another or coincident (warning).
1516       ptr = getIds(ptr, NODE, nodeIds);
1517       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
1518       ptr = getIds(ptr, NODE, nodeIds);
1519       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
1520       break;
1521     case 3009:
1522       // Constrained edge (e1, e2) cannot be enforced (warning).
1523       ptr = getIds(ptr, EDGE, nodeIds);
1524       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
1525       break;
1526     case 3019:
1527       // Constrained face (f 1, f 2, f 3) cannot be enforced
1528       ptr = getIds(ptr, TRIA, nodeIds);
1529       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
1530       break;
1531     case 3103: // ERR  3103 :  1 2 WITH  7 3
1532       // The surface edge (e1, e2) intersects another surface edge (e3, e4)
1533       ptr = getIds(ptr, EDGE, nodeIds);
1534       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
1535       ptr = getIds(ptr, EDGE, nodeIds);
1536       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
1537       break;
1538     case 3104: // ERR  3104 :  9 10 WITH  1 2 3
1539       // The surface edge (e1, e2) intersects the surface face (f 1, f 2, f 3)
1540       ptr = getIds(ptr, EDGE, nodeIds);
1541       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
1542       ptr = getIds(ptr, TRIA, nodeIds);
1543       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
1544       break;
1545     case 3105: // ERR  3105 :  8 IN  2 3 5
1546       // One boundary point (say p1) lies within a surface face (f 1, f 2, f 3)
1547       ptr = getIds(ptr, NODE, nodeIds);
1548       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
1549       ptr = getIds(ptr, TRIA, nodeIds);
1550       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
1551       break;
1552     case 3106:
1553       // One surface edge (say e1, e2) intersects a surface face (f 1, f 2, f 3)
1554       ptr = getIds(ptr, EDGE, nodeIds);
1555       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
1556       ptr = getIds(ptr, TRIA, nodeIds);
1557       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
1558       break;
1559     case 3107: // ERR  3107 :  2 IN  4 1
1560       // One boundary point (say p1) lies within a surface edge (e1, e2) (stop).
1561       ptr = getIds(ptr, NODE, nodeIds);
1562       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
1563       ptr = getIds(ptr, EDGE, nodeIds);
1564       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
1565       break;
1566     case 3109: // ERR  3109 :  EDGE  5 6 UNIQUE
1567       // Edge (e1, e2) is unique (i.e., bounds a hole in the surface)
1568       ptr = getIds(ptr, EDGE, nodeIds);
1569       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
1570       break;
1571     case 9000: // ERR  9000 
1572       //  ELEMENT  261 WITH VERTICES :  7 396 -8 242 
1573       //  VOLUME   : -1.11325045E+11 W.R.T. EPSILON   0.
1574       // A too small volume element is detected. Are reported the index of the element,
1575       // its four vertex indices, its volume and the tolerance threshold value
1576       ptr = getIds(ptr, ID, nodeIds);
1577       ptr = getIds(ptr, VOL, nodeIds);
1578       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
1579       // even if all nodes found, volume it most probably invisible,
1580       // add its faces to demenstrate it anyhow
1581       {
1582         vector<int> faceNodes( nodeIds.begin(), --nodeIds.end() ); // 012
1583         badElems.push_back( toSmdsConvertor.getElement(faceNodes));
1584         faceNodes[2] = nodeIds[3]; // 013
1585         badElems.push_back( toSmdsConvertor.getElement(faceNodes));
1586         faceNodes[1] = nodeIds[2]; // 023
1587         badElems.push_back( toSmdsConvertor.getElement(faceNodes));
1588         faceNodes[0] = nodeIds[1]; // 123
1589         badElems.push_back( toSmdsConvertor.getElement(faceNodes));
1590       }
1591       break;
1592     case 9001: // ERR  9001
1593       //  %% NUMBER OF NEGATIVE VOLUME TETS  :  1 
1594       //  %% THE LARGEST NEGATIVE TET        :   1.75376581E+11 
1595       //  %%  NUMBER OF NULL VOLUME TETS     :  0
1596       // There exists at least a null or negative volume element
1597       break;
1598     case 9002:
1599       // There exist n null or negative volume elements
1600       break;
1601     case 9003:
1602       // A too small volume element is detected
1603       break;
1604     case 9102:
1605       // A too bad quality face is detected. This face is considered degenerated,
1606       // its index, its three vertex indices together with its quality value are reported
1607       break; // same as next
1608     case 9112: // ERR  9112 
1609       //  FACE   2 WITH VERTICES :  4 2 5 
1610       //  SMALL INRADIUS :   0.
1611       // A too bad quality face is detected. This face is degenerated,
1612       // its index, its three vertex indices together with its inradius are reported
1613       ptr = getIds(ptr, ID, nodeIds);
1614       ptr = getIds(ptr, TRIA, nodeIds);
1615       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
1616       // add triangle edges as it most probably has zero area and hence invisible
1617       {
1618         vector<int> edgeNodes(2);
1619         edgeNodes[0] = nodeIds[0]; edgeNodes[1] = nodeIds[1]; // 0-1
1620         badElems.push_back( toSmdsConvertor.getElement(edgeNodes));
1621         edgeNodes[1] = nodeIds[2]; // 0-2
1622         badElems.push_back( toSmdsConvertor.getElement(edgeNodes));
1623         edgeNodes[0] = nodeIds[1]; // 1-2
1624         badElems.push_back( toSmdsConvertor.getElement(edgeNodes));
1625       }
1626       break;
1627     }
1628
1629     bool isNewError = foundErrorStr.insert( string( errBeg, ptr )).second;
1630     if ( !isNewError )
1631       continue; // not to report same error several times
1632
1633 //     const SMDS_MeshElement* nullElem = 0;
1634 //     bool allElemsOk = ( find( badElems.begin(), badElems.end(), nullElem) == badElems.end());
1635
1636 //     if ( allElemsOk && !badElems.empty() && !elemErrorNums.empty() ) {
1637 //       bool oneMoreErrorType = elemErrorNums.insert( errNum ).second;
1638 //       if ( oneMoreErrorType )
1639 //         continue; // not to report different types of errors with bad elements
1640 //     }
1641
1642     // store bad elements
1643     //if ( allElemsOk ) {
1644       list<const SMDS_MeshElement*>::iterator elem = badElems.begin();
1645       for ( ; elem != badElems.end(); ++elem )
1646         addBadInputElement( *elem );
1647       //}
1648
1649     // make error text
1650     string text = translateError( errNum );
1651     if ( errDescription.find( text ) == text.npos ) {
1652       if ( !errDescription.empty() )
1653         errDescription << "\n";
1654       errDescription << text;
1655     }
1656
1657   } // end while
1658
1659   if ( errDescription.empty() ) { // no errors found
1660     char msg[] = "connection to server failed";
1661     if ( search( &buf[0], bufEnd, msg, msg + strlen(msg)) != bufEnd )
1662       errDescription << "Licence problems.";
1663   }
1664
1665   if ( errDescription.empty() )
1666     errDescription << "See " << logFile << " for problem description";
1667   else
1668     errDescription << "\nSee " << logFile << " for more information";
1669
1670   return error( errDescription );
1671 }
1672
1673 //================================================================================
1674 /*!
1675  * \brief Creates _Ghs2smdsConvertor
1676  */
1677 //================================================================================
1678
1679 _Ghs2smdsConvertor::_Ghs2smdsConvertor( const map <int,const SMDS_MeshNode*> & ghs2NodeMap)
1680   :_ghs2NodeMap( & ghs2NodeMap ), _nodeByGhsId( 0 )
1681 {
1682 }
1683
1684 //================================================================================
1685 /*!
1686  * \brief Creates _Ghs2smdsConvertor
1687  */
1688 //================================================================================
1689
1690 _Ghs2smdsConvertor::_Ghs2smdsConvertor( const vector <const SMDS_MeshNode*> &  nodeByGhsId)
1691   : _ghs2NodeMap( 0 ), _nodeByGhsId( &nodeByGhsId )
1692 {
1693 }
1694
1695 //================================================================================
1696 /*!
1697  * \brief Return SMDS element by ids of GHS3D nodes
1698  */
1699 //================================================================================
1700
1701 const SMDS_MeshElement* _Ghs2smdsConvertor::getElement(const vector<int>& ghsNodes) const
1702 {
1703   size_t nbNodes = ghsNodes.size();
1704   vector<const SMDS_MeshNode*> nodes( nbNodes, 0 );
1705   for ( size_t i = 0; i < nbNodes; ++i ) {
1706     int ghsNode = ghsNodes[ i ];
1707     if ( _ghs2NodeMap ) {
1708       map <int,const SMDS_MeshNode*>::const_iterator in = _ghs2NodeMap->find( ghsNode);
1709       if ( in == _ghs2NodeMap->end() )
1710         return 0;
1711       nodes[ i ] = in->second;
1712     }
1713     else {
1714       if ( ghsNode < 1 || ghsNode > _nodeByGhsId->size() )
1715         return 0;
1716       nodes[ i ] = (*_nodeByGhsId)[ ghsNode-1 ];
1717     }
1718   }
1719   if ( nbNodes == 1 )
1720     return nodes[0];
1721
1722   if ( nbNodes == 2 ) {
1723     const SMDS_MeshElement* edge= SMDS_Mesh::FindEdge( nodes[0], nodes[1] );
1724     if ( !edge )
1725       edge = new SMDS_MeshEdge( nodes[0], nodes[1] );
1726     return edge;
1727   }
1728   if ( nbNodes == 3 ) {
1729     const SMDS_MeshElement* face = SMDS_Mesh::FindFace( nodes );
1730     if ( !face )
1731       face = new SMDS_FaceOfNodes( nodes[0], nodes[1], nodes[2] );
1732     return face;
1733   }
1734   if ( nbNodes == 4 )
1735     return new SMDS_VolumeOfNodes( nodes[0], nodes[1], nodes[2], nodes[3] );
1736
1737   return 0;
1738 }
1739
1740
1741 //=============================================================================
1742 /*!
1743  *  
1744  */
1745 //=============================================================================
1746 bool GHS3DPlugin_GHS3D::Evaluate(SMESH_Mesh& aMesh,
1747                                  const TopoDS_Shape& aShape,
1748                                  MapShapeNbElems& aResMap)
1749 {
1750   int nbtri = 0, nbqua = 0;
1751   double fullArea = 0.0;
1752   for (TopExp_Explorer exp(aShape, TopAbs_FACE); exp.More(); exp.Next()) {
1753     TopoDS_Face F = TopoDS::Face( exp.Current() );
1754     SMESH_subMesh *sm = aMesh.GetSubMesh(F);
1755     MapShapeNbElemsItr anIt = aResMap.find(sm);
1756     if( anIt==aResMap.end() ) {
1757       SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
1758       smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,
1759                                             "Submesh can not be evaluated",this));
1760       return false;
1761     }
1762     std::vector<int> aVec = (*anIt).second;
1763     nbtri += Max(aVec[SMDSEntity_Triangle],aVec[SMDSEntity_Quad_Triangle]);
1764     nbqua += Max(aVec[SMDSEntity_Quadrangle],aVec[SMDSEntity_Quad_Quadrangle]);
1765     GProp_GProps G;
1766     BRepGProp::SurfaceProperties(F,G);
1767     double anArea = G.Mass();
1768     fullArea += anArea;
1769   }
1770
1771   // collect info from edges
1772   int nb0d_e = 0, nb1d_e = 0;
1773   bool IsQuadratic = false;
1774   bool IsFirst = true;
1775   TopTools_MapOfShape tmpMap;
1776   for (TopExp_Explorer exp(aShape, TopAbs_EDGE); exp.More(); exp.Next()) {
1777     TopoDS_Edge E = TopoDS::Edge(exp.Current());
1778     if( tmpMap.Contains(E) )
1779       continue;
1780     tmpMap.Add(E);
1781     SMESH_subMesh *aSubMesh = aMesh.GetSubMesh(exp.Current());
1782     MapShapeNbElemsItr anIt = aResMap.find(aSubMesh);
1783     std::vector<int> aVec = (*anIt).second;
1784     nb0d_e += aVec[SMDSEntity_Node];
1785     nb1d_e += Max(aVec[SMDSEntity_Edge],aVec[SMDSEntity_Quad_Edge]);
1786     if(IsFirst) {
1787       IsQuadratic = (aVec[SMDSEntity_Quad_Edge] > aVec[SMDSEntity_Edge]);
1788       IsFirst = false;
1789     }
1790   }
1791   tmpMap.Clear();
1792
1793   double ELen = sqrt(2.* ( fullArea/(nbtri+nbqua*2) ) / sqrt(3.0) );
1794
1795   GProp_GProps G;
1796   BRepGProp::VolumeProperties(aShape,G);
1797   double aVolume = G.Mass();
1798   double tetrVol = 0.1179*ELen*ELen*ELen;
1799   double CoeffQuality = 0.9;
1800   int nbVols = int(aVolume/tetrVol/CoeffQuality);
1801   int nb1d_f = (nbtri*3 + nbqua*4 - nb1d_e) / 2;
1802   int nb1d_in = (int) ( nbVols*6 - nb1d_e - nb1d_f ) / 5;
1803   std::vector<int> aVec(SMDSEntity_Last);
1804   for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aVec[i]=0;
1805   if( IsQuadratic ) {
1806     aVec[SMDSEntity_Node] = nb1d_in/6 + 1 + nb1d_in;
1807     aVec[SMDSEntity_Quad_Tetra] = nbVols - nbqua*2;
1808     aVec[SMDSEntity_Quad_Pyramid] = nbqua;
1809   }
1810   else {
1811     aVec[SMDSEntity_Node] = nb1d_in/6 + 1;
1812     aVec[SMDSEntity_Tetra] = nbVols - nbqua*2;
1813     aVec[SMDSEntity_Pyramid] = nbqua;
1814   }
1815   SMESH_subMesh *sm = aMesh.GetSubMesh(aShape);
1816   aResMap.insert(std::make_pair(sm,aVec));
1817
1818   return true;
1819 }