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>
73 //=============================================================================
77 //=============================================================================
79 GHS3DPlugin_GHS3D::GHS3DPlugin_GHS3D(int hypId, int studyId, SMESH_Gen* gen)
80 : SMESH_3D_Algo(hypId, studyId, gen)
82 MESSAGE("GHS3DPlugin_GHS3D::GHS3DPlugin_GHS3D");
84 _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);// 1 bit /shape type
89 //=============================================================================
93 //=============================================================================
95 GHS3DPlugin_GHS3D::~GHS3DPlugin_GHS3D()
97 MESSAGE("GHS3DPlugin_GHS3D::~GHS3DPlugin_GHS3D");
100 //=============================================================================
104 //=============================================================================
106 bool GHS3DPlugin_GHS3D::CheckHypothesis ( SMESH_Mesh& aMesh,
107 const TopoDS_Shape& aShape,
108 SMESH_Hypothesis::Hypothesis_Status& aStatus )
110 // MESSAGE("GHS3DPlugin_GHS3D::CheckHypothesis");
111 aStatus = SMESH_Hypothesis::HYP_OK;
115 //=======================================================================
116 //function : writeFaces
118 //=======================================================================
120 static bool writeFaces (ofstream & theFile,
121 SMESHDS_Mesh * theMesh,
122 const map <int,int> & theSmdsToGhs3dIdMap)
126 // NB_ELEMS DUMMY_INT
127 // Loop from 1 to NB_ELEMS
128 // NB_NODES NODE_NB_1 NODE_NB_2 ... (NB_NODES + 1) times: DUMMY_INT
130 // get all faces bound to theShape
133 TopoDS_Shape theShape = theMesh->ShapeToMesh();
134 list< const SMDS_MeshElement* > faces;
135 TopExp_Explorer fExp( theShape, TopAbs_FACE );
137 SMDS_ElemIteratorPtr eIt;
139 const char* space = " ";
140 const int dummyint = 0;
142 list< const SMDS_MeshElement* >::iterator f;
143 map<int,int>::const_iterator it;
144 SMDS_ElemIteratorPtr nodeIt;
145 const SMDS_MeshElement* elem;
149 for ( ; fExp.More(); fExp.Next() ) {
150 sm = theMesh->MeshElements( fExp.Current() );
152 eIt = sm->GetElements();
153 while ( eIt->more() ) {
154 faces.push_back( eIt->next() );
163 cout << nbFaces << " triangles" << endl;
165 // NB_ELEMS DUMMY_INT
166 theFile << space << nbFaces << space << dummyint << endl;
168 // Loop from 1 to NB_ELEMS
171 for ( ; f != faces.end(); ++f )
175 nbNodes = elem->NbNodes();
176 theFile << space << nbNodes;
178 // NODE_NB_1 NODE_NB_2 ...
179 nodeIt = elem->nodesIterator();
180 while ( nodeIt->more() )
183 aSmdsID = nodeIt->next()->GetID();
184 it = theSmdsToGhs3dIdMap.find( aSmdsID );
185 ASSERT( it != theSmdsToGhs3dIdMap.end() );
186 theFile << space << (*it).second;
189 // (NB_NODES + 1) times: DUMMY_INT
190 for ( int i=0; i<=nbNodes; i++)
191 theFile << space << dummyint;
199 //=======================================================================
200 //function : writePoints
202 //=======================================================================
204 static bool writePoints (ofstream & theFile,
205 SMESHDS_Mesh * theMesh,
206 map <int,int> & theSmdsToGhs3dIdMap,
207 map <int,const SMDS_MeshNode*> & theGhs3dIdToNodeMap)
212 // Loop from 1 to NB_NODES
215 int nbNodes = theMesh->NbNodes();
219 const char* space = " ";
220 const int dummyint = 0;
223 SMDS_NodeIteratorPtr it = theMesh->nodesIterator();
224 const SMDS_MeshNode* node;
227 theFile << space << nbNodes << endl;
228 cout << "The initial 2D mesh contains " << nbNodes << " nodes and ";
230 // Loop from 1 to NB_NODES
235 theSmdsToGhs3dIdMap.insert( map <int,int>::value_type( node->GetID(), aGhs3dID ));
236 theGhs3dIdToNodeMap.insert (map <int,const SMDS_MeshNode*>::value_type( aGhs3dID, node ));
241 << space << node->X()
242 << space << node->Y()
243 << space << node->Z()
244 << space << dummyint;
252 //=======================================================================
253 //function : findSolid
255 //=======================================================================
257 static TopoDS_Shape findSolid(const SMDS_MeshNode *aNode[],
259 const TopoDS_Shape shape[],
260 const double box[][6],
263 Standard_Real PX, PY, PZ;
266 PX = ( aNode[0]->X() + aNode[1]->X() + aNode[2]->X() + aNode[3]->X() ) / 4.0;
267 PY = ( aNode[0]->Y() + aNode[1]->Y() + aNode[2]->Y() + aNode[3]->Y() ) / 4.0;
268 PZ = ( aNode[0]->Z() + aNode[1]->Z() + aNode[2]->Z() + aNode[3]->Z() ) / 4.0;
269 gp_Pnt aPnt(PX, PY, PZ);
271 BRepClass3d_SolidClassifier SC (aSolid, aPnt, Precision::Confusion());
272 if ( not(SC.State() == TopAbs_IN) ) {
273 for (iShape = 0; iShape < nShape; iShape++) {
274 aSolid = shape[iShape];
275 if ( not( PX < box[iShape][0] || box[iShape][1] < PX ||
276 PY < box[iShape][2] || box[iShape][3] < PY ||
277 PZ < box[iShape][4] || box[iShape][5] < PZ) ) {
278 BRepClass3d_SolidClassifier SC (aSolid, aPnt, Precision::Confusion());
279 if (SC.State() == TopAbs_IN)
287 //=======================================================================
288 //function : readMapIntLine
290 //=======================================================================
292 static char* readMapIntLine(char* ptr, int tab[]) {
296 for ( int i=0; i<17; i++ ) {
297 intVal = strtol(ptr, &ptr, 10);
304 //=======================================================================
305 //function : readResultFile
307 //=======================================================================
309 static bool readResultFile(const int fileOpen,
310 SMESHDS_Mesh* theMeshDS,
311 TopoDS_Shape tabShape[],
314 map <int,const SMDS_MeshNode*>& theGhs3dIdToNodeMap) {
324 int nbElems, nbNodes, nbInputNodes;
325 int nodeId, triangleId;
326 int tab[3], tabID[nShape];
328 int ID, shapeID, ghs3dShapeID;
333 SMDS_MeshNode * aNewNode;
334 const SMDS_MeshNode * node[4];
335 map <int,const SMDS_MeshNode*>::iterator IdNode;
336 SMDS_MeshElement* aTet;
338 for (int i=0; i<nShape; i++)
341 // Read the file state
342 fileStat = fstat(fileOpen, &status);
343 length = status.st_size;
345 // Mapping the result file into memory
346 ptr = (char *) mmap(0,length,PROT_READ,MAP_PRIVATE,fileOpen,0);
349 ptr = readMapIntLine(ptr, tab);
354 nbInputNodes = tab[2];
356 // Reading the nodeId
357 for (int i=0; i < 4*nbElems; i++)
358 nodeId = strtol(ptr, &ptr, 10);
360 // Reading the nodeCoor and update the nodeMap
361 for (int iNode=0; iNode < nbNodes; iNode++) {
362 for (int iCoor=0; iCoor < 3; iCoor++)
363 coord[ iCoor ] = strtod(ptr, &ptr);
364 if ((iNode+1) > nbInputNodes) {
365 aNewNode = theMeshDS->AddNode( coord[0],coord[1],coord[2] );
366 theGhs3dIdToNodeMap.insert(make_pair( (iNode+1), aNewNode ));
370 // Reading the triangles
371 nbTriangle = strtol(ptr, &ptr, 10);
373 for (int i=0; i < 3*nbTriangle; i++)
374 triangleId = strtol(ptr, &ptr, 10);
378 // Associating the tetrahedrons to the shapes
379 for (int iElem = 0; iElem < nbElems; iElem++) {
380 for (int iNode = 0; iNode < 4; iNode++) {
381 ID = strtol(tetraPtr, &tetraPtr, 10);
382 IdNode = theGhs3dIdToNodeMap.find(ID);
383 node[ iNode ] = IdNode->second;
385 aTet = theMeshDS->AddVolume( node[1], node[0], node[2], node[3] );
386 ghs3dShapeID = strtol(shapePtr, &shapePtr, 10);
387 if ( tabID[ ghs3dShapeID - 1 ] == 0 ) {
389 aSolid = tabShape[0];
390 aSolid = findSolid(node, aSolid, tabShape, tabBox, nbTriangle);
391 shapeID = theMeshDS->ShapeToIndex( aSolid );
392 tabID[ ghs3dShapeID - 1] = shapeID;
395 shapeID = tabID[ ghs3dShapeID - 1];
396 theMeshDS->SetMeshElementOnShape( aTet, shapeID );
397 if ( (iElem + 1) == nbElems )
398 cout << nbElems << " tetrahedrons have been associated to " << nbTriangle << " shapes" << endl;
400 munmap(mapPtr, length);
405 //=======================================================================
406 //function : getTmpDir
408 //=======================================================================
410 static TCollection_AsciiString getTmpDir()
412 TCollection_AsciiString aTmpDir;
414 char *Tmp_dir = getenv("SALOME_TMP_DIR");
415 if(Tmp_dir != NULL) {
418 if(aTmpDir.Value(aTmpDir.Length()) != '\\') aTmpDir+='\\';
420 if(aTmpDir.Value(aTmpDir.Length()) != '/') aTmpDir+='/';
425 aTmpDir = TCollection_AsciiString("C:\\");
427 aTmpDir = TCollection_AsciiString("/tmp/");
433 //=============================================================================
435 *Here we are going to use the GHS3D mesher
437 //=============================================================================
439 bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh& theMesh,
440 const TopoDS_Shape& theShape)
443 SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
445 if (_iShape == 0 && _nbShape == 0) {
447 cout << "Ghs3d execution..." << endl;
450 TopExp_Explorer exp (meshDS->ShapeToMesh(), TopAbs_SOLID);
451 for (; exp.More(); exp.Next())
457 if ( _iShape == _nbShape ) {
459 // create bounding box for every shape
462 TopoDS_Shape tabShape[_nbShape];
463 double tabBox[_nbShape][6];
464 Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
466 TopExp_Explorer expBox (meshDS->ShapeToMesh(), TopAbs_SOLID);
467 for (; expBox.More(); expBox.Next()) {
468 tabShape[iShape] = expBox.Current();
470 BRepBndLib::Add(expBox.Current(), BoundingBox);
471 BoundingBox.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
472 tabBox[iShape][0] = Xmin; tabBox[iShape][1] = Xmax;
473 tabBox[iShape][2] = Ymin; tabBox[iShape][3] = Ymax;
474 tabBox[iShape][4] = Zmin; tabBox[iShape][5] = Zmax;
478 // make a unique working file name
479 // to avoid access to the same files by eg different users
481 TCollection_AsciiString aGenericName, aTmpDir = getTmpDir();
482 aGenericName = aTmpDir + "GHS3D_";
484 aGenericName += GetCurrentProcessId();
486 aGenericName += getpid();
489 aGenericName += meshDS->ShapeToIndex( theShape );
491 TCollection_AsciiString aFacesFileName, aPointsFileName, aResultFileName;
492 TCollection_AsciiString aBadResFileName, aBbResFileName, aLogFileName;
493 aFacesFileName = aGenericName + ".faces"; // in faces
494 aPointsFileName = aGenericName + ".points"; // in points
495 aResultFileName = aGenericName + ".noboite";// out points and volumes
496 aBadResFileName = aGenericName + ".boite"; // out bad result
497 aBbResFileName = aGenericName + ".bb"; // out vertex stepsize
498 aLogFileName = aGenericName + ".log"; // log
504 ofstream aFacesFile ( aFacesFileName.ToCString() , ios::out);
505 ofstream aPointsFile ( aPointsFileName.ToCString() , ios::out);
509 aFacesFile->is_open() && aPointsFile->is_open();
511 aFacesFile.rdbuf()->is_open() && aPointsFile.rdbuf()->is_open();
514 INFOS( "Can't write into " << aTmpDir.ToCString());
517 map <int,int> aSmdsToGhs3dIdMap;
518 map <int,const SMDS_MeshNode*> aGhs3dIdToNodeMap;
520 Ok = writePoints( aPointsFile, meshDS, aSmdsToGhs3dIdMap, aGhs3dIdToNodeMap ) &&
521 writeFaces ( aFacesFile, meshDS, aSmdsToGhs3dIdMap );
527 if ( !getenv("GHS3D_KEEP_FILES") ) {
528 OSD_File( aFacesFileName ).Remove();
529 OSD_File( aPointsFileName ).Remove();
535 // run ghs3d mesher WIN32???
538 // ghs3d need to know amount of memory it may use (MB).
539 // Default memory is defined at ghs3d installation but it may be not enough,
540 // so allow to use about all available memory
542 TCollection_AsciiString memory;
545 int err = sysinfo( &si );
547 int freeMem = si.totalram * si.mem_unit / 1024 / 1024;
549 memory += int( 0.7 * freeMem );
553 MESSAGE("GHS3DPlugin_GHS3D::Compute");
554 TCollection_AsciiString cmd( "ghs3d " ); // command to run
557 " -c0 -f " + aGenericName + // file to read
558 " 1>" + aLogFileName; // dump into file
560 system( cmd.ToCString() ); // run
563 cout << "End of Ghs3d execution !" << endl;
569 // Mapping the result file
572 fileOpen = open( aResultFileName.ToCString(), O_RDONLY);
573 if ( fileOpen < 0 ) {
575 cout << "Error when opening the " << aResultFileName.ToCString() << " file" << endl;
580 Ok = readResultFile( fileOpen, meshDS, tabShape, tabBox, _nbShape, aGhs3dIdToNodeMap );
582 // ---------------------
583 // remove working files
584 // ---------------------
587 OSD_File( aLogFileName ).Remove();
588 else if ( OSD_File( aLogFileName ).Size() > 0 ) {
589 INFOS( "GHS3D Error: see " << aLogFileName.ToCString() );
592 OSD_File( aLogFileName ).Remove();
593 INFOS( "GHS3D Error: command '" << cmd.ToCString() << "' failed" );
596 if ( !getenv("GHS3D_KEEP_FILES") ) {
597 OSD_File( aFacesFileName ).Remove();
598 OSD_File( aPointsFileName ).Remove();
599 OSD_File( aResultFileName ).Remove();
600 OSD_File( aBadResFileName ).Remove();
601 OSD_File( aBbResFileName ).Remove();
603 if ( _iShape == _nbShape ) {
604 cout << aResultFileName.ToCString() << " Output file ";
607 cout << "treated !" << endl;
615 //=============================================================================
619 //=============================================================================
621 ostream & GHS3DPlugin_GHS3D::SaveTo(ostream & save)
626 //=============================================================================
630 //=============================================================================
632 istream & GHS3DPlugin_GHS3D::LoadFrom(istream & load)
637 //=============================================================================
641 //=============================================================================
643 ostream & operator << (ostream & save, GHS3DPlugin_GHS3D & hyp)
645 return hyp.SaveTo( save );
648 //=============================================================================
652 //=============================================================================
654 istream & operator >> (istream & load, GHS3DPlugin_GHS3D & hyp)
656 return hyp.LoadFrom( load );