]> SALOME platform Git repositories - plugins/hybridplugin.git/blob - src/GHS3DPlugin/GHS3DPlugin_GHS3D.cxx
Salome HOME
0022098: EDF 2036 SMESH: Create groups from none conected parts of a mesh
[plugins/hybridplugin.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 void removeFile( const TCollection_AsciiString& fileName )
116 {
117   try {
118     OSD_File( fileName ).Remove();
119   }
120   catch ( Standard_ProgramError ) {
121     MESSAGE("Can't remove file: " << fileName.ToCString() << " ; file does not exist or permission denied");
122   }
123 }
124
125 //=============================================================================
126 /*!
127  *  
128  */
129 //=============================================================================
130
131 GHS3DPlugin_GHS3D::GHS3DPlugin_GHS3D(int hypId, int studyId, SMESH_Gen* gen)
132   : SMESH_3D_Algo(hypId, studyId, gen)
133 {
134   MESSAGE("GHS3DPlugin_GHS3D::GHS3DPlugin_GHS3D");
135   _name = "GHS3D_3D";
136   _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);// 1 bit /shape type
137   _onlyUnaryInput = false; // Compute() will be called on a compound of solids
138   _iShape=0;
139   _nbShape=0;
140   _compatibleHypothesis.push_back( GHS3DPlugin_Hypothesis::GetHypType());
141   _compatibleHypothesis.push_back( StdMeshers_ViscousLayers::GetHypType() );
142   _requireShape = false; // can work without shape_studyId
143
144   smeshGen_i = SMESH_Gen_i::GetSMESHGen();
145   CORBA::Object_var anObject = smeshGen_i->GetNS()->Resolve("/myStudyManager");
146   SALOMEDS::StudyManager_var aStudyMgr = SALOMEDS::StudyManager::_narrow(anObject);
147
148   MESSAGE("studyid = " << _studyId);
149
150   myStudy = NULL;
151   myStudy = aStudyMgr->GetStudyByID(_studyId);
152   if (myStudy)
153     MESSAGE("myStudy->StudyId() = " << myStudy->StudyId());
154   
155 #ifdef WITH_SMESH_CANCEL_COMPUTE
156   _compute_canceled = false;
157 #endif
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 : readGMFFile
1060 //purpose  : read GMF file w/o geometry associated to mesh
1061 //=======================================================================
1062
1063 static bool readGMFFile(const char*                     theFile,
1064 #ifdef WITH_SMESH_CANCEL_COMPUTE
1065                         GHS3DPlugin_GHS3D*              theAlgo,
1066 #endif 
1067                         SMESH_MesherHelper*             theHelper,
1068                         TopoDS_Shape                    theSolid,
1069                         vector <const SMDS_MeshNode*> & theNodeByGhs3dId,
1070                         map<const SMDS_MeshNode*,int> & theNodeToGhs3dIdMap,
1071                         std::vector<std::string> &      aNodeGroupByGhs3dId,
1072                         std::vector<std::string> &      anEdgeGroupByGhs3dId,
1073                         std::vector<std::string> &      aFaceGroupByGhs3dId,
1074                         std::set<std::string> &         groupsToRemove
1075                        )
1076 {
1077   std::string tmpStr;
1078   SMESHDS_Mesh* theMeshDS = theHelper->GetMeshDS();
1079
1080   int nbInitialNodes = theNodeByGhs3dId.size();
1081   int nbMeshNodes = theMeshDS->NbNodes();
1082   
1083   const bool isQuadMesh = 
1084     theHelper->GetMesh()->NbEdges( ORDER_QUADRATIC ) ||
1085     theHelper->GetMesh()->NbFaces( ORDER_QUADRATIC ) ||
1086     theHelper->GetMesh()->NbVolumes( ORDER_QUADRATIC );
1087     
1088 #ifdef _DEBUG_
1089   std::cout << "theNodeByGhs3dId.size(): " << nbInitialNodes << std::endl;
1090   std::cout << "theHelper->GetMesh()->NbNodes(): " << nbMeshNodes << std::endl;
1091   std::cout << "isQuadMesh: " << isQuadMesh << std::endl;
1092 #endif
1093   
1094   if (theHelper->GetSubShapeID() != 0)
1095     theHelper->IsQuadraticSubMesh( theHelper->GetSubShape() );
1096
1097   // ---------------------------------
1098   // Read generated elements and nodes
1099   // ---------------------------------
1100
1101   int nbElem = 0, nbRef = 0;
1102   int aGMFNodeID = 0/*, shapeID*/;
1103   //int *nodeAssigne;
1104   const SMDS_MeshNode** GMFNode;
1105 #ifdef _DEBUG_
1106   std::map<int, std::set<int> > subdomainId2tetraId;
1107 #endif
1108   std::map <GmfKwdCod,int> tabRef;
1109
1110   tabRef[GmfVertices]       = 3; // for new nodes and enforced nodes
1111   tabRef[GmfCorners]        = 1;
1112   tabRef[GmfEdges]          = 2; // for enforced edges
1113   tabRef[GmfRidges]         = 1;
1114   tabRef[GmfTriangles]      = 3; // for enforced faces
1115   tabRef[GmfQuadrilaterals] = 4;
1116   tabRef[GmfTetrahedra]     = 4; // for new tetras
1117   tabRef[GmfHexahedra]      = 8;
1118
1119   int ver, dim;
1120   MESSAGE("Read " << theFile << " file");
1121   int InpMsh = GmfOpenMesh(theFile, GmfRead, &ver, &dim);
1122   if (!InpMsh)
1123     return false;
1124   MESSAGE("Done ");
1125
1126   // Issue 0020682. Avoid creating nodes and tetras at place where
1127   // volumic elements already exist
1128   SMESH_ElementSearcher* elemSearcher = 0;
1129   vector< const SMDS_MeshElement* > foundVolumes;
1130   if ( theHelper->GetMesh()->NbVolumes() > 0 )
1131     elemSearcher = SMESH_MeshAlgos::GetElementSearcher( *theHelper->GetMeshDS() );
1132
1133   int nbVertices = GmfStatKwd(InpMsh, GmfVertices) - nbInitialNodes;
1134   GMFNode = new const SMDS_MeshNode*[ nbVertices + 1 ];
1135   //nodeAssigne = new int[ nbVertices + 1 ];
1136
1137   std::map <GmfKwdCod,int>::const_iterator it = tabRef.begin();
1138   for ( ; it != tabRef.end() ; ++it)
1139   {
1140 #ifdef WITH_SMESH_CANCEL_COMPUTE
1141     if(theAlgo->computeCanceled()) {
1142       GmfCloseMesh(InpMsh);
1143       delete [] GMFNode;
1144       //delete [] nodeAssigne;
1145       return false;
1146     }
1147 #endif
1148     int dummy;
1149     GmfKwdCod token = it->first;
1150     nbRef    = it->second;
1151
1152     nbElem = GmfStatKwd(InpMsh, token);
1153     if (nbElem > 0) {
1154       GmfGotoKwd(InpMsh, token);
1155       std::cout << "Read " << nbElem;
1156     }
1157     else
1158       continue;
1159
1160     std::vector<int> id (nbElem*tabRef[token]); // node ids
1161
1162     if (token == GmfVertices) {
1163       (nbElem <= 1) ? tmpStr = " vertex" : tmpStr = " vertices";
1164 //       std::cout << nbInitialNodes << " from input mesh " << std::endl;
1165
1166       // Remove orphan nodes from previous enforced mesh which was cleared
1167 //       if ( nbElem < nbMeshNodes ) {
1168 //         const SMDS_MeshNode* node;
1169 //         SMDS_NodeIteratorPtr nodeIt = theMeshDS->nodesIterator();
1170 //         while ( nodeIt->more() )
1171 //         {
1172 //           node = nodeIt->next();
1173 //           if (theNodeToGhs3dIdMap.find(node) != theNodeToGhs3dIdMap.end())
1174 //             theMeshDS->RemoveNode(node);
1175 //         }
1176 //       }
1177
1178       
1179       int aGMFID;
1180
1181       float VerTab_f[3];
1182       double x, y, z;
1183       const SMDS_MeshNode * aGMFNode;
1184
1185       //shapeID = theMeshDS->ShapeToIndex( theSolid );
1186       for ( int iElem = 0; iElem < nbElem; iElem++ ) {
1187 #ifdef WITH_SMESH_CANCEL_COMPUTE
1188         if(theAlgo->computeCanceled()) {
1189           GmfCloseMesh(InpMsh);
1190           delete [] GMFNode;
1191           //delete [] nodeAssigne;
1192           return false;
1193         }
1194 #endif
1195         if (ver == GmfFloat) {
1196           GmfGetLin(InpMsh, token, &VerTab_f[0], &VerTab_f[1], &VerTab_f[2], &dummy);
1197           x = VerTab_f[0];
1198           y = VerTab_f[1];
1199           z = VerTab_f[2];
1200         }
1201         else {
1202           GmfGetLin(InpMsh, token, &x, &y, &z, &dummy);
1203         }
1204         if (iElem >= nbInitialNodes) {
1205           if ( elemSearcher &&
1206                 elemSearcher->FindElementsByPoint( gp_Pnt(x,y,z), SMDSAbs_Volume, foundVolumes))
1207             aGMFNode = 0;
1208           else
1209             aGMFNode = theHelper->AddNode(x, y, z);
1210           
1211           aGMFID = iElem -nbInitialNodes +1;
1212           GMFNode[ aGMFID ] = aGMFNode;
1213           //nodeAssigne[ aGMFID ] = 0;
1214           if (aGMFID-1 < aNodeGroupByGhs3dId.size() && !aNodeGroupByGhs3dId.at(aGMFID-1).empty())
1215             addElemInMeshGroup(theHelper->GetMesh(), aGMFNode, aNodeGroupByGhs3dId.at(aGMFID-1), groupsToRemove);
1216         }
1217       }
1218     }
1219     else if (token == GmfCorners && nbElem > 0) {
1220       (nbElem <= 1) ? tmpStr = " corner" : tmpStr = " corners";
1221       for ( int iElem = 0; iElem < nbElem; iElem++ )
1222         GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]]);
1223     }
1224     else if (token == GmfRidges && nbElem > 0) {
1225       (nbElem <= 1) ? tmpStr = " ridge" : tmpStr = " ridges";
1226       for ( int iElem = 0; iElem < nbElem; iElem++ )
1227         GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]]);
1228     }
1229     else if (token == GmfEdges && nbElem > 0) {
1230       (nbElem <= 1) ? tmpStr = " edge" : tmpStr = " edges";
1231       for ( int iElem = 0; iElem < nbElem; iElem++ )
1232         GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &dummy);
1233     }
1234     else if (token == GmfTriangles && nbElem > 0) {
1235       (nbElem <= 1) ? tmpStr = " triangle" : tmpStr = " triangles";
1236       for ( int iElem = 0; iElem < nbElem; iElem++ )
1237         GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &id[iElem*tabRef[token]+2], &dummy);
1238     }
1239     else if (token == GmfQuadrilaterals && nbElem > 0) {
1240       (nbElem <= 1) ? tmpStr = " Quadrilateral" : tmpStr = " Quadrilaterals";
1241       for ( int iElem = 0; iElem < nbElem; iElem++ )
1242         GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &id[iElem*tabRef[token]+2], &id[iElem*tabRef[token]+3], &dummy);
1243     }
1244     else if (token == GmfTetrahedra && nbElem > 0) {
1245       (nbElem <= 1) ? tmpStr = " Tetrahedron" : tmpStr = " Tetrahedra";
1246       for ( int iElem = 0; iElem < nbElem; iElem++ ) {
1247         GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &id[iElem*tabRef[token]+2], &id[iElem*tabRef[token]+3], &dummy);
1248 #ifdef _DEBUG_
1249         subdomainId2tetraId[dummy].insert(iElem+1);
1250 //         MESSAGE("subdomainId2tetraId["<<dummy<<"].insert("<<iElem+1<<")");
1251 #endif
1252       }
1253     }
1254     else if (token == GmfHexahedra && nbElem > 0) {
1255       (nbElem <= 1) ? tmpStr = " Hexahedron" : tmpStr = " Hexahedra";
1256       for ( int iElem = 0; iElem < nbElem; iElem++ )
1257         GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &id[iElem*tabRef[token]+2], &id[iElem*tabRef[token]+3],
1258                   &id[iElem*tabRef[token]+4], &id[iElem*tabRef[token]+5], &id[iElem*tabRef[token]+6], &id[iElem*tabRef[token]+7], &dummy);
1259     }
1260     std::cout << tmpStr << std::endl;
1261     std::cout << std::endl;
1262
1263     switch (token) {
1264     case GmfCorners:
1265     case GmfRidges:
1266     case GmfEdges:
1267     case GmfTriangles:
1268     case GmfQuadrilaterals:
1269     case GmfTetrahedra:
1270     case GmfHexahedra:
1271     {
1272       std::vector< const SMDS_MeshNode* > node( nbRef );
1273       std::vector< int >          nodeID( nbRef );
1274       std::vector< SMDS_MeshNode* > enfNode( nbRef );
1275       const SMDS_MeshElement* aCreatedElem;
1276
1277       for ( int iElem = 0; iElem < nbElem; iElem++ )
1278       {
1279 #ifdef WITH_SMESH_CANCEL_COMPUTE
1280         if(theAlgo->computeCanceled()) {
1281           GmfCloseMesh(InpMsh);
1282           delete [] GMFNode;
1283           //delete [] nodeAssigne;
1284           return false;
1285         }
1286 #endif
1287         // Check if elem is already in input mesh. If yes => skip
1288         bool fullyCreatedElement = false; // if at least one of the nodes was created
1289         for ( int iRef = 0; iRef < nbRef; iRef++ )
1290         {
1291           aGMFNodeID = id[iElem*tabRef[token]+iRef]; // read nbRef aGMFNodeID
1292           if (aGMFNodeID <= nbInitialNodes) // input nodes
1293           {
1294             aGMFNodeID--;
1295             node[ iRef ] = theNodeByGhs3dId[aGMFNodeID];
1296           }
1297           else
1298           {
1299             fullyCreatedElement = true;
1300             aGMFNodeID -= nbInitialNodes;
1301             nodeID[ iRef ] = aGMFNodeID ;
1302             node  [ iRef ] = GMFNode[ aGMFNodeID ];
1303           }
1304         }
1305
1306         switch (token)
1307         {
1308         case GmfEdges:
1309           if (fullyCreatedElement) {
1310             aCreatedElem = theHelper->AddEdge( node[0], node[1], /*id =*/0, /*force3d =*/false );
1311             if (anEdgeGroupByGhs3dId.size() && !anEdgeGroupByGhs3dId[iElem].empty())
1312               addElemInMeshGroup(theHelper->GetMesh(), aCreatedElem, anEdgeGroupByGhs3dId[iElem], groupsToRemove);
1313           }
1314           break;
1315         case GmfTriangles:
1316           if (fullyCreatedElement) {
1317             aCreatedElem = theHelper->AddFace( node[0], node[1], node[2], /*id =*/0, /*force3d =*/false );
1318             // for ( int iRef = 0; iRef < nbRef; iRef++ )
1319             //   nodeAssigne[ nodeID[ iRef ]] = 1;
1320             if (aFaceGroupByGhs3dId.size() && !aFaceGroupByGhs3dId[iElem].empty())
1321               addElemInMeshGroup(theHelper->GetMesh(), aCreatedElem, aFaceGroupByGhs3dId[iElem], groupsToRemove);
1322           }
1323           break;
1324         case GmfQuadrilaterals:
1325           if (fullyCreatedElement) {
1326             theHelper->AddFace( node[0], node[1], node[2], node[3], /*id =*/0, /*force3d =*/false );
1327             // for ( int iRef = 0; iRef < nbRef; iRef++ )
1328             //   nodeAssigne[ nodeID[ iRef ]] = 1;
1329           }
1330           break;
1331         case GmfTetrahedra:
1332           if ( elemSearcher ) {
1333             // Issue 0020682. Avoid creating nodes and tetras at place where
1334             // volumic elements already exist
1335             if ( !node[1] || !node[0] || !node[2] || !node[3] )
1336               continue;
1337             if ( elemSearcher->FindElementsByPoint((SMESH_TNodeXYZ(node[0]) +
1338                                                     SMESH_TNodeXYZ(node[1]) +
1339                                                     SMESH_TNodeXYZ(node[2]) +
1340                                                     SMESH_TNodeXYZ(node[3]) ) / 4.,
1341                                                     SMDSAbs_Volume, foundVolumes ))
1342             break;
1343           }
1344           theHelper->AddVolume( node[1], node[0], node[2], node[3], /*id =*/0, /*force3d =*/false );
1345 //           theMeshDS->SetMeshElementOnShape( aTet, shapeID );
1346           break;
1347         case GmfHexahedra:
1348           if ( elemSearcher ) {
1349             // Issue 0020682. Avoid creating nodes and tetras at place where
1350             // volumic elements already exist
1351             if ( !node[1] || !node[0] || !node[2] || !node[3] || !node[4] || !node[5] || !node[6] || !node[7])
1352               continue;
1353             if ( elemSearcher->FindElementsByPoint((SMESH_TNodeXYZ(node[0]) +
1354                                                     SMESH_TNodeXYZ(node[1]) +
1355                                                     SMESH_TNodeXYZ(node[2]) +
1356                                                     SMESH_TNodeXYZ(node[3]) +
1357                                                     SMESH_TNodeXYZ(node[4]) +
1358                                                     SMESH_TNodeXYZ(node[5]) +
1359                                                     SMESH_TNodeXYZ(node[6]) +
1360                                                     SMESH_TNodeXYZ(node[7])) / 8.,
1361                                                     SMDSAbs_Volume, foundVolumes ))
1362             break;
1363           }
1364           theHelper->AddVolume( node[0], node[3], node[2], node[1],
1365                                 node[4], node[7], node[6], node[5], /*id =*/0, /*force3d =*/false );
1366 //           theMeshDS->SetMeshElementOnShape( aTet, shapeID );
1367           break;
1368         default: continue;
1369         }
1370       }
1371       break;
1372     }
1373     }
1374   }
1375
1376   // for ( int i = 0; i < nbVertices; ++i ) {
1377   //   if ( !nodeAssigne[ i+1 ])
1378   //     theMeshDS->SetNodeInVolume( GMFNode[ i+1 ], shapeID );
1379   // }
1380
1381   GmfCloseMesh(InpMsh);
1382   delete [] GMFNode;
1383   //delete [] nodeAssigne;
1384 #ifdef _DEBUG_  
1385   MESSAGE("Nb subdomains " << subdomainId2tetraId.size());
1386   std::map<int, std::set<int> >::const_iterator subdomainIt = subdomainId2tetraId.begin();
1387   TCollection_AsciiString aSubdomainFileName = theFile;
1388   aSubdomainFileName = aSubdomainFileName + ".subdomain";
1389   ofstream aSubdomainFile  ( aSubdomainFileName.ToCString()  , ios::out);
1390
1391   aSubdomainFile << "Nb subdomains " << subdomainId2tetraId.size() << std::endl;
1392   for(;subdomainIt != subdomainId2tetraId.end() ; ++subdomainIt) {
1393     int subdomainId = subdomainIt->first;
1394     std::set<int> tetraIds = subdomainIt->second;
1395     MESSAGE("Subdomain #"<<subdomainId<<": "<<tetraIds.size()<<" tetrahedrons");
1396     std::set<int>::const_iterator tetraIdsIt = tetraIds.begin();
1397     aSubdomainFile << subdomainId << std::endl;
1398     for(;tetraIdsIt != tetraIds.end() ; ++tetraIdsIt) {
1399       aSubdomainFile << (*tetraIdsIt) << " ";
1400     }
1401     aSubdomainFile << std::endl;
1402   }
1403   aSubdomainFile.close();
1404 #endif  
1405   
1406   return true;
1407 }
1408
1409 static bool writeGMFFile(const char*                                     theMeshFileName,
1410                          const char*                                     theRequiredFileName,
1411                          const char*                                     theSolFileName,
1412                          const SMESH_ProxyMesh&                          theProxyMesh,
1413                          SMESH_Mesh *                                    theMesh,
1414                          std::vector <const SMDS_MeshNode*> &            theNodeByGhs3dId,
1415                          std::map<const SMDS_MeshNode*,int> &            aNodeToGhs3dIdMap,
1416                          std::vector<std::string> &                      aNodeGroupByGhs3dId,
1417                          std::vector<std::string> &                      anEdgeGroupByGhs3dId,
1418                          std::vector<std::string> &                      aFaceGroupByGhs3dId,
1419                          GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap & theEnforcedNodes,
1420                          GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedEdges,
1421                          GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedTriangles,
1422                          std::map<std::vector<double>, std::string> &    enfVerticesWithGroup,
1423                          GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues & theEnforcedVertices)
1424 {
1425   MESSAGE("writeGMFFile w/o geometry");
1426   std::string tmpStr;
1427   int idx, idxRequired = 0, idxSol = 0;
1428   const int dummyint = 0;
1429   GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues::const_iterator vertexIt;
1430   std::vector<double> enfVertexSizes;
1431   const SMDS_MeshElement* elem;
1432   TIDSortedElemSet anElemSet, theKeptEnforcedEdges, theKeptEnforcedTriangles;
1433   SMDS_ElemIteratorPtr nodeIt;
1434   std::vector <const SMDS_MeshNode*> theEnforcedNodeByGhs3dId;
1435   map<const SMDS_MeshNode*,int> anEnforcedNodeToGhs3dIdMap, anExistingEnforcedNodeToGhs3dIdMap;
1436   std::vector< const SMDS_MeshElement* > foundElems;
1437   map<const SMDS_MeshNode*,TopAbs_State> aNodeToTopAbs_StateMap;
1438   int nbFoundElems;
1439   GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap::iterator elemIt;
1440   TIDSortedElemSet::iterator elemSetIt;
1441   bool isOK;
1442   auto_ptr< SMESH_ElementSearcher > pntCls
1443     ( SMESH_MeshAlgos::GetElementSearcher(*theMesh->GetMeshDS()));
1444   
1445   int nbEnforcedVertices = theEnforcedVertices.size();
1446   
1447   // count faces
1448   int nbFaces = theProxyMesh.NbFaces();
1449   int nbNodes;
1450   
1451   // groups management
1452   int usedEnforcedNodes = 0;
1453   std::string gn = "";
1454
1455   if ( nbFaces == 0 )
1456     return false;
1457   
1458   idx = GmfOpenMesh(theMeshFileName, GmfWrite, GMFVERSION, GMFDIMENSION);
1459   if (!idx)
1460     return false;
1461   
1462   /* ========================== FACES ========================== */
1463   /* TRIANGLES ========================== */
1464   SMDS_ElemIteratorPtr eIt = theProxyMesh.GetFaces();
1465   while ( eIt->more() )
1466   {
1467     elem = eIt->next();
1468     anElemSet.insert(elem);
1469     nodeIt = elem->nodesIterator();
1470     nbNodes = elem->NbCornerNodes();
1471     while ( nodeIt->more() && nbNodes--)
1472     {
1473       // find GHS3D ID
1474       const SMDS_MeshNode* node = castToNode( nodeIt->next() );
1475       int newId = aNodeToGhs3dIdMap.size() + 1; // ghs3d ids count from 1
1476       aNodeToGhs3dIdMap.insert( make_pair( node, newId ));
1477     }
1478   }
1479   
1480   /* EDGES ========================== */
1481   
1482   // Iterate over the enforced edges
1483   for(elemIt = theEnforcedEdges.begin() ; elemIt != theEnforcedEdges.end() ; ++elemIt) {
1484     elem = elemIt->first;
1485     isOK = true;
1486     nodeIt = elem->nodesIterator();
1487     nbNodes = 2;
1488     while ( nodeIt->more() && nbNodes-- ) {
1489       // find GHS3D ID
1490       const SMDS_MeshNode* node = castToNode( nodeIt->next() );
1491       // Test if point is inside shape to mesh
1492       gp_Pnt myPoint(node->X(),node->Y(),node->Z());
1493       TopAbs_State result = pntCls->GetPointState( myPoint );
1494       if ( result == TopAbs_OUT ) {
1495         isOK = false;
1496         break;
1497       }
1498       aNodeToTopAbs_StateMap.insert( make_pair( node, result ));
1499     }
1500     if (isOK) {
1501       nodeIt = elem->nodesIterator();
1502       nbNodes = 2;
1503       int newId = -1;
1504       while ( nodeIt->more() && nbNodes-- ) {
1505         // find GHS3D ID
1506         const SMDS_MeshNode* node = castToNode( nodeIt->next() );
1507         gp_Pnt myPoint(node->X(),node->Y(),node->Z());
1508         nbFoundElems = pntCls->FindElementsByPoint(myPoint, SMDSAbs_Node, foundElems);
1509 #ifdef _DEBUG_
1510         std::cout << "Node at "<<node->X()<<", "<<node->Y()<<", "<<node->Z()<<std::endl;
1511         std::cout << "Nb nodes found : "<<nbFoundElems<<std::endl;
1512 #endif
1513         if (nbFoundElems ==0) {
1514           if ((*aNodeToTopAbs_StateMap.find(node)).second == TopAbs_IN) {
1515             newId = aNodeToGhs3dIdMap.size() + anEnforcedNodeToGhs3dIdMap.size() + 1; // ghs3d ids count from 1
1516             anEnforcedNodeToGhs3dIdMap.insert( make_pair( node, newId ));
1517           }
1518         }
1519         else if (nbFoundElems ==1) {
1520           const SMDS_MeshNode* existingNode = (SMDS_MeshNode*) foundElems.at(0);
1521           newId = (*aNodeToGhs3dIdMap.find(existingNode)).second;
1522           anExistingEnforcedNodeToGhs3dIdMap.insert( make_pair( node, newId ));
1523         }
1524         else
1525           isOK = false;
1526 #ifdef _DEBUG_
1527         std::cout << "GHS3D node ID: "<<newId<<std::endl;
1528 #endif
1529       }
1530       if (isOK)
1531         theKeptEnforcedEdges.insert(elem);
1532     }
1533   }
1534   
1535   /* ENFORCED TRIANGLES ========================== */
1536   
1537   // Iterate over the enforced triangles
1538   for(elemIt = theEnforcedTriangles.begin() ; elemIt != theEnforcedTriangles.end() ; ++elemIt) {
1539     elem = elemIt->first;
1540     isOK = true;
1541     nodeIt = elem->nodesIterator();
1542     nbNodes = 3;
1543     while ( nodeIt->more() && nbNodes--) {
1544       // find GHS3D ID
1545       const SMDS_MeshNode* node = castToNode( nodeIt->next() );
1546       // Test if point is inside shape to mesh
1547       gp_Pnt myPoint(node->X(),node->Y(),node->Z());
1548       TopAbs_State result = pntCls->GetPointState( myPoint );
1549       if ( result == TopAbs_OUT ) {
1550         isOK = false;
1551         break;
1552       }
1553       aNodeToTopAbs_StateMap.insert( make_pair( node, result ));
1554     }
1555     if (isOK) {
1556       nodeIt = elem->nodesIterator();
1557       nbNodes = 3;
1558       int newId = -1;
1559       while ( nodeIt->more() && nbNodes--) {
1560         // find GHS3D ID
1561         const SMDS_MeshNode* node = castToNode( nodeIt->next() );
1562         gp_Pnt myPoint(node->X(),node->Y(),node->Z());
1563         nbFoundElems = pntCls->FindElementsByPoint(myPoint, SMDSAbs_Node, foundElems);
1564 #ifdef _DEBUG_
1565         std::cout << "Nb nodes found : "<<nbFoundElems<<std::endl;
1566 #endif
1567         if (nbFoundElems ==0) {
1568           if ((*aNodeToTopAbs_StateMap.find(node)).second == TopAbs_IN) {
1569             newId = aNodeToGhs3dIdMap.size() + anEnforcedNodeToGhs3dIdMap.size() + 1; // ghs3d ids count from 1
1570             anEnforcedNodeToGhs3dIdMap.insert( make_pair( node, newId ));
1571           }
1572         }
1573         else if (nbFoundElems ==1) {
1574           const SMDS_MeshNode* existingNode = (SMDS_MeshNode*) foundElems.at(0);
1575           newId = (*aNodeToGhs3dIdMap.find(existingNode)).second;
1576           anExistingEnforcedNodeToGhs3dIdMap.insert( make_pair( node, newId ));
1577         }
1578         else
1579           isOK = false;
1580 #ifdef _DEBUG_
1581         std::cout << "GHS3D node ID: "<<newId<<std::endl;
1582 #endif
1583       }
1584       if (isOK)
1585         theKeptEnforcedTriangles.insert(elem);
1586     }
1587   }
1588   
1589   // put nodes to theNodeByGhs3dId vector
1590 #ifdef _DEBUG_
1591   std::cout << "aNodeToGhs3dIdMap.size(): "<<aNodeToGhs3dIdMap.size()<<std::endl;
1592 #endif
1593   theNodeByGhs3dId.resize( aNodeToGhs3dIdMap.size() );
1594   map<const SMDS_MeshNode*,int>::const_iterator n2id = aNodeToGhs3dIdMap.begin();
1595   for ( ; n2id != aNodeToGhs3dIdMap.end(); ++ n2id)
1596   {
1597 //     std::cout << "n2id->first: "<<n2id->first<<std::endl;
1598     theNodeByGhs3dId[ n2id->second - 1 ] = n2id->first; // ghs3d ids count from 1
1599   }
1600
1601   // put nodes to anEnforcedNodeToGhs3dIdMap vector
1602 #ifdef _DEBUG_
1603   std::cout << "anEnforcedNodeToGhs3dIdMap.size(): "<<anEnforcedNodeToGhs3dIdMap.size()<<std::endl;
1604 #endif
1605   theEnforcedNodeByGhs3dId.resize( anEnforcedNodeToGhs3dIdMap.size());
1606   n2id = anEnforcedNodeToGhs3dIdMap.begin();
1607   for ( ; n2id != anEnforcedNodeToGhs3dIdMap.end(); ++ n2id)
1608   {
1609     if (n2id->second > aNodeToGhs3dIdMap.size()) {
1610       theEnforcedNodeByGhs3dId[ n2id->second - aNodeToGhs3dIdMap.size() - 1 ] = n2id->first; // ghs3d ids count from 1
1611     }
1612   }
1613   
1614   
1615   /* ========================== NODES ========================== */
1616   vector<const SMDS_MeshNode*> theOrderedNodes, theRequiredNodes;
1617   std::set< std::vector<double> > nodesCoords;
1618   vector<const SMDS_MeshNode*>::const_iterator ghs3dNodeIt = theNodeByGhs3dId.begin();
1619   vector<const SMDS_MeshNode*>::const_iterator after  = theNodeByGhs3dId.end();
1620   
1621   (theNodeByGhs3dId.size() <= 1) ? tmpStr = " node" : " nodes";
1622   std::cout << theNodeByGhs3dId.size() << tmpStr << " from mesh ..." << std::endl;
1623   for ( ; ghs3dNodeIt != after; ++ghs3dNodeIt )
1624   {
1625     const SMDS_MeshNode* node = *ghs3dNodeIt;
1626     std::vector<double> coords;
1627     coords.push_back(node->X());
1628     coords.push_back(node->Y());
1629     coords.push_back(node->Z());
1630     nodesCoords.insert(coords);
1631     theOrderedNodes.push_back(node);
1632   }
1633   
1634   // Iterate over the enforced nodes given by enforced elements
1635   ghs3dNodeIt = theEnforcedNodeByGhs3dId.begin();
1636   after  = theEnforcedNodeByGhs3dId.end();
1637   (theEnforcedNodeByGhs3dId.size() <= 1) ? tmpStr = " node" : " nodes";
1638   std::cout << theEnforcedNodeByGhs3dId.size() << tmpStr << " from enforced elements ..." << std::endl;
1639   for ( ; ghs3dNodeIt != after; ++ghs3dNodeIt )
1640   {
1641     const SMDS_MeshNode* node = *ghs3dNodeIt;
1642     std::vector<double> coords;
1643     coords.push_back(node->X());
1644     coords.push_back(node->Y());
1645     coords.push_back(node->Z());
1646 #ifdef _DEBUG_
1647     std::cout << "Node at " << node->X()<<", " <<node->Y()<<", " <<node->Z();
1648 #endif
1649     
1650     if (nodesCoords.find(coords) != nodesCoords.end()) {
1651       // node already exists in original mesh
1652 #ifdef _DEBUG_
1653       std::cout << " found" << std::endl;
1654 #endif
1655       continue;
1656     }
1657     
1658     if (theEnforcedVertices.find(coords) != theEnforcedVertices.end()) {
1659       // node already exists in enforced vertices
1660 #ifdef _DEBUG_
1661       std::cout << " found" << std::endl;
1662 #endif
1663       continue;
1664     }
1665     
1666 //     gp_Pnt myPoint(node->X(),node->Y(),node->Z());
1667 //     nbFoundElems = pntCls->FindElementsByPoint(myPoint, SMDSAbs_Node, foundElems);
1668 //     if (nbFoundElems ==0) {
1669 //       std::cout << " not found" << std::endl;
1670 //       if ((*aNodeToTopAbs_StateMap.find(node)).second == TopAbs_IN) {
1671 //         nodesCoords.insert(coords);
1672 //         theOrderedNodes.push_back(node);
1673 //       }
1674 //     }
1675 //     else {
1676 //       std::cout << " found in initial mesh" << std::endl;
1677 //       const SMDS_MeshNode* existingNode = (SMDS_MeshNode*) foundElems.at(0);
1678 //       nodesCoords.insert(coords);
1679 //       theOrderedNodes.push_back(existingNode);
1680 //     }
1681     
1682 #ifdef _DEBUG_
1683     std::cout << " not found" << std::endl;
1684 #endif
1685     
1686     nodesCoords.insert(coords);
1687     theOrderedNodes.push_back(node);
1688 //     theRequiredNodes.push_back(node);
1689   }
1690   
1691   
1692   // Iterate over the enforced nodes
1693   GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap::const_iterator enfNodeIt;
1694   (theEnforcedNodes.size() <= 1) ? tmpStr = " node" : " nodes";
1695   std::cout << theEnforcedNodes.size() << tmpStr << " from enforced nodes ..." << std::endl;
1696   for(enfNodeIt = theEnforcedNodes.begin() ; enfNodeIt != theEnforcedNodes.end() ; ++enfNodeIt)
1697   {
1698     const SMDS_MeshNode* node = enfNodeIt->first;
1699     std::vector<double> coords;
1700     coords.push_back(node->X());
1701     coords.push_back(node->Y());
1702     coords.push_back(node->Z());
1703 #ifdef _DEBUG_
1704     std::cout << "Node at " << node->X()<<", " <<node->Y()<<", " <<node->Z();
1705 #endif
1706     
1707     // Test if point is inside shape to mesh
1708     gp_Pnt myPoint(node->X(),node->Y(),node->Z());
1709     TopAbs_State result = pntCls->GetPointState( myPoint );
1710     if ( result == TopAbs_OUT ) {
1711 #ifdef _DEBUG_
1712       std::cout << " out of volume" << std::endl;
1713 #endif
1714       continue;
1715     }
1716     
1717     if (nodesCoords.find(coords) != nodesCoords.end()) {
1718 #ifdef _DEBUG_
1719       std::cout << " found in nodesCoords" << std::endl;
1720 #endif
1721 //       theRequiredNodes.push_back(node);
1722       continue;
1723     }
1724
1725     if (theEnforcedVertices.find(coords) != theEnforcedVertices.end()) {
1726 #ifdef _DEBUG_
1727       std::cout << " found in theEnforcedVertices" << std::endl;
1728 #endif
1729       continue;
1730     }
1731     
1732 //     nbFoundElems = pntCls->FindElementsByPoint(myPoint, SMDSAbs_Node, foundElems);
1733 //     if (nbFoundElems ==0) {
1734 //       std::cout << " not found" << std::endl;
1735 //       if (result == TopAbs_IN) {
1736 //         nodesCoords.insert(coords);
1737 //         theRequiredNodes.push_back(node);
1738 //       }
1739 //     }
1740 //     else {
1741 //       std::cout << " found in initial mesh" << std::endl;
1742 //       const SMDS_MeshNode* existingNode = (SMDS_MeshNode*) foundElems.at(0);
1743 // //       nodesCoords.insert(coords);
1744 //       theRequiredNodes.push_back(existingNode);
1745 //     }
1746 //     
1747 //     
1748 //     
1749 //     if (pntCls->FindElementsByPoint(myPoint, SMDSAbs_Node, foundElems) == 0)
1750 //       continue;
1751
1752 //     if ( result != TopAbs_IN )
1753 //       continue;
1754     
1755 #ifdef _DEBUG_
1756     std::cout << " not found" << std::endl;
1757 #endif
1758     nodesCoords.insert(coords);
1759 //     theOrderedNodes.push_back(node);
1760     theRequiredNodes.push_back(node);
1761   }
1762   int requiredNodes = theRequiredNodes.size();
1763   
1764   int solSize = 0;
1765   std::vector<std::vector<double> > ReqVerTab;
1766   if (nbEnforcedVertices) {
1767 //    ReqVerTab.clear();
1768     (nbEnforcedVertices <= 1) ? tmpStr = " node" : " nodes";
1769     std::cout << nbEnforcedVertices << tmpStr << " from enforced vertices ..." << std::endl;
1770     // Iterate over the enforced vertices
1771     for(vertexIt = theEnforcedVertices.begin() ; vertexIt != theEnforcedVertices.end() ; ++vertexIt) {
1772       double x = vertexIt->first[0];
1773       double y = vertexIt->first[1];
1774       double z = vertexIt->first[2];
1775       // Test if point is inside shape to mesh
1776       gp_Pnt myPoint(x,y,z);
1777       TopAbs_State result = pntCls->GetPointState( myPoint );
1778       if ( result == TopAbs_OUT )
1779         continue;
1780       //if (pntCls->FindElementsByPoint(myPoint, SMDSAbs_Node, foundElems) == 0)
1781       //continue;
1782
1783 //       if ( result != TopAbs_IN )
1784 //         continue;
1785       std::vector<double> coords;
1786       coords.push_back(x);
1787       coords.push_back(y);
1788       coords.push_back(z);
1789       ReqVerTab.push_back(coords);
1790       enfVertexSizes.push_back(vertexIt->second);
1791       solSize++;
1792     }
1793   }
1794   
1795   
1796   // GmfVertices
1797   std::cout << "Begin writting required nodes in GmfVertices" << std::endl;
1798   std::cout << "Nb vertices: " << theOrderedNodes.size() << std::endl;
1799   GmfSetKwd(idx, GmfVertices, theOrderedNodes.size()/*+solSize*/);
1800   for (ghs3dNodeIt = theOrderedNodes.begin();ghs3dNodeIt != theOrderedNodes.end();++ghs3dNodeIt) {
1801     GmfSetLin(idx, GmfVertices, (*ghs3dNodeIt)->X(), (*ghs3dNodeIt)->Y(), (*ghs3dNodeIt)->Z(), dummyint);
1802   }
1803
1804   std::cout << "End writting required nodes in GmfVertices" << std::endl;
1805
1806   if (requiredNodes + solSize) {
1807     std::cout << "Begin writting in req and sol file" << std::endl;
1808     aNodeGroupByGhs3dId.resize( requiredNodes + solSize );
1809     idxRequired = GmfOpenMesh(theRequiredFileName, GmfWrite, GMFVERSION, GMFDIMENSION);
1810     if (!idxRequired) {
1811       GmfCloseMesh(idx);
1812       return false;
1813     }
1814     idxSol = GmfOpenMesh(theSolFileName, GmfWrite, GMFVERSION, GMFDIMENSION);
1815     if (!idxSol) {
1816       GmfCloseMesh(idx);
1817       if (idxRequired)
1818         GmfCloseMesh(idxRequired);
1819       return false;
1820     }
1821     int TypTab[] = {GmfSca};
1822     double ValTab[] = {0.0};
1823     GmfSetKwd(idxRequired, GmfVertices, requiredNodes + solSize);
1824     GmfSetKwd(idxSol, GmfSolAtVertices, requiredNodes + solSize, 1, TypTab);
1825 //     int usedEnforcedNodes = 0;
1826 //     std::string gn = "";
1827     for (ghs3dNodeIt = theRequiredNodes.begin();ghs3dNodeIt != theRequiredNodes.end();++ghs3dNodeIt) {
1828       GmfSetLin(idxRequired, GmfVertices, (*ghs3dNodeIt)->X(), (*ghs3dNodeIt)->Y(), (*ghs3dNodeIt)->Z(), dummyint);
1829       GmfSetLin(idxSol, GmfSolAtVertices, ValTab);
1830       if (theEnforcedNodes.find((*ghs3dNodeIt)) != theEnforcedNodes.end())
1831         gn = theEnforcedNodes.find((*ghs3dNodeIt))->second;
1832       aNodeGroupByGhs3dId[usedEnforcedNodes] = gn;
1833       usedEnforcedNodes++;
1834     }
1835
1836     for (int i=0;i<solSize;i++) {
1837       std::cout << ReqVerTab[i][0] <<" "<< ReqVerTab[i][1] << " "<< ReqVerTab[i][2] << std::endl;
1838 #ifdef _DEBUG_
1839       std::cout << "enfVertexSizes.at("<<i<<"): " << enfVertexSizes.at(i) << std::endl;
1840 #endif
1841       double solTab[] = {enfVertexSizes.at(i)};
1842       GmfSetLin(idxRequired, GmfVertices, ReqVerTab[i][0], ReqVerTab[i][1], ReqVerTab[i][2], dummyint);
1843       GmfSetLin(idxSol, GmfSolAtVertices, solTab);
1844       aNodeGroupByGhs3dId[usedEnforcedNodes] = enfVerticesWithGroup.find(ReqVerTab[i])->second;
1845 #ifdef _DEBUG_
1846       std::cout << "aNodeGroupByGhs3dId["<<usedEnforcedNodes<<"] = \""<<aNodeGroupByGhs3dId[usedEnforcedNodes]<<"\""<<std::endl;
1847 #endif
1848       usedEnforcedNodes++;
1849     }
1850     std::cout << "End writting in req and sol file" << std::endl;
1851   }
1852
1853   int nedge[2], ntri[3];
1854     
1855   // GmfEdges
1856   int usedEnforcedEdges = 0;
1857   if (theKeptEnforcedEdges.size()) {
1858     anEdgeGroupByGhs3dId.resize( theKeptEnforcedEdges.size() );
1859 //    idxRequired = GmfOpenMesh(theRequiredFileName, GmfWrite, GMFVERSION, GMFDIMENSION);
1860 //    if (!idxRequired)
1861 //      return false;
1862     GmfSetKwd(idx, GmfEdges, theKeptEnforcedEdges.size());
1863 //    GmfSetKwd(idxRequired, GmfEdges, theKeptEnforcedEdges.size());
1864     for(elemSetIt = theKeptEnforcedEdges.begin() ; elemSetIt != theKeptEnforcedEdges.end() ; ++elemSetIt) {
1865       elem = (*elemSetIt);
1866       nodeIt = elem->nodesIterator();
1867       int index=0;
1868       while ( nodeIt->more() ) {
1869         // find GHS3D ID
1870         const SMDS_MeshNode* node = castToNode( nodeIt->next() );
1871         map< const SMDS_MeshNode*,int >::iterator it = anEnforcedNodeToGhs3dIdMap.find(node);
1872         if (it == anEnforcedNodeToGhs3dIdMap.end()) {
1873           it = anExistingEnforcedNodeToGhs3dIdMap.find(node);
1874           if (it == anEnforcedNodeToGhs3dIdMap.end())
1875             throw "Node not found";
1876         }
1877         nedge[index] = it->second;
1878         index++;
1879       }
1880       GmfSetLin(idx, GmfEdges, nedge[0], nedge[1], dummyint);
1881       anEdgeGroupByGhs3dId[usedEnforcedEdges] = theEnforcedEdges.find(elem)->second;
1882 //      GmfSetLin(idxRequired, GmfEdges, nedge[0], nedge[1], dummyint);
1883       usedEnforcedEdges++;
1884     }
1885 //    GmfCloseMesh(idxRequired);
1886   }
1887
1888
1889   if (usedEnforcedEdges) {
1890     GmfSetKwd(idx, GmfRequiredEdges, usedEnforcedEdges);
1891     for (int enfID=1;enfID<=usedEnforcedEdges;enfID++) {
1892       GmfSetLin(idx, GmfRequiredEdges, enfID);
1893     }
1894   }
1895
1896   // GmfTriangles
1897   int usedEnforcedTriangles = 0;
1898   if (anElemSet.size()+theKeptEnforcedTriangles.size()) {
1899     aFaceGroupByGhs3dId.resize( anElemSet.size()+theKeptEnforcedTriangles.size() );
1900     GmfSetKwd(idx, GmfTriangles, anElemSet.size()+theKeptEnforcedTriangles.size());
1901     int k=0;
1902     for(elemSetIt = anElemSet.begin() ; elemSetIt != anElemSet.end() ; ++elemSetIt,++k) {
1903       elem = (*elemSetIt);
1904       nodeIt = elem->nodesIterator();
1905       int index=0;
1906       for ( int j = 0; j < 3; ++j ) {
1907         // find GHS3D ID
1908         const SMDS_MeshNode* node = castToNode( nodeIt->next() );
1909         map< const SMDS_MeshNode*,int >::iterator it = aNodeToGhs3dIdMap.find(node);
1910         if (it == aNodeToGhs3dIdMap.end())
1911           throw "Node not found";
1912         ntri[index] = it->second;
1913         index++;
1914       }
1915       GmfSetLin(idx, GmfTriangles, ntri[0], ntri[1], ntri[2], dummyint);
1916       aFaceGroupByGhs3dId[k] = "";
1917     }
1918     if (theKeptEnforcedTriangles.size()) {
1919       for(elemSetIt = theKeptEnforcedTriangles.begin() ; elemSetIt != theKeptEnforcedTriangles.end() ; ++elemSetIt,++k) {
1920         elem = (*elemSetIt);
1921         nodeIt = elem->nodesIterator();
1922         int index=0;
1923         for ( int j = 0; j < 3; ++j ) {
1924           // find GHS3D ID
1925           const SMDS_MeshNode* node = castToNode( nodeIt->next() );
1926           map< const SMDS_MeshNode*,int >::iterator it = anEnforcedNodeToGhs3dIdMap.find(node);
1927           if (it == anEnforcedNodeToGhs3dIdMap.end()) {
1928             it = anExistingEnforcedNodeToGhs3dIdMap.find(node);
1929             if (it == anEnforcedNodeToGhs3dIdMap.end())
1930               throw "Node not found";
1931           }
1932           ntri[index] = it->second;
1933           index++;
1934         }
1935         GmfSetLin(idx, GmfTriangles, ntri[0], ntri[1], ntri[2], dummyint);
1936         aFaceGroupByGhs3dId[k] = theEnforcedTriangles.find(elem)->second;
1937         usedEnforcedTriangles++;
1938       }
1939     }
1940   }
1941
1942   
1943   if (usedEnforcedTriangles) {
1944     GmfSetKwd(idx, GmfRequiredTriangles, usedEnforcedTriangles);
1945     for (int enfID=1;enfID<=usedEnforcedTriangles;enfID++)
1946       GmfSetLin(idx, GmfRequiredTriangles, anElemSet.size()+enfID);
1947   }
1948
1949   GmfCloseMesh(idx);
1950   if (idxRequired)
1951     GmfCloseMesh(idxRequired);
1952   if (idxSol)
1953     GmfCloseMesh(idxSol);
1954   
1955   return true;
1956   
1957 }
1958
1959 // static bool writeGMFFile(const char*                                    theMeshFileName,
1960 //                         const char*                                     theRequiredFileName,
1961 //                         const char*                                     theSolFileName,
1962 //                         SMESH_MesherHelper&                             theHelper,
1963 //                         const SMESH_ProxyMesh&                          theProxyMesh,
1964 //                         std::map <int,int> &                            theNodeId2NodeIndexMap,
1965 //                         std::map <int,int> &                            theSmdsToGhs3dIdMap,
1966 //                         std::map <int,const SMDS_MeshNode*> &           theGhs3dIdToNodeMap,
1967 //                         TIDSortedNodeSet &                              theEnforcedNodes,
1968 //                         TIDSortedElemSet &                              theEnforcedEdges,
1969 //                         TIDSortedElemSet &                              theEnforcedTriangles,
1970 // //                         TIDSortedElemSet &                              theEnforcedQuadrangles,
1971 //                         GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues & theEnforcedVertices)
1972 // {
1973 //   MESSAGE("writeGMFFile with geometry");
1974 //   int idx, idxRequired, idxSol;
1975 //   int nbv, nbev, nben, aGhs3dID = 0;
1976 //   const int dummyint = 0;
1977 //   GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues::const_iterator vertexIt;
1978 //   std::vector<double> enfVertexSizes;
1979 //   TIDSortedNodeSet::const_iterator enfNodeIt;
1980 //   const SMDS_MeshNode* node;
1981 //   SMDS_NodeIteratorPtr nodeIt;
1982 // 
1983 //   idx = GmfOpenMesh(theMeshFileName, GmfWrite, GMFVERSION, GMFDIMENSION);
1984 //   if (!idx)
1985 //     return false;
1986 //   
1987 //   SMESHDS_Mesh * theMeshDS = theHelper.GetMeshDS();
1988 //   
1989 //   /* ========================== NODES ========================== */
1990 //   // NB_NODES
1991 //   nbv = theMeshDS->NbNodes();
1992 //   if ( nbv == 0 )
1993 //     return false;
1994 //   nbev = theEnforcedVertices.size();
1995 //   nben = theEnforcedNodes.size();
1996 //   
1997 //   // Issue 020674: EDF 870 SMESH: Mesh generated by Netgen not usable by GHS3D
1998 //   // The problem is in nodes on degenerated edges, we need to skip nodes which are free
1999 //   // and replace not-free nodes on edges by the node on vertex
2000 //   TNodeNodeMap n2nDegen; // map a node on degenerated edge to a node on vertex
2001 //   TNodeNodeMap::iterator n2nDegenIt;
2002 //   if ( theHelper.HasDegeneratedEdges() )
2003 //   {
2004 //     set<int> checkedSM;
2005 //     for (TopExp_Explorer e(theMeshDS->ShapeToMesh(), TopAbs_EDGE ); e.More(); e.Next())
2006 //     {
2007 //       SMESH_subMesh* sm = theHelper.GetMesh()->GetSubMesh( e.Current() );
2008 //       if ( checkedSM.insert( sm->GetId() ).second && theHelper.IsDegenShape(sm->GetId() ))
2009 //       {
2010 //         if ( SMESHDS_SubMesh* smDS = sm->GetSubMeshDS() )
2011 //         {
2012 //           TopoDS_Shape vertex = TopoDS_Iterator( e.Current() ).Value();
2013 //           const SMDS_MeshNode* vNode = SMESH_Algo::VertexNode( TopoDS::Vertex( vertex ), theMeshDS);
2014 //           {
2015 //             SMDS_NodeIteratorPtr nIt = smDS->GetNodes();
2016 //             while ( nIt->more() )
2017 //               n2nDegen.insert( make_pair( nIt->next(), vNode ));
2018 //           }
2019 //         }
2020 //       }
2021 //     }
2022 //   }
2023 //   
2024 //   const bool isQuadMesh = 
2025 //     theHelper.GetMesh()->NbEdges( ORDER_QUADRATIC ) ||
2026 //     theHelper.GetMesh()->NbFaces( ORDER_QUADRATIC ) ||
2027 //     theHelper.GetMesh()->NbVolumes( ORDER_QUADRATIC );
2028 // 
2029 //   std::vector<std::vector<double> > VerTab;
2030 //   std::set<std::vector<double> > VerMap;
2031 //   VerTab.clear();
2032 //   std::vector<double> aVerTab;
2033 //   // Loop from 1 to NB_NODES
2034 // 
2035 //   nodeIt = theMeshDS->nodesIterator();
2036 //   
2037 //   while ( nodeIt->more() )
2038 //   {
2039 //     node = nodeIt->next();
2040 //     if ( isQuadMesh && theHelper.IsMedium( node )) // Issue 0021238
2041 //       continue;
2042 //     if ( n2nDegen.count( node ) ) // Issue 0020674
2043 //       continue;
2044 // 
2045 //     std::vector<double> coords;
2046 //     coords.push_back(node->X());
2047 //     coords.push_back(node->Y());
2048 //     coords.push_back(node->Z());
2049 //     if (VerMap.find(coords) != VerMap.end()) {
2050 //       aGhs3dID = theSmdsToGhs3dIdMap[node->GetID()];
2051 //       theGhs3dIdToNodeMap[theSmdsToGhs3dIdMap[node->GetID()]] = node;
2052 //       continue;
2053 //     }
2054 //     VerTab.push_back(coords);
2055 //     VerMap.insert(coords);
2056 //     aGhs3dID++;
2057 //     theSmdsToGhs3dIdMap.insert( make_pair( node->GetID(), aGhs3dID ));
2058 //     theGhs3dIdToNodeMap.insert( make_pair( aGhs3dID, node ));
2059 //   }
2060 //   
2061 //   
2062 //   /* ENFORCED NODES ========================== */
2063 //   if (nben) {
2064 //     std::cout << "Add " << nben << " enforced nodes to input .mesh file" << std::endl;
2065 //     for(enfNodeIt = theEnforcedNodes.begin() ; enfNodeIt != theEnforcedNodes.end() ; ++enfNodeIt) {
2066 //       double x = (*enfNodeIt)->X();
2067 //       double y = (*enfNodeIt)->Y();
2068 //       double z = (*enfNodeIt)->Z();
2069 //       // Test if point is inside shape to mesh
2070 //       gp_Pnt myPoint(x,y,z);
2071 //       BRepClass3d_SolidClassifier scl(theMeshDS->ShapeToMesh());
2072 //       scl.Perform(myPoint, 1e-7);
2073 //       TopAbs_State result = scl.State();
2074 //       if ( result != TopAbs_IN )
2075 //         continue;
2076 //       std::vector<double> coords;
2077 //       coords.push_back(x);
2078 //       coords.push_back(y);
2079 //       coords.push_back(z);
2080 //       if (theEnforcedVertices.find(coords) != theEnforcedVertices.end())
2081 //         continue;
2082 //       if (VerMap.find(coords) != VerMap.end())
2083 //         continue;
2084 //       VerTab.push_back(coords);
2085 //       VerMap.insert(coords);
2086 //       aGhs3dID++;
2087 //       theNodeId2NodeIndexMap.insert( make_pair( (*enfNodeIt)->GetID(), aGhs3dID ));
2088 //     }
2089 //   }
2090 //     
2091 //   
2092 //   /* ENFORCED VERTICES ========================== */
2093 //   int solSize = 0;
2094 //   std::vector<std::vector<double> > ReqVerTab;
2095 //   ReqVerTab.clear();
2096 //   if (nbev) {
2097 //     std::cout << "Add " << nbev << " enforced vertices to input .mesh file" << std::endl;
2098 //     for(vertexIt = theEnforcedVertices.begin() ; vertexIt != theEnforcedVertices.end() ; ++vertexIt) {
2099 //       double x = vertexIt->first[0];
2100 //       double y = vertexIt->first[1];
2101 //       double z = vertexIt->first[2];
2102 //       // Test if point is inside shape to mesh
2103 //       gp_Pnt myPoint(x,y,z);
2104 //       BRepClass3d_SolidClassifier scl(theMeshDS->ShapeToMesh());
2105 //       scl.Perform(myPoint, 1e-7);
2106 //       TopAbs_State result = scl.State();
2107 //       if ( result != TopAbs_IN )
2108 //         continue;
2109 //       enfVertexSizes.push_back(vertexIt->second);
2110 //       std::vector<double> coords;
2111 //       coords.push_back(x);
2112 //       coords.push_back(y);
2113 //       coords.push_back(z);
2114 //       if (VerMap.find(coords) != VerMap.end())
2115 //         continue;
2116 //       ReqVerTab.push_back(coords);
2117 //       VerMap.insert(coords);
2118 //       solSize++;
2119 //     }
2120 //   }
2121 // 
2122 //   
2123 //   /* ========================== FACES ========================== */
2124 //   
2125 //   int nbTriangles = 0/*, nbQuadrangles = 0*/, aSmdsID;
2126 //   TopTools_IndexedMapOfShape facesMap, trianglesMap/*, quadranglesMap*/;
2127 //   TIDSortedElemSet::const_iterator elemIt;
2128 //   const SMESHDS_SubMesh* theSubMesh;
2129 //   TopoDS_Shape aShape;
2130 //   SMDS_ElemIteratorPtr itOnSubMesh, itOnSubFace;
2131 //   const SMDS_MeshElement* aFace;
2132 //   map<int,int>::const_iterator itOnMap;
2133 //   std::vector<std::vector<int> > tt, qt,et;
2134 //   tt.clear();
2135 //   qt.clear();
2136 //   et.clear();
2137 //   std::vector<int> att, aqt, aet;
2138 //   
2139 //   TopExp::MapShapes( theMeshDS->ShapeToMesh(), TopAbs_FACE, facesMap );
2140 // 
2141 //   for ( int i = 1; i <= facesMap.Extent(); ++i )
2142 //     if (( theSubMesh  = theProxyMesh.GetSubMesh( facesMap(i))))
2143 //     {
2144 //       SMDS_ElemIteratorPtr it = theSubMesh->GetElements();
2145 //       while (it->more())
2146 //       {
2147 //         const SMDS_MeshElement *elem = it->next();
2148 //         int nbCornerNodes = elem->NbCornerNodes();
2149 //         if (nbCornerNodes == 3)
2150 //         {
2151 //           trianglesMap.Add(facesMap(i));
2152 //           nbTriangles ++;
2153 //         }
2154 // //         else if (nbCornerNodes == 4)
2155 // //         {
2156 // //           quadranglesMap.Add(facesMap(i));
2157 // //           nbQuadrangles ++;
2158 // //         }
2159 //       }
2160 //     }
2161 //     
2162 //   /* TRIANGLES ========================== */
2163 //   if (nbTriangles) {
2164 //     for ( int i = 1; i <= trianglesMap.Extent(); i++ )
2165 //     {
2166 //       aShape = trianglesMap(i);
2167 //       theSubMesh = theProxyMesh.GetSubMesh(aShape);
2168 //       if ( !theSubMesh ) continue;
2169 //       itOnSubMesh = theSubMesh->GetElements();
2170 //       while ( itOnSubMesh->more() )
2171 //       {
2172 //         aFace = itOnSubMesh->next();
2173 //         itOnSubFace = aFace->nodesIterator();
2174 //         att.clear();
2175 //         for ( int j = 0; j < 3; ++j ) {
2176 //           // find GHS3D ID
2177 //           node = castToNode( itOnSubFace->next() );
2178 //           if (( n2nDegenIt = n2nDegen.find( node )) != n2nDegen.end() )
2179 //             node = n2nDegenIt->second;
2180 //           aSmdsID = node->GetID();
2181 //           itOnMap = theSmdsToGhs3dIdMap.find( aSmdsID );
2182 //           ASSERT( itOnMap != theSmdsToGhs3dIdMap.end() );
2183 //           att.push_back((*itOnMap).second);
2184 //         }
2185 //         tt.push_back(att);
2186 //       }
2187 //     }
2188 //   }
2189 // 
2190 //   if (theEnforcedTriangles.size()) {
2191 //     std::cout << "Add " << theEnforcedTriangles.size() << " enforced triangles to input .mesh file" << std::endl;
2192 //     // Iterate over the enforced triangles
2193 //     for(elemIt = theEnforcedTriangles.begin() ; elemIt != theEnforcedTriangles.end() ; ++elemIt) {
2194 //       aFace = (*elemIt);
2195 //       itOnSubFace = aFace->nodesIterator();
2196 //       bool isOK = true;
2197 //       att.clear();
2198 //       
2199 //       for ( int j = 0; j < 3; ++j ) {
2200 //         node = castToNode( itOnSubFace->next() );
2201 //         if (( n2nDegenIt = n2nDegen.find( node )) != n2nDegen.end() )
2202 //           node = n2nDegenIt->second;
2203 // //         std::cout << node;
2204 //         double x = node->X();
2205 //         double y = node->Y();
2206 //         double z = node->Z();
2207 //         // Test if point is inside shape to mesh
2208 //         gp_Pnt myPoint(x,y,z);
2209 //         BRepClass3d_SolidClassifier scl(theMeshDS->ShapeToMesh());
2210 //         scl.Perform(myPoint, 1e-7);
2211 //         TopAbs_State result = scl.State();
2212 //         if ( result != TopAbs_IN ) {
2213 //           isOK = false;
2214 //           theEnforcedTriangles.erase(elemIt);
2215 //           continue;
2216 //         }
2217 //         std::vector<double> coords;
2218 //         coords.push_back(x);
2219 //         coords.push_back(y);
2220 //         coords.push_back(z);
2221 //         if (VerMap.find(coords) != VerMap.end()) {
2222 //           att.push_back(theNodeId2NodeIndexMap[node->GetID()]);
2223 //           continue;
2224 //         }
2225 //         VerTab.push_back(coords);
2226 //         VerMap.insert(coords);
2227 //         aGhs3dID++;
2228 //         theNodeId2NodeIndexMap.insert( make_pair( node->GetID(), aGhs3dID ));
2229 //         att.push_back(aGhs3dID);
2230 //       }
2231 //       if (isOK)
2232 //         tt.push_back(att);
2233 //     }
2234 //   }
2235 // 
2236 // 
2237 //   /* ========================== EDGES ========================== */
2238 // 
2239 //   if (theEnforcedEdges.size()) {
2240 //     // Iterate over the enforced edges
2241 //     std::cout << "Add " << theEnforcedEdges.size() << " enforced edges to input .mesh file" << std::endl;
2242 //     for(elemIt = theEnforcedEdges.begin() ; elemIt != theEnforcedEdges.end() ; ++elemIt) {
2243 //       aFace = (*elemIt);
2244 //       bool isOK = true;
2245 //       itOnSubFace = aFace->nodesIterator();
2246 //       aet.clear();
2247 //       for ( int j = 0; j < 2; ++j ) {
2248 //         node = castToNode( itOnSubFace->next() );
2249 //         if (( n2nDegenIt = n2nDegen.find( node )) != n2nDegen.end() )
2250 //           node = n2nDegenIt->second;
2251 //         double x = node->X();
2252 //         double y = node->Y();
2253 //         double z = node->Z();
2254 //         // Test if point is inside shape to mesh
2255 //         gp_Pnt myPoint(x,y,z);
2256 //         BRepClass3d_SolidClassifier scl(theMeshDS->ShapeToMesh());
2257 //         scl.Perform(myPoint, 1e-7);
2258 //         TopAbs_State result = scl.State();
2259 //         if ( result != TopAbs_IN ) {
2260 //           isOK = false;
2261 //           theEnforcedEdges.erase(elemIt);
2262 //           continue;
2263 //         }
2264 //         std::vector<double> coords;
2265 //         coords.push_back(x);
2266 //         coords.push_back(y);
2267 //         coords.push_back(z);
2268 //         if (VerMap.find(coords) != VerMap.end()) {
2269 //           aet.push_back(theNodeId2NodeIndexMap[node->GetID()]);
2270 //           continue;
2271 //         }
2272 //         VerTab.push_back(coords);
2273 //         VerMap.insert(coords);
2274 //         
2275 //         aGhs3dID++;
2276 //         theNodeId2NodeIndexMap.insert( make_pair( node->GetID(), aGhs3dID ));
2277 //         aet.push_back(aGhs3dID);
2278 //       }
2279 //       if (isOK)
2280 //         et.push_back(aet);
2281 //     }
2282 //   }
2283 // 
2284 // 
2285 //   /* Write vertices number */
2286 //   MESSAGE("Number of vertices: "<<aGhs3dID);
2287 //   MESSAGE("Size of vector: "<<VerTab.size());
2288 //   GmfSetKwd(idx, GmfVertices, aGhs3dID/*+solSize*/);
2289 //   for (int i=0;i<aGhs3dID;i++)
2290 //     GmfSetLin(idx, GmfVertices, VerTab[i][0], VerTab[i][1], VerTab[i][2], dummyint);
2291 // //   for (int i=0;i<solSize;i++) {
2292 // //     std::cout << ReqVerTab[i][0] <<" "<< ReqVerTab[i][1] << " "<< ReqVerTab[i][2] << std::endl;
2293 // //     GmfSetLin(idx, GmfVertices, ReqVerTab[i][0], ReqVerTab[i][1], ReqVerTab[i][2], dummyint);
2294 // //   }
2295 // 
2296 //   if (solSize) {
2297 //     idxRequired = GmfOpenMesh(theRequiredFileName, GmfWrite, GMFVERSION, GMFDIMENSION);
2298 //     if (!idxRequired) {
2299 //       GmfCloseMesh(idx);
2300 //       return false;
2301 //     }
2302 //     idxSol = GmfOpenMesh(theSolFileName, GmfWrite, GMFVERSION, GMFDIMENSION);
2303 //     if (!idxSol){
2304 //       GmfCloseMesh(idx);
2305 //       if (idxRequired)
2306 //         GmfCloseMesh(idxRequired);
2307 //       return false;
2308 //     }
2309 //     
2310 //     int TypTab[] = {GmfSca};
2311 //     GmfSetKwd(idxRequired, GmfVertices, solSize);
2312 //     GmfSetKwd(idxSol, GmfSolAtVertices, solSize, 1, TypTab);
2313 //     
2314 //     for (int i=0;i<solSize;i++) {
2315 //       double solTab[] = {enfVertexSizes.at(i)};
2316 //       GmfSetLin(idxRequired, GmfVertices, ReqVerTab[i][0], ReqVerTab[i][1], ReqVerTab[i][2], dummyint);
2317 //       GmfSetLin(idxSol, GmfSolAtVertices, solTab);
2318 //     }
2319 //     GmfCloseMesh(idxRequired);
2320 //     GmfCloseMesh(idxSol);
2321 //   }
2322 //   
2323 //   /* Write triangles number */
2324 //   if (tt.size()) {
2325 //     GmfSetKwd(idx, GmfTriangles, tt.size());
2326 //     for (int i=0;i<tt.size();i++)
2327 //       GmfSetLin(idx, GmfTriangles, tt[i][0], tt[i][1], tt[i][2], dummyint);
2328 //   }  
2329 //   
2330 //   /* Write edges number */
2331 //   if (et.size()) {
2332 //     GmfSetKwd(idx, GmfEdges, et.size());
2333 //     for (int i=0;i<et.size();i++)
2334 //       GmfSetLin(idx, GmfEdges, et[i][0], et[i][1], dummyint);
2335 //   }
2336 // 
2337 //   /* QUADRANGLES ========================== */
2338 //   // TODO: add pyramids ?
2339 // //   if (nbQuadrangles) {
2340 // //     for ( int i = 1; i <= quadranglesMap.Extent(); i++ )
2341 // //     {
2342 // //       aShape = quadranglesMap(i);
2343 // //       theSubMesh = theProxyMesh.GetSubMesh(aShape);
2344 // //       if ( !theSubMesh ) continue;
2345 // //       itOnSubMesh = theSubMesh->GetElements();
2346 // //       for ( int j = 0; j < 4; ++j )
2347 // //       {
2348 // //         aFace = itOnSubMesh->next();
2349 // //         itOnSubFace = aFace->nodesIterator();
2350 // //         aqt.clear();
2351 // //         while ( itOnSubFace->more() ) {
2352 // //           // find GHS3D ID
2353 // //           aSmdsID = itOnSubFace->next()->GetID();
2354 // //           itOnMap = theSmdsToGhs3dIdMap.find( aSmdsID );
2355 // //           ASSERT( itOnMap != theSmdsToGhs3dIdMap.end() );
2356 // //           aqt.push_back((*itOnMap).second);
2357 // //         }
2358 // //         qt.push_back(aqt);
2359 // //       }
2360 // //     }
2361 // //   }
2362 // // 
2363 // //   if (theEnforcedQuadrangles.size()) {
2364 // //     // Iterate over the enforced triangles
2365 // //     for(elemIt = theEnforcedQuadrangles.begin() ; elemIt != theEnforcedQuadrangles.end() ; ++elemIt) {
2366 // //       aFace = (*elemIt);
2367 // //       bool isOK = true;
2368 // //       itOnSubFace = aFace->nodesIterator();
2369 // //       aqt.clear();
2370 // //       for ( int j = 0; j < 4; ++j ) {
2371 // //         int aNodeID = itOnSubFace->next()->GetID();
2372 // //         itOnMap = theNodeId2NodeIndexMap.find(aNodeID);
2373 // //         if (itOnMap != theNodeId2NodeIndexMap.end())
2374 // //           aqt.push_back((*itOnMap).second);
2375 // //         else {
2376 // //           isOK = false;
2377 // //           theEnforcedQuadrangles.erase(elemIt);
2378 // //           break;
2379 // //         }
2380 // //       }
2381 // //       if (isOK)
2382 // //         qt.push_back(aqt);
2383 // //     }
2384 // //   }
2385 // //  
2386 //   
2387 // //   /* Write quadrilaterals number */
2388 // //   if (qt.size()) {
2389 // //     GmfSetKwd(idx, GmfQuadrilaterals, qt.size());
2390 // //     for (int i=0;i<qt.size();i++)
2391 // //       GmfSetLin(idx, GmfQuadrilaterals, qt[i][0], qt[i][1], qt[i][2], qt[i][3], dummyint);
2392 // //   }
2393 // 
2394 //   GmfCloseMesh(idx);
2395 //   return true;
2396 // }
2397
2398
2399 //=======================================================================
2400 //function : writeFaces
2401 //purpose  : 
2402 //=======================================================================
2403
2404 static bool writeFaces (ofstream &              theFile,
2405                         const SMESH_ProxyMesh&  theMesh,
2406                         const TopoDS_Shape&     theShape,
2407                         const map <int,int> &   theSmdsToGhs3dIdMap,
2408                         const map <int,int> &   theEnforcedNodeIdToGhs3dIdMap,
2409                         GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedEdges,
2410                         GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedTriangles)
2411 {
2412   // record structure:
2413   //
2414   // NB_ELEMS DUMMY_INT
2415   // Loop from 1 to NB_ELEMS
2416   // NB_NODES NODE_NB_1 NODE_NB_2 ... (NB_NODES + 1) times: DUMMY_INT
2417
2418   TopoDS_Shape aShape;
2419   const SMESHDS_SubMesh* theSubMesh;
2420   const SMDS_MeshElement* aFace;
2421   const char* space    = "  ";
2422   const int   dummyint = 0;
2423   map<int,int>::const_iterator itOnMap;
2424   SMDS_ElemIteratorPtr itOnSubMesh, itOnSubFace;
2425   int nbNodes, aSmdsID;
2426
2427   TIDSortedElemSet::const_iterator elemIt;
2428   int nbEnforcedEdges       = theEnforcedEdges.size();
2429   int nbEnforcedTriangles   = theEnforcedTriangles.size();
2430
2431   // count triangles bound to geometry
2432   int nbTriangles = 0;
2433
2434   TopTools_IndexedMapOfShape facesMap, trianglesMap;
2435   TopExp::MapShapes( theShape, TopAbs_FACE, facesMap );
2436   
2437   int nbFaces = facesMap.Extent();
2438
2439   for ( int i = 1; i <= nbFaces; ++i )
2440     if (( theSubMesh  = theMesh.GetSubMesh( facesMap(i))))
2441       nbTriangles += theSubMesh->NbElements();
2442   std::string tmpStr;
2443   (nbFaces == 0 || nbFaces == 1) ? tmpStr = " shape " : tmpStr = " shapes " ;
2444   std::cout << "    " << nbFaces << tmpStr << "of 2D dimension";
2445   int nbEnforcedElements = nbEnforcedEdges+nbEnforcedTriangles;
2446   if (nbEnforcedElements > 0) {
2447     (nbEnforcedElements == 1) ? tmpStr = "shape:" : tmpStr = "shapes:";
2448     std::cout << " and" << std::endl;
2449     std::cout << "    " << nbEnforcedElements 
2450                         << " enforced " << tmpStr << std::endl;
2451   }
2452   else
2453     std::cout << std::endl;
2454   if (nbEnforcedEdges) {
2455     (nbEnforcedEdges == 1) ? tmpStr = "edge" : tmpStr = "edges";
2456     std::cout << "      " << nbEnforcedEdges << " enforced " << tmpStr << std::endl;
2457   }
2458   if (nbEnforcedTriangles) {
2459     (nbEnforcedTriangles == 1) ? tmpStr = "triangle" : tmpStr = "triangles";
2460     std::cout << "      " << nbEnforcedTriangles << " enforced " << tmpStr << std::endl;
2461   }
2462   std::cout << std::endl;
2463
2464 //   theFile << space << nbTriangles << space << dummyint << std::endl;
2465   std::ostringstream globalStream, localStream, aStream;
2466
2467   for ( int i = 1; i <= facesMap.Extent(); i++ )
2468   {
2469     aShape = facesMap(i);
2470     theSubMesh = theMesh.GetSubMesh(aShape);
2471     if ( !theSubMesh ) continue;
2472     itOnSubMesh = theSubMesh->GetElements();
2473     while ( itOnSubMesh->more() )
2474     {
2475       aFace = itOnSubMesh->next();
2476       nbNodes = aFace->NbCornerNodes();
2477
2478       localStream << nbNodes << space;
2479
2480       itOnSubFace = aFace->nodesIterator();
2481       for ( int j = 0; j < 3; ++j ) {
2482         // find GHS3D ID
2483         aSmdsID = itOnSubFace->next()->GetID();
2484         itOnMap = theSmdsToGhs3dIdMap.find( aSmdsID );
2485         // if ( itOnMap == theSmdsToGhs3dIdMap.end() ) {
2486         //   cout << "not found node: " << aSmdsID << endl;
2487         //   return false;
2488         // }
2489         ASSERT( itOnMap != theSmdsToGhs3dIdMap.end() );
2490
2491         localStream << (*itOnMap).second << space ;
2492       }
2493
2494       // (NB_NODES + 1) times: DUMMY_INT
2495       for ( int j=0; j<=nbNodes; j++)
2496         localStream << dummyint << space ;
2497
2498       localStream << std::endl;
2499     }
2500   }
2501   
2502   globalStream << localStream.str();
2503   localStream.str("");
2504
2505   //
2506   //        FACES : END
2507   //
2508
2509 //   //
2510 //   //        ENFORCED EDGES : BEGIN
2511 //   //
2512 //   
2513 //   // Iterate over the enforced edges
2514 //   int usedEnforcedEdges = 0;
2515 //   bool isOK;
2516 //   for(elemIt = theEnforcedEdges.begin() ; elemIt != theEnforcedEdges.end() ; ++elemIt) {
2517 //     aFace = (*elemIt);
2518 //     isOK = true;
2519 //     itOnSubFace = aFace->nodesIterator();
2520 //     aStream.str("");
2521 //     aStream << "2" << space ;
2522 //     for ( int j = 0; j < 2; ++j ) {
2523 //       aSmdsID = itOnSubFace->next()->GetID();
2524 //       itOnMap = theEnforcedNodeIdToGhs3dIdMap.find(aSmdsID);
2525 //       if (itOnMap != theEnforcedNodeIdToGhs3dIdMap.end())
2526 //         aStream << (*itOnMap).second << space;
2527 //       else {
2528 //         isOK = false;
2529 //         break;
2530 //       }
2531 //     }
2532 //     if (isOK) {
2533 //       for ( int j=0; j<=2; j++)
2534 //         aStream << dummyint << space ;
2535 // //       aStream << dummyint << space << dummyint;
2536 //       localStream << aStream.str() << std::endl;
2537 //       usedEnforcedEdges++;
2538 //     }
2539 //   }
2540 //   
2541 //   if (usedEnforcedEdges) {
2542 //     globalStream << localStream.str();
2543 //     localStream.str("");
2544 //   }
2545 // 
2546 //   //
2547 //   //        ENFORCED EDGES : END
2548 //   //
2549 //   //
2550 // 
2551 //   //
2552 //   //        ENFORCED TRIANGLES : BEGIN
2553 //   //
2554 //     // Iterate over the enforced triangles
2555 //   int usedEnforcedTriangles = 0;
2556 //   for(elemIt = theEnforcedTriangles.begin() ; elemIt != theEnforcedTriangles.end() ; ++elemIt) {
2557 //     aFace = (*elemIt);
2558 //     nbNodes = aFace->NbCornerNodes();
2559 //     isOK = true;
2560 //     itOnSubFace = aFace->nodesIterator();
2561 //     aStream.str("");
2562 //     aStream << nbNodes << space ;
2563 //     for ( int j = 0; j < 3; ++j ) {
2564 //       aSmdsID = itOnSubFace->next()->GetID();
2565 //       itOnMap = theEnforcedNodeIdToGhs3dIdMap.find(aSmdsID);
2566 //       if (itOnMap != theEnforcedNodeIdToGhs3dIdMap.end())
2567 //         aStream << (*itOnMap).second << space;
2568 //       else {
2569 //         isOK = false;
2570 //         break;
2571 //       }
2572 //     }
2573 //     if (isOK) {
2574 //       for ( int j=0; j<=3; j++)
2575 //         aStream << dummyint << space ;
2576 //       localStream << aStream.str() << std::endl;
2577 //       usedEnforcedTriangles++;
2578 //     }
2579 //   }
2580 //   
2581 //   if (usedEnforcedTriangles) {
2582 //     globalStream << localStream.str();
2583 //     localStream.str("");
2584 //   }
2585 // 
2586 //   //
2587 //   //        ENFORCED TRIANGLES : END
2588 //   //
2589   
2590   theFile
2591   << nbTriangles/*+usedEnforcedTriangles+usedEnforcedEdges*/
2592   << " 0" << std::endl
2593   << globalStream.str();
2594
2595   return true;
2596 }
2597
2598 //=======================================================================
2599 //function : writePoints
2600 //purpose  : 
2601 //=======================================================================
2602
2603 static bool writePoints (ofstream &                       theFile,
2604                          SMESH_MesherHelper&              theHelper,
2605                          map <int,int> &                  theSmdsToGhs3dIdMap,
2606                          map <int,int> &                  theEnforcedNodeIdToGhs3dIdMap,
2607                          map <int,const SMDS_MeshNode*> & theGhs3dIdToNodeMap,
2608                          GHS3DPlugin_Hypothesis::TID2SizeMap & theNodeIDToSizeMap,
2609                          GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues & theEnforcedVertices,
2610                          GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap & theEnforcedNodes,
2611                          GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedEdges,
2612                          GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedTriangles)
2613 {
2614   // record structure:
2615   //
2616   // NB_NODES
2617   // Loop from 1 to NB_NODES
2618   //   X Y Z DUMMY_INT
2619
2620   SMESHDS_Mesh * theMeshDS = theHelper.GetMeshDS();
2621   int nbNodes = theMeshDS->NbNodes();
2622   if ( nbNodes == 0 )
2623     return false;
2624   
2625   int nbEnforcedVertices = theEnforcedVertices.size();
2626   int nbEnforcedNodes    = theEnforcedNodes.size();
2627   
2628   const TopoDS_Shape shapeToMesh = theMeshDS->ShapeToMesh();
2629   
2630   int aGhs3dID = 1;
2631   SMDS_NodeIteratorPtr nodeIt = theMeshDS->nodesIterator();
2632   const SMDS_MeshNode* node;
2633
2634   // Issue 020674: EDF 870 SMESH: Mesh generated by Netgen not usable by GHS3D
2635   // The problem is in nodes on degenerated edges, we need to skip nodes which are free
2636   // and replace not-free nodes on degenerated edges by the node on vertex
2637   TNodeNodeMap n2nDegen; // map a node on degenerated edge to a node on vertex
2638   TNodeNodeMap::iterator n2nDegenIt;
2639   if ( theHelper.HasDegeneratedEdges() )
2640   {
2641     set<int> checkedSM;
2642     for (TopExp_Explorer e(theMeshDS->ShapeToMesh(), TopAbs_EDGE ); e.More(); e.Next())
2643     {
2644       SMESH_subMesh* sm = theHelper.GetMesh()->GetSubMesh( e.Current() );
2645       if ( checkedSM.insert( sm->GetId() ).second && theHelper.IsDegenShape(sm->GetId() ))
2646       {
2647         if ( SMESHDS_SubMesh* smDS = sm->GetSubMeshDS() )
2648         {
2649           TopoDS_Shape vertex = TopoDS_Iterator( e.Current() ).Value();
2650           const SMDS_MeshNode* vNode = SMESH_Algo::VertexNode( TopoDS::Vertex( vertex ), theMeshDS);
2651           {
2652             SMDS_NodeIteratorPtr nIt = smDS->GetNodes();
2653             while ( nIt->more() )
2654               n2nDegen.insert( make_pair( nIt->next(), vNode ));
2655           }
2656         }
2657       }
2658     }
2659     nbNodes -= n2nDegen.size();
2660   }
2661
2662   const bool isQuadMesh = 
2663     theHelper.GetMesh()->NbEdges( ORDER_QUADRATIC ) ||
2664     theHelper.GetMesh()->NbFaces( ORDER_QUADRATIC ) ||
2665     theHelper.GetMesh()->NbVolumes( ORDER_QUADRATIC );
2666   if ( isQuadMesh )
2667   {
2668     // descrease nbNodes by nb of medium nodes
2669     while ( nodeIt->more() )
2670     {
2671       node = nodeIt->next();
2672       if ( !theHelper.IsDegenShape( node->getshapeId() ))
2673         nbNodes -= int( theHelper.IsMedium( node ));
2674     }
2675     nodeIt = theMeshDS->nodesIterator();
2676   }
2677
2678   const char* space    = "  ";
2679   const int   dummyint = 0;
2680
2681   std::string tmpStr;
2682   (nbNodes == 0 || nbNodes == 1) ? tmpStr = " node" : tmpStr = " nodes";
2683   // NB_NODES
2684   std::cout << std::endl;
2685   std::cout << "The initial 2D mesh contains :" << std::endl;
2686   std::cout << "    " << nbNodes << tmpStr << std::endl;
2687   if (nbEnforcedVertices > 0) {
2688     (nbEnforcedVertices == 1) ? tmpStr = "vertex" : tmpStr = "vertices";
2689     std::cout << "    " << nbEnforcedVertices << " enforced " << tmpStr << std::endl;
2690   }
2691   if (nbEnforcedNodes > 0) {
2692     (nbEnforcedNodes == 1) ? tmpStr = "node" : tmpStr = "nodes";
2693     std::cout << "    " << nbEnforcedNodes << " enforced " << tmpStr << std::endl;
2694   }
2695   std::cout << std::endl;
2696   std::cout << "Start writing in 'points' file ..." << std::endl;
2697
2698   theFile << nbNodes << std::endl;
2699
2700   // Loop from 1 to NB_NODES
2701
2702   while ( nodeIt->more() )
2703   {
2704     node = nodeIt->next();
2705     if ( isQuadMesh && theHelper.IsMedium( node )) // Issue 0021238
2706       continue;
2707     if ( n2nDegen.count( node ) ) // Issue 0020674
2708       continue;
2709
2710     theSmdsToGhs3dIdMap.insert( make_pair( node->GetID(), aGhs3dID ));
2711     theGhs3dIdToNodeMap.insert( make_pair( aGhs3dID, node ));
2712     aGhs3dID++;
2713
2714     // X Y Z DUMMY_INT
2715     theFile
2716     << node->X() << space 
2717     << node->Y() << space 
2718     << node->Z() << space 
2719     << dummyint;
2720
2721     theFile << std::endl;
2722
2723   }
2724   
2725   // Iterate over the enforced nodes
2726   std::map<int,double> enfVertexIndexSizeMap;
2727   if (nbEnforcedNodes) {
2728     GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap::const_iterator nodeIt = theEnforcedNodes.begin();
2729     for( ; nodeIt != theEnforcedNodes.end() ; ++nodeIt) {
2730       double x = nodeIt->first->X();
2731       double y = nodeIt->first->Y();
2732       double z = nodeIt->first->Z();
2733       // Test if point is inside shape to mesh
2734       gp_Pnt myPoint(x,y,z);
2735       BRepClass3d_SolidClassifier scl(shapeToMesh);
2736       scl.Perform(myPoint, 1e-7);
2737       TopAbs_State result = scl.State();
2738       if ( result != TopAbs_IN )
2739         continue;
2740       std::vector<double> coords;
2741       coords.push_back(x);
2742       coords.push_back(y);
2743       coords.push_back(z);
2744       if (theEnforcedVertices.find(coords) != theEnforcedVertices.end())
2745         continue;
2746         
2747 //      double size = theNodeIDToSizeMap.find(nodeIt->first->GetID())->second;
2748   //       theGhs3dIdToNodeMap.insert( make_pair( nbNodes + i, (*nodeIt) ));
2749   //       MESSAGE("Adding enforced node (" << x << "," << y <<"," << z << ")");
2750       // X Y Z PHY_SIZE DUMMY_INT
2751       theFile
2752       << x << space 
2753       << y << space 
2754       << z << space
2755       << -1 << space
2756       << dummyint << space;
2757       theFile << std::endl;
2758       theEnforcedNodeIdToGhs3dIdMap.insert( make_pair( nodeIt->first->GetID(), aGhs3dID ));
2759       enfVertexIndexSizeMap[aGhs3dID] = -1;
2760       aGhs3dID++;
2761   //     else
2762   //         MESSAGE("Enforced vertex (" << x << "," << y <<"," << z << ") is not inside the geometry: it was not added ");
2763     }
2764   }
2765   
2766   if (nbEnforcedVertices) {
2767     // Iterate over the enforced vertices
2768     GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues::const_iterator vertexIt = theEnforcedVertices.begin();
2769     for( ; vertexIt != theEnforcedVertices.end() ; ++vertexIt) {
2770       double x = vertexIt->first[0];
2771       double y = vertexIt->first[1];
2772       double z = vertexIt->first[2];
2773       // Test if point is inside shape to mesh
2774       gp_Pnt myPoint(x,y,z);
2775       BRepClass3d_SolidClassifier scl(shapeToMesh);
2776       scl.Perform(myPoint, 1e-7);
2777       TopAbs_State result = scl.State();
2778       if ( result != TopAbs_IN )
2779         continue;
2780       MESSAGE("Adding enforced vertex (" << x << "," << y <<"," << z << ") = " << vertexIt->second);
2781       // X Y Z PHY_SIZE DUMMY_INT
2782       theFile
2783       << x << space 
2784       << y << space 
2785       << z << space
2786       << vertexIt->second << space 
2787       << dummyint << space;
2788       theFile << std::endl;
2789       enfVertexIndexSizeMap[aGhs3dID] = vertexIt->second;
2790       aGhs3dID++;
2791     }
2792   }
2793   
2794   
2795   std::cout << std::endl;
2796   std::cout << "End writing in 'points' file." << std::endl;
2797
2798   return true;
2799 }
2800
2801 //=======================================================================
2802 //function : readResultFile
2803 //purpose  : readResultFile with geometry
2804 //=======================================================================
2805
2806 static bool readResultFile(const int                       fileOpen,
2807 #ifdef WNT
2808                            const char*                     fileName,
2809 #endif
2810 #ifdef WITH_SMESH_CANCEL_COMPUTE
2811                            GHS3DPlugin_GHS3D*              theAlgo,
2812 #endif
2813                            SMESH_MesherHelper&             theHelper,
2814                            TopoDS_Shape                    tabShape[],
2815                            double**                        tabBox,
2816                            const int                       nbShape,
2817                            map <int,const SMDS_MeshNode*>& theGhs3dIdToNodeMap,
2818                            std::map <int,int> &            theNodeId2NodeIndexMap,
2819                            bool                            toMeshHoles,
2820                            int                             nbEnforcedVertices,
2821                            int                             nbEnforcedNodes,
2822                            GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedEdges,
2823                            GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedTriangles)
2824 {
2825   MESSAGE("GHS3DPlugin_GHS3D::readResultFile()");
2826   Kernel_Utils::Localizer loc;
2827   struct stat status;
2828   size_t      length;
2829   
2830   std::string tmpStr;
2831
2832   char *ptr, *mapPtr;
2833   char *tetraPtr;
2834   char *shapePtr;
2835
2836   SMESHDS_Mesh* theMeshDS = theHelper.GetMeshDS();
2837
2838   int nbElems, nbNodes, nbInputNodes;
2839   int nbTriangle;
2840   int ID, shapeID, ghs3dShapeID;
2841   int IdShapeRef = 1;
2842   int compoundID =
2843     nbShape ? theMeshDS->ShapeToIndex( tabShape[0] ) : theMeshDS->ShapeToIndex( theMeshDS->ShapeToMesh() );
2844
2845   int *tab, *tabID, *nodeID, *nodeAssigne;
2846   double *coord;
2847   const SMDS_MeshNode **node;
2848
2849   tab    = new int[3];
2850   nodeID = new int[4];
2851   coord  = new double[3];
2852   node   = new const SMDS_MeshNode*[4];
2853
2854   TopoDS_Shape aSolid;
2855   SMDS_MeshNode * aNewNode;
2856   map <int,const SMDS_MeshNode*>::iterator itOnNode;
2857   SMDS_MeshElement* aTet;
2858 #ifdef _DEBUG_
2859   set<int> shapeIDs;
2860 #endif
2861
2862   // Read the file state
2863   fstat(fileOpen, &status);
2864   length   = status.st_size;
2865
2866   // Mapping the result file into memory
2867 #ifdef WNT
2868   HANDLE fd = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ,
2869                          NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
2870   HANDLE hMapObject = CreateFileMapping(fd, NULL, PAGE_READONLY,
2871                                         0, (DWORD)length, NULL);
2872   ptr = ( char* ) MapViewOfFile(hMapObject, FILE_MAP_READ, 0, 0, 0 );
2873 #else
2874   ptr = (char *) mmap(0,length,PROT_READ,MAP_PRIVATE,fileOpen,0);
2875 #endif
2876   mapPtr = ptr;
2877
2878   ptr      = readMapIntLine(ptr, tab);
2879   tetraPtr = ptr;
2880
2881   nbElems      = tab[0];
2882   nbNodes      = tab[1];
2883   nbInputNodes = tab[2];
2884
2885   nodeAssigne = new int[ nbNodes+1 ];
2886
2887   if (nbShape > 0)
2888     aSolid = tabShape[0];
2889
2890   // Reading the nodeId
2891   for (int i=0; i < 4*nbElems; i++)
2892     strtol(ptr, &ptr, 10);
2893
2894   MESSAGE("nbInputNodes: "<<nbInputNodes);
2895   MESSAGE("nbEnforcedVertices: "<<nbEnforcedVertices);
2896   MESSAGE("nbEnforcedNodes: "<<nbEnforcedNodes);
2897   // Reading the nodeCoor and update the nodeMap
2898   for (int iNode=1; iNode <= nbNodes; iNode++) {
2899 #ifdef WITH_SMESH_CANCEL_COMPUTE
2900     if(theAlgo->computeCanceled())
2901       return false;
2902 #endif
2903     for (int iCoor=0; iCoor < 3; iCoor++)
2904       coord[ iCoor ] = strtod(ptr, &ptr);
2905     nodeAssigne[ iNode ] = 1;
2906     if ( iNode > (nbInputNodes-(nbEnforcedVertices+nbEnforcedNodes)) ) {
2907       // Creating SMESH nodes
2908       // - for enforced vertices
2909       // - for vertices of forced edges
2910       // - for ghs3d nodes
2911       nodeAssigne[ iNode ] = 0;
2912       aNewNode = theMeshDS->AddNode( coord[0],coord[1],coord[2] );
2913       theGhs3dIdToNodeMap.insert(theGhs3dIdToNodeMap.end(), make_pair( iNode, aNewNode ));
2914     }
2915   }
2916
2917   // Reading the number of triangles which corresponds to the number of sub-domains
2918   nbTriangle = strtol(ptr, &ptr, 10);
2919
2920   tabID = new int[nbTriangle];
2921   for (int i=0; i < nbTriangle; i++) {
2922 #ifdef WITH_SMESH_CANCEL_COMPUTE
2923     if(theAlgo->computeCanceled())
2924       return false;
2925 #endif
2926     tabID[i] = 0;
2927     // find the solid corresponding to GHS3D sub-domain following
2928     // the technique proposed in GHS3D manual in chapter
2929     // "B.4 Subdomain (sub-region) assignment"
2930     int nodeId1 = strtol(ptr, &ptr, 10);
2931     int nodeId2 = strtol(ptr, &ptr, 10);
2932     int nodeId3 = strtol(ptr, &ptr, 10);
2933     if ( nbTriangle > 1 ) {
2934       const SMDS_MeshNode* n1 = theGhs3dIdToNodeMap[ nodeId1 ];
2935       const SMDS_MeshNode* n2 = theGhs3dIdToNodeMap[ nodeId2 ];
2936       const SMDS_MeshNode* n3 = theGhs3dIdToNodeMap[ nodeId3 ];
2937       if (!n1 || !n2 || !n3) {
2938         tabID[i] = HOLE_ID;
2939         continue;
2940       }
2941       try {
2942         OCC_CATCH_SIGNALS;
2943 //         tabID[i] = findShapeID( theHelper, n1, n2, n3, toMeshHoles );
2944         tabID[i] = findShapeID( *theHelper.GetMesh(), n1, n2, n3, toMeshHoles );
2945         // -- 0020330: Pb with ghs3d as a submesh
2946         // check that found shape is to be meshed
2947         if ( tabID[i] > 0 ) {
2948           const TopoDS_Shape& foundShape = theMeshDS->IndexToShape( tabID[i] );
2949           bool isToBeMeshed = false;
2950           for ( int iS = 0; !isToBeMeshed && iS < nbShape; ++iS )
2951             isToBeMeshed = foundShape.IsSame( tabShape[ iS ]);
2952           if ( !isToBeMeshed )
2953             tabID[i] = HOLE_ID;
2954         }
2955         // END -- 0020330: Pb with ghs3d as a submesh
2956 #ifdef _DEBUG_
2957         std::cout << i+1 << " subdomain: findShapeID() returns " << tabID[i] << std::endl;
2958 #endif
2959       }
2960       catch ( Standard_Failure & ex)
2961       {
2962 #ifdef _DEBUG_
2963         std::cout << i+1 << " subdomain: Exception caugt: " << ex.GetMessageString() << std::endl;
2964 #endif
2965       }
2966       catch (...) {
2967 #ifdef _DEBUG_
2968         std::cout << i+1 << " subdomain: unknown exception caught " << std::endl;
2969 #endif
2970       }
2971     }
2972   }
2973
2974   shapePtr = ptr;
2975
2976   if ( nbTriangle <= nbShape ) // no holes
2977     toMeshHoles = true; // not avoid creating tetras in holes
2978
2979   // Associating the tetrahedrons to the shapes
2980   shapeID = compoundID;
2981   for (int iElem = 0; iElem < nbElems; iElem++) {
2982 #ifdef WITH_SMESH_CANCEL_COMPUTE
2983     if(theAlgo->computeCanceled())
2984       return false;
2985 #endif
2986     for (int iNode = 0; iNode < 4; iNode++) {
2987       ID = strtol(tetraPtr, &tetraPtr, 10);
2988       itOnNode = theGhs3dIdToNodeMap.find(ID);
2989       node[ iNode ] = itOnNode->second;
2990       nodeID[ iNode ] = ID;
2991     }
2992     // We always run GHS3D with "to mesh holes"==TRUE but we must not create
2993     // tetras within holes depending on hypo option,
2994     // so we first check if aTet is inside a hole and then create it 
2995     //aTet = theMeshDS->AddVolume( node[1], node[0], node[2], node[3] );
2996     if ( nbTriangle > 1 ) {
2997       shapeID = HOLE_ID; // negative shapeID means not to create tetras if !toMeshHoles
2998       ghs3dShapeID = strtol(shapePtr, &shapePtr, 10) - IdShapeRef;
2999       if ( tabID[ ghs3dShapeID ] == 0 ) {
3000         TopAbs_State state;
3001         aSolid = findShape(node, aSolid, tabShape, tabBox, nbShape, &state);
3002         if ( toMeshHoles || state == TopAbs_IN )
3003           shapeID = theMeshDS->ShapeToIndex( aSolid );
3004         tabID[ ghs3dShapeID ] = shapeID;
3005       }
3006       else
3007         shapeID = tabID[ ghs3dShapeID ];
3008     }
3009     else if ( nbShape > 1 ) {
3010       // Case where nbTriangle == 1 while nbShape == 2 encountered
3011       // with compound of 2 boxes and "To mesh holes"==False,
3012       // so there are no subdomains specified for each tetrahedron.
3013       // Try to guess a solid by a node already bound to shape
3014       shapeID = 0;
3015       for ( int i=0; i<4 && shapeID==0; i++ ) {
3016         if ( nodeAssigne[ nodeID[i] ] == 1 &&
3017              node[i]->GetPosition()->GetTypeOfPosition() == SMDS_TOP_3DSPACE &&
3018              node[i]->getshapeId() > 1 )
3019         {
3020           shapeID = node[i]->getshapeId();
3021         }
3022       }
3023       if ( shapeID==0 ) {
3024         aSolid = findShape(node, aSolid, tabShape, tabBox, nbShape);
3025         shapeID = theMeshDS->ShapeToIndex( aSolid );
3026       }
3027     }
3028     // set new nodes and tetrahedron onto the shape
3029     for ( int i=0; i<4; i++ ) {
3030       if ( nodeAssigne[ nodeID[i] ] == 0 ) {
3031         if ( shapeID != HOLE_ID )
3032           theMeshDS->SetNodeInVolume( node[i], shapeID );
3033         nodeAssigne[ nodeID[i] ] = shapeID;
3034       }
3035     }
3036     if ( toMeshHoles || shapeID != HOLE_ID ) {
3037       aTet = theHelper.AddVolume( node[1], node[0], node[2], node[3],
3038                                   /*id=*/0, /*force3d=*/false);
3039       theMeshDS->SetMeshElementOnShape( aTet, shapeID );
3040     }
3041 #ifdef _DEBUG_
3042     shapeIDs.insert( shapeID );
3043 #endif
3044   }
3045   
3046   // Add enforced elements
3047   GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap::const_iterator elemIt;
3048   const SMDS_MeshElement* anElem;
3049   SMDS_ElemIteratorPtr itOnEnfElem;
3050   map<int,int>::const_iterator itOnMap;
3051   shapeID = compoundID;
3052   // Enforced edges
3053   if (theEnforcedEdges.size()) {
3054     (theEnforcedEdges.size() <= 1) ? tmpStr = " enforced edge" : " enforced edges";
3055     std::cout << "Add " << theEnforcedEdges.size() << tmpStr << std::endl;
3056     std::vector< const SMDS_MeshNode* > node( 2 );
3057     // Iterate over the enforced edges
3058     for(elemIt = theEnforcedEdges.begin() ; elemIt != theEnforcedEdges.end() ; ++elemIt) {
3059       anElem = elemIt->first;
3060       bool addElem = true;
3061       itOnEnfElem = anElem->nodesIterator();
3062       for ( int j = 0; j < 2; ++j ) {
3063         int aNodeID = itOnEnfElem->next()->GetID();
3064         itOnMap = theNodeId2NodeIndexMap.find(aNodeID);
3065         if (itOnMap != theNodeId2NodeIndexMap.end()) {
3066           itOnNode = theGhs3dIdToNodeMap.find((*itOnMap).second);
3067           if (itOnNode != theGhs3dIdToNodeMap.end()) {
3068             node.push_back((*itOnNode).second);
3069 //             shapeID =(*itOnNode).second->getshapeId();
3070           }
3071           else
3072             addElem = false;
3073         }
3074         else
3075           addElem = false;
3076       }
3077       if (addElem) {
3078         aTet = theHelper.AddEdge( node[0], node[1], 0,  false);
3079         theMeshDS->SetMeshElementOnShape( aTet, shapeID );
3080       }
3081     }
3082   }
3083   // Enforced faces
3084   if (theEnforcedTriangles.size()) {
3085     (theEnforcedTriangles.size() <= 1) ? tmpStr = " enforced triangle" : " enforced triangles";
3086     std::cout << "Add " << theEnforcedTriangles.size() << " enforced triangles" << std::endl;
3087     std::vector< const SMDS_MeshNode* > node( 3 );
3088     // Iterate over the enforced triangles
3089     for(elemIt = theEnforcedTriangles.begin() ; elemIt != theEnforcedTriangles.end() ; ++elemIt) {
3090       anElem = elemIt->first;
3091       bool addElem = true;
3092       itOnEnfElem = anElem->nodesIterator();
3093       for ( int j = 0; j < 3; ++j ) {
3094         int aNodeID = itOnEnfElem->next()->GetID();
3095         itOnMap = theNodeId2NodeIndexMap.find(aNodeID);
3096         if (itOnMap != theNodeId2NodeIndexMap.end()) {
3097           itOnNode = theGhs3dIdToNodeMap.find((*itOnMap).second);
3098           if (itOnNode != theGhs3dIdToNodeMap.end()) {
3099             node.push_back((*itOnNode).second);
3100 //             shapeID =(*itOnNode).second->getshapeId();
3101           }
3102           else
3103             addElem = false;
3104         }
3105         else
3106           addElem = false;
3107       }
3108       if (addElem) {
3109         aTet = theHelper.AddFace( node[0], node[1], node[2], 0,  false);
3110         theMeshDS->SetMeshElementOnShape( aTet, shapeID );
3111       }
3112     }
3113   }
3114
3115   // Remove nodes of tetras inside holes if !toMeshHoles
3116   if ( !toMeshHoles ) {
3117     itOnNode = theGhs3dIdToNodeMap.find( nbInputNodes );
3118     for ( ; itOnNode != theGhs3dIdToNodeMap.end(); ++itOnNode) {
3119       ID = itOnNode->first;
3120       if ( nodeAssigne[ ID ] == HOLE_ID )
3121         theMeshDS->RemoveFreeNode( itOnNode->second, 0 );
3122     }
3123   }
3124
3125   
3126   if ( nbElems ) {
3127     (nbElems <= 1) ? tmpStr = " tetrahedra" : " tetrahedrons";
3128     cout << nbElems << tmpStr << " have been associated to " << nbShape;
3129     (nbShape <= 1) ? tmpStr = " shape" : " shapes";
3130     cout << tmpStr << endl;
3131   }
3132 #ifdef WNT
3133   UnmapViewOfFile(mapPtr);
3134   CloseHandle(hMapObject);
3135   CloseHandle(fd);
3136 #else
3137   munmap(mapPtr, length);
3138 #endif
3139   close(fileOpen);
3140
3141   delete [] tab;
3142   delete [] tabID;
3143   delete [] nodeID;
3144   delete [] coord;
3145   delete [] node;
3146   delete [] nodeAssigne;
3147
3148 #ifdef _DEBUG_
3149   shapeIDs.erase(-1);
3150   if ( shapeIDs.size() != nbShape ) {
3151     (shapeIDs.size() <= 1) ? tmpStr = " solid" : " solids";
3152     std::cout << "Only " << shapeIDs.size() << tmpStr << " of " << nbShape << " found" << std::endl;
3153     for (int i=0; i<nbShape; i++) {
3154       shapeID = theMeshDS->ShapeToIndex( tabShape[i] );
3155       if ( shapeIDs.find( shapeID ) == shapeIDs.end() )
3156         std::cout << "  Solid #" << shapeID << " not found" << std::endl;
3157     }
3158   }
3159 #endif
3160
3161   return true;
3162 }
3163
3164
3165 //=============================================================================
3166 /*!
3167  *Here we are going to use the GHS3D mesher with geometry
3168  */
3169 //=============================================================================
3170
3171 bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
3172                                 const TopoDS_Shape& theShape)
3173 {
3174   bool Ok(false);
3175   //SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
3176
3177   // we count the number of shapes
3178   // _nbShape = countShape( meshDS, TopAbs_SOLID ); -- 0020330: Pb with ghs3d as a submesh
3179   _nbShape = 0;
3180   TopExp_Explorer expBox ( theShape, TopAbs_SOLID );
3181   for ( ; expBox.More(); expBox.Next() )
3182     _nbShape++;
3183
3184   // create bounding box for every shape inside the compound
3185
3186   int iShape = 0;
3187   TopoDS_Shape* tabShape;
3188   double**      tabBox;
3189   tabShape = new TopoDS_Shape[_nbShape];
3190   tabBox   = new double*[_nbShape];
3191   for (int i=0; i<_nbShape; i++)
3192     tabBox[i] = new double[6];
3193   Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
3194
3195   for (expBox.ReInit(); expBox.More(); expBox.Next()) {
3196     tabShape[iShape] = expBox.Current();
3197     Bnd_Box BoundingBox;
3198     BRepBndLib::Add(expBox.Current(), BoundingBox);
3199     BoundingBox.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
3200     tabBox[iShape][0] = Xmin; tabBox[iShape][1] = Xmax;
3201     tabBox[iShape][2] = Ymin; tabBox[iShape][3] = Ymax;
3202     tabBox[iShape][4] = Zmin; tabBox[iShape][5] = Zmax;
3203     iShape++;
3204   }
3205
3206   // a unique working file name
3207   // to avoid access to the same files by eg different users
3208   TCollection_AsciiString aGenericName
3209     = (char*) GHS3DPlugin_Hypothesis::GetFileName(_hyp).c_str();
3210
3211   TCollection_AsciiString aResultFileName;
3212   TCollection_AsciiString aLogFileName    = aGenericName + ".log";    // log
3213   // The output .mesh file does not contain yet the subdomain-info (Ghs3D 4.2)
3214 //   TCollection_AsciiString aGMFFileName, aRequiredVerticesFileName, aSolFileName;
3215 //   TCollection_AsciiString aGenericNameRequired = aGenericName + "_required";
3216 // #ifdef _DEBUG_
3217 //   aGMFFileName    = aGenericName + ".mesh"; // GMF mesh file
3218 //   aResultFileName = aGenericName + "Vol.mesh"; // GMF mesh file
3219 //   aRequiredVerticesFileName    = aGenericNameRequired + ".mesh"; // GMF required vertices mesh file
3220 //   aSolFileName    = aGenericName + "_required.sol"; // GMF solution file
3221 // #else
3222 //   aGMFFileName    = aGenericName + ".meshb"; // GMF mesh file
3223 //   aResultFileName = aGenericName + "Vol.meshb"; // GMF mesh file
3224 //   aRequiredVerticesFileName    = aGenericNameRequired + ".meshb"; // GMF required vertices mesh file
3225 //   aSolFileName    = aGenericName + "_required.solb"; // GMF solution file
3226 // #endif
3227
3228   TCollection_AsciiString aFacesFileName, aPointsFileName, aBadResFileName, aBbResFileName;
3229
3230   aFacesFileName  = aGenericName + ".faces";  // in faces
3231   aPointsFileName = aGenericName + ".points"; // in points
3232   aResultFileName = aGenericName + ".noboite";// out points and volumes
3233   aBadResFileName = aGenericName + ".boite";  // out bad result
3234   aBbResFileName  = aGenericName + ".bb";     // out vertex stepsize
3235   
3236   // -----------------
3237   // make input files
3238   // -----------------
3239
3240   ofstream aFacesFile  ( aFacesFileName.ToCString()  , ios::out);
3241   ofstream aPointsFile ( aPointsFileName.ToCString() , ios::out);
3242
3243   Ok =
3244     aFacesFile.rdbuf()->is_open() && aPointsFile.rdbuf()->is_open();
3245   if (!Ok) {
3246     INFOS( "Can't write into " << aFacesFileName);
3247     return error(SMESH_Comment("Can't write into ") << aFacesFileName);
3248   }
3249
3250   std::map <int,int> aNodeId2NodeIndexMap, aSmdsToGhs3dIdMap, anEnforcedNodeIdToGhs3dIdMap;
3251   std::map <int,const SMDS_MeshNode*> aGhs3dIdToNodeMap;
3252   std::map <int, int> nodeID2nodeIndexMap;
3253   GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues coordsSizeMap = GHS3DPlugin_Hypothesis::GetEnforcedVerticesCoordsSize(_hyp);
3254   GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap enforcedNodes = GHS3DPlugin_Hypothesis::GetEnforcedNodes(_hyp);
3255   GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap enforcedEdges = GHS3DPlugin_Hypothesis::GetEnforcedEdges(_hyp);
3256   GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap enforcedTriangles = GHS3DPlugin_Hypothesis::GetEnforcedTriangles(_hyp);
3257 //   TIDSortedElemSet enforcedQuadrangles = GHS3DPlugin_Hypothesis::GetEnforcedQuadrangles(_hyp);
3258   GHS3DPlugin_Hypothesis::TID2SizeMap nodeIDToSizeMap = GHS3DPlugin_Hypothesis::GetNodeIDToSizeMap(_hyp);
3259
3260   int nbEnforcedVertices = coordsSizeMap.size();
3261   int nbEnforcedNodes = enforcedNodes.size();
3262   
3263   std::string tmpStr;
3264   (nbEnforcedNodes <= 1) ? tmpStr = "node" : "nodes";
3265   std::cout << nbEnforcedNodes << " enforced " << tmpStr << " from hypo" << std::endl;
3266   (nbEnforcedVertices <= 1) ? tmpStr = "vertex" : "vertices";
3267   std::cout << nbEnforcedVertices << " enforced " << tmpStr << " from hypo" << std::endl;
3268   
3269   SMESH_MesherHelper helper( theMesh );
3270   helper.SetSubShape( theShape );
3271
3272   {
3273     SMESH_ProxyMesh::Ptr proxyMesh( new SMESH_ProxyMesh( theMesh ));
3274
3275     // make prisms on quadrangles
3276     if ( theMesh.NbQuadrangles() > 0 )
3277     {
3278       vector<SMESH_ProxyMesh::Ptr> components;
3279       for (expBox.ReInit(); expBox.More(); expBox.Next())
3280       {
3281         if ( _viscousLayersHyp )
3282         {
3283           proxyMesh = _viscousLayersHyp->Compute( theMesh, expBox.Current() );
3284           if ( !proxyMesh )
3285             return false;
3286         }
3287         StdMeshers_QuadToTriaAdaptor* q2t = new StdMeshers_QuadToTriaAdaptor;
3288         q2t->Compute( theMesh, expBox.Current(), proxyMesh.get() );
3289         components.push_back( SMESH_ProxyMesh::Ptr( q2t ));
3290       }
3291       proxyMesh.reset( new SMESH_ProxyMesh( components ));
3292     }
3293     // build viscous layers
3294     else if ( _viscousLayersHyp )
3295     {
3296       proxyMesh = _viscousLayersHyp->Compute( theMesh, theShape );
3297       if ( !proxyMesh )
3298         return false;
3299     }
3300
3301     Ok = (writePoints( aPointsFile, helper, 
3302                        aSmdsToGhs3dIdMap, anEnforcedNodeIdToGhs3dIdMap, aGhs3dIdToNodeMap, 
3303                        nodeIDToSizeMap,
3304                        coordsSizeMap, enforcedNodes, enforcedEdges, enforcedTriangles)
3305           &&
3306           writeFaces ( aFacesFile, *proxyMesh, theShape, 
3307                        aSmdsToGhs3dIdMap, anEnforcedNodeIdToGhs3dIdMap,
3308                        enforcedEdges, enforcedTriangles ));
3309 //     Ok = writeGMFFile(aGMFFileName.ToCString(), aRequiredVerticesFileName.ToCString(), aSolFileName.ToCString(),
3310 //                       helper, *proxyMesh,
3311 //                       aNodeId2NodeIndexMap, aSmdsToGhs3dIdMap, aGhs3dIdToNodeMap,
3312 //                       enforcedNodes, enforcedEdges, enforcedTriangles, /*enforcedQuadrangles,*/
3313 //                       coordsSizeMap);
3314   }
3315
3316   // Write aSmdsToGhs3dIdMap to temp file
3317   TCollection_AsciiString aSmdsToGhs3dIdMapFileName;
3318   aSmdsToGhs3dIdMapFileName = aGenericName + ".ids";  // ids relation
3319   ofstream aIdsFile  ( aSmdsToGhs3dIdMapFileName.ToCString()  , ios::out);
3320   Ok = aIdsFile.rdbuf()->is_open();
3321   if (!Ok) {
3322     INFOS( "Can't write into " << aSmdsToGhs3dIdMapFileName);
3323     return error(SMESH_Comment("Can't write into ") << aSmdsToGhs3dIdMapFileName);
3324   }
3325   INFOS( "Writing ids relation into " << aSmdsToGhs3dIdMapFileName);
3326   aIdsFile << "Smds Ghs3d" << std::endl;
3327   map <int,int>::const_iterator myit;
3328   for (myit=aSmdsToGhs3dIdMap.begin() ; myit != aSmdsToGhs3dIdMap.end() ; ++myit) {
3329     aIdsFile << myit->first << " " << myit->second << std::endl;
3330   }
3331
3332   aIdsFile.close();
3333   aFacesFile.close();
3334   aPointsFile.close();
3335   
3336   if ( ! Ok ) {
3337     if ( !_keepFiles ) {
3338 //       removeFile( aGMFFileName );
3339 //       removeFile( aRequiredVerticesFileName );
3340 //       removeFile( aSolFileName );
3341       removeFile( aFacesFileName );
3342       removeFile( aPointsFileName );
3343       removeFile( aSmdsToGhs3dIdMapFileName );
3344     }
3345     return error(COMPERR_BAD_INPUT_MESH);
3346   }
3347   removeFile( aResultFileName ); // needed for boundary recovery module usage
3348
3349   // -----------------
3350   // run ghs3d mesher
3351   // -----------------
3352
3353   TCollection_AsciiString cmd = TCollection_AsciiString((char*)GHS3DPlugin_Hypothesis::CommandToRun( _hyp ).c_str() );
3354   cmd += TCollection_AsciiString(" -f ") + aGenericName;  // file to read
3355   cmd += TCollection_AsciiString(" 1>" ) + aLogFileName;  // dump into file
3356   // The output .mesh file does not contain yet the subdomain-info (Ghs3D 4.2)
3357 //   cmd += TCollection_AsciiString(" --in ") + aGenericName;
3358 //   cmd += TCollection_AsciiString(" --required_vertices ") + aGenericNameRequired;
3359 //    cmd += TCollection_AsciiString(" --out ") + aResultGMFFileName;
3360 //   cmd += TCollection_AsciiString(" 1>" ) + aLogFileName;  // dump into file
3361
3362   std::cout << std::endl;
3363   std::cout << "Ghs3d execution..." << std::endl;
3364   std::cout << cmd << std::endl;
3365
3366 #ifdef WITH_SMESH_CANCEL_COMPUTE
3367   _compute_canceled = false;
3368 #endif
3369
3370   system( cmd.ToCString() ); // run
3371
3372   std::cout << std::endl;
3373   std::cout << "End of Ghs3d execution !" << std::endl;
3374
3375   // --------------
3376   // read a result
3377   // --------------
3378
3379   // Mapping the result file
3380
3381   int fileOpen;
3382   fileOpen = open( aResultFileName.ToCString(), O_RDONLY);
3383   if ( fileOpen < 0 ) {
3384     std::cout << std::endl;
3385     std::cout << "Can't open the " << aResultFileName.ToCString() << " GHS3D output file" << std::endl;
3386     std::cout << "Log: " << aLogFileName << std::endl;
3387     Ok = false;
3388   }
3389   else {
3390     bool toMeshHoles =
3391       _hyp ? _hyp->GetToMeshHoles(true) : GHS3DPlugin_Hypothesis::DefaultMeshHoles();
3392
3393     helper.IsQuadraticSubMesh( theShape );
3394     helper.SetElementsOnShape( false );
3395
3396     Ok = readResultFile( fileOpen,
3397 #ifdef WNT
3398                          aResultFileName.ToCString(),
3399 #endif
3400 #ifdef WITH_SMESH_CANCEL_COMPUTE
3401                          this,
3402 #endif
3403                          /*theMesh, */helper, tabShape, tabBox, _nbShape, 
3404                          aGhs3dIdToNodeMap, aNodeId2NodeIndexMap,
3405                          toMeshHoles, 
3406                          nbEnforcedVertices, nbEnforcedNodes, 
3407                          enforcedEdges, enforcedTriangles );
3408                          
3409 //       Ok = readGMFFile(
3410 // #ifndef GMF_HAS_SUBDOMAIN_INFO
3411 //                        fileOpen,
3412 // #endif
3413 //                        aGenericName.ToCString(), theMesh,
3414 //                        _nbShape, tabShape, tabBox, 
3415 //                        aGhs3dIdToNodeMap, toMeshHoles,
3416 //                        nbEnforcedVertices, nbEnforcedNodes);
3417   }
3418
3419
3420
3421
3422   // ---------------------
3423   // remove working files
3424   // ---------------------
3425
3426   if ( Ok )
3427   {
3428     if ( !_keepFiles )
3429       removeFile( aLogFileName );
3430   }
3431   else if ( OSD_File( aLogFileName ).Size() > 0 )
3432   {
3433     // get problem description from the log file
3434     _Ghs2smdsConvertor conv( aGhs3dIdToNodeMap );
3435     storeErrorDescription( aLogFileName, conv );
3436   }
3437   else
3438   {
3439     // the log file is empty
3440     removeFile( aLogFileName );
3441     INFOS( "GHS3D Error, command '" << cmd.ToCString() << "' failed" );
3442     error(COMPERR_ALGO_FAILED, "ghs3d: command not found" );
3443   }
3444
3445   if ( !_keepFiles ) {
3446 #ifdef WITH_SMESH_CANCEL_COMPUTE
3447     if (! Ok)
3448       if(_compute_canceled)
3449         removeFile( aLogFileName );
3450 #endif
3451     removeFile( aFacesFileName );
3452     removeFile( aPointsFileName );
3453     removeFile( aResultFileName );
3454     removeFile( aBadResFileName );
3455     removeFile( aBbResFileName );
3456     removeFile( aSmdsToGhs3dIdMapFileName );
3457   }
3458   std::cout << "<" << aResultFileName.ToCString() << "> GHS3D output file ";
3459   if ( !Ok )
3460     std::cout << "not ";
3461   std::cout << "treated !" << std::endl;
3462   std::cout << std::endl;
3463
3464   _nbShape = 0;    // re-initializing _nbShape for the next Compute() method call
3465   delete [] tabShape;
3466   delete [] tabBox;
3467
3468   return Ok;
3469 }
3470
3471 //=============================================================================
3472 /*!
3473  *Here we are going to use the GHS3D mesher w/o geometry
3474  */
3475 //=============================================================================
3476 bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
3477                                 SMESH_MesherHelper* theHelper)
3478 {
3479   MESSAGE("GHS3DPlugin_GHS3D::Compute()");
3480
3481   //SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
3482   TopoDS_Shape theShape = theHelper->GetSubShape();
3483
3484   // a unique working file name
3485   // to avoid access to the same files by eg different users
3486   TCollection_AsciiString aGenericName
3487     = (char*) GHS3DPlugin_Hypothesis::GetFileName(_hyp).c_str();
3488   TCollection_AsciiString aGenericNameRequired = aGenericName + "_required";
3489
3490   TCollection_AsciiString aLogFileName    = aGenericName + ".log";    // log
3491   TCollection_AsciiString aResultFileName;
3492   bool Ok;
3493
3494   TCollection_AsciiString aGMFFileName, aRequiredVerticesFileName, aSolFileName;
3495 //#ifdef _DEBUG_
3496   aGMFFileName              = aGenericName + ".mesh"; // GMF mesh file
3497   aResultFileName           = aGenericName + "Vol.mesh"; // GMF mesh file
3498   aRequiredVerticesFileName = aGenericNameRequired + ".mesh"; // GMF required vertices mesh file
3499   aSolFileName              = aGenericNameRequired + ".sol"; // GMF solution file
3500 //#else
3501 //  aGMFFileName    = aGenericName + ".meshb"; // GMF mesh file
3502 //  aResultFileName = aGenericName + "Vol.meshb"; // GMF mesh file
3503 //  aRequiredVerticesFileName    = aGenericNameRequired + ".meshb"; // GMF required vertices mesh file
3504 //  aSolFileName    = aGenericNameRequired + ".solb"; // GMF solution file
3505 //#endif
3506
3507   std::map <int, int> nodeID2nodeIndexMap;
3508   std::map<std::vector<double>, std::string> enfVerticesWithGroup;
3509   GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues coordsSizeMap;
3510   TopoDS_Shape GeomShape;
3511 //   TopAbs_ShapeEnum GeomType;
3512   std::vector<double> coords;
3513   gp_Pnt aPnt;
3514   GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertex* enfVertex;
3515
3516   GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexList enfVertices = GHS3DPlugin_Hypothesis::GetEnforcedVertices(_hyp);
3517   GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexList::const_iterator enfVerIt = enfVertices.begin();
3518
3519   for ( ; enfVerIt != enfVertices.end() ; ++enfVerIt)
3520   {
3521     enfVertex = (*enfVerIt);
3522 //     if (enfVertex->geomEntry.empty() && enfVertex->coords.size()) {
3523     if (enfVertex->coords.size()) {
3524       coordsSizeMap.insert(make_pair(enfVertex->coords,enfVertex->size));
3525       enfVerticesWithGroup.insert(make_pair(enfVertex->coords,enfVertex->groupName));
3526 //       MESSAGE("enfVerticesWithGroup.insert(make_pair(("<<enfVertex->coords[0]<<","<<enfVertex->coords[1]<<","<<enfVertex->coords[2]<<"),\""<<enfVertex->groupName<<"\"))");
3527     }
3528     else {
3529 //     if (!enfVertex->geomEntry.empty()) {
3530       GeomShape = entryToShape(enfVertex->geomEntry);
3531 //       GeomType = GeomShape.ShapeType();
3532
3533 //       if (!enfVertex->isCompound) {
3534 // //       if (GeomType == TopAbs_VERTEX) {
3535 //         coords.clear();
3536 //         aPnt = BRep_Tool::Pnt(TopoDS::Vertex(GeomShape));
3537 //         coords.push_back(aPnt.X());
3538 //         coords.push_back(aPnt.Y());
3539 //         coords.push_back(aPnt.Z());
3540 //         if (coordsSizeMap.find(coords) == coordsSizeMap.end()) {
3541 //           coordsSizeMap.insert(make_pair(coords,enfVertex->size));
3542 //           enfVerticesWithGroup.insert(make_pair(coords,enfVertex->groupName));
3543 //         }
3544 //       }
3545 //
3546 //       // Group Management
3547 //       else {
3548 //       if (GeomType == TopAbs_COMPOUND){
3549         for (TopoDS_Iterator it (GeomShape); it.More(); it.Next()){
3550           coords.clear();
3551           if (it.Value().ShapeType() == TopAbs_VERTEX){
3552             aPnt = BRep_Tool::Pnt(TopoDS::Vertex(it.Value()));
3553             coords.push_back(aPnt.X());
3554             coords.push_back(aPnt.Y());
3555             coords.push_back(aPnt.Z());
3556             if (coordsSizeMap.find(coords) == coordsSizeMap.end()) {
3557               coordsSizeMap.insert(make_pair(coords,enfVertex->size));
3558               enfVerticesWithGroup.insert(make_pair(coords,enfVertex->groupName));
3559 //               MESSAGE("enfVerticesWithGroup.insert(make_pair(("<<coords[0]<<","<<coords[1]<<","<<coords[2]<<"),\""<<enfVertex->groupName<<"\"))");
3560             }
3561           }
3562         }
3563 //       }
3564     }
3565   }
3566
3567 //   const SMDS_MeshNode* enfNode;
3568   GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap enforcedNodes = GHS3DPlugin_Hypothesis::GetEnforcedNodes(_hyp);
3569 //   GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap::const_iterator enfNodeIt = enforcedNodes.begin();
3570 //   for ( ; enfNodeIt != enforcedNodes.end() ; ++enfNodeIt)
3571 //   {
3572 //     enfNode = enfNodeIt->first;
3573 //     coords.clear();
3574 //     coords.push_back(enfNode->X());
3575 //     coords.push_back(enfNode->Y());
3576 //     coords.push_back(enfNode->Z());
3577 //     if (enfVerticesWithGro
3578 //       enfVerticesWithGroup.insert(make_pair(coords,enfNodeIt->second));
3579 //   }
3580
3581
3582   GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap enforcedEdges = GHS3DPlugin_Hypothesis::GetEnforcedEdges(_hyp);
3583   GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap enforcedTriangles = GHS3DPlugin_Hypothesis::GetEnforcedTriangles(_hyp);
3584 //   TIDSortedElemSet enforcedQuadrangles = GHS3DPlugin_Hypothesis::GetEnforcedQuadrangles(_hyp);
3585   GHS3DPlugin_Hypothesis::TID2SizeMap nodeIDToSizeMap = GHS3DPlugin_Hypothesis::GetNodeIDToSizeMap(_hyp);
3586
3587   std::string tmpStr;
3588
3589   int nbEnforcedVertices = coordsSizeMap.size();
3590   int nbEnforcedNodes = enforcedNodes.size();
3591   (nbEnforcedNodes <= 1) ? tmpStr = "node" : tmpStr = "nodes";
3592   std::cout << nbEnforcedNodes << " enforced " << tmpStr << " from hypo" << std::endl;
3593   (nbEnforcedVertices <= 1) ? tmpStr = "vertex" : tmpStr = "vertices";
3594   std::cout << nbEnforcedVertices << " enforced " << tmpStr << " from hypo" << std::endl;
3595
3596   std::vector <const SMDS_MeshNode*> aNodeByGhs3dId, anEnforcedNodeByGhs3dId;
3597   std::map<const SMDS_MeshNode*,int> aNodeToGhs3dIdMap;
3598   std::vector<std::string> aNodeGroupByGhs3dId, anEdgeGroupByGhs3dId, aFaceGroupByGhs3dId;
3599   {
3600     SMESH_ProxyMesh::Ptr proxyMesh( new SMESH_ProxyMesh( theMesh ));
3601     if ( theMesh.NbQuadrangles() > 0 )
3602     {
3603       StdMeshers_QuadToTriaAdaptor* aQuad2Trias = new StdMeshers_QuadToTriaAdaptor;
3604       aQuad2Trias->Compute( theMesh );
3605       proxyMesh.reset( aQuad2Trias );
3606     }
3607
3608     Ok = writeGMFFile(aGMFFileName.ToCString(), aRequiredVerticesFileName.ToCString(), aSolFileName.ToCString(),
3609                       *proxyMesh, &theMesh,
3610                       aNodeByGhs3dId, aNodeToGhs3dIdMap,
3611                       aNodeGroupByGhs3dId, anEdgeGroupByGhs3dId, aFaceGroupByGhs3dId,
3612                       enforcedNodes, enforcedEdges, enforcedTriangles,
3613                       enfVerticesWithGroup, coordsSizeMap);
3614   }
3615
3616   // -----------------
3617   // run ghs3d mesher
3618   // -----------------
3619
3620   TCollection_AsciiString cmd = TCollection_AsciiString((char*)GHS3DPlugin_Hypothesis::CommandToRun( _hyp, false ).c_str());
3621
3622   cmd += TCollection_AsciiString(" --in ") + aGenericName;
3623   if ( nbEnforcedVertices + nbEnforcedNodes)
3624     cmd += TCollection_AsciiString(" --required_vertices ") + aGenericNameRequired;
3625   cmd += TCollection_AsciiString(" --out ") + aResultFileName;
3626   cmd += TCollection_AsciiString(" 1>" ) + aLogFileName;  // dump into file
3627
3628   std::cout << std::endl;
3629   std::cout << "Ghs3d execution..." << std::endl;
3630   std::cout << cmd << std::endl;
3631
3632 #ifdef WITH_SMESH_CANCEL_COMPUTE
3633   _compute_canceled = false;
3634 #endif
3635
3636   system( cmd.ToCString() ); // run
3637
3638   std::cout << std::endl;
3639   std::cout << "End of Ghs3d execution !" << std::endl;
3640
3641   // --------------
3642   // read a result
3643   // --------------
3644   GHS3DPlugin_Hypothesis::TSetStrings groupsToRemove = GHS3DPlugin_Hypothesis::GetGroupsToRemove(_hyp);
3645
3646   Ok = readGMFFile(aResultFileName.ToCString(),
3647 #ifdef WITH_SMESH_CANCEL_COMPUTE
3648                    this,
3649 #endif
3650                    theHelper, theShape, aNodeByGhs3dId, aNodeToGhs3dIdMap,
3651                    aNodeGroupByGhs3dId, anEdgeGroupByGhs3dId, aFaceGroupByGhs3dId,
3652                    groupsToRemove);
3653
3654   updateMeshGroups(theHelper->GetMesh(), groupsToRemove);
3655
3656   if ( Ok ) {
3657     GHS3DPlugin_Hypothesis* that = (GHS3DPlugin_Hypothesis*)this->_hyp;
3658     if (that)
3659       that->ClearGroupsToRemove();
3660   }
3661   // ---------------------
3662   // remove working files
3663   // ---------------------
3664
3665   if ( Ok )
3666   {
3667     if ( !_keepFiles )
3668       removeFile( aLogFileName );
3669   }
3670   else if ( OSD_File( aLogFileName ).Size() > 0 )
3671   {
3672     // get problem description from the log file
3673     _Ghs2smdsConvertor conv( aNodeByGhs3dId );
3674     storeErrorDescription( aLogFileName, conv );
3675   }
3676   else {
3677     // the log file is empty
3678     removeFile( aLogFileName );
3679     INFOS( "GHS3D Error, command '" << cmd.ToCString() << "' failed" );
3680     error(COMPERR_ALGO_FAILED, "ghs3d: command not found" );
3681   }
3682
3683   if ( !_keepFiles )
3684   {
3685 #ifdef WITH_SMESH_CANCEL_COMPUTE
3686     if (! Ok)
3687       if(_compute_canceled)
3688         removeFile( aLogFileName );
3689 #endif
3690     removeFile( aGMFFileName );
3691     removeFile( aResultFileName );
3692     removeFile( aRequiredVerticesFileName );
3693     removeFile( aSolFileName );
3694   }
3695   return Ok;
3696 }
3697
3698 #ifdef WITH_SMESH_CANCEL_COMPUTE
3699 void GHS3DPlugin_GHS3D::CancelCompute()
3700 {
3701   _compute_canceled = true;
3702 #ifdef WNT
3703 #else
3704   TCollection_AsciiString aGenericName
3705     = (char*) GHS3DPlugin_Hypothesis::GetFileName(_hyp).c_str();
3706   TCollection_AsciiString cmd =
3707     TCollection_AsciiString("ps ux | grep ") + aGenericName;
3708   cmd += TCollection_AsciiString(" | grep -v grep | awk '{print $2}' | xargs kill -9 > /dev/null 2>&1");
3709   system( cmd.ToCString() );
3710 #endif
3711 }
3712 #endif
3713
3714 //================================================================================
3715 /*!
3716  * \brief Provide human readable text by error code reported by ghs3d
3717  */
3718 //================================================================================
3719
3720 static string translateError(const int errNum)
3721 {
3722   switch ( errNum ) {
3723   case 0:
3724     return "The surface mesh includes a face of type other than edge, "
3725       "triangle or quadrilateral. This face type is not supported.";
3726   case 1:
3727     return "Not enough memory for the face table.";
3728   case 2:
3729     return "Not enough memory.";
3730   case 3:
3731     return "Not enough memory.";
3732   case 4:
3733     return "Face is ignored.";
3734   case 5:
3735     return "End of file. Some data are missing in the file.";
3736   case 6:
3737     return "Read error on the file. There are wrong data in the file.";
3738   case 7:
3739     return "the metric file is inadequate (dimension other than 3).";
3740   case 8:
3741     return "the metric file is inadequate (values not per vertices).";
3742   case 9:
3743     return "the metric file contains more than one field.";
3744   case 10:
3745     return "the number of values in the \".bb\" (metric file) is incompatible with the expected"
3746       "value of number of mesh vertices in the \".noboite\" file.";
3747   case 12:
3748     return "Too many sub-domains.";
3749   case 13:
3750     return "the number of vertices is negative or null.";
3751   case 14:
3752     return "the number of faces is negative or null.";
3753   case 15:
3754     return "A face has a null vertex.";
3755   case 22:
3756     return "incompatible data.";
3757   case 131:
3758     return "the number of vertices is negative or null.";
3759   case 132:
3760     return "the number of vertices is negative or null (in the \".mesh\" file).";
3761   case 133:
3762     return "the number of faces is negative or null.";
3763   case 1000:
3764     return "A face appears more than once in the input surface mesh.";
3765   case 1001:
3766     return "An edge appears more than once in the input surface mesh.";
3767   case 1002:
3768     return "A face has a vertex negative or null.";
3769   case 1003:
3770     return "NOT ENOUGH MEMORY.";
3771   case 2000:
3772     return "Not enough available memory.";
3773   case 2002:
3774     return "Some initial points cannot be inserted. The surface mesh is probably very bad "
3775       "in terms of quality or the input list of points is wrong.";
3776   case 2003:
3777     return "Some vertices are too close to one another or coincident.";
3778   case 2004:
3779     return "Some vertices are too close to one another or coincident.";
3780   case 2012:
3781     return "A vertex cannot be inserted.";
3782   case 2014:
3783     return "There are at least two points considered as coincident.";
3784   case 2103:
3785     return "Some vertices are too close to one another or coincident.";
3786   case 3000:
3787     return "The surface mesh regeneration step has failed.";
3788   case 3009:
3789     return "Constrained edge cannot be enforced.";
3790   case 3019:
3791     return "Constrained face cannot be enforced.";
3792   case 3029:
3793     return "Missing faces.";
3794   case 3100:
3795     return "No guess to start the definition of the connected component(s).";
3796   case 3101:
3797     return "The surface mesh includes at least one hole. The domain is not well defined.";
3798   case 3102:
3799     return "Impossible to define a component.";
3800   case 3103:
3801     return "The surface edge intersects another surface edge.";
3802   case 3104:
3803     return "The surface edge intersects the surface face.";
3804   case 3105:
3805     return "One boundary point lies within a surface face.";
3806   case 3106:
3807     return "One surface edge intersects a surface face.";
3808   case 3107:
3809     return "One boundary point lies within a surface edge.";
3810   case 3108:
3811     return "Insufficient memory ressources detected due to a bad quality surface mesh leading "
3812       "to too many swaps.";
3813   case 3109:
3814     return "Edge is unique (i.e., bounds a hole in the surface).";
3815   case 3122:
3816     return "Presumably, the surface mesh is not compatible with the domain being processed.";
3817   case 3123:
3818     return "Too many components, too many sub-domain.";
3819   case 3209:
3820     return "The surface mesh includes at least one hole. "
3821       "Therefore there is no domain properly defined.";
3822   case 3300:
3823     return "Statistics.";
3824   case 3400:
3825     return "Statistics.";
3826   case 3500:
3827     return "Warning, it is dramatically tedious to enforce the boundary items.";
3828   case 4000:
3829     return "Not enough memory at this time, nevertheless, the program continues. "
3830       "The expected mesh will be correct but not really as large as required.";
3831   case 4002:
3832     return "see above error code, resulting quality may be poor.";
3833   case 4003:
3834     return "Not enough memory at this time, nevertheless, the program continues (warning).";
3835   case 8000:
3836     return "Unknown face type.";
3837   case 8005:
3838   case 8006:
3839     return "End of file. Some data are missing in the file.";
3840   case 9000:
3841     return "A too small volume element is detected.";
3842   case 9001:
3843     return "There exists at least a null or negative volume element.";
3844   case 9002:
3845     return "There exist null or negative volume elements.";
3846   case 9003:
3847     return "A too small volume element is detected. A face is considered being degenerated.";
3848   case 9100:
3849     return "Some element is suspected to be very bad shaped or wrong.";
3850   case 9102:
3851     return "A too bad quality face is detected. This face is considered degenerated.";
3852   case 9112:
3853     return "A too bad quality face is detected. This face is degenerated.";
3854   case 9122:
3855     return "Presumably, the surface mesh is not compatible with the domain being processed.";
3856   case 9999:
3857     return "Abnormal error occured, contact hotline.";
3858   case 23600:
3859     return "Not enough memory for the face table.";
3860   case 23601:
3861     return "The algorithm cannot run further. "
3862       "The surface mesh is probably very bad in terms of quality.";
3863   case 23602:
3864     return "Bad vertex number.";
3865   }
3866   return "";
3867 }
3868
3869 //================================================================================
3870 /*!
3871  * \brief Retrieve from a string given number of integers
3872  */
3873 //================================================================================
3874
3875 static char* getIds( char* ptr, int nbIds, vector<int>& ids )
3876 {
3877   ids.clear();
3878   ids.reserve( nbIds );
3879   while ( nbIds )
3880   {
3881     while ( !isdigit( *ptr )) ++ptr;
3882     if ( ptr[-1] == '-' ) --ptr;
3883     ids.push_back( strtol( ptr, &ptr, 10 ));
3884     --nbIds;
3885   }
3886   return ptr;
3887 }
3888
3889 //================================================================================
3890 /*!
3891  * \brief Retrieve problem description form a log file
3892  *  \retval bool - always false
3893  */
3894 //================================================================================
3895
3896 bool GHS3DPlugin_GHS3D::storeErrorDescription(const TCollection_AsciiString& logFile,
3897                                               const _Ghs2smdsConvertor &     toSmdsConvertor )
3898 {
3899 #ifdef WITH_SMESH_CANCEL_COMPUTE
3900   if(_compute_canceled)
3901     return error(SMESH_Comment("interruption initiated by user"));
3902 #endif
3903   // open file
3904 #ifdef WNT
3905   int file = ::_open (logFile.ToCString(), _O_RDONLY|_O_BINARY);
3906 #else
3907   int file = ::open (logFile.ToCString(), O_RDONLY);
3908 #endif
3909   if ( file < 0 )
3910     return error( SMESH_Comment("See ") << logFile << " for problem description");
3911
3912   // get file size
3913 //   struct stat status;
3914 //   fstat(file, &status);
3915 //   size_t length = status.st_size;
3916   off_t length = lseek( file, 0, SEEK_END);
3917   lseek( file, 0, SEEK_SET);
3918
3919   // read file
3920   vector< char > buf( length );
3921   int nBytesRead = ::read (file, & buf[0], length);
3922   ::close (file);
3923   char* ptr = & buf[0];
3924   char* bufEnd = ptr + nBytesRead;
3925
3926   SMESH_Comment errDescription;
3927
3928   enum { NODE = 1, EDGE, TRIA, VOL, ID = 1 };
3929
3930   // look for errors "ERR #"
3931
3932   set<string> foundErrorStr; // to avoid reporting same error several times
3933   set<int>    elemErrorNums; // not to report different types of errors with bad elements
3934   while ( ++ptr < bufEnd )
3935   {
3936     if ( strncmp( ptr, "ERR ", 4 ) != 0 )
3937       continue;
3938
3939     list<const SMDS_MeshElement*> badElems;
3940     vector<int> nodeIds;
3941
3942     ptr += 4;
3943     char* errBeg = ptr;
3944     int   errNum = strtol(ptr, &ptr, 10);
3945     switch ( errNum ) { // we treat errors enumerated in [SALOME platform 0019316] issue
3946     case 0015:
3947       // The face number (numfac) with vertices (f 1, f 2, f 3) has a null vertex.
3948       ptr = getIds(ptr, NODE, nodeIds);
3949       ptr = getIds(ptr, TRIA, nodeIds);
3950       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
3951       break;
3952     case 1000: // ERR  1000 :  1 3 2
3953       // Face (f 1, f 2, f 3) appears more than once in the input surface mesh.
3954       ptr = getIds(ptr, TRIA, nodeIds);
3955       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
3956       break;
3957     case 1001:
3958       // Edge (e1, e2) appears more than once in the input surface mesh
3959       ptr = getIds(ptr, EDGE, nodeIds);
3960       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
3961       break;
3962     case 1002:
3963       // Face (f 1, f 2, f 3) has a vertex negative or null
3964       ptr = getIds(ptr, TRIA, nodeIds);
3965       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
3966       break;
3967     case 2004:
3968       // Vertex v1 and vertex v2 are too close to one another or coincident (warning).
3969       ptr = getIds(ptr, NODE, nodeIds);
3970       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
3971       ptr = getIds(ptr, NODE, nodeIds);
3972       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
3973       break;
3974     case 2012:
3975       // Vertex v1 cannot be inserted (warning).
3976       ptr = getIds(ptr, NODE, nodeIds);
3977       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
3978       break;
3979     case 2014:
3980       // There are at least two points whose distance is dist, i.e., considered as coincident
3981     case 2103: // ERR  2103 :  16 WITH  3
3982       // Vertex v1 and vertex v2 are too close to one another or coincident (warning).
3983       ptr = getIds(ptr, NODE, nodeIds);
3984       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
3985       ptr = getIds(ptr, NODE, nodeIds);
3986       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
3987       break;
3988     case 3009:
3989       // Constrained edge (e1, e2) cannot be enforced (warning).
3990       ptr = getIds(ptr, EDGE, nodeIds);
3991       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
3992       break;
3993     case 3019:
3994       // Constrained face (f 1, f 2, f 3) cannot be enforced
3995       ptr = getIds(ptr, TRIA, nodeIds);
3996       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
3997       break;
3998     case 3103: // ERR  3103 :  1 2 WITH  7 3
3999       // The surface edge (e1, e2) intersects another surface edge (e3, e4)
4000       ptr = getIds(ptr, EDGE, nodeIds);
4001       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4002       ptr = getIds(ptr, EDGE, nodeIds);
4003       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4004       break;
4005     case 3104: // ERR  3104 :  9 10 WITH  1 2 3
4006       // The surface edge (e1, e2) intersects the surface face (f 1, f 2, f 3)
4007       ptr = getIds(ptr, EDGE, nodeIds);
4008       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4009       ptr = getIds(ptr, TRIA, nodeIds);
4010       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4011       break;
4012     case 3105: // ERR  3105 :  8 IN  2 3 5
4013       // One boundary point (say p1) lies within a surface face (f 1, f 2, f 3)
4014       ptr = getIds(ptr, NODE, nodeIds);
4015       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4016       ptr = getIds(ptr, TRIA, nodeIds);
4017       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4018       break;
4019     case 3106:
4020       // One surface edge (say e1, e2) intersects a surface face (f 1, f 2, f 3)
4021       ptr = getIds(ptr, EDGE, nodeIds);
4022       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4023       ptr = getIds(ptr, TRIA, nodeIds);
4024       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4025       break;
4026     case 3107: // ERR  3107 :  2 IN  4 1
4027       // One boundary point (say p1) lies within a surface edge (e1, e2) (stop).
4028       ptr = getIds(ptr, NODE, nodeIds);
4029       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4030       ptr = getIds(ptr, EDGE, nodeIds);
4031       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4032       break;
4033     case 3109: // ERR  3109 :  EDGE  5 6 UNIQUE
4034       // Edge (e1, e2) is unique (i.e., bounds a hole in the surface)
4035       ptr = getIds(ptr, EDGE, nodeIds);
4036       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4037       break;
4038     case 9000: // ERR  9000
4039       //  ELEMENT  261 WITH VERTICES :  7 396 -8 242
4040       //  VOLUME   : -1.11325045E+11 W.R.T. EPSILON   0.
4041       // A too small volume element is detected. Are reported the index of the element,
4042       // its four vertex indices, its volume and the tolerance threshold value
4043       ptr = getIds(ptr, ID, nodeIds);
4044       ptr = getIds(ptr, VOL, nodeIds);
4045       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4046       // even if all nodes found, volume it most probably invisible,
4047       // add its faces to demenstrate it anyhow
4048       {
4049         vector<int> faceNodes( nodeIds.begin(), --nodeIds.end() ); // 012
4050         badElems.push_back( toSmdsConvertor.getElement(faceNodes));
4051         faceNodes[2] = nodeIds[3]; // 013
4052         badElems.push_back( toSmdsConvertor.getElement(faceNodes));
4053         faceNodes[1] = nodeIds[2]; // 023
4054         badElems.push_back( toSmdsConvertor.getElement(faceNodes));
4055         faceNodes[0] = nodeIds[1]; // 123
4056         badElems.push_back( toSmdsConvertor.getElement(faceNodes));
4057       }
4058       break;
4059     case 9001: // ERR  9001
4060       //  %% NUMBER OF NEGATIVE VOLUME TETS  :  1
4061       //  %% THE LARGEST NEGATIVE TET        :   1.75376581E+11
4062       //  %%  NUMBER OF NULL VOLUME TETS     :  0
4063       // There exists at least a null or negative volume element
4064       break;
4065     case 9002:
4066       // There exist n null or negative volume elements
4067       break;
4068     case 9003:
4069       // A too small volume element is detected
4070       break;
4071     case 9102:
4072       // A too bad quality face is detected. This face is considered degenerated,
4073       // its index, its three vertex indices together with its quality value are reported
4074       break; // same as next
4075     case 9112: // ERR  9112
4076       //  FACE   2 WITH VERTICES :  4 2 5
4077       //  SMALL INRADIUS :   0.
4078       // A too bad quality face is detected. This face is degenerated,
4079       // its index, its three vertex indices together with its inradius are reported
4080       ptr = getIds(ptr, ID, nodeIds);
4081       ptr = getIds(ptr, TRIA, nodeIds);
4082       badElems.push_back( toSmdsConvertor.getElement(nodeIds));
4083       // add triangle edges as it most probably has zero area and hence invisible
4084       {
4085         vector<int> edgeNodes(2);
4086         edgeNodes[0] = nodeIds[0]; edgeNodes[1] = nodeIds[1]; // 0-1
4087         badElems.push_back( toSmdsConvertor.getElement(edgeNodes));
4088         edgeNodes[1] = nodeIds[2]; // 0-2
4089         badElems.push_back( toSmdsConvertor.getElement(edgeNodes));
4090         edgeNodes[0] = nodeIds[1]; // 1-2
4091         badElems.push_back( toSmdsConvertor.getElement(edgeNodes));
4092       }
4093       break;
4094     }
4095
4096     bool isNewError = foundErrorStr.insert( string( errBeg, ptr )).second;
4097     if ( !isNewError )
4098       continue; // not to report same error several times
4099
4100 //     const SMDS_MeshElement* nullElem = 0;
4101 //     bool allElemsOk = ( find( badElems.begin(), badElems.end(), nullElem) == badElems.end());
4102
4103 //     if ( allElemsOk && !badElems.empty() && !elemErrorNums.empty() ) {
4104 //       bool oneMoreErrorType = elemErrorNums.insert( errNum ).second;
4105 //       if ( oneMoreErrorType )
4106 //         continue; // not to report different types of errors with bad elements
4107 //     }
4108
4109     // store bad elements
4110     //if ( allElemsOk ) {
4111       list<const SMDS_MeshElement*>::iterator elem = badElems.begin();
4112       for ( ; elem != badElems.end(); ++elem )
4113         addBadInputElement( *elem );
4114       //}
4115
4116     // make error text
4117     string text = translateError( errNum );
4118     if ( errDescription.find( text ) == text.npos ) {
4119       if ( !errDescription.empty() )
4120         errDescription << "\n";
4121       errDescription << text;
4122     }
4123
4124   } // end while
4125
4126   if ( errDescription.empty() ) { // no errors found
4127     char msgLic1[] = "connection to server failed";
4128     char msgLic2[] = " Dlim ";
4129     if ( search( &buf[0], bufEnd, msgLic1, msgLic1 + strlen(msgLic1)) != bufEnd ||
4130          search( &buf[0], bufEnd, msgLic2, msgLic2 + strlen(msgLic2)) != bufEnd )
4131       errDescription << "Licence problems.";
4132     else
4133     {
4134       char msg2[] = "SEGMENTATION FAULT";
4135       if ( search( &buf[0], bufEnd, msg2, msg2 + strlen(msg2)) != bufEnd )
4136         errDescription << "ghs3d: SEGMENTATION FAULT. ";
4137     }
4138   }
4139
4140   if ( errDescription.empty() )
4141     errDescription << "See " << logFile << " for problem description";
4142   else
4143     errDescription << "\nSee " << logFile << " for more information";
4144
4145   return error( errDescription );
4146 }
4147
4148 //================================================================================
4149 /*!
4150  * \brief Creates _Ghs2smdsConvertor
4151  */
4152 //================================================================================
4153
4154 _Ghs2smdsConvertor::_Ghs2smdsConvertor( const map <int,const SMDS_MeshNode*> & ghs2NodeMap)
4155   :_ghs2NodeMap( & ghs2NodeMap ), _nodeByGhsId( 0 )
4156 {
4157 }
4158
4159 //================================================================================
4160 /*!
4161  * \brief Creates _Ghs2smdsConvertor
4162  */
4163 //================================================================================
4164
4165 _Ghs2smdsConvertor::_Ghs2smdsConvertor( const vector <const SMDS_MeshNode*> &  nodeByGhsId)
4166   : _ghs2NodeMap( 0 ), _nodeByGhsId( &nodeByGhsId )
4167 {
4168 }
4169
4170 //================================================================================
4171 /*!
4172  * \brief Return SMDS element by ids of GHS3D nodes
4173  */
4174 //================================================================================
4175
4176 const SMDS_MeshElement* _Ghs2smdsConvertor::getElement(const vector<int>& ghsNodes) const
4177 {
4178   size_t nbNodes = ghsNodes.size();
4179   vector<const SMDS_MeshNode*> nodes( nbNodes, 0 );
4180   for ( size_t i = 0; i < nbNodes; ++i ) {
4181     int ghsNode = ghsNodes[ i ];
4182     if ( _ghs2NodeMap ) {
4183       map <int,const SMDS_MeshNode*>::const_iterator in = _ghs2NodeMap->find( ghsNode);
4184       if ( in == _ghs2NodeMap->end() )
4185         return 0;
4186       nodes[ i ] = in->second;
4187     }
4188     else {
4189       if ( ghsNode < 1 || ghsNode > _nodeByGhsId->size() )
4190         return 0;
4191       nodes[ i ] = (*_nodeByGhsId)[ ghsNode-1 ];
4192     }
4193   }
4194   if ( nbNodes == 1 )
4195     return nodes[0];
4196
4197   if ( nbNodes == 2 ) {
4198     const SMDS_MeshElement* edge= SMDS_Mesh::FindEdge( nodes[0], nodes[1] );
4199     if ( !edge )
4200       edge = new SMDS_LinearEdge( nodes[0], nodes[1] );
4201     return edge;
4202   }
4203   if ( nbNodes == 3 ) {
4204     const SMDS_MeshElement* face = SMDS_Mesh::FindFace( nodes );
4205     if ( !face )
4206       face = new SMDS_FaceOfNodes( nodes[0], nodes[1], nodes[2] );
4207     return face;
4208   }
4209   if ( nbNodes == 4 )
4210     return new SMDS_VolumeOfNodes( nodes[0], nodes[1], nodes[2], nodes[3] );
4211
4212   return 0;
4213 }
4214
4215
4216 //=============================================================================
4217 /*!
4218  *
4219  */
4220 //=============================================================================
4221 bool GHS3DPlugin_GHS3D::Evaluate(SMESH_Mesh& aMesh,
4222                                  const TopoDS_Shape& aShape,
4223                                  MapShapeNbElems& aResMap)
4224 {
4225   int nbtri = 0, nbqua = 0;
4226   double fullArea = 0.0;
4227   for (TopExp_Explorer exp(aShape, TopAbs_FACE); exp.More(); exp.Next()) {
4228     TopoDS_Face F = TopoDS::Face( exp.Current() );
4229     SMESH_subMesh *sm = aMesh.GetSubMesh(F);
4230     MapShapeNbElemsItr anIt = aResMap.find(sm);
4231     if( anIt==aResMap.end() ) {
4232       SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
4233       smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,
4234                                             "Submesh can not be evaluated",this));
4235       return false;
4236     }
4237     std::vector<int> aVec = (*anIt).second;
4238     nbtri += Max(aVec[SMDSEntity_Triangle],aVec[SMDSEntity_Quad_Triangle]);
4239     nbqua += Max(aVec[SMDSEntity_Quadrangle],aVec[SMDSEntity_Quad_Quadrangle]);
4240     GProp_GProps G;
4241     BRepGProp::SurfaceProperties(F,G);
4242     double anArea = G.Mass();
4243     fullArea += anArea;
4244   }
4245
4246   // collect info from edges
4247   int nb0d_e = 0, nb1d_e = 0;
4248   bool IsQuadratic = false;
4249   bool IsFirst = true;
4250   TopTools_MapOfShape tmpMap;
4251   for (TopExp_Explorer exp(aShape, TopAbs_EDGE); exp.More(); exp.Next()) {
4252     TopoDS_Edge E = TopoDS::Edge(exp.Current());
4253     if( tmpMap.Contains(E) )
4254       continue;
4255     tmpMap.Add(E);
4256     SMESH_subMesh *aSubMesh = aMesh.GetSubMesh(exp.Current());
4257     MapShapeNbElemsItr anIt = aResMap.find(aSubMesh);
4258     std::vector<int> aVec = (*anIt).second;
4259     nb0d_e += aVec[SMDSEntity_Node];
4260     nb1d_e += Max(aVec[SMDSEntity_Edge],aVec[SMDSEntity_Quad_Edge]);
4261     if(IsFirst) {
4262       IsQuadratic = (aVec[SMDSEntity_Quad_Edge] > aVec[SMDSEntity_Edge]);
4263       IsFirst = false;
4264     }
4265   }
4266   tmpMap.Clear();
4267
4268   double ELen = sqrt(2.* ( fullArea/(nbtri+nbqua*2) ) / sqrt(3.0) );
4269
4270   GProp_GProps G;
4271   BRepGProp::VolumeProperties(aShape,G);
4272   double aVolume = G.Mass();
4273   double tetrVol = 0.1179*ELen*ELen*ELen;
4274   double CoeffQuality = 0.9;
4275   int nbVols = int(aVolume/tetrVol/CoeffQuality);
4276   int nb1d_f = (nbtri*3 + nbqua*4 - nb1d_e) / 2;
4277   int nb1d_in = (int) ( nbVols*6 - nb1d_e - nb1d_f ) / 5;
4278   std::vector<int> aVec(SMDSEntity_Last);
4279   for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aVec[i]=0;
4280   if( IsQuadratic ) {
4281     aVec[SMDSEntity_Node] = nb1d_in/6 + 1 + nb1d_in;
4282     aVec[SMDSEntity_Quad_Tetra] = nbVols - nbqua*2;
4283     aVec[SMDSEntity_Quad_Pyramid] = nbqua;
4284   }
4285   else {
4286     aVec[SMDSEntity_Node] = nb1d_in/6 + 1;
4287     aVec[SMDSEntity_Tetra] = nbVols - nbqua*2;
4288     aVec[SMDSEntity_Pyramid] = nbqua;
4289   }
4290   SMESH_subMesh *sm = aMesh.GetSubMesh(aShape);
4291   aResMap.insert(std::make_pair(sm,aVec));
4292
4293   return true;
4294 }
4295
4296 bool GHS3DPlugin_GHS3D::importGMFMesh(const char* theGMFFileName, SMESH_Mesh& theMesh)
4297 {
4298   SMESH_MesherHelper* helper  = new SMESH_MesherHelper(theMesh );
4299 //   TopoDS_Shape theShape = theMesh.GetShapeToMesh();
4300   std::vector <const SMDS_MeshNode*> dummyNodeVector;
4301   std::map<const SMDS_MeshNode*,int> dummyNodeMap;
4302   std::map<std::vector<double>, std::string> dummyEnfVertGroup;
4303   std::vector<std::string> dummyElemGroup;
4304   std::set<std::string> dummyGroupsToRemove;
4305
4306   bool ok = readGMFFile(theGMFFileName,
4307 #ifdef WITH_SMESH_CANCEL_COMPUTE
4308                         this,
4309 #endif
4310                         helper, theMesh.GetShapeToMesh(), dummyNodeVector, dummyNodeMap, dummyElemGroup, dummyElemGroup, dummyElemGroup, dummyGroupsToRemove);
4311   theMesh.GetMeshDS()->Modified();
4312   return ok;
4313 }
4314
4315 namespace
4316 {
4317   //================================================================================
4318   /*!
4319    * \brief Sub-mesh event listener setting enforced elements as soon as an enforced
4320    *        mesh is loaded
4321    */
4322   struct _EnforcedMeshRestorer : public SMESH_subMeshEventListener
4323   {
4324     _EnforcedMeshRestorer():
4325       SMESH_subMeshEventListener( /*isDeletable = */true, Name() )
4326     {}
4327
4328     //================================================================================
4329     /*!
4330      * \brief Returns an ID of listener
4331      */
4332     static const char* Name() { return "GHS3DPlugin_GHS3D::_EnforcedMeshRestorer"; }
4333
4334     //================================================================================
4335     /*!
4336      * \brief Treat events of the subMesh
4337      */
4338     void ProcessEvent(const int                       event,
4339                       const int                       eventType,
4340                       SMESH_subMesh*                  subMesh,
4341                       SMESH_subMeshEventListenerData* data,
4342                       const SMESH_Hypothesis*         hyp)
4343     {
4344       if ( SMESH_subMesh::SUBMESH_LOADED == event &&
4345            SMESH_subMesh::COMPUTE_EVENT  == eventType &&
4346            data &&
4347            !data->mySubMeshes.empty() )
4348       {
4349         // An enforced mesh (subMesh->_father) has been loaded from hdf file
4350         if ( GHS3DPlugin_Hypothesis* hyp = GetGHSHypothesis( data->mySubMeshes.front() ))
4351           hyp->RestoreEnfElemsByMeshes();
4352       }
4353     }
4354     //================================================================================
4355     /*!
4356      * \brief Returns GHS3DPlugin_Hypothesis used to compute a subMesh
4357      */
4358     static GHS3DPlugin_Hypothesis* GetGHSHypothesis( SMESH_subMesh* subMesh )
4359     {
4360       SMESH_HypoFilter ghsHypFilter( SMESH_HypoFilter::HasName( "GHS3D_Parameters" ));
4361       return (GHS3DPlugin_Hypothesis* )
4362         subMesh->GetFather()->GetHypothesis( subMesh->GetSubShape(),
4363                                              ghsHypFilter,
4364                                              /*visitAncestors=*/true);
4365     }
4366   };
4367 }
4368
4369 //================================================================================
4370 /*!
4371  * \brief Set an event listener to set enforced elements as soon as an enforced
4372  *        mesh is loaded
4373  */
4374 //================================================================================
4375
4376 void GHS3DPlugin_GHS3D::SubmeshRestored(SMESH_subMesh* subMesh)
4377 {
4378   if ( GHS3DPlugin_Hypothesis* hyp = _EnforcedMeshRestorer::GetGHSHypothesis( subMesh ))
4379   {
4380     GHS3DPlugin_Hypothesis::TGHS3DEnforcedMeshList enfMeshes = hyp->_GetEnforcedMeshes();
4381     GHS3DPlugin_Hypothesis::TGHS3DEnforcedMeshList::iterator it = enfMeshes.begin();
4382     for(;it != enfMeshes.end();++it) {
4383       GHS3DPlugin_Hypothesis::TGHS3DEnforcedMesh* enfMesh = *it;
4384       if ( SMESH_Mesh* mesh = GetMeshByPersistentID( enfMesh->persistID ))
4385       {
4386         SMESH_subMesh* smToListen = mesh->GetSubMesh( mesh->GetShapeToMesh() );
4387         // a listener set to smToListen will care of hypothesis stored in SMESH_EventListenerData
4388         subMesh->SetEventListener( new _EnforcedMeshRestorer(),
4389                                    SMESH_subMeshEventListenerData::MakeData( subMesh ),
4390                                    smToListen);
4391       }
4392     }
4393   }
4394 }