Salome HOME
PR : merge from V7_2_1
[plugins/ghs3dplugin.git] / src / GHS3DPlugin / GHS3DPlugin_GHS3D.cxx
1 // Copyright (C) 2004-2013  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 //=============================================================================
21 // File      : GHS3DPlugin_GHS3D.cxx
22 // Created   : 
23 // Author    : Edward AGAPOV, modified by Lioka RAZAFINDRAZAKA (CEA) 09/02/2007
24 // Project   : SALOME
25 //=============================================================================
26 //
27 #include "GHS3DPlugin_GHS3D.hxx"
28 #include "GHS3DPlugin_Hypothesis.hxx"
29
30 #include <Basics_Utils.hxx>
31
32 //#include <SMESH_Gen.hxx>
33 #include <SMESH_Client.hxx>
34 #include <SMESH_Mesh.hxx>
35 #include <SMESH_Comment.hxx>
36 #include <SMESH_MesherHelper.hxx>
37 #include <SMESH_MeshEditor.hxx>
38 #include <SMESH_OctreeNode.hxx>
39 #include <SMESH_Group.hxx>
40 #include <SMESH_subMeshEventListener.hxx>
41 #include <SMESH_HypoFilter.hxx>
42 #include <SMESH_MeshAlgos.hxx>
43
44 #include <SMDS_MeshElement.hxx>
45 #include <SMDS_MeshNode.hxx>
46 #include <SMDS_FaceOfNodes.hxx>
47 #include <SMDS_VolumeOfNodes.hxx>
48
49 #include <SMESHDS_Group.hxx>
50
51 #include <StdMeshers_QuadToTriaAdaptor.hxx>
52 #include <StdMeshers_ViscousLayers.hxx>
53
54 #include <BRepAdaptor_Surface.hxx>
55 #include <BRepBndLib.hxx>
56 #include <BRepBuilderAPI_MakeVertex.hxx>
57 #include <BRepClass3d_SolidClassifier.hxx>
58 #include <BRepExtrema_DistShapeShape.hxx>
59 #include <BRepGProp.hxx>
60 #include <BRepTools.hxx>
61 #include <BRep_Tool.hxx>
62 #include <Bnd_Box.hxx>
63 #include <GProp_GProps.hxx>
64 #include <GeomAPI_ProjectPointOnSurf.hxx>
65 #include <OSD_File.hxx>
66 #include <Precision.hxx>
67 #include <Quantity_Parameter.hxx>
68 #include <Standard_ErrorHandler.hxx>
69 #include <Standard_Failure.hxx>
70 #include <Standard_ProgramError.hxx>
71 #include <TopExp.hxx>
72 #include <TopExp_Explorer.hxx>
73 #include <TopTools_IndexedMapOfShape.hxx>
74 #include <TopTools_ListIteratorOfListOfShape.hxx>
75 #include <TopTools_MapOfShape.hxx>
76 #include <TopoDS.hxx>
77 #include <TopoDS_Shape.hxx>
78 #include <TopoDS_Solid.hxx>
79
80 #include <utilities.h>
81
82 #ifdef WIN32
83 #include <io.h>
84 #else
85 #include <sys/sysinfo.h>
86 #endif
87 #include <algorithm>
88
89 //#include <Standard_Stream.hxx>
90
91
92 #define castToNode(n) static_cast<const SMDS_MeshNode *>( n );
93
94 #ifdef _DEBUG_
95 #define DUMP(txt) \
96 //  std::cout << txt
97 #else
98 #define DUMP(txt)
99 #endif
100
101 extern "C"
102 {
103 #ifndef WNT
104 #include <unistd.h>
105 #include <sys/mman.h>
106 #endif
107 #include <sys/stat.h>
108 #include <fcntl.h>
109 }
110
111 #define HOLE_ID -1
112
113 typedef const list<const SMDS_MeshFace*> TTriaList;
114
115 static const char theDomainGroupNamePrefix[] = "Domain_";
116
117 static void removeFile( const TCollection_AsciiString& fileName )
118 {
119   try {
120     OSD_File( fileName ).Remove();
121   }
122   catch ( Standard_ProgramError ) {
123     MESSAGE("Can't remove file: " << fileName.ToCString() << " ; file does not exist or permission denied");
124   }
125 }
126
127 //=============================================================================
128 /*!
129  *  
130  */
131 //=============================================================================
132
133 GHS3DPlugin_GHS3D::GHS3DPlugin_GHS3D(int hypId, int studyId, SMESH_Gen* gen)
134   : SMESH_3D_Algo(hypId, studyId, gen)
135 {
136   MESSAGE("GHS3DPlugin_GHS3D::GHS3DPlugin_GHS3D");
137   _name = Name();
138   _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);// 1 bit /shape type
139   _onlyUnaryInput = false; // Compute() will be called on a compound of solids
140   _iShape=0;
141   _nbShape=0;
142   _compatibleHypothesis.push_back( GHS3DPlugin_Hypothesis::GetHypType());
143   _compatibleHypothesis.push_back( StdMeshers_ViscousLayers::GetHypType() );
144   _requireShape = false; // can work without shape_studyId
145
146   smeshGen_i = SMESH_Gen_i::GetSMESHGen();
147   CORBA::Object_var anObject = smeshGen_i->GetNS()->Resolve("/myStudyManager");
148   SALOMEDS::StudyManager_var aStudyMgr = SALOMEDS::StudyManager::_narrow(anObject);
149
150   MESSAGE("studyid = " << _studyId);
151
152   myStudy = NULL;
153   myStudy = aStudyMgr->GetStudyByID(_studyId);
154   if (myStudy)
155     MESSAGE("myStudy->StudyId() = " << myStudy->StudyId());
156   
157   _compute_canceled = false;
158 }
159
160 //=============================================================================
161 /*!
162  *  
163  */
164 //=============================================================================
165
166 GHS3DPlugin_GHS3D::~GHS3DPlugin_GHS3D()
167 {
168   MESSAGE("GHS3DPlugin_GHS3D::~GHS3DPlugin_GHS3D");
169 }
170
171 //=============================================================================
172 /*!
173  *  
174  */
175 //=============================================================================
176
177 bool GHS3DPlugin_GHS3D::CheckHypothesis ( SMESH_Mesh&         aMesh,
178                                           const TopoDS_Shape& aShape,
179                                           Hypothesis_Status&  aStatus )
180 {
181   aStatus = SMESH_Hypothesis::HYP_OK;
182
183   _hyp = 0;
184   _viscousLayersHyp = 0;
185   _keepFiles = false;
186
187   const list <const SMESHDS_Hypothesis * >& hyps =
188     GetUsedHypothesis(aMesh, aShape, /*ignoreAuxiliary=*/false);
189   list <const SMESHDS_Hypothesis* >::const_iterator h = hyps.begin();
190   for ( ; h != hyps.end(); ++h )
191   {
192     if ( !_hyp )
193       _hyp = dynamic_cast< const GHS3DPlugin_Hypothesis*> ( *h );
194     if ( !_viscousLayersHyp )
195       _viscousLayersHyp = dynamic_cast< const StdMeshers_ViscousLayers*> ( *h );
196   }
197   if ( _hyp )
198     _keepFiles = _hyp->GetKeepFiles();
199
200   return true;
201 }
202
203
204 //=======================================================================
205 //function : entryToShape
206 //purpose  : 
207 //=======================================================================
208
209 TopoDS_Shape GHS3DPlugin_GHS3D::entryToShape(std::string entry)
210 {
211   MESSAGE("GHS3DPlugin_GHS3D::entryToShape "<<entry );
212   GEOM::GEOM_Object_var aGeomObj;
213   TopoDS_Shape S = TopoDS_Shape();
214   SALOMEDS::SObject_var aSObj = myStudy->FindObjectID( entry.c_str() );
215   if (!aSObj->_is_nil() ) {
216     CORBA::Object_var obj = aSObj->GetObject();
217     aGeomObj = GEOM::GEOM_Object::_narrow(obj);
218     aSObj->UnRegister();
219   }
220   if ( !aGeomObj->_is_nil() )
221     S = smeshGen_i->GeomObjectToShape( aGeomObj.in() );
222   return S;
223 }
224
225 //=======================================================================
226 //function : findShape
227 //purpose  : 
228 //=======================================================================
229
230 static TopoDS_Shape findShape(const SMDS_MeshNode *aNode[],
231                               TopoDS_Shape        aShape,
232                               const TopoDS_Shape  shape[],
233                               double**            box,
234                               const int           nShape,
235                               TopAbs_State *      state = 0)
236 {
237   gp_XYZ aPnt(0,0,0);
238   int j, iShape, nbNode = 4;
239
240   for ( j=0; j<nbNode; j++ ) {
241     gp_XYZ p ( aNode[j]->X(), aNode[j]->Y(), aNode[j]->Z() );
242     if ( aNode[j]->GetPosition()->GetTypeOfPosition() == SMDS_TOP_3DSPACE ) {
243       aPnt = p;
244       break;
245     }
246     aPnt += p / nbNode;
247   }
248
249   BRepClass3d_SolidClassifier SC (aShape, aPnt, Precision::Confusion());
250   if (state) *state = SC.State();
251   if ( SC.State() != TopAbs_IN || aShape.IsNull() || aShape.ShapeType() != TopAbs_SOLID) {
252     for (iShape = 0; iShape < nShape; iShape++) {
253       aShape = shape[iShape];
254       if ( !( aPnt.X() < box[iShape][0] || box[iShape][1] < aPnt.X() ||
255               aPnt.Y() < box[iShape][2] || box[iShape][3] < aPnt.Y() ||
256               aPnt.Z() < box[iShape][4] || box[iShape][5] < aPnt.Z()) ) {
257         BRepClass3d_SolidClassifier SC (aShape, aPnt, Precision::Confusion());
258         if (state) *state = SC.State();
259         if (SC.State() == TopAbs_IN)
260           break;
261       }
262     }
263   }
264   return aShape;
265 }
266
267 //=======================================================================
268 //function : readMapIntLine
269 //purpose  : 
270 //=======================================================================
271
272 static char* readMapIntLine(char* ptr, int tab[]) {
273   long int intVal;
274   std::cout << std::endl;
275
276   for ( int i=0; i<17; i++ ) {
277     intVal = strtol(ptr, &ptr, 10);
278     if ( i < 3 )
279       tab[i] = intVal;
280   }
281   return ptr;
282 }
283
284 //================================================================================
285 /*!
286  * \brief returns true if a triangle defined by the nodes is a temporary face on a
287  * side facet of pyramid and defines sub-domian inside the pyramid
288  */
289 //================================================================================
290
291 static bool isTmpFace(const SMDS_MeshNode* node1,
292                       const SMDS_MeshNode* node2,
293                       const SMDS_MeshNode* node3)
294 {
295   // find a pyramid sharing the 3 nodes
296   //const SMDS_MeshElement* pyram = 0;
297   SMDS_ElemIteratorPtr vIt1 = node1->GetInverseElementIterator(SMDSAbs_Volume);
298   while ( vIt1->more() )
299   {
300     const SMDS_MeshElement* pyram = vIt1->next();
301     if ( pyram->NbCornerNodes() != 5 ) continue;
302     int i2, i3;
303     if ( (i2 = pyram->GetNodeIndex( node2 )) >= 0 &&
304          (i3 = pyram->GetNodeIndex( node3 )) >= 0 )
305     {
306       // Triangle defines sub-domian inside the pyramid if it's
307       // normal points out of the pyram
308
309       // make i2 and i3 hold indices of base nodes of the pyram while
310       // keeping the nodes order in the triangle
311       const int iApex = 4;
312       if ( i2 == iApex )
313         i2 = i3, i3 = pyram->GetNodeIndex( node1 );
314       else if ( i3 == iApex )
315         i3 = i2, i2 = pyram->GetNodeIndex( node1 );
316
317       int i3base = (i2+1) % 4; // next index after i2 within the pyramid base
318       return ( i3base != i3 );
319     }
320   }
321   return false;
322 }
323
324 //=======================================================================
325 //function : findShapeID
326 //purpose  : find the solid corresponding to GHS3D sub-domain following
327 //           the technique proposed in GHS3D manual (available within
328 //           ghs3d installation) in chapter "B.4 Subdomain (sub-region) assignment".
329 //           In brief: normal of the triangle defined by the given nodes
330 //           points out of the domain it is associated to
331 //=======================================================================
332
333 static int findShapeID(SMESH_Mesh&          mesh,
334                        const SMDS_MeshNode* node1,
335                        const SMDS_MeshNode* node2,
336                        const SMDS_MeshNode* node3,
337                        const bool           toMeshHoles)
338 {
339   const int invalidID = 0;
340   SMESHDS_Mesh* meshDS = mesh.GetMeshDS();
341
342   // face the nodes belong to
343   const SMDS_MeshElement * face = meshDS->FindFace(node1,node2,node3);
344   if ( !face )
345     return isTmpFace(node1, node2, node3) ? HOLE_ID : invalidID;
346 #ifdef _DEBUG_
347   std::cout << "bnd face " << face->GetID() << " - ";
348 #endif
349   // geom face the face assigned to
350   SMESH_MeshEditor editor(&mesh);
351   int geomFaceID = editor.FindShape( face );
352   if ( !geomFaceID )
353     return isTmpFace(node1, node2, node3) ? HOLE_ID : invalidID;
354   TopoDS_Shape shape = meshDS->IndexToShape( geomFaceID );
355   if ( shape.IsNull() || shape.ShapeType() != TopAbs_FACE )
356     return invalidID;
357   TopoDS_Face geomFace = TopoDS::Face( shape );
358
359   // solids bounded by geom face
360   TopTools_IndexedMapOfShape solids, shells;
361   TopTools_ListIteratorOfListOfShape ansIt = mesh.GetAncestors(geomFace);
362   for ( ; ansIt.More(); ansIt.Next() ) {
363     switch ( ansIt.Value().ShapeType() ) {
364     case TopAbs_SOLID:
365       solids.Add( ansIt.Value() ); break;
366     case TopAbs_SHELL:
367       shells.Add( ansIt.Value() ); break;
368     default:;
369     }
370   }
371   // analyse found solids
372   if ( solids.Extent() == 0 || shells.Extent() == 0)
373     return invalidID;
374
375   const TopoDS_Solid& solid1 = TopoDS::Solid( solids(1) );
376   if ( solids.Extent() == 1 )
377   {
378     if ( toMeshHoles )
379       return meshDS->ShapeToIndex( solid1 );
380
381     //////////// UNCOMMENT AS SOON AS
382     //////////// http://tracker.dev.opencascade.org/view.php?id=23129
383     //////////// IS SOLVED
384     // - Are we at a hole boundary face?
385     // if ( shells(1).IsSame( BRepTools::OuterShell( solid1 )) )
386     // { // - No, but maybe a hole is bound by two shapes? Does shells(1) touches another shell?
387     //   bool touch = false;
388     //   TopExp_Explorer eExp( shells(1), TopAbs_EDGE );
389     //   // check if any edge of shells(1) belongs to another shell
390     //   for ( ; eExp.More() && !touch; eExp.Next() ) {
391     //     ansIt = mesh.GetAncestors( eExp.Current() );
392     //     for ( ; ansIt.More() && !touch; ansIt.Next() ) {
393     //       if ( ansIt.Value().ShapeType() == TopAbs_SHELL )
394     //         touch = ( !ansIt.Value().IsSame( shells(1) ));
395     //     }
396     //   }
397     //   if (!touch)
398     //     return meshDS->ShapeToIndex( solid1 );
399     // }
400   }
401   // find orientation of geom face within the first solid
402   TopExp_Explorer fExp( solid1, TopAbs_FACE );
403   for ( ; fExp.More(); fExp.Next() )
404     if ( geomFace.IsSame( fExp.Current() )) {
405       geomFace = TopoDS::Face( fExp.Current() );
406       break;
407     }
408   if ( !fExp.More() )
409     return invalidID; // face not found
410
411   // normale to triangle
412   gp_Pnt node1Pnt ( node1->X(), node1->Y(), node1->Z() );
413   gp_Pnt node2Pnt ( node2->X(), node2->Y(), node2->Z() );
414   gp_Pnt node3Pnt ( node3->X(), node3->Y(), node3->Z() );
415   gp_Vec vec12( node1Pnt, node2Pnt );
416   gp_Vec vec13( node1Pnt, node3Pnt );
417   gp_Vec meshNormal = vec12 ^ vec13;
418   if ( meshNormal.SquareMagnitude() < DBL_MIN )
419     return invalidID;
420
421   // get normale to geomFace at any node
422   bool geomNormalOK = false;
423   gp_Vec geomNormal;
424   const SMDS_MeshNode* nodes[3] = { node1, node2, node3 };
425   SMESH_MesherHelper helper( mesh ); helper.SetSubShape( geomFace );
426   for ( int i = 0; !geomNormalOK && i < 3; ++i )
427   {
428     // find UV of i-th node on geomFace
429     const SMDS_MeshNode* nNotOnSeamEdge = 0;
430     if ( helper.IsSeamShape( nodes[i]->getshapeId() )) {
431       if ( helper.IsSeamShape( nodes[(i+1)%3]->getshapeId() ))
432         nNotOnSeamEdge = nodes[(i+2)%3];
433       else
434         nNotOnSeamEdge = nodes[(i+1)%3];
435     }
436     bool uvOK;
437     gp_XY uv = helper.GetNodeUV( geomFace, nodes[i], nNotOnSeamEdge, &uvOK );
438     // check that uv is correct
439     if (uvOK) {
440       double tol = 1e-6;
441       TopoDS_Shape nodeShape = helper.GetSubShapeByNode( nodes[i], meshDS );
442       if ( !nodeShape.IsNull() )
443         switch ( nodeShape.ShapeType() )
444         {
445         case TopAbs_FACE:   tol = BRep_Tool::Tolerance( TopoDS::Face( nodeShape )); break;
446         case TopAbs_EDGE:   tol = BRep_Tool::Tolerance( TopoDS::Edge( nodeShape )); break;
447         case TopAbs_VERTEX: tol = BRep_Tool::Tolerance( TopoDS::Vertex( nodeShape )); break;
448         default:;
449         }
450       gp_Pnt nodePnt ( nodes[i]->X(), nodes[i]->Y(), nodes[i]->Z() );
451       BRepAdaptor_Surface surface( geomFace );
452       uvOK = ( nodePnt.Distance( surface.Value( uv.X(), uv.Y() )) < 2 * tol );
453       if ( uvOK ) {
454         // normale to geomFace at UV
455         gp_Vec du, dv;
456         surface.D1( uv.X(), uv.Y(), nodePnt, du, dv );
457         geomNormal = du ^ dv;
458         if ( geomFace.Orientation() == TopAbs_REVERSED )
459           geomNormal.Reverse();
460         geomNormalOK = ( geomNormal.SquareMagnitude() > DBL_MIN * 1e3 );
461       }
462     }
463   }
464   if ( !geomNormalOK)
465     return invalidID;
466
467   // compare normals
468   bool isReverse = ( meshNormal * geomNormal ) < 0;
469   if ( !isReverse )
470     return meshDS->ShapeToIndex( solid1 );
471
472   if ( solids.Extent() == 1 )
473     return HOLE_ID; // we are inside a hole
474   else
475     return meshDS->ShapeToIndex( solids(2) );
476 }
477
478 // //=======================================================================
479 // //function : countShape
480 // //purpose  :
481 // //=======================================================================
482 // 
483 // template < class Mesh, class Shape >
484 // static int countShape( Mesh* mesh, Shape shape ) {
485 //   TopExp_Explorer expShape ( mesh->ShapeToMesh(), shape );
486 //   TopTools_MapOfShape mapShape;
487 //   int nbShape = 0;
488 //   for ( ; expShape.More(); expShape.Next() ) {
489 //     if (mapShape.Add(expShape.Current())) {
490 //       nbShape++;
491 //     }
492 //   }
493 //   return nbShape;
494 // }
495 // 
496 // //=======================================================================
497 // //function : getShape
498 // //purpose  :
499 // //=======================================================================
500 // 
501 // template < class Mesh, class Shape, class Tab >
502 // void getShape(Mesh* mesh, Shape shape, Tab *t_Shape) {
503 //   TopExp_Explorer expShape ( mesh->ShapeToMesh(), shape );
504 //   TopTools_MapOfShape mapShape;
505 //   for ( int i=0; expShape.More(); expShape.Next() ) {
506 //     if (mapShape.Add(expShape.Current())) {
507 //       t_Shape[i] = expShape.Current();
508 //       i++;
509 //     }
510 //   }
511 //   return;
512 // }
513 // 
514 // // //=======================================================================
515 // // //function : findEdgeID
516 // // //purpose  :
517 // // //=======================================================================
518 // 
519 // static int findEdgeID(const SMDS_MeshNode* aNode,
520 //                       const SMESHDS_Mesh*  theMesh,
521 //                       const int            nEdge,
522 //                       const TopoDS_Shape*  t_Edge) {
523 // 
524 //   TopoDS_Shape aPntShape, foundEdge;
525 //   TopoDS_Vertex aVertex;
526 //   gp_Pnt aPnt( aNode->X(), aNode->Y(), aNode->Z() );
527 // 
528 //   int foundInd, ind;
529 //   double nearest = RealLast(), *t_Dist;
530 //   double epsilon = Precision::Confusion();
531 // 
532 //   t_Dist = new double[ nEdge ];
533 //   aPntShape = BRepBuilderAPI_MakeVertex( aPnt ).Shape();
534 //   aVertex   = TopoDS::Vertex( aPntShape );
535 // 
536 //   for ( ind=0; ind < nEdge; ind++ ) {
537 //     BRepExtrema_DistShapeShape aDistance ( aVertex, t_Edge[ind] );
538 //     t_Dist[ind] = aDistance.Value();
539 //     if ( t_Dist[ind] < nearest ) {
540 //       nearest   = t_Dist[ind];
541 //       foundEdge = t_Edge[ind];
542 //       foundInd  = ind;
543 //       if ( nearest < epsilon )
544 //         ind = nEdge;
545 //     }
546 //   }
547 // 
548 //   delete [] t_Dist;
549 //   return theMesh->ShapeToIndex( foundEdge );
550 // }
551 // 
552 // 
553 // // =======================================================================
554 // // function : readGMFFile
555 // // purpose  : read GMF file with geometry associated to mesh
556 // // =======================================================================
557 // 
558 // static bool readGMFFile(const int                       fileOpen,
559 //                         const char*                     theFileName, 
560 //                         SMESH_Mesh&                     theMesh,
561 //                         const int                       nbShape,
562 //                         const TopoDS_Shape*             tabShape,
563 //                         double**                        tabBox,
564 //                         map <int,const SMDS_MeshNode*>& theGhs3dIdToNodeMap,
565 //                         bool                            toMeshHoles,
566 //                         int                             nbEnforcedVertices,
567 //                         int                             nbEnforcedNodes)
568 // {
569 //   TopoDS_Shape aShape;
570 //   TopoDS_Vertex aVertex;
571 //   SMESHDS_Mesh* theMeshDS = theMesh.GetMeshDS();
572 //   int nbElem = 0, nbRef = 0, IdShapeRef = 1;
573 //   int *tabID;
574 //   int aGMFNodeID = 0;
575 //   int compoundID =
576 //     nbShape ? theMeshDS->ShapeToIndex( tabShape[0] ) : theMeshDS->ShapeToIndex( theMeshDS->ShapeToMesh() );
577 //   int tetraShapeID = compoundID;
578 //   double epsilon = Precision::Confusion();
579 //   int *nodeAssigne, *GMFNodeAssigne;
580 //   SMDS_MeshNode** GMFNode;
581 //   TopoDS_Shape *tabCorner, *tabEdge;
582 //   std::map <GmfKwdCod,int> tabRef;
583 //   
584 //   
585 //   int ver, dim;
586 //   MESSAGE("Read " << theFileName << " file");
587 //   int InpMsh = GmfOpenMesh(theFileName, GmfRead, &ver, &dim);
588 //   if (!InpMsh)
589 //     return false;
590 //   
591 //   // ===========================
592 //   // Fill the tabID array: BEGIN
593 //   // ===========================
594 //   
595 //   /*
596 //   The output .mesh file does not contain yet the subdomain-info (Ghs3D 4.2)
597 //   */
598 //   Kernel_Utils::Localizer loc;
599 //   struct stat status;
600 //   size_t      length;
601 // 
602 //   char *ptr, *mapPtr;
603 //   char *tetraPtr;
604 //   int *tab = new int[3];
605 //   
606 //   // Read the file state
607 //   fstat(fileOpen, &status);
608 //   length   = status.st_size;
609 //   
610 //   // Mapping the result file into memory
611 // #ifdef WNT
612 //   HANDLE fd = CreateFile(theFileName, GENERIC_READ, FILE_SHARE_READ,
613 //                          NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
614 //   HANDLE hMapObject = CreateFileMapping(fd, NULL, PAGE_READONLY,
615 //                                         0, (DWORD)length, NULL);
616 //   ptr = ( char* ) MapViewOfFile(hMapObject, FILE_MAP_READ, 0, 0, 0 );
617 // #else
618 //   ptr = (char *) mmap(0,length,PROT_READ,MAP_PRIVATE,fileOpen,0);
619 // #endif
620 //   mapPtr = ptr;
621 // 
622 //   ptr      = readMapIntLine(ptr, tab);
623 //   tetraPtr = ptr;
624 // 
625 //   nbElem            = tab[0];
626 //   int nbNodes       = tab[1];
627 //   
628 //   for (int i=0; i < 4*nbElem; i++)
629 //     strtol(ptr, &ptr, 10);
630 //   
631 //   for (int iNode=1; iNode <= nbNodes; iNode++)
632 //     for (int iCoor=0; iCoor < 3; iCoor++)
633 //       strtod(ptr, &ptr);
634 // 
635 //     
636 //   // Reading the number of triangles which corresponds to the number of sub-domains
637 //   int nbTriangle = strtol(ptr, &ptr, 10);
638 // 
639 //   
640 //   // The keyword does not exist yet => to update when it is created
641 // //   int nbSubdomains = GmfStatKwd(InpMsh, GmfSubdomain);
642 // //   int id_tri[3];
643 // 
644 // 
645 //   tabID = new int[nbTriangle];
646 //   for (int i=0; i < nbTriangle; i++) {
647 //     tabID[i] = 0;
648 //     int nodeId1, nodeId2, nodeId3;
649 //     // find the solid corresponding to GHS3D sub-domain following
650 //     // the technique proposed in GHS3D manual in chapter
651 //     // "B.4 Subdomain (sub-region) assignment"
652 // 
653 //     nodeId1 = strtol(ptr, &ptr, 10);
654 //     nodeId2 = strtol(ptr, &ptr, 10);
655 //     nodeId3 = strtol(ptr, &ptr, 10);
656 // 
657 // //   // The keyword does not exist yet => to update when it is created
658 // //     GmfGetLin(InpMsh, GmfSubdomain, &id_tri[0], &id_tri[1], &id_tri[2]);
659 // //     nodeId1 = id_tri[0];
660 // //     nodeId2 = id_tri[1];
661 // //     nodeId3 = id_tri[2];
662 // 
663 //     if ( nbTriangle > 1 ) {
664 //       // get the nodes indices
665 //       const SMDS_MeshNode* n1 = theGhs3dIdToNodeMap[ nodeId1 ];
666 //       const SMDS_MeshNode* n2 = theGhs3dIdToNodeMap[ nodeId2 ];
667 //       const SMDS_MeshNode* n3 = theGhs3dIdToNodeMap[ nodeId3 ];
668 //       try {
669 //         OCC_CATCH_SIGNALS;
670 //         tabID[i] = findShapeID( theMesh, n1, n2, n3, toMeshHoles );
671 //         // -- 0020330: Pb with ghs3d as a submesh
672 //         // check that found shape is to be meshed
673 //         if ( tabID[i] > 0 ) {
674 //           const TopoDS_Shape& foundShape = theMeshDS->IndexToShape( tabID[i] );
675 //           bool isToBeMeshed = false;
676 //           for ( int iS = 0; !isToBeMeshed && iS < nbShape; ++iS )
677 //             isToBeMeshed = foundShape.IsSame( tabShape[ iS ]);
678 //           if ( !isToBeMeshed )
679 //             tabID[i] = HOLE_ID;
680 //         }
681 //         // END -- 0020330: Pb with ghs3d as a submesh
682 // #ifdef _DEBUG_
683 //         std::cout << i+1 << " subdomain: findShapeID() returns " << tabID[i] << std::endl;
684 // #endif
685 //       }
686 //       catch ( Standard_Failure & ex)
687 //       {
688 // #ifdef _DEBUG_
689 //         std::cout << i+1 << " subdomain: Exception caugt: " << ex.GetMessageString() << std::endl;
690 // #endif
691 //       }
692 //       catch (...) {
693 // #ifdef _DEBUG_
694 //         std::cout << i+1 << " subdomain: unknown exception caught " << std::endl;
695 // #endif
696 //       }
697 //     }
698 //   }
699 //   
700 //   // ===========================
701 //   // Fill the tabID array: END
702 //   // ===========================
703 //   
704 // 
705 //   tabRef[GmfVertices]       = 3;
706 //   tabRef[GmfCorners]        = 1;
707 //   tabRef[GmfEdges]          = 2;
708 //   tabRef[GmfRidges]         = 1;
709 //   tabRef[GmfTriangles]      = 3;
710 // //   tabRef[GmfQuadrilaterals] = 4;
711 //   tabRef[GmfTetrahedra]     = 4;
712 // //   tabRef[GmfHexahedra]      = 8;
713 //   
714 //   SMDS_NodeIteratorPtr itOnGMFInputNode = theMeshDS->nodesIterator();
715 //   while ( itOnGMFInputNode->more() )
716 //     theMeshDS->RemoveNode( itOnGMFInputNode->next() );
717 // 
718 //   
719 //   int nbVertices = GmfStatKwd(InpMsh, GmfVertices);
720 //   int nbCorners = max(countShape( theMeshDS, TopAbs_VERTEX ) , GmfStatKwd(InpMsh, GmfCorners));
721 //   int nbShapeEdge = countShape( theMeshDS, TopAbs_EDGE );
722 // 
723 //   tabCorner       = new TopoDS_Shape[ nbCorners ];
724 //   tabEdge         = new TopoDS_Shape[ nbShapeEdge ];
725 //   nodeAssigne     = new int[ nbVertices + 1 ];
726 //   GMFNodeAssigne  = new int[ nbVertices + 1 ];
727 //   GMFNode         = new SMDS_MeshNode*[ nbVertices + 1 ];
728 // 
729 //   getShape(theMeshDS, TopAbs_VERTEX, tabCorner);
730 //   getShape(theMeshDS, TopAbs_EDGE,   tabEdge);
731 // 
732 //   std::map <GmfKwdCod,int>::const_iterator it = tabRef.begin();
733 //   for ( ; it != tabRef.end() ; ++it)
734 //   {
735 // //     int dummy;
736 //     GmfKwdCod token = it->first;
737 //     nbRef    = it->second;
738 // 
739 //     nbElem = GmfStatKwd(InpMsh, token);
740 //     if (nbElem > 0) {
741 //       GmfGotoKwd(InpMsh, token);
742 //       std::cout << "Read " << nbElem;
743 //     }
744 //     else
745 //       continue;
746 // 
747 //     int id[nbElem*tabRef[token]];
748 //     int ghs3dShapeID[nbElem];
749 // 
750 //     if (token == GmfVertices) {
751 //       std::cout << " vertices" << std::endl;
752 //       int aGMFID;
753 // 
754 //       float VerTab_f[nbElem][3];
755 //       double VerTab_d[nbElem][3];
756 //       SMDS_MeshNode * aGMFNode;
757 // 
758 //       for ( int iElem = 0; iElem < nbElem; iElem++ ) {
759 //         aGMFID = iElem + 1;
760 //         if (ver == GmfFloat) {
761 //           GmfGetLin(InpMsh, token, &VerTab_f[nbElem][0], &VerTab_f[nbElem][1], &VerTab_f[nbElem][2], &ghs3dShapeID[iElem]);
762 //           aGMFNode = theMeshDS->AddNode(VerTab_f[nbElem][0], VerTab_f[nbElem][1], VerTab_f[nbElem][2]);
763 //         }
764 //         else {
765 //           GmfGetLin(InpMsh, token, &VerTab_d[nbElem][0], &VerTab_d[nbElem][1], &VerTab_d[nbElem][2], &ghs3dShapeID[iElem]);
766 //           aGMFNode = theMeshDS->AddNode(VerTab_d[nbElem][0], VerTab_d[nbElem][1], VerTab_d[nbElem][2]);
767 //         }
768 //         GMFNode[ aGMFID ] = aGMFNode;
769 //         nodeAssigne[ aGMFID ] = 0;
770 //         GMFNodeAssigne[ aGMFID ] = 0;
771 //       }
772 //     }
773 //     else if (token == GmfCorners && nbElem > 0) {
774 //       std::cout << " corners" << std::endl;
775 //       for ( int iElem = 0; iElem < nbElem; iElem++ )
776 //         GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]]);
777 //     }
778 //     else if (token == GmfRidges && nbElem > 0) {
779 //       std::cout << " ridges" << std::endl;
780 //       for ( int iElem = 0; iElem < nbElem; iElem++ )
781 //         GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]]);
782 //     }
783 //     else if (token == GmfEdges && nbElem > 0) {
784 //       std::cout << " edges" << std::endl;
785 //       for ( int iElem = 0; iElem < nbElem; iElem++ )
786 //         GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &ghs3dShapeID[iElem]);
787 //     }
788 //     else if (token == GmfTriangles && nbElem > 0) {
789 //       std::cout << " triangles" << std::endl;
790 //       for ( int iElem = 0; iElem < nbElem; iElem++ )
791 //         GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &id[iElem*tabRef[token]+2], &ghs3dShapeID[iElem]);
792 //     }
793 // //     else if (token == GmfQuadrilaterals && nbElem > 0) {
794 // //       std::cout << " Quadrilaterals" << std::endl;
795 // //       for ( int iElem = 0; iElem < nbElem; iElem++ )
796 // //         GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &id[iElem*tabRef[token]+2], &id[iElem*tabRef[token]+3], &ghs3dShapeID[iElem]);
797 // //     }
798 //     else if (token == GmfTetrahedra && nbElem > 0) {
799 //       std::cout << " Tetrahedra" << std::endl;
800 //       for ( int iElem = 0; iElem < nbElem; iElem++ )
801 //         GmfGetLin(InpMsh, token, 
802 //                   &id[iElem*tabRef[token]], 
803 //                   &id[iElem*tabRef[token]+1], 
804 //                   &id[iElem*tabRef[token]+2], 
805 //                   &id[iElem*tabRef[token]+3], 
806 //                   &ghs3dShapeID[iElem]);
807 //     }
808 // //     else if (token == GmfHexahedra && nbElem > 0) {
809 // //       std::cout << " Hexahedra" << std::endl;
810 // //       for ( int iElem = 0; iElem < nbElem; iElem++ )
811 // //         GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &id[iElem*tabRef[token]+2], &id[iElem*tabRef[token]+3],
812 // //                   &id[iElem*tabRef[token]+4], &id[iElem*tabRef[token]+5], &id[iElem*tabRef[token]+6], &id[iElem*tabRef[token]+7], &ghs3dShapeID[iElem]);
813 // //     }
814 // 
815 //     switch (token) {
816 //     case GmfCorners:
817 //     case GmfRidges:
818 //     case GmfEdges:
819 //     case GmfTriangles:
820 // //     case GmfQuadrilaterals:
821 //     case GmfTetrahedra:
822 // //     case GmfHexahedra:
823 //     {
824 //       int nodeDim, shapeID, *nodeID;
825 //       const SMDS_MeshNode** node;
826 // //       std::vector< SMDS_MeshNode* > enfNode( nbRef );
827 //       SMDS_MeshElement * aGMFElement;
828 //       
829 //       node    = new const SMDS_MeshNode*[nbRef];
830 //       nodeID  = new int[ nbRef ];
831 // 
832 //       for ( int iElem = 0; iElem < nbElem; iElem++ )
833 //       {
834 //         for ( int iRef = 0; iRef < nbRef; iRef++ )
835 //         {
836 //           aGMFNodeID = id[iElem*tabRef[token]+iRef]; // read nbRef aGMFNodeID
837 //           node  [ iRef ] = GMFNode[ aGMFNodeID ];
838 //           nodeID[ iRef ] = aGMFNodeID;
839 //         }
840 // 
841 //         switch (token)
842 //         {
843 //         case GmfCorners: {
844 //           nodeDim = 1;
845 //           gp_Pnt GMFPnt ( node[0]->X(), node[0]->Y(), node[0]->Z() );
846 //           for ( int i=0; i<nbElem; i++ ) {
847 //             aVertex = TopoDS::Vertex( tabCorner[i] );
848 //             gp_Pnt aPnt = BRep_Tool::Pnt( aVertex );
849 //             if ( aPnt.Distance( GMFPnt ) < epsilon )
850 //               break;
851 //           }
852 //           break;
853 //         }
854 //         case GmfEdges: {
855 //           nodeDim = 2;
856 //           aGMFElement = theMeshDS->AddEdge( node[0], node[1] );
857 //           int iNode = 1;
858 //           if ( GMFNodeAssigne[ nodeID[0] ] == 0 || GMFNodeAssigne[ nodeID[0] ] == 2 )
859 //             iNode = 0;
860 //           shapeID = findEdgeID( node[iNode], theMeshDS, nbShapeEdge, tabEdge );
861 //           break;
862 //         }
863 //         case GmfRidges:
864 //           break;
865 //         case GmfTriangles: {
866 //           nodeDim = 3;
867 //           aGMFElement = theMeshDS->AddFace( node[0], node[1], node[2]);
868 //           shapeID = -1;
869 //           break;
870 //         }
871 // //         case GmfQuadrilaterals: {
872 // //           nodeDim = 4;
873 // //           aGMFElement = theMeshDS->AddFace( node[0], node[1], node[2], node[3] );
874 // //           shapeID = -1;
875 // //           break;
876 // //         }
877 //         case GmfTetrahedra: {
878 //           
879 //           // IN WORK
880 //           TopoDS_Shape aSolid;
881 //           // We always run GHS3D with "to mesh holes"==TRUE but we must not create
882 //           // tetras within holes depending on hypo option,
883 //           // so we first check if aTet is inside a hole and then create it 
884 //           if ( nbTriangle > 1 ) {
885 //             tetraShapeID = HOLE_ID; // negative tetraShapeID means not to create tetras if !toMeshHoles
886 //             int aGhs3dShapeID = ghs3dShapeID[iElem] - IdShapeRef;
887 //             if ( tabID[ aGhs3dShapeID ] == 0 ) {
888 //               TopAbs_State state;
889 //               aSolid = findShape(node, aSolid, tabShape, tabBox, nbShape, &state);
890 //               if ( toMeshHoles || state == TopAbs_IN )
891 //                 tetraShapeID = theMeshDS->ShapeToIndex( aSolid );
892 //               tabID[ aGhs3dShapeID ] = tetraShapeID;
893 //             }
894 //             else
895 //               tetraShapeID = tabID[ aGhs3dShapeID ];
896 //           }
897 //           else if ( nbShape > 1 ) {
898 //             // Case where nbTriangle == 1 while nbShape == 2 encountered
899 //             // with compound of 2 boxes and "To mesh holes"==False,
900 //             // so there are no subdomains specified for each tetrahedron.
901 //             // Try to guess a solid by a node already bound to shape
902 //             tetraShapeID = 0;
903 //             for ( int i=0; i<4 && tetraShapeID==0; i++ ) {
904 //               if ( nodeAssigne[ nodeID[i] ] == 1 &&
905 //                   node[i]->GetPosition()->GetTypeOfPosition() == SMDS_TOP_3DSPACE &&
906 //                   node[i]->getshapeId() > 1 )
907 //               {
908 //                 tetraShapeID = node[i]->getshapeId();
909 //               }
910 //             }
911 //             if ( tetraShapeID==0 ) {
912 //               aSolid = findShape(node, aSolid, tabShape, tabBox, nbShape);
913 //               tetraShapeID = theMeshDS->ShapeToIndex( aSolid );
914 //             }
915 //           }
916 //           // set new nodes and tetrahedron onto the shape
917 //           for ( int i=0; i<4; i++ ) {
918 //             if ( nodeAssigne[ nodeID[i] ] == 0 ) {
919 //               if ( tetraShapeID != HOLE_ID )
920 //                 theMeshDS->SetNodeInVolume( node[i], tetraShapeID );
921 //               nodeAssigne[ nodeID[i] ] = tetraShapeID;
922 //             }
923 //           }
924 //           if ( toMeshHoles || tetraShapeID != HOLE_ID ) {
925 //             aGMFElement = theMeshDS->AddVolume( node[1], node[0], node[2], node[3] );
926 //             theMeshDS->SetMeshElementOnShape( aGMFElement, tetraShapeID );
927 //           }
928 //           
929 //           // IN WORK
930 //           
931 //           nodeDim = 5;
932 //           break;
933 //         }
934 // //         case GmfHexahedra: {
935 // //           nodeDim = 6;
936 // //           aGMFElement = theMeshDS->AddVolume( node[0], node[3], node[2], node[1],
937 // //                                             node[4], node[7], node[6], node[5] );
938 // //           break;
939 // //         }
940 //         default: continue;
941 //         }
942 //         if (token != GmfRidges)
943 //         {
944 //           for ( int i=0; i<nbRef; i++ ) {
945 //               if ( GMFNodeAssigne[ nodeID[i] ] == 0 ) {
946 //                 if      ( token == GmfCorners )   theMeshDS->SetNodeOnVertex( node[0], aVertex );
947 //                 else if ( token == GmfEdges )     theMeshDS->SetNodeOnEdge( node[i], shapeID );
948 //                 else if ( token == GmfTriangles ) theMeshDS->SetNodeOnFace( node[i], shapeID );
949 //                 GMFNodeAssigne[ nodeID[i] ] = nodeDim;
950 //               }
951 //             }
952 //             if ( token != "Corners" )
953 //               theMeshDS->SetMeshElementOnShape( aGMFElement, shapeID );
954 //         }
955 //       } // for
956 //       
957 //       if ( !toMeshHoles ) {
958 //         map <int,const SMDS_MeshNode*>::iterator itOnNode = theGhs3dIdToNodeMap.find( nbVertices-(nbEnforcedVertices+nbEnforcedNodes) );
959 //         for ( ; itOnNode != theGhs3dIdToNodeMap.end(); ++itOnNode) {
960 //           if ( nodeAssigne[ itOnNode->first ] == HOLE_ID )
961 //             theMeshDS->RemoveFreeNode( itOnNode->second, 0 );
962 //         }
963 //       }
964 //       
965 //       delete [] node;
966 //       delete [] nodeID;
967 //       break;
968 //       } // case GmfTetrahedra
969 //     } // switch(token)
970 //   } // for
971 //   cout << std::endl;
972 //   
973 // #ifdef WNT
974 //   UnmapViewOfFile(mapPtr);
975 //   CloseHandle(hMapObject);
976 //   CloseHandle(fd);
977 // #else
978 //   munmap(mapPtr, length);
979 // #endif
980 //   close(fileOpen);
981 //   
982 //   delete [] tabID;
983 //   delete [] tabCorner;
984 //   delete [] tabEdge;
985 //   delete [] nodeAssigne;
986 //   delete [] GMFNodeAssigne;
987 //   delete [] GMFNode;
988 //   
989 //   return true;
990 // }
991
992
993 //=======================================================================
994 //function : addElemInMeshGroup
995 //purpose  : Update or create groups in mesh
996 //=======================================================================
997
998 static void addElemInMeshGroup(SMESH_Mesh*             theMesh,
999                                const SMDS_MeshElement* anElem,
1000                                std::string&            groupName,
1001                                std::set<std::string>&  groupsToRemove)
1002 {
1003   if ( !anElem ) return; // issue 0021776
1004
1005   bool groupDone = false;
1006   SMESH_Mesh::GroupIteratorPtr grIt = theMesh->GetGroups();
1007   while (grIt->more()) {
1008     SMESH_Group * group = grIt->next();
1009     if ( !group ) continue;
1010     SMESHDS_GroupBase* groupDS = group->GetGroupDS();
1011     if ( !groupDS ) continue;
1012     if ( groupDS->GetType()==anElem->GetType() &&groupName.compare(group->GetName())==0) {
1013       SMESHDS_Group* aGroupDS = static_cast<SMESHDS_Group*>( groupDS );
1014       aGroupDS->SMDSGroup().Add(anElem);
1015       groupDone = true;
1016 //       MESSAGE("Successfully added enforced element to existing group " << groupName);
1017       break;
1018     }
1019   }
1020   
1021   if (!groupDone)
1022   {
1023     int groupId;
1024     SMESH_Group* aGroup = theMesh->AddGroup(anElem->GetType(), groupName.c_str(), groupId);
1025     aGroup->SetName( groupName.c_str() );
1026     SMESHDS_Group* aGroupDS = static_cast<SMESHDS_Group*>( aGroup->GetGroupDS() );
1027     aGroupDS->SMDSGroup().Add(anElem);
1028 //     MESSAGE("Successfully created enforced vertex group " << groupName);
1029     groupDone = true;
1030   }
1031   if (!groupDone)
1032     throw SALOME_Exception(LOCALIZED("A given element was not added to a group"));
1033 }
1034
1035
1036 //=======================================================================
1037 //function : updateMeshGroups
1038 //purpose  : Update or create groups in mesh
1039 //=======================================================================
1040
1041 static void updateMeshGroups(SMESH_Mesh* theMesh, std::set<std::string> groupsToRemove)
1042 {
1043   SMESH_Mesh::GroupIteratorPtr grIt = theMesh->GetGroups();
1044   while (grIt->more()) {
1045     SMESH_Group * group = grIt->next();
1046     if ( !group ) continue;
1047     SMESHDS_GroupBase* groupDS = group->GetGroupDS();
1048     if ( !groupDS ) continue;
1049     std::string currentGroupName = (string)group->GetName();
1050     if (groupDS->IsEmpty() && groupsToRemove.find(currentGroupName) != groupsToRemove.end()) {
1051       // Previous group created by enforced elements
1052       MESSAGE("Delete previous group created by removed enforced elements: " << group->GetName())
1053       theMesh->RemoveGroup(groupDS->GetID());
1054     }
1055   }
1056 }
1057
1058 //=======================================================================
1059 //function : removeEmptyGroupsOfDomains
1060 //purpose  : remove empty groups named "Domain_nb" created due to
1061 //           "To make groups of domains" option.
1062 //=======================================================================
1063
1064 static void removeEmptyGroupsOfDomains(SMESH_Mesh* mesh,
1065                                        bool        notEmptyAsWell = false)
1066 {
1067   const char* refName = theDomainGroupNamePrefix;
1068   const size_t refLen = strlen( theDomainGroupNamePrefix );
1069
1070   std::list<int> groupIDs = mesh->GetGroupIds();
1071   std::list<int>::const_iterator id = groupIDs.begin();
1072   for ( ; id != groupIDs.end(); ++id )
1073   {
1074     SMESH_Group* group = mesh->GetGroup( *id );
1075     if ( !group || ( !group->GetGroupDS()->IsEmpty() && !notEmptyAsWell ))
1076       continue;
1077     const char* name = group->GetName();
1078     char* end;
1079     // check the name
1080     if ( strncmp( name, refName, refLen ) == 0 && // starts from refName;
1081          isdigit( *( name + refLen )) &&          // refName is followed by a digit;
1082          strtol( name + refLen, &end, 10) &&      // there are only digits ...
1083          *end == '\0')                            // ... till a string end.
1084     {
1085       mesh->RemoveGroup( *id );
1086     }
1087   }
1088 }
1089
1090 //=======================================================================
1091 //function : readGMFFile
1092 //purpose  : read GMF file w/o geometry associated to mesh
1093 //=======================================================================
1094
1095 static bool readGMFFile(const char*                     theFile,
1096                         GHS3DPlugin_GHS3D*              theAlgo,
1097                         SMESH_MesherHelper*             theHelper,
1098                         TopoDS_Shape                    theSolid,
1099                         vector <const SMDS_MeshNode*> & theNodeByGhs3dId,
1100                         map<const SMDS_MeshNode*,int> & theNodeToGhs3dIdMap,
1101                         std::vector<std::string> &      aNodeGroupByGhs3dId,
1102                         std::vector<std::string> &      anEdgeGroupByGhs3dId,
1103                         std::vector<std::string> &      aFaceGroupByGhs3dId,
1104                         std::set<std::string> &         groupsToRemove,
1105                         bool                            toMakeGroupsOfDomains=false)
1106 {
1107   std::string tmpStr;
1108   SMESHDS_Mesh* theMeshDS = theHelper->GetMeshDS();
1109
1110   int nbInitialNodes = theNodeByGhs3dId.size();
1111   int nbMeshNodes = theMeshDS->NbNodes();
1112   
1113   const bool isQuadMesh = 
1114     theHelper->GetMesh()->NbEdges( ORDER_QUADRATIC ) ||
1115     theHelper->GetMesh()->NbFaces( ORDER_QUADRATIC ) ||
1116     theHelper->GetMesh()->NbVolumes( ORDER_QUADRATIC );
1117     
1118 #ifdef _DEBUG_
1119   std::cout << "theNodeByGhs3dId.size(): " << nbInitialNodes << std::endl;
1120   std::cout << "theHelper->GetMesh()->NbNodes(): " << nbMeshNodes << std::endl;
1121   std::cout << "isQuadMesh: " << isQuadMesh << std::endl;
1122 #endif
1123   
1124   if (theHelper->GetSubShapeID() != 0)
1125     theHelper->IsQuadraticSubMesh( theHelper->GetSubShape() );
1126
1127   // ---------------------------------
1128   // Read generated elements and nodes
1129   // ---------------------------------
1130
1131   int nbElem = 0, nbRef = 0;
1132   int aGMFNodeID = 0;
1133   const SMDS_MeshNode** GMFNode;
1134 #ifdef _DEBUG_
1135   std::map<int, std::set<int> > subdomainId2tetraId;
1136 #endif
1137   std::map <GmfKwdCod,int> tabRef;
1138   const bool force3d = true; // since there is no geometry
1139   const int  noID  = 0;
1140
1141   tabRef[GmfVertices]       = 3; // for new nodes and enforced nodes
1142   tabRef[GmfCorners]        = 1;
1143   tabRef[GmfEdges]          = 2; // for enforced edges
1144   tabRef[GmfRidges]         = 1;
1145   tabRef[GmfTriangles]      = 3; // for enforced faces
1146   tabRef[GmfQuadrilaterals] = 4;
1147   tabRef[GmfTetrahedra]     = 4; // for new tetras
1148   tabRef[GmfHexahedra]      = 8;
1149
1150   int ver, dim;
1151   MESSAGE("Read " << theFile << " file");
1152   int InpMsh = GmfOpenMesh(theFile, GmfRead, &ver, &dim);
1153   if (!InpMsh)
1154     return false;
1155   MESSAGE("Done ");
1156
1157   // Issue 0020682. Avoid creating nodes and tetras at place where
1158   // volumic elements already exist
1159   SMESH_ElementSearcher* elemSearcher = 0;
1160   std::vector< const SMDS_MeshElement* > foundVolumes;
1161   if ( theHelper->GetMesh()->NbVolumes() > 0 )
1162     elemSearcher = SMESH_MeshAlgos::GetElementSearcher( *theHelper->GetMeshDS() );
1163
1164   // IMP 0022172: [CEA 790] create the groups corresponding to domains
1165   std::vector< std::vector< const SMDS_MeshElement* > > elemsOfDomain;
1166
1167   int nbVertices = GmfStatKwd(InpMsh, GmfVertices) - nbInitialNodes;
1168   GMFNode = new const SMDS_MeshNode*[ nbVertices + 1 ];
1169
1170   std::map <GmfKwdCod,int>::const_iterator it = tabRef.begin();
1171   for ( ; it != tabRef.end() ; ++it)
1172   {
1173     if(theAlgo->computeCanceled()) {
1174       GmfCloseMesh(InpMsh);
1175       delete [] GMFNode;
1176       return false;
1177     }
1178     int dummy;
1179     GmfKwdCod token = it->first;
1180     nbRef           = it->second;
1181
1182     nbElem = GmfStatKwd(InpMsh, token);
1183     if (nbElem > 0) {
1184       GmfGotoKwd(InpMsh, token);
1185       std::cout << "Read " << nbElem;
1186     }
1187     else
1188       continue;
1189
1190     std::vector<int> id (nbElem*tabRef[token]); // node ids
1191     std::vector<int> domainID( nbElem ); // domain
1192
1193     if (token == GmfVertices) {
1194       (nbElem <= 1) ? tmpStr = " vertex" : tmpStr = " vertices";
1195 //       std::cout << nbInitialNodes << " from input mesh " << std::endl;
1196
1197       // Remove orphan nodes from previous enforced mesh which was cleared
1198 //       if ( nbElem < nbMeshNodes ) {
1199 //         const SMDS_MeshNode* node;
1200 //         SMDS_NodeIteratorPtr nodeIt = theMeshDS->nodesIterator();
1201 //         while ( nodeIt->more() )
1202 //         {
1203 //           node = nodeIt->next();
1204 //           if (theNodeToGhs3dIdMap.find(node) != theNodeToGhs3dIdMap.end())
1205 //             theMeshDS->RemoveNode(node);
1206 //         }
1207 //       }
1208
1209       
1210       int aGMFID;
1211
1212       float VerTab_f[3];
1213       double x, y, z;
1214       const SMDS_MeshNode * aGMFNode;
1215
1216       for ( int iElem = 0; iElem < nbElem; iElem++ ) {
1217         if(theAlgo->computeCanceled()) {
1218           GmfCloseMesh(InpMsh);
1219           delete [] GMFNode;
1220           return false;
1221         }
1222         if (ver == GmfFloat) {
1223           GmfGetLin(InpMsh, token, &VerTab_f[0], &VerTab_f[1], &VerTab_f[2], &dummy);
1224           x = VerTab_f[0];
1225           y = VerTab_f[1];
1226           z = VerTab_f[2];
1227         }
1228         else {
1229           GmfGetLin(InpMsh, token, &x, &y, &z, &dummy);
1230         }
1231         if (iElem >= nbInitialNodes) {
1232           if ( elemSearcher &&
1233                 elemSearcher->FindElementsByPoint( gp_Pnt(x,y,z), SMDSAbs_Volume, foundVolumes))
1234             aGMFNode = 0;
1235           else
1236             aGMFNode = theHelper->AddNode(x, y, z);
1237           
1238           aGMFID = iElem -nbInitialNodes +1;
1239           GMFNode[ aGMFID ] = aGMFNode;
1240           if (aGMFID-1 < aNodeGroupByGhs3dId.size() && !aNodeGroupByGhs3dId.at(aGMFID-1).empty())
1241             addElemInMeshGroup(theHelper->GetMesh(), aGMFNode, aNodeGroupByGhs3dId.at(aGMFID-1), groupsToRemove);
1242         }
1243       }
1244     }
1245     else if (token == GmfCorners && nbElem > 0) {
1246       (nbElem <= 1) ? tmpStr = " corner" : tmpStr = " corners";
1247       for ( int iElem = 0; iElem < nbElem; iElem++ )
1248         GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]]);
1249     }
1250     else if (token == GmfRidges && nbElem > 0) {
1251       (nbElem <= 1) ? tmpStr = " ridge" : tmpStr = " ridges";
1252       for ( int iElem = 0; iElem < nbElem; iElem++ )
1253         GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]]);
1254     }
1255     else if (token == GmfEdges && nbElem > 0) {
1256       (nbElem <= 1) ? tmpStr = " edge" : tmpStr = " edges";
1257       for ( int iElem = 0; iElem < nbElem; iElem++ )
1258         GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &domainID[iElem]);
1259     }
1260     else if (token == GmfTriangles && nbElem > 0) {
1261       (nbElem <= 1) ? tmpStr = " triangle" : tmpStr = " triangles";
1262       for ( int iElem = 0; iElem < nbElem; iElem++ )
1263         GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &id[iElem*tabRef[token]+2], &domainID[iElem]);
1264     }
1265     else if (token == GmfQuadrilaterals && nbElem > 0) {
1266       (nbElem <= 1) ? tmpStr = " Quadrilateral" : tmpStr = " Quadrilaterals";
1267       for ( int iElem = 0; iElem < nbElem; iElem++ )
1268         GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &id[iElem*tabRef[token]+2], &id[iElem*tabRef[token]+3], &domainID[iElem]);
1269     }
1270     else if (token == GmfTetrahedra && nbElem > 0) {
1271       (nbElem <= 1) ? tmpStr = " Tetrahedron" : tmpStr = " Tetrahedra";
1272       for ( int iElem = 0; iElem < nbElem; iElem++ ) {
1273         GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &id[iElem*tabRef[token]+2], &id[iElem*tabRef[token]+3], &domainID[iElem]);
1274 #ifdef _DEBUG_
1275         subdomainId2tetraId[dummy].insert(iElem+1);
1276 //         MESSAGE("subdomainId2tetraId["<<dummy<<"].insert("<<iElem+1<<")");
1277 #endif
1278       }
1279     }
1280     else if (token == GmfHexahedra && nbElem > 0) {
1281       (nbElem <= 1) ? tmpStr = " Hexahedron" : tmpStr = " Hexahedra";
1282       for ( int iElem = 0; iElem < nbElem; iElem++ )
1283         GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &id[iElem*tabRef[token]+2], &id[iElem*tabRef[token]+3],
1284                   &id[iElem*tabRef[token]+4], &id[iElem*tabRef[token]+5], &id[iElem*tabRef[token]+6], &id[iElem*tabRef[token]+7], &domainID[iElem]);
1285     }
1286     std::cout << tmpStr << std::endl;
1287     std::cout << std::endl;
1288
1289     switch (token) {
1290     case GmfCorners:
1291     case GmfRidges:
1292     case GmfEdges:
1293     case GmfTriangles:
1294     case GmfQuadrilaterals:
1295     case GmfTetrahedra:
1296     case GmfHexahedra:
1297     {
1298       std::vector< const SMDS_MeshNode* > node( nbRef );
1299       std::vector< int >          nodeID( nbRef );
1300       std::vector< SMDS_MeshNode* > enfNode( nbRef );
1301       const SMDS_MeshElement* aCreatedElem;
1302
1303       for ( int iElem = 0; iElem < nbElem; iElem++ )
1304       {
1305         if(theAlgo->computeCanceled()) {
1306           GmfCloseMesh(InpMsh);
1307           delete [] GMFNode;
1308           return false;
1309         }
1310         // Check if elem is already in input mesh. If yes => skip
1311         bool fullyCreatedElement = false; // if at least one of the nodes was created
1312         for ( int iRef = 0; iRef < nbRef; iRef++ )
1313         {
1314           aGMFNodeID = id[iElem*tabRef[token]+iRef]; // read nbRef aGMFNodeID
1315           if (aGMFNodeID <= nbInitialNodes) // input nodes
1316           {
1317             aGMFNodeID--;
1318             node[ iRef ] = theNodeByGhs3dId[aGMFNodeID];
1319           }
1320           else
1321           {
1322             fullyCreatedElement = true;
1323             aGMFNodeID -= nbInitialNodes;
1324             nodeID[ iRef ] = aGMFNodeID ;
1325             node  [ iRef ] = GMFNode[ aGMFNodeID ];
1326           }
1327         }
1328         aCreatedElem = 0;
1329         switch (token)
1330         {
1331         case GmfEdges:
1332           if (fullyCreatedElement) {
1333             aCreatedElem = theHelper->AddEdge( node[0], node[1], noID, force3d );
1334             if (anEdgeGroupByGhs3dId.size() && !anEdgeGroupByGhs3dId[iElem].empty())
1335               addElemInMeshGroup(theHelper->GetMesh(), aCreatedElem, anEdgeGroupByGhs3dId[iElem], groupsToRemove);
1336           }
1337           break;
1338         case GmfTriangles:
1339           if (fullyCreatedElement) {
1340             aCreatedElem = theHelper->AddFace( node[0], node[1], node[2], noID, force3d );
1341             if (aFaceGroupByGhs3dId.size() && !aFaceGroupByGhs3dId[iElem].empty())
1342               addElemInMeshGroup(theHelper->GetMesh(), aCreatedElem, aFaceGroupByGhs3dId[iElem], groupsToRemove);
1343           }
1344           break;
1345         case GmfQuadrilaterals:
1346           if (fullyCreatedElement) {
1347             aCreatedElem = theHelper->AddFace( node[0], node[1], node[2], node[3], noID, force3d );
1348           }
1349           break;
1350         case GmfTetrahedra:
1351           if ( elemSearcher ) {
1352             // Issue 0020682. Avoid creating nodes and tetras at place where
1353             // volumic elements already exist
1354             if ( !node[1] || !node[0] || !node[2] || !node[3] )
1355               continue;
1356             if ( elemSearcher->FindElementsByPoint((SMESH_TNodeXYZ(node[0]) +
1357                                                     SMESH_TNodeXYZ(node[1]) +
1358                                                     SMESH_TNodeXYZ(node[2]) +
1359                                                     SMESH_TNodeXYZ(node[3]) ) / 4.,
1360                                                     SMDSAbs_Volume, foundVolumes ))
1361             break;
1362           }
1363           aCreatedElem = theHelper->AddVolume( node[1], node[0], node[2], node[3], noID, force3d );
1364           break;
1365         case GmfHexahedra:
1366           if ( elemSearcher ) {
1367             // Issue 0020682. Avoid creating nodes and tetras at place where
1368             // volumic elements already exist
1369             if ( !node[1] || !node[0] || !node[2] || !node[3] || !node[4] || !node[5] || !node[6] || !node[7])
1370               continue;
1371             if ( elemSearcher->FindElementsByPoint((SMESH_TNodeXYZ(node[0]) +
1372                                                     SMESH_TNodeXYZ(node[1]) +
1373                                                     SMESH_TNodeXYZ(node[2]) +
1374                                                     SMESH_TNodeXYZ(node[3]) +
1375                                                     SMESH_TNodeXYZ(node[4]) +
1376                                                     SMESH_TNodeXYZ(node[5]) +
1377                                                     SMESH_TNodeXYZ(node[6]) +
1378                                                     SMESH_TNodeXYZ(node[7])) / 8.,
1379                                                     SMDSAbs_Volume, foundVolumes ))
1380             break;
1381           }
1382           aCreatedElem = theHelper->AddVolume( node[0], node[3], node[2], node[1],
1383                                                node[4], node[7], node[6], node[5], noID, force3d );
1384           break;
1385         default: continue;
1386         }
1387         if ( aCreatedElem && toMakeGroupsOfDomains )
1388         {
1389           if ( domainID[iElem] >= (int) elemsOfDomain.size() )
1390             elemsOfDomain.resize( domainID[iElem] + 1 );
1391           elemsOfDomain[ domainID[iElem] ].push_back( aCreatedElem );
1392         }
1393       } // loop on elements of one type
1394       break;
1395     } // case ...
1396     } // switch (token)
1397   } // loop on tabRef
1398
1399   GmfCloseMesh(InpMsh);
1400   delete [] GMFNode;
1401
1402   // 0022172: [CEA 790] create the groups corresponding to domains
1403   if ( toMakeGroupsOfDomains )
1404   {
1405     int nbDomains = 0;
1406     for ( size_t i = 0; i < elemsOfDomain.size(); ++i )
1407       nbDomains += ( elemsOfDomain[i].size() > 0 );
1408
1409     if ( nbDomains > 1 )
1410       for ( size_t iDomain = 0; iDomain < elemsOfDomain.size(); ++iDomain )
1411       {
1412         std::vector< const SMDS_MeshElement* > & elems = elemsOfDomain[ iDomain ];
1413         if ( elems.empty() ) continue;
1414
1415         // find existing groups
1416         std::vector< SMESH_Group* > groupOfType( SMDSAbs_NbElementTypes, (SMESH_Group*)NULL );
1417         const std::string domainName = ( SMESH_Comment( theDomainGroupNamePrefix ) << iDomain );
1418         SMESH_Mesh::GroupIteratorPtr groupIt = theHelper->GetMesh()->GetGroups();
1419         while ( groupIt->more() )
1420         {
1421           SMESH_Group* group = groupIt->next();
1422           if ( domainName == group->GetName() &&
1423                dynamic_cast< SMESHDS_Group* >( group->GetGroupDS()) )
1424             groupOfType[ group->GetGroupDS()->GetType() ] = group;
1425         }
1426         // create and fill the groups
1427         size_t iElem = 0;
1428         int groupID;
1429         do
1430         {
1431           SMESH_Group* group = groupOfType[ elems[ iElem ]->GetType() ];
1432           if ( !group )
1433             group = theHelper->GetMesh()->AddGroup( elems[ iElem ]->GetType(),
1434                                                     domainName.c_str(), groupID );
1435           SMDS_MeshGroup& groupDS =
1436             static_cast< SMESHDS_Group* >( group->GetGroupDS() )->SMDSGroup();
1437
1438           while ( iElem < elems.size() && groupDS.Add( elems[iElem] ))
1439             ++iElem;
1440
1441         } while ( iElem < elems.size() );
1442       }
1443   }
1444
1445 #ifdef _DEBUG_
1446   MESSAGE("Nb subdomains " << subdomainId2tetraId.size());
1447   std::map<int, std::set<int> >::const_iterator subdomainIt = subdomainId2tetraId.begin();
1448   TCollection_AsciiString aSubdomainFileName = theFile;
1449   aSubdomainFileName = aSubdomainFileName + ".subdomain";
1450   ofstream aSubdomainFile  ( aSubdomainFileName.ToCString()  , ios::out);
1451
1452   aSubdomainFile << "Nb subdomains " << subdomainId2tetraId.size() << std::endl;
1453   for(;subdomainIt != subdomainId2tetraId.end() ; ++subdomainIt) {
1454     int subdomainId = subdomainIt->first;
1455     std::set<int> tetraIds = subdomainIt->second;
1456     MESSAGE("Subdomain #"<<subdomainId<<": "<<tetraIds.size()<<" tetrahedrons");
1457     std::set<int>::const_iterator tetraIdsIt = tetraIds.begin();
1458     aSubdomainFile << subdomainId << std::endl;
1459     for(;tetraIdsIt != tetraIds.end() ; ++tetraIdsIt) {
1460       aSubdomainFile << (*tetraIdsIt) << " ";
1461     }
1462     aSubdomainFile << std::endl;
1463   }
1464   aSubdomainFile.close();
1465 #endif  
1466   
1467   if (elemSearcher)
1468   {
1469     MESSAGE("delete elemSearcher")
1470     delete elemSearcher;
1471     elemSearcher = 0;
1472   }
1473   return true;
1474 }
1475
1476 static bool writeGMFFile(const char*                                     theMeshFileName,
1477                          const char*                                     theRequiredFileName,
1478                          const char*                                     theSolFileName,
1479                          const SMESH_ProxyMesh&                          theProxyMesh,
1480                          SMESH_Mesh *                                    theMesh,
1481                          std::vector <const SMDS_MeshNode*> &            theNodeByGhs3dId,
1482                          std::map<const SMDS_MeshNode*,int> &            aNodeToGhs3dIdMap,
1483                          std::vector<std::string> &                      aNodeGroupByGhs3dId,
1484                          std::vector<std::string> &                      anEdgeGroupByGhs3dId,
1485                          std::vector<std::string> &                      aFaceGroupByGhs3dId,
1486                          GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap & theEnforcedNodes,
1487                          GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedEdges,
1488                          GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedTriangles,
1489                          std::map<std::vector<double>, std::string> &    enfVerticesWithGroup,
1490                          GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues & theEnforcedVertices)
1491 {
1492   MESSAGE("writeGMFFile w/o geometry");
1493   std::string tmpStr;
1494   int idx, idxRequired = 0, idxSol = 0;
1495   const int dummyint = 0;
1496   GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues::const_iterator vertexIt;
1497   std::vector<double> enfVertexSizes;
1498   const SMDS_MeshElement* elem;
1499   TIDSortedElemSet anElemSet, theKeptEnforcedEdges, theKeptEnforcedTriangles;
1500   SMDS_ElemIteratorPtr nodeIt;
1501   std::vector <const SMDS_MeshNode*> theEnforcedNodeByGhs3dId;
1502   map<const SMDS_MeshNode*,int> anEnforcedNodeToGhs3dIdMap, anExistingEnforcedNodeToGhs3dIdMap;
1503   std::vector< const SMDS_MeshElement* > foundElems;
1504   map<const SMDS_MeshNode*,TopAbs_State> aNodeToTopAbs_StateMap;
1505   int nbFoundElems;
1506   GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap::iterator elemIt;
1507   TIDSortedElemSet::iterator elemSetIt;
1508   bool isOK;
1509   auto_ptr< SMESH_ElementSearcher > pntCls
1510     ( SMESH_MeshAlgos::GetElementSearcher(*theMesh->GetMeshDS()));
1511   
1512   int nbEnforcedVertices = theEnforcedVertices.size();
1513   
1514   // count faces
1515   int nbFaces = theProxyMesh.NbFaces();
1516   int nbNodes;
1517   
1518   // groups management
1519   int usedEnforcedNodes = 0;
1520   std::string gn = "";
1521
1522   if ( nbFaces == 0 )
1523     return false;
1524   
1525   idx = GmfOpenMesh(theMeshFileName, GmfWrite, GMFVERSION, GMFDIMENSION);
1526   if (!idx)
1527     return false;
1528   
1529   /* ========================== FACES ========================== */
1530   /* TRIANGLES ========================== */
1531   SMDS_ElemIteratorPtr eIt = theProxyMesh.GetFaces();
1532   while ( eIt->more() )
1533   {
1534     elem = eIt->next();
1535     anElemSet.insert(elem);
1536     nodeIt = elem->nodesIterator();
1537     nbNodes = elem->NbCornerNodes();
1538     while ( nodeIt->more() && nbNodes--)
1539     {
1540       // find GHS3D ID
1541       const SMDS_MeshNode* node = castToNode( nodeIt->next() );
1542       int newId = aNodeToGhs3dIdMap.size() + 1; // ghs3d ids count from 1
1543       aNodeToGhs3dIdMap.insert( make_pair( node, newId ));
1544     }
1545   }
1546   
1547   /* EDGES ========================== */
1548   
1549   // Iterate over the enforced edges
1550   for(elemIt = theEnforcedEdges.begin() ; elemIt != theEnforcedEdges.end() ; ++elemIt) {
1551     elem = elemIt->first;
1552     isOK = true;
1553     nodeIt = elem->nodesIterator();
1554     nbNodes = 2;
1555     while ( nodeIt->more() && nbNodes-- ) {
1556       // find GHS3D ID
1557       const SMDS_MeshNode* node = castToNode( nodeIt->next() );
1558       // Test if point is inside shape to mesh
1559       gp_Pnt myPoint(node->X(),node->Y(),node->Z());
1560       TopAbs_State result = pntCls->GetPointState( myPoint );
1561       if ( result == TopAbs_OUT ) {
1562         isOK = false;
1563         break;
1564       }
1565       aNodeToTopAbs_StateMap.insert( make_pair( node, result ));
1566     }
1567     if (isOK) {
1568       nodeIt = elem->nodesIterator();
1569       nbNodes = 2;
1570       int newId = -1;
1571       while ( nodeIt->more() && nbNodes-- ) {
1572         // find GHS3D ID
1573         const SMDS_MeshNode* node = castToNode( nodeIt->next() );
1574         gp_Pnt myPoint(node->X(),node->Y(),node->Z());
1575         nbFoundElems = pntCls->FindElementsByPoint(myPoint, SMDSAbs_Node, foundElems);
1576 #ifdef _DEBUG_
1577         std::cout << "Node at "<<node->X()<<", "<<node->Y()<<", "<<node->Z()<<std::endl;
1578         std::cout << "Nb nodes found : "<<nbFoundElems<<std::endl;
1579 #endif
1580         if (nbFoundElems ==0) {
1581           if ((*aNodeToTopAbs_StateMap.find(node)).second == TopAbs_IN) {
1582             newId = aNodeToGhs3dIdMap.size() + anEnforcedNodeToGhs3dIdMap.size() + 1; // ghs3d ids count from 1
1583             anEnforcedNodeToGhs3dIdMap.insert( make_pair( node, newId ));
1584           }
1585         }
1586         else if (nbFoundElems ==1) {
1587           const SMDS_MeshNode* existingNode = (SMDS_MeshNode*) foundElems.at(0);
1588           newId = (*aNodeToGhs3dIdMap.find(existingNode)).second;
1589           anExistingEnforcedNodeToGhs3dIdMap.insert( make_pair( node, newId ));
1590         }
1591         else
1592           isOK = false;
1593 #ifdef _DEBUG_
1594         std::cout << "GHS3D node ID: "<<newId<<std::endl;
1595 #endif
1596       }
1597       if (isOK)
1598         theKeptEnforcedEdges.insert(elem);
1599     }
1600   }
1601   
1602   /* ENFORCED TRIANGLES ========================== */
1603   
1604   // Iterate over the enforced triangles
1605   for(elemIt = theEnforcedTriangles.begin() ; elemIt != theEnforcedTriangles.end() ; ++elemIt) {
1606     elem = elemIt->first;
1607     isOK = true;
1608     nodeIt = elem->nodesIterator();
1609     nbNodes = 3;
1610     while ( nodeIt->more() && nbNodes--) {
1611       // find GHS3D ID
1612       const SMDS_MeshNode* node = castToNode( nodeIt->next() );
1613       // Test if point is inside shape to mesh
1614       gp_Pnt myPoint(node->X(),node->Y(),node->Z());
1615       TopAbs_State result = pntCls->GetPointState( myPoint );
1616       if ( result == TopAbs_OUT ) {
1617         isOK = false;
1618         break;
1619       }
1620       aNodeToTopAbs_StateMap.insert( make_pair( node, result ));
1621     }
1622     if (isOK) {
1623       nodeIt = elem->nodesIterator();
1624       nbNodes = 3;
1625       int newId = -1;
1626       while ( nodeIt->more() && nbNodes--) {
1627         // find GHS3D ID
1628         const SMDS_MeshNode* node = castToNode( nodeIt->next() );
1629         gp_Pnt myPoint(node->X(),node->Y(),node->Z());
1630         nbFoundElems = pntCls->FindElementsByPoint(myPoint, SMDSAbs_Node, foundElems);
1631 #ifdef _DEBUG_
1632         std::cout << "Nb nodes found : "<<nbFoundElems<<std::endl;
1633 #endif
1634         if (nbFoundElems ==0) {
1635           if ((*aNodeToTopAbs_StateMap.find(node)).second == TopAbs_IN) {
1636             newId = aNodeToGhs3dIdMap.size() + anEnforcedNodeToGhs3dIdMap.size() + 1; // ghs3d ids count from 1
1637             anEnforcedNodeToGhs3dIdMap.insert( make_pair( node, newId ));
1638           }
1639         }
1640         else if (nbFoundElems ==1) {
1641           const SMDS_MeshNode* existingNode = (SMDS_MeshNode*) foundElems.at(0);
1642           newId = (*aNodeToGhs3dIdMap.find(existingNode)).second;
1643           anExistingEnforcedNodeToGhs3dIdMap.insert( make_pair( node, newId ));
1644         }
1645         else
1646           isOK = false;
1647 #ifdef _DEBUG_
1648         std::cout << "GHS3D node ID: "<<newId<<std::endl;
1649 #endif
1650       }
1651       if (isOK)
1652         theKeptEnforcedTriangles.insert(elem);
1653     }
1654   }
1655   
1656   // put nodes to theNodeByGhs3dId vector
1657 #ifdef _DEBUG_
1658   std::cout << "aNodeToGhs3dIdMap.size(): "<<aNodeToGhs3dIdMap.size()<<std::endl;
1659 #endif
1660   theNodeByGhs3dId.resize( aNodeToGhs3dIdMap.size() );
1661   map<const SMDS_MeshNode*,int>::const_iterator n2id = aNodeToGhs3dIdMap.begin();
1662   for ( ; n2id != aNodeToGhs3dIdMap.end(); ++ n2id)
1663   {
1664 //     std::cout << "n2id->first: "<<n2id->first<<std::endl;
1665     theNodeByGhs3dId[ n2id->second - 1 ] = n2id->first; // ghs3d ids count from 1
1666   }
1667
1668   // put nodes to anEnforcedNodeToGhs3dIdMap vector
1669 #ifdef _DEBUG_
1670   std::cout << "anEnforcedNodeToGhs3dIdMap.size(): "<<anEnforcedNodeToGhs3dIdMap.size()<<std::endl;
1671 #endif
1672   theEnforcedNodeByGhs3dId.resize( anEnforcedNodeToGhs3dIdMap.size());
1673   n2id = anEnforcedNodeToGhs3dIdMap.begin();
1674   for ( ; n2id != anEnforcedNodeToGhs3dIdMap.end(); ++ n2id)
1675   {
1676     if (n2id->second > aNodeToGhs3dIdMap.size()) {
1677       theEnforcedNodeByGhs3dId[ n2id->second - aNodeToGhs3dIdMap.size() - 1 ] = n2id->first; // ghs3d ids count from 1
1678     }
1679   }
1680   
1681   
1682   /* ========================== NODES ========================== */
1683   vector<const SMDS_MeshNode*> theOrderedNodes, theRequiredNodes;
1684   std::set< std::vector<double> > nodesCoords;
1685   vector<const SMDS_MeshNode*>::const_iterator ghs3dNodeIt = theNodeByGhs3dId.begin();
1686   vector<const SMDS_MeshNode*>::const_iterator after  = theNodeByGhs3dId.end();
1687   
1688   (theNodeByGhs3dId.size() <= 1) ? tmpStr = " node" : " nodes";
1689   std::cout << theNodeByGhs3dId.size() << tmpStr << " from mesh ..." << std::endl;
1690   for ( ; ghs3dNodeIt != after; ++ghs3dNodeIt )
1691   {
1692     const SMDS_MeshNode* node = *ghs3dNodeIt;
1693     std::vector<double> coords;
1694     coords.push_back(node->X());
1695     coords.push_back(node->Y());
1696     coords.push_back(node->Z());
1697     nodesCoords.insert(coords);
1698     theOrderedNodes.push_back(node);
1699   }
1700   
1701   // Iterate over the enforced nodes given by enforced elements
1702   ghs3dNodeIt = theEnforcedNodeByGhs3dId.begin();
1703   after  = theEnforcedNodeByGhs3dId.end();
1704   (theEnforcedNodeByGhs3dId.size() <= 1) ? tmpStr = " node" : " nodes";
1705   std::cout << theEnforcedNodeByGhs3dId.size() << tmpStr << " from enforced elements ..." << std::endl;
1706   for ( ; ghs3dNodeIt != after; ++ghs3dNodeIt )
1707   {
1708     const SMDS_MeshNode* node = *ghs3dNodeIt;
1709     std::vector<double> coords;
1710     coords.push_back(node->X());
1711     coords.push_back(node->Y());
1712     coords.push_back(node->Z());
1713 #ifdef _DEBUG_
1714     std::cout << "Node at " << node->X()<<", " <<node->Y()<<", " <<node->Z();
1715 #endif
1716     
1717     if (nodesCoords.find(coords) != nodesCoords.end()) {
1718       // node already exists in original mesh
1719 #ifdef _DEBUG_
1720       std::cout << " found" << std::endl;
1721 #endif
1722       continue;
1723     }
1724     
1725     if (theEnforcedVertices.find(coords) != theEnforcedVertices.end()) {
1726       // node already exists in enforced vertices
1727 #ifdef _DEBUG_
1728       std::cout << " found" << std::endl;
1729 #endif
1730       continue;
1731     }
1732     
1733 //     gp_Pnt myPoint(node->X(),node->Y(),node->Z());
1734 //     nbFoundElems = pntCls->FindElementsByPoint(myPoint, SMDSAbs_Node, foundElems);
1735 //     if (nbFoundElems ==0) {
1736 //       std::cout << " not found" << std::endl;
1737 //       if ((*aNodeToTopAbs_StateMap.find(node)).second == TopAbs_IN) {
1738 //         nodesCoords.insert(coords);
1739 //         theOrderedNodes.push_back(node);
1740 //       }
1741 //     }
1742 //     else {
1743 //       std::cout << " found in initial mesh" << std::endl;
1744 //       const SMDS_MeshNode* existingNode = (SMDS_MeshNode*) foundElems.at(0);
1745 //       nodesCoords.insert(coords);
1746 //       theOrderedNodes.push_back(existingNode);
1747 //     }
1748     
1749 #ifdef _DEBUG_
1750     std::cout << " not found" << std::endl;
1751 #endif
1752     
1753     nodesCoords.insert(coords);
1754     theOrderedNodes.push_back(node);
1755 //     theRequiredNodes.push_back(node);
1756   }
1757   
1758   
1759   // Iterate over the enforced nodes
1760   GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap::const_iterator enfNodeIt;
1761   (theEnforcedNodes.size() <= 1) ? tmpStr = " node" : " nodes";
1762   std::cout << theEnforcedNodes.size() << tmpStr << " from enforced nodes ..." << std::endl;
1763   for(enfNodeIt = theEnforcedNodes.begin() ; enfNodeIt != theEnforcedNodes.end() ; ++enfNodeIt)
1764   {
1765     const SMDS_MeshNode* node = enfNodeIt->first;
1766     std::vector<double> coords;
1767     coords.push_back(node->X());
1768     coords.push_back(node->Y());
1769     coords.push_back(node->Z());
1770 #ifdef _DEBUG_
1771     std::cout << "Node at " << node->X()<<", " <<node->Y()<<", " <<node->Z();
1772 #endif
1773     
1774     // Test if point is inside shape to mesh
1775     gp_Pnt myPoint(node->X(),node->Y(),node->Z());
1776     TopAbs_State result = pntCls->GetPointState( myPoint );
1777     if ( result == TopAbs_OUT ) {
1778 #ifdef _DEBUG_
1779       std::cout << " out of volume" << std::endl;
1780 #endif
1781       continue;
1782     }
1783     
1784     if (nodesCoords.find(coords) != nodesCoords.end()) {
1785 #ifdef _DEBUG_
1786       std::cout << " found in nodesCoords" << std::endl;
1787 #endif
1788 //       theRequiredNodes.push_back(node);
1789       continue;
1790     }
1791
1792     if (theEnforcedVertices.find(coords) != theEnforcedVertices.end()) {
1793 #ifdef _DEBUG_
1794       std::cout << " found in theEnforcedVertices" << std::endl;
1795 #endif
1796       continue;
1797     }
1798     
1799 //     nbFoundElems = pntCls->FindElementsByPoint(myPoint, SMDSAbs_Node, foundElems);
1800 //     if (nbFoundElems ==0) {
1801 //       std::cout << " not found" << std::endl;
1802 //       if (result == TopAbs_IN) {
1803 //         nodesCoords.insert(coords);
1804 //         theRequiredNodes.push_back(node);
1805 //       }
1806 //     }
1807 //     else {
1808 //       std::cout << " found in initial mesh" << std::endl;
1809 //       const SMDS_MeshNode* existingNode = (SMDS_MeshNode*) foundElems.at(0);
1810 // //       nodesCoords.insert(coords);
1811 //       theRequiredNodes.push_back(existingNode);
1812 //     }
1813 //     
1814 //     
1815 //     
1816 //     if (pntCls->FindElementsByPoint(myPoint, SMDSAbs_Node, foundElems) == 0)
1817 //       continue;
1818
1819 //     if ( result != TopAbs_IN )
1820 //       continue;
1821     
1822 #ifdef _DEBUG_
1823     std::cout << " not found" << std::endl;
1824 #endif
1825     nodesCoords.insert(coords);
1826 //     theOrderedNodes.push_back(node);
1827     theRequiredNodes.push_back(node);
1828   }
1829   int requiredNodes = theRequiredNodes.size();
1830   
1831   int solSize = 0;
1832   std::vector<std::vector<double> > ReqVerTab;
1833   if (nbEnforcedVertices) {
1834 //    ReqVerTab.clear();
1835     (nbEnforcedVertices <= 1) ? tmpStr = " node" : " nodes";
1836     std::cout << nbEnforcedVertices << tmpStr << " from enforced vertices ..." << std::endl;
1837     // Iterate over the enforced vertices
1838     for(vertexIt = theEnforcedVertices.begin() ; vertexIt != theEnforcedVertices.end() ; ++vertexIt) {
1839       double x = vertexIt->first[0];
1840       double y = vertexIt->first[1];
1841       double z = vertexIt->first[2];
1842       // Test if point is inside shape to mesh
1843       gp_Pnt myPoint(x,y,z);
1844       TopAbs_State result = pntCls->GetPointState( myPoint );
1845       if ( result == TopAbs_OUT )
1846         continue;
1847       //if (pntCls->FindElementsByPoint(myPoint, SMDSAbs_Node, foundElems) == 0)
1848       //continue;
1849
1850 //       if ( result != TopAbs_IN )
1851 //         continue;
1852       std::vector<double> coords;
1853       coords.push_back(x);
1854       coords.push_back(y);
1855       coords.push_back(z);
1856       ReqVerTab.push_back(coords);
1857       enfVertexSizes.push_back(vertexIt->second);
1858       solSize++;
1859     }
1860   }
1861   
1862   
1863   // GmfVertices
1864   std::cout << "Begin writting required nodes in GmfVertices" << std::endl;
1865   std::cout << "Nb vertices: " << theOrderedNodes.size() << std::endl;
1866   GmfSetKwd(idx, GmfVertices, theOrderedNodes.size()/*+solSize*/);
1867   for (ghs3dNodeIt = theOrderedNodes.begin();ghs3dNodeIt != theOrderedNodes.end();++ghs3dNodeIt) {
1868     GmfSetLin(idx, GmfVertices, (*ghs3dNodeIt)->X(), (*ghs3dNodeIt)->Y(), (*ghs3dNodeIt)->Z(), dummyint);
1869   }
1870
1871   std::cout << "End writting required nodes in GmfVertices" << std::endl;
1872
1873   if (requiredNodes + solSize) {
1874     std::cout << "Begin writting in req and sol file" << std::endl;
1875     aNodeGroupByGhs3dId.resize( requiredNodes + solSize );
1876     idxRequired = GmfOpenMesh(theRequiredFileName, GmfWrite, GMFVERSION, GMFDIMENSION);
1877     if (!idxRequired) {
1878       GmfCloseMesh(idx);
1879       return false;
1880     }
1881     idxSol = GmfOpenMesh(theSolFileName, GmfWrite, GMFVERSION, GMFDIMENSION);
1882     if (!idxSol) {
1883       GmfCloseMesh(idx);
1884       if (idxRequired)
1885         GmfCloseMesh(idxRequired);
1886       return false;
1887     }
1888     int TypTab[] = {GmfSca};
1889     double ValTab[] = {0.0};
1890     GmfSetKwd(idxRequired, GmfVertices, requiredNodes + solSize);
1891     GmfSetKwd(idxSol, GmfSolAtVertices, requiredNodes + solSize, 1, TypTab);
1892 //     int usedEnforcedNodes = 0;
1893 //     std::string gn = "";
1894     for (ghs3dNodeIt = theRequiredNodes.begin();ghs3dNodeIt != theRequiredNodes.end();++ghs3dNodeIt) {
1895       GmfSetLin(idxRequired, GmfVertices, (*ghs3dNodeIt)->X(), (*ghs3dNodeIt)->Y(), (*ghs3dNodeIt)->Z(), dummyint);
1896       GmfSetLin(idxSol, GmfSolAtVertices, ValTab);
1897       if (theEnforcedNodes.find((*ghs3dNodeIt)) != theEnforcedNodes.end())
1898         gn = theEnforcedNodes.find((*ghs3dNodeIt))->second;
1899       aNodeGroupByGhs3dId[usedEnforcedNodes] = gn;
1900       usedEnforcedNodes++;
1901     }
1902
1903     for (int i=0;i<solSize;i++) {
1904       std::cout << ReqVerTab[i][0] <<" "<< ReqVerTab[i][1] << " "<< ReqVerTab[i][2] << std::endl;
1905 #ifdef _DEBUG_
1906       std::cout << "enfVertexSizes.at("<<i<<"): " << enfVertexSizes.at(i) << std::endl;
1907 #endif
1908       double solTab[] = {enfVertexSizes.at(i)};
1909       GmfSetLin(idxRequired, GmfVertices, ReqVerTab[i][0], ReqVerTab[i][1], ReqVerTab[i][2], dummyint);
1910       GmfSetLin(idxSol, GmfSolAtVertices, solTab);
1911       aNodeGroupByGhs3dId[usedEnforcedNodes] = enfVerticesWithGroup.find(ReqVerTab[i])->second;
1912 #ifdef _DEBUG_
1913       std::cout << "aNodeGroupByGhs3dId["<<usedEnforcedNodes<<"] = \""<<aNodeGroupByGhs3dId[usedEnforcedNodes]<<"\""<<std::endl;
1914 #endif
1915       usedEnforcedNodes++;
1916     }
1917     std::cout << "End writting in req and sol file" << std::endl;
1918   }
1919
1920   int nedge[2], ntri[3];
1921     
1922   // GmfEdges
1923   int usedEnforcedEdges = 0;
1924   if (theKeptEnforcedEdges.size()) {
1925     anEdgeGroupByGhs3dId.resize( theKeptEnforcedEdges.size() );
1926 //    idxRequired = GmfOpenMesh(theRequiredFileName, GmfWrite, GMFVERSION, GMFDIMENSION);
1927 //    if (!idxRequired)
1928 //      return false;
1929     GmfSetKwd(idx, GmfEdges, theKeptEnforcedEdges.size());
1930 //    GmfSetKwd(idxRequired, GmfEdges, theKeptEnforcedEdges.size());
1931     for(elemSetIt = theKeptEnforcedEdges.begin() ; elemSetIt != theKeptEnforcedEdges.end() ; ++elemSetIt) {
1932       elem = (*elemSetIt);
1933       nodeIt = elem->nodesIterator();
1934       int index=0;
1935       while ( nodeIt->more() ) {
1936         // find GHS3D ID
1937         const SMDS_MeshNode* node = castToNode( nodeIt->next() );
1938         map< const SMDS_MeshNode*,int >::iterator it = anEnforcedNodeToGhs3dIdMap.find(node);
1939         if (it == anEnforcedNodeToGhs3dIdMap.end()) {
1940           it = anExistingEnforcedNodeToGhs3dIdMap.find(node);
1941           if (it == anEnforcedNodeToGhs3dIdMap.end())
1942             throw "Node not found";
1943         }
1944         nedge[index] = it->second;
1945         index++;
1946       }
1947       GmfSetLin(idx, GmfEdges, nedge[0], nedge[1], dummyint);
1948       anEdgeGroupByGhs3dId[usedEnforcedEdges] = theEnforcedEdges.find(elem)->second;
1949 //      GmfSetLin(idxRequired, GmfEdges, nedge[0], nedge[1], dummyint);
1950       usedEnforcedEdges++;
1951     }
1952 //    GmfCloseMesh(idxRequired);
1953   }
1954
1955
1956   if (usedEnforcedEdges) {
1957     GmfSetKwd(idx, GmfRequiredEdges, usedEnforcedEdges);
1958     for (int enfID=1;enfID<=usedEnforcedEdges;enfID++) {
1959       GmfSetLin(idx, GmfRequiredEdges, enfID);
1960     }
1961   }
1962
1963   // GmfTriangles
1964   int usedEnforcedTriangles = 0;
1965   if (anElemSet.size()+theKeptEnforcedTriangles.size()) {
1966     aFaceGroupByGhs3dId.resize( anElemSet.size()+theKeptEnforcedTriangles.size() );
1967     GmfSetKwd(idx, GmfTriangles, anElemSet.size()+theKeptEnforcedTriangles.size());
1968     int k=0;
1969     for(elemSetIt = anElemSet.begin() ; elemSetIt != anElemSet.end() ; ++elemSetIt,++k) {
1970       elem = (*elemSetIt);
1971       nodeIt = elem->nodesIterator();
1972       int index=0;
1973       for ( int j = 0; j < 3; ++j ) {
1974         // find GHS3D ID
1975         const SMDS_MeshNode* node = castToNode( nodeIt->next() );
1976         map< const SMDS_MeshNode*,int >::iterator it = aNodeToGhs3dIdMap.find(node);
1977         if (it == aNodeToGhs3dIdMap.end())
1978           throw "Node not found";
1979         ntri[index] = it->second;
1980         index++;
1981       }
1982       GmfSetLin(idx, GmfTriangles, ntri[0], ntri[1], ntri[2], dummyint);
1983       aFaceGroupByGhs3dId[k] = "";
1984     }
1985     if (theKeptEnforcedTriangles.size()) {
1986       for(elemSetIt = theKeptEnforcedTriangles.begin() ; elemSetIt != theKeptEnforcedTriangles.end() ; ++elemSetIt,++k) {
1987         elem = (*elemSetIt);
1988         nodeIt = elem->nodesIterator();
1989         int index=0;
1990         for ( int j = 0; j < 3; ++j ) {
1991           // find GHS3D ID
1992           const SMDS_MeshNode* node = castToNode( nodeIt->next() );
1993           map< const SMDS_MeshNode*,int >::iterator it = anEnforcedNodeToGhs3dIdMap.find(node);
1994           if (it == anEnforcedNodeToGhs3dIdMap.end()) {
1995             it = anExistingEnforcedNodeToGhs3dIdMap.find(node);
1996             if (it == anEnforcedNodeToGhs3dIdMap.end())
1997               throw "Node not found";
1998           }
1999           ntri[index] = it->second;
2000           index++;
2001         }
2002         GmfSetLin(idx, GmfTriangles, ntri[0], ntri[1], ntri[2], dummyint);
2003         aFaceGroupByGhs3dId[k] = theEnforcedTriangles.find(elem)->second;
2004         usedEnforcedTriangles++;
2005       }
2006     }
2007   }
2008
2009   
2010   if (usedEnforcedTriangles) {
2011     GmfSetKwd(idx, GmfRequiredTriangles, usedEnforcedTriangles);
2012     for (int enfID=1;enfID<=usedEnforcedTriangles;enfID++)
2013       GmfSetLin(idx, GmfRequiredTriangles, anElemSet.size()+enfID);
2014   }
2015
2016   GmfCloseMesh(idx);
2017   if (idxRequired)
2018     GmfCloseMesh(idxRequired);
2019   if (idxSol)
2020     GmfCloseMesh(idxSol);
2021   
2022   return true;
2023   
2024 }
2025
2026 // static bool writeGMFFile(const char*                                    theMeshFileName,
2027 //                         const char*                                     theRequiredFileName,
2028 //                         const char*                                     theSolFileName,
2029 //                         SMESH_MesherHelper&                             theHelper,
2030 //                         const SMESH_ProxyMesh&                          theProxyMesh,
2031 //                         std::map <int,int> &                            theNodeId2NodeIndexMap,
2032 //                         std::map <int,int> &                            theSmdsToGhs3dIdMap,
2033 //                         std::map <int,const SMDS_MeshNode*> &           theGhs3dIdToNodeMap,
2034 //                         TIDSortedNodeSet &                              theEnforcedNodes,
2035 //                         TIDSortedElemSet &                              theEnforcedEdges,
2036 //                         TIDSortedElemSet &                              theEnforcedTriangles,
2037 // //                         TIDSortedElemSet &                              theEnforcedQuadrangles,
2038 //                         GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues & theEnforcedVertices)
2039 // {
2040 //   MESSAGE("writeGMFFile with geometry");
2041 //   int idx, idxRequired, idxSol;
2042 //   int nbv, nbev, nben, aGhs3dID = 0;
2043 //   const int dummyint = 0;
2044 //   GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues::const_iterator vertexIt;
2045 //   std::vector<double> enfVertexSizes;
2046 //   TIDSortedNodeSet::const_iterator enfNodeIt;
2047 //   const SMDS_MeshNode* node;
2048 //   SMDS_NodeIteratorPtr nodeIt;
2049 // 
2050 //   idx = GmfOpenMesh(theMeshFileName, GmfWrite, GMFVERSION, GMFDIMENSION);
2051 //   if (!idx)
2052 //     return false;
2053 //   
2054 //   SMESHDS_Mesh * theMeshDS = theHelper.GetMeshDS();
2055 //   
2056 //   /* ========================== NODES ========================== */
2057 //   // NB_NODES
2058 //   nbv = theMeshDS->NbNodes();
2059 //   if ( nbv == 0 )
2060 //     return false;
2061 //   nbev = theEnforcedVertices.size();
2062 //   nben = theEnforcedNodes.size();
2063 //   
2064 //   // Issue 020674: EDF 870 SMESH: Mesh generated by Netgen not usable by GHS3D
2065 //   // The problem is in nodes on degenerated edges, we need to skip nodes which are free
2066 //   // and replace not-free nodes on edges by the node on vertex
2067 //   TNodeNodeMap n2nDegen; // map a node on degenerated edge to a node on vertex
2068 //   TNodeNodeMap::iterator n2nDegenIt;
2069 //   if ( theHelper.HasDegeneratedEdges() )
2070 //   {
2071 //     set<int> checkedSM;
2072 //     for (TopExp_Explorer e(theMeshDS->ShapeToMesh(), TopAbs_EDGE ); e.More(); e.Next())
2073 //     {
2074 //       SMESH_subMesh* sm = theHelper.GetMesh()->GetSubMesh( e.Current() );
2075 //       if ( checkedSM.insert( sm->GetId() ).second && theHelper.IsDegenShape(sm->GetId() ))
2076 //       {
2077 //         if ( SMESHDS_SubMesh* smDS = sm->GetSubMeshDS() )
2078 //         {
2079 //           TopoDS_Shape vertex = TopoDS_Iterator( e.Current() ).Value();
2080 //           const SMDS_MeshNode* vNode = SMESH_Algo::VertexNode( TopoDS::Vertex( vertex ), theMeshDS);
2081 //           {
2082 //             SMDS_NodeIteratorPtr nIt = smDS->GetNodes();
2083 //             while ( nIt->more() )
2084 //               n2nDegen.insert( make_pair( nIt->next(), vNode ));
2085 //           }
2086 //         }
2087 //       }
2088 //     }
2089 //   }
2090 //   
2091 //   const bool isQuadMesh = 
2092 //     theHelper.GetMesh()->NbEdges( ORDER_QUADRATIC ) ||
2093 //     theHelper.GetMesh()->NbFaces( ORDER_QUADRATIC ) ||
2094 //     theHelper.GetMesh()->NbVolumes( ORDER_QUADRATIC );
2095 // 
2096 //   std::vector<std::vector<double> > VerTab;
2097 //   std::set<std::vector<double> > VerMap;
2098 //   VerTab.clear();
2099 //   std::vector<double> aVerTab;
2100 //   // Loop from 1 to NB_NODES
2101 // 
2102 //   nodeIt = theMeshDS->nodesIterator();
2103 //   
2104 //   while ( nodeIt->more() )
2105 //   {
2106 //     node = nodeIt->next();
2107 //     if ( isQuadMesh && theHelper.IsMedium( node )) // Issue 0021238
2108 //       continue;
2109 //     if ( n2nDegen.count( node ) ) // Issue 0020674
2110 //       continue;
2111 // 
2112 //     std::vector<double> coords;
2113 //     coords.push_back(node->X());
2114 //     coords.push_back(node->Y());
2115 //     coords.push_back(node->Z());
2116 //     if (VerMap.find(coords) != VerMap.end()) {
2117 //       aGhs3dID = theSmdsToGhs3dIdMap[node->GetID()];
2118 //       theGhs3dIdToNodeMap[theSmdsToGhs3dIdMap[node->GetID()]] = node;
2119 //       continue;
2120 //     }
2121 //     VerTab.push_back(coords);
2122 //     VerMap.insert(coords);
2123 //     aGhs3dID++;
2124 //     theSmdsToGhs3dIdMap.insert( make_pair( node->GetID(), aGhs3dID ));
2125 //     theGhs3dIdToNodeMap.insert( make_pair( aGhs3dID, node ));
2126 //   }
2127 //   
2128 //   
2129 //   /* ENFORCED NODES ========================== */
2130 //   if (nben) {
2131 //     std::cout << "Add " << nben << " enforced nodes to input .mesh file" << std::endl;
2132 //     for(enfNodeIt = theEnforcedNodes.begin() ; enfNodeIt != theEnforcedNodes.end() ; ++enfNodeIt) {
2133 //       double x = (*enfNodeIt)->X();
2134 //       double y = (*enfNodeIt)->Y();
2135 //       double z = (*enfNodeIt)->Z();
2136 //       // Test if point is inside shape to mesh
2137 //       gp_Pnt myPoint(x,y,z);
2138 //       BRepClass3d_SolidClassifier scl(theMeshDS->ShapeToMesh());
2139 //       scl.Perform(myPoint, 1e-7);
2140 //       TopAbs_State result = scl.State();
2141 //       if ( result != TopAbs_IN )
2142 //         continue;
2143 //       std::vector<double> coords;
2144 //       coords.push_back(x);
2145 //       coords.push_back(y);
2146 //       coords.push_back(z);
2147 //       if (theEnforcedVertices.find(coords) != theEnforcedVertices.end())
2148 //         continue;
2149 //       if (VerMap.find(coords) != VerMap.end())
2150 //         continue;
2151 //       VerTab.push_back(coords);
2152 //       VerMap.insert(coords);
2153 //       aGhs3dID++;
2154 //       theNodeId2NodeIndexMap.insert( make_pair( (*enfNodeIt)->GetID(), aGhs3dID ));
2155 //     }
2156 //   }
2157 //     
2158 //   
2159 //   /* ENFORCED VERTICES ========================== */
2160 //   int solSize = 0;
2161 //   std::vector<std::vector<double> > ReqVerTab;
2162 //   ReqVerTab.clear();
2163 //   if (nbev) {
2164 //     std::cout << "Add " << nbev << " enforced vertices to input .mesh file" << std::endl;
2165 //     for(vertexIt = theEnforcedVertices.begin() ; vertexIt != theEnforcedVertices.end() ; ++vertexIt) {
2166 //       double x = vertexIt->first[0];
2167 //       double y = vertexIt->first[1];
2168 //       double z = vertexIt->first[2];
2169 //       // Test if point is inside shape to mesh
2170 //       gp_Pnt myPoint(x,y,z);
2171 //       BRepClass3d_SolidClassifier scl(theMeshDS->ShapeToMesh());
2172 //       scl.Perform(myPoint, 1e-7);
2173 //       TopAbs_State result = scl.State();
2174 //       if ( result != TopAbs_IN )
2175 //         continue;
2176 //       enfVertexSizes.push_back(vertexIt->second);
2177 //       std::vector<double> coords;
2178 //       coords.push_back(x);
2179 //       coords.push_back(y);
2180 //       coords.push_back(z);
2181 //       if (VerMap.find(coords) != VerMap.end())
2182 //         continue;
2183 //       ReqVerTab.push_back(coords);
2184 //       VerMap.insert(coords);
2185 //       solSize++;
2186 //     }
2187 //   }
2188 // 
2189 //   
2190 //   /* ========================== FACES ========================== */
2191 //   
2192 //   int nbTriangles = 0/*, nbQuadrangles = 0*/, aSmdsID;
2193 //   TopTools_IndexedMapOfShape facesMap, trianglesMap/*, quadranglesMap*/;
2194 //   TIDSortedElemSet::const_iterator elemIt;
2195 //   const SMESHDS_SubMesh* theSubMesh;
2196 //   TopoDS_Shape aShape;
2197 //   SMDS_ElemIteratorPtr itOnSubMesh, itOnSubFace;
2198 //   const SMDS_MeshElement* aFace;
2199 //   map<int,int>::const_iterator itOnMap;
2200 //   std::vector<std::vector<int> > tt, qt,et;
2201 //   tt.clear();
2202 //   qt.clear();
2203 //   et.clear();
2204 //   std::vector<int> att, aqt, aet;
2205 //   
2206 //   TopExp::MapShapes( theMeshDS->ShapeToMesh(), TopAbs_FACE, facesMap );
2207 // 
2208 //   for ( int i = 1; i <= facesMap.Extent(); ++i )
2209 //     if (( theSubMesh  = theProxyMesh.GetSubMesh( facesMap(i))))
2210 //     {
2211 //       SMDS_ElemIteratorPtr it = theSubMesh->GetElements();
2212 //       while (it->more())
2213 //       {
2214 //         const SMDS_MeshElement *elem = it->next();
2215 //         int nbCornerNodes = elem->NbCornerNodes();
2216 //         if (nbCornerNodes == 3)
2217 //         {
2218 //           trianglesMap.Add(facesMap(i));
2219 //           nbTriangles ++;
2220 //         }
2221 // //         else if (nbCornerNodes == 4)
2222 // //         {
2223 // //           quadranglesMap.Add(facesMap(i));
2224 // //           nbQuadrangles ++;
2225 // //         }
2226 //       }
2227 //     }
2228 //     
2229 //   /* TRIANGLES ========================== */
2230 //   if (nbTriangles) {
2231 //     for ( int i = 1; i <= trianglesMap.Extent(); i++ )
2232 //     {
2233 //       aShape = trianglesMap(i);
2234 //       theSubMesh = theProxyMesh.GetSubMesh(aShape);
2235 //       if ( !theSubMesh ) continue;
2236 //       itOnSubMesh = theSubMesh->GetElements();
2237 //       while ( itOnSubMesh->more() )
2238 //       {
2239 //         aFace = itOnSubMesh->next();
2240 //         itOnSubFace = aFace->nodesIterator();
2241 //         att.clear();
2242 //         for ( int j = 0; j < 3; ++j ) {
2243 //           // find GHS3D ID
2244 //           node = castToNode( itOnSubFace->next() );
2245 //           if (( n2nDegenIt = n2nDegen.find( node )) != n2nDegen.end() )
2246 //             node = n2nDegenIt->second;
2247 //           aSmdsID = node->GetID();
2248 //           itOnMap = theSmdsToGhs3dIdMap.find( aSmdsID );
2249 //           ASSERT( itOnMap != theSmdsToGhs3dIdMap.end() );
2250 //           att.push_back((*itOnMap).second);
2251 //         }
2252 //         tt.push_back(att);
2253 //       }
2254 //     }
2255 //   }
2256 // 
2257 //   if (theEnforcedTriangles.size()) {
2258 //     std::cout << "Add " << theEnforcedTriangles.size() << " enforced triangles to input .mesh file" << std::endl;
2259 //     // Iterate over the enforced triangles
2260 //     for(elemIt = theEnforcedTriangles.begin() ; elemIt != theEnforcedTriangles.end() ; ++elemIt) {
2261 //       aFace = (*elemIt);
2262 //       itOnSubFace = aFace->nodesIterator();
2263 //       bool isOK = true;
2264 //       att.clear();
2265 //       
2266 //       for ( int j = 0; j < 3; ++j ) {
2267 //         node = castToNode( itOnSubFace->next() );
2268 //         if (( n2nDegenIt = n2nDegen.find( node )) != n2nDegen.end() )
2269 //           node = n2nDegenIt->second;
2270 // //         std::cout << node;
2271 //         double x = node->X();
2272 //         double y = node->Y();
2273 //         double z = node->Z();
2274 //         // Test if point is inside shape to mesh
2275 //         gp_Pnt myPoint(x,y,z);
2276 //         BRepClass3d_SolidClassifier scl(theMeshDS->ShapeToMesh());
2277 //         scl.Perform(myPoint, 1e-7);
2278 //         TopAbs_State result = scl.State();
2279 //         if ( result != TopAbs_IN ) {
2280 //           isOK = false;
2281 //           theEnforcedTriangles.erase(elemIt);
2282 //           continue;
2283 //         }
2284 //         std::vector<double> coords;
2285 //         coords.push_back(x);
2286 //         coords.push_back(y);
2287 //         coords.push_back(z);
2288 //         if (VerMap.find(coords) != VerMap.end()) {
2289 //           att.push_back(theNodeId2NodeIndexMap[node->GetID()]);
2290 //           continue;
2291 //         }
2292 //         VerTab.push_back(coords);
2293 //         VerMap.insert(coords);
2294 //         aGhs3dID++;
2295 //         theNodeId2NodeIndexMap.insert( make_pair( node->GetID(), aGhs3dID ));
2296 //         att.push_back(aGhs3dID);
2297 //       }
2298 //       if (isOK)
2299 //         tt.push_back(att);
2300 //     }
2301 //   }
2302 // 
2303 // 
2304 //   /* ========================== EDGES ========================== */
2305 // 
2306 //   if (theEnforcedEdges.size()) {
2307 //     // Iterate over the enforced edges
2308 //     std::cout << "Add " << theEnforcedEdges.size() << " enforced edges to input .mesh file" << std::endl;
2309 //     for(elemIt = theEnforcedEdges.begin() ; elemIt != theEnforcedEdges.end() ; ++elemIt) {
2310 //       aFace = (*elemIt);
2311 //       bool isOK = true;
2312 //       itOnSubFace = aFace->nodesIterator();
2313 //       aet.clear();
2314 //       for ( int j = 0; j < 2; ++j ) {
2315 //         node = castToNode( itOnSubFace->next() );
2316 //         if (( n2nDegenIt = n2nDegen.find( node )) != n2nDegen.end() )
2317 //           node = n2nDegenIt->second;
2318 //         double x = node->X();
2319 //         double y = node->Y();
2320 //         double z = node->Z();
2321 //         // Test if point is inside shape to mesh
2322 //         gp_Pnt myPoint(x,y,z);
2323 //         BRepClass3d_SolidClassifier scl(theMeshDS->ShapeToMesh());
2324 //         scl.Perform(myPoint, 1e-7);
2325 //         TopAbs_State result = scl.State();
2326 //         if ( result != TopAbs_IN ) {
2327 //           isOK = false;
2328 //           theEnforcedEdges.erase(elemIt);
2329 //           continue;
2330 //         }
2331 //         std::vector<double> coords;
2332 //         coords.push_back(x);
2333 //         coords.push_back(y);
2334 //         coords.push_back(z);
2335 //         if (VerMap.find(coords) != VerMap.end()) {
2336 //           aet.push_back(theNodeId2NodeIndexMap[node->GetID()]);
2337 //           continue;
2338 //         }
2339 //         VerTab.push_back(coords);
2340 //         VerMap.insert(coords);
2341 //         
2342 //         aGhs3dID++;
2343 //         theNodeId2NodeIndexMap.insert( make_pair( node->GetID(), aGhs3dID ));
2344 //         aet.push_back(aGhs3dID);
2345 //       }
2346 //       if (isOK)
2347 //         et.push_back(aet);
2348 //     }
2349 //   }
2350 // 
2351 // 
2352 //   /* Write vertices number */
2353 //   MESSAGE("Number of vertices: "<<aGhs3dID);
2354 //   MESSAGE("Size of vector: "<<VerTab.size());
2355 //   GmfSetKwd(idx, GmfVertices, aGhs3dID/*+solSize*/);
2356 //   for (int i=0;i<aGhs3dID;i++)
2357 //     GmfSetLin(idx, GmfVertices, VerTab[i][0], VerTab[i][1], VerTab[i][2], dummyint);
2358 // //   for (int i=0;i<solSize;i++) {
2359 // //     std::cout << ReqVerTab[i][0] <<" "<< ReqVerTab[i][1] << " "<< ReqVerTab[i][2] << std::endl;
2360 // //     GmfSetLin(idx, GmfVertices, ReqVerTab[i][0], ReqVerTab[i][1], ReqVerTab[i][2], dummyint);
2361 // //   }
2362 // 
2363 //   if (solSize) {
2364 //     idxRequired = GmfOpenMesh(theRequiredFileName, GmfWrite, GMFVERSION, GMFDIMENSION);
2365 //     if (!idxRequired) {
2366 //       GmfCloseMesh(idx);
2367 //       return false;
2368 //     }
2369 //     idxSol = GmfOpenMesh(theSolFileName, GmfWrite, GMFVERSION, GMFDIMENSION);
2370 //     if (!idxSol){
2371 //       GmfCloseMesh(idx);
2372 //       if (idxRequired)
2373 //         GmfCloseMesh(idxRequired);
2374 //       return false;
2375 //     }
2376 //     
2377 //     int TypTab[] = {GmfSca};
2378 //     GmfSetKwd(idxRequired, GmfVertices, solSize);
2379 //     GmfSetKwd(idxSol, GmfSolAtVertices, solSize, 1, TypTab);
2380 //     
2381 //     for (int i=0;i<solSize;i++) {
2382 //       double solTab[] = {enfVertexSizes.at(i)};
2383 //       GmfSetLin(idxRequired, GmfVertices, ReqVerTab[i][0], ReqVerTab[i][1], ReqVerTab[i][2], dummyint);
2384 //       GmfSetLin(idxSol, GmfSolAtVertices, solTab);
2385 //     }
2386 //     GmfCloseMesh(idxRequired);
2387 //     GmfCloseMesh(idxSol);
2388 //   }
2389 //   
2390 //   /* Write triangles number */
2391 //   if (tt.size()) {
2392 //     GmfSetKwd(idx, GmfTriangles, tt.size());
2393 //     for (int i=0;i<tt.size();i++)
2394 //       GmfSetLin(idx, GmfTriangles, tt[i][0], tt[i][1], tt[i][2], dummyint);
2395 //   }  
2396 //   
2397 //   /* Write edges number */
2398 //   if (et.size()) {
2399 //     GmfSetKwd(idx, GmfEdges, et.size());
2400 //     for (int i=0;i<et.size();i++)
2401 //       GmfSetLin(idx, GmfEdges, et[i][0], et[i][1], dummyint);
2402 //   }
2403 // 
2404 //   /* QUADRANGLES ========================== */
2405 //   // TODO: add pyramids ?
2406 // //   if (nbQuadrangles) {
2407 // //     for ( int i = 1; i <= quadranglesMap.Extent(); i++ )
2408 // //     {
2409 // //       aShape = quadranglesMap(i);
2410 // //       theSubMesh = theProxyMesh.GetSubMesh(aShape);
2411 // //       if ( !theSubMesh ) continue;
2412 // //       itOnSubMesh = theSubMesh->GetElements();
2413 // //       for ( int j = 0; j < 4; ++j )
2414 // //       {
2415 // //         aFace = itOnSubMesh->next();
2416 // //         itOnSubFace = aFace->nodesIterator();
2417 // //         aqt.clear();
2418 // //         while ( itOnSubFace->more() ) {
2419 // //           // find GHS3D ID
2420 // //           aSmdsID = itOnSubFace->next()->GetID();
2421 // //           itOnMap = theSmdsToGhs3dIdMap.find( aSmdsID );
2422 // //           ASSERT( itOnMap != theSmdsToGhs3dIdMap.end() );
2423 // //           aqt.push_back((*itOnMap).second);
2424 // //         }
2425 // //         qt.push_back(aqt);
2426 // //       }
2427 // //     }
2428 // //   }
2429 // // 
2430 // //   if (theEnforcedQuadrangles.size()) {
2431 // //     // Iterate over the enforced triangles
2432 // //     for(elemIt = theEnforcedQuadrangles.begin() ; elemIt != theEnforcedQuadrangles.end() ; ++elemIt) {
2433 // //       aFace = (*elemIt);
2434 // //       bool isOK = true;
2435 // //       itOnSubFace = aFace->nodesIterator();
2436 // //       aqt.clear();
2437 // //       for ( int j = 0; j < 4; ++j ) {
2438 // //         int aNodeID = itOnSubFace->next()->GetID();
2439 // //         itOnMap = theNodeId2NodeIndexMap.find(aNodeID);
2440 // //         if (itOnMap != theNodeId2NodeIndexMap.end())
2441 // //           aqt.push_back((*itOnMap).second);
2442 // //         else {
2443 // //           isOK = false;
2444 // //           theEnforcedQuadrangles.erase(elemIt);
2445 // //           break;
2446 // //         }
2447 // //       }
2448 // //       if (isOK)
2449 // //         qt.push_back(aqt);
2450 // //     }
2451 // //   }
2452 // //  
2453 //   
2454 // //   /* Write quadrilaterals number */
2455 // //   if (qt.size()) {
2456 // //     GmfSetKwd(idx, GmfQuadrilaterals, qt.size());
2457 // //     for (int i=0;i<qt.size();i++)
2458 // //       GmfSetLin(idx, GmfQuadrilaterals, qt[i][0], qt[i][1], qt[i][2], qt[i][3], dummyint);
2459 // //   }
2460 // 
2461 //   GmfCloseMesh(idx);
2462 //   return true;
2463 // }
2464
2465
2466 //=======================================================================
2467 //function : writeFaces
2468 //purpose  : 
2469 //=======================================================================
2470
2471 static bool writeFaces (ofstream &              theFile,
2472                         const SMESH_ProxyMesh&  theMesh,
2473                         const TopoDS_Shape&     theShape,
2474                         const map <int,int> &   theSmdsToGhs3dIdMap,
2475                         const map <int,int> &   theEnforcedNodeIdToGhs3dIdMap,
2476                         GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedEdges,
2477                         GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedTriangles)
2478 {
2479   // record structure:
2480   //
2481   // NB_ELEMS DUMMY_INT
2482   // Loop from 1 to NB_ELEMS
2483   // NB_NODES NODE_NB_1 NODE_NB_2 ... (NB_NODES + 1) times: DUMMY_INT
2484
2485   TopoDS_Shape aShape;
2486   const SMESHDS_SubMesh* theSubMesh;
2487   const SMDS_MeshElement* aFace;
2488   const char* space    = "  ";
2489   const int   dummyint = 0;
2490   map<int,int>::const_iterator itOnMap;
2491   SMDS_ElemIteratorPtr itOnSubMesh, itOnSubFace;
2492   int nbNodes, aSmdsID;
2493
2494   TIDSortedElemSet::const_iterator elemIt;
2495   int nbEnforcedEdges       = theEnforcedEdges.size();
2496   int nbEnforcedTriangles   = theEnforcedTriangles.size();
2497
2498   // count triangles bound to geometry
2499   int nbTriangles = 0;
2500
2501   TopTools_IndexedMapOfShape facesMap, trianglesMap;
2502   TopExp::MapShapes( theShape, TopAbs_FACE, facesMap );
2503   
2504   int nbFaces = facesMap.Extent();
2505
2506   for ( int i = 1; i <= nbFaces; ++i )
2507     if (( theSubMesh  = theMesh.GetSubMesh( facesMap(i))))
2508       nbTriangles += theSubMesh->NbElements();
2509   std::string tmpStr;
2510   (nbFaces == 0 || nbFaces == 1) ? tmpStr = " shape " : tmpStr = " shapes " ;
2511   std::cout << "    " << nbFaces << tmpStr << "of 2D dimension";
2512   int nbEnforcedElements = nbEnforcedEdges+nbEnforcedTriangles;
2513   if (nbEnforcedElements > 0) {
2514     (nbEnforcedElements == 1) ? tmpStr = "shape:" : tmpStr = "shapes:";
2515     std::cout << " and" << std::endl;
2516     std::cout << "    " << nbEnforcedElements 
2517                         << " enforced " << tmpStr << std::endl;
2518   }
2519   else
2520     std::cout << std::endl;
2521   if (nbEnforcedEdges) {
2522     (nbEnforcedEdges == 1) ? tmpStr = "edge" : tmpStr = "edges";
2523     std::cout << "      " << nbEnforcedEdges << " enforced " << tmpStr << std::endl;
2524   }
2525   if (nbEnforcedTriangles) {
2526     (nbEnforcedTriangles == 1) ? tmpStr = "triangle" : tmpStr = "triangles";
2527     std::cout << "      " << nbEnforcedTriangles << " enforced " << tmpStr << std::endl;
2528   }
2529   std::cout << std::endl;
2530
2531 //   theFile << space << nbTriangles << space << dummyint << std::endl;
2532   std::ostringstream globalStream, localStream, aStream;
2533
2534   for ( int i = 1; i <= facesMap.Extent(); i++ )
2535   {
2536     aShape = facesMap(i);
2537     theSubMesh = theMesh.GetSubMesh(aShape);
2538     if ( !theSubMesh ) continue;
2539     itOnSubMesh = theSubMesh->GetElements();
2540     while ( itOnSubMesh->more() )
2541     {
2542       aFace = itOnSubMesh->next();
2543       nbNodes = aFace->NbCornerNodes();
2544
2545       localStream << nbNodes << space;
2546
2547       itOnSubFace = aFace->nodesIterator();
2548       for ( int j = 0; j < 3; ++j ) {
2549         // find GHS3D ID
2550         aSmdsID = itOnSubFace->next()->GetID();
2551         itOnMap = theSmdsToGhs3dIdMap.find( aSmdsID );
2552         // if ( itOnMap == theSmdsToGhs3dIdMap.end() ) {
2553         //   cout << "not found node: " << aSmdsID << endl;
2554         //   return false;
2555         // }
2556         ASSERT( itOnMap != theSmdsToGhs3dIdMap.end() );
2557
2558         localStream << (*itOnMap).second << space ;
2559       }
2560
2561       // (NB_NODES + 1) times: DUMMY_INT
2562       for ( int j=0; j<=nbNodes; j++)
2563         localStream << dummyint << space ;
2564
2565       localStream << std::endl;
2566     }
2567   }
2568   
2569   globalStream << localStream.str();
2570   localStream.str("");
2571
2572   //
2573   //        FACES : END
2574   //
2575
2576 //   //
2577 //   //        ENFORCED EDGES : BEGIN
2578 //   //
2579 //   
2580 //   // Iterate over the enforced edges
2581 //   int usedEnforcedEdges = 0;
2582 //   bool isOK;
2583 //   for(elemIt = theEnforcedEdges.begin() ; elemIt != theEnforcedEdges.end() ; ++elemIt) {
2584 //     aFace = (*elemIt);
2585 //     isOK = true;
2586 //     itOnSubFace = aFace->nodesIterator();
2587 //     aStream.str("");
2588 //     aStream << "2" << space ;
2589 //     for ( int j = 0; j < 2; ++j ) {
2590 //       aSmdsID = itOnSubFace->next()->GetID();
2591 //       itOnMap = theEnforcedNodeIdToGhs3dIdMap.find(aSmdsID);
2592 //       if (itOnMap != theEnforcedNodeIdToGhs3dIdMap.end())
2593 //         aStream << (*itOnMap).second << space;
2594 //       else {
2595 //         isOK = false;
2596 //         break;
2597 //       }
2598 //     }
2599 //     if (isOK) {
2600 //       for ( int j=0; j<=2; j++)
2601 //         aStream << dummyint << space ;
2602 // //       aStream << dummyint << space << dummyint;
2603 //       localStream << aStream.str() << std::endl;
2604 //       usedEnforcedEdges++;
2605 //     }
2606 //   }
2607 //   
2608 //   if (usedEnforcedEdges) {
2609 //     globalStream << localStream.str();
2610 //     localStream.str("");
2611 //   }
2612 // 
2613 //   //
2614 //   //        ENFORCED EDGES : END
2615 //   //
2616 //   //
2617 // 
2618 //   //
2619 //   //        ENFORCED TRIANGLES : BEGIN
2620 //   //
2621 //     // Iterate over the enforced triangles
2622 //   int usedEnforcedTriangles = 0;
2623 //   for(elemIt = theEnforcedTriangles.begin() ; elemIt != theEnforcedTriangles.end() ; ++elemIt) {
2624 //     aFace = (*elemIt);
2625 //     nbNodes = aFace->NbCornerNodes();
2626 //     isOK = true;
2627 //     itOnSubFace = aFace->nodesIterator();
2628 //     aStream.str("");
2629 //     aStream << nbNodes << space ;
2630 //     for ( int j = 0; j < 3; ++j ) {
2631 //       aSmdsID = itOnSubFace->next()->GetID();
2632 //       itOnMap = theEnforcedNodeIdToGhs3dIdMap.find(aSmdsID);
2633 //       if (itOnMap != theEnforcedNodeIdToGhs3dIdMap.end())
2634 //         aStream << (*itOnMap).second << space;
2635 //       else {
2636 //         isOK = false;
2637 //         break;
2638 //       }
2639 //     }
2640 //     if (isOK) {
2641 //       for ( int j=0; j<=3; j++)
2642 //         aStream << dummyint << space ;
2643 //       localStream << aStream.str() << std::endl;
2644 //       usedEnforcedTriangles++;
2645 //     }
2646 //   }
2647 //   
2648 //   if (usedEnforcedTriangles) {
2649 //     globalStream << localStream.str();
2650 //     localStream.str("");
2651 //   }
2652 // 
2653 //   //
2654 //   //        ENFORCED TRIANGLES : END
2655 //   //
2656   
2657   theFile
2658   << nbTriangles/*+usedEnforcedTriangles+usedEnforcedEdges*/
2659   << " 0" << std::endl
2660   << globalStream.str();
2661
2662   return true;
2663 }
2664
2665 //=======================================================================
2666 //function : writePoints
2667 //purpose  : 
2668 //=======================================================================
2669
2670 static bool writePoints (ofstream &                       theFile,
2671                          SMESH_MesherHelper&              theHelper,
2672                          map <int,int> &                  theSmdsToGhs3dIdMap,
2673                          map <int,int> &                  theEnforcedNodeIdToGhs3dIdMap,
2674                          map <int,const SMDS_MeshNode*> & theGhs3dIdToNodeMap,
2675                          GHS3DPlugin_Hypothesis::TID2SizeMap & theNodeIDToSizeMap,
2676                          GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues & theEnforcedVertices,
2677                          GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap & theEnforcedNodes,
2678                          GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedEdges,
2679                          GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedTriangles)
2680 {
2681   // record structure:
2682   //
2683   // NB_NODES
2684   // Loop from 1 to NB_NODES
2685   //   X Y Z DUMMY_INT
2686
2687   SMESHDS_Mesh * theMeshDS = theHelper.GetMeshDS();
2688   int nbNodes = theMeshDS->NbNodes();
2689   if ( nbNodes == 0 )
2690     return false;
2691   
2692   int nbEnforcedVertices = theEnforcedVertices.size();
2693   int nbEnforcedNodes    = theEnforcedNodes.size();
2694   
2695   const TopoDS_Shape shapeToMesh = theMeshDS->ShapeToMesh();
2696   
2697   int aGhs3dID = 1;
2698   SMDS_NodeIteratorPtr nodeIt = theMeshDS->nodesIterator();
2699   const SMDS_MeshNode* node;
2700
2701   // Issue 020674: EDF 870 SMESH: Mesh generated by Netgen not usable by GHS3D
2702   // The problem is in nodes on degenerated edges, we need to skip nodes which are free
2703   // and replace not-free nodes on degenerated edges by the node on vertex
2704   TNodeNodeMap n2nDegen; // map a node on degenerated edge to a node on vertex
2705   TNodeNodeMap::iterator n2nDegenIt;
2706   if ( theHelper.HasDegeneratedEdges() )
2707   {
2708     set<int> checkedSM;
2709     for (TopExp_Explorer e(theMeshDS->ShapeToMesh(), TopAbs_EDGE ); e.More(); e.Next())
2710     {
2711       SMESH_subMesh* sm = theHelper.GetMesh()->GetSubMesh( e.Current() );
2712       if ( checkedSM.insert( sm->GetId() ).second && theHelper.IsDegenShape(sm->GetId() ))
2713       {
2714         if ( SMESHDS_SubMesh* smDS = sm->GetSubMeshDS() )
2715         {
2716           TopoDS_Shape vertex = TopoDS_Iterator( e.Current() ).Value();
2717           const SMDS_MeshNode* vNode = SMESH_Algo::VertexNode( TopoDS::Vertex( vertex ), theMeshDS);
2718           {
2719             SMDS_NodeIteratorPtr nIt = smDS->GetNodes();
2720             while ( nIt->more() )
2721               n2nDegen.insert( make_pair( nIt->next(), vNode ));
2722           }
2723         }
2724       }
2725     }
2726     nbNodes -= n2nDegen.size();
2727   }
2728
2729   const bool isQuadMesh = 
2730     theHelper.GetMesh()->NbEdges( ORDER_QUADRATIC ) ||
2731     theHelper.GetMesh()->NbFaces( ORDER_QUADRATIC ) ||
2732     theHelper.GetMesh()->NbVolumes( ORDER_QUADRATIC );
2733   if ( isQuadMesh )
2734   {
2735     // descrease nbNodes by nb of medium nodes
2736     while ( nodeIt->more() )
2737     {
2738       node = nodeIt->next();
2739       if ( !theHelper.IsDegenShape( node->getshapeId() ))
2740         nbNodes -= int( theHelper.IsMedium( node ));
2741     }
2742     nodeIt = theMeshDS->nodesIterator();
2743   }
2744
2745   const char* space    = "  ";
2746   const int   dummyint = 0;
2747
2748   std::string tmpStr;
2749   (nbNodes == 0 || nbNodes == 1) ? tmpStr = " node" : tmpStr = " nodes";
2750   // NB_NODES
2751   std::cout << std::endl;
2752   std::cout << "The initial 2D mesh contains :" << std::endl;
2753   std::cout << "    " << nbNodes << tmpStr << std::endl;
2754   if (nbEnforcedVertices > 0) {
2755     (nbEnforcedVertices == 1) ? tmpStr = "vertex" : tmpStr = "vertices";
2756     std::cout << "    " << nbEnforcedVertices << " enforced " << tmpStr << std::endl;
2757   }
2758   if (nbEnforcedNodes > 0) {
2759     (nbEnforcedNodes == 1) ? tmpStr = "node" : tmpStr = "nodes";
2760     std::cout << "    " << nbEnforcedNodes << " enforced " << tmpStr << std::endl;
2761   }
2762   std::cout << std::endl;
2763   std::cout << "Start writing in 'points' file ..." << std::endl;
2764
2765   theFile << nbNodes << std::endl;
2766
2767   // Loop from 1 to NB_NODES
2768
2769   while ( nodeIt->more() )
2770   {
2771     node = nodeIt->next();
2772     if ( isQuadMesh && theHelper.IsMedium( node )) // Issue 0021238
2773       continue;
2774     if ( n2nDegen.count( node ) ) // Issue 0020674
2775       continue;
2776
2777     theSmdsToGhs3dIdMap.insert( make_pair( node->GetID(), aGhs3dID ));
2778     theGhs3dIdToNodeMap.insert( make_pair( aGhs3dID, node ));
2779     aGhs3dID++;
2780
2781     // X Y Z DUMMY_INT
2782     theFile
2783     << node->X() << space 
2784     << node->Y() << space 
2785     << node->Z() << space 
2786     << dummyint;
2787
2788     theFile << std::endl;
2789
2790   }
2791   
2792   // Iterate over the enforced nodes
2793   std::map<int,double> enfVertexIndexSizeMap;
2794   if (nbEnforcedNodes) {
2795     GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap::const_iterator nodeIt = theEnforcedNodes.begin();
2796     for( ; nodeIt != theEnforcedNodes.end() ; ++nodeIt) {
2797       double x = nodeIt->first->X();
2798       double y = nodeIt->first->Y();
2799       double z = nodeIt->first->Z();
2800       // Test if point is inside shape to mesh
2801       gp_Pnt myPoint(x,y,z);
2802       BRepClass3d_SolidClassifier scl(shapeToMesh);
2803       scl.Perform(myPoint, 1e-7);
2804       TopAbs_State result = scl.State();
2805       if ( result != TopAbs_IN )
2806         continue;
2807       std::vector<double> coords;
2808       coords.push_back(x);
2809       coords.push_back(y);
2810       coords.push_back(z);
2811       if (theEnforcedVertices.find(coords) != theEnforcedVertices.end())
2812         continue;
2813         
2814 //      double size = theNodeIDToSizeMap.find(nodeIt->first->GetID())->second;
2815   //       theGhs3dIdToNodeMap.insert( make_pair( nbNodes + i, (*nodeIt) ));
2816   //       MESSAGE("Adding enforced node (" << x << "," << y <<"," << z << ")");
2817       // X Y Z PHY_SIZE DUMMY_INT
2818       theFile
2819       << x << space 
2820       << y << space 
2821       << z << space
2822       << -1 << space
2823       << dummyint << space;
2824       theFile << std::endl;
2825       theEnforcedNodeIdToGhs3dIdMap.insert( make_pair( nodeIt->first->GetID(), aGhs3dID ));
2826       enfVertexIndexSizeMap[aGhs3dID] = -1;
2827       aGhs3dID++;
2828   //     else
2829   //         MESSAGE("Enforced vertex (" << x << "," << y <<"," << z << ") is not inside the geometry: it was not added ");
2830     }
2831   }
2832   
2833   if (nbEnforcedVertices) {
2834     // Iterate over the enforced vertices
2835     GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues::const_iterator vertexIt = theEnforcedVertices.begin();
2836     for( ; vertexIt != theEnforcedVertices.end() ; ++vertexIt) {
2837       double x = vertexIt->first[0];
2838       double y = vertexIt->first[1];
2839       double z = vertexIt->first[2];
2840       // Test if point is inside shape to mesh
2841       gp_Pnt myPoint(x,y,z);
2842       BRepClass3d_SolidClassifier scl(shapeToMesh);
2843       scl.Perform(myPoint, 1e-7);
2844       TopAbs_State result = scl.State();
2845       if ( result != TopAbs_IN )
2846         continue;
2847       MESSAGE("Adding enforced vertex (" << x << "," << y <<"," << z << ") = " << vertexIt->second);
2848       // X Y Z PHY_SIZE DUMMY_INT
2849       theFile
2850       << x << space 
2851       << y << space 
2852       << z << space
2853       << vertexIt->second << space 
2854       << dummyint << space;
2855       theFile << std::endl;
2856       enfVertexIndexSizeMap[aGhs3dID] = vertexIt->second;
2857       aGhs3dID++;
2858     }
2859   }
2860   
2861   
2862   std::cout << std::endl;
2863   std::cout << "End writing in 'points' file." << std::endl;
2864
2865   return true;
2866 }
2867
2868 //=======================================================================
2869 //function : readResultFile
2870 //purpose  : readResultFile with geometry
2871 //=======================================================================
2872
2873 static bool readResultFile(const int                       fileOpen,
2874 #ifdef WNT
2875                            const char*                     fileName,
2876 #endif
2877                            GHS3DPlugin_GHS3D*              theAlgo,
2878                            SMESH_MesherHelper&             theHelper,
2879                            TopoDS_Shape                    tabShape[],
2880                            double**                        tabBox,
2881                            const int                       nbShape,
2882                            map <int,const SMDS_MeshNode*>& theGhs3dIdToNodeMap,
2883                            std::map <int,int> &            theNodeId2NodeIndexMap,
2884                            bool                            toMeshHoles,
2885                            int                             nbEnforcedVertices,
2886                            int                             nbEnforcedNodes,
2887                            GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedEdges,
2888                            GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedTriangles)
2889 {
2890   MESSAGE("GHS3DPlugin_GHS3D::readResultFile()");
2891   Kernel_Utils::Localizer loc;
2892   struct stat status;
2893   size_t      length;
2894   
2895   std::string tmpStr;
2896
2897   char *ptr, *mapPtr;
2898   char *tetraPtr;
2899   char *shapePtr;
2900
2901   SMESHDS_Mesh* theMeshDS = theHelper.GetMeshDS();
2902
2903   int nbElems, nbNodes, nbInputNodes;
2904   int nbTriangle;
2905   int ID, shapeID, ghs3dShapeID;
2906   int IdShapeRef = 1;
2907   int compoundID =
2908     nbShape ? theMeshDS->ShapeToIndex( tabShape[0] ) : theMeshDS->ShapeToIndex( theMeshDS->ShapeToMesh() );
2909
2910   int *tab, *tabID, *nodeID, *nodeAssigne;
2911   double *coord;
2912   const SMDS_MeshNode **node;
2913
2914   tab    = new int[3];
2915   nodeID = new int[4];
2916   coord  = new double[3];
2917   node   = new const SMDS_MeshNode*[4];
2918
2919   TopoDS_Shape aSolid;
2920   SMDS_MeshNode * aNewNode;
2921   map <int,const SMDS_MeshNode*>::iterator itOnNode;
2922   SMDS_MeshElement* aTet;
2923 #ifdef _DEBUG_
2924   set<int> shapeIDs;
2925 #endif
2926
2927   // Read the file state
2928   fstat(fileOpen, &status);
2929   length   = status.st_size;
2930
2931   // Mapping the result file into memory
2932 #ifdef WNT
2933   HANDLE fd = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ,
2934                          NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
2935   HANDLE hMapObject = CreateFileMapping(fd, NULL, PAGE_READONLY,
2936                                         0, (DWORD)length, NULL);
2937   ptr = ( char* ) MapViewOfFile(hMapObject, FILE_MAP_READ, 0, 0, 0 );
2938 #else
2939   ptr = (char *) mmap(0,length,PROT_READ,MAP_PRIVATE,fileOpen,0);
2940 #endif
2941   mapPtr = ptr;
2942
2943   ptr      = readMapIntLine(ptr, tab);
2944   tetraPtr = ptr;
2945
2946   nbElems      = tab[0];
2947   nbNodes      = tab[1];
2948   nbInputNodes = tab[2];
2949
2950   nodeAssigne = new int[ nbNodes+1 ];
2951
2952   if (nbShape > 0)
2953     aSolid = tabShape[0];
2954
2955   // Reading the nodeId
2956   for (int i=0; i < 4*nbElems; i++)
2957     strtol(ptr, &ptr, 10);
2958
2959   MESSAGE("nbInputNodes: "<<nbInputNodes);
2960   MESSAGE("nbEnforcedVertices: "<<nbEnforcedVertices);
2961   MESSAGE("nbEnforcedNodes: "<<nbEnforcedNodes);
2962   // Reading the nodeCoor and update the nodeMap
2963   for (int iNode=1; iNode <= nbNodes; iNode++) {
2964     if(theAlgo->computeCanceled())
2965       return false;
2966     for (int iCoor=0; iCoor < 3; iCoor++)
2967       coord[ iCoor ] = strtod(ptr, &ptr);
2968     nodeAssigne[ iNode ] = 1;
2969     if ( iNode > (nbInputNodes-(nbEnforcedVertices+nbEnforcedNodes)) ) {
2970       // Creating SMESH nodes
2971       // - for enforced vertices
2972       // - for vertices of forced edges
2973       // - for ghs3d nodes
2974       nodeAssigne[ iNode ] = 0;
2975       aNewNode = theMeshDS->AddNode( coord[0],coord[1],coord[2] );
2976       theGhs3dIdToNodeMap.insert(theGhs3dIdToNodeMap.end(), make_pair( iNode, aNewNode ));
2977     }
2978   }
2979
2980   // Reading the number of triangles which corresponds to the number of sub-domains
2981   nbTriangle = strtol(ptr, &ptr, 10);
2982
2983   tabID = new int[nbTriangle];
2984   for (int i=0; i < nbTriangle; i++) {
2985     if(theAlgo->computeCanceled())
2986       return false;
2987     tabID[i] = 0;
2988     // find the solid corresponding to GHS3D sub-domain following
2989     // the technique proposed in GHS3D manual in chapter
2990     // "B.4 Subdomain (sub-region) assignment"
2991     int nodeId1 = strtol(ptr, &ptr, 10);
2992     int nodeId2 = strtol(ptr, &ptr, 10);
2993     int nodeId3 = strtol(ptr, &ptr, 10);
2994     if ( nbTriangle > 1 ) {
2995       const SMDS_MeshNode* n1 = theGhs3dIdToNodeMap[ nodeId1 ];
2996       const SMDS_MeshNode* n2 = theGhs3dIdToNodeMap[ nodeId2 ];
2997       const SMDS_MeshNode* n3 = theGhs3dIdToNodeMap[ nodeId3 ];
2998       if (!n1 || !n2 || !n3) {
2999         tabID[i] = HOLE_ID;
3000         continue;
3001       }
3002       try {
3003         OCC_CATCH_SIGNALS;
3004 //         tabID[i] = findShapeID( theHelper, n1, n2, n3, toMeshHoles );
3005         tabID[i] = findShapeID( *theHelper.GetMesh(), n1, n2, n3, toMeshHoles );
3006         // -- 0020330: Pb with ghs3d as a submesh
3007         // check that found shape is to be meshed
3008         if ( tabID[i] > 0 ) {
3009           const TopoDS_Shape& foundShape = theMeshDS->IndexToShape( tabID[i] );
3010           bool isToBeMeshed = false;
3011           for ( int iS = 0; !isToBeMeshed && iS < nbShape; ++iS )
3012             isToBeMeshed = foundShape.IsSame( tabShape[ iS ]);
3013           if ( !isToBeMeshed )
3014             tabID[i] = HOLE_ID;
3015         }
3016         // END -- 0020330: Pb with ghs3d as a submesh
3017 #ifdef _DEBUG_
3018         std::cout << i+1 << " subdomain: findShapeID() returns " << tabID[i] << std::endl;
3019 #endif
3020       }
3021       catch ( Standard_Failure & ex)
3022       {
3023 #ifdef _DEBUG_
3024         std::cout << i+1 << " subdomain: Exception caugt: " << ex.GetMessageString() << std::endl;
3025 #endif
3026       }
3027       catch (...) {
3028 #ifdef _DEBUG_
3029         std::cout << i+1 << " subdomain: unknown exception caught " << std::endl;
3030 #endif
3031       }
3032     }
3033   }
3034
3035   shapePtr = ptr;
3036
3037   if ( nbTriangle <= nbShape ) // no holes
3038     toMeshHoles = true; // not avoid creating tetras in holes
3039
3040   // Associating the tetrahedrons to the shapes
3041   shapeID = compoundID;
3042   for (int iElem = 0; iElem < nbElems; iElem++) {
3043     if(theAlgo->computeCanceled())
3044       return false;
3045     for (int iNode = 0; iNode < 4; iNode++) {
3046       ID = strtol(tetraPtr, &tetraPtr, 10);
3047       itOnNode = theGhs3dIdToNodeMap.find(ID);
3048       node[ iNode ] = itOnNode->second;
3049       nodeID[ iNode ] = ID;
3050     }
3051     // We always run GHS3D with "to mesh holes"==TRUE but we must not create
3052     // tetras within holes depending on hypo option,
3053     // so we first check if aTet is inside a hole and then create it 
3054     //aTet = theMeshDS->AddVolume( node[1], node[0], node[2], node[3] );
3055     if ( nbTriangle > 1 ) {
3056       shapeID = HOLE_ID; // negative shapeID means not to create tetras if !toMeshHoles
3057       ghs3dShapeID = strtol(shapePtr, &shapePtr, 10) - IdShapeRef;
3058       if ( tabID[ ghs3dShapeID ] == 0 ) {
3059         TopAbs_State state;
3060         aSolid = findShape(node, aSolid, tabShape, tabBox, nbShape, &state);
3061         if ( toMeshHoles || state == TopAbs_IN )
3062           shapeID = theMeshDS->ShapeToIndex( aSolid );
3063         tabID[ ghs3dShapeID ] = shapeID;
3064       }
3065       else
3066         shapeID = tabID[ ghs3dShapeID ];
3067     }
3068     else if ( nbShape > 1 ) {
3069       // Case where nbTriangle == 1 while nbShape == 2 encountered
3070       // with compound of 2 boxes and "To mesh holes"==False,
3071       // so there are no subdomains specified for each tetrahedron.
3072       // Try to guess a solid by a node already bound to shape
3073       shapeID = 0;
3074       for ( int i=0; i<4 && shapeID==0; i++ ) {
3075         if ( nodeAssigne[ nodeID[i] ] == 1 &&
3076              node[i]->GetPosition()->GetTypeOfPosition() == SMDS_TOP_3DSPACE &&
3077              node[i]->getshapeId() > 1 )
3078         {
3079           shapeID = node[i]->getshapeId();
3080         }
3081       }
3082       if ( shapeID==0 ) {
3083         aSolid = findShape(node, aSolid, tabShape, tabBox, nbShape);
3084         shapeID = theMeshDS->ShapeToIndex( aSolid );
3085       }
3086     }
3087     // set new nodes and tetrahedron onto the shape
3088     for ( int i=0; i<4; i++ ) {
3089       if ( nodeAssigne[ nodeID[i] ] == 0 ) {
3090         if ( shapeID != HOLE_ID )
3091           theMeshDS->SetNodeInVolume( node[i], shapeID );
3092         nodeAssigne[ nodeID[i] ] = shapeID;
3093       }
3094     }
3095     if ( toMeshHoles || shapeID != HOLE_ID ) {
3096       aTet = theHelper.AddVolume( node[1], node[0], node[2], node[3],
3097                                   /*id=*/0, /*force3d=*/false);
3098       theMeshDS->SetMeshElementOnShape( aTet, shapeID );
3099     }
3100 #ifdef _DEBUG_
3101     shapeIDs.insert( shapeID );
3102 #endif
3103   }
3104   
3105   // Add enforced elements
3106   GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap::const_iterator elemIt;
3107   const SMDS_MeshElement* anElem;
3108   SMDS_ElemIteratorPtr itOnEnfElem;
3109   map<int,int>::const_iterator itOnMap;
3110   shapeID = compoundID;
3111   // Enforced edges
3112   if (theEnforcedEdges.size()) {
3113     (theEnforcedEdges.size() <= 1) ? tmpStr = " enforced edge" : " enforced edges";
3114     std::cout << "Add " << theEnforcedEdges.size() << tmpStr << std::endl;
3115     std::vector< const SMDS_MeshNode* > node( 2 );
3116     // Iterate over the enforced edges
3117     for(elemIt = theEnforcedEdges.begin() ; elemIt != theEnforcedEdges.end() ; ++elemIt) {
3118       anElem = elemIt->first;
3119       bool addElem = true;
3120       itOnEnfElem = anElem->nodesIterator();
3121       for ( int j = 0; j < 2; ++j ) {
3122         int aNodeID = itOnEnfElem->next()->GetID();
3123         itOnMap = theNodeId2NodeIndexMap.find(aNodeID);
3124         if (itOnMap != theNodeId2NodeIndexMap.end()) {
3125           itOnNode = theGhs3dIdToNodeMap.find((*itOnMap).second);
3126           if (itOnNode != theGhs3dIdToNodeMap.end()) {
3127             node.push_back((*itOnNode).second);
3128 //             shapeID =(*itOnNode).second->getshapeId();
3129           }
3130           else
3131             addElem = false;
3132         }
3133         else
3134           addElem = false;
3135       }
3136       if (addElem) {
3137         aTet = theHelper.AddEdge( node[0], node[1], 0,  false);
3138         theMeshDS->SetMeshElementOnShape( aTet, shapeID );
3139       }
3140     }
3141   }
3142   // Enforced faces
3143   if (theEnforcedTriangles.size()) {
3144     (theEnforcedTriangles.size() <= 1) ? tmpStr = " enforced triangle" : " enforced triangles";
3145     std::cout << "Add " << theEnforcedTriangles.size() << " enforced triangles" << std::endl;
3146     std::vector< const SMDS_MeshNode* > node( 3 );
3147     // Iterate over the enforced triangles
3148     for(elemIt = theEnforcedTriangles.begin() ; elemIt != theEnforcedTriangles.end() ; ++elemIt) {
3149       anElem = elemIt->first;
3150       bool addElem = true;
3151       itOnEnfElem = anElem->nodesIterator();
3152       for ( int j = 0; j < 3; ++j ) {
3153         int aNodeID = itOnEnfElem->next()->GetID();
3154         itOnMap = theNodeId2NodeIndexMap.find(aNodeID);
3155         if (itOnMap != theNodeId2NodeIndexMap.end()) {
3156           itOnNode = theGhs3dIdToNodeMap.find((*itOnMap).second);
3157           if (itOnNode != theGhs3dIdToNodeMap.end()) {
3158             node.push_back((*itOnNode).second);
3159 //             shapeID =(*itOnNode).second->getshapeId();
3160           }
3161           else
3162             addElem = false;
3163         }
3164         else
3165           addElem = false;
3166       }
3167       if (addElem) {
3168         aTet = theHelper.AddFace( node[0], node[1], node[2], 0,  false);
3169         theMeshDS->SetMeshElementOnShape( aTet, shapeID );
3170       }
3171     }
3172   }
3173
3174   // Remove nodes of tetras inside holes if !toMeshHoles
3175   if ( !toMeshHoles ) {
3176     itOnNode = theGhs3dIdToNodeMap.find( nbInputNodes );
3177     for ( ; itOnNode != theGhs3dIdToNodeMap.end(); ++itOnNode) {
3178       ID = itOnNode->first;
3179       if ( nodeAssigne[ ID ] == HOLE_ID )
3180         theMeshDS->RemoveFreeNode( itOnNode->second, 0 );
3181     }
3182   }
3183
3184   
3185   if ( nbElems ) {
3186     (nbElems <= 1) ? tmpStr = " tetrahedra" : " tetrahedrons";
3187     cout << nbElems << tmpStr << " have been associated to " << nbShape;
3188     (nbShape <= 1) ? tmpStr = " shape" : " shapes";
3189     cout << tmpStr << endl;
3190   }
3191 #ifdef WNT
3192   UnmapViewOfFile(mapPtr);
3193   CloseHandle(hMapObject);
3194   CloseHandle(fd);
3195 #else
3196   munmap(mapPtr, length);
3197 #endif
3198   close(fileOpen);
3199
3200   delete [] tab;
3201   delete [] tabID;
3202   delete [] nodeID;
3203   delete [] coord;
3204   delete [] node;
3205   delete [] nodeAssigne;
3206
3207 #ifdef _DEBUG_
3208   shapeIDs.erase(-1);
3209   if ( shapeIDs.size() != nbShape ) {
3210     (shapeIDs.size() <= 1) ? tmpStr = " solid" : " solids";
3211     std::cout << "Only " << shapeIDs.size() << tmpStr << " of " << nbShape << " found" << std::endl;
3212     for (int i=0; i<nbShape; i++) {
3213       shapeID = theMeshDS->ShapeToIndex( tabShape[i] );
3214       if ( shapeIDs.find( shapeID ) == shapeIDs.end() )
3215         std::cout << "  Solid #" << shapeID << " not found" << std::endl;
3216     }
3217   }
3218 #endif
3219
3220   return true;
3221 }
3222
3223
3224 //=============================================================================
3225 /*!
3226  *Here we are going to use the GHS3D mesher with geometry
3227  */
3228 //=============================================================================
3229
3230 bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
3231                                 const TopoDS_Shape& theShape)
3232 {
3233   bool Ok(false);
3234   //SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
3235
3236   // we count the number of shapes
3237   // _nbShape = countShape( meshDS, TopAbs_SOLID ); -- 0020330: Pb with ghs3d as a submesh
3238   _nbShape = 0;
3239   TopExp_Explorer expBox ( theShape, TopAbs_SOLID );
3240   for ( ; expBox.More(); expBox.Next() )
3241     _nbShape++;
3242
3243   // create bounding box for every shape inside the compound
3244
3245   int iShape = 0;
3246   TopoDS_Shape* tabShape;
3247   double**      tabBox;
3248   tabShape = new TopoDS_Shape[_nbShape];
3249   tabBox   = new double*[_nbShape];
3250   for (int i=0; i<_nbShape; i++)
3251     tabBox[i] = new double[6];
3252   Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
3253
3254   for (expBox.ReInit(); expBox.More(); expBox.Next()) {
3255     tabShape[iShape] = expBox.Current();
3256     Bnd_Box BoundingBox;
3257     BRepBndLib::Add(expBox.Current(), BoundingBox);
3258     BoundingBox.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
3259     tabBox[iShape][0] = Xmin; tabBox[iShape][1] = Xmax;
3260     tabBox[iShape][2] = Ymin; tabBox[iShape][3] = Ymax;
3261     tabBox[iShape][4] = Zmin; tabBox[iShape][5] = Zmax;
3262     iShape++;
3263   }
3264
3265   // a unique working file name
3266   // to avoid access to the same files by eg different users
3267   _genericName = GHS3DPlugin_Hypothesis::GetFileName(_hyp);
3268   TCollection_AsciiString aGenericName((char*) _genericName.c_str() );
3269
3270   TCollection_AsciiString aResultFileName;
3271   TCollection_AsciiString aLogFileName    = aGenericName + ".log";    // log
3272   // The output .mesh file does not contain yet the subdomain-info (Ghs3D 4.2)
3273 //   TCollection_AsciiString aGMFFileName, aRequiredVerticesFileName, aSolFileName;
3274 //   TCollection_AsciiString aGenericNameRequired = aGenericName + "_required";
3275 // #ifdef _DEBUG_
3276 //   aGMFFileName    = aGenericName + ".mesh"; // GMF mesh file
3277 //   aResultFileName = aGenericName + "Vol.mesh"; // GMF mesh file
3278 //   aRequiredVerticesFileName    = aGenericNameRequired + ".mesh"; // GMF required vertices mesh file
3279 //   aSolFileName    = aGenericName + "_required.sol"; // GMF solution file
3280 // #else
3281 //   aGMFFileName    = aGenericName + ".meshb"; // GMF mesh file
3282 //   aResultFileName = aGenericName + "Vol.meshb"; // GMF mesh file
3283 //   aRequiredVerticesFileName    = aGenericNameRequired + ".meshb"; // GMF required vertices mesh file
3284 //   aSolFileName    = aGenericName + "_required.solb"; // GMF solution file
3285 // #endif
3286
3287   TCollection_AsciiString aFacesFileName, aPointsFileName, aBadResFileName, aBbResFileName;
3288
3289   aFacesFileName  = aGenericName + ".faces";  // in faces
3290   aPointsFileName = aGenericName + ".points"; // in points
3291   aResultFileName = aGenericName + ".noboite";// out points and volumes
3292   aBadResFileName = aGenericName + ".boite";  // out bad result
3293   aBbResFileName  = aGenericName + ".bb";     // out vertex stepsize
3294   
3295   // -----------------
3296   // make input files
3297   // -----------------
3298
3299   ofstream aFacesFile  ( aFacesFileName.ToCString()  , ios::out);
3300   ofstream aPointsFile ( aPointsFileName.ToCString() , ios::out);
3301
3302   Ok =
3303     aFacesFile.rdbuf()->is_open() && aPointsFile.rdbuf()->is_open();
3304   if (!Ok) {
3305     INFOS( "Can't write into " << aFacesFileName);
3306     return error(SMESH_Comment("Can't write into ") << aFacesFileName);
3307   }
3308
3309   std::map <int,int> aNodeId2NodeIndexMap, aSmdsToGhs3dIdMap, anEnforcedNodeIdToGhs3dIdMap;
3310   std::map <int,const SMDS_MeshNode*> aGhs3dIdToNodeMap;
3311   std::map <int, int> nodeID2nodeIndexMap;
3312   GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues coordsSizeMap = GHS3DPlugin_Hypothesis::GetEnforcedVerticesCoordsSize(_hyp);
3313   GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap enforcedNodes = GHS3DPlugin_Hypothesis::GetEnforcedNodes(_hyp);
3314   GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap enforcedEdges = GHS3DPlugin_Hypothesis::GetEnforcedEdges(_hyp);
3315   GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap enforcedTriangles = GHS3DPlugin_Hypothesis::GetEnforcedTriangles(_hyp);
3316 //   TIDSortedElemSet enforcedQuadrangles = GHS3DPlugin_Hypothesis::GetEnforcedQuadrangles(_hyp);
3317   GHS3DPlugin_Hypothesis::TID2SizeMap nodeIDToSizeMap = GHS3DPlugin_Hypothesis::GetNodeIDToSizeMap(_hyp);
3318
3319   int nbEnforcedVertices = coordsSizeMap.size();
3320   int nbEnforcedNodes = enforcedNodes.size();
3321   
3322   std::string tmpStr;
3323   (nbEnforcedNodes <= 1) ? tmpStr = "node" : "nodes";
3324   std::cout << nbEnforcedNodes << " enforced " << tmpStr << " from hypo" << std::endl;
3325   (nbEnforcedVertices <= 1) ? tmpStr = "vertex" : "vertices";
3326   std::cout << nbEnforcedVertices << " enforced " << tmpStr << " from hypo" << std::endl;
3327   
3328   SMESH_MesherHelper helper( theMesh );
3329   helper.SetSubShape( theShape );
3330
3331   {
3332     SMESH_ProxyMesh::Ptr proxyMesh( new SMESH_ProxyMesh( theMesh ));
3333
3334     // make prisms on quadrangles
3335     if ( theMesh.NbQuadrangles() > 0 )
3336     {
3337       vector<SMESH_ProxyMesh::Ptr> components;
3338       for (expBox.ReInit(); expBox.More(); expBox.Next())
3339       {
3340         if ( _viscousLayersHyp )
3341         {
3342           proxyMesh = _viscousLayersHyp->Compute( theMesh, expBox.Current() );
3343           if ( !proxyMesh )
3344             return false;
3345         }
3346         StdMeshers_QuadToTriaAdaptor* q2t = new StdMeshers_QuadToTriaAdaptor;
3347         q2t->Compute( theMesh, expBox.Current(), proxyMesh.get() );
3348         components.push_back( SMESH_ProxyMesh::Ptr( q2t ));
3349       }
3350       proxyMesh.reset( new SMESH_ProxyMesh( components ));
3351     }
3352     // build viscous layers
3353     else if ( _viscousLayersHyp )
3354     {
3355       proxyMesh = _viscousLayersHyp->Compute( theMesh, theShape );
3356       if ( !proxyMesh )
3357         return false;
3358     }
3359
3360     Ok = (writePoints( aPointsFile, helper, 
3361                        aSmdsToGhs3dIdMap, anEnforcedNodeIdToGhs3dIdMap, aGhs3dIdToNodeMap, 
3362                        nodeIDToSizeMap,
3363                        coordsSizeMap, enforcedNodes, enforcedEdges, enforcedTriangles)
3364           &&
3365           writeFaces ( aFacesFile, *proxyMesh, theShape, 
3366                        aSmdsToGhs3dIdMap, anEnforcedNodeIdToGhs3dIdMap,
3367                        enforcedEdges, enforcedTriangles ));
3368 //     Ok = writeGMFFile(aGMFFileName.ToCString(), aRequiredVerticesFileName.ToCString(), aSolFileName.ToCString(),
3369 //                       helper, *proxyMesh,
3370 //                       aNodeId2NodeIndexMap, aSmdsToGhs3dIdMap, aGhs3dIdToNodeMap,
3371 //                       enforcedNodes, enforcedEdges, enforcedTriangles, /*enforcedQuadrangles,*/
3372 //                       coordsSizeMap);
3373   }
3374
3375   // Write aSmdsToGhs3dIdMap to temp file
3376   TCollection_AsciiString aSmdsToGhs3dIdMapFileName;
3377   aSmdsToGhs3dIdMapFileName = aGenericName + ".ids";  // ids relation
3378   ofstream aIdsFile  ( aSmdsToGhs3dIdMapFileName.ToCString()  , ios::out);
3379   Ok = aIdsFile.rdbuf()->is_open();
3380   if (!Ok) {
3381     INFOS( "Can't write into " << aSmdsToGhs3dIdMapFileName);
3382     return error(SMESH_Comment("Can't write into ") << aSmdsToGhs3dIdMapFileName);
3383   }
3384   INFOS( "Writing ids relation into " << aSmdsToGhs3dIdMapFileName);
3385   aIdsFile << "Smds Ghs3d" << std::endl;
3386   map <int,int>::const_iterator myit;
3387   for (myit=aSmdsToGhs3dIdMap.begin() ; myit != aSmdsToGhs3dIdMap.end() ; ++myit) {
3388     aIdsFile << myit->first << " " << myit->second << std::endl;
3389   }
3390
3391   aIdsFile.close();
3392   aFacesFile.close();
3393   aPointsFile.close();
3394   
3395   if ( ! Ok ) {
3396     if ( !_keepFiles ) {
3397 //       removeFile( aGMFFileName );
3398 //       removeFile( aRequiredVerticesFileName );
3399 //       removeFile( aSolFileName );
3400       removeFile( aFacesFileName );
3401       removeFile( aPointsFileName );
3402       removeFile( aSmdsToGhs3dIdMapFileName );
3403     }
3404     return error(COMPERR_BAD_INPUT_MESH);
3405   }
3406   removeFile( aResultFileName ); // needed for boundary recovery module usage
3407
3408   // -----------------
3409   // run ghs3d mesher
3410   // -----------------
3411
3412   TCollection_AsciiString cmd( (char*)GHS3DPlugin_Hypothesis::CommandToRun( _hyp ).c_str() );
3413   cmd += TCollection_AsciiString(" -f ") + aGenericName;  // file to read
3414   cmd += TCollection_AsciiString(" 1>" ) + aLogFileName;  // dump into file
3415   // The output .mesh file does not contain yet the subdomain-info (Ghs3D 4.2)
3416 //   cmd += TCollection_AsciiString(" --in ") + aGenericName;
3417 //   cmd += TCollection_AsciiString(" --required_vertices ") + aGenericNameRequired;
3418 //    cmd += TCollection_AsciiString(" --out ") + aResultGMFFileName;
3419 //   cmd += TCollection_AsciiString(" 1>" ) + aLogFileName;  // dump into file
3420
3421   std::cout << std::endl;
3422   std::cout << "Ghs3d execution..." << std::endl;
3423   std::cout << cmd << std::endl;
3424
3425   _compute_canceled = false;
3426
3427   system( cmd.ToCString() ); // run
3428
3429   std::cout << std::endl;
3430   std::cout << "End of Ghs3d execution !" << std::endl;
3431
3432   // --------------
3433   // read a result
3434   // --------------
3435
3436   // Mapping the result file
3437
3438   int fileOpen;
3439   fileOpen = open( aResultFileName.ToCString(), O_RDONLY);
3440   if ( fileOpen < 0 ) {
3441     std::cout << std::endl;
3442     std::cout << "Can't open the " << aResultFileName.ToCString() << " GHS3D output file" << std::endl;
3443     std::cout << "Log: " << aLogFileName << std::endl;
3444     Ok = false;
3445   }
3446   else {
3447     bool toMeshHoles =
3448       _hyp ? _hyp->GetToMeshHoles(true) : GHS3DPlugin_Hypothesis::DefaultMeshHoles();
3449
3450     helper.IsQuadraticSubMesh( theShape );
3451     helper.SetElementsOnShape( false );
3452
3453     Ok = readResultFile( fileOpen,
3454 #ifdef WNT
3455                          aResultFileName.ToCString(),
3456 #endif
3457                          this,
3458                          /*theMesh, */helper, tabShape, tabBox, _nbShape, 
3459                          aGhs3dIdToNodeMap, aNodeId2NodeIndexMap,
3460                          toMeshHoles, 
3461                          nbEnforcedVertices, nbEnforcedNodes, 
3462                          enforcedEdges, enforcedTriangles );
3463                          
3464 //       Ok = readGMFFile(
3465 // #ifndef GMF_HAS_SUBDOMAIN_INFO
3466 //                        fileOpen,
3467 // #endif
3468 //                        aGenericName.ToCString(), theMesh,
3469 //                        _nbShape, tabShape, tabBox, 
3470 //                        aGhs3dIdToNodeMap, toMeshHoles,
3471 //                        nbEnforcedVertices, nbEnforcedNodes);
3472   }
3473
3474
3475
3476
3477   // ---------------------
3478   // remove working files
3479   // ---------------------
3480
3481   if ( Ok )
3482   {
3483     if ( !_keepFiles )
3484       removeFile( aLogFileName );
3485
3486     if ( _hyp && _hyp->GetToMakeGroupsOfDomains() )
3487       error( COMPERR_WARNING, "'toMakeGroupsOfDomains' is ignored since the mesh is on shape" );
3488   }
3489   else if ( OSD_File( aLogFileName ).Size() > 0 )
3490   {
3491     // get problem description from the log file
3492     _Ghs2smdsConvertor conv( aGhs3dIdToNodeMap );
3493     storeErrorDescription( aLogFileName, conv );
3494   }
3495   else
3496   {
3497     // the log file is empty
3498     removeFile( aLogFileName );
3499     INFOS( "GHS3D Error, command '" << cmd.ToCString() << "' failed" );
3500     error(COMPERR_ALGO_FAILED, "ghs3d: command not found" );
3501   }
3502
3503   if ( !_keepFiles ) {
3504     if (! Ok)
3505       if(_compute_canceled)
3506         removeFile( aLogFileName );
3507     removeFile( aFacesFileName );
3508     removeFile( aPointsFileName );
3509     removeFile( aResultFileName );
3510     removeFile( aBadResFileName );
3511     removeFile( aBbResFileName );
3512     removeFile( aSmdsToGhs3dIdMapFileName );
3513   }
3514   std::cout << "<" << aResultFileName.ToCString() << "> GHS3D output file ";
3515   if ( !Ok )
3516     std::cout << "not ";
3517   std::cout << "treated !" << std::endl;
3518   std::cout << std::endl;
3519
3520   _nbShape = 0;    // re-initializing _nbShape for the next Compute() method call
3521   delete [] tabShape;
3522   delete [] tabBox;
3523
3524   return Ok;
3525 }
3526
3527 //=============================================================================
3528 /*!
3529  *Here we are going to use the GHS3D mesher w/o geometry
3530  */
3531 //=============================================================================
3532 bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
3533                                 SMESH_MesherHelper* theHelper)
3534 {
3535   MESSAGE("GHS3DPlugin_GHS3D::Compute()");
3536
3537   //SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
3538   TopoDS_Shape theShape = theHelper->GetSubShape();
3539
3540   // a unique working file name
3541   // to avoid access to the same files by eg different users
3542   _genericName = GHS3DPlugin_Hypothesis::GetFileName(_hyp);
3543   TCollection_AsciiString aGenericName((char*) _genericName.c_str() );
3544   TCollection_AsciiString aGenericNameRequired = aGenericName + "_required";
3545
3546   TCollection_AsciiString aLogFileName    = aGenericName + ".log";    // log
3547   TCollection_AsciiString aResultFileName;
3548   bool Ok;
3549
3550   TCollection_AsciiString aGMFFileName, aRequiredVerticesFileName, aSolFileName;
3551 //#ifdef _DEBUG_
3552   aGMFFileName              = aGenericName + ".mesh"; // GMF mesh file
3553   aResultFileName           = aGenericName + "Vol.mesh"; // GMF mesh file
3554   aRequiredVerticesFileName = aGenericNameRequired + ".mesh"; // GMF required vertices mesh file
3555   aSolFileName              = aGenericNameRequired + ".sol"; // GMF solution file
3556 //#else
3557 //  aGMFFileName    = aGenericName + ".meshb"; // GMF mesh file
3558 //  aResultFileName = aGenericName + "Vol.meshb"; // GMF mesh file
3559 //  aRequiredVerticesFileName    = aGenericNameRequired + ".meshb"; // GMF required vertices mesh file
3560 //  aSolFileName    = aGenericNameRequired + ".solb"; // GMF solution file
3561 //#endif
3562
3563   std::map <int, int> nodeID2nodeIndexMap;
3564   std::map<std::vector<double>, std::string> enfVerticesWithGroup;
3565   GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues coordsSizeMap;
3566   TopoDS_Shape GeomShape;
3567 //   TopAbs_ShapeEnum GeomType;
3568   std::vector<double> coords;
3569   gp_Pnt aPnt;
3570   GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertex* enfVertex;
3571
3572   GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexList enfVertices = GHS3DPlugin_Hypothesis::GetEnforcedVertices(_hyp);
3573   GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexList::const_iterator enfVerIt = enfVertices.begin();
3574
3575   for ( ; enfVerIt != enfVertices.end() ; ++enfVerIt)
3576   {
3577     enfVertex = (*enfVerIt);
3578 //     if (enfVertex->geomEntry.empty() && enfVertex->coords.size()) {
3579     if (enfVertex->coords.size()) {
3580       coordsSizeMap.insert(make_pair(enfVertex->coords,enfVertex->size));
3581       enfVerticesWithGroup.insert(make_pair(enfVertex->coords,enfVertex->groupName));
3582 //       MESSAGE("enfVerticesWithGroup.insert(make_pair(("<<enfVertex->coords[0]<<","<<enfVertex->coords[1]<<","<<enfVertex->coords[2]<<"),\""<<enfVertex->groupName<<"\"))");
3583     }
3584     else {
3585 //     if (!enfVertex->geomEntry.empty()) {
3586       GeomShape = entryToShape(enfVertex->geomEntry);
3587 //       GeomType = GeomShape.ShapeType();
3588
3589 //       if (!enfVertex->isCompound) {
3590 // //       if (GeomType == TopAbs_VERTEX) {
3591 //         coords.clear();
3592 //         aPnt = BRep_Tool::Pnt(TopoDS::Vertex(GeomShape));
3593 //         coords.push_back(aPnt.X());
3594 //         coords.push_back(aPnt.Y());
3595 //         coords.push_back(aPnt.Z());
3596 //         if (coordsSizeMap.find(coords) == coordsSizeMap.end()) {
3597 //           coordsSizeMap.insert(make_pair(coords,enfVertex->size));
3598 //           enfVerticesWithGroup.insert(make_pair(coords,enfVertex->groupName));
3599 //         }
3600 //       }
3601 //
3602 //       // Group Management
3603 //       else {
3604 //       if (GeomType == TopAbs_COMPOUND){
3605         for (TopoDS_Iterator it (GeomShape); it.More(); it.Next()){
3606           coords.clear();
3607           if (it.Value().ShapeType() == TopAbs_VERTEX){
3608             aPnt = BRep_Tool::Pnt(TopoDS::Vertex(it.Value()));
3609             coords.push_back(aPnt.X());
3610             coords.push_back(aPnt.Y());
3611             coords.push_back(aPnt.Z());
3612             if (coordsSizeMap.find(coords) == coordsSizeMap.end()) {
3613               coordsSizeMap.insert(make_pair(coords,enfVertex->size));
3614               enfVerticesWithGroup.insert(make_pair(coords,enfVertex->groupName));
3615 //               MESSAGE("enfVerticesWithGroup.insert(make_pair(("<<coords[0]<<","<<coords[1]<<","<<coords[2]<<"),\""<<enfVertex->groupName<<"\"))");
3616             }
3617           }
3618         }
3619 //       }
3620     }
3621   }
3622
3623 //   const SMDS_MeshNode* enfNode;
3624   GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap enforcedNodes = GHS3DPlugin_Hypothesis::GetEnforcedNodes(_hyp);
3625 //   GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap::const_iterator enfNodeIt = enforcedNodes.begin();
3626 //   for ( ; enfNodeIt != enforcedNodes.end() ; ++enfNodeIt)
3627 //   {
3628 //     enfNode = enfNodeIt->first;
3629 //     coords.clear();
3630 //     coords.push_back(enfNode->X());
3631 //     coords.push_back(enfNode->Y());
3632 //     coords.push_back(enfNode->Z());
3633 //     if (enfVerticesWithGro
3634 //       enfVerticesWithGroup.insert(make_pair(coords,enfNodeIt->second));
3635 //   }
3636
3637
3638   GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap enforcedEdges = GHS3DPlugin_Hypothesis::GetEnforcedEdges(_hyp);
3639   GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap enforcedTriangles = GHS3DPlugin_Hypothesis::GetEnforcedTriangles(_hyp);
3640 //   TIDSortedElemSet enforcedQuadrangles = GHS3DPlugin_Hypothesis::GetEnforcedQuadrangles(_hyp);
3641   GHS3DPlugin_Hypothesis::TID2SizeMap nodeIDToSizeMap = GHS3DPlugin_Hypothesis::GetNodeIDToSizeMap(_hyp);
3642
3643   std::string tmpStr;
3644
3645   int nbEnforcedVertices = coordsSizeMap.size();
3646   int nbEnforcedNodes = enforcedNodes.size();
3647   (nbEnforcedNodes <= 1) ? tmpStr = "node" : tmpStr = "nodes";
3648   std::cout << nbEnforcedNodes << " enforced " << tmpStr << " from hypo" << std::endl;
3649   (nbEnforcedVertices <= 1) ? tmpStr = "vertex" : tmpStr = "vertices";
3650   std::cout << nbEnforcedVertices << " enforced " << tmpStr << " from hypo" << std::endl;
3651
3652   std::vector <const SMDS_MeshNode*> aNodeByGhs3dId, anEnforcedNodeByGhs3dId;
3653   std::map<const SMDS_MeshNode*,int> aNodeToGhs3dIdMap;
3654   std::vector<std::string> aNodeGroupByGhs3dId, anEdgeGroupByGhs3dId, aFaceGroupByGhs3dId;
3655   {
3656     SMESH_ProxyMesh::Ptr proxyMesh( new SMESH_ProxyMesh( theMesh ));
3657     if ( theMesh.NbQuadrangles() > 0 )
3658     {
3659       StdMeshers_QuadToTriaAdaptor* aQuad2Trias = new StdMeshers_QuadToTriaAdaptor;
3660       aQuad2Trias->Compute( theMesh );
3661       proxyMesh.reset( aQuad2Trias );
3662     }
3663
3664     Ok = writeGMFFile(aGMFFileName.ToCString(), aRequiredVerticesFileName.ToCString(), aSolFileName.ToCString(),
3665                       *proxyMesh, &theMesh,
3666                       aNodeByGhs3dId, aNodeToGhs3dIdMap,
3667                       aNodeGroupByGhs3dId, anEdgeGroupByGhs3dId, aFaceGroupByGhs3dId,
3668                       enforcedNodes, enforcedEdges, enforcedTriangles,
3669                       enfVerticesWithGroup, coordsSizeMap);
3670   }
3671
3672   // -----------------
3673   // run ghs3d mesher
3674   // -----------------
3675
3676   TCollection_AsciiString cmd = TCollection_AsciiString((char*)GHS3DPlugin_Hypothesis::CommandToRun( _hyp, false ).c_str());
3677
3678   cmd += TCollection_AsciiString(" --in ") + aGenericName;
3679   if ( nbEnforcedVertices + nbEnforcedNodes)
3680     cmd += TCollection_AsciiString(" --required_vertices ") + aGenericNameRequired;
3681   cmd += TCollection_AsciiString(" --out ") + aResultFileName;
3682   cmd += TCollection_AsciiString(" 1>" ) + aLogFileName;  // dump into file
3683
3684   std::cout << std::endl;
3685   std::cout << "Ghs3d execution..." << std::endl;
3686   std::cout << cmd << std::endl;
3687
3688   _compute_canceled = false;
3689
3690   system( cmd.ToCString() ); // run
3691
3692   std::cout << std::endl;
3693   std::cout << "End of Ghs3d execution !" << std::endl;
3694
3695   // --------------
3696   // read a result
3697   // --------------
3698   GHS3DPlugin_Hypothesis::TSetStrings groupsToRemove = GHS3DPlugin_Hypothesis::GetGroupsToRemove(_hyp);
3699   const bool toMakeGroupsOfDomains = GHS3DPlugin_Hypothesis::GetToMakeGroupsOfDomains( _hyp );
3700
3701   Ok = readGMFFile(aResultFileName.ToCString(),
3702                    this,
3703                    theHelper, theShape, aNodeByGhs3dId, aNodeToGhs3dIdMap,
3704                    aNodeGroupByGhs3dId, anEdgeGroupByGhs3dId, aFaceGroupByGhs3dId,
3705                    groupsToRemove, toMakeGroupsOfDomains);
3706
3707   updateMeshGroups(theHelper->GetMesh(), groupsToRemove);
3708   removeEmptyGroupsOfDomains( theHelper->GetMesh() );
3709
3710   if ( Ok ) {
3711     GHS3DPlugin_Hypothesis* that = (GHS3DPlugin_Hypothesis*)this->_hyp;
3712     if (that)
3713       that->ClearGroupsToRemove();
3714   }
3715   // ---------------------
3716   // remove working files
3717   // ---------------------
3718
3719   if ( Ok )
3720   {
3721     if ( !_keepFiles )
3722       removeFile( aLogFileName );
3723
3724     if ( !toMakeGroupsOfDomains && _hyp && _hyp->GetToMakeGroupsOfDomains() )
3725       error( COMPERR_WARNING, "'toMakeGroupsOfDomains' is ignored since 'toMeshHoles' is OFF." );
3726   }
3727   else if ( OSD_File( aLogFileName ).Size() > 0 )
3728   {
3729     // get problem description from the log file
3730     _Ghs2smdsConvertor conv( aNodeByGhs3dId );
3731     storeErrorDescription( aLogFileName, conv );
3732   }
3733   else {
3734     // the log file is empty
3735     removeFile( aLogFileName );
3736     INFOS( "GHS3D Error, command '" << cmd.ToCString() << "' failed" );
3737     error(COMPERR_ALGO_FAILED, "ghs3d: command not found" );
3738   }
3739
3740   if ( !_keepFiles )
3741   {
3742     if (! Ok)
3743       if(_compute_canceled)
3744         removeFile( aLogFileName );
3745     removeFile( aGMFFileName );
3746     removeFile( aResultFileName );
3747     removeFile( aRequiredVerticesFileName );
3748     removeFile( aSolFileName );
3749   }
3750   return Ok;
3751 }
3752
3753 void GHS3DPlugin_GHS3D::CancelCompute()
3754 {
3755   _compute_canceled = true;
3756 #ifdef WNT
3757 #else
3758   std::string cmd = "ps xo pid,args | grep " + _genericName;
3759   //cmd += " | grep -e \"^ *[0-9]\\+ \\+" + GHS3DPlugin_Hypothesis::GetExeName() + "\"";
3760   cmd += " | awk '{print $1}' | xargs kill -9 > /dev/null 2>&1";
3761   system( cmd.c_str() );
3762 #endif
3763 }
3764
3765 //================================================================================
3766 /*!
3767  * \brief Provide human readable text by error code reported by ghs3d
3768  */
3769 //================================================================================
3770
3771 static string translateError(const int errNum)
3772 {
3773   switch ( errNum ) {
3774   case 0:
3775     return "The surface mesh includes a face of type other than edge, "
3776       "triangle or quadrilateral. This face type is not supported.";
3777   case 1:
3778     return "Not enough memory for the face table.";
3779   case 2:
3780     return "Not enough memory.";
3781   case 3:
3782     return "Not enough memory.";
3783   case 4:
3784     return "Face is ignored.";
3785   case 5:
3786     return "End of file. Some data are missing in the file.";
3787   case 6:
3788     return "Read error on the file. There are wrong data in the file.";
3789   case 7:
3790     return "the metric file is inadequate (dimension other than 3).";
3791   case 8:
3792     return "the metric file is inadequate (values not per vertices).";
3793   case 9:
3794     return "the metric file contains more than one field.";
3795   case 10:
3796     return "the number of values in the \".bb\" (metric file) is incompatible with the expected"
3797       "value of number of mesh vertices in the \".noboite\" file.";
3798   case 12:
3799     return "Too many sub-domains.";
3800   case 13:
3801     return "the number of vertices is negative or null.";
3802   case 14:
3803     return "the number of faces is negative or null.";
3804   case 15:
3805     return "A face has a null vertex.";
3806   case 22:
3807     return "incompatible data.";
3808   case 131:
3809     return "the number of vertices is negative or null.";
3810   case 132:
3811     return "the number of vertices is negative or null (in the \".mesh\" file).";
3812   case 133:
3813     return "the number of faces is negative or null.";
3814   case 1000:
3815     return "A face appears more than once in the input surface mesh.";
3816   case 1001:
3817     return "An edge appears more than once in the input surface mesh.";
3818   case 1002:
3819     return "A face has a vertex negative or null.";
3820   case 1003:
3821     return "NOT ENOUGH MEMORY.";
3822   case 2000:
3823     return "Not enough available memory.";
3824   case 2002:
3825     return "Some initial points cannot be inserted. The surface mesh is probably very bad "
3826       "in terms of quality or the input list of points is wrong.";
3827   case 2003:
3828     return "Some vertices are too close to one another or coincident.";
3829   case 2004:
3830     return "Some vertices are too close to one another or coincident.";
3831   case 2012:
3832     return "A vertex cannot be inserted.";
3833   case 2014:
3834     return "There are at least two points considered as coincident.";
3835   case 2103:
3836     return "Some vertices are too close to one another or coincident.";
3837   case 3000:
3838     return "The surface mesh regeneration step has failed.";
3839   case 3009:
3840     return "Constrained edge cannot be enforced.";
3841   case 3019:
3842     return "Constrained face cannot be enforced.";
3843   case 3029:
3844     return "Missing faces.";
3845   case 3100:
3846     return "No guess to start the definition of the connected component(s).";
3847   case 3101:
3848     return "The surface mesh includes at least one hole. The domain is not well defined.";
3849   case 3102:
3850     return "Impossible to define a component.";
3851   case 3103:
3852     return "The surface edge intersects another surface edge.";
3853   case 3104:
3854     return "The surface edge intersects the surface face.";
3855   case 3105:
3856     return "One boundary point lies within a surface face.";
3857   case 3106:
3858     return "One surface edge intersects a surface face.";
3859   case 3107:
3860     return "One boundary point lies within a surface edge.";
3861   case 3108:
3862     return "Insufficient memory ressources detected due to a bad quality surface mesh leading "
3863       "to too many swaps.";
3864   case 3109:
3865     return "Edge is unique (i.e., bounds a hole in the surface).";
3866   case 3122:
3867     return "Presumably, the surface mesh is not compatible with the domain being processed.";
3868   case 3123:
3869     return "Too many components, too many sub-domain.";
3870   case 3209:
3871     return "The surface mesh includes at least one hole. "
3872       "Therefore there is no domain properly defined.";
3873   case 3300:
3874     return "Statistics.";
3875   case 3400:
3876     return "Statistics.";
3877   case 3500:
3878     return "Warning, it is dramatically tedious to enforce the boundary items.";
3879   case 4000:
3880     return "Not enough memory at this time, nevertheless, the program continues. "
3881       "The expected mesh will be correct but not really as large as required.";
3882   case 4002:
3883     return "see above error code, resulting quality may be poor.";
3884   case 4003:
3885     return "Not enough memory at this time, nevertheless, the program continues (warning).";
3886   case 8000:
3887     return "Unknown face type.";
3888   case 8005:
3889   case 8006:
3890     return "End of file. Some data are missing in the file.";
3891   case 9000:
3892     return "A too small volume element is detected.";
3893   case 9001:
3894     return "There exists at least a null or negative volume element.";
3895   case 9002:
3896     return "There exist null or negative volume elements.";
3897   case 9003:
3898     return "A too small volume element is detected. A face is considered being degenerated.";
3899   case 9100:
3900     return "Some element is suspected to be very bad shaped or wrong.";
3901   case 9102:
3902     return "A too bad quality face is detected. This face is considered degenerated.";
3903   case 9112:
3904     return "A too bad quality face is detected. This face is degenerated.";
3905   case 9122:
3906     return "Presumably, the surface mesh is not compatible with the domain being processed.";
3907   case 9999:
3908     return "Abnormal error occured, contact hotline.";
3909   case 23600:
3910     return "Not enough memory for the face table.";
3911   case 23601:
3912     return "The algorithm cannot run further. "
3913       "The surface mesh is probably very bad in terms of quality.";
3914   case 23602:
3915     return "Bad vertex number.";
3916   }
3917   return "";
3918 }
3919
3920 //================================================================================
3921 /*!
3922  * \brief Retrieve from a string given number of integers
3923  */
3924 //================================================================================
3925
3926 static char* getIds( char* ptr, int nbIds, vector<int>& ids )
3927 {
3928   ids.clear();
3929   ids.reserve( nbIds );
3930   while ( nbIds )
3931   {
3932     while ( !isdigit( *ptr )) ++ptr;
3933     if ( ptr[-1] == '-' ) --ptr;
3934     ids.push_back( strtol( ptr, &ptr, 10 ));
3935     --nbIds;
3936   }
3937   return ptr;
3938 }
3939
3940 //================================================================================
3941 /*!
3942  * \brief Retrieve problem description form a log file
3943  *  \retval bool - always false
3944  */
3945 //================================================================================
3946
3947 bool GHS3DPlugin_GHS3D::storeErrorDescription(const TCollection_AsciiString& logFile,
3948                                               const _Ghs2smdsConvertor &     toSmdsConvertor )
3949 {
3950   if(_compute_canceled)
3951     return error(SMESH_Comment("interruption initiated by user"));
3952   // open file
3953 #ifdef WNT
3954   int file = ::_open (logFile.ToCString(), _O_RDONLY|_O_BINARY);
3955 #else
3956   int file = ::open (logFile.ToCString(), O_RDONLY);
3957 #endif
3958   if ( file < 0 )
3959     return error( SMESH_Comment("See ") << logFile << " for problem description");
3960
3961   // get file size
3962 //   struct stat status;
3963 //   fstat(file, &status);
3964 //   size_t length = status.st_size;
3965   off_t length = lseek( file, 0, SEEK_END);
3966   lseek( file, 0, SEEK_SET);
3967
3968   // read file
3969   vector< char > buf( length );
3970   int nBytesRead = ::read (file, & buf[0], length);
3971   ::close (file);
3972   char* ptr = & buf[0];
3973   char* bufEnd = ptr + nBytesRead;
3974
3975   SMESH_Comment errDescription;
3976
3977   enum { NODE = 1, EDGE, TRIA, VOL, ID = 1 };
3978
3979   // look for errors "ERR #"
3980
3981   set<string> foundErrorStr; // to avoid reporting same error several times
3982   set<int>    elemErrorNums; // not to report different types of errors with bad elements
3983   while ( ++ptr < bufEnd )
3984   {
3985     if ( strncmp( ptr, "ERR ", 4 ) != 0 )
3986       continue;
3987
3988     list<const SMDS_MeshElement*> badElems;
3989     vector<int> nodeIds;
3990
3991     ptr += 4;
3992     char* errBeg = ptr;
3993     int   errNum = strtol(ptr, &ptr, 10);
3994     switch ( errNum ) { // we treat errors enumerated in [SALOME platform 0019316] issue
3995     case 0015:
3996       // The face number (numfac) with vertices (f 1, f 2, f 3) has a null vertex.
3997       ptr = getIds(ptr, NODE, nodeIds);
3998       ptr = getIds(ptr, TRIA, nodeIds);
3999       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4000       break;
4001     case 1000: // ERR  1000 :  1 3 2
4002       // Face (f 1, f 2, f 3) appears more than once in the input surface mesh.
4003       ptr = getIds(ptr, TRIA, nodeIds);
4004       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4005       break;
4006     case 1001:
4007       // Edge (e1, e2) appears more than once in the input surface mesh
4008       ptr = getIds(ptr, EDGE, nodeIds);
4009       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4010       break;
4011     case 1002:
4012       // Face (f 1, f 2, f 3) has a vertex negative or null
4013       ptr = getIds(ptr, TRIA, nodeIds);
4014       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4015       break;
4016     case 2004:
4017       // Vertex v1 and vertex v2 are too close to one another or coincident (warning).
4018       ptr = getIds(ptr, NODE, nodeIds);
4019       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4020       ptr = getIds(ptr, NODE, nodeIds);
4021       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4022       break;
4023     case 2012:
4024       // Vertex v1 cannot be inserted (warning).
4025       ptr = getIds(ptr, NODE, nodeIds);
4026       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4027       break;
4028     case 2014:
4029       // There are at least two points whose distance is dist, i.e., considered as coincident
4030     case 2103: // ERR  2103 :  16 WITH  3
4031       // Vertex v1 and vertex v2 are too close to one another or coincident (warning).
4032       ptr = getIds(ptr, NODE, nodeIds);
4033       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4034       ptr = getIds(ptr, NODE, nodeIds);
4035       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4036       break;
4037     case 3009:
4038       // Constrained edge (e1, e2) cannot be enforced (warning).
4039       ptr = getIds(ptr, EDGE, nodeIds);
4040       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4041       break;
4042     case 3019:
4043       // Constrained face (f 1, f 2, f 3) cannot be enforced
4044       ptr = getIds(ptr, TRIA, nodeIds);
4045       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4046       break;
4047     case 3103: // ERR  3103 :  1 2 WITH  7 3
4048       // The surface edge (e1, e2) intersects another surface edge (e3, e4)
4049       ptr = getIds(ptr, EDGE, nodeIds);
4050       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4051       ptr = getIds(ptr, EDGE, nodeIds);
4052       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4053       break;
4054     case 3104: // ERR  3104 :  9 10 WITH  1 2 3
4055       // The surface edge (e1, e2) intersects the surface face (f 1, f 2, f 3)
4056       ptr = getIds(ptr, EDGE, nodeIds);
4057       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4058       ptr = getIds(ptr, TRIA, nodeIds);
4059       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4060       break;
4061     case 3105: // ERR  3105 :  8 IN  2 3 5
4062       // One boundary point (say p1) lies within a surface face (f 1, f 2, f 3)
4063       ptr = getIds(ptr, NODE, nodeIds);
4064       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4065       ptr = getIds(ptr, TRIA, nodeIds);
4066       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4067       break;
4068     case 3106:
4069       // One surface edge (say e1, e2) intersects a surface face (f 1, f 2, f 3)
4070       ptr = getIds(ptr, EDGE, nodeIds);
4071       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4072       ptr = getIds(ptr, TRIA, nodeIds);
4073       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4074       break;
4075     case 3107: // ERR  3107 :  2 IN  4 1
4076       // One boundary point (say p1) lies within a surface edge (e1, e2) (stop).
4077       ptr = getIds(ptr, NODE, nodeIds);
4078       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4079       ptr = getIds(ptr, EDGE, nodeIds);
4080       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4081       break;
4082     case 3109: // ERR  3109 :  EDGE  5 6 UNIQUE
4083       // Edge (e1, e2) is unique (i.e., bounds a hole in the surface)
4084       ptr = getIds(ptr, EDGE, nodeIds);
4085       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4086       break;
4087     case 9000: // ERR  9000
4088       //  ELEMENT  261 WITH VERTICES :  7 396 -8 242
4089       //  VOLUME   : -1.11325045E+11 W.R.T. EPSILON   0.
4090       // A too small volume element is detected. Are reported the index of the element,
4091       // its four vertex indices, its volume and the tolerance threshold value
4092       ptr = getIds(ptr, ID, nodeIds);
4093       ptr = getIds(ptr, VOL, nodeIds);
4094       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4095       // even if all nodes found, volume it most probably invisible,
4096       // add its faces to demenstrate it anyhow
4097       {
4098         vector<int> faceNodes( nodeIds.begin(), --nodeIds.end() ); // 012
4099         badElems.push_back( toSmdsConvertor.getElement(faceNodes));
4100         faceNodes[2] = nodeIds[3]; // 013
4101         badElems.push_back( toSmdsConvertor.getElement(faceNodes));
4102         faceNodes[1] = nodeIds[2]; // 023
4103         badElems.push_back( toSmdsConvertor.getElement(faceNodes));
4104         faceNodes[0] = nodeIds[1]; // 123
4105         badElems.push_back( toSmdsConvertor.getElement(faceNodes));
4106       }
4107       break;
4108     case 9001: // ERR  9001
4109       //  %% NUMBER OF NEGATIVE VOLUME TETS  :  1
4110       //  %% THE LARGEST NEGATIVE TET        :   1.75376581E+11
4111       //  %%  NUMBER OF NULL VOLUME TETS     :  0
4112       // There exists at least a null or negative volume element
4113       break;
4114     case 9002:
4115       // There exist n null or negative volume elements
4116       break;
4117     case 9003:
4118       // A too small volume element is detected
4119       break;
4120     case 9102:
4121       // A too bad quality face is detected. This face is considered degenerated,
4122       // its index, its three vertex indices together with its quality value are reported
4123       break; // same as next
4124     case 9112: // ERR  9112
4125       //  FACE   2 WITH VERTICES :  4 2 5
4126       //  SMALL INRADIUS :   0.
4127       // A too bad quality face is detected. This face is degenerated,
4128       // its index, its three vertex indices together with its inradius are reported
4129       ptr = getIds(ptr, ID, nodeIds);
4130       ptr = getIds(ptr, TRIA, nodeIds);
4131       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4132       // add triangle edges as it most probably has zero area and hence invisible
4133       {
4134         vector<int> edgeNodes(2);
4135         edgeNodes[0] = nodeIds[0]; edgeNodes[1] = nodeIds[1]; // 0-1
4136         badElems.push_back( toSmdsConvertor.getElement(edgeNodes));
4137         edgeNodes[1] = nodeIds[2]; // 0-2
4138         badElems.push_back( toSmdsConvertor.getElement(edgeNodes));
4139         edgeNodes[0] = nodeIds[1]; // 1-2
4140         badElems.push_back( toSmdsConvertor.getElement(edgeNodes));
4141       }
4142       break;
4143     }
4144
4145     bool isNewError = foundErrorStr.insert( string( errBeg, ptr )).second;
4146     if ( !isNewError )
4147       continue; // not to report same error several times
4148
4149 //     const SMDS_MeshElement* nullElem = 0;
4150 //     bool allElemsOk = ( find( badElems.begin(), badElems.end(), nullElem) == badElems.end());
4151
4152 //     if ( allElemsOk && !badElems.empty() && !elemErrorNums.empty() ) {
4153 //       bool oneMoreErrorType = elemErrorNums.insert( errNum ).second;
4154 //       if ( oneMoreErrorType )
4155 //         continue; // not to report different types of errors with bad elements
4156 //     }
4157
4158     // store bad elements
4159     //if ( allElemsOk ) {
4160       list<const SMDS_MeshElement*>::iterator elem = badElems.begin();
4161       for ( ; elem != badElems.end(); ++elem )
4162         addBadInputElement( *elem );
4163       //}
4164
4165     // make error text
4166     string text = translateError( errNum );
4167     if ( errDescription.find( text ) == text.npos ) {
4168       if ( !errDescription.empty() )
4169         errDescription << "\n";
4170       errDescription << text;
4171     }
4172
4173   } // end while
4174
4175   if ( errDescription.empty() ) { // no errors found
4176     char msgLic1[] = "connection to server failed";
4177     char msgLic2[] = " Dlim ";
4178     if ( search( &buf[0], bufEnd, msgLic1, msgLic1 + strlen(msgLic1)) != bufEnd ||
4179          search( &buf[0], bufEnd, msgLic2, msgLic2 + strlen(msgLic2)) != bufEnd )
4180       errDescription << "Licence problems.";
4181     else
4182     {
4183       char msg2[] = "SEGMENTATION FAULT";
4184       if ( search( &buf[0], bufEnd, msg2, msg2 + strlen(msg2)) != bufEnd )
4185         errDescription << "ghs3d: SEGMENTATION FAULT. ";
4186     }
4187   }
4188
4189   if ( errDescription.empty() )
4190     errDescription << "See " << logFile << " for problem description";
4191   else
4192     errDescription << "\nSee " << logFile << " for more information";
4193
4194   return error( errDescription );
4195 }
4196
4197 //================================================================================
4198 /*!
4199  * \brief Creates _Ghs2smdsConvertor
4200  */
4201 //================================================================================
4202
4203 _Ghs2smdsConvertor::_Ghs2smdsConvertor( const map <int,const SMDS_MeshNode*> & ghs2NodeMap)
4204   :_ghs2NodeMap( & ghs2NodeMap ), _nodeByGhsId( 0 )
4205 {
4206 }
4207
4208 //================================================================================
4209 /*!
4210  * \brief Creates _Ghs2smdsConvertor
4211  */
4212 //================================================================================
4213
4214 _Ghs2smdsConvertor::_Ghs2smdsConvertor( const vector <const SMDS_MeshNode*> &  nodeByGhsId)
4215   : _ghs2NodeMap( 0 ), _nodeByGhsId( &nodeByGhsId )
4216 {
4217 }
4218
4219 //================================================================================
4220 /*!
4221  * \brief Return SMDS element by ids of GHS3D nodes
4222  */
4223 //================================================================================
4224
4225 const SMDS_MeshElement* _Ghs2smdsConvertor::getElement(const vector<int>& ghsNodes) const
4226 {
4227   size_t nbNodes = ghsNodes.size();
4228   vector<const SMDS_MeshNode*> nodes( nbNodes, 0 );
4229   for ( size_t i = 0; i < nbNodes; ++i ) {
4230     int ghsNode = ghsNodes[ i ];
4231     if ( _ghs2NodeMap ) {
4232       map <int,const SMDS_MeshNode*>::const_iterator in = _ghs2NodeMap->find( ghsNode);
4233       if ( in == _ghs2NodeMap->end() )
4234         return 0;
4235       nodes[ i ] = in->second;
4236     }
4237     else {
4238       if ( ghsNode < 1 || ghsNode > _nodeByGhsId->size() )
4239         return 0;
4240       nodes[ i ] = (*_nodeByGhsId)[ ghsNode-1 ];
4241     }
4242   }
4243   if ( nbNodes == 1 )
4244     return nodes[0];
4245
4246   if ( nbNodes == 2 ) {
4247     const SMDS_MeshElement* edge= SMDS_Mesh::FindEdge( nodes[0], nodes[1] );
4248     if ( !edge )
4249       edge = new SMDS_LinearEdge( nodes[0], nodes[1] );
4250     return edge;
4251   }
4252   if ( nbNodes == 3 ) {
4253     const SMDS_MeshElement* face = SMDS_Mesh::FindFace( nodes );
4254     if ( !face )
4255       face = new SMDS_FaceOfNodes( nodes[0], nodes[1], nodes[2] );
4256     return face;
4257   }
4258   if ( nbNodes == 4 )
4259     return new SMDS_VolumeOfNodes( nodes[0], nodes[1], nodes[2], nodes[3] );
4260
4261   return 0;
4262 }
4263
4264
4265 //=============================================================================
4266 /*!
4267  *
4268  */
4269 //=============================================================================
4270 bool GHS3DPlugin_GHS3D::Evaluate(SMESH_Mesh& aMesh,
4271                                  const TopoDS_Shape& aShape,
4272                                  MapShapeNbElems& aResMap)
4273 {
4274   int nbtri = 0, nbqua = 0;
4275   double fullArea = 0.0;
4276   for (TopExp_Explorer exp(aShape, TopAbs_FACE); exp.More(); exp.Next()) {
4277     TopoDS_Face F = TopoDS::Face( exp.Current() );
4278     SMESH_subMesh *sm = aMesh.GetSubMesh(F);
4279     MapShapeNbElemsItr anIt = aResMap.find(sm);
4280     if( anIt==aResMap.end() ) {
4281       SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
4282       smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,
4283                                             "Submesh can not be evaluated",this));
4284       return false;
4285     }
4286     std::vector<int> aVec = (*anIt).second;
4287     nbtri += Max(aVec[SMDSEntity_Triangle],aVec[SMDSEntity_Quad_Triangle]);
4288     nbqua += Max(aVec[SMDSEntity_Quadrangle],aVec[SMDSEntity_Quad_Quadrangle]);
4289     GProp_GProps G;
4290     BRepGProp::SurfaceProperties(F,G);
4291     double anArea = G.Mass();
4292     fullArea += anArea;
4293   }
4294
4295   // collect info from edges
4296   int nb0d_e = 0, nb1d_e = 0;
4297   bool IsQuadratic = false;
4298   bool IsFirst = true;
4299   TopTools_MapOfShape tmpMap;
4300   for (TopExp_Explorer exp(aShape, TopAbs_EDGE); exp.More(); exp.Next()) {
4301     TopoDS_Edge E = TopoDS::Edge(exp.Current());
4302     if( tmpMap.Contains(E) )
4303       continue;
4304     tmpMap.Add(E);
4305     SMESH_subMesh *aSubMesh = aMesh.GetSubMesh(exp.Current());
4306     MapShapeNbElemsItr anIt = aResMap.find(aSubMesh);
4307     std::vector<int> aVec = (*anIt).second;
4308     nb0d_e += aVec[SMDSEntity_Node];
4309     nb1d_e += Max(aVec[SMDSEntity_Edge],aVec[SMDSEntity_Quad_Edge]);
4310     if(IsFirst) {
4311       IsQuadratic = (aVec[SMDSEntity_Quad_Edge] > aVec[SMDSEntity_Edge]);
4312       IsFirst = false;
4313     }
4314   }
4315   tmpMap.Clear();
4316
4317   double ELen = sqrt(2.* ( fullArea/(nbtri+nbqua*2) ) / sqrt(3.0) );
4318
4319   GProp_GProps G;
4320   BRepGProp::VolumeProperties(aShape,G);
4321   double aVolume = G.Mass();
4322   double tetrVol = 0.1179*ELen*ELen*ELen;
4323   double CoeffQuality = 0.9;
4324   int nbVols = int(aVolume/tetrVol/CoeffQuality);
4325   int nb1d_f = (nbtri*3 + nbqua*4 - nb1d_e) / 2;
4326   int nb1d_in = (int) ( nbVols*6 - nb1d_e - nb1d_f ) / 5;
4327   std::vector<int> aVec(SMDSEntity_Last);
4328   for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aVec[i]=0;
4329   if( IsQuadratic ) {
4330     aVec[SMDSEntity_Node] = nb1d_in/6 + 1 + nb1d_in;
4331     aVec[SMDSEntity_Quad_Tetra] = nbVols - nbqua*2;
4332     aVec[SMDSEntity_Quad_Pyramid] = nbqua;
4333   }
4334   else {
4335     aVec[SMDSEntity_Node] = nb1d_in/6 + 1;
4336     aVec[SMDSEntity_Tetra] = nbVols - nbqua*2;
4337     aVec[SMDSEntity_Pyramid] = nbqua;
4338   }
4339   SMESH_subMesh *sm = aMesh.GetSubMesh(aShape);
4340   aResMap.insert(std::make_pair(sm,aVec));
4341
4342   return true;
4343 }
4344
4345 bool GHS3DPlugin_GHS3D::importGMFMesh(const char* theGMFFileName, SMESH_Mesh& theMesh)
4346 {
4347   SMESH_MesherHelper* helper  = new SMESH_MesherHelper(theMesh );
4348 //   TopoDS_Shape theShape = theMesh.GetShapeToMesh();
4349   std::vector <const SMDS_MeshNode*> dummyNodeVector;
4350   std::map<const SMDS_MeshNode*,int> dummyNodeMap;
4351   std::map<std::vector<double>, std::string> dummyEnfVertGroup;
4352   std::vector<std::string> dummyElemGroup;
4353   std::set<std::string> dummyGroupsToRemove;
4354
4355   bool ok = readGMFFile(theGMFFileName,
4356                         this,
4357                         helper, theMesh.GetShapeToMesh(), dummyNodeVector, dummyNodeMap, dummyElemGroup, dummyElemGroup, dummyElemGroup, dummyGroupsToRemove);
4358   theMesh.GetMeshDS()->Modified();
4359   return ok;
4360 }
4361
4362 namespace
4363 {
4364   //================================================================================
4365   /*!
4366    * \brief Sub-mesh event listener setting enforced elements as soon as an enforced
4367    *        mesh is loaded
4368    */
4369   struct _EnforcedMeshRestorer : public SMESH_subMeshEventListener
4370   {
4371     _EnforcedMeshRestorer():
4372       SMESH_subMeshEventListener( /*isDeletable = */true, Name() )
4373     {}
4374
4375     //================================================================================
4376     /*!
4377      * \brief Returns an ID of listener
4378      */
4379     static const char* Name() { return "GHS3DPlugin_GHS3D::_EnforcedMeshRestorer"; }
4380
4381     //================================================================================
4382     /*!
4383      * \brief Treat events of the subMesh
4384      */
4385     void ProcessEvent(const int                       event,
4386                       const int                       eventType,
4387                       SMESH_subMesh*                  subMesh,
4388                       SMESH_subMeshEventListenerData* data,
4389                       const SMESH_Hypothesis*         hyp)
4390     {
4391       if ( SMESH_subMesh::SUBMESH_LOADED == event &&
4392            SMESH_subMesh::COMPUTE_EVENT  == eventType &&
4393            data &&
4394            !data->mySubMeshes.empty() )
4395       {
4396         // An enforced mesh (subMesh->_father) has been loaded from hdf file
4397         if ( GHS3DPlugin_Hypothesis* hyp = GetGHSHypothesis( data->mySubMeshes.front() ))
4398           hyp->RestoreEnfElemsByMeshes();
4399       }
4400     }
4401     //================================================================================
4402     /*!
4403      * \brief Returns GHS3DPlugin_Hypothesis used to compute a subMesh
4404      */
4405     static GHS3DPlugin_Hypothesis* GetGHSHypothesis( SMESH_subMesh* subMesh )
4406     {
4407       SMESH_HypoFilter ghsHypFilter( SMESH_HypoFilter::HasName( "GHS3D_Parameters" ));
4408       return (GHS3DPlugin_Hypothesis* )
4409         subMesh->GetFather()->GetHypothesis( subMesh->GetSubShape(),
4410                                              ghsHypFilter,
4411                                              /*visitAncestors=*/true);
4412     }
4413   };
4414
4415   //================================================================================
4416   /*!
4417    * \brief Sub-mesh event listener removing empty groups created due to "To make
4418    *        groups of domains".
4419    */
4420   struct _GroupsOfDomainsRemover : public SMESH_subMeshEventListener
4421   {
4422     _GroupsOfDomainsRemover():
4423       SMESH_subMeshEventListener( /*isDeletable = */true,
4424                                   "GHS3DPlugin_GHS3D::_GroupsOfDomainsRemover" ) {}
4425     /*!
4426      * \brief Treat events of the subMesh
4427      */
4428     void ProcessEvent(const int                       event,
4429                       const int                       eventType,
4430                       SMESH_subMesh*                  subMesh,
4431                       SMESH_subMeshEventListenerData* data,
4432                       const SMESH_Hypothesis*         hyp)
4433     {
4434       if (SMESH_subMesh::ALGO_EVENT == eventType &&
4435           !subMesh->GetAlgo() )
4436       {
4437         removeEmptyGroupsOfDomains( subMesh->GetFather(), /*notEmptyAsWell=*/true );
4438       }
4439     }
4440   };
4441 }
4442
4443 //================================================================================
4444 /*!
4445  * \brief Set an event listener to set enforced elements as soon as an enforced
4446  *        mesh is loaded
4447  */
4448 //================================================================================
4449
4450 void GHS3DPlugin_GHS3D::SubmeshRestored(SMESH_subMesh* subMesh)
4451 {
4452   if ( GHS3DPlugin_Hypothesis* hyp = _EnforcedMeshRestorer::GetGHSHypothesis( subMesh ))
4453   {
4454     GHS3DPlugin_Hypothesis::TGHS3DEnforcedMeshList enfMeshes = hyp->_GetEnforcedMeshes();
4455     GHS3DPlugin_Hypothesis::TGHS3DEnforcedMeshList::iterator it = enfMeshes.begin();
4456     for(;it != enfMeshes.end();++it) {
4457       GHS3DPlugin_Hypothesis::TGHS3DEnforcedMesh* enfMesh = *it;
4458       if ( SMESH_Mesh* mesh = GetMeshByPersistentID( enfMesh->persistID ))
4459       {
4460         SMESH_subMesh* smToListen = mesh->GetSubMesh( mesh->GetShapeToMesh() );
4461         // a listener set to smToListen will care of hypothesis stored in SMESH_EventListenerData
4462         subMesh->SetEventListener( new _EnforcedMeshRestorer(),
4463                                    SMESH_subMeshEventListenerData::MakeData( subMesh ),
4464                                    smToListen);
4465       }
4466     }
4467   }
4468 }
4469
4470 //================================================================================
4471 /*!
4472  * \brief Sets an event listener removing empty groups created due to "To make
4473  *        groups of domains".
4474  * \param subMesh - submesh where algo is set
4475  *
4476  * This method is called when a submesh gets HYP_OK algo_state.
4477  * After being set, event listener is notified on each event of a submesh.
4478  */
4479 //================================================================================
4480
4481 void GHS3DPlugin_GHS3D::SetEventListener(SMESH_subMesh* subMesh)
4482 {
4483   subMesh->SetEventListener( new _GroupsOfDomainsRemover(), 0, subMesh );
4484 }