Salome HOME
Windows compatibility
[plugins/hexoticplugin.git] / src / HexoticPlugin / HexoticPlugin_Hexotic.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   : HexoticPlugin_Hexotic.cxx
22 // Author : Lioka RAZAFINDRAZAKA (CEA)
23 // ---
24 //
25 #include "HexoticPlugin_Hexotic.hxx"
26 #include "HexoticPlugin_Hypothesis.hxx"
27 #include "MG_Hexotic_API.hxx"
28
29 #include "utilities.h"
30
31 #ifdef WIN32
32 #include <process.h>
33 #endif
34
35 #ifdef _DEBUG_
36 #define DUMP(txt) \
37 //  cout << txt
38 #else
39 #define DUMP(txt)
40 #endif
41
42 #include <SMESHDS_GroupBase.hxx>
43 #include <SMESHDS_Mesh.hxx>
44 #include <SMESH_ComputeError.hxx>
45 #include <SMESH_File.hxx>
46 #include <SMESH_Gen.hxx>
47 #include <SMESH_HypoFilter.hxx>
48 #include <SMESH_MesherHelper.hxx>
49 #include <SMESH_subMesh.hxx>
50 #include <SMESH_ControlPnt.hxx>
51
52 #include <list>
53 #include <cstdlib>
54
55 #include <Standard_ProgramError.hxx>
56
57 #include <BRepBndLib.hxx>
58 #include <BRepClass3d_SolidClassifier.hxx>
59 #include <BRep_Tool.hxx>
60 #include <Bnd_Box.hxx>
61 #include <OSD_File.hxx>
62 #include <Precision.hxx>
63 #include <TopExp_Explorer.hxx>
64 #include <TopTools_MapOfShape.hxx>
65 #include <TopoDS.hxx>
66 #include <TopoDS_Vertex.hxx>
67 #include <gp_Pnt.hxx>
68
69 #include <Basics_Utils.hxx>
70 #include <GEOMImpl_Types.hxx>
71 #include <GEOM_wrap.hxx>
72
73 #define GMFVERSION GmfDouble
74 #define GMFDIMENSION 3
75
76 using SMESHUtils::ControlPnt;
77
78 static void removeFile( const TCollection_AsciiString& fileName )
79 {
80   try {
81     OSD_File( fileName ).Remove();
82   }
83   catch ( Standard_ProgramError ) {
84     MESSAGE("Can't remove file: " << fileName.ToCString() << " ; file does not exist or permission denied");
85   }
86 }
87
88 //=============================================================================
89 /*!
90  *  
91  */
92 //=============================================================================
93
94 HexoticPlugin_Hexotic::HexoticPlugin_Hexotic(int hypId, int studyId, SMESH_Gen* gen)
95   : SMESH_3D_Algo(hypId, studyId, gen)
96 {
97   MESSAGE("HexoticPlugin_Hexotic::HexoticPlugin_Hexotic");
98   _name = "MG-Hexa";
99   _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);// 1 bit /shape type
100   _onlyUnaryInput = false;
101   _requireShape = false;
102   _iShape=0;
103   _nbShape=0;
104   _hexoticFilesKept=false;
105   _compatibleHypothesis.push_back( HexoticPlugin_Hypothesis::GetHypType() );
106 #ifdef WITH_BLSURFPLUGIN
107   _blsurfHypo = NULL;
108 #endif
109   _computeCanceled = false;
110   
111   // Copy of what is done in BLSURFPLugin TODO : share the code
112   smeshGen_i = SMESH_Gen_i::GetSMESHGen();
113   CORBA::Object_var anObject = smeshGen_i->GetNS()->Resolve("/myStudyManager");
114   SALOMEDS::StudyManager_var aStudyMgr = SALOMEDS::StudyManager::_narrow(anObject);
115   
116   myStudy = NULL;
117   myStudy = aStudyMgr->GetStudyByID(_studyId);
118   if ( !myStudy->_is_nil() )
119     MESSAGE("myStudy->StudyId() = " << myStudy->StudyId());
120 }
121
122 //=============================================================================
123 /*!
124  *  
125  */
126 //=============================================================================
127
128 HexoticPlugin_Hexotic::~HexoticPlugin_Hexotic()
129 {
130   MESSAGE("HexoticPlugin_Hexotic::~HexoticPlugin_Hexotic");
131 }
132
133
134 #ifdef WITH_BLSURFPLUGIN
135 bool HexoticPlugin_Hexotic::CheckBLSURFHypothesis( SMESH_Mesh&         aMesh,
136                                                    const TopoDS_Shape& aShape )
137 {
138   // MESSAGE("HexoticPlugin_Hexotic::CheckBLSURFHypothesis");
139   _blsurfHypo = NULL;
140
141   std::list<const SMESHDS_Hypothesis*>::const_iterator itl;
142   const SMESHDS_Hypothesis* theHyp;
143
144   // If a BLSURF hypothesis is applied, get it
145   SMESH_HypoFilter blsurfFilter;
146   blsurfFilter.Init( blsurfFilter.HasName( BLSURFPlugin_Hypothesis::GetHypType() ));
147   std::list<const SMESHDS_Hypothesis *> appliedHyps;
148   aMesh.GetHypotheses( aShape, blsurfFilter, appliedHyps, false );
149
150   if ( appliedHyps.size() > 0 ) {
151     itl = appliedHyps.begin();
152     theHyp = (*itl); // use only the first hypothesis
153     std::string hypName = theHyp->GetName();
154     if (hypName == BLSURFPlugin_Hypothesis::GetHypType()) {
155       _blsurfHypo = static_cast<const BLSURFPlugin_Hypothesis*> (theHyp);
156       ASSERT(_blsurfHypo);
157       return true;
158     }
159   }
160   return false;
161 }
162 #endif
163
164 //=============================================================================
165 /*!
166  *  
167  */
168 //=============================================================================
169
170 bool HexoticPlugin_Hexotic::CheckHypothesis( SMESH_Mesh&                          aMesh,
171                                              const TopoDS_Shape&                  aShape,
172                                              SMESH_Hypothesis::Hypothesis_Status& aStatus )
173 {
174   // MESSAGE("HexoticPlugin_Hexotic::CheckHypothesis");
175   _hypothesis = NULL;
176
177   std::list<const SMESHDS_Hypothesis*>::const_iterator itl;
178   const SMESHDS_Hypothesis* theHyp;
179
180   const std::list<const SMESHDS_Hypothesis*>& hyps = GetUsedHypothesis(aMesh, aShape, false);
181   int nbHyp = hyps.size();
182   if (!nbHyp) {
183     aStatus = SMESH_Hypothesis::HYP_OK;
184     return true;  // can work with no hypothesis
185   }
186
187   itl = hyps.begin();
188   theHyp = (*itl); // use only the first hypothesis
189
190   std::string hypName = theHyp->GetName();
191   if (hypName == HexoticPlugin_Hypothesis::GetHypType() ) {
192     _hypothesis = static_cast<const HexoticPlugin_Hypothesis*> (theHyp);
193     ASSERT(_hypothesis);
194     aStatus = SMESH_Hypothesis::HYP_OK;
195   }
196   else
197     aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
198   
199 #ifdef WITH_BLSURFPLUGIN
200   CheckBLSURFHypothesis(aMesh, aShape);
201 #endif
202   
203   return aStatus == SMESH_Hypothesis::HYP_OK;
204 }
205
206 //=======================================================================
207 //function : findShape
208 //purpose  :
209 //=======================================================================
210
211 static TopoDS_Shape findShape(SMDS_MeshNode**     t_Node,
212                               TopoDS_Shape        aShape,
213                               const TopoDS_Shape* t_Shape,
214                               double**            t_Box,
215                               const int           nShape)
216 {
217   double pntCoor[3];
218   int iShape, nbNode = 8;
219
220   for ( int i=0; i<3; i++ ) {
221     pntCoor[i] = 0;
222     for ( int j=0; j<nbNode; j++ ) {
223       if ( i == 0) pntCoor[i] += t_Node[j]->X();
224       if ( i == 1) pntCoor[i] += t_Node[j]->Y();
225       if ( i == 2) pntCoor[i] += t_Node[j]->Z();
226     }
227     pntCoor[i] /= nbNode;
228   }
229   gp_Pnt aPnt(pntCoor[0], pntCoor[1], pntCoor[2]);
230
231   if ( aShape.IsNull() ) aShape = t_Shape[0];
232   BRepClass3d_SolidClassifier SC (aShape, aPnt, Precision::Confusion());
233   if ( !(SC.State() == TopAbs_IN) ) {
234     aShape.Nullify();
235     for (iShape = 0; iShape < nShape && aShape.IsNull(); iShape++) {
236       if ( !( pntCoor[0] < t_Box[iShape][0] || t_Box[iShape][1] < pntCoor[0] ||
237               pntCoor[1] < t_Box[iShape][2] || t_Box[iShape][3] < pntCoor[1] ||
238               pntCoor[2] < t_Box[iShape][4] || t_Box[iShape][5] < pntCoor[2]) ) {
239         BRepClass3d_SolidClassifier SC (t_Shape[iShape], aPnt, Precision::Confusion());
240         if (SC.State() == TopAbs_IN)
241           aShape = t_Shape[iShape];
242       }
243     }
244   }
245   return aShape;
246 }
247
248 //=======================================================================
249 //function : getNbShape
250 //purpose  :
251 //=======================================================================
252
253 static int getNbShape(MG_Hexotic_API* hexaOutput, int iMesh, GmfKwdCod what, int defaultValue=0)
254 {
255   int number = hexaOutput->GmfStatKwd( iMesh, what );
256   if ( number > 0 )
257   {
258   // std::string aLine;
259   // std::ifstream file(aFile.c_str());
260   // while ( !file.eof() ) {
261   //   getline( file, aLine);
262   //   if ( aLine == aString ) {
263   //     getline( file, aLine);
264   //     std::istringstream stringFlux( aLine );
265   //     stringFlux >> number;
266       number = ( number + defaultValue + std::abs(number - defaultValue) ) / 2;
267     //   break;
268     // }
269   }
270   else
271   {
272     number = defaultValue;
273   }
274   //file.close();
275   return number;
276 }
277
278 //=======================================================================
279 //function : countShape
280 //purpose  :
281 //=======================================================================
282
283 static int countShape( SMESH_Mesh* mesh, TopAbs_ShapeEnum shape )
284 {
285   if ( !mesh->HasShapeToMesh() )
286     return 0;
287   TopExp_Explorer expShape ( mesh->GetShapeToMesh(), shape );
288   TopTools_MapOfShape mapShape;
289   int nbShape = 0;
290   for ( ; expShape.More(); expShape.Next() ) {
291     if (mapShape.Add(expShape.Current())) {
292       nbShape++;
293     }
294   }
295   return nbShape;
296 }
297
298 //=======================================================================
299 //function : getShape
300 //purpose  :
301 //=======================================================================
302
303 template < class Mesh, class Shape, class Tab >
304 void getShape(Mesh* mesh, Shape shape, Tab *t_Shape)
305 {
306   TopExp_Explorer expShape ( mesh->ShapeToMesh(), shape );
307   TopTools_MapOfShape mapShape;
308   for ( int i=0; expShape.More(); expShape.Next() ) {
309     if (mapShape.Add(expShape.Current())) {
310       t_Shape[i] = expShape.Current();
311       i++;
312     }
313   }
314   return;
315 }
316
317 //=======================================================================
318 //function : printWarning
319 //purpose  :
320 //=======================================================================
321
322 static void printWarning(const int nbExpected, std::string aString, const int nbFound) {
323   cout << std::endl;
324   cout << "WARNING : " << nbExpected << " " << aString << " expected, MG-Hexa has found " << nbFound << std::endl;
325   cout << "=======" << std::endl;
326   cout << std::endl;
327   return;
328 }
329
330 //=======================================================================
331 //function : removeHexoticFiles
332 //purpose  :
333 //=======================================================================
334
335 static void removeHexoticFiles(TCollection_AsciiString file_In, TCollection_AsciiString file_Out) {
336   removeFile( file_In );
337   removeFile( file_Out );
338 }
339
340 //=======================================================================
341 //function : splitQuads
342 //purpose  : splits all quadrangles into triangles
343 //=======================================================================
344
345 static void splitQuads(SMESH_Mesh& aMesh)
346 {
347   SMESH_MeshEditor spliter( &aMesh );
348
349   TIDSortedElemSet elems;
350   SMDS_ElemIteratorPtr eIt = aMesh.GetMeshDS()->elementsIterator();
351   while( eIt->more() )
352     elems.insert( elems.end(), eIt->next() );
353   
354   spliter.QuadToTri ( elems, /*the13Diag=*/true);
355 }
356
357 //=======================================================================
358 //function : writeInput
359 //purpose  : pass a mesh to input of MG-Hexa
360 //=======================================================================
361
362 static void writeInput(MG_Hexotic_API*     theHexaInput,
363                        const char*         theFile,
364                        const SMESHDS_Mesh* theMeshDS)
365 {
366   int meshID = theHexaInput->GmfOpenMesh( theFile, GmfWrite, GMFVERSION, GMFDIMENSION);
367   
368   // nodes
369   int iN = 0, nbNodes = theMeshDS->NbNodes();
370   theHexaInput->GmfSetKwd( meshID, GmfVertices, nbNodes );
371   std::map< const SMDS_MeshNode*, int, TIDCompare > node2IdMap;
372   SMDS_NodeIteratorPtr nodeIt = theMeshDS->nodesIterator();
373   SMESH_TNodeXYZ n;
374   while ( nodeIt->more() )
375   {
376     n.Set( nodeIt->next() );
377     theHexaInput->GmfSetLin( meshID, GmfVertices, n.X(), n.Y(), n.Z(), n._node->getshapeId() );
378     node2IdMap.insert( node2IdMap.end(), std::make_pair( n._node, ++iN ));
379   }
380
381   // edges
382   SMDS_ElemIteratorPtr elemIt = theMeshDS->elementsIterator( SMDSAbs_Edge );
383   if ( elemIt->more() )
384   {
385     int nbEdges = theMeshDS->GetMeshInfo().NbElements( SMDSAbs_Edge );
386     theHexaInput->GmfSetKwd(meshID, GmfEdges, nbEdges );
387     for ( int gmfID = 1; elemIt->more(); ++gmfID )
388     {
389       const SMDS_MeshElement* edge = elemIt->next();
390       theHexaInput->GmfSetLin(meshID, GmfEdges, 
391                               node2IdMap[ edge->GetNode( 0 )],
392                               node2IdMap[ edge->GetNode( 1 )],
393                               edge->getshapeId() );
394     }
395   }
396
397   // triangles
398   elemIt = theMeshDS->elementGeomIterator( SMDSGeom_TRIANGLE );
399   if ( elemIt->more() )
400   {
401     int nbTria = theMeshDS->GetMeshInfo().NbElements( SMDSGeom_TRIANGLE );
402     theHexaInput->GmfSetKwd(meshID, GmfTriangles, nbTria );
403     for ( int gmfID = 1; elemIt->more(); ++gmfID )
404     {
405       const SMDS_MeshElement* tria = elemIt->next();
406       theHexaInput->GmfSetLin(meshID, GmfTriangles, 
407                               node2IdMap[ tria->GetNode( 0 )],
408                               node2IdMap[ tria->GetNode( 1 )],
409                               node2IdMap[ tria->GetNode( 2 )],
410                               tria->getshapeId() );
411     }
412   }
413   theHexaInput->GmfCloseMesh( meshID );
414 }
415
416 //=======================================================================
417 //function : readResult
418 //purpose  : Read GMF file in case of a mesh with geometry
419 //=======================================================================
420
421 static bool readResult(MG_Hexotic_API*       theHexaOutput,
422                        const char*           theFile,
423                        HexoticPlugin_Hexotic*theAlgo,
424                        SMESH_MesherHelper*   theHelper,
425                        const int             nbShape = 0,
426                        const TopoDS_Shape*   tabShape = 0,
427                        double**              tabBox = 0)
428 {
429   SMESH_Mesh*     theMesh = theHelper->GetMesh();
430   SMESHDS_Mesh* theMeshDS = theHelper->GetMeshDS();
431
432   // ---------------------------------
433   // Read generated elements and nodes
434   // ---------------------------------
435
436   TopoDS_Shape aShape;
437   TopoDS_Vertex aVertex;
438   std::string token;
439   int shapeID, hexoticShapeID;
440   const int IdShapeRef = 2;
441   int *tabID = 0;
442   double epsilon = Precision::Confusion();
443   std::map <std::string,int> mapField;
444   SMDS_MeshNode** HexoticNode;
445   TopoDS_Shape *tabCorner;
446
447   const int nbDomains = countShape( theMesh, TopAbs_SHELL );
448   const int holeID = -1;
449
450   if ( nbDomains > 0 )
451   {
452     tabID = new int[nbDomains];
453
454     for (int i=0; i<nbDomains; i++)
455       tabID[i] = 0;
456     if ( nbDomains == 1 )
457       tabID[0] = theMeshDS->ShapeToIndex( tabShape[0] );
458   }
459   else
460   {
461     tabID = new int[1];
462     tabID[0] = 1;
463   }
464
465   SMDS_ElemIteratorPtr eIt = theMeshDS->elementsIterator();
466   while( eIt->more() )
467     theMeshDS->RemoveFreeElement( eIt->next(), /*sm=*/0 );
468   SMDS_NodeIteratorPtr nIt = theMeshDS->nodesIterator();
469   while ( nIt->more() )
470     theMeshDS->RemoveFreeNode( nIt->next(), /*sm=*/0 );
471
472   theHelper->SetElementsOnShape( false );
473
474   int ver, dim;
475   int meshID = theHexaOutput->GmfOpenMesh( theFile, GmfRead, &ver, &dim );
476
477   int nbVertices  = getNbShape(theHexaOutput, meshID, GmfVertices );
478   int nbCorners   = getNbShape(theHexaOutput, meshID, GmfCorners, countShape( theMesh, TopAbs_VERTEX ));
479   if ( nbVertices == 0 )
480     return false;
481
482   tabCorner   = new TopoDS_Shape[ nbCorners ];
483   HexoticNode = new SMDS_MeshNode*[ nbVertices + 1 ];
484
485   if ( nbCorners > 0 )
486     getShape(theMeshDS, TopAbs_VERTEX, tabCorner);
487
488   int nbNodes = theHexaOutput->GmfStatKwd( meshID, GmfVertices );
489   if ( nbNodes > 0 )
490   {
491     theHexaOutput->GmfGotoKwd( meshID, GmfVertices );
492     double x,y,z;
493     for ( int aHexoticID = 1; aHexoticID <= nbNodes; ++aHexoticID )
494     {
495       if ( theAlgo->computeCanceled() )
496         return false;
497       theHexaOutput->GmfGetLin( meshID, GmfVertices, &x, &y, &z, &shapeID );
498       HexoticNode[ aHexoticID ] = theHelper->AddNode( x,y,z );
499     }
500   }
501
502   int nodeID[8];
503   SMDS_MeshNode* node[8];
504   SMDS_MeshElement * aHexoticElement;
505
506   nbCorners = theHexaOutput->GmfStatKwd( meshID, GmfCorners );
507   if ( nbCorners > 0 && nbDomains > 0 )
508   {
509     theHexaOutput->GmfGotoKwd( meshID, GmfCorners );
510     for ( int iElem = 0; iElem < nbCorners; iElem++ )
511     {
512       if ( theAlgo->computeCanceled() )
513         return false;
514       theHexaOutput->GmfGetLin( meshID, GmfCorners, &nodeID[0] );
515       node[0] = HexoticNode[ nodeID[0] ];
516       gp_Pnt HexoticPnt ( node[0]->X(), node[0]->Y(), node[0]->Z() );
517       for ( int i = 0; i < nbCorners; i++ )
518       {
519         aVertex = TopoDS::Vertex( tabCorner[i] );
520         gp_Pnt aPnt = BRep_Tool::Pnt( aVertex );
521         if ( aPnt.Distance( HexoticPnt ) < epsilon )
522         {
523           theMeshDS->SetNodeOnVertex( node[0], aVertex );
524           break;
525         }
526       }
527     }
528   }
529
530   int nbEdges = theHexaOutput->GmfStatKwd( meshID, GmfEdges );
531   if ( nbEdges > 0 )
532   {
533     theHexaOutput->GmfGotoKwd( meshID, GmfEdges );
534     for ( int iElem = 0; iElem < nbEdges; iElem++ )
535     {
536       if ( theAlgo->computeCanceled() )
537         return false;
538       theHexaOutput->GmfGetLin( meshID, GmfEdges, &nodeID[0], &nodeID[1], &shapeID );
539       for ( int i = 0; i < 2; ++i )
540       {
541         node[i] = HexoticNode[ nodeID[i]];
542         if ( shapeID > 0 && node[i]->getshapeId() < 1 )
543           theMeshDS->SetNodeOnEdge( node[i], shapeID );
544       }
545       aHexoticElement = theHelper->AddEdge( node[0], node[1] );
546       if ( shapeID > 0 && aHexoticElement->getshapeId() < 1 )
547         theMeshDS->SetMeshElementOnShape( aHexoticElement, shapeID );
548     }
549   }
550
551   int nbQuad = theHexaOutput->GmfStatKwd( meshID, GmfQuadrilaterals );
552   if ( nbQuad > 0 )
553   {
554     theHexaOutput->GmfGotoKwd( meshID, GmfQuadrilaterals );
555     for ( int iElem = 0; iElem < nbQuad; iElem++ )
556     {
557       if ( theAlgo->computeCanceled() )
558         return false;
559       theHexaOutput->GmfGetLin( meshID, GmfQuadrilaterals,
560                                 &nodeID[0], &nodeID[1], &nodeID[2], &nodeID[3], &shapeID );
561       for ( int i = 0; i < 4; ++i )
562       {
563         node[i] = HexoticNode[ nodeID[i]];
564         if ( shapeID > 0 && node[i]->getshapeId() < 1 )
565           theMeshDS->SetNodeOnFace( node[i], shapeID );
566       }
567       aHexoticElement = theHelper->AddFace( node[0], node[1], node[2], node[3] );
568       if ( shapeID > 0 && aHexoticElement->getshapeId() < 1 )
569         theMeshDS->SetMeshElementOnShape( aHexoticElement, shapeID );
570     }
571   }
572
573   int nbHexa = theHexaOutput->GmfStatKwd( meshID, GmfHexahedra );
574   if ( nbHexa > 0 )
575   {
576     theHexaOutput->GmfGotoKwd( meshID, GmfHexahedra );
577     for ( int iElem = 0; iElem < nbHexa; iElem++ )
578     {
579       if ( theAlgo->computeCanceled() )
580         return false;
581       theHexaOutput->GmfGetLin( meshID, GmfHexahedra,
582                                 &nodeID[0], &nodeID[1], &nodeID[2], &nodeID[3],
583                                 &nodeID[4], &nodeID[5], &nodeID[6], &nodeID[7],
584                                 &shapeID );
585       for ( int i = 0; i < 8; ++i )
586       {
587         node[i] = HexoticNode[ nodeID[i]];
588       }
589       if ( nbDomains > 1 ) {
590         hexoticShapeID = shapeID - IdShapeRef;
591         if ( tabID[ hexoticShapeID ] == 0 ) {
592           aShape = findShape(node, aShape, tabShape, tabBox, nbShape);
593           shapeID = aShape.IsNull() ? holeID : theMeshDS->ShapeToIndex( aShape );
594           tabID[ hexoticShapeID ] = shapeID;
595         }
596         else {
597           shapeID = tabID[ hexoticShapeID ];
598         }
599         if ( iElem == ( nbHexa - 1) ) {
600           int shapeAssociated = 0;
601           for ( int i=0; i<nbDomains; i++ ) {
602             if (tabID[i] > 0 )
603               shapeAssociated += 1;
604           }
605           if ( shapeAssociated != nbShape )
606             printWarning(nbShape, "domains", shapeAssociated);
607         }
608       }
609       else {
610         shapeID = tabID[0];
611       }
612
613       if ( shapeID != holeID )
614       {
615         for ( int i = 0; i < 8; ++i )
616         {
617           if ( node[i]->NbInverseElements( SMDSAbs_Face ) == 0 )
618             theMeshDS->SetNodeInVolume( node[i], shapeID );
619         }
620         aHexoticElement = theHelper->AddVolume( node[0], node[3], node[2], node[1],
621                                                 node[4], node[7], node[6], node[5]);
622         if ( aHexoticElement->getshapeId() < 1 )
623           theMeshDS->SetMeshElementOnShape( aHexoticElement, shapeID );
624       }
625     }
626   }
627   cout << std::endl;
628
629   // remove nodes in holes
630   if ( nbDomains > 1 )
631   {
632     SMESHDS_SubMesh* subMesh = 0;
633     for ( int i = 1; i <= nbNodes; ++i )
634       if ( HexoticNode[i]->NbInverseElements() == 0 )
635       {
636         theMeshDS->RemoveFreeNode( HexoticNode[i], subMesh, /*fromGroups=*/false );
637       }
638   }
639   delete [] tabID;
640   delete [] tabCorner;
641   delete [] HexoticNode;
642   return true;
643 }
644
645 //=============================================================================
646 /*!
647  * Pass parameters to MG-Hexa
648  */
649 //=============================================================================
650
651 void HexoticPlugin_Hexotic::SetParameters(const HexoticPlugin_Hypothesis* hyp) {
652
653   MESSAGE("HexoticPlugin_Hexotic::SetParameters");
654   if (hyp) {
655     _hexesMinLevel = hyp->GetHexesMinLevel();
656     _hexesMaxLevel = hyp->GetHexesMaxLevel();
657     _hexesMinSize = hyp->GetMinSize();
658     _hexesMaxSize = hyp->GetMaxSize();
659     _hexoticIgnoreRidges = hyp->GetHexoticIgnoreRidges();
660     _hexoticInvalidElements = hyp->GetHexoticInvalidElements();
661     _hexoticSharpAngleThreshold = hyp->GetHexoticSharpAngleThreshold();
662     _hexoticNbProc = hyp->GetHexoticNbProc();
663     _hexoticWorkingDirectory = hyp->GetHexoticWorkingDirectory();
664     _hexoticVerbosity = hyp->GetHexoticVerbosity();
665     _hexoticMaxMemory = hyp->GetHexoticMaxMemory();
666     _hexoticSdMode = hyp->GetHexoticSdMode();
667     _textOptions = hyp->GetAdvancedOption();
668     _sizeMaps = hyp->GetSizeMaps();
669     _nbLayers = hyp->GetNbLayers();
670     _firstLayerSize = hyp->GetFirstLayerSize();
671     _direction = hyp->GetDirection();
672     _growth = hyp->GetGrowth();
673     _facesWithLayers = hyp->GetFacesWithLayers();
674     _imprintedFaces = hyp->GetImprintedFaces();
675   }
676   else {
677     cout << std::endl;
678     cout << "WARNING : The MG-Hexa default parameters are taken into account" << std::endl;
679     cout << "=======" << std::endl;
680     _hexesMinLevel = hyp->GetDefaultHexesMinLevel();
681     _hexesMaxLevel = hyp->GetDefaultHexesMaxLevel();
682     _hexesMinSize = hyp->GetDefaultMinSize();
683     _hexesMaxSize = hyp->GetDefaultMaxSize();
684     _hexoticIgnoreRidges = hyp->GetDefaultHexoticIgnoreRidges();
685     _hexoticInvalidElements = hyp->GetDefaultHexoticInvalidElements();
686     _hexoticSharpAngleThreshold = hyp->GetDefaultHexoticSharpAngleThreshold();
687     _hexoticNbProc = hyp->GetDefaultHexoticNbProc();
688     _hexoticWorkingDirectory = hyp->GetDefaultHexoticWorkingDirectory();
689     _hexoticVerbosity = hyp->GetDefaultHexoticVerbosity();
690     _hexoticMaxMemory = hyp->GetDefaultHexoticMaxMemory();
691     _hexoticSdMode = hyp->GetDefaultHexoticSdMode();
692     _textOptions = hyp->GetDefaultTextOptions();
693     _sizeMaps = hyp->GetDefaultHexoticSizeMaps();
694     _nbLayers = hyp->GetDefaultNbLayers();
695     _firstLayerSize = hyp->GetDefaultFirstLayerSize();
696     _direction = hyp->GetDefaultDirection();
697     _growth = hyp->GetDefaultGrowth();
698     _facesWithLayers = hyp->GetDefaultFacesWithLayers();
699     _imprintedFaces = hyp->GetDefaultImprintedFaces();
700   }
701 }
702
703 //=======================================================================
704 //function : getSuffix
705 //purpose  : Returns a suffix that will be unique for the current process
706 //=======================================================================
707
708 static TCollection_AsciiString getSuffix()
709 {
710   TCollection_AsciiString aSuffix = "";
711   aSuffix += "_";
712 #ifndef WIN32
713   aSuffix += getenv("USER");
714 #else
715   std::string uname = std::string(getenv("USERNAME"));
716   replace(uname.begin(), uname.end(), ' ', '_');
717   aSuffix += uname.c_str();
718 #endif
719   aSuffix += "_";
720   aSuffix += Kernel_Utils::GetHostname().c_str();
721   aSuffix += "_";
722 #ifndef WIN32
723   aSuffix += getpid();
724 #else
725   aSuffix += _getpid();
726 #endif
727
728   return aSuffix;
729 }
730
731 //================================================================================
732 /*!
733  * \brief Returns a command to run MG-Hexa mesher
734  */
735 //================================================================================
736
737 std::string HexoticPlugin_Hexotic::getHexoticCommand(const TCollection_AsciiString& Hexotic_In,
738                                                      const TCollection_AsciiString& Hexotic_Out,
739                                                      const TCollection_AsciiString& Hexotic_SizeMap_Prefix,
740                                                      const bool                     forExecutable) const
741 {
742   cout << std::endl;
743   cout << "MG-Hexa execution..." << std::endl;
744   cout << _name << " parameters :" << std::endl;
745   cout << "    " << _name << " Verbosity = " << _hexoticVerbosity << std::endl;
746   cout << "    " << _name << " Max Memory = " << _hexoticMaxMemory << std::endl;
747   cout << "    " << _name << " Segments Min Level = " << _hexesMinLevel << std::endl;
748   cout << "    " << _name << " Segments Max Level = " << _hexesMaxLevel << std::endl;
749   cout << "    " << _name << " Segments Min Size = " << _hexesMinSize << std::endl;
750   cout << "    " << _name << " Segments Max Size = " << _hexesMaxSize << std::endl;
751   cout << "    " << "MG-Hexa can ignore ridges : " << (_hexoticIgnoreRidges ? "yes":"no") << std::endl;
752   cout << "    " << "MG-Hexa authorize invalide elements : " << ( _hexoticInvalidElements ? "yes":"no") << std::endl;
753   cout << "    " << _name << " Sharp angle threshold = " << _hexoticSharpAngleThreshold << " degrees" << std::endl;
754   cout << "    " << _name << " Number of threads = " << _hexoticNbProc << std::endl;
755   cout << "    " << _name << " Working directory = \"" << _hexoticWorkingDirectory << "\"" << std::endl;
756   cout << "    " << _name << " Sub. Dom mode = " << _hexoticSdMode << std::endl;
757   cout << "    " << _name << " Text options = \"" << _textOptions << "\"" << std::endl;
758   cout << "    " << _name << " Number of layers = " << _nbLayers << std::endl;
759   cout << "    " << _name << " Size of the first layer  = " << _firstLayerSize << std::endl;
760   cout << "    " << _name << " Direction of the layers = " << ( _direction ? "Inward" : "Outward" ) << std::endl;
761   cout << "    " << _name << " Growth = " << _growth << std::endl;
762   if (!_facesWithLayers.empty()) {
763     cout << "    " << _name << " Faces with layers = ";
764     for (size_t i = 0; i < _facesWithLayers.size(); i++)
765     {
766       cout << _facesWithLayers.at(i);
767       if ((i + 1) != _facesWithLayers.size())
768         cout << ", ";
769     }
770     cout << std::endl;
771   }
772   if (!_imprintedFaces.empty()) {
773     cout << "    " << _name << " Imprinted faces = ";
774     for (size_t i = 0; i < _imprintedFaces.size(); i++)
775     {
776       cout << _imprintedFaces.at(i);
777       if ((i + 1) != _imprintedFaces.size())
778         cout << ", ";
779     }
780     cout << std::endl;
781   }
782
783   TCollection_AsciiString run_Hexotic("mg-hexa.exe");
784
785   TCollection_AsciiString minl = " --min_level ", maxl = " --max_level ", angle = " --ridge_angle ";
786   TCollection_AsciiString mins = " --min_size ", maxs = " --max_size ";
787   TCollection_AsciiString in   = " --in ",   out  = " --out ";
788   TCollection_AsciiString sizeMap = " --read_sizemap ";
789   TCollection_AsciiString ignoreRidges = " --compute_ridges no ", invalideElements = " --allow_invalid_elements yes ";
790   TCollection_AsciiString subdom = " --components ";
791 #ifndef WIN32
792   TCollection_AsciiString proc = " --max_number_of_threads ";
793 #endif
794   TCollection_AsciiString verb = " --verbose ";
795   TCollection_AsciiString maxmem = " --max_memory ";
796
797   TCollection_AsciiString comNbLayers = " --number_of_boundary_layers ";
798   TCollection_AsciiString comFirstLayerSize = " --height_of_the_first_layer ";
799   TCollection_AsciiString comDirection = " --boundary_layers_subdomain_direction ";
800   TCollection_AsciiString comGrowth = " --boundary_layers_geometric_progression ";
801   TCollection_AsciiString comFacesWithLayers = " --boundary_layers_surface_ids ";
802   TCollection_AsciiString comImptintedFaces = " --imprinted_surface_ids ";
803
804   TCollection_AsciiString minLevel, maxLevel, minSize, maxSize, sharpAngle, mode, nbproc, verbosity, maxMemory,
805                           textOptions, nbLayers, firstLayerSize, direction, growth, facesWithLayers, imprintedFaces;
806   minLevel = _hexesMinLevel;
807   maxLevel = _hexesMaxLevel;
808   minSize = _hexesMinSize;
809   maxSize = _hexesMaxSize;
810   sharpAngle = _hexoticSharpAngleThreshold;
811   // Mode translation for mg-tetra 1.1
812   switch ( _hexoticSdMode )
813   {
814     case 1:
815       mode = "outside_skin_only";
816       break;
817     case 2:
818       mode = "outside_components";
819       break;
820     case 3:
821       mode = "all";
822       break;
823     case 4:
824       mode = "all --manifold_geometry no";
825       break;
826   }
827   nbproc = _hexoticNbProc;
828   verbosity = _hexoticVerbosity;
829   maxMemory = _hexoticMaxMemory;
830   textOptions = (" " + _textOptions + " ").c_str();
831   nbLayers = _nbLayers;
832   firstLayerSize = _firstLayerSize;
833   direction = _direction ? "1" : "-1";
834   growth = _growth;
835   for (size_t i = 0; i < _facesWithLayers.size(); i++)
836   {
837     facesWithLayers += _facesWithLayers[i];
838     if ((i + 1) != _facesWithLayers.size())
839       facesWithLayers += ",";
840   }
841   for (size_t i = 0; i < _imprintedFaces.size(); i++)
842   {
843     imprintedFaces += _imprintedFaces[i];
844     if ((i + 1) != _imprintedFaces.size())
845       imprintedFaces += ",";
846   }
847
848   if (_hexoticIgnoreRidges)
849     run_Hexotic +=  ignoreRidges;
850
851   if (_hexoticInvalidElements)
852     run_Hexotic +=  invalideElements;
853
854   if (_hexesMinSize > 0)
855     run_Hexotic +=  mins + minSize;
856
857   if (_hexesMaxSize > 0)
858     run_Hexotic +=  maxs + maxSize;
859
860   if (_hexesMinLevel > 0)
861     run_Hexotic +=  minl + minLevel;
862
863   if (_hexesMaxLevel > 0)
864     run_Hexotic +=  maxl + maxLevel;
865
866   if (_hexoticSharpAngleThreshold > 0)
867     run_Hexotic +=  angle + sharpAngle;
868   
869   if (_sizeMaps.begin() != _sizeMaps.end() && forExecutable )
870     run_Hexotic += sizeMap + Hexotic_SizeMap_Prefix;
871
872   if (_nbLayers       > 0 &&
873       _firstLayerSize > 0 &&
874       _growth         > 0 &&
875       !_facesWithLayers.empty())
876   {
877     run_Hexotic += comNbLayers + nbLayers;
878     run_Hexotic += comFirstLayerSize + firstLayerSize;
879     run_Hexotic += comDirection + direction;
880     run_Hexotic += comGrowth + growth;
881     run_Hexotic += comFacesWithLayers + facesWithLayers;
882     if (!_imprintedFaces.empty())
883       run_Hexotic += comImptintedFaces + imprintedFaces;
884   }
885   if ( forExecutable )
886     run_Hexotic += in + Hexotic_In + out + Hexotic_Out;
887   run_Hexotic += subdom + mode;
888 #ifndef WIN32
889   run_Hexotic += proc + nbproc;
890 #endif
891   run_Hexotic += verb + verbosity;
892   run_Hexotic += maxmem + maxMemory;
893
894   if (!_textOptions.empty())
895     run_Hexotic += textOptions;
896
897   return run_Hexotic.ToCString();
898 }
899
900 // TODO : this is a duplication of some code found in BLSURFPlugin_BLSURF find a proper
901 // way to share it
902 TopoDS_Shape HexoticPlugin_Hexotic::entryToShape(std::string entry)
903 {
904   MESSAGE("HexoticPlugin_Hexotic::entryToShape "<<entry );
905   if ( myStudy->_is_nil() )
906     throw SALOME_Exception("MG-Hexa plugin can't work w/o publishing in the study");
907   GEOM::GEOM_Object_var aGeomObj;
908   TopoDS_Shape S = TopoDS_Shape();
909   SALOMEDS::SObject_var aSObj = myStudy->FindObjectID( entry.c_str() );
910   if (!aSObj->_is_nil()) {
911     CORBA::Object_var obj = aSObj->GetObject();
912     aGeomObj = GEOM::GEOM_Object::_narrow(obj);
913     aSObj->UnRegister();
914   }
915   if ( !aGeomObj->_is_nil() )
916     S = smeshGen_i->GeomObjectToShape( aGeomObj.in() );
917   return S;
918 }
919
920 //================================================================================
921 /*!
922  * \brief Produces a .mesh file with the size maps informations to give to Hexotic
923  */
924 //================================================================================
925 std::vector<std::string> HexoticPlugin_Hexotic::writeSizeMapFile( MG_Hexotic_API* mgInput,
926                                                                   std::string     sizeMapPrefix )
927 {
928   HexoticPlugin_Hypothesis::THexoticSizeMaps::iterator it;
929   
930   std::vector<ControlPnt> points;
931   // Iterate on the size maps
932   for (it=_sizeMaps.begin(); it!=_sizeMaps.end(); it++)
933   {
934     // Step 1 : Get the GEOM object entry and the size 
935     // from the _sizeMaps infos
936     std::string anEntry = it->first;
937     double aLocalSize = it->second;
938     TopoDS_Shape aShape = entryToShape( anEntry );
939     
940     // Step 2 : Create the points
941     createControlPoints( aShape, aLocalSize, points );
942   }
943
944   // Write the .mesh size map file
945
946   std::string myVerticesFile = sizeMapPrefix + ".mesh";
947   std::string      mySolFile = sizeMapPrefix + ".sol";
948   
949   // Open files
950   int verticesFileID =
951     mgInput->GmfOpenMesh( myVerticesFile.c_str(), GmfWrite, GMFVERSION, GMFDIMENSION );  
952   int solFileID =
953     mgInput->GmfOpenMesh( mySolFile.c_str(), GmfWrite, GMFVERSION, GMFDIMENSION );
954   
955   int pointsNumber = points.size();
956   
957   // Vertices Keyword
958   mgInput->GmfSetKwd( verticesFileID, GmfVertices, pointsNumber );
959   // SolAtVertices Keyword
960   int TypTab[] = {GmfSca};
961   mgInput->GmfSetKwd(solFileID, GmfSolAtVertices, pointsNumber, 1, TypTab);
962   
963   // Read the control points information from the vector and write it into the files
964   double ValTab[1];
965   std::vector<ControlPnt>::const_iterator points_it;
966   for (points_it = points.begin(); points_it != points.end(); points_it++ )
967   {
968     mgInput->GmfSetLin( verticesFileID, GmfVertices, points_it->X(), points_it->Y(), points_it->Z(), 0 );
969     ValTab[0] = points_it->Size();
970     mgInput->GmfSetLin( solFileID, GmfSolAtVertices, ValTab);
971   }
972
973   // Close Files
974   mgInput->GmfCloseMesh( verticesFileID );
975   mgInput->GmfCloseMesh( solFileID );
976
977   std::vector<std::string> fileNames(2);
978   fileNames[0] = myVerticesFile;
979   fileNames[1] = mySolFile;
980
981   return fileNames;
982 }
983
984 //=============================================================================
985 /*!
986  * Here we are going to use the MG-Hexa mesher
987  */
988 //=============================================================================
989
990 bool HexoticPlugin_Hexotic::Compute(SMESH_Mesh&          aMesh,
991                                     const TopoDS_Shape& aShape)
992 {
993   _computeCanceled = false;
994   bool Ok = true;
995   SMESHDS_Mesh* meshDS = aMesh.GetMeshDS();
996   TCollection_AsciiString hexahedraMessage;
997
998   _nbShape = countShape( &aMesh, TopAbs_SOLID );  // we count the number of shapes
999
1000   {
1001     // create bounding box for each shape of the compound
1002
1003     int iShape = 0;
1004     TopoDS_Shape *tabShape;
1005     double **tabBox;
1006
1007     tabShape = new TopoDS_Shape[_nbShape];
1008     tabBox   = new double*[_nbShape];
1009     for (int i=0; i<_nbShape; i++)
1010       tabBox[i] = new double[6];
1011     double Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
1012
1013     TopExp_Explorer expBox (meshDS->ShapeToMesh(), TopAbs_SOLID);
1014     for (; expBox.More(); expBox.Next()) {
1015       tabShape[iShape] = expBox.Current();
1016       Bnd_Box BoundingBox;
1017       BRepBndLib::Add(expBox.Current(), BoundingBox);
1018       BoundingBox.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
1019       tabBox[iShape][0] = Xmin; tabBox[iShape][1] = Xmax;
1020       tabBox[iShape][2] = Ymin; tabBox[iShape][3] = Ymax;
1021       tabBox[iShape][4] = Zmin; tabBox[iShape][5] = Zmax;
1022       iShape++;
1023     }
1024
1025     SetParameters(_hypothesis);
1026
1027     TCollection_AsciiString aTmpDir = _hexoticWorkingDirectory.c_str();
1028     TCollection_AsciiString aQuote("");
1029 #ifdef WIN32
1030     aQuote = "\"";
1031     if ( aTmpDir.Value(aTmpDir.Length()) != '\\' ) aTmpDir += '\\';
1032 #else
1033     if ( aTmpDir.Value(aTmpDir.Length()) != '/' ) aTmpDir += '/';
1034 #endif
1035     TCollection_AsciiString Hexotic_In(""), Hexotic_Out, Hexotic_SizeMap_Prefix;
1036     TCollection_AsciiString modeFile_In( "chmod 666 " ), modeFile_Out( "chmod 666 " );
1037     TCollection_AsciiString aLogFileName = aTmpDir + "Hexotic"+getSuffix()+".log";    // log
1038
1039     std::map <int,int> aSmdsToHexoticIdMap;
1040     std::map <int,const SMDS_MeshNode*> aHexoticIdToNodeMap;
1041
1042     MG_Hexotic_API mgHexa( _computeCanceled, _progress );
1043
1044     Hexotic_Out = aTmpDir + "Hexotic"+getSuffix()+"_Out.mesh";
1045 #ifdef WITH_BLSURFPLUGIN
1046     bool defaultInputFile = true;
1047     if (_blsurfHypo && !_blsurfHypo->GetQuadAllowed()) {
1048       Hexotic_In = _blsurfHypo->GetGMFFile().c_str();
1049       if ( !Hexotic_In.IsEmpty() &&
1050            SMESH_File( _blsurfHypo->GetGMFFile() ).exists() )
1051       {
1052         mgHexa.SetUseExecutable();
1053         defaultInputFile = false;
1054       }
1055     }
1056     if (defaultInputFile) {
1057 #endif
1058       Hexotic_In  = aTmpDir + "Hexotic"+getSuffix()+"_In.mesh";
1059       removeHexoticFiles(Hexotic_In, Hexotic_Out);
1060       splitQuads(aMesh); // quadrangles are no longer acceptable as input
1061       if ( mgHexa.IsExecutable() )
1062       {
1063         cout << std::endl;
1064         cout << "Creating MG-Hexa input mesh file : " << Hexotic_In << std::endl;
1065       }
1066       writeInput( &mgHexa, Hexotic_In.ToCString(), meshDS );
1067 #ifdef WITH_BLSURFPLUGIN
1068     }
1069     else {
1070       removeFile( Hexotic_Out );
1071     }
1072 #endif
1073     
1074     Hexotic_SizeMap_Prefix = aTmpDir + "Hexotic_SizeMap" + getSuffix();
1075     std::vector<std::string> sizeMapFiles = writeSizeMapFile( &mgHexa, Hexotic_SizeMap_Prefix.ToCString() );
1076     
1077     std::string run_Hexotic = getHexoticCommand(aQuote + Hexotic_In + aQuote, aQuote + Hexotic_Out + aQuote, Hexotic_SizeMap_Prefix, mgHexa.IsExecutable() );
1078     run_Hexotic += std::string(" 1> ") + aQuote.ToCString() + aLogFileName.ToCString() + aQuote.ToCString();  // dump into file
1079     mgHexa.SetLogFile( aLogFileName.ToCString() );
1080     cout << "Creating MG-Hexa log file : " << aLogFileName << std::endl;
1081
1082     cout << std::endl;
1083     cout << "MG-Hexa command : " << run_Hexotic << std::endl;
1084
1085     if ( mgHexa.IsExecutable() )
1086     {
1087 #ifndef WIN32    
1088       modeFile_In += Hexotic_In;
1089       system( modeFile_In.ToCString() );
1090 #endif
1091     }
1092     aSmdsToHexoticIdMap.clear();
1093     aHexoticIdToNodeMap.clear();
1094
1095     MESSAGE("HexoticPlugin_Hexotic::Compute");
1096
1097     
1098     std::string errStr;
1099     Ok = mgHexa.Compute( run_Hexotic, errStr ); // run
1100
1101
1102     // --------------
1103     // read a result
1104     // --------------
1105
1106     if ( mgHexa.IsExecutable() )
1107     {
1108 #ifndef WIN32
1109       modeFile_Out += Hexotic_Out;
1110       system( modeFile_Out.ToCString() );
1111 #endif
1112     }
1113     SMESH_MesherHelper aHelper( aMesh );
1114
1115     Ok = readResult( &mgHexa, Hexotic_Out.ToCString(),
1116                      this,
1117                      &aHelper, _nbShape, tabShape, tabBox );
1118
1119     std::string log = mgHexa.GetLog();
1120     if ( Ok )
1121     {
1122       hexahedraMessage = "success";
1123 #ifndef _DEBUG_
1124       removeFile(Hexotic_Out);
1125       removeFile(Hexotic_In);
1126       //removeFile(aLogFileName);
1127       for( size_t i=0; i<sizeMapFiles.size(); i++)
1128       {
1129         removeFile( TCollection_AsciiString( sizeMapFiles[i].c_str() ) );
1130       }
1131 #endif
1132     }
1133     else
1134     {
1135       hexahedraMessage = "failed";
1136       if ( mgHexa.IsExecutable() )
1137         cout << "Problem with MG-Hexa output file " << Hexotic_Out.ToCString() << std::endl;
1138       // analyse log file
1139       if ( !log.empty() )
1140       {
1141         char msgLic[] = " Dlim ";
1142         std::string log = mgHexa.GetLog();
1143         const char* fileBeg = &log[0], *fileEnd = fileBeg + log.size();
1144         if ( std::search( fileBeg, fileEnd, msgLic, msgLic+strlen(msgLic)) != fileEnd )
1145           error("Licence problems.");
1146       }
1147       if ( !errStr.empty() )
1148         error(errStr);
1149     }
1150     cout << "Hexahedra meshing " << hexahedraMessage << std::endl;
1151     cout << std::endl;
1152
1153     delete [] tabShape;
1154     for (int i=0; i<_nbShape; i++)
1155       delete [] tabBox[i];
1156     delete [] tabBox;
1157     _nbShape = 0;
1158     _iShape  = 0;
1159   }
1160
1161   if(_computeCanceled)
1162     return error(SMESH_Comment("interruption initiated by user"));
1163
1164   return Ok;
1165 }
1166
1167 //=============================================================================
1168 /*!
1169  * \brief Computes mesh without geometry
1170  *  \param aMesh - the mesh
1171  *  \param aHelper - helper that must be used for adding elements to \aaMesh
1172  *  \retval bool - is a success
1173  *
1174  * The method is called if ( !aMesh->HasShapeToMesh() )
1175  */
1176 //=============================================================================
1177
1178 bool HexoticPlugin_Hexotic::Compute(SMESH_Mesh & aMesh, SMESH_MesherHelper* aHelper)
1179 {
1180   _computeCanceled = false;
1181 /*
1182   SMESH_ComputeErrorPtr myError = SMESH_ComputeError::New();
1183 */
1184   bool Ok = true;
1185   TCollection_AsciiString hexahedraMessage;
1186   TCollection_AsciiString aQuote("");
1187 #ifdef WIN32
1188     aQuote = "\"";
1189 #endif
1190   SetParameters(_hypothesis);
1191
1192   TCollection_AsciiString aTmpDir = _hexoticWorkingDirectory.c_str();//getTmpDir();
1193   TCollection_AsciiString Hexotic_In, Hexotic_Out, Hexotic_SizeMap_Prefix;
1194   TCollection_AsciiString modeFile_In( "chmod 666 " ), modeFile_Out( "chmod 666 " );
1195   TCollection_AsciiString aLogFileName = aTmpDir + "Hexotic"+getSuffix()+".log";    // log
1196
1197   std::map <int,int> aSmdsToHexoticIdMap;
1198   std::map <int,const SMDS_MeshNode*> aHexoticIdToNodeMap;
1199
1200   Hexotic_In  = aTmpDir + "Hexotic"+getSuffix()+"_In.mesh";
1201   Hexotic_Out = aTmpDir + "Hexotic"+getSuffix()+"_Out.mesh";
1202   Hexotic_SizeMap_Prefix = aTmpDir + "Hexotic_SizeMap";
1203  
1204   MG_Hexotic_API mgHexa( _computeCanceled, _progress );
1205
1206   std::vector<std::string> sizeMapFiles = writeSizeMapFile( &mgHexa, Hexotic_SizeMap_Prefix.ToCString() );
1207
1208   std::string run_Hexotic = getHexoticCommand(aQuote + Hexotic_In + aQuote, aQuote + Hexotic_Out + aQuote, Hexotic_SizeMap_Prefix, mgHexa.IsExecutable());
1209   run_Hexotic += std::string(" 1> ") + aQuote.ToCString() + aLogFileName.ToCString() + aQuote.ToCString();  // dump into file
1210   mgHexa.SetLogFile( aLogFileName.ToCString() );
1211   cout << "Creating MG-Hexa log file : " << aLogFileName << std::endl;
1212
1213   removeHexoticFiles(Hexotic_In, Hexotic_Out);
1214
1215   splitQuads(aMesh); // quadrangles are no longer acceptable as input
1216
1217   cout << std::endl;
1218   cout << "Creating MG-Hexa input mesh file : " << Hexotic_In << std::endl;
1219   writeInput( &mgHexa, Hexotic_In.ToCString(), aHelper->GetMeshDS() );
1220   if ( mgHexa.IsExecutable() )
1221   {
1222 #ifndef WIN32    
1223     modeFile_In += Hexotic_In;
1224     system( modeFile_In.ToCString() );
1225 #endif
1226   }
1227   aSmdsToHexoticIdMap.clear();
1228   aHexoticIdToNodeMap.clear();
1229
1230   MESSAGE("HexoticPlugin_Hexotic::Compute");
1231
1232   cout << std::endl;
1233   cout << "MG-Hexa command : " << run_Hexotic << std::endl;
1234
1235   std::string errStr;
1236   Ok = mgHexa.Compute( run_Hexotic, errStr ); // run
1237
1238   // --------------
1239   // read a result
1240   // --------------
1241
1242   if ( mgHexa.IsExecutable() )
1243   {
1244     modeFile_Out += Hexotic_Out;
1245     system( modeFile_Out.ToCString() );
1246   }
1247
1248   Ok = Ok && readResult( &mgHexa, Hexotic_Out.ToCString(), this, aHelper );
1249
1250   std::string log = mgHexa.GetLog();
1251   if ( Ok )
1252   {
1253     hexahedraMessage = "success";
1254   }
1255   else
1256   {
1257     hexahedraMessage = "failed";
1258     if ( mgHexa.IsExecutable() )
1259       cout << "Problem with MG-Hexa output file " << Hexotic_Out << std::endl;
1260
1261     if ( log.find( " license " ) != std::string::npos ||
1262          log.find( " Dlim "    ) != std::string::npos )
1263       error("License problems.");
1264
1265     if ( !errStr.empty() )
1266       error(errStr);
1267   }
1268   cout << "Hexahedra meshing " << hexahedraMessage << std::endl;
1269   cout << std::endl;
1270
1271   if(_computeCanceled)
1272     return error(SMESH_Comment("interruption initiated by user"));
1273   removeFile(Hexotic_Out);
1274   removeFile(Hexotic_In);
1275   if ( Ok )
1276     removeFile(aLogFileName);
1277   for( size_t i=0; i<sizeMapFiles.size(); i++)
1278   {
1279     removeFile( TCollection_AsciiString(sizeMapFiles[i].c_str()) );
1280   }
1281   return Ok;
1282 }
1283
1284 //=============================================================================
1285 /*!
1286  *
1287  */
1288 //=============================================================================
1289
1290 bool HexoticPlugin_Hexotic::Evaluate(SMESH_Mesh&         aMesh,
1291                                      const TopoDS_Shape& aShape,
1292                                      MapShapeNbElems&    aResMap)
1293 {
1294   std::vector<int> aResVec(SMDSEntity_Last);
1295   for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0;
1296   SMESH_subMesh * sm = aMesh.GetSubMesh(aShape);
1297   aResMap.insert(std::make_pair(sm,aResVec));
1298
1299   SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
1300   smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Evaluation is not implemented",this));
1301
1302   return true;
1303 }
1304
1305 void HexoticPlugin_Hexotic::CancelCompute()
1306 {
1307   _computeCanceled = true;
1308 #ifdef WIN32
1309 #else
1310   TCollection_AsciiString aTmpDir = _hexoticWorkingDirectory.c_str(); //getTmpDir();
1311   TCollection_AsciiString Hexotic_In = aTmpDir + "Hexotic_In.mesh";
1312   TCollection_AsciiString cmd = TCollection_AsciiString("ps ux | grep ") + Hexotic_In;
1313   cmd += TCollection_AsciiString(" | grep -v grep | awk '{print $2}' | xargs kill -9 > /dev/null 2>&1");
1314   system( cmd.ToCString() );
1315 #endif
1316 }