1 //=============================================================================
2 // File : GHS3DPlugin_GHS3D.cxx
4 // Author : Edward AGAPOV
6 // Copyright : CEA 2003
8 //=============================================================================
11 #include "GHS3DPlugin_GHS3D.hxx"
12 #include "SMESH_Gen.hxx"
13 #include "SMESH_Mesh.hxx"
15 #include "SMDS_MeshElement.hxx"
16 #include "SMDS_MeshNode.hxx"
18 #include <TopExp_Explorer.hxx>
20 #include "utilities.h"
31 //=============================================================================
35 //=============================================================================
37 GHS3DPlugin_GHS3D::GHS3DPlugin_GHS3D(int hypId, int studyId, SMESH_Gen* gen)
38 : SMESH_3D_Algo(hypId, studyId, gen)
40 MESSAGE("GHS3DPlugin_GHS3D::GHS3DPlugin_GHS3D");
42 _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);// 1 bit /shape type
45 //=============================================================================
49 //=============================================================================
51 GHS3DPlugin_GHS3D::~GHS3DPlugin_GHS3D()
53 MESSAGE("GHS3DPlugin_GHS3D::~GHS3DPlugin_GHS3D");
56 //=============================================================================
60 //=============================================================================
62 bool GHS3DPlugin_GHS3D::CheckHypothesis
64 const TopoDS_Shape& aShape,
65 SMESH_Hypothesis::Hypothesis_Status& aStatus)
67 // MESSAGE("GHS3DPlugin_GHS3D::CheckHypothesis");
68 aStatus = SMESH_Hypothesis::HYP_OK;
72 //=======================================================================
73 //function : writeFaces
75 //=======================================================================
77 static bool writeFaces (ofstream & theFile,
78 SMESHDS_Mesh * theMesh,
79 const map <int,int> & theSmdsToGhs3dIdMap)
84 // Loop from 1 to NB_ELEMS
85 // NB_NODES NODE_NB_1 NODE_NB_2 ... (NB_NODES + 1) times: DUMMY_INT
87 int nbFaces = theMesh->NbFaces();
91 const char* space = " ";
92 const int dummyint = 0;
95 theFile << space << nbFaces << space << dummyint << endl;
97 // Loop from 1 to NB_ELEMS
98 SMDS_FaceIteratorPtr it = theMesh->facesIterator();
102 const SMDS_MeshElement* elem = it->next();
103 const int nbNodes = elem->NbNodes();
104 theFile << space << nbNodes;
106 // NODE_NB_1 NODE_NB_2 ...
107 SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator();
108 while ( nodeIt->more() )
111 int aSmdsID = nodeIt->next()->GetID();
112 map<int,int>::const_iterator it = theSmdsToGhs3dIdMap.find( aSmdsID );
113 ASSERT( it != theSmdsToGhs3dIdMap.end() );
114 theFile << space << (*it).second;
117 // (NB_NODES + 1) times: DUMMY_INT
118 for ( int i=0; i<=nbNodes; i++)
119 theFile << space << dummyint;
127 //=======================================================================
128 //function : writePoints
130 //=======================================================================
132 static bool writePoints (ofstream & theFile,
133 SMESHDS_Mesh * theMesh,
134 map <int,int> & theSmdsToGhs3dIdMap,
135 map <int,const SMDS_MeshNode*> & theGhs3dIdToNodeMap)
140 // Loop from 1 to NB_NODES
143 int nbNodes = theMesh->NbNodes();
147 const char* space = " ";
148 const int dummyint = 0;
151 theFile << space << nbNodes << endl;
153 // Loop from 1 to NB_NODES
155 SMDS_NodeIteratorPtr it = theMesh->nodesIterator();
158 const SMDS_MeshNode* node = it->next();
159 theSmdsToGhs3dIdMap.insert( map <int,int>::value_type( node->GetID(), aGhs3dID ));
160 theGhs3dIdToNodeMap.insert (map <int,const SMDS_MeshNode*>::value_type( aGhs3dID, node ));
165 << space << node->X()
166 << space << node->Y()
167 << space << node->Z()
168 << space << dummyint;
176 //=======================================================================
179 //=======================================================================
181 static bool getInt( int & theValue, char * & theLine )
184 theValue = strtol( theLine, &ptr, 10 );
185 if ( ptr == theLine ||
186 // there must not be neither '.' nor ',' nor 'E' ...
187 (*ptr != ' ' && *ptr != '\n' && *ptr != '\0'))
190 DUMP( " " << theValue );
195 //=======================================================================
196 //function : getDouble
198 //=======================================================================
200 static bool getDouble( double & theValue, char * & theLine )
203 theValue = strtod( theLine, &ptr );
204 if ( ptr == theLine )
207 DUMP( " " << theValue );
212 //=======================================================================
213 //function : readLine
215 //=======================================================================
217 #define GHS3DPlugin_BUFLENGTH 256
218 #define GHS3DPlugin_ReadLine(aPtr,aBuf,aFile,aLineNb) \
219 { aPtr = fgets( aBuf, GHS3DPlugin_BUFLENGTH - 2, aFile ); aLineNb++; DUMP(endl); }
221 //=======================================================================
222 //function : readResult
224 //=======================================================================
226 static bool readResult(FILE * theFile,
227 SMESHDS_Mesh * theMesh,
228 const TopoDS_Shape& theShape,
229 map <int,const SMDS_MeshNode*>& theGhs3dIdToNodeMap)
234 // NB_ELEMENTS NB_NODES NB_INPUT_NODES (14 DUMMY_INT)
236 // (NB_ELEMENTS * 4) node nbs
238 // (NB_NODES) node XYZ
240 char aBuffer[ GHS3DPlugin_BUFLENGTH ];
244 // get shell to set nodes in
245 TopExp_Explorer exp( theShape, TopAbs_SHELL );
246 TopoDS_Shell aShell = TopoDS::Shell( exp.Current() );
247 if ( aShell.IsNull() )
250 // ----------------------------------------
252 // read nb of generated elements and nodes
253 // ----------------------------------------
254 int nbElems = 0 , nbNodes = 0, nbInputNodes = 0;
255 GHS3DPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb );
257 !getInt( nbElems, aPtr ) ||
258 !getInt( nbNodes, aPtr ) ||
259 !getInt( nbInputNodes, aPtr))
262 // -------------------------------------------
264 // read element nodes and create tetrahedrons
265 // -------------------------------------------
266 GHS3DPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb );
267 for (int iElem = 0; iElem < nbElems; iElem++)
270 const SMDS_MeshNode * node[4];
271 for (int iNode = 0; iNode < 4; iNode++)
273 // read Ghs3d node ID
275 if (!aPtr || ! getInt ( ID, aPtr ))
277 GHS3DPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb );
278 if (!aPtr || ! getInt ( ID, aPtr ))
280 MESSAGE( "Cant read " << (iNode+1) << "-th node on line " << aLineNb );
284 // find/create a node with ID
285 map <int,const SMDS_MeshNode*>::iterator IdNode = theGhs3dIdToNodeMap.find( ID );
286 if ( IdNode == theGhs3dIdToNodeMap.end())
288 // ID is not yet in theGhs3dIdToNodeMap
289 ASSERT ( ID > nbInputNodes ); // it should be a new one
290 SMDS_MeshNode * aNewNode = theMesh->AddNode( 0.,0.,0. ); // read XYZ later
291 theMesh->SetNodeInVolume( aNewNode, aShell );
292 theGhs3dIdToNodeMap.insert
293 ( map <int,const SMDS_MeshNode*>::value_type( ID, aNewNode ));
294 node[ iNode ] = aNewNode;
298 node[ iNode ] = (*IdNode).second;
301 // create a tetrahedron
302 SMDS_MeshElement* aTet = theMesh->AddVolume( node[0], node[1], node[2], node[3] );
303 theMesh->SetMeshElementOnShape( aTet, theShape );
306 // ------------------------
308 // read and set nodes' XYZ
309 // ------------------------
310 GHS3DPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb );
311 for (int iNode = 0; iNode < nbNodes; iNode++)
313 // read 3 coordinates
315 for (int iCoord = 0; iCoord < 3; iCoord++)
317 if (!aPtr || ! getDouble ( coord[ iCoord ], aPtr ))
319 GHS3DPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb );
320 if (!aPtr || ! getDouble ( coord[ iCoord ], aPtr ))
322 MESSAGE( "Cant read " << (iCoord+1) << "-th node coord on line " << aLineNb );
327 // do not move old nodes
329 if (ID <= nbInputNodes)
332 map <int,const SMDS_MeshNode*>::iterator IdNode = theGhs3dIdToNodeMap.find( ID );
333 ASSERT ( IdNode != theGhs3dIdToNodeMap.end());
334 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*> ( (*IdNode).second );
337 theMesh->MoveNode( node, coord[0], coord[1], coord[2] );
343 //=============================================================================
345 *Here we are going to use the GHS3D mesher
347 //=============================================================================
349 bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh& theMesh,
350 const TopoDS_Shape& theShape)
352 MESSAGE("GHS3DPlugin_GHS3D::Compute");
355 QString aTmpDir ( getenv("SALOME_TMP_DIR") );
356 if ( !aTmpDir.isEmpty() ) {
358 if(aTmpDir.at(aTmpDir.length()-1) != '\\') aTmpDir+='\\';
360 if(aTmpDir.at(aTmpDir.length()-1) != '/') aTmpDir+='/';
370 // a unique name helps to avoid access to the same files by eg different users
373 aUniqueNb = GetCurrentProcessId();
375 aUniqueNb = getpid();
378 const QString aGenericName = (aTmpDir + ( "GHS3D_%1" )).arg( aUniqueNb );
379 const QString aFacesFileName = aGenericName + ".faces";
380 const QString aPointsFileName = aGenericName + ".points";
381 const QString aResultFileName = aGenericName + ".noboite";
382 const QString aErrorFileName = aGenericName + ".log";
385 QFile( aFacesFileName ).remove();
386 QFile( aPointsFileName ).remove();
387 QFile( aResultFileName ).remove();
388 QFile( aErrorFileName ).remove();
395 ofstream aFacesFile ( aFacesFileName.latin1() , ios::out);
396 ofstream aPointsFile ( aPointsFileName.latin1() , ios::out);
399 aFacesFile->is_open() && aPointsFile->is_open();
401 aFacesFile.rdbuf()->is_open() && aPointsFile.rdbuf()->is_open();
405 MESSAGE( "Can't write into " << aTmpDir << " directory");
408 SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
409 map <int,int> aSmdsToGhs3dIdMap;
410 map <int,const SMDS_MeshNode*> aGhs3dIdToNodeMap;
413 (writePoints( aPointsFile, meshDS, aSmdsToGhs3dIdMap, aGhs3dIdToNodeMap ) &&
414 writeFaces ( aFacesFile, meshDS, aSmdsToGhs3dIdMap ));
423 // run ghs3d mesher WIN32???
426 QString cmd = "ghs3d "
427 "-m 1000 " // memory: 1000 M
428 "-f " + aGenericName + // file to read
429 " 1>" + aErrorFileName; // dump into file
430 if (system(cmd.latin1()))
432 MESSAGE ("command failed: " << cmd.latin1() );
440 FILE * aResultFile = fopen( aResultFileName.latin1(), "r" );
443 MESSAGE( "GHS3D ERROR: see " << aErrorFileName.latin1() );
447 Ok = readResult( aResultFile, meshDS, theShape, aGhs3dIdToNodeMap );
451 QFile( aFacesFileName ).remove();
452 QFile( aPointsFileName ).remove();
453 QFile( aResultFileName ).remove();
454 QFile( aErrorFileName ).remove();
460 //=============================================================================
464 //=============================================================================
466 ostream & GHS3DPlugin_GHS3D::SaveTo(ostream & save)
471 //=============================================================================
475 //=============================================================================
477 istream & GHS3DPlugin_GHS3D::LoadFrom(istream & load)
482 //=============================================================================
486 //=============================================================================
488 ostream & operator << (ostream & save, GHS3DPlugin_GHS3D & hyp)
490 return hyp.SaveTo( save );
493 //=============================================================================
497 //=============================================================================
499 istream & operator >> (istream & load, GHS3DPlugin_GHS3D & hyp)
501 return hyp.LoadFrom( load );