--- /dev/null
+//=============================================================================
+// File : GHS3DPlugin_GHS3D.cxx
+// Created :
+// Author : Edward AGAPOV
+// Project : SALOME
+// Copyright : CEA 2003
+// $Header$
+//=============================================================================
+using namespace std;
+
+#include "GHS3DPlugin_GHS3D.hxx"
+#include "SMESH_Gen.hxx"
+#include "SMESH_Mesh.hxx"
+
+#include "SMDS_MeshElement.hxx"
+#include "SMDS_MeshNode.hxx"
+
+#include <TopExp_Explorer.hxx>
+
+#include "utilities.h"
+
+#include <qdir.h>
+
+#ifdef _DEBUG_
+#define DUMP(txt) \
+// cout << txt
+#else
+#define DUMP(txt)
+#endif
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+
+GHS3DPlugin_GHS3D::GHS3DPlugin_GHS3D(int hypId, int studyId, SMESH_Gen* gen)
+ : SMESH_3D_Algo(hypId, studyId, gen)
+{
+ MESSAGE("GHS3DPlugin_GHS3D::GHS3DPlugin_GHS3D");
+ _name = "GHS3D";
+ _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);// 1 bit /shape type
+}
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+
+GHS3DPlugin_GHS3D::~GHS3DPlugin_GHS3D()
+{
+ MESSAGE("GHS3DPlugin_GHS3D::~GHS3DPlugin_GHS3D");
+}
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+
+bool GHS3DPlugin_GHS3D::CheckHypothesis
+ (SMESH_Mesh& aMesh,
+ const TopoDS_Shape& aShape,
+ SMESH_Hypothesis::Hypothesis_Status& aStatus)
+{
+// MESSAGE("GHS3DPlugin_GHS3D::CheckHypothesis");
+ aStatus = SMESH_Hypothesis::HYP_OK;
+ return true;
+}
+
+//=======================================================================
+//function : writeFaces
+//purpose :
+//=======================================================================
+
+static bool writeFaces (ofstream & theFile,
+ SMESHDS_Mesh * theMesh,
+ const map <int,int> & theSmdsToGhs3dIdMap)
+{
+ // structure:
+ //
+ // NB_ELEMS DUMMY_INT
+ // Loop from 1 to NB_ELEMS
+ // NB_NODES NODE_NB_1 NODE_NB_2 ... (NB_NODES + 1) times: DUMMY_INT
+
+ int nbFaces = theMesh->NbFaces();
+ if ( nbFaces == 0 )
+ return false;
+
+ const char* space = " ";
+ const int dummyint = 0;
+
+ // NB_ELEMS DUMMY_INT
+ theFile << space << nbFaces << space << dummyint << endl;
+
+ // Loop from 1 to NB_ELEMS
+ SMDS_FaceIteratorPtr it = theMesh->facesIterator();
+ while ( it->more() )
+ {
+ // NB_NODES
+ const SMDS_MeshElement* elem = it->next();
+ const int nbNodes = elem->NbNodes();
+ theFile << space << nbNodes;
+
+ // NODE_NB_1 NODE_NB_2 ...
+ SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator();
+ while ( nodeIt->more() )
+ {
+ // find GHS3D ID
+ int aSmdsID = nodeIt->next()->GetID();
+ map<int,int>::const_iterator it = theSmdsToGhs3dIdMap.find( aSmdsID );
+ ASSERT( it != theSmdsToGhs3dIdMap.end() );
+ theFile << space << (*it).second;
+ }
+
+ // (NB_NODES + 1) times: DUMMY_INT
+ for ( int i=0; i<=nbNodes; i++)
+ theFile << space << dummyint;
+
+ theFile << endl;
+ }
+
+ return true;
+}
+
+//=======================================================================
+//function : writePoints
+//purpose :
+//=======================================================================
+
+static bool writePoints (ofstream & theFile,
+ SMESHDS_Mesh * theMesh,
+ map <int,int> & theSmdsToGhs3dIdMap,
+ map <int,const SMDS_MeshNode*> & theGhs3dIdToNodeMap)
+{
+ // structure:
+ //
+ // NB_NODES
+ // Loop from 1 to NB_NODES
+ // X Y Z DUMMY_INT
+
+ int nbNodes = theMesh->NbNodes();
+ if ( nbNodes == 0 )
+ return false;
+
+ const char* space = " ";
+ const int dummyint = 0;
+
+ // NB_NODES
+ theFile << space << nbNodes << endl;
+
+ // Loop from 1 to NB_NODES
+ int aGhs3dID = 1;
+ SMDS_NodeIteratorPtr it = theMesh->nodesIterator();
+ while ( it->more() )
+ {
+ const SMDS_MeshNode* node = it->next();
+ theSmdsToGhs3dIdMap.insert( map <int,int>::value_type( node->GetID(), aGhs3dID ));
+ theGhs3dIdToNodeMap.insert (map <int,const SMDS_MeshNode*>::value_type( aGhs3dID, node ));
+ aGhs3dID++;
+
+ // X Y Z DUMMY_INT
+ theFile
+ << space << node->X()
+ << space << node->Y()
+ << space << node->Z()
+ << space << dummyint;
+
+ theFile << endl;
+ }
+
+ return true;
+}
+
+//=======================================================================
+//function : getInt
+//purpose :
+//=======================================================================
+
+static bool getInt( int & theValue, char * & theLine )
+{
+ char *ptr;
+ theValue = strtol( theLine, &ptr, 10 );
+ if ( ptr == theLine ||
+ // there must not be neither '.' nor ',' nor 'E' ...
+ (*ptr != ' ' && *ptr != '\n' && *ptr != '\0'))
+ return false;
+
+ DUMP( " " << theValue );
+ theLine = ptr;
+ return true;
+}
+
+//=======================================================================
+//function : getDouble
+//purpose :
+//=======================================================================
+
+static bool getDouble( double & theValue, char * & theLine )
+{
+ char *ptr;
+ theValue = strtod( theLine, &ptr );
+ if ( ptr == theLine )
+ return false;
+
+ DUMP( " " << theValue );
+ theLine = ptr;
+ return true;
+}
+
+//=======================================================================
+//function : readLine
+//purpose :
+//=======================================================================
+
+#define GHS3DPlugin_BUFLENGTH 256
+#define GHS3DPlugin_ReadLine(aPtr,aBuf,aFile,aLineNb) \
+{ aPtr = fgets( aBuf, GHS3DPlugin_BUFLENGTH - 2, aFile ); aLineNb++; DUMP(endl); }
+
+//=======================================================================
+//function : readResult
+//purpose :
+//=======================================================================
+
+static bool readResult(FILE * theFile,
+ SMESHDS_Mesh * theMesh,
+ const TopoDS_Shape& theShape,
+ map <int,const SMDS_MeshNode*>& theGhs3dIdToNodeMap)
+{
+ // structure:
+
+ // record 1:
+ // NB_ELEMENTS NB_NODES NB_INPUT_NODES (14 DUMMY_INT)
+ // record 2:
+ // (NB_ELEMENTS * 4) node nbs
+ // record 3:
+ // (NB_NODES) node XYZ
+
+ char aBuffer[ GHS3DPlugin_BUFLENGTH ];
+ char * aPtr;
+ int aLineNb = 0;
+
+ // get shell to set nodes in
+ TopExp_Explorer exp( theShape, TopAbs_SHELL );
+ TopoDS_Shell aShell = TopoDS::Shell( exp.Current() );
+
+ // -------------------------------------
+ // record 1:
+ // read nb generated elements and nodes
+ // -------------------------------------
+ int nbElems = 0 , nbNodes = 0, nbInputNodes = 0;
+ GHS3DPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb );
+ if (!aPtr ||
+ !getInt( nbElems, aPtr ) ||
+ !getInt( nbNodes, aPtr ) ||
+ !getInt( nbInputNodes, aPtr))
+ return false;
+
+ // -------------------------------------------
+ // record 2:
+ // read element nodes and create tetrahedrons
+ // -------------------------------------------
+ GHS3DPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb );
+ for (int iElem = 0; iElem < nbElems; iElem++)
+ {
+ // read 4 nodes
+ const SMDS_MeshNode * node[4];
+ for (int iNode = 0; iNode < 4; iNode++)
+ {
+ // read Ghs3d node ID
+ int ID = 0;
+ if (!aPtr || ! getInt ( ID, aPtr ))
+ {
+ GHS3DPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb );
+ if (!aPtr || ! getInt ( ID, aPtr ))
+ {
+ MESSAGE( "Cant read " << (iNode+1) << "-th node on line " << aLineNb );
+ return false;
+ }
+ }
+ // find/create a node with ID
+ map <int,const SMDS_MeshNode*>::iterator IdNode = theGhs3dIdToNodeMap.find( ID );
+ if ( IdNode == theGhs3dIdToNodeMap.end())
+ {
+ // ID is not yet in theGhs3dIdToNodeMap
+ ASSERT ( ID > nbInputNodes ); // it should be a new one
+ SMDS_MeshNode * aNewNode = theMesh->AddNode( 0.,0.,0. ); // read XYZ later
+ theMesh->SetNodeInVolume( aNewNode, aShell );
+ theGhs3dIdToNodeMap.insert
+ ( map <int,const SMDS_MeshNode*>::value_type( ID, aNewNode ));
+ node[ iNode ] = aNewNode;
+ }
+ else
+ {
+ node[ iNode ] = (*IdNode).second;
+ }
+ }
+ // create a tetrahedron
+ SMDS_MeshElement* aTet = theMesh->AddVolume( node[0], node[1], node[2], node[3] );
+ theMesh->SetMeshElementOnShape( aTet, theShape );
+ }
+
+ // ------------------------
+ // record 3:
+ // read and set nodes' XYZ
+ // ------------------------
+ GHS3DPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb );
+ for (int iNode = 0; iNode < nbNodes; iNode++)
+ {
+ // read 3 coordinates
+ double coord [3];
+ for (int iCoord = 0; iCoord < 3; iCoord++)
+ {
+ if (!aPtr || ! getDouble ( coord[ iCoord ], aPtr ))
+ {
+ GHS3DPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb );
+ if (!aPtr || ! getDouble ( coord[ iCoord ], aPtr ))
+ {
+ MESSAGE( "Cant read " << (iCoord+1) << "-th node coord on line " << aLineNb );
+ return false;
+ }
+ }
+ }
+ // do not move old nodes
+ int ID = iNode + 1;
+ if (ID <= nbInputNodes)
+ continue;
+ // find a node
+ map <int,const SMDS_MeshNode*>::iterator IdNode = theGhs3dIdToNodeMap.find( ID );
+ ASSERT ( IdNode != theGhs3dIdToNodeMap.end());
+ SMDS_MeshNode* node = const_cast<SMDS_MeshNode*> ( (*IdNode).second );
+
+ // set XYZ
+ theMesh->MoveNode( node, coord[0], coord[1], coord[2] );
+ }
+
+ return true;
+}
+
+//=============================================================================
+/*!
+ *Here we are going to use the GHS3D mesher
+ */
+//=============================================================================
+
+bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh& theMesh,
+ const TopoDS_Shape& theShape)
+{
+ MESSAGE("GHS3DPlugin_GHS3D::Compute");
+
+ // working dir
+ const char* wdName = "tmp";
+ QDir wd = QDir::root(); // "/"
+ if ( !wd.cd( wdName ) ) { // "/tmp"
+ MESSAGE( "Cannot find the " << wdName << " directory" );
+ return false;
+ }
+
+ const QString aGenericName = wd.filePath( "GHS3DTMP" );
+ const QString aFacesFileName = aGenericName + ".faces";
+ const QString aPointsFileName = aGenericName + ".points";
+ const QString aResultFileName = aGenericName + ".noboite";
+ const QString aErrorFileName = aGenericName + ".error";
+
+ // remove old files
+ QFile( aFacesFileName ).remove();
+ QFile( aPointsFileName ).remove();
+ QFile( aResultFileName ).remove();
+ QFile( aErrorFileName ).remove();
+
+
+ // -----------------
+ // make input files
+ // -----------------
+
+ ofstream aFacesFile ( aFacesFileName.latin1() , ios::out);
+ ofstream aPointsFile ( aPointsFileName.latin1() , ios::out);
+ if (!aFacesFile || !aFacesFile.rdbuf()->is_open() ||
+ !aPointsFile || !aPointsFile.rdbuf()->is_open())
+ {
+ MESSAGE( "Can't write into " << wdName << " directory");
+ return false;
+ }
+ SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
+ map <int,int> aSmdsToGhs3dIdMap;
+ map <int,const SMDS_MeshNode*> aGhs3dIdToNodeMap;
+
+ bool Ok =
+ (writePoints( aPointsFile, meshDS, aSmdsToGhs3dIdMap, aGhs3dIdToNodeMap ) &&
+ writeFaces ( aFacesFile, meshDS, aSmdsToGhs3dIdMap ));
+
+ aFacesFile.close();
+ aPointsFile.close();
+
+ if ( ! Ok )
+ return false;
+
+ // -----------------
+ // run ghs3d mesher
+ // -----------------
+
+ QString cmd = "ghs3d "
+ "-m 1000 " // memory: 1000 M
+ "-f " + aGenericName + // file to read
+ " 1>" + aErrorFileName; // dump into file
+ if (system(cmd.latin1()))
+ {
+ MESSAGE ("Failed: <" << cmd.latin1() << ">");
+ return false;
+ }
+
+ // --------------
+ // read a result
+ // --------------
+
+ FILE * aResultFile = fopen( aResultFileName.latin1(), "r" );
+ if (!aResultFile)
+ {
+ MESSAGE( "GHS3D ERROR: see " << aErrorFileName.latin1() );
+ return false;
+ }
+
+ Ok = readResult( aResultFile, meshDS, theShape, aGhs3dIdToNodeMap );
+ fclose(aResultFile);
+
+ return Ok;
+}
+
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+
+ostream & GHS3DPlugin_GHS3D::SaveTo(ostream & save)
+{
+ return save;
+}
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+
+istream & GHS3DPlugin_GHS3D::LoadFrom(istream & load)
+{
+ return load;
+}
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+
+ostream & operator << (ostream & save, GHS3DPlugin_GHS3D & hyp)
+{
+ return hyp.SaveTo( save );
+}
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+
+istream & operator >> (istream & load, GHS3DPlugin_GHS3D & hyp)
+{
+ return hyp.LoadFrom( load );
+}