1 // HexoticPlugin : C++ implementation
3 // Copyright (C) 2006 OPEN CASCADE, CEA/DEN, EDF R&D
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License.
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
22 // File : HexoticPlugin_Hexotic.cxx
23 // Author : Lioka RAZAFINDRAZAKA (CEA)
26 //=============================================================================
29 #include "HexoticPlugin_Hexotic.hxx"
30 #include "HexoticPlugin_Hypothesis.hxx"
31 // #include "HexoticPlugin_Mesher.hxx"
33 #include "SMDS_MeshElement.hxx"
34 #include "SMDS_MeshNode.hxx"
36 #include <TopExp_Explorer.hxx>
37 #include <OSD_File.hxx>
39 #include "utilities.h"
42 #include <sys/sysinfo.h>
52 #include <SMESH_Gen.hxx>
53 #include <SMESHDS_Mesh.hxx>
54 #include <SMESH_ControlsDef.hxx>
58 //=============================================================================
62 //=============================================================================
64 HexoticPlugin_Hexotic::HexoticPlugin_Hexotic(int hypId, int studyId, SMESH_Gen* gen)
65 : SMESH_3D_Algo(hypId, studyId, gen)
67 MESSAGE("HexoticPlugin_Hexotic::HexoticPlugin_Hexotic");
69 _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);// 1 bit /shape type
73 _compatibleHypothesis.push_back("Hexotic_Parameters");
76 //=============================================================================
80 //=============================================================================
82 HexoticPlugin_Hexotic::~HexoticPlugin_Hexotic()
84 MESSAGE("HexoticPlugin_Hexotic::~HexoticPlugin_Hexotic");
87 //=============================================================================
91 //=============================================================================
93 bool HexoticPlugin_Hexotic::CheckHypothesis( SMESH_Mesh& aMesh,
94 const TopoDS_Shape& aShape,
95 SMESH_Hypothesis::Hypothesis_Status& aStatus )
97 // MESSAGE("HexoticPlugin_Hexotic::CheckHypothesis");
101 list<const SMESHDS_Hypothesis*>::const_iterator itl;
102 const SMESHDS_Hypothesis* theHyp;
104 const list<const SMESHDS_Hypothesis*>& hyps = GetUsedHypothesis(aMesh, aShape);
105 int nbHyp = hyps.size();
108 aStatus = SMESH_Hypothesis::HYP_OK;
109 return true; // can work with no hypothesis
113 theHyp = (*itl); // use only the first hypothesis
115 string hypName = theHyp->GetName();
116 if (hypName == "Hexotic_Parameters")
118 _hypothesis = static_cast<const HexoticPlugin_Hypothesis*> (theHyp);
120 aStatus = SMESH_Hypothesis::HYP_OK;
123 aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
125 return aStatus == SMESH_Hypothesis::HYP_OK;
128 //=======================================================================
129 //function : countFaces
131 //=======================================================================
133 static int countFaces( SMESHDS_Mesh* the2DMesh,
134 list< const SMDS_MeshElement* >& theListOfFaces,
138 TopExp_Explorer fExp( (the2DMesh->ShapeToMesh()), TopAbs_FACE );
139 SMESHDS_SubMesh* the2DSubMesh;
140 SMDS_ElemIteratorPtr itOnSmdsElement;
143 nbFaces = the2DMesh->NbFaces();
145 for ( ; fExp.More(); fExp.Next() ) {
146 the2DSubMesh = the2DMesh->MeshElements( fExp.Current() );
147 if ( the2DSubMesh ) {
148 itOnSmdsElement = the2DSubMesh->GetElements();
149 while ( itOnSmdsElement->more() ) {
150 theListOfFaces.push_back( itOnSmdsElement->next() );
159 //=======================================================================
160 //function : writeHexoticFile
162 //=======================================================================
164 static bool writeHexoticFile (ofstream & theFile,
165 SMESHDS_Mesh * theMesh,
166 map <int,int> & theSmdsToHexoticIdMap,
167 map <int,const SMDS_MeshNode*> & theHexoticIdToNodeMap,
168 const TCollection_AsciiString & Hexotic_In) {
170 cout << "Creating Hexotic processed mesh file : " << Hexotic_In << endl;
172 bool onlyExternalFaces = true;
175 const char* space = " ";
176 const int dummyint = 0;
179 const SMDS_MeshNode* aNode;
180 SMDS_NodeIteratorPtr itOnNode;
182 list< const SMDS_MeshElement* > faces;
183 list< const SMDS_MeshElement* >::iterator itListFace;
184 const SMDS_MeshElement* aFace;
185 map<int,int>::const_iterator itOnSmdsNode;
186 SMDS_ElemIteratorPtr itOnSmdsElement;
187 SMDS_ElemIteratorPtr itOnFaceNode;
188 SMDS_FaceIteratorPtr itOnSmdsFace;
190 // Writing SMESH points into Hexotic File
192 nbVertices = theMesh->NbNodes();
194 theFile << "MeshVersionFormatted 1" << endl;
196 theFile << "Dimension" << endl;
197 theFile << 3 << endl;
198 theFile << "# Set of mesh vertices" << endl;
199 theFile << "Vertices" << endl;
200 theFile << nbVertices << endl;
202 itOnNode = theMesh->nodesIterator();
203 while ( itOnNode->more() ) {
204 aNode = itOnNode->next();
205 theSmdsToHexoticIdMap.insert( map <int,int>::value_type( aNode->GetID(), aSmdsNodeID ));
206 theHexoticIdToNodeMap.insert (map <int,const SMDS_MeshNode*>::value_type( aSmdsNodeID, aNode ));
208 theFile << aNode->X() << space << aNode->Y() << space << aNode->Z() << space << dummyint << endl;
211 // Writing SMESH faces into Hexotic File
213 nbTriangles = countFaces(theMesh, faces, onlyExternalFaces);
216 theFile << "# Set of mesh triangles (v1,v2,v3,tag)" << endl;
217 theFile << "Triangles" << endl;
218 theFile << nbTriangles << endl;
220 if ( onlyExternalFaces ) {
221 itOnSmdsFace = theMesh->facesIterator();
222 while ( itOnSmdsFace->more() ) {
223 aFace = itOnSmdsFace->next();
224 itOnFaceNode = aFace->nodesIterator();
225 while ( itOnFaceNode->more() ) {
226 aSmdsNodeID = itOnFaceNode->next()->GetID();
227 itOnSmdsNode = theSmdsToHexoticIdMap.find( aSmdsNodeID );
228 ASSERT( itOnSmdsNode != theSmdsToHexoticIdMap.end() );
229 theFile << (*itOnSmdsNode).second << space;
231 theFile << dummyint << endl;
235 itListFace = faces.begin();
236 for ( ; itListFace != faces.end(); ++itListFace ) {
238 itOnFaceNode = aFace->nodesIterator();
239 while ( itOnFaceNode->more() ) {
240 aSmdsNodeID = itOnFaceNode->next()->GetID();
241 itOnSmdsNode = theSmdsToHexoticIdMap.find( aSmdsNodeID );
242 ASSERT( itOnSmdsNode != theSmdsToHexoticIdMap.end() );
243 theFile << (*itOnSmdsNode).second << space;
245 theFile << dummyint << endl;
250 theFile << "End" << endl;
252 cout << "Processed mesh file created, it contains :" << endl;
253 cout << " " << nbVertices << " vertices" << endl;
254 cout << " " << nbTriangles << " triangles" << endl;
260 //=======================================================================
263 //=======================================================================
265 static bool getInt( int & theValue, char * & theLine )
268 theValue = strtol( theLine, &ptr, 10 );
269 if ( ptr == theLine ||
270 // there must not be neither '.' nor ',' nor 'E' ...
271 (*ptr != ' ' && *ptr != '\n' && *ptr != '\0'))
274 DUMP( " " << theValue );
279 //=======================================================================
280 //function : getDouble
282 //=======================================================================
284 static bool getDouble( double & theValue, char * & theLine )
287 theValue = strtod( theLine, &ptr );
288 if ( ptr == theLine )
291 DUMP( " " << theValue );
296 //=======================================================================
297 //function : readLine
299 //=======================================================================
301 #define HexoticPlugin_BUFLENGTH 256
302 #define HexoticPlugin_ReadLine(aPtr,aBuf,aFile,aLineNb) \
303 { aPtr = fgets( aBuf, HexoticPlugin_BUFLENGTH - 2, aFile ); aLineNb++; DUMP(endl); }
305 //=======================================================================
306 //function : readResult
308 //=======================================================================
310 static bool readResult(FILE * theFile,
311 SMESHDS_Mesh * theMesh,
312 const TopoDS_Shape & theShape,
313 map <int,const SMDS_MeshNode*> & theHexoticIdToNodeMap,
314 const TCollection_AsciiString & Hexotic_Out,
317 // ---------------------------------
318 // Read generated elements and nodes
319 // ---------------------------------
321 cout << "Reading Hexotic output file : " << Hexotic_Out << endl;
324 char aBuffer[ HexoticPlugin_BUFLENGTH ];
327 int shapeID = theMesh->ShapeToIndex( theShape );
329 int line = 1, EndOfFile = 0, nbElem = 0, nField = 10, nbRef = 0, aHexoticNodeID = 0;
332 char * tabField [nField];
335 tabField[0] = "MeshVersionFormatted"; tabRef[0] = 0;
336 tabField[1] = "Dimension"; tabRef[1] = 0;
337 tabField[2] = "Vertices"; tabRef[2] = 3;
338 tabField[3] = "Edges"; tabRef[3] = 2;
339 tabField[4] = "Triangles"; tabRef[4] = 3;
340 tabField[5] = "Quadrilaterals"; tabRef[5] = 4;
341 tabField[6] = "Hexahedra"; tabRef[6] = 8;
342 tabField[7] = "Corners"; tabRef[7] = 1;
343 tabField[8] = "Ridges"; tabRef[0] = 1;
344 tabField[9] = "End"; tabRef[0] = 0;
346 nodeRefNumber += theMesh->NbNodes();
348 SMDS_NodeIteratorPtr itOnHexoticInputNode = theMesh->nodesIterator();
349 while ( itOnHexoticInputNode->more() )
350 theMesh->RemoveNode( itOnHexoticInputNode->next() );
352 while ( EndOfFile == 0 ) {
353 HexoticPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb );
354 for ( int iField = 0; iField < nField; iField++ ) {
355 stringstream theMessage;
356 theField = tabField[iField];
357 if ( strncmp(aPtr, theField, strlen(theField)) == 0 ) {
358 if ( strcmp(theField, "End") == 0 ) {
360 theMessage << "End of Hexotic output file has been reached";
363 HexoticPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb );
365 getInt( nbElem, aPtr );
367 if ( strcmp(theField, "MeshVersionFormatted") == 0 )
368 theMessage << "Hexotic mesh descriptor : " << theField << " " << nbElem;
369 else if ( strcmp(theField, "Dimension") == 0 )
370 theMessage << "Hexotic mesh of " << nbElem << "D dimension";
371 else if ( strcmp(theField, "Vertices") == 0 ||
372 strcmp(theField, "Edges") == 0 ||
373 strcmp(theField, "Quadrilaterals") == 0 ||
374 strcmp(theField, "Hexahedra") == 0 ) {
375 nbRef = tabRef[iField];
376 HexoticPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb ); // read blank line
378 if ( strcmp(theField, "Vertices") == 0 ) {
381 SMDS_MeshNode * aHexoticNode;
383 for ( int iElem = 0; iElem < nbElem; iElem++ ) {
384 aHexoticID = iElem + 1 + nodeRefNumber;
385 HexoticPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb ); // read file lines
386 for ( int iCoord = 0; iCoord < 3; iCoord++ )
387 getDouble ( coord[ iCoord ], aPtr );
388 aHexoticNode = theMesh->AddNode(coord[0], coord[1], coord[2]);
389 theMesh->SetNodeInVolume( aHexoticNode, shapeID );
390 theHexoticIdToNodeMap[ aHexoticID ] = aHexoticNode;
394 const SMDS_MeshNode * node[nbRef];
395 SMDS_MeshElement* aHexoticElement;
396 map <int,const SMDS_MeshNode*>::iterator itOnHexoticNode;
398 for ( int iElem = 0; iElem < nbElem; iElem++ ) {
399 HexoticPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb ); // read file lines
400 for ( int iRef = 0; iRef < nbRef; iRef++ ) {
401 getInt ( aHexoticNodeID, aPtr ); // read nbRef aHexoticNodeID
402 aHexoticNodeID += nodeRefNumber;
403 itOnHexoticNode = theHexoticIdToNodeMap.find( aHexoticNodeID );
404 node[ iRef ] = itOnHexoticNode->second;
407 if ( strcmp(theField, "Edges") == 0 ) // create an element
408 aHexoticElement = theMesh->AddEdge( node[0], node[1] );
409 else if ( strcmp(theField, "Quadrilaterals") == 0 )
410 aHexoticElement = theMesh->AddFace( node[0], node[1], node[2], node[3] );
411 else if ( strcmp(theField, "Hexahedra") == 0 )
412 aHexoticElement = theMesh->AddVolume( node[0], node[1], node[2], node[3], node[4], node[5], node[6], node[7] );
414 theMesh->SetMeshElementOnShape( aHexoticElement, shapeID );
417 theMessage << nbElem << " " << theField << " created";
420 if ( theMessage.str().size() != 0 ) {
421 cout << theMessage.str() << endl;
431 //=============================================================================
433 * Pass parameters to Hexotic
435 //=============================================================================
437 void HexoticPlugin_Hexotic::SetParameters(const HexoticPlugin_Hypothesis* hyp) {
439 MESSAGE("HexoticPlugin_Hexotic::SetParameters");
440 _hexesMinLevel = hyp->GetHexesMinLevel();
441 _hexesMaxLevel = hyp->GetHexesMaxLevel();
442 _hexoticQuadrangles = hyp->GetHexoticQuadrangles();
446 //=======================================================================
447 //function : getTmpDir
449 //=======================================================================
451 static TCollection_AsciiString getTmpDir()
453 TCollection_AsciiString aTmpDir;
455 char *Tmp_dir = getenv("SALOME_TMP_DIR");
456 if(Tmp_dir != NULL) {
459 if(aTmpDir.Value(aTmpDir.Length()) != '\\') aTmpDir+='\\';
461 if(aTmpDir.Value(aTmpDir.Length()) != '/') aTmpDir+='/';
466 aTmpDir = TCollection_AsciiString("C:\\");
468 aTmpDir = TCollection_AsciiString("/tmp/");
474 //=============================================================================
476 * Here we are going to use the Hexotic mesher
478 //=============================================================================
480 bool HexoticPlugin_Hexotic::Compute(SMESH_Mesh& theMesh,
481 const TopoDS_Shape& theShape)
484 SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
486 if (_iShape == 0 && _nbShape == 0) {
488 cout << "Hexotic execution..." << endl;
491 TopExp_Explorer expf(meshDS->ShapeToMesh(), TopAbs_SOLID);
492 for ( ; expf.More(); expf.Next() )
498 if (_iShape == _nbShape ) {
499 SetParameters(_hypothesis);
502 cout << _name << " parameters :" << endl;
503 cout << " " << _name << " Segments Min Level = " << _hexesMinLevel << endl;
504 cout << " " << _name << " Segments Max Level = " << _hexesMaxLevel << endl;
505 cout << " " << "Salome Quadrangles : " << (_hexoticQuadrangles ? "yes":"no") << endl;
507 TCollection_AsciiString aTmpDir = getTmpDir();
508 TCollection_AsciiString Hexotic_In, Hexotic_Out;
509 TCollection_AsciiString run_Hexotic( "hexotic" );
511 TCollection_AsciiString minl = " -minl ", maxl = " -maxl ";
512 TCollection_AsciiString in = " -in ", out = " -out ";
514 TCollection_AsciiString minLevel, maxLevel;
515 minLevel = _hexesMinLevel;
516 maxLevel = _hexesMaxLevel;
518 map <int,int> aSmdsToHexoticIdMap;
519 map <int,const SMDS_MeshNode*> aHexoticIdToNodeMap;
521 Hexotic_In = aTmpDir + "Hexotic_In.mesh";
522 Hexotic_Out = aTmpDir + "Hexotic_Out.mesh";
523 run_Hexotic += minl + minLevel + maxl + maxLevel + in + Hexotic_In + out + Hexotic_Out;
525 // cout << "Hexotic command : " << run_Hexotic << endl;
527 OSD_File( Hexotic_In ).Remove();
528 OSD_File( Hexotic_Out ).Remove();
530 ofstream HexoticFile (Hexotic_In.ToCString() , ios::out);
532 Ok = ( writeHexoticFile(HexoticFile, meshDS, aSmdsToHexoticIdMap, aHexoticIdToNodeMap, Hexotic_In) );
535 MESSAGE("HexoticPlugin_Hexotic::Compute");
537 system( run_Hexotic.ToCString() );
543 FILE * aResultFile = fopen( Hexotic_Out.ToCString(), "r" );
545 Ok = readResult( aResultFile, meshDS, theShape, aHexoticIdToNodeMap, Hexotic_Out, _nodeRefNumber );
547 cout << "Hexotic output file read !" << endl;
557 //=============================================================================
561 //=============================================================================
563 ostream & HexoticPlugin_Hexotic::SaveTo(ostream & save)
568 //=============================================================================
572 //=============================================================================
574 istream & HexoticPlugin_Hexotic::LoadFrom(istream & load)
579 //=============================================================================
583 //=============================================================================
585 ostream & operator << (ostream & save, HexoticPlugin_Hexotic & hyp)
587 return hyp.SaveTo( save );
590 //=============================================================================
594 //=============================================================================
596 istream & operator >> (istream & load, HexoticPlugin_Hexotic & hyp)
598 return hyp.LoadFrom( load );