1 // Copyright (C) 2005 CEA/DEN, EDF R&D, OPEN CASCADE, PRINCIPIA R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 //=============================================================================
20 // File : GHS3DPlugin_GHS3D.cxx
22 // Author : Edward AGAPOV, modified by Lioka RAZAFINDRAZAKA (CEA) 09/02/2007
24 // Copyright : CEA 2003
26 //=============================================================================
29 #include "GHS3DPlugin_GHS3D.hxx"
30 #include "SMESH_Gen.hxx"
31 #include "SMESH_Mesh.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>
45 //#include <Standard_Stream.hxx>
47 #include <BRepGProp.hxx>
48 #include <BRepBndLib.hxx>
49 #include <BRepClass_FaceClassifier.hxx>
50 #include <BRepClass3d_SolidClassifier.hxx>
52 #include <Bnd_Box.hxx>
53 #include <GProp_GProps.hxx>
54 #include <Precision.hxx>
64 #include "HDFconvert.hxx"
66 //=============================================================================
70 //=============================================================================
72 GHS3DPlugin_GHS3D::GHS3DPlugin_GHS3D(int hypId, int studyId, SMESH_Gen* gen)
73 : SMESH_3D_Algo(hypId, studyId, gen)
75 MESSAGE("GHS3DPlugin_GHS3D::GHS3DPlugin_GHS3D");
77 _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);// 1 bit /shape type
82 //=============================================================================
86 //=============================================================================
88 GHS3DPlugin_GHS3D::~GHS3DPlugin_GHS3D()
90 MESSAGE("GHS3DPlugin_GHS3D::~GHS3DPlugin_GHS3D");
93 //=============================================================================
97 //=============================================================================
99 bool GHS3DPlugin_GHS3D::CheckHypothesis ( SMESH_Mesh& aMesh,
100 const TopoDS_Shape& aShape,
101 SMESH_Hypothesis::Hypothesis_Status& aStatus )
103 // MESSAGE("GHS3DPlugin_GHS3D::CheckHypothesis");
104 aStatus = SMESH_Hypothesis::HYP_OK;
108 //=======================================================================
109 //function : writeFaces
111 //=======================================================================
113 static bool writeFaces (ofstream & theFile,
114 SMESHDS_Mesh * theMesh,
115 const map <int,int> & theSmdsToGhs3dIdMap)
119 // NB_ELEMS DUMMY_INT
120 // Loop from 1 to NB_ELEMS
121 // NB_NODES NODE_NB_1 NODE_NB_2 ... (NB_NODES + 1) times: DUMMY_INT
123 // get all faces bound to theShape
126 TopoDS_Shape theShape = theMesh->ShapeToMesh();
127 list< const SMDS_MeshElement* > faces;
128 TopExp_Explorer fExp( theShape, TopAbs_FACE );
130 SMDS_ElemIteratorPtr eIt;
132 const char* space = " ";
133 const int dummyint = 0;
135 list< const SMDS_MeshElement* >::iterator f;
136 map<int,int>::const_iterator it;
137 SMDS_ElemIteratorPtr nodeIt;
138 const SMDS_MeshElement* elem;
142 for ( ; fExp.More(); fExp.Next() ) {
143 sm = theMesh->MeshElements( fExp.Current() );
145 eIt = sm->GetElements();
146 while ( eIt->more() ) {
147 faces.push_back( eIt->next() );
156 cout << " " << nbFaces << " triangles" << endl;
159 // NB_ELEMS DUMMY_INT
160 theFile << space << nbFaces << space << dummyint << endl;
162 // Loop from 1 to NB_ELEMS
165 for ( ; f != faces.end(); ++f )
169 nbNodes = elem->NbNodes();
170 theFile << space << nbNodes;
172 // NODE_NB_1 NODE_NB_2 ...
173 nodeIt = elem->nodesIterator();
174 while ( nodeIt->more() )
177 aSmdsID = nodeIt->next()->GetID();
178 it = theSmdsToGhs3dIdMap.find( aSmdsID );
179 ASSERT( it != theSmdsToGhs3dIdMap.end() );
180 theFile << space << (*it).second;
183 // (NB_NODES + 1) times: DUMMY_INT
184 for ( int i=0; i<=nbNodes; i++)
185 theFile << space << dummyint;
193 //=======================================================================
194 //function : writePoints
196 //=======================================================================
198 static bool writePoints (ofstream & theFile,
199 SMESHDS_Mesh * theMesh,
200 map <int,int> & theSmdsToGhs3dIdMap,
201 map <int,const SMDS_MeshNode*> & theGhs3dIdToNodeMap)
206 // Loop from 1 to NB_NODES
209 int nbNodes = theMesh->NbNodes();
213 const char* space = " ";
214 const int dummyint = 0;
217 SMDS_NodeIteratorPtr it = theMesh->nodesIterator();
218 const SMDS_MeshNode* node;
221 theFile << space << nbNodes << endl;
222 cout << "The 2D mesh contains :" << endl;
223 cout << " " << nbNodes << " nodes" << endl;
225 // Loop from 1 to NB_NODES
230 theSmdsToGhs3dIdMap.insert( map <int,int>::value_type( node->GetID(), aGhs3dID ));
231 theGhs3dIdToNodeMap.insert (map <int,const SMDS_MeshNode*>::value_type( aGhs3dID, node ));
236 << space << node->X()
237 << space << node->Y()
238 << space << node->Z()
239 << space << dummyint;
247 //=======================================================================
248 //function : findSolid
250 //=======================================================================
252 static TopoDS_Shape findSolid(const SMDS_MeshNode *aNode[],
254 const TopoDS_Shape shape[],
255 const double box[][6],
258 Standard_Real PX, PY, PZ;
261 PX = ( aNode[0]->X() + aNode[1]->X() + aNode[2]->X() + aNode[3]->X() ) / 4.0;
262 PY = ( aNode[0]->Y() + aNode[1]->Y() + aNode[2]->Y() + aNode[3]->Y() ) / 4.0;
263 PZ = ( aNode[0]->Z() + aNode[1]->Z() + aNode[2]->Z() + aNode[3]->Z() ) / 4.0;
264 gp_Pnt aPnt(PX, PY, PZ);
266 BRepClass3d_SolidClassifier SC (aSolid, aPnt, Precision::Confusion());
267 if ( not(SC.State() == TopAbs_IN) ) {
268 for (iShape = 0; iShape < nShape; iShape++) {
269 aSolid = shape[iShape];
270 if ( not( PX < box[iShape][0] || box[iShape][1] < PX ||
271 PY < box[iShape][2] || box[iShape][3] < PY ||
272 PZ < box[iShape][4] || box[iShape][5] < PZ) ) {
273 BRepClass3d_SolidClassifier SC (aSolid, aPnt, Precision::Confusion());
274 if (SC.State() == TopAbs_IN)
282 //=======================================================================
283 //function : readMapIntLine
285 //=======================================================================
287 static char* readMapIntLine(char* ptr, int tab[]) {
293 while ( *ptr != *ptrRet ) {
294 intVal = strtol(ptr, &ptr, 10);
302 //=======================================================================
303 //function : readResultFile
305 //=======================================================================
307 static bool readResultFile(const int fileOpen,
308 SMESHDS_Mesh* theMeshDS,
309 TopoDS_Shape tabShape[],
312 map <int,const SMDS_MeshNode*>& theGhs3dIdToNodeMap) {
321 int fileStat, fileClose;
322 int nbElems, nbNodes, nbInputNodes;
323 int nodeId, triangleId;
324 int tab[3], tabID[nShape];
326 int ID, shapeID, ghs3dShapeID;
331 SMDS_MeshNode * aNewNode;
332 const SMDS_MeshNode * node[4];
333 map <int,const SMDS_MeshNode*>::iterator IdNode;
334 SMDS_MeshElement* aTet;
336 for (int i=0; i<nShape; i++)
339 // Read the file state
340 fileStat = fstat(fileOpen, &status);
341 length = status.st_size;
343 // Mapping the result file into memory
344 ptr = (char *) mmap(0,length,PROT_READ,MAP_PRIVATE,fileOpen,0);
345 fileClose = close(fileOpen);
347 ptr = readMapIntLine(ptr, tab);
352 nbInputNodes = tab[2];
354 // Reading the nodeId
355 for (int i=0; i < 4*nbElems; i++)
356 nodeId = strtol(ptr, &ptr, 10);
358 // Reading the nodeCoor and update the nodeMap
359 for (int iNode=0; iNode < nbNodes; iNode++) {
360 for (int iCoor=0; iCoor < 3; iCoor++)
361 coord[ iCoor ] = strtod(ptr, &ptr);
362 if ((iNode+1) > nbInputNodes) {
363 aNewNode = theMeshDS->AddNode( coord[0],coord[1],coord[2] );
364 theGhs3dIdToNodeMap.insert(make_pair( (iNode+1), aNewNode ));
368 // Reading the triangles
369 nbTriangle = strtol(ptr, &ptr, 10);
371 for (int i=0; i < 3*nbTriangle; i++)
372 triangleId = strtol(ptr, &ptr, 10);
376 // Associating the tetrahedrons with the shapes
377 for (int iElem = 0; iElem < nbElems; iElem++) {
378 for (int iNode = 0; iNode < 4; iNode++) {
379 ID = strtol(tetraPtr, &tetraPtr, 10);
380 IdNode = theGhs3dIdToNodeMap.find(ID);
381 node[ iNode ] = IdNode->second;
383 aTet = theMeshDS->AddVolume( node[1], node[0], node[2], node[3] );
384 ghs3dShapeID = strtol(shapePtr, &shapePtr, 10);
385 if ( tabID[ ghs3dShapeID - 1 ] == 0 ) {
387 aSolid = tabShape[0];
388 aSolid = findSolid(node, aSolid, tabShape, tabBox, nbTriangle);
389 shapeID = theMeshDS->ShapeToIndex( aSolid );
390 tabID[ ghs3dShapeID - 1] = shapeID;
393 shapeID = tabID[ ghs3dShapeID - 1];
394 theMeshDS->SetMeshElementOnShape( aTet, shapeID );
399 //=======================================================================
400 //function : getTmpDir
402 //=======================================================================
404 static TCollection_AsciiString getTmpDir()
406 TCollection_AsciiString aTmpDir;
408 char *Tmp_dir = getenv("SALOME_TMP_DIR");
409 if(Tmp_dir != NULL) {
412 if(aTmpDir.Value(aTmpDir.Length()) != '\\') aTmpDir+='\\';
414 if(aTmpDir.Value(aTmpDir.Length()) != '/') aTmpDir+='/';
419 aTmpDir = TCollection_AsciiString("C:\\");
421 aTmpDir = TCollection_AsciiString("/tmp/");
427 //=============================================================================
429 *Here we are going to use the GHS3D mesher
431 //=============================================================================
433 bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh& theMesh,
434 const TopoDS_Shape& theShape)
437 SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
439 if (_iShape == 0 && _nbShape == 0) {
441 cout << "Ghs3d execution..." << endl;
444 TopExp_Explorer exp (meshDS->ShapeToMesh(), TopAbs_SOLID);
445 for (; exp.More(); exp.Next())
451 if ( _iShape == _nbShape ) {
453 // create bounding box for every shape
456 TopoDS_Shape tabShape[_nbShape];
457 double tabBox[_nbShape][6];
458 Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
460 TopExp_Explorer expBox (meshDS->ShapeToMesh(), TopAbs_SOLID);
461 for (; expBox.More(); expBox.Next()) {
462 tabShape[iShape] = expBox.Current();
464 BRepBndLib::Add(expBox.Current(), BoundingBox);
465 BoundingBox.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
466 tabBox[iShape][0] = Xmin; tabBox[iShape][1] = Xmax;
467 tabBox[iShape][2] = Ymin; tabBox[iShape][3] = Ymax;
468 tabBox[iShape][4] = Zmin; tabBox[iShape][5] = Zmax;
472 // make a unique working file name
473 // to avoid access to the same files by eg different users
475 TCollection_AsciiString aGenericName, aTmpDir = getTmpDir();
476 aGenericName = aTmpDir + "GHS3D_";
478 aGenericName += GetCurrentProcessId();
480 aGenericName += getpid();
483 aGenericName += meshDS->ShapeToIndex( theShape );
485 TCollection_AsciiString aFacesFileName, aPointsFileName, aResultFileName;
486 TCollection_AsciiString aBadResFileName, aBbResFileName, aLogFileName;
487 aFacesFileName = aGenericName + ".faces"; // in faces
488 aPointsFileName = aGenericName + ".points"; // in points
489 aResultFileName = aGenericName + ".noboite";// out points and volumes
490 aBadResFileName = aGenericName + ".boite"; // out bad result
491 aBbResFileName = aGenericName + ".bb"; // out vertex stepsize
492 aLogFileName = aGenericName + ".log"; // log
498 ofstream aFacesFile ( aFacesFileName.ToCString() , ios::out);
499 ofstream aPointsFile ( aPointsFileName.ToCString() , ios::out);
503 aFacesFile->is_open() && aPointsFile->is_open();
505 aFacesFile.rdbuf()->is_open() && aPointsFile.rdbuf()->is_open();
508 INFOS( "Can't write into " << aTmpDir.ToCString());
511 map <int,int> aSmdsToGhs3dIdMap;
512 map <int,const SMDS_MeshNode*> aGhs3dIdToNodeMap;
514 Ok = writePoints( aPointsFile, meshDS, aSmdsToGhs3dIdMap, aGhs3dIdToNodeMap ) &&
515 writeFaces ( aFacesFile, meshDS, aSmdsToGhs3dIdMap );
521 if ( !getenv("GHS3D_KEEP_FILES") ) {
522 OSD_File( aFacesFileName ).Remove();
523 OSD_File( aPointsFileName ).Remove();
529 // run ghs3d mesher WIN32???
532 // ghs3d need to know amount of memory it may use (MB).
533 // Default memory is defined at ghs3d installation but it may be not enough,
534 // so allow to use about all available memory
536 TCollection_AsciiString memory;
539 int err = sysinfo( &si );
541 int freeMem = si.totalram * si.mem_unit / 1024 / 1024;
543 memory += int( 0.7 * freeMem );
547 MESSAGE("GHS3DPlugin_GHS3D::Compute");
548 TCollection_AsciiString cmd( "ghs3d " ); // command to run
551 " -c0 -f " + aGenericName + // file to read
552 " 1>" + aLogFileName; // dump into file
554 system( cmd.ToCString() ); // run
557 cout << "End of Ghs3d execution !" << endl;
563 // Mapping the result file
566 fileOpen = open( aResultFileName.ToCString(), O_RDONLY);
567 if ( fileOpen < 0 ) {
569 cout << "Error when opening the " << aResultFileName.ToCString() << " file" << endl;
574 Ok = readResultFile( fileOpen, meshDS, tabShape, tabBox, _nbShape, aGhs3dIdToNodeMap );
576 // ---------------------
577 // remove working files
578 // ---------------------
581 OSD_File( aLogFileName ).Remove();
583 else if ( OSD_File( aLogFileName ).Size() > 0 ) {
584 INFOS( "GHS3D Error: see " << aLogFileName.ToCString() );
587 OSD_File( aLogFileName ).Remove();
588 INFOS( "GHS3D Error: command '" << cmd.ToCString() << "' failed" );
591 if ( !getenv("GHS3D_KEEP_FILES") ) {
592 OSD_File( aFacesFileName ).Remove();
593 OSD_File( aPointsFileName ).Remove();
594 OSD_File( aResultFileName ).Remove();
595 OSD_File( aBadResFileName ).Remove();
596 OSD_File( aBbResFileName ).Remove();
598 if ( _iShape == _nbShape ) {
599 cout << "Output file " << aResultFileName.ToCString();
601 cout << " not treated !" << endl;
603 cout << " treated !" << endl;
611 //=============================================================================
615 //=============================================================================
617 ostream & GHS3DPlugin_GHS3D::SaveTo(ostream & save)
622 //=============================================================================
626 //=============================================================================
628 istream & GHS3DPlugin_GHS3D::LoadFrom(istream & load)
633 //=============================================================================
637 //=============================================================================
639 ostream & operator << (ostream & save, GHS3DPlugin_GHS3D & hyp)
641 return hyp.SaveTo( save );
644 //=============================================================================
648 //=============================================================================
650 istream & operator >> (istream & load, GHS3DPlugin_GHS3D & hyp)
652 return hyp.LoadFrom( load );