Salome HOME
Merge from V6_main (04/10/2012)
[plugins/hexoticplugin.git] / src / HexoticPlugin / HexoticPlugin_Hexotic.cxx
1 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 // ---
21 // File   : HexoticPlugin_Hexotic.cxx
22 // Author : Lioka RAZAFINDRAZAKA (CEA)
23 // ---
24 //
25 #include "HexoticPlugin_Hexotic.hxx"
26 #include "HexoticPlugin_Hypothesis.hxx"
27
28 #include "SMDS_MeshElement.hxx"
29 #include "SMDS_MeshNode.hxx"
30
31 #include <TopoDS.hxx>
32 #include <TopExp_Explorer.hxx>
33 #include <OSD_File.hxx>
34
35 #include "utilities.h"
36
37 #ifndef WIN32
38 #include <sys/sysinfo.h>
39 #endif
40
41 #ifdef _DEBUG_
42 #define DUMP(txt) \
43 //  cout << txt
44 #else
45 #define DUMP(txt)
46 #endif
47
48 #include <SMESHDS_GroupBase.hxx>
49 #include <SMESHDS_Mesh.hxx>
50 #include <SMESH_ControlsDef.hxx>
51 #include <SMESH_File.hxx>
52 #include <SMESH_Gen.hxx>
53 #include <SMESH_HypoFilter.hxx>
54 #include <SMESH_MesherHelper.hxx>
55 #include <SMESH_subMesh.hxx>
56
57 #include <list>
58 #include <cstdlib>
59 #include <iostream>
60
61 #include <Standard_ProgramError.hxx>
62
63 #include <BRepClass3d_SolidClassifier.hxx>
64 #include <Bnd_Box.hxx>
65 #include <BRepBndLib.hxx>
66 #include <Precision.hxx>
67
68 #include <BRepBuilderAPI_MakeVertex.hxx>
69 #include <BRep_Tool.hxx>
70 #include <TopTools_MapOfShape.hxx>
71 #include <TopTools_Array1OfShape.hxx>
72 #include <BRepExtrema_DistShapeShape.hxx>
73 #include <TColStd_Array1OfReal.hxx>
74 #include <BRepExtrema_DistShapeShape.hxx>
75
76 static void removeFile( const TCollection_AsciiString& fileName )
77 {
78   try {
79     OSD_File( fileName ).Remove();
80   }
81   catch ( Standard_ProgramError ) {
82     MESSAGE("Can't remove file: " << fileName.ToCString() << " ; file does not exist or permission denied");
83   }
84 }
85
86 //=============================================================================
87 /*!
88  *  
89  */
90 //=============================================================================
91
92 HexoticPlugin_Hexotic::HexoticPlugin_Hexotic(int hypId, int studyId, SMESH_Gen* gen)
93   : SMESH_3D_Algo(hypId, studyId, gen)
94 {
95   MESSAGE("HexoticPlugin_Hexotic::HexoticPlugin_Hexotic");
96   _name = "Hexotic_3D";
97   _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);// 1 bit /shape type
98 //   _onlyUnaryInput = false;
99   _requireShape = false;
100   _iShape=0;
101   _nbShape=0;
102   _hexoticFilesKept=false;
103   _compatibleHypothesis.push_back("Hexotic_Parameters");
104 #ifdef WITH_BLSURFPLUGIN
105   _blsurfHypo = NULL;
106 #endif
107 #ifdef WITH_SMESH_CANCEL_COMPUTE
108   _compute_canceled = false;
109 #endif
110 }
111
112 //=============================================================================
113 /*!
114  *  
115  */
116 //=============================================================================
117
118 HexoticPlugin_Hexotic::~HexoticPlugin_Hexotic()
119 {
120   MESSAGE("HexoticPlugin_Hexotic::~HexoticPlugin_Hexotic");
121 }
122
123
124 #ifdef WITH_BLSURFPLUGIN
125 bool HexoticPlugin_Hexotic::CheckBLSURFHypothesis( SMESH_Mesh&         aMesh,
126                                                    const TopoDS_Shape& aShape )
127 {
128   // MESSAGE("HexoticPlugin_Hexotic::CheckBLSURFHypothesis");
129   _blsurfHypo = NULL;
130
131   std::list<const SMESHDS_Hypothesis*>::const_iterator itl;
132   const SMESHDS_Hypothesis* theHyp;
133
134   // If a BLSURF hypothesis is applied, get it
135   SMESH_HypoFilter blsurfFilter;
136   blsurfFilter.Init( blsurfFilter.HasName( "BLSURF_Parameters" ));
137   std::list<const SMESHDS_Hypothesis *> appliedHyps;
138   aMesh.GetHypotheses( aShape, blsurfFilter, appliedHyps, false );
139
140   if ( appliedHyps.size() > 0 ) {
141     itl = appliedHyps.begin();
142     theHyp = (*itl); // use only the first hypothesis
143     std::string hypName = theHyp->GetName();
144     if (hypName == "BLSURF_Parameters") {
145       _blsurfHypo = static_cast<const BLSURFPlugin_Hypothesis*> (theHyp);
146       ASSERT(_blsurfHypo);
147       return true;
148     }
149   }
150   return false;
151 }
152 #endif
153
154 //=============================================================================
155 /*!
156  *  
157  */
158 //=============================================================================
159
160 bool HexoticPlugin_Hexotic::CheckHypothesis( SMESH_Mesh&                          aMesh,
161                                              const TopoDS_Shape&                  aShape,
162                                              SMESH_Hypothesis::Hypothesis_Status& aStatus )
163 {
164   // MESSAGE("HexoticPlugin_Hexotic::CheckHypothesis");
165   _hypothesis = NULL;
166
167   std::list<const SMESHDS_Hypothesis*>::const_iterator itl;
168   const SMESHDS_Hypothesis* theHyp;
169
170   const std::list<const SMESHDS_Hypothesis*>& hyps = GetUsedHypothesis(aMesh, aShape, false);
171   int nbHyp = hyps.size();
172   if (!nbHyp) {
173     aStatus = SMESH_Hypothesis::HYP_OK;
174     return true;  // can work with no hypothesis
175   }
176
177   itl = hyps.begin();
178   theHyp = (*itl); // use only the first hypothesis
179
180   std::string hypName = theHyp->GetName();
181   if (hypName == "Hexotic_Parameters") {
182     _hypothesis = static_cast<const HexoticPlugin_Hypothesis*> (theHyp);
183     ASSERT(_hypothesis);
184     aStatus = SMESH_Hypothesis::HYP_OK;
185   }
186   else
187     aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
188   
189 #ifdef WITH_BLSURFPLUGIN
190   CheckBLSURFHypothesis(aMesh, aShape);
191 #endif
192   
193   return aStatus == SMESH_Hypothesis::HYP_OK;
194 }
195
196 //=======================================================================
197 //function : findShape
198 //purpose  :
199 //=======================================================================
200
201 static TopoDS_Shape findShape(SMDS_MeshNode**     t_Node,
202                               TopoDS_Shape        aShape,
203                               const TopoDS_Shape* t_Shape,
204                               double**            t_Box,
205                               const int           nShape)
206 {
207   double pntCoor[3];
208   int iShape, nbNode = 8;
209
210   for ( int i=0; i<3; i++ ) {
211     pntCoor[i] = 0;
212     for ( int j=0; j<nbNode; j++ ) {
213       if ( i == 0) pntCoor[i] += t_Node[j]->X();
214       if ( i == 1) pntCoor[i] += t_Node[j]->Y();
215       if ( i == 2) pntCoor[i] += t_Node[j]->Z();
216     }
217     pntCoor[i] /= nbNode;
218   }
219   gp_Pnt aPnt(pntCoor[0], pntCoor[1], pntCoor[2]);
220
221   if ( aShape.IsNull() ) aShape = t_Shape[0];
222   BRepClass3d_SolidClassifier SC (aShape, aPnt, Precision::Confusion());
223   if ( !(SC.State() == TopAbs_IN) ) {
224     aShape.Nullify();
225     for (iShape = 0; iShape < nShape && aShape.IsNull(); iShape++) {
226       if ( !( pntCoor[0] < t_Box[iShape][0] || t_Box[iShape][1] < pntCoor[0] ||
227               pntCoor[1] < t_Box[iShape][2] || t_Box[iShape][3] < pntCoor[1] ||
228               pntCoor[2] < t_Box[iShape][4] || t_Box[iShape][5] < pntCoor[2]) ) {
229         BRepClass3d_SolidClassifier SC (t_Shape[iShape], aPnt, Precision::Confusion());
230         if (SC.State() == TopAbs_IN)
231           aShape = t_Shape[iShape];
232       }
233     }
234   }
235   return aShape;
236 }
237
238 //=======================================================================
239 //function : findEdge
240 //purpose  :
241 //=======================================================================
242
243 static int findEdge(const SMDS_MeshNode* aNode,
244                     const SMESHDS_Mesh*  theMesh,
245                     const int            nEdge,
246                     const TopoDS_Shape*  t_Edge) {
247
248   TopoDS_Shape aPntShape, foundEdge;
249   TopoDS_Vertex aVertex;
250   gp_Pnt aPnt( aNode->X(), aNode->Y(), aNode->Z() );
251
252   int foundInd, ind;
253   double nearest = RealLast(), *t_Dist;
254   double epsilon = Precision::Confusion();
255
256   t_Dist = new double[ nEdge ];
257   aPntShape = BRepBuilderAPI_MakeVertex( aPnt ).Shape();
258   aVertex   = TopoDS::Vertex( aPntShape );
259
260   for ( ind=0; ind < nEdge; ind++ ) {
261     BRepExtrema_DistShapeShape aDistance ( aVertex, t_Edge[ind] );
262     t_Dist[ind] = aDistance.Value();
263     if ( t_Dist[ind] < nearest ) {
264       nearest   = t_Dist[ind];
265       foundEdge = t_Edge[ind];
266       foundInd  = ind;
267       if ( nearest < epsilon )
268         ind = nEdge;
269     }
270   }
271
272   delete [] t_Dist;
273   return theMesh->ShapeToIndex( foundEdge );
274 }
275
276 //=======================================================================
277 //function : getNbShape
278 //purpose  :
279 //=======================================================================
280
281 static int getNbShape(std::string aFile, std::string aString, int defaultValue=0) {
282   int number = defaultValue;
283   std::string aLine;
284   std::ifstream file(aFile.c_str());
285   while ( !file.eof() ) {
286     getline( file, aLine);
287     if ( aLine == aString ) {
288       getline( file, aLine);
289       std::istringstream stringFlux( aLine );
290       stringFlux >> number;
291       number = ( number + defaultValue + std::abs(number - defaultValue) ) / 2;
292       break;
293     }
294   }
295   file.close();
296   return number;
297 }
298
299 //=======================================================================
300 //function : countShape
301 //purpose  :
302 //=======================================================================
303
304 template < class Mesh, class Shape >
305 static int countShape( Mesh* mesh, Shape shape ) {
306   TopExp_Explorer expShape ( mesh->ShapeToMesh(), shape );
307   TopTools_MapOfShape mapShape;
308   int nbShape = 0;
309   for ( ; expShape.More(); expShape.Next() ) {
310     if (mapShape.Add(expShape.Current())) {
311       nbShape++;
312     }
313   }
314   return nbShape;
315 }
316
317 //=======================================================================
318 //function : getShape
319 //purpose  :
320 //=======================================================================
321
322 template < class Mesh, class Shape, class Tab >
323 void getShape(Mesh* mesh, Shape shape, Tab *t_Shape) {
324   TopExp_Explorer expShape ( mesh->ShapeToMesh(), shape );
325   TopTools_MapOfShape mapShape;
326   for ( int i=0; expShape.More(); expShape.Next() ) {
327     if (mapShape.Add(expShape.Current())) {
328       t_Shape[i] = expShape.Current();
329       i++;
330     }
331   }
332   return;
333 }
334
335 //=======================================================================
336 //function : printWarning
337 //purpose  :
338 //=======================================================================
339
340 static void printWarning(const int nbExpected, std::string aString, const int nbFound) {
341   cout << std::endl;
342   cout << "WARNING : " << nbExpected << " " << aString << " expected, Hexotic has found " << nbFound << std::endl;
343   cout << "=======" << std::endl;
344   cout << std::endl;
345   return;
346 }
347
348 //=======================================================================
349 //function : removeHexoticFiles
350 //purpose  :
351 //=======================================================================
352
353 static void removeHexoticFiles(TCollection_AsciiString file_In, TCollection_AsciiString file_Out) {
354   removeFile( file_In );
355   removeFile( file_Out );
356 }
357
358 //=======================================================================
359 //function : writeHexoticFile
360 //purpose  : 
361 //=======================================================================
362
363 static bool writeHexoticFile (std::ofstream&                       theFile,
364                               const SMESHDS_Mesh*                  theMesh,
365                               std::map <int,int>&                  theSmdsToHexoticIdMap,
366                               std::map <int,const SMDS_MeshNode*>& /*theHexoticIdToNodeMap*/,
367                               const TCollection_AsciiString&       Hexotic_In) {
368   cout << std::endl;
369   cout << "Creating Hexotic processed mesh file : " << Hexotic_In << std::endl;
370
371   int nbShape = 0;
372
373   TopExp_Explorer expface(theMesh->ShapeToMesh(), TopAbs_FACE);
374   for ( ; expface.More(); expface.Next() )
375     nbShape++;
376
377   int *tabID;
378   int *tabNodeId;
379   TopoDS_Shape *tabShape, aShape;
380
381   int shapeID;
382   bool idFound;
383
384   int nbVertices    = 0;
385   int nbTriangles   = 0;
386   const char* space = "  ";
387   int dummy_0D      = 0;
388   int dummy_2D;
389   int nbNodes = 0;
390
391   int aSmdsNodeID = 1;
392   const SMDS_MeshNode* aNode;
393   SMDS_NodeIteratorPtr itOnNode;
394
395   std::list< const SMDS_MeshElement* > faces;
396   std::list< const SMDS_MeshElement* >::iterator itListFace;
397   const SMDS_MeshElement* aFace;
398   SMESHDS_SubMesh* theSubMesh;
399   std::map<int,int>::const_iterator itOnSmdsNode;
400   SMDS_ElemIteratorPtr itOnSubNode, itOnSubFace;
401
402 // Writing SMESH points into Hexotic File
403
404   nbVertices = theMesh->NbNodes();
405
406   theFile << "MeshVersionFormatted 2" << std::endl;
407   theFile << std::endl;
408   theFile << "Dimension" << std::endl;
409   theFile << 3 << std::endl;
410   theFile << "# Set of mesh vertices" << std::endl;
411   theFile << "Vertices" << std::endl;
412   theFile << nbVertices << std::endl;
413
414   tabID     = new int[nbShape];
415   tabNodeId = new int[ nbVertices ];
416   tabShape  = new TopoDS_Shape[nbShape];
417
418   itOnNode = theMesh->nodesIterator();
419   while ( itOnNode->more() ) {
420       aNode = itOnNode->next();
421       dummy_0D = aNode->getshapeId();
422       tabNodeId[ aSmdsNodeID - 1 ] = 0;
423       idFound  = false;
424       for ( int j=0; j< aSmdsNodeID; j++ ) {
425         if ( dummy_0D == tabNodeId[j] ) {
426           idFound = true;
427           break;
428         }
429       }
430       if ( ! idFound )
431         tabNodeId[ aSmdsNodeID - 1 ] = dummy_0D;
432       theSmdsToHexoticIdMap.insert(std::map <int,int>::value_type( aNode->GetID(), aSmdsNodeID ));
433       aSmdsNodeID++;
434       theFile << aNode->X() << space << aNode->Y() << space << aNode->Z() << space << dummy_0D << std::endl;
435       }
436
437 // Writing SMESH faces into Hexotic File
438
439   ostringstream triaOut;
440   nbTriangles = 0;
441
442   expface.ReInit();
443   for ( int i = 0; expface.More(); expface.Next(), i++ ) {
444     tabID[i] = 0;
445     aShape   = expface.Current();
446     shapeID  = theMesh->ShapeToIndex( aShape );
447     idFound  = false;
448     for ( int j=0; j<=i; j++) {
449       if ( shapeID == tabID[j] ) {
450         idFound = true;
451         break;
452       }
453     }
454     if ( ! idFound ) {
455       tabID[i]    = shapeID;
456       tabShape[i] = aShape;
457     }
458   }
459   for ( int i=0; i<nbShape; i++ ) {
460     if ( ! (tabID[i] == 0) ) {
461       aShape      = tabShape[i];
462       shapeID     = tabID[i];
463       theSubMesh  = theMesh->MeshElements( aShape );
464       itOnSubFace = theSubMesh->GetElements();
465       while ( itOnSubFace->more() ) {
466         aFace    = itOnSubFace->next();
467         dummy_2D = shapeID;
468         
469         nbNodes = aFace->IsQuadratic() ? aFace->NbNodes()/2 : aFace->NbNodes();
470         if ( nbNodes == 3 ) // triangle
471         {
472           nbTriangles++;
473           for ( int i = 0; i < nbNodes; ++i )
474           {
475             aSmdsNodeID = aFace->GetNode( i )->GetID();
476             itOnSmdsNode = theSmdsToHexoticIdMap.find( aSmdsNodeID );
477             ASSERT( itOnSmdsNode != theSmdsToHexoticIdMap.end() );
478             triaOut << (*itOnSmdsNode).second << space;
479           }
480           triaOut << dummy_2D << std::endl;
481         }
482         else // polygon
483         {
484           int nbTria = nbNodes - 2, n0 = theSmdsToHexoticIdMap[ aFace->GetNode(0)->GetID() ];
485           nbTriangles += nbTria;
486           for ( int i = 0; i < nbTria; ++i )
487           {
488             triaOut << n0 << space;
489             triaOut << theSmdsToHexoticIdMap[ aFace->GetNode(i+1)->GetID() ] << space;
490             triaOut << theSmdsToHexoticIdMap[ aFace->GetNode(i+2)->GetID() ] << space;
491             triaOut << dummy_2D << std::endl;
492           }
493         }
494       }
495     }
496   }
497
498   theFile << std::endl;
499   theFile << "# Set of mesh triangles (v1,v2,v3,tag)" << std::endl;
500   theFile << "Triangles" << std::endl;
501   theFile << nbTriangles << std::endl;
502   theFile << triaOut.str() << std::endl;
503
504   theFile << std::endl;
505   theFile << "End" << std::endl;
506
507   cout << "Processed mesh file created, it contains :" << std::endl;
508   cout << "    " << nbVertices  << " vertices"  << std::endl;
509   cout << "    " << nbTriangles << " triangles" << std::endl;
510   cout << std::endl;
511
512   delete [] tabID;
513   delete [] tabNodeId;
514   delete [] tabShape;
515
516   return true;
517 }
518
519 //=======================================================================
520 //function : writeHexoticFile
521 //purpose  : 
522 //=======================================================================
523
524 static bool writeHexoticFile (std::ofstream&                       theFile,
525                               const SMESH_MesherHelper*            theHelper,
526                               std::map <int,int>&                  theSmdsToHexoticIdMap,
527                               const TCollection_AsciiString&       Hexotic_In)
528 {
529   cout << std::endl;
530   cout << "Creating Hexotic processed mesh file : " << Hexotic_In << std::endl;
531
532   int nbVertices    = 0;
533   int nbTriangles   = 0;
534   const char* space = "  ";
535   int dummy_0D      = 0;
536   int dummy_2D      = 0;
537
538   int aSmdsNodeID = 1;
539   const SMDS_MeshNode* aNode;
540   SMDS_NodeIteratorPtr itOnNode;
541
542   const SMDS_MeshElement* aFace;
543   std::map<int,int>::const_iterator itOnSmdsNode;
544   SMDS_ElemIteratorPtr itOnSubNode, itOnSubFace;
545
546   // Writing SMESH points into Hexotic File
547
548   nbVertices = theHelper->GetMeshDS()->NbNodes();
549
550   theFile << "MeshVersionFormatted 2" << std::endl;
551   theFile << std::endl;
552   theFile << "Dimension" << std::endl;
553   theFile << 3 << std::endl;
554   theFile << "# Set of mesh vertices" << std::endl;
555   theFile << "Vertices" << std::endl;
556   theFile << nbVertices << std::endl;
557
558   itOnNode = theHelper->GetMeshDS()->nodesIterator();
559   while ( itOnNode->more() )
560   {
561     aNode = itOnNode->next();
562     theSmdsToHexoticIdMap.insert(make_pair( aNode->GetID(), aSmdsNodeID ));
563     aSmdsNodeID++;
564     theFile << aNode->X() << space << aNode->Y() << space << aNode->Z() << space << dummy_0D << std::endl;
565   }
566
567   // Writing SMESH faces into Hexotic File
568
569   ostringstream triaOut;
570
571   itOnSubFace = theHelper->GetMeshDS()->elementsIterator(SMDSAbs_Face);
572   while ( itOnSubFace->more() )
573   {
574     aFace = itOnSubFace->next();
575     int nbNodes = aFace->IsQuadratic() ? aFace->NbNodes()/2 : aFace->NbNodes();
576     if ( nbNodes == 3 ) // triangle
577     {
578       nbTriangles++;
579       for ( int i = 0; i < nbNodes; ++i )
580       {
581         aSmdsNodeID = aFace->GetNode( i )->GetID();
582         itOnSmdsNode = theSmdsToHexoticIdMap.find( aSmdsNodeID );
583         ASSERT( itOnSmdsNode != theSmdsToHexoticIdMap.end() );
584         triaOut << (*itOnSmdsNode).second << space;
585       }
586       triaOut << dummy_2D << std::endl;
587     }
588     else // polygon
589     {
590       int nbTria = nbNodes - 2, n0 = theSmdsToHexoticIdMap[ aFace->GetNode(0)->GetID() ];
591       nbTriangles += nbTria;
592       for ( int i = 0; i < nbTria; ++i )
593       {
594         triaOut << n0 << space;
595         triaOut << theSmdsToHexoticIdMap[ aFace->GetNode(i+1)->GetID() ] << space;
596         triaOut << theSmdsToHexoticIdMap[ aFace->GetNode(i+2)->GetID() ] << space;
597         triaOut << dummy_2D << std::endl;
598       }
599     }
600   }
601
602   theFile << std::endl;
603   theFile << "# Set of mesh triangles (v1,v2,v3,tag)" << std::endl;
604   theFile << "Triangles" << std::endl;
605   theFile << nbTriangles << std::endl;
606   theFile << triaOut.str() << std::endl;
607
608   theFile << std::endl;
609   theFile << "End" << std::endl;
610
611   cout << "Processed mesh file created, it contains :" << std::endl;
612   cout << "    " << nbVertices  << " vertices"  << std::endl;
613   cout << "    " << nbTriangles << " triangles" << std::endl;
614   cout << std::endl;
615
616   return true;
617 }
618
619 //=======================================================================
620 //function : readResult
621 //purpose  : 
622 //=======================================================================
623
624 static bool readResult(std::string         theFile,
625 #ifdef WITH_SMESH_CANCEL_COMPUTE
626                        HexoticPlugin_Hexotic*  theAlgo,
627 #endif
628                        SMESHDS_Mesh*       theMesh,
629                        const int           nbShape,
630                        const TopoDS_Shape* tabShape,
631                        double**            tabBox,
632                        const int           sdMode)
633 {
634   // ---------------------------------
635   // Optimisation of the plugin ...
636   // Retrieve the correspondance edge --> shape
637   // (which is very costly) only when user
638   // has defined at least one group of edges
639   // which should be rare for a 3d mesh !
640   // ---------------------------------
641   
642   bool retrieve_edges = false;
643   const std::set<SMESHDS_GroupBase*>& aGroups = theMesh->GetGroups();
644   set<SMESHDS_GroupBase*>::const_iterator GrIt = aGroups.begin();
645   for (; GrIt != aGroups.end(); GrIt++)
646     {
647       SMESHDS_GroupBase* aGrp = *GrIt;
648       if ( !aGrp )
649         continue;
650       if ( aGrp->GetType() == SMDSAbs_Edge )
651         {
652           retrieve_edges = true;
653           break;
654         }
655     }
656   
657   // ---------------------------------
658   // Read generated elements and nodes
659   // ---------------------------------
660
661   TopoDS_Shape aShape;
662   TopoDS_Vertex aVertex;
663   std::string token;
664   int EndOfFile = 0, nbElem = 0, nField = 9, nbRef = 0;
665   int aHexoticNodeID = 0, shapeID, hexoticShapeID;
666   const int IdShapeRef = 2;
667   int *tabID, *tabRef, *nodeAssigne;
668   bool *tabDummy, hasDummy = false;
669   double epsilon = Precision::Confusion();
670   std::map <std::string,int> mapField;
671   SMDS_MeshNode** HexoticNode;
672   TopoDS_Shape *tabCorner, *tabEdge;
673
674   const int nbDomains = countShape( theMesh, TopAbs_SHELL );
675   MESSAGE("Nb domains in the meshed shape: " << nbDomains );
676   const int holeID = -1;
677
678   // tabID    = new int[nbShape];
679   tabID    = new int[nbDomains];
680   tabRef   = new int[nField];
681   tabDummy = new bool[nField];
682
683   for (int i=0; i<nbDomains; i++)
684     tabID[i] = 0;
685   if ( nbDomains == 1 )
686     tabID[0] = theMesh->ShapeToIndex( tabShape[0] );
687
688   mapField["MeshVersionFormatted"] = 0; tabRef[0] = 0; tabDummy[0] = false;
689   mapField["Dimension"]            = 1; tabRef[1] = 0; tabDummy[1] = false;
690   mapField["Vertices"]             = 2; tabRef[2] = 3; tabDummy[2] = true;
691   mapField["Corners"]              = 3; tabRef[3] = 1; tabDummy[3] = false;
692   mapField["Edges"]                = 4; tabRef[4] = 2; tabDummy[4] = true;
693   mapField["Ridges"]               = 5; tabRef[5] = 1; tabDummy[5] = false;
694   mapField["Quadrilaterals"]       = 6; tabRef[6] = 4; tabDummy[6] = true;
695   mapField["Hexahedra"]            = 7; tabRef[7] = 8; tabDummy[7] = true;
696   mapField["End"]                  = 8; tabRef[8] = 0; tabDummy[0] = false;
697
698   SMDS_NodeIteratorPtr itOnHexoticInputNode = theMesh->nodesIterator();
699   while ( itOnHexoticInputNode->more() )
700     theMesh->RemoveNode( itOnHexoticInputNode->next() );
701
702   int nbVertices   = getNbShape(theFile, "Vertices");
703   int nbCorners    = getNbShape(theFile, "Corners", countShape( theMesh, TopAbs_VERTEX ));
704   int nbShapeEdge  = countShape( theMesh, TopAbs_EDGE );
705
706   tabCorner   = new TopoDS_Shape[ nbCorners ];
707   tabEdge     = new TopoDS_Shape[ nbShapeEdge ];
708   nodeAssigne = new int[ nbVertices + 1 ];
709   HexoticNode = new SMDS_MeshNode*[ nbVertices + 1 ];
710
711   getShape(theMesh, TopAbs_VERTEX, tabCorner);
712   getShape(theMesh, TopAbs_EDGE,   tabEdge);
713
714   MESSAGE("Read " << theFile << " file");
715   std::ifstream fileRes(theFile.c_str());
716   ASSERT(fileRes);
717
718   while ( EndOfFile == 0  ) {
719     int dummy;
720     fileRes >> token;
721
722     if (mapField.count(token)) {
723       nField   = mapField[token];
724       nbRef    = tabRef[nField];
725       hasDummy = tabDummy[nField];
726     }
727     else {
728       nField = -1;
729       nbRef = 0;
730     }
731
732     nbElem = 0;
733     if ( nField < (mapField.size() - 1) && nField >= 0 )
734       fileRes >> nbElem;
735
736     switch (nField) {
737       case 0: { // "MeshVersionFormatted"
738         MESSAGE(token << " " << nbElem);
739         break;
740       }
741       case 1: { // "Dimension"
742         MESSAGE("Mesh dimension " << nbElem << "D");
743         break;
744       }
745       case 2: { // "Vertices"
746         MESSAGE("Read " << nbElem << " " << token);
747         int aHexoticID;
748         double *coord;
749         SMDS_MeshNode * aHexoticNode;
750
751         coord = new double[nbRef];
752         for ( int iElem = 0; iElem < nbElem; iElem++ ) {
753 #ifdef WITH_SMESH_CANCEL_COMPUTE
754           if(theAlgo->computeCanceled())
755             {
756               return false;
757             }
758 #endif
759           aHexoticID = iElem + 1;
760           for ( int iCoord = 0; iCoord < 3; iCoord++ )
761             fileRes >> coord[ iCoord ];
762           fileRes >> dummy;
763           aHexoticNode = theMesh->AddNode(coord[0], coord[1], coord[2]);
764           HexoticNode[ aHexoticID ] = aHexoticNode;
765           nodeAssigne[ aHexoticID ] = 0;
766         }
767         delete [] coord;
768         break;
769       }
770       case 3: // "Corners"
771       case 4: // "Edges"
772       case 5: // "Ridges"
773       case 6: // "Quadrilaterals"
774       case 7: { // "Hexahedra"
775         MESSAGE("Read " << nbElem << " " << token);
776         SMDS_MeshNode** node;
777         int nodeDim, *nodeID;
778         SMDS_MeshElement * aHexoticElement = 0;
779
780         node   = new SMDS_MeshNode*[ nbRef ];
781         nodeID = new int[ nbRef ];
782         for ( int iElem = 0; iElem < nbElem; iElem++ ) {
783 #ifdef WITH_SMESH_CANCEL_COMPUTE
784           if(theAlgo->computeCanceled())
785             {
786               return false;
787             }
788 #endif
789           for ( int iRef = 0; iRef < nbRef; iRef++ ) {
790             fileRes >> aHexoticNodeID;                          // read nbRef aHexoticNodeID
791             node[ iRef ]   = HexoticNode[ aHexoticNodeID ];
792             nodeID[ iRef ] = aHexoticNodeID;
793           }
794           if ( hasDummy )
795             fileRes >> dummy;
796           switch (nField) {
797             case 3: { // "Corners"
798               nodeDim = 1;
799               gp_Pnt HexoticPnt ( node[0]->X(), node[0]->Y(), node[0]->Z() );
800               for ( int i=0; i<nbElem; i++ ) {
801                 aVertex = TopoDS::Vertex( tabCorner[i] );
802                 gp_Pnt aPnt = BRep_Tool::Pnt( aVertex );
803                 if ( aPnt.Distance( HexoticPnt ) < epsilon )
804                   break;
805               }
806               break;
807             }
808             case 4: { // "Edges"
809               nodeDim = 2;
810               aHexoticElement = theMesh->AddEdge( node[0], node[1] );
811               int iNode = 1;
812               if ( nodeAssigne[ nodeID[0] ] == 0 || nodeAssigne[ nodeID[0] ] == 2 )
813                 iNode = 0;
814               if(retrieve_edges)
815                 shapeID = findEdge( node[iNode], theMesh, nbShapeEdge, tabEdge );
816               else
817                 shapeID = 0;
818               break;
819             }
820             case 5: { // "Ridges"
821               break;
822             }
823             case 6: { // "Quadrilaterals"
824               nodeDim = 3;
825               aHexoticElement = theMesh->AddFace( node[0], node[1], node[2], node[3] );
826               shapeID = dummy;
827               break;
828             }
829             case 7: { // "Hexahedra"
830               nodeDim = 4;
831               if ( nbDomains > 1 ) {
832                 hexoticShapeID = dummy - IdShapeRef;
833                 if ( tabID[ hexoticShapeID ] == 0 ) {
834                   aShape = findShape(node, aShape, tabShape, tabBox, nbShape);
835                   shapeID = aShape.IsNull() ? holeID : theMesh->ShapeToIndex( aShape );
836                   tabID[ hexoticShapeID ] = shapeID;
837                 }
838                 else
839                   shapeID = tabID[ hexoticShapeID ];
840                 if ( iElem == (nbElem - 1) ) {
841                   int shapeAssociated = 0;
842                   for ( int i=0; i<nbDomains; i++ ) {
843                     if (tabID[i] > 0 )
844                       shapeAssociated += 1;
845                   }
846                   if ( shapeAssociated != nbShape )
847                     printWarning(nbShape, "domains", shapeAssociated);
848                 }
849               }
850               else {
851                 shapeID = tabID[0];
852               }
853               if ( (sdMode == 4 && shapeID != holeID) || sdMode != 2 )
854                 aHexoticElement = theMesh->AddVolume( node[0], node[3], node[2], node[1], node[4], node[7], node[6], node[5] );
855               break;
856             }
857           } // switch (nField)
858
859           if ( token != "Ridges" && ( shapeID > 0 || token == "Corners")) {
860             for ( int i=0; i<nbRef; i++ ) {
861               if ( nodeAssigne[ nodeID[i] ] == 0 ) {
862                 if      ( token == "Corners" )        theMesh->SetNodeOnVertex( node[0], aVertex );
863                 else if ( token == "Edges" )          theMesh->SetNodeOnEdge( node[i], shapeID );
864                 else if ( token == "Quadrilaterals" ) theMesh->SetNodeOnFace( node[i], shapeID );
865                 else if ( token == "Hexahedra" )      theMesh->SetNodeInVolume( node[i], shapeID );
866                 nodeAssigne[ nodeID[i] ] = nodeDim;
867               }
868             }
869             if ( token != "Corners" && aHexoticElement )
870               theMesh->SetMeshElementOnShape( aHexoticElement, shapeID );
871           }
872         }
873         delete [] node;
874         delete [] nodeID;
875         break;
876       }
877       case 8: { // "End"
878         EndOfFile = 1;
879         MESSAGE("End of " << theFile << " file");
880         break;
881       }
882       default: {
883         MESSAGE("Unknown Token: " << token);
884       }
885     }
886   }
887   cout << std::endl;
888
889   // remove nodes in holes
890   if ( nbDomains > 1 )
891   {
892     SMESHDS_SubMesh* subMesh;
893     for ( int i = 1; i <= nbVertices; ++i )
894       if ( HexoticNode[i]->NbInverseElements() == 0 )
895       {
896         subMesh =  HexoticNode[i]->getshapeId() > 0 ? theMesh->MeshElements(HexoticNode[i]->getshapeId() ) : 0;
897         theMesh->RemoveFreeNode( HexoticNode[i], subMesh, /*fromGroups=*/false );
898       }
899   }
900   delete [] tabID;
901   delete [] tabRef;
902   delete [] tabDummy;
903   delete [] tabCorner;
904   delete [] tabEdge;
905   delete [] nodeAssigne;
906   delete [] HexoticNode;
907   return true;
908 }
909
910
911 //=======================================================================
912 //function : readResult
913 //purpose  : 
914 //=======================================================================
915
916 static bool readResult(std::string            theFile,
917 #ifdef WITH_SMESH_CANCEL_COMPUTE
918                        HexoticPlugin_Hexotic* theAlgo,
919 #endif
920                        SMESH_MesherHelper*    theHelper,
921                        const int              sdMode)
922 {
923   SMESHDS_Mesh* theMesh = theHelper->GetMeshDS();
924
925   // ---------------------------------
926   // Read generated elements and nodes
927   // ---------------------------------
928
929   std::string token;
930   const int nbField = 9;
931   int nField, EndOfFile = 0, nbElem = 0, nbRef = 0;
932   int aHexoticNodeID = 0, shapeID;
933   int tabRef[nbField], *nodeAssigne;
934   bool tabDummy[nbField], hasDummy = false;
935   std::map <std::string,int> mapField;
936   SMDS_MeshNode** HexoticNode;
937
938   mapField["MeshVersionFormatted"] = 0; tabRef[0] = 0; tabDummy[0] = false;
939   mapField["Dimension"]            = 1; tabRef[1] = 0; tabDummy[1] = false;
940   mapField["Vertices"]             = 2; tabRef[2] = 3; tabDummy[2] = true;
941   mapField["Corners"]              = 3; tabRef[3] = 1; tabDummy[3] = false;
942   mapField["Edges"]                = 4; tabRef[4] = 2; tabDummy[4] = true;
943   mapField["Ridges"]               = 5; tabRef[5] = 1; tabDummy[5] = false;
944   mapField["Quadrilaterals"]       = 6; tabRef[6] = 4; tabDummy[6] = true;
945   mapField["Hexahedra"]            = 7; tabRef[7] = 8; tabDummy[7] = true;
946   mapField["End"]                  = 8; tabRef[8] = 0; tabDummy[8] = false;
947
948   theHelper->GetMesh()->Clear();
949
950   int nbVertices = getNbShape(theFile, "Vertices");
951   HexoticNode = new SMDS_MeshNode*[ nbVertices + 1 ];
952   nodeAssigne = new int[ nbVertices + 1 ];
953
954   MESSAGE("Read " << theFile << " file");
955   std::ifstream fileRes(theFile.c_str());
956   ASSERT(fileRes);
957
958   while ( !EndOfFile  )
959   {
960     int dummy;
961     fileRes >> token;
962
963     if (mapField.count(token)) {
964       nField   = mapField[token];
965       nbRef    = tabRef[nField];
966       hasDummy = tabDummy[nField];
967     }
968     else {
969       nField = -1;
970       nbRef = 0;
971     }
972
973     nbElem = 0;
974     if ( nField < (mapField.size() - 1) && nField >= 0 )
975       fileRes >> nbElem;
976
977     switch (nField) {
978     case 0: { // "MeshVersionFormatted"
979       MESSAGE(token << " " << nbElem);
980       break;
981     }
982     case 1: { // "Dimension"
983       MESSAGE("Mesh dimension " << nbElem << "D");
984       break;
985     }
986     case 2: { // "Vertices"
987       MESSAGE("Read " << nbElem << " " << token);
988       int aHexoticID;
989       double coord[3];
990       SMDS_MeshNode * aHexoticNode;
991
992       for ( int iElem = 0; iElem < nbElem; iElem++ ) {
993 #ifdef WITH_SMESH_CANCEL_COMPUTE
994         if(theAlgo->computeCanceled())
995           {
996             return false;
997           }
998 #endif
999         aHexoticID = iElem + 1;
1000         for ( int iCoord = 0; iCoord < 3; iCoord++ )
1001           fileRes >> coord[ iCoord ];
1002         fileRes >> dummy;
1003         aHexoticNode = theMesh->AddNode(coord[0], coord[1], coord[2]);
1004         HexoticNode[ aHexoticID ] = aHexoticNode;
1005         nodeAssigne[ aHexoticID ] = 0;
1006       }
1007       break;
1008     }
1009     case 3: // "Corners"
1010     case 4: // "Edges"
1011     case 5: // "Ridges"
1012     case 6: // "Quadrilaterals"
1013     case 7: { // "Hexahedra"
1014       MESSAGE("Read " << nbElem << " " << token);
1015       std::vector< SMDS_MeshNode* > node( nbRef );
1016       std::vector< int >          nodeID( nbRef );
1017
1018       for ( int iElem = 0; iElem < nbElem; iElem++ )
1019       {
1020 #ifdef WITH_SMESH_CANCEL_COMPUTE
1021         if(theAlgo->computeCanceled())
1022           {
1023             return false;
1024           }
1025 #endif
1026         for ( int iRef = 0; iRef < nbRef; iRef++ )
1027         {
1028           fileRes >> aHexoticNodeID;                          // read nbRef aHexoticNodeID
1029           node  [ iRef ] = HexoticNode[ aHexoticNodeID ];
1030           nodeID[ iRef ] = aHexoticNodeID;
1031         }
1032         if ( hasDummy )
1033           fileRes >> dummy;
1034         switch (nField)
1035         {
1036         case 4: // "Edges"
1037           theHelper->AddEdge( node[0], node[1] ); break;
1038         case 6:  // "Quadrilaterals"
1039           theMesh->AddFace( node[0], node[1], node[2], node[3] ); break;
1040         case 7: // "Hexahedra"
1041           theHelper->AddVolume( node[0], node[3], node[2], node[1],
1042                                 node[4], node[7], node[6], node[5] ); break;
1043         default: continue;
1044         }
1045         if ( nField == 6 )
1046           for ( int iRef = 0; iRef < nbRef; iRef++ )
1047             nodeAssigne[ nodeID[ iRef ]] = 1;
1048       }
1049       break;
1050     }
1051     case 8: { // "End"
1052       EndOfFile = 1;
1053       MESSAGE("End of " << theFile << " file");
1054       break;
1055     }
1056     default: {
1057       MESSAGE("Unknown Token: " << token);
1058     }
1059     }
1060   }
1061   cout << std::endl;
1062
1063   shapeID = theHelper->GetSubShapeID();
1064   for ( int i = 0; i < nbVertices; ++i )
1065     if ( !nodeAssigne[ i+1 ])
1066       theMesh->SetNodeInVolume( HexoticNode[ i+1 ], shapeID );
1067
1068   delete [] HexoticNode;
1069   delete [] nodeAssigne;
1070   return true;
1071 }
1072
1073 //=============================================================================
1074 /*!
1075  * Pass parameters to Hexotic
1076  */
1077 //=============================================================================
1078
1079 void HexoticPlugin_Hexotic::SetParameters(const HexoticPlugin_Hypothesis* hyp) {
1080
1081   MESSAGE("HexoticPlugin_Hexotic::SetParameters");
1082   if (hyp) {
1083     _hexesMinLevel = hyp->GetHexesMinLevel();
1084     _hexesMaxLevel = hyp->GetHexesMaxLevel();
1085     _hexesMinSize = hyp->GetMinSize();
1086     _hexesMaxSize = hyp->GetMaxSize();
1087     _hexoticIgnoreRidges = hyp->GetHexoticIgnoreRidges();
1088     _hexoticInvalidElements = hyp->GetHexoticInvalidElements();
1089     _hexoticSharpAngleThreshold = hyp->GetHexoticSharpAngleThreshold();
1090     _hexoticNbProc = hyp->GetHexoticNbProc();
1091     _hexoticWorkingDirectory = hyp->GetHexoticWorkingDirectory();
1092     _hexoticVerbosity = hyp->GetHexoticVerbosity();
1093     _hexoticSdMode = hyp->GetHexoticSdMode();
1094   }
1095   else {
1096     cout << std::endl;
1097     cout << "WARNING : The Hexotic default parameters are taken into account" << std::endl;
1098     cout << "=======" << std::endl;
1099     _hexesMinLevel = hyp->GetDefaultHexesMinLevel();
1100     _hexesMaxLevel = hyp->GetDefaultHexesMaxLevel();
1101     _hexesMinSize = hyp->GetDefaultMinSize();
1102     _hexesMaxSize = hyp->GetDefaultMaxSize();
1103     _hexoticIgnoreRidges = hyp->GetDefaultHexoticIgnoreRidges();
1104     _hexoticInvalidElements = hyp->GetDefaultHexoticInvalidElements();
1105     _hexoticSharpAngleThreshold = hyp->GetDefaultHexoticSharpAngleThreshold();
1106     _hexoticNbProc = hyp->GetDefaultHexoticNbProc();
1107     _hexoticWorkingDirectory = hyp->GetDefaultHexoticWorkingDirectory();
1108     _hexoticVerbosity = hyp->GetDefaultHexoticVerbosity();
1109     _hexoticSdMode = hyp->GetDefaultHexoticSdMode();
1110   }
1111 }
1112
1113 //=======================================================================
1114 //function : getTmpDir
1115 //purpose  :
1116 //=======================================================================
1117
1118 static TCollection_AsciiString getTmpDir()
1119 {
1120   TCollection_AsciiString aTmpDir;
1121
1122   char *Tmp_dir = getenv("SALOME_TMP_DIR");
1123   if(Tmp_dir != NULL) {
1124     aTmpDir = Tmp_dir;
1125     #ifdef WIN32
1126     if(aTmpDir.Value(aTmpDir.Length()) != '\\') aTmpDir+='\\';
1127 #else
1128     if(aTmpDir.Value(aTmpDir.Length()) != '/') aTmpDir+='/';
1129 #endif
1130   }
1131   else {
1132 #ifdef WIN32
1133     aTmpDir = TCollection_AsciiString("C:\\");
1134 #else
1135     aTmpDir = TCollection_AsciiString("/tmp/");
1136 #endif
1137   }
1138   return aTmpDir;
1139 }
1140
1141 //================================================================================
1142 /*!
1143  * \brief Returns a command to run Hexotic mesher
1144  */
1145 //================================================================================
1146
1147 std::string HexoticPlugin_Hexotic::getHexoticCommand(const TCollection_AsciiString& Hexotic_In,
1148                                                      const TCollection_AsciiString& Hexotic_Out) const
1149 {
1150   cout << std::endl;
1151   cout << "Hexotic execution..." << std::endl;
1152   cout << _name << " parameters :" << std::endl;
1153   cout << "    " << _name << " Verbosity = " << _hexoticVerbosity << std::endl;
1154   cout << "    " << _name << " Segments Min Level = " << _hexesMinLevel << std::endl;
1155   cout << "    " << _name << " Segments Max Level = " << _hexesMaxLevel << std::endl;
1156   cout << "    " << _name << " Segments Min Size = " << _hexesMinSize << std::endl;
1157   cout << "    " << _name << " Segments Max Size = " << _hexesMaxSize << std::endl;
1158   cout << "    " << "Hexotic can ignore ridges : " << (_hexoticIgnoreRidges ? "yes":"no") << std::endl;
1159   cout << "    " << "Hexotic authorize invalide elements : " << ( _hexoticInvalidElements ? "yes":"no") << std::endl;
1160   cout << "    " << _name << " Sharp angle threshold = " << _hexoticSharpAngleThreshold << " degrees" << std::endl;
1161   cout << "    " << _name << " Number of threads = " << _hexoticNbProc << std::endl;
1162   cout << "    " << _name << " Working directory = \"" << _hexoticWorkingDirectory << "\"" << std::endl;
1163   cout << "    " << _name << " Sub. Dom mode = " << _hexoticSdMode << std::endl;
1164
1165   TCollection_AsciiString run_Hexotic( "hexotic" );
1166
1167   TCollection_AsciiString minl = " -minl ", maxl = " -maxl ", angle = " -ra ";
1168   TCollection_AsciiString mins = " -mins ", maxs = " -maxs ";
1169   TCollection_AsciiString in   = " -in ",   out  = " -out ";
1170   TCollection_AsciiString ignoreRidges = " -nr ", invalideElements = " -inv ";
1171   TCollection_AsciiString subdom = " -sd ", sharp = " -sharp ";
1172   TCollection_AsciiString proc = " -nproc ";
1173   TCollection_AsciiString verb = " -v ";
1174
1175   TCollection_AsciiString minLevel, maxLevel, minSize, maxSize, sharpAngle, mode, nbproc, verbosity;
1176   minLevel = _hexesMinLevel;
1177   maxLevel = _hexesMaxLevel;
1178   minSize = _hexesMinSize;
1179   maxSize = _hexesMaxSize;
1180   sharpAngle = _hexoticSharpAngleThreshold;
1181   mode = _hexoticSdMode;
1182   nbproc = _hexoticNbProc;
1183   verbosity = _hexoticVerbosity;
1184
1185   if (_hexoticIgnoreRidges)
1186     run_Hexotic +=  ignoreRidges;
1187
1188   if (_hexoticInvalidElements)
1189     run_Hexotic +=  invalideElements;
1190
1191   if (_hexesMinSize > 0)
1192     run_Hexotic +=  mins + minSize;
1193
1194   if (_hexesMaxSize > 0)
1195     run_Hexotic +=  maxs + maxSize;
1196
1197   if (_hexesMinLevel > 0)
1198     run_Hexotic +=  minl + minLevel;
1199
1200   if (_hexesMaxLevel > 0)
1201     run_Hexotic +=  maxl + maxLevel;
1202
1203   if (_hexoticSharpAngleThreshold > 0)
1204     run_Hexotic +=  angle + sharpAngle;
1205
1206   run_Hexotic += in + Hexotic_In + out + Hexotic_Out;
1207   run_Hexotic += subdom + mode;
1208   run_Hexotic += proc + nbproc;
1209   run_Hexotic += verb + verbosity;
1210
1211   return run_Hexotic.ToCString();
1212 }
1213
1214 //=============================================================================
1215 /*!
1216  * Here we are going to use the Hexotic mesher
1217  */
1218 //=============================================================================
1219
1220 bool HexoticPlugin_Hexotic::Compute(SMESH_Mesh&          theMesh,
1221                                      const TopoDS_Shape& theShape)
1222 {
1223 #ifdef WITH_SMESH_CANCEL_COMPUTE
1224   _compute_canceled = false;
1225 #endif
1226   bool Ok = true;
1227   SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
1228   TCollection_AsciiString hexahedraMessage;
1229
1230   if (_iShape == 0 && _nbShape == 0) {
1231     _nbShape = countShape( meshDS, TopAbs_SOLID );  // we count the number of shapes
1232     //_tabNode = new SMDS_MeshNode*[_nbShape];        // we declare the size of the node array
1233   }
1234
1235   // to prevent from displaying error message after computing,
1236   // SetIsAlwaysComputed( true ) to empty sub-meshes
1237   for ( int i = 0; i < _nbShape; ++i )
1238     if ( SMESH_subMesh* sm = theMesh.GetSubMeshContaining( theShape ))
1239     {
1240       SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/true,
1241                                                                /*complexShapeFirst=*/false);
1242       while ( smIt->more() )
1243       {
1244         sm = smIt->next();
1245         if ( !sm->IsMeshComputed() )
1246           sm->SetIsAlwaysComputed( true );
1247       }
1248     }
1249
1250   _iShape++;
1251
1252   if (_iShape == _nbShape ) {
1253
1254     // for (int i=0; i<_nbShape; i++)        // we destroy the (_nbShape - 1) nodes created and used
1255     //   meshDS->RemoveNode( _tabNode[i] );  // to simulate successful mesh computing.
1256     // delete [] _tabNode;
1257
1258     // create bounding box for each shape of the compound
1259
1260     int iShape = 0;
1261     TopoDS_Shape *tabShape;
1262     double **tabBox;
1263
1264     tabShape = new TopoDS_Shape[_nbShape];
1265     tabBox   = new double*[_nbShape];
1266     for (int i=0; i<_nbShape; i++)
1267       tabBox[i] = new double[6];
1268     double Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
1269
1270     TopExp_Explorer expBox (meshDS->ShapeToMesh(), TopAbs_SOLID);
1271     for (; expBox.More(); expBox.Next()) {
1272       tabShape[iShape] = expBox.Current();
1273       Bnd_Box BoundingBox;
1274       BRepBndLib::Add(expBox.Current(), BoundingBox);
1275       BoundingBox.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
1276       tabBox[iShape][0] = Xmin; tabBox[iShape][1] = Xmax;
1277       tabBox[iShape][2] = Ymin; tabBox[iShape][3] = Ymax;
1278       tabBox[iShape][4] = Zmin; tabBox[iShape][5] = Zmax;
1279       iShape++;
1280     }
1281
1282     SetParameters(_hypothesis);
1283
1284 //     TCollection_AsciiString aTmpDir = getTmpDir();
1285     TCollection_AsciiString aTmpDir = TCollection_AsciiString(_hexoticWorkingDirectory.c_str());
1286 #ifdef WIN32
1287     if ( aTmpDir.Value(aTmpDir.Length()) != '\\' ) aTmpDir += '\\';
1288 #else
1289     if ( aTmpDir.Value(aTmpDir.Length()) != '/' ) aTmpDir += '/';
1290 #endif
1291     TCollection_AsciiString Hexotic_In(""), Hexotic_Out;
1292     TCollection_AsciiString modeFile_In( "chmod 666 " ), modeFile_Out( "chmod 666 " );
1293     TCollection_AsciiString aLogFileName = aTmpDir + "Hexotic.log";    // log
1294
1295     std::map <int,int> aSmdsToHexoticIdMap;
1296     std::map <int,const SMDS_MeshNode*> aHexoticIdToNodeMap;
1297
1298     Hexotic_Out = aTmpDir + "Hexotic_Out.mesh";
1299 #ifdef WITH_BLSURFPLUGIN
1300     bool defaultInputFile = true;
1301     if (_blsurfHypo && !_blsurfHypo->GetQuadAllowed()) {
1302       Hexotic_In = TCollection_AsciiString(_blsurfHypo->GetGMFFile().c_str());
1303       if (Hexotic_In != "")
1304         defaultInputFile = false;
1305     }
1306     if (defaultInputFile) {
1307 #endif
1308       Hexotic_In  = aTmpDir + "Hexotic_In.mesh";
1309       removeHexoticFiles(Hexotic_In, Hexotic_Out);
1310       std::ofstream HexoticFile (Hexotic_In.ToCString(), std::ios::out);
1311       Ok = ( writeHexoticFile(HexoticFile, meshDS, aSmdsToHexoticIdMap, aHexoticIdToNodeMap, Hexotic_In) );
1312       HexoticFile.close();
1313 #ifdef WITH_BLSURFPLUGIN
1314     }
1315     else {
1316       removeFile( Hexotic_Out );
1317     }
1318 #endif
1319     
1320
1321     std::string run_Hexotic = getHexoticCommand(Hexotic_In, Hexotic_Out);
1322     run_Hexotic += std::string(" 1 > ") + aLogFileName.ToCString();  // dump into file
1323
1324     cout << std::endl;
1325     cout << "Hexotic command : " << run_Hexotic << std::endl;
1326
1327     
1328 //     removeHexoticFiles(Hexotic_In, Hexotic_Out);
1329 // 
1330 //     std::ofstream HexoticFile (Hexotic_In.ToCString(), std::ios::out);
1331 // 
1332 //     Ok = ( writeHexoticFile(HexoticFile, meshDS, aSmdsToHexoticIdMap, aHexoticIdToNodeMap, Hexotic_In) );
1333
1334 //     HexoticFile.close();
1335     modeFile_In += Hexotic_In;
1336     system( modeFile_In.ToCString() );
1337     aSmdsToHexoticIdMap.clear();
1338     aHexoticIdToNodeMap.clear();
1339
1340     MESSAGE("HexoticPlugin_Hexotic::Compute");
1341
1342     system( run_Hexotic.data() );
1343
1344     // --------------
1345     // read a result
1346     // --------------
1347
1348     std::ifstream fileRes( Hexotic_Out.ToCString() );
1349     modeFile_Out += Hexotic_Out;
1350     system( modeFile_Out.ToCString() );
1351     if ( ! fileRes.fail() ) {
1352       Ok = readResult( Hexotic_Out.ToCString(),
1353 #ifdef WITH_SMESH_CANCEL_COMPUTE
1354                        this,
1355 #endif
1356                        meshDS, _nbShape, tabShape, tabBox, _hexoticSdMode );
1357       if(Ok)
1358         hexahedraMessage = "success";
1359       else
1360         hexahedraMessage = "failed";
1361     }
1362     else {
1363       hexahedraMessage = "failed";
1364       cout << "Problem with Hexotic output file " << Hexotic_Out.ToCString() << std::endl;
1365       Ok = false;
1366       // analyse log file
1367       SMESH_File logFile( aLogFileName.ToCString() );
1368       if ( !logFile.eof() )
1369       {
1370         char msgLic[] = " Dlim ";
1371         const char* fileBeg = logFile.getPos(), *fileEnd = fileBeg + logFile.size();
1372         if ( std::search( fileBeg, fileEnd, msgLic, msgLic+strlen(msgLic)) != fileEnd )
1373           error("Licence problems.");
1374       }
1375     }
1376     cout << "Hexahedra meshing " << hexahedraMessage << std::endl;
1377     cout << std::endl;
1378
1379     delete [] tabShape;
1380     for (int i=0; i<_nbShape; i++)
1381       delete [] tabBox[i];
1382     delete [] tabBox;
1383     _nbShape = 0;
1384     _iShape  = 0;
1385   }
1386 #ifdef WITH_SMESH_CANCEL_COMPUTE
1387   if(_compute_canceled)
1388     return error(SMESH_Comment("interruption initiated by user"));
1389 #endif
1390   return Ok;
1391 }
1392
1393 //=============================================================================
1394 /*!
1395  * \brief Computes mesh without geometry
1396  *  \param aMesh - the mesh
1397  *  \param aHelper - helper that must be used for adding elements to \aaMesh
1398  *  \retval bool - is a success
1399  *
1400  * The method is called if ( !aMesh->HasShapeToMesh() )
1401  */
1402 //=============================================================================
1403
1404 bool HexoticPlugin_Hexotic::Compute(SMESH_Mesh & aMesh, SMESH_MesherHelper* aHelper)
1405 {
1406 #ifdef WITH_SMESH_CANCEL_COMPUTE
1407   _compute_canceled = false;
1408 #endif
1409   bool Ok = true;
1410   TCollection_AsciiString hexahedraMessage;
1411
1412   SetParameters(_hypothesis);
1413
1414   TCollection_AsciiString aTmpDir = getTmpDir();
1415   TCollection_AsciiString Hexotic_In, Hexotic_Out;
1416   TCollection_AsciiString modeFile_In( "chmod 666 " ), modeFile_Out( "chmod 666 " );
1417   TCollection_AsciiString aLogFileName = aTmpDir + "Hexotic.log";    // log
1418
1419   std::map <int,int> aSmdsToHexoticIdMap;
1420   std::map <int,const SMDS_MeshNode*> aHexoticIdToNodeMap;
1421
1422   Hexotic_In  = aTmpDir + "Hexotic_In.mesh";
1423   Hexotic_Out = aTmpDir + "Hexotic_Out.mesh";
1424
1425   std::string run_Hexotic = getHexoticCommand(Hexotic_In, Hexotic_Out);
1426   run_Hexotic += std::string(" 1 > ") + aLogFileName.ToCString();  // dump into file
1427
1428   cout << std::endl;
1429   cout << "Hexotic command : " << run_Hexotic << std::endl;
1430
1431   removeHexoticFiles(Hexotic_In, Hexotic_Out);
1432
1433   std::ofstream HexoticFile (Hexotic_In.ToCString(), std::ios::out);
1434
1435   Ok = ( writeHexoticFile(HexoticFile, aHelper, aSmdsToHexoticIdMap, Hexotic_In) );
1436
1437   HexoticFile.close();
1438   modeFile_In += Hexotic_In;
1439   system( modeFile_In.ToCString() );
1440   aSmdsToHexoticIdMap.clear();
1441   aHexoticIdToNodeMap.clear();
1442
1443   MESSAGE("HexoticPlugin_Hexotic::Compute");
1444
1445   system( run_Hexotic.data() );
1446
1447   // --------------
1448   // read a result
1449   // --------------
1450
1451   std::ifstream fileRes( Hexotic_Out.ToCString() );
1452   modeFile_Out += Hexotic_Out;
1453   system( modeFile_Out.ToCString() );
1454   if ( ! fileRes.fail() ) {
1455     Ok = readResult( Hexotic_Out.ToCString(),
1456 #ifdef WITH_SMESH_CANCEL_COMPUTE
1457                      this,
1458 #endif
1459                      aHelper, _hexoticSdMode );
1460     if(Ok)
1461       hexahedraMessage = "success";
1462     else
1463       hexahedraMessage = "failed";
1464   }
1465   else {
1466     hexahedraMessage = "failed";
1467     cout << "Problem with Hexotic output file " << Hexotic_Out << std::endl;
1468     // analyse log file
1469     SMESH_File logFile( aLogFileName.ToCString() );
1470     if ( !logFile.eof() )
1471     {
1472       char msgLic[] = " Dlim ";
1473       const char* fileBeg = logFile.getPos(), *fileEnd = fileBeg + logFile.size();
1474       if ( std::search( fileBeg, fileEnd, msgLic, msgLic+strlen(msgLic)) != fileEnd )
1475         return error("Licence problems.");
1476     }
1477     return error(SMESH_Comment("Problem with Hexotic output file ")<<Hexotic_Out);
1478   }
1479   cout << "Hexahedra meshing " << hexahedraMessage << std::endl;
1480   cout << std::endl;
1481
1482 #ifdef WITH_SMESH_CANCEL_COMPUTE
1483   if(_compute_canceled)
1484     return error(SMESH_Comment("interruption initiated by user"));
1485 #endif
1486   return Ok;
1487 }
1488
1489 //=============================================================================
1490 /*!
1491  *
1492  */
1493 //=============================================================================
1494
1495 bool HexoticPlugin_Hexotic::Evaluate(SMESH_Mesh& aMesh,
1496                                      const TopoDS_Shape& aShape,
1497                                      MapShapeNbElems& aResMap)
1498 {
1499   std::vector<int> aResVec(SMDSEntity_Last);
1500   for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0;
1501   SMESH_subMesh * sm = aMesh.GetSubMesh(aShape);
1502   aResMap.insert(std::make_pair(sm,aResVec));
1503
1504   SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
1505   smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Evaluation is not implemented",this));
1506
1507   return true;
1508 }
1509
1510 #ifdef WITH_SMESH_CANCEL_COMPUTE
1511 void HexoticPlugin_Hexotic::CancelCompute()
1512 {
1513   _compute_canceled = true;
1514 #ifdef WNT
1515 #else
1516   TCollection_AsciiString aTmpDir = getTmpDir();
1517   TCollection_AsciiString Hexotic_In = aTmpDir + "Hexotic_In.mesh";
1518   TCollection_AsciiString cmd = TCollection_AsciiString("ps ux | grep ") + Hexotic_In;
1519   cmd += TCollection_AsciiString(" | grep -v grep | awk '{print $2}' | xargs kill -9 > /dev/null 2>&1");
1520   system( cmd.ToCString() );
1521 #endif
1522 }
1523 #endif