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