From: eap Date: Tue, 23 Aug 2016 10:43:28 +0000 (+0300) Subject: 23308: [EDF] Re-implement DISTENE meshing plugins to use libraries instead of executables X-Git-Tag: V8_1_0rc1~7 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=c4621e29931db6ea7478d333448dac4f78fc3752;p=plugins%2Fhexoticplugin.git 23308: [EDF] Re-implement DISTENE meshing plugins to use libraries instead of executables --- diff --git a/CMakeLists.txt b/CMakeLists.txt index d843de7..0456203 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,6 +75,8 @@ IF(SALOME_BUILD_TESTS) ENDIF() # Advanced options: +OPTION(SALOME_USE_MG_LIBS "Use MeshGems libraries" ON) +MARK_AS_ADVANCED(SALOME_USE_MG_LIBS) OPTION(SALOME_BUILD_GUI "Enable HexoticPLUGIN GUI" ON) MARK_AS_ADVANCED(SALOME_BUILD_GUI) OPTION(SALOME_HEXOTICPLUGIN_USE_BLSURFPLUGIN "Enable using BLSURFPLUGIN" ON) @@ -164,6 +166,16 @@ ELSE(EXISTS ${SMESH_ROOT_DIR}) MESSAGE(FATAL_ERROR "We absolutely need a Salome SMESH, please define SMESH_ROOT_DIR") ENDIF(EXISTS ${SMESH_ROOT_DIR}) +## +## Find MESHGEMS (optional) +## ============= + +IF(SALOME_USE_MG_LIBS) + FIND_PACKAGE(SalomeMESHGEMS) + SALOME_LOG_OPTIONAL_PACKAGE(MESHGEMS SALOME_USE_MG_LIBS) + ADD_DEFINITIONS(-DUSE_MG_LIBS) +ENDIF(SALOME_USE_MG_LIBS) + # Find BLSURFPLUGIN (optional) # =========== @@ -270,17 +282,18 @@ EXPORT(TARGETS ${_${PROJECT_NAME}_exposed_targets} # Ensure the variables are always defined for the configure: SET(SMESH_ROOT_DIR "${SMESH_ROOT_DIR}") +SET(MESHGEMS_ROOT_DIR "${MESHGEMS_ROOT_DIR}") SET(CONF_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/include" "${PROJECT_BINARY_DIR}/include") # Build variables that will be expanded when configuring SalomeConfig.cmake: -# SALOME_CONFIGURE_PREPARE() #For use in the future +SALOME_CONFIGURE_PREPARE(MESHGEMS) CONFIGURE_PACKAGE_CONFIG_FILE(${PROJECT_NAME}Config.cmake.in ${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake INSTALL_DESTINATION "${SALOME_INSTALL_CMAKE_LOCAL}" PATH_VARS CONF_INCLUDE_DIRS SALOME_INSTALL_CMAKE_LOCAL CMAKE_INSTALL_PREFIX - SMESH_ROOT_DIR) + SMESH_ROOT_DIR MESHGEMS_ROOT_DIR) WRITE_BASIC_PACKAGE_VERSION_FILE(${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake VERSION ${${PROJECT_NAME_UC}_VERSION} diff --git a/src/GUI/HexoticPluginGUI_StdWidget.cxx b/src/GUI/HexoticPluginGUI_StdWidget.cxx index 50516ed..2113cb2 100644 --- a/src/GUI/HexoticPluginGUI_StdWidget.cxx +++ b/src/GUI/HexoticPluginGUI_StdWidget.cxx @@ -84,7 +84,7 @@ void HexoticPluginGUI_StdWidget::onDirBtnClicked() { QString dir = SUIT_FileDlg::getExistingDirectory( this, myHexoticWorkingDir->text(), QString() ); if ( !dir.isEmpty() ) - myHexoticWorkingDir->setText( dir ); + myHexoticWorkingDir->setText( dir ); } void HexoticPluginGUI_StdWidget::onSdModeSelected(int sdMode) { diff --git a/src/GUI/HexoticPluginGUI_StdWidget_QTD.ui b/src/GUI/HexoticPluginGUI_StdWidget_QTD.ui index 2ee4018..1416d0c 100644 --- a/src/GUI/HexoticPluginGUI_StdWidget_QTD.ui +++ b/src/GUI/HexoticPluginGUI_StdWidget_QTD.ui @@ -109,7 +109,7 @@ - 2 + 10 1 diff --git a/src/HexoticPlugin/CMakeLists.txt b/src/HexoticPlugin/CMakeLists.txt index 55bfa22..38e1ea4 100644 --- a/src/HexoticPlugin/CMakeLists.txt +++ b/src/HexoticPlugin/CMakeLists.txt @@ -25,6 +25,7 @@ INCLUDE_DIRECTORIES( ${Boost_INCLUDE_DIRS} ${CAS_INCLUDE_DIRS} ${VTK_INCLUDE_DIRS} + ${MESHGEMS_INCLUDE_DIRS} ${KERNEL_INCLUDE_DIRS} ${GUI_INCLUDE_DIRS} ${GEOM_INCLUDE_DIRS} @@ -47,6 +48,7 @@ SET(_link_LIBRARIES ${CAS_TKTopAlgo} ${CAS_TKBRep} ${CAS_SALOMELocalTrace} + ${MESHGEMS_HEXA_LIBRARY} ${SMESH_SMESHimpl} ${SMESH_SMESHEngine} ${SMESH_StdMeshersEngine} @@ -69,6 +71,7 @@ SET(HexoticEngine_HEADERS HexoticPlugin_Hexotic_i.hxx HexoticPlugin_Hypothesis.hxx HexoticPlugin_Hypothesis_i.hxx + MG_Hexotic_API.hxx ) # --- sources --- @@ -85,6 +88,7 @@ SET(HexoticEngine_SOURCES HexoticPlugin_Hypothesis_i.cxx HexoticPlugin_i.cxx HexoticPlugin_Defs.hxx + MG_Hexotic_API.cxx ) # --- scripts --- diff --git a/src/HexoticPlugin/HexoticPlugin_Hexotic.cxx b/src/HexoticPlugin/HexoticPlugin_Hexotic.cxx index 96a09d0..d08466c 100644 --- a/src/HexoticPlugin/HexoticPlugin_Hexotic.cxx +++ b/src/HexoticPlugin/HexoticPlugin_Hexotic.cxx @@ -24,16 +24,10 @@ // #include "HexoticPlugin_Hexotic.hxx" #include "HexoticPlugin_Hypothesis.hxx" +#include "MG_Hexotic_API.hxx" #include "utilities.h" -#ifndef WIN32 -#include -#else -#include -#include -#endif - #ifdef _DEBUG_ #define DUMP(txt) \ // cout << txt @@ -41,8 +35,8 @@ #define DUMP(txt) #endif -#include #include +#include #include #include #include @@ -56,28 +50,29 @@ #include -#include #include #include -#include -#include +#include +#include +#include +#include +#include #include +#include #include #include #include #include -#include -#include -#include -#include -#include -#include #include -#include +#include +#include #include -#include "GEOMImpl_Types.hxx" -#include "GEOM_wrap.hxx" +#include +#include + +#define GMFVERSION GmfDouble +#define GMFDIMENSION 3 static void removeFile( const TCollection_AsciiString& fileName ) { @@ -101,7 +96,7 @@ HexoticPlugin_Hexotic::HexoticPlugin_Hexotic(int hypId, int studyId, SMESH_Gen* MESSAGE("HexoticPlugin_Hexotic::HexoticPlugin_Hexotic"); _name = "MG-Hexa"; _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);// 1 bit /shape type -// _onlyUnaryInput = false; + _onlyUnaryInput = false; _requireShape = false; _iShape=0; _nbShape=0; @@ -110,7 +105,7 @@ HexoticPlugin_Hexotic::HexoticPlugin_Hexotic(int hypId, int studyId, SMESH_Gen* #ifdef WITH_BLSURFPLUGIN _blsurfHypo = NULL; #endif - _compute_canceled = false; + _computeCanceled = false; // Copy of what is done in BLSURFPLugin TODO : share the code smeshGen_i = SMESH_Gen_i::GetSMESHGen(); @@ -119,7 +114,7 @@ HexoticPlugin_Hexotic::HexoticPlugin_Hexotic(int hypId, int studyId, SMESH_Gen* myStudy = NULL; myStudy = aStudyMgr->GetStudyByID(_studyId); - if (myStudy) + if ( !myStudy->_is_nil() ) MESSAGE("myStudy->StudyId() = " << myStudy->StudyId()); } @@ -254,21 +249,28 @@ static TopoDS_Shape findShape(SMDS_MeshNode** t_Node, //purpose : //======================================================================= -static int getNbShape(std::string aFile, std::string aString, int defaultValue=0) { - int number = defaultValue; - std::string aLine; - std::ifstream file(aFile.c_str()); - while ( !file.eof() ) { - getline( file, aLine); - if ( aLine == aString ) { - getline( file, aLine); - std::istringstream stringFlux( aLine ); - stringFlux >> number; +static int getNbShape(MG_Hexotic_API* hexaOutput, int iMesh, GmfKwdCod what, int defaultValue=0) +{ + int number = hexaOutput->GmfStatKwd( iMesh, what ); + if ( number > 0 ) + { + // std::string aLine; + // std::ifstream file(aFile.c_str()); + // while ( !file.eof() ) { + // getline( file, aLine); + // if ( aLine == aString ) { + // getline( file, aLine); + // std::istringstream stringFlux( aLine ); + // stringFlux >> number; number = ( number + defaultValue + std::abs(number - defaultValue) ) / 2; - break; - } + // break; + // } + } + else + { + number = defaultValue; } - file.close(); + //file.close(); return number; } @@ -277,9 +279,11 @@ static int getNbShape(std::string aFile, std::string aString, int defaultValue=0 //purpose : //======================================================================= -template < class Mesh, class Shape > -static int countShape( Mesh* mesh, Shape shape ) { - TopExp_Explorer expShape ( mesh->ShapeToMesh(), shape ); +static int countShape( SMESH_Mesh* mesh, TopAbs_ShapeEnum shape ) +{ + if ( !mesh->HasShapeToMesh() ) + return 0; + TopExp_Explorer expShape ( mesh->GetShapeToMesh(), shape ); TopTools_MapOfShape mapShape; int nbShape = 0; for ( ; expShape.More(); expShape.Next() ) { @@ -296,7 +300,8 @@ static int countShape( Mesh* mesh, Shape shape ) { //======================================================================= template < class Mesh, class Shape, class Tab > -void getShape(Mesh* mesh, Shape shape, Tab *t_Shape) { +void getShape(Mesh* mesh, Shape shape, Tab *t_Shape) +{ TopExp_Explorer expShape ( mesh->ShapeToMesh(), shape ); TopTools_MapOfShape mapShape; for ( int i=0; expShape.More(); expShape.Next() ) { @@ -348,18 +353,81 @@ static void splitQuads(SMESH_Mesh& aMesh) spliter.QuadToTri ( elems, /*the13Diag=*/true); } +//======================================================================= +//function : writeInput +//purpose : pass a mesh to input of MG-Hexa +//======================================================================= + +static void writeInput(MG_Hexotic_API* theHexaInput, + const char* theFile, + const SMESHDS_Mesh* theMeshDS) +{ + int meshID = theHexaInput->GmfOpenMesh( theFile, GmfWrite, GMFVERSION, GMFDIMENSION); + + // nodes + int iN = 0, nbNodes = theMeshDS->NbNodes(); + theHexaInput->GmfSetKwd( meshID, GmfVertices, nbNodes ); + std::map< const SMDS_MeshNode*, int, TIDCompare > node2IdMap; + SMDS_NodeIteratorPtr nodeIt = theMeshDS->nodesIterator(); + SMESH_TNodeXYZ n; + while ( nodeIt->more() ) + { + n.Set( nodeIt->next() ); + theHexaInput->GmfSetLin( meshID, GmfVertices, n.X(), n.Y(), n.Z(), n._node->getshapeId() ); + node2IdMap.insert( node2IdMap.end(), std::make_pair( n._node, ++iN )); + } + + // edges + SMDS_ElemIteratorPtr elemIt = theMeshDS->elementsIterator( SMDSAbs_Edge ); + if ( elemIt->more() ) + { + int nbEdges = theMeshDS->GetMeshInfo().NbElements( SMDSAbs_Edge ); + theHexaInput->GmfSetKwd(meshID, GmfEdges, nbEdges ); + for ( int gmfID = 1; elemIt->more(); ++gmfID ) + { + const SMDS_MeshElement* edge = elemIt->next(); + theHexaInput->GmfSetLin(meshID, GmfEdges, + node2IdMap[ edge->GetNode( 0 )], + node2IdMap[ edge->GetNode( 1 )], + edge->getshapeId() ); + } + } + + // triangles + elemIt = theMeshDS->elementGeomIterator( SMDSGeom_TRIANGLE ); + if ( elemIt->more() ) + { + int nbTria = theMeshDS->GetMeshInfo().NbElements( SMDSGeom_TRIANGLE ); + theHexaInput->GmfSetKwd(meshID, GmfTriangles, nbTria ); + for ( int gmfID = 1; elemIt->more(); ++gmfID ) + { + const SMDS_MeshElement* tria = elemIt->next(); + theHexaInput->GmfSetLin(meshID, GmfTriangles, + node2IdMap[ tria->GetNode( 0 )], + node2IdMap[ tria->GetNode( 1 )], + node2IdMap[ tria->GetNode( 2 )], + tria->getshapeId() ); + } + } + theHexaInput->GmfCloseMesh( meshID ); +} + //======================================================================= //function : readResult //purpose : Read GMF file in case of a mesh with geometry //======================================================================= -static bool readResult(std::string theFile, - HexoticPlugin_Hexotic* theAlgo, - SMESHDS_Mesh* theMesh, - const int nbShape, - const TopoDS_Shape* tabShape, - double** tabBox) +static bool readResult(MG_Hexotic_API* theHexaOutput, + const char* theFile, + HexoticPlugin_Hexotic*theAlgo, + SMESH_MesherHelper* theHelper, + const int nbShape = 0, + const TopoDS_Shape* tabShape = 0, + double** tabBox = 0) { + SMESH_Mesh* theMesh = theHelper->GetMesh(); + SMESHDS_Mesh* theMeshDS = theHelper->GetMeshDS(); + // --------------------------------- // Read generated elements and nodes // --------------------------------- @@ -367,409 +435,201 @@ static bool readResult(std::string theFile, TopoDS_Shape aShape; TopoDS_Vertex aVertex; std::string token; - int EndOfFile = 0, nbElem = 0, nField = 9, nbRef = 0; - int aHexoticNodeID = 0, shapeID, hexoticShapeID; + int shapeID, hexoticShapeID; const int IdShapeRef = 2; - int *tabID, *tabRef, *nodeAssigne; - bool *tabDummy, hasDummy = false; + int *tabID; double epsilon = Precision::Confusion(); std::map mapField; SMDS_MeshNode** HexoticNode; - TopoDS_Shape *tabCorner, *tabEdge; + TopoDS_Shape *tabCorner; const int nbDomains = countShape( theMesh, TopAbs_SHELL ); const int holeID = -1; - // tabID = new int[nbShape]; - tabID = new int[nbDomains]; - tabRef = new int[nField]; - tabDummy = new bool[nField]; - - for (int i=0; iShapeToIndex( tabShape[0] ); - - mapField["MeshVersionFormatted"] = 0; tabRef[0] = 0; tabDummy[0] = false; - mapField["Dimension"] = 1; tabRef[1] = 0; tabDummy[1] = false; - mapField["Vertices"] = 2; tabRef[2] = 3; tabDummy[2] = true; - mapField["Corners"] = 3; tabRef[3] = 1; tabDummy[3] = false; - mapField["Edges"] = 4; tabRef[4] = 2; tabDummy[4] = true; - mapField["Ridges"] = 5; tabRef[5] = 1; tabDummy[5] = false; - mapField["Quadrilaterals"] = 6; tabRef[6] = 4; tabDummy[6] = true; - mapField["Hexahedra"] = 7; tabRef[7] = 8; tabDummy[7] = true; - mapField["End"] = 8; tabRef[8] = 0; tabDummy[0] = false; - - SMDS_NodeIteratorPtr itOnHexoticInputNode = theMesh->nodesIterator(); - while ( itOnHexoticInputNode->more() ) - theMesh->RemoveNode( itOnHexoticInputNode->next() ); - - int nbVertices = getNbShape(theFile, "Vertices"); - int nbCorners = getNbShape(theFile, "Corners", countShape( theMesh, TopAbs_VERTEX )); - int nbShapeEdge = countShape( theMesh, TopAbs_EDGE ); + if ( nbDomains > 0 ) + { + tabID = new int[nbDomains]; + + for (int i=0; iShapeToIndex( tabShape[0] ); + } - tabCorner = new TopoDS_Shape[ nbCorners ]; - tabEdge = new TopoDS_Shape[ nbShapeEdge ]; - nodeAssigne = new int[ nbVertices + 1 ]; - HexoticNode = new SMDS_MeshNode*[ nbVertices + 1 ]; + SMDS_ElemIteratorPtr eIt = theMeshDS->elementsIterator(); + while( eIt->more() ) + theMeshDS->RemoveFreeElement( eIt->next(), /*sm=*/0 ); + SMDS_NodeIteratorPtr nIt = theMeshDS->nodesIterator(); + while ( nIt->more() ) + theMeshDS->RemoveFreeNode( nIt->next(), /*sm=*/0 ); - getShape(theMesh, TopAbs_VERTEX, tabCorner); - getShape(theMesh, TopAbs_EDGE, tabEdge); + int ver, dim; + int meshID = theHexaOutput->GmfOpenMesh( theFile, GmfRead, &ver, &dim ); - MESSAGE("Read " << theFile << " file"); - std::ifstream fileRes(theFile.c_str()); - ASSERT(fileRes); + int nbVertices = getNbShape(theHexaOutput, meshID, GmfVertices ); + int nbCorners = getNbShape(theHexaOutput, meshID, GmfCorners, countShape( theMesh, TopAbs_VERTEX )); + if ( nbVertices == 0 ) + return false; - while ( EndOfFile == 0 ) { - int dummy; - fileRes >> token; + tabCorner = new TopoDS_Shape[ nbCorners ]; + HexoticNode = new SMDS_MeshNode*[ nbVertices + 1 ]; - if (mapField.count(token)) { - nField = mapField[token]; - nbRef = tabRef[nField]; - hasDummy = tabDummy[nField]; - } - else { - nField = -1; - nbRef = 0; + getShape(theMeshDS, TopAbs_VERTEX, tabCorner); + + int nbNodes = theHexaOutput->GmfStatKwd( meshID, GmfVertices ); + if ( nbNodes > 0 ) + { + theHexaOutput->GmfGotoKwd( meshID, GmfVertices ); + double x,y,z; + for ( int aHexoticID = 1; aHexoticID <= nbNodes; ++aHexoticID ) + { + if ( theAlgo->computeCanceled() ) + return false; + theHexaOutput->GmfGetLin( meshID, GmfVertices, &x, &y, &z, &shapeID ); + HexoticNode[ aHexoticID ] = theHelper->AddNode( x,y,z ); } + } - nbElem = 0; - if ( nField < int(mapField.size() - 1) && nField >= 0 ) - fileRes >> nbElem; + int nodeID[8]; + SMDS_MeshNode* node[8]; + SMDS_MeshElement * aHexoticElement; - switch (nField) { - case 0: { // "MeshVersionFormatted" - MESSAGE(token << " " << nbElem); - break; - } - case 1: { // "Dimension" - MESSAGE("Mesh dimension " << nbElem << "D"); - break; - } - case 2: { // "Vertices" - MESSAGE("Read " << nbElem << " " << token); - int aHexoticID; - double *coord; - SMDS_MeshNode * aHexoticNode; - - coord = new double[nbRef]; - for ( int iElem = 0; iElem < nbElem; iElem++ ) { - if(theAlgo->computeCanceled()) - { - return false; - } - aHexoticID = iElem + 1; - for ( int iCoord = 0; iCoord < 3; iCoord++ ) - fileRes >> coord[ iCoord ]; - fileRes >> dummy; - aHexoticNode = theMesh->AddNode(coord[0], coord[1], coord[2]); - HexoticNode[ aHexoticID ] = aHexoticNode; - nodeAssigne[ aHexoticID ] = 0; - } - delete [] coord; - break; - } - case 3: // "Corners" - case 4: // "Edges" - case 5: // "Ridges" - case 6: // "Quadrilaterals" - case 7: { // "Hexahedra" - MESSAGE("Read " << nbElem << " " << token); - SMDS_MeshNode** node; - int nodeDim, *nodeID; - SMDS_MeshElement * aHexoticElement = 0; - - node = new SMDS_MeshNode*[ nbRef ]; - nodeID = new int[ nbRef ]; - for ( int iElem = 0; iElem < nbElem; iElem++ ) { - if(theAlgo->computeCanceled()) - { - return false; - } - for ( int iRef = 0; iRef < nbRef; iRef++ ) { - fileRes >> aHexoticNodeID; // read nbRef aHexoticNodeID - node[ iRef ] = HexoticNode[ aHexoticNodeID ]; - nodeID[ iRef ] = aHexoticNodeID; - } - if ( hasDummy ) - fileRes >> dummy; - switch (nField) { - case 3: { // "Corners" - nodeDim = 1; - gp_Pnt HexoticPnt ( node[0]->X(), node[0]->Y(), node[0]->Z() ); - for ( int i=0; iUnSetNodeOnShape( node[0] ); - nodeAssigne[ nodeID[0] ] = 0; - } - break; - } - case 4: { // "Edges" - nodeDim = 2; - aHexoticElement = theMesh->AddEdge( node[0], node[1] ); - // int iNode = 1; - // if ( nodeAssigne[ nodeID[0] ] == 0 || nodeAssigne[ nodeID[0] ] == 2 ) - // iNode = 0; - shapeID = dummy; - break; - } - case 5: { // "Ridges" - break; - } - case 6: { // "Quadrilaterals" - nodeDim = 3; - aHexoticElement = theMesh->AddFace( node[0], node[1], node[2], node[3] ); - shapeID = dummy; - break; - } - case 7: { // "Hexahedra" - nodeDim = 4; - if ( nbDomains > 1 ) { - hexoticShapeID = dummy - IdShapeRef; - if ( tabID[ hexoticShapeID ] == 0 ) { - aShape = findShape(node, aShape, tabShape, tabBox, nbShape); - shapeID = aShape.IsNull() ? holeID : theMesh->ShapeToIndex( aShape ); - tabID[ hexoticShapeID ] = shapeID; - } - else - shapeID = tabID[ hexoticShapeID ]; - if ( iElem == (nbElem - 1) ) { - int shapeAssociated = 0; - for ( int i=0; i 0 ) - shapeAssociated += 1; - } - if ( shapeAssociated != nbShape ) - printWarning(nbShape, "domains", shapeAssociated); - } - } - else { - shapeID = tabID[0]; - } - if ( shapeID != holeID ) - aHexoticElement = theMesh->AddVolume( node[0], node[3], node[2], node[1], node[4], node[7], node[6], node[5] ); - break; - } - } // switch (nField) - - if ( token != "Ridges" && ( shapeID > 0 || token == "Corners")) { - for ( int i=0; iSetNodeOnVertex( node[0], aVertex ); - else if ( token == "Edges" ) theMesh->SetNodeOnEdge( node[i], shapeID ); - else if ( token == "Quadrilaterals" ) theMesh->SetNodeOnFace( node[i], shapeID ); - else if ( token == "Hexahedra" ) theMesh->SetNodeInVolume( node[i], shapeID ); - nodeAssigne[ nodeID[i] ] = nodeDim; - } - } - if ( token != "Corners" && aHexoticElement ) - theMesh->SetMeshElementOnShape( aHexoticElement, shapeID ); - } + nbCorners = theHexaOutput->GmfStatKwd( meshID, GmfCorners ); + if ( nbCorners > 0 && nbDomains > 0 ) + { + theHexaOutput->GmfGotoKwd( meshID, GmfCorners ); + for ( int iElem = 0; iElem < nbCorners; iElem++ ) + { + if ( theAlgo->computeCanceled() ) + return false; + theHexaOutput->GmfGetLin( meshID, GmfCorners, &nodeID[0] ); + node[0] = HexoticNode[ nodeID[0] ]; + gp_Pnt HexoticPnt ( node[0]->X(), node[0]->Y(), node[0]->Z() ); + for ( int i = 0; i < nbCorners; i++ ) + { + aVertex = TopoDS::Vertex( tabCorner[i] ); + gp_Pnt aPnt = BRep_Tool::Pnt( aVertex ); + if ( aPnt.Distance( HexoticPnt ) < epsilon ) + { + theMeshDS->SetNodeOnVertex( node[0], aVertex ); + break; } - delete [] node; - delete [] nodeID; - break; - } - case 8: { // "End" - EndOfFile = 1; - MESSAGE("End of " << theFile << " file"); - break; - } - default: { - MESSAGE("Unknown Token: " << token); } } } - cout << std::endl; - // remove nodes in holes - if ( nbDomains > 1 ) + int nbEdges = theHexaOutput->GmfStatKwd( meshID, GmfEdges ); + if ( nbEdges > 0 ) { - SMESHDS_SubMesh* subMesh; - for ( int i = 1; i <= nbVertices; ++i ) - if ( HexoticNode[i]->NbInverseElements() == 0 ) + theHexaOutput->GmfGotoKwd( meshID, GmfEdges ); + for ( int iElem = 0; iElem < nbEdges; iElem++ ) + { + if ( theAlgo->computeCanceled() ) + return false; + theHexaOutput->GmfGetLin( meshID, GmfEdges, &nodeID[0], &nodeID[1], &shapeID ); + for ( int i = 0; i < 2; ++i ) { - subMesh = HexoticNode[i]->getshapeId() > 0 ? theMesh->MeshElements(HexoticNode[i]->getshapeId() ) : 0; - theMesh->RemoveFreeNode( HexoticNode[i], subMesh, /*fromGroups=*/false ); + node[i] = HexoticNode[ nodeID[i]]; + if ( node[i]->getshapeId() < 1 ) + theMeshDS->SetNodeOnEdge( node[i], shapeID ); } + aHexoticElement = theHelper->AddEdge( node[0], node[1] ); + if ( aHexoticElement->getshapeId() < 1 ) + theMeshDS->SetMeshElementOnShape( aHexoticElement, shapeID ); + } } - delete [] tabID; - delete [] tabRef; - delete [] tabDummy; - delete [] tabCorner; - delete [] tabEdge; - delete [] nodeAssigne; - delete [] HexoticNode; - return true; -} - - -//======================================================================= -//function : readResult -//purpose : Read GMF file in case of a mesh w/o geometry -//======================================================================= - -static bool readResult(std::string theFile, - HexoticPlugin_Hexotic* theAlgo, - SMESH_MesherHelper* theHelper) -{ - SMESHDS_Mesh* theMesh = theHelper->GetMeshDS(); - - // --------------------------------- - // Read generated elements and nodes - // --------------------------------- - - std::string token; - const int nbField = 9; - int nField, EndOfFile = 0, nbElem = 0, nbRef = 0; - int aHexoticNodeID = 0, shapeID; - int tabRef[nbField], *nodeAssigne; - bool tabDummy[nbField], hasDummy = false; - std::map mapField; - SMDS_MeshNode** HexoticNode; - - mapField["MeshVersionFormatted"] = 0; tabRef[0] = 0; tabDummy[0] = false; - mapField["Dimension"] = 1; tabRef[1] = 0; tabDummy[1] = false; - mapField["Vertices"] = 2; tabRef[2] = 3; tabDummy[2] = true; - mapField["Corners"] = 3; tabRef[3] = 1; tabDummy[3] = false; - mapField["Edges"] = 4; tabRef[4] = 2; tabDummy[4] = true; - mapField["Ridges"] = 5; tabRef[5] = 1; tabDummy[5] = false; - mapField["Quadrilaterals"] = 6; tabRef[6] = 4; tabDummy[6] = true; - mapField["Hexahedra"] = 7; tabRef[7] = 8; tabDummy[7] = true; - mapField["End"] = 8; tabRef[8] = 0; tabDummy[8] = false; + int nbQuad = theHexaOutput->GmfStatKwd( meshID, GmfQuadrilaterals ); + if ( nbQuad > 0 ) { - // theMesh->Clear(); -- this does not remove imported mesh - SMDS_ElemIteratorPtr eIt = theMesh->elementsIterator(); - while( eIt->more() ) - theMesh->RemoveFreeElement( eIt->next(), /*sm=*/0 ); - SMDS_NodeIteratorPtr nIt = theMesh->nodesIterator(); - while ( nIt->more() ) - theMesh->RemoveFreeNode( nIt->next(), /*sm=*/0 ); + theHexaOutput->GmfGotoKwd( meshID, GmfQuadrilaterals ); + for ( int iElem = 0; iElem < nbQuad; iElem++ ) + { + if ( theAlgo->computeCanceled() ) + return false; + theHexaOutput->GmfGetLin( meshID, GmfQuadrilaterals, + &nodeID[0], &nodeID[1], &nodeID[2], &nodeID[3], &shapeID ); + for ( int i = 0; i < 4; ++i ) + { + node[i] = HexoticNode[ nodeID[i]]; + if ( shapeID > 0 && node[i]->getshapeId() < 1 ) + theMeshDS->SetNodeOnFace( node[i], shapeID ); + } + aHexoticElement = theHelper->AddFace( node[0], node[1], node[2], node[3] ); + if ( shapeID > 0 && aHexoticElement->getshapeId() < 1 ) + theMeshDS->SetMeshElementOnShape( aHexoticElement, shapeID ); + } } - int nbVertices = getNbShape(theFile, "Vertices"); - HexoticNode = new SMDS_MeshNode*[ nbVertices + 1 ]; - nodeAssigne = new int[ nbVertices + 1 ]; - - MESSAGE("Read " << theFile << " file"); - std::ifstream fileRes(theFile.c_str()); - ASSERT(fileRes); - - while ( !EndOfFile ) + int nbHexa = theHexaOutput->GmfStatKwd( meshID, GmfHexahedra ); + if ( nbHexa > 0 ) { - int dummy; - fileRes >> token; - - if (mapField.count(token)) { - nField = mapField[token]; - nbRef = tabRef[nField]; - hasDummy = tabDummy[nField]; - } - else { - nField = -1; - nbRef = 0; - } - - nbElem = 0; - if ( nField < int(mapField.size() - 1) && nField >= 0 ) - fileRes >> nbElem; - - switch (nField) { - case 0: { // "MeshVersionFormatted" - MESSAGE(token << " " << nbElem); - break; - } - case 1: { // "Dimension" - MESSAGE("Mesh dimension " << nbElem << "D"); - break; - } - case 2: { // "Vertices" - MESSAGE("Read " << nbElem << " " << token); - int aHexoticID; - double coord[3]; - SMDS_MeshNode * aHexoticNode; - - for ( int iElem = 0; iElem < nbElem; iElem++ ) { - if(theAlgo->computeCanceled()) - { - return false; - } - aHexoticID = iElem + 1; - for ( int iCoord = 0; iCoord < 3; iCoord++ ) - fileRes >> coord[ iCoord ]; - fileRes >> dummy; - aHexoticNode = theMesh->AddNode(coord[0], coord[1], coord[2]); - HexoticNode[ aHexoticID ] = aHexoticNode; - nodeAssigne[ aHexoticID ] = 0; - } - break; - } - case 3: // "Corners" - case 4: // "Edges" - case 5: // "Ridges" - case 6: // "Quadrilaterals" - case 7: { // "Hexahedra" - MESSAGE("Read " << nbElem << " " << token); - std::vector< SMDS_MeshNode* > node( nbRef ); - std::vector< int > nodeID( nbRef ); - - for ( int iElem = 0; iElem < nbElem; iElem++ ) + theHexaOutput->GmfGotoKwd( meshID, GmfHexahedra ); + for ( int iElem = 0; iElem < nbHexa; iElem++ ) + { + if ( theAlgo->computeCanceled() ) + return false; + theHexaOutput->GmfGetLin( meshID, GmfHexahedra, + &nodeID[0], &nodeID[1], &nodeID[2], &nodeID[3], + &nodeID[4], &nodeID[5], &nodeID[6], &nodeID[7], + &shapeID ); + for ( int i = 0; i < 8; ++i ) { - if(theAlgo->computeCanceled()) - { - return false; + node[i] = HexoticNode[ nodeID[i]]; + } + if ( nbDomains > 1 ) { + hexoticShapeID = shapeID - IdShapeRef; + if ( tabID[ hexoticShapeID ] == 0 ) { + aShape = findShape(node, aShape, tabShape, tabBox, nbShape); + shapeID = aShape.IsNull() ? holeID : theMeshDS->ShapeToIndex( aShape ); + tabID[ hexoticShapeID ] = shapeID; + } + else { + shapeID = tabID[ hexoticShapeID ]; + } + if ( iElem == ( nbHexa - 1) ) { + int shapeAssociated = 0; + for ( int i=0; i 0 ) + shapeAssociated += 1; } - for ( int iRef = 0; iRef < nbRef; iRef++ ) - { - fileRes >> aHexoticNodeID; // read nbRef aHexoticNodeID - node [ iRef ] = HexoticNode[ aHexoticNodeID ]; - nodeID[ iRef ] = aHexoticNodeID; + if ( shapeAssociated != nbShape ) + printWarning(nbShape, "domains", shapeAssociated); } - if ( hasDummy ) - fileRes >> dummy; - switch (nField) + } + else { + shapeID = tabID[0]; + } + + if ( shapeID != holeID ) + { + for ( int i = 0; i < 8; ++i ) { - case 4: // "Edges" - theHelper->AddEdge( node[0], node[1] ); break; - case 6: // "Quadrilaterals" - theMesh->AddFace( node[0], node[1], node[2], node[3] ); break; - case 7: // "Hexahedra" - theHelper->AddVolume( node[0], node[3], node[2], node[1], - node[4], node[7], node[6], node[5] ); break; - default: continue; + if ( node[i]->getshapeId() < 1 ) + theMeshDS->SetNodeInVolume( node[i], shapeID ); } - if ( nField == 6 ) - for ( int iRef = 0; iRef < nbRef; iRef++ ) - nodeAssigne[ nodeID[ iRef ]] = 1; + aHexoticElement = theHelper->AddVolume( node[0], node[3], node[2], node[1], + node[4], node[7], node[6], node[5]); + if ( aHexoticElement->getshapeId() < 1 ) + theMeshDS->SetMeshElementOnShape( aHexoticElement, shapeID ); } - break; - } - case 8: { // "End" - EndOfFile = 1; - MESSAGE("End of " << theFile << " file"); - break; - } - default: { - MESSAGE("Unknown Token: " << token); - } } } cout << std::endl; - shapeID = theHelper->GetSubShapeID(); - for ( int i = 0; i < nbVertices; ++i ) - if ( !nodeAssigne[ i+1 ]) - theMesh->SetNodeInVolume( HexoticNode[ i+1 ], shapeID ); - + // remove nodes in holes + if ( nbDomains > 1 ) + { + SMESHDS_SubMesh* subMesh = 0; + for ( int i = 1; i <= nbNodes; ++i ) + if ( HexoticNode[i]->NbInverseElements() == 0 ) + { + theMeshDS->RemoveFreeNode( HexoticNode[i], subMesh, /*fromGroups=*/false ); + } + } + delete [] tabID; + delete [] tabCorner; delete [] HexoticNode; - delete [] nodeAssigne; return true; } @@ -831,42 +691,6 @@ void HexoticPlugin_Hexotic::SetParameters(const HexoticPlugin_Hypothesis* hyp) { } } -//======================================================================= -//function : getTmpDir -//purpose : -//======================================================================= - -// static TCollection_AsciiString getTmpDir() -// { -// TCollection_AsciiString aTmpDir; - -// char *Tmp_dir = getenv("SALOME_TMP_DIR"); -// #ifdef WIN32 -// if(Tmp_dir == NULL) { -// Tmp_dir = getenv("TEMP"); -// if( Tmp_dir== NULL ) -// Tmp_dir = getenv("TMP"); -// } -// #endif - -// if(Tmp_dir != NULL) { -// aTmpDir = Tmp_dir; -// #ifdef WIN32 -// if(aTmpDir.Value(aTmpDir.Length()) != '\\') aTmpDir+='\\'; -// #else -// if(aTmpDir.Value(aTmpDir.Length()) != '/') aTmpDir+='/'; -// #endif -// } -// else { -// #ifdef WIN32 -// aTmpDir = TCollection_AsciiString("C:\\"); -// #else -// aTmpDir = TCollection_AsciiString("/tmp/"); -// #endif -// } -// return aTmpDir; -// } - //======================================================================= //function : getSuffix //purpose : Returns a suffix that will be unique for the current process @@ -903,7 +727,8 @@ static TCollection_AsciiString getSuffix() std::string HexoticPlugin_Hexotic::getHexoticCommand(const TCollection_AsciiString& Hexotic_In, const TCollection_AsciiString& Hexotic_Out, - const TCollection_AsciiString& Hexotic_SizeMap_Prefix) const + const TCollection_AsciiString& Hexotic_SizeMap_Prefix, + const bool forExecutable) const { cout << std::endl; cout << "MG-Hexa execution..." << std::endl; @@ -946,7 +771,7 @@ std::string HexoticPlugin_Hexotic::getHexoticCommand(const TCollection_AsciiStri cout << std::endl; } - TCollection_AsciiString run_Hexotic( "mg-hexa.exe" ); + TCollection_AsciiString run_Hexotic("mg-hexa.exe"); TCollection_AsciiString minl = " --min_level ", maxl = " --max_level ", angle = " --ridge_angle "; TCollection_AsciiString mins = " --min_size ", maxs = " --max_size "; @@ -1032,7 +857,7 @@ std::string HexoticPlugin_Hexotic::getHexoticCommand(const TCollection_AsciiStri if (_hexoticSharpAngleThreshold > 0) run_Hexotic += angle + sharpAngle; - if (_sizeMaps.begin() != _sizeMaps.end()) + if (_sizeMaps.begin() != _sizeMaps.end() && forExecutable ) run_Hexotic += sizeMap + Hexotic_SizeMap_Prefix; if (_nbLayers > 0 && @@ -1048,7 +873,8 @@ std::string HexoticPlugin_Hexotic::getHexoticCommand(const TCollection_AsciiStri if (!_imprintedFaces.empty()) run_Hexotic += comImptintedFaces + imprintedFaces; } - run_Hexotic += in + Hexotic_In + out + Hexotic_Out; + if ( forExecutable ) + run_Hexotic += in + Hexotic_In + out + Hexotic_Out; run_Hexotic += subdom + mode; #ifndef WIN32 run_Hexotic += proc + nbproc; @@ -1067,6 +893,8 @@ std::string HexoticPlugin_Hexotic::getHexoticCommand(const TCollection_AsciiStri TopoDS_Shape HexoticPlugin_Hexotic::entryToShape(std::string entry) { MESSAGE("HexoticPlugin_Hexotic::entryToShape "<_is_nil() ) + throw SALOME_Exception("MG-Hexa plugin can't work w/o publishing in the study"); GEOM::GEOM_Object_var aGeomObj; TopoDS_Shape S = TopoDS_Shape(); SALOMEDS::SObject_var aSObj = myStudy->FindObjectID( entry.c_str() ); @@ -1085,13 +913,10 @@ TopoDS_Shape HexoticPlugin_Hexotic::entryToShape(std::string entry) * \brief Produces a .mesh file with the size maps informations to give to Hexotic */ //================================================================================ -std::vector HexoticPlugin_Hexotic::writeSizeMapFile( std::string sizeMapPrefix ) +std::vector HexoticPlugin_Hexotic::writeSizeMapFile( MG_Hexotic_API* mgOutput, + std::string sizeMapPrefix ) { - HexoticPlugin_Hypothesis::THexoticSizeMaps::iterator it ; - - // The GMF driver will be used to write the size map file - DriverGMF_Write aWriter; - aWriter.SetSizeMapPrefix( sizeMapPrefix ); + HexoticPlugin_Hypothesis::THexoticSizeMaps::iterator it; std::vector points; // Iterate on the size maps @@ -1106,9 +931,45 @@ std::vector HexoticPlugin_Hexotic::writeSizeMapFile( std::string si // Step 2 : Create the points createControlPoints( aShape, aLocalSize, points ); } + // Write the .mesh size map file - aWriter.PerformSizeMap(points); - return aWriter.GetSizeMapFiles(); + + std::string myVerticesFile = sizeMapPrefix + ".mesh"; + std::string mySolFile = sizeMapPrefix + ".sol"; + + // Open files + int verticesFileID = + mgOutput->GmfOpenMesh( myVerticesFile.c_str(), GmfWrite, GMFVERSION, GMFDIMENSION ); + int solFileID = + mgOutput->GmfOpenMesh( mySolFile.c_str(), GmfWrite, GMFVERSION, GMFDIMENSION ); + + int pointsNumber = points.size(); + + // Vertices Keyword + mgOutput->GmfSetKwd( verticesFileID, GmfVertices, pointsNumber ); + // SolAtVertices Keyword + int TypTab[] = {GmfSca}; + mgOutput->GmfSetKwd(solFileID, GmfSolAtVertices, pointsNumber, 1, TypTab); + + // Read the control points information from the vector and write it into the files + double ValTab[1]; + std::vector::const_iterator points_it; + for (points_it = points.begin(); points_it != points.end(); points_it++ ) + { + mgOutput->GmfSetLin( verticesFileID, GmfVertices, points_it->X(), points_it->Y(), points_it->Z(), 0 ); + ValTab[0] = points_it->Size(); + mgOutput->GmfSetLin( solFileID, GmfSolAtVertices, ValTab); + } + + // Close Files + mgOutput->GmfCloseMesh( verticesFileID ); + mgOutput->GmfCloseMesh( solFileID ); + + std::vector fileNames(2); + fileNames[0] = myVerticesFile; + fileNames[1] = mySolFile; + + return fileNames; } //================================================================================ @@ -1459,38 +1320,14 @@ gp_Pnt HexoticPlugin_Hexotic::tangencyPoint(const gp_Pnt& p1, bool HexoticPlugin_Hexotic::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) { - _compute_canceled = false; + _computeCanceled = false; bool Ok = true; SMESHDS_Mesh* meshDS = aMesh.GetMeshDS(); TCollection_AsciiString hexahedraMessage; - if (_iShape == 0 && _nbShape == 0) { - _nbShape = countShape( meshDS, TopAbs_SOLID ); // we count the number of shapes - } - - // to prevent from displaying error message after computing, - // SetIsAlwaysComputed( true ) to empty sub-meshes - std::vector< SMESH_subMesh* > subMeshesAlwaysComp; - for ( int i = 0; i < _nbShape; ++i ) - if ( SMESH_subMesh* sm = aMesh.GetSubMeshContaining( aShape )) - { - SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/true, - /*complexShapeFirst=*/false); - while ( smIt->more() ) - { - sm = smIt->next(); - if ( !sm->IsMeshComputed() ) - { - sm->SetIsAlwaysComputed( true ); - subMeshesAlwaysComp.push_back( sm ); - } - } - } - - _iShape++; - - if (_iShape == _nbShape ) { + _nbShape = countShape( &aMesh, TopAbs_SOLID ); // we count the number of shapes + { // create bounding box for each shape of the compound int iShape = 0; @@ -1517,7 +1354,6 @@ bool HexoticPlugin_Hexotic::Compute(SMESH_Mesh& aMesh, SetParameters(_hypothesis); -// TCollection_AsciiString aTmpDir = getTmpDir(); TCollection_AsciiString aTmpDir = _hexoticWorkingDirectory.c_str(); TCollection_AsciiString aQuote(""); #ifdef WIN32 @@ -1527,11 +1363,14 @@ bool HexoticPlugin_Hexotic::Compute(SMESH_Mesh& aMesh, if ( aTmpDir.Value(aTmpDir.Length()) != '/' ) aTmpDir += '/'; #endif TCollection_AsciiString Hexotic_In(""), Hexotic_Out, Hexotic_SizeMap_Prefix; - TCollection_AsciiString modeFile_In( "chmod 666 " ), modeFile_Out( "chmod 666 " ); TCollection_AsciiString aLogFileName = aTmpDir + "Hexotic"+getSuffix()+".log"; // log + TCollection_AsciiString modeFile_In( "chmod 666 " ), modeFile_Out( "chmod 666 " ); + TCollection_AsciiString aLogFileName = aTmpDir + "Hexotic"+getSuffix()+".log"; // log std::map aSmdsToHexoticIdMap; std::map aHexoticIdToNodeMap; + MG_Hexotic_API mgHexa( _computeCanceled, _progress ); + Hexotic_Out = aTmpDir + "Hexotic"+getSuffix()+"_Out.mesh"; #ifdef WITH_BLSURFPLUGIN bool defaultInputFile = true; @@ -1539,16 +1378,22 @@ bool HexoticPlugin_Hexotic::Compute(SMESH_Mesh& aMesh, Hexotic_In = _blsurfHypo->GetGMFFile().c_str(); if ( !Hexotic_In.IsEmpty() && SMESH_File( _blsurfHypo->GetGMFFile() ).exists() ) + { + mgHexa.SetUseExecutable(); defaultInputFile = false; + } } if (defaultInputFile) { #endif Hexotic_In = aTmpDir + "Hexotic"+getSuffix()+"_In.mesh"; removeHexoticFiles(Hexotic_In, Hexotic_Out); splitQuads(aMesh); // quadrangles are no longer acceptable as input - cout << std::endl; - cout << "Creating MG-Hexa input mesh file : " << Hexotic_In << std::endl; - aMesh.ExportGMF(Hexotic_In.ToCString(), meshDS, true); + if ( mgHexa.IsExecutable() ) + { + cout << std::endl; + cout << "Creating MG-Hexa input mesh file : " << Hexotic_In << std::endl; + } + writeInput( &mgHexa, Hexotic_In.ToCString(), meshDS ); #ifdef WITH_BLSURFPLUGIN } else { @@ -1557,99 +1402,84 @@ bool HexoticPlugin_Hexotic::Compute(SMESH_Mesh& aMesh, #endif Hexotic_SizeMap_Prefix = aTmpDir + "Hexotic_SizeMap" + getSuffix(); - std::vector sizeMapFiles = writeSizeMapFile( Hexotic_SizeMap_Prefix.ToCString() ); + std::vector sizeMapFiles = writeSizeMapFile( &mgHexa, Hexotic_SizeMap_Prefix.ToCString() ); - std::string run_Hexotic = getHexoticCommand(aQuote + Hexotic_In + aQuote, aQuote + Hexotic_Out + aQuote, Hexotic_SizeMap_Prefix); + std::string run_Hexotic = getHexoticCommand(aQuote + Hexotic_In + aQuote, aQuote + Hexotic_Out + aQuote, Hexotic_SizeMap_Prefix, mgHexa.IsExecutable() ); run_Hexotic += std::string(" 1> ") + aQuote.ToCString() + aLogFileName.ToCString() + aQuote.ToCString(); // dump into file - + mgHexa.SetLogFile( aLogFileName.ToCString() ); cout << "Creating MG-Hexa log file : " << aLogFileName << std::endl; + cout << std::endl; cout << "MG-Hexa command : " << run_Hexotic << std::endl; + if ( mgHexa.IsExecutable() ) + { #ifndef WIN32 - modeFile_In += Hexotic_In; - system( modeFile_In.ToCString() ); + modeFile_In += Hexotic_In; + system( modeFile_In.ToCString() ); #endif + } aSmdsToHexoticIdMap.clear(); aHexoticIdToNodeMap.clear(); MESSAGE("HexoticPlugin_Hexotic::Compute"); - int status = system( run_Hexotic.data() ); + + std::string errStr; + Ok = mgHexa.Compute( run_Hexotic, errStr ); // run + // -------------- // read a result // -------------- - std::ifstream fileRes( Hexotic_Out.ToCString() ); -#ifndef WIN32 - modeFile_Out += Hexotic_Out; - system( modeFile_Out.ToCString() ); + if ( mgHexa.IsExecutable() ) + { +#ifndef WIN32 + modeFile_Out += Hexotic_Out; + system( modeFile_Out.ToCString() ); #endif - if ( ! fileRes.fail() ) { - Ok = readResult( Hexotic_Out.ToCString(), - this, - meshDS, _nbShape, tabShape, tabBox ); - if(Ok) { -/********************* -// TODO: Detect and remove elements in holes in case of sd mode = 4 - // Remove previous nodes and elements - SMDS_ElemIteratorPtr itElement = meshDS->elementsIterator(); - SMDS_NodeIteratorPtr itNode = meshDS->nodesIterator(); - - while ( itElement->more() ) - meshDS->RemoveElement( itElement->next() ); - while ( itNode->more() ) - meshDS->RemoveNode( itNode->next() ); - - SMESH_ComputeErrorPtr myError = aMesh.GMFToMesh(Hexotic_Out.ToCString()); - if (myError) -*/ - hexahedraMessage = "success"; - #ifndef _DEBUG_ - removeFile(Hexotic_Out); - removeFile(Hexotic_In); - //removeFile(aLogFileName); - for( int i=0; i 0 && WEXITSTATUS(status) == 127 ) - error("mg-hexa.exe: command not found"); -#else - int err = errno; - if ( status == 0 && err == ENOENT ) { - error("mg-hexa.exe: command not found"); - } -#endif + if ( !errStr.empty() ) + error(errStr); } cout << "Hexahedra meshing " << hexahedraMessage << std::endl; cout << std::endl; - // restore "always computed" flag of sub-meshes (0022127) - for ( size_t iSM = 0; iSM < subMeshesAlwaysComp.size(); ++iSM ) - subMeshesAlwaysComp[ iSM ]->SetIsAlwaysComputed( false ); - delete [] tabShape; for (int i=0; i<_nbShape; i++) delete [] tabBox[i]; @@ -1657,8 +1487,10 @@ bool HexoticPlugin_Hexotic::Compute(SMESH_Mesh& aMesh, _nbShape = 0; _iShape = 0; } - if(_compute_canceled) + + if(_computeCanceled) return error(SMESH_Comment("interruption initiated by user")); + return Ok; } @@ -1675,7 +1507,7 @@ bool HexoticPlugin_Hexotic::Compute(SMESH_Mesh& aMesh, bool HexoticPlugin_Hexotic::Compute(SMESH_Mesh & aMesh, SMESH_MesherHelper* aHelper) { - _compute_canceled = false; + _computeCanceled = false; /* SMESH_ComputeErrorPtr myError = SMESH_ComputeError::New(); */ @@ -1699,11 +1531,14 @@ bool HexoticPlugin_Hexotic::Compute(SMESH_Mesh & aMesh, SMESH_MesherHelper* aHel Hexotic_Out = aTmpDir + "Hexotic"+getSuffix()+"_Out.mesh"; Hexotic_SizeMap_Prefix = aTmpDir + "Hexotic_SizeMap"; - - std::vector sizeMapFiles = writeSizeMapFile( Hexotic_SizeMap_Prefix.ToCString() ); + MG_Hexotic_API mgHexa( _computeCanceled, _progress ); + + std::vector sizeMapFiles = writeSizeMapFile( &mgHexa, Hexotic_SizeMap_Prefix.ToCString() ); - std::string run_Hexotic = getHexoticCommand(aQuote + Hexotic_In + aQuote, aQuote + Hexotic_Out + aQuote, Hexotic_SizeMap_Prefix); + std::string run_Hexotic = getHexoticCommand(aQuote + Hexotic_In + aQuote, aQuote + Hexotic_Out + aQuote, Hexotic_SizeMap_Prefix, mgHexa.IsExecutable()); run_Hexotic += std::string(" 1> ") + aQuote.ToCString() + aLogFileName.ToCString() + aQuote.ToCString(); // dump into file + mgHexa.SetLogFile( aLogFileName.ToCString() ); + cout << "Creating MG-Hexa log file : " << aLogFileName << std::endl; removeHexoticFiles(Hexotic_In, Hexotic_Out); @@ -1711,12 +1546,14 @@ bool HexoticPlugin_Hexotic::Compute(SMESH_Mesh & aMesh, SMESH_MesherHelper* aHel cout << std::endl; cout << "Creating MG-Hexa input mesh file : " << Hexotic_In << std::endl; - cout << "Creating MG-Hexa log file : " << aLogFileName << std::endl; - aMesh.ExportGMF(Hexotic_In.ToCString(), aHelper->GetMeshDS()); + writeInput( &mgHexa, Hexotic_In.ToCString(), aHelper->GetMeshDS() ); + if ( mgHexa.IsExecutable() ) + { #ifndef WIN32 - modeFile_In += Hexotic_In; - system( modeFile_In.ToCString() ); + modeFile_In += Hexotic_In; + system( modeFile_In.ToCString() ); #endif + } aSmdsToHexoticIdMap.clear(); aHexoticIdToNodeMap.clear(); @@ -1724,69 +1561,49 @@ bool HexoticPlugin_Hexotic::Compute(SMESH_Mesh & aMesh, SMESH_MesherHelper* aHel cout << std::endl; cout << "MG-Hexa command : " << run_Hexotic << std::endl; - system( run_Hexotic.data() ); + + std::string errStr; + Ok = mgHexa.Compute( run_Hexotic, errStr ); // run // -------------- // read a result // -------------- - std::ifstream fileRes( Hexotic_Out.ToCString() ); - modeFile_Out += Hexotic_Out; - system( modeFile_Out.ToCString() ); - if ( ! fileRes.fail() ) { - Ok = readResult( Hexotic_Out.ToCString(), - this, - aHelper ); - if(Ok) -/* - // Remove previous nodes and elements - SMDS_ElemIteratorPtr itElement = aHelper->GetMeshDS()->elementsIterator(); - SMDS_NodeIteratorPtr itNode = aHelper->GetMeshDS()->nodesIterator(); - - while ( itElement->more() ) - aHelper->GetMeshDS()->RemoveElement( itElement->next() ); - while ( itNode->more() ) - aHelper->GetMeshDS()->RemoveNode( itNode->next() ); - - // Import GMF mesh - myError = aMesh.GMFToMesh(Hexotic_Out.ToCString()); - - itElement = aHelper->GetMeshDS()->elementsIterator(); - itNode = aHelper->GetMeshDS()->nodesIterator(); + if ( mgHexa.IsExecutable() ) + { + modeFile_Out += Hexotic_Out; + system( modeFile_Out.ToCString() ); + } - // Assign nodes and elements to the pseudo shape - while ( itNode->more() ) - aHelper->GetMeshDS()->SetNodeInVolume(itNode->next(), 1); - while ( itElement->more() ) - aHelper->GetMeshDS()->SetMeshElementOnShape(itElement->next(), 1); + Ok = readResult( &mgHexa, Hexotic_Out.ToCString(), + this, + aHelper ); - if(myError->IsOK()) -*/ - hexahedraMessage = "success"; - else - hexahedraMessage = "failed"; + std::string log = mgHexa.GetLog(); + if ( Ok ) + { + hexahedraMessage = "success"; } - else { -/* - myError->myName = COMPERR_EXCEPTION; -*/ + else + { hexahedraMessage = "failed"; - cout << "Problem with MG-Hexa output file " << Hexotic_Out << std::endl; + if ( mgHexa.IsExecutable() ) + cout << "Problem with MG-Hexa output file " << Hexotic_Out << std::endl; // analyse log file - SMESH_File logFile( aLogFileName.ToCString() ); - if ( !logFile.eof() ) + if ( !log.empty() ) { char msgLic[] = " Dlim "; - const char* fileBeg = logFile.getPos(), *fileEnd = fileBeg + logFile.size(); + const char* fileBeg = &log[0], *fileEnd = fileBeg + log.size(); if ( std::search( fileBeg, fileEnd, msgLic, msgLic+strlen(msgLic)) != fileEnd ) - return error("Licence problems."); + error("Licence problems."); } - return error(SMESH_Comment("Problem with MG-Hexa output file ")<IsOK(); -*/ } //============================================================================= @@ -1807,9 +1621,9 @@ bool HexoticPlugin_Hexotic::Compute(SMESH_Mesh & aMesh, SMESH_MesherHelper* aHel */ //============================================================================= -bool HexoticPlugin_Hexotic::Evaluate(SMESH_Mesh& aMesh, +bool HexoticPlugin_Hexotic::Evaluate(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape, - MapShapeNbElems& aResMap) + MapShapeNbElems& aResMap) { std::vector aResVec(SMDSEntity_Last); for(int i=SMDSEntity_Node; i -class SMESH_Mesh; class HexoticPlugin_Hypothesis; class TCollection_AsciiString; class gp_Pnt; +class MG_Hexotic_API; class HEXOTICPLUGIN_EXPORT HexoticPlugin_Hexotic: public SMESH_3D_Algo { @@ -71,8 +71,8 @@ public: virtual bool Compute(SMESH_Mesh & aMesh, SMESH_MesherHelper* aHelper); - virtual void CancelCompute(); - bool computeCanceled() { return _compute_canceled;}; + virtual void CancelCompute(); + bool computeCanceled() { return _computeCanceled; } virtual bool Evaluate(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape, MapShapeNbElems& aResMap); @@ -84,12 +84,14 @@ private: std::string getHexoticCommand(const TCollection_AsciiString& Hexotic_In, const TCollection_AsciiString& Hexotic_Out, - const TCollection_AsciiString& Hexotic_Sol) const; + const TCollection_AsciiString& Hexotic_Sol, + const bool forExecutable) const; GEOM::GEOM_Object_var entryToGeomObj(std::string entry); TopoDS_Shape entryToShape(std::string entry); - std::vector writeSizeMapFile(std::string fileName); + std::vector writeSizeMapFile(MG_Hexotic_API* mgOutput, + std::string fileName); // Functions to get sample point from shapes void createControlPoints( const TopoDS_Shape& theShape, @@ -150,8 +152,6 @@ private: #endif - volatile bool _compute_canceled; - SALOMEDS::Study_var myStudy; SMESH_Gen_i* smeshGen_i; diff --git a/src/HexoticPlugin/MG_Hexotic_API.cxx b/src/HexoticPlugin/MG_Hexotic_API.cxx new file mode 100644 index 0000000..1946f4f --- /dev/null +++ b/src/HexoticPlugin/MG_Hexotic_API.cxx @@ -0,0 +1,1242 @@ +// Copyright (C) 2004-2016 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#include "MG_Hexotic_API.hxx" + +#include +#include +#include + +#include +#include +#include + +#ifdef USE_MG_LIBS + +extern "C"{ +#include +#include +} + +struct MG_Hexotic_API::LibData +{ + // MG objects + context_t * _context; + hexa_session_t * _session; + mesh_t * _tria_mesh; + sizemap_t * _sizemap; + mesh_t * _hexa_mesh; + + // data to pass to MG + std::vector _xyz; + std::vector _nodeSize; // required nodes + std::vector _edgeNodesTags; + int _nbRequiredEdges; + std::vector _triaNodesTags; + int _nbRequiredTria; + + std::vector _corners; + + int _count; + volatile bool& _cancelled_flag; + std::string _errorStr; + double& _progress; + double _msgCost; + + LibData( volatile bool & cancelled_flag, double& progress ) + : _context(0), _session(0), _tria_mesh(0), _sizemap(0), _hexa_mesh(0), + _nbRequiredEdges(0), _nbRequiredTria(0), + _cancelled_flag( cancelled_flag ), _progress( progress ), _msgCost( 0.00015 ) + { + } + // methods setting callbacks implemented after callback definitions + void Init(); + bool Compute(); + + ~LibData() + { + if ( _hexa_mesh ) + hexa_regain_mesh( _session, _hexa_mesh ); + if ( _session ) + hexa_session_delete( _session ); + if ( _tria_mesh ) + mesh_delete( _tria_mesh ); + if ( _sizemap ) + sizemap_delete( _sizemap ); + if ( _context ) + context_delete( _context ); + + _hexa_mesh = 0; + _session = 0; + _tria_mesh = 0; + _sizemap = 0; + _context = 0; + } + + void AddError( const char *txt ) + { + if ( txt ) + { + _errorStr += txt; + } + } + + const std::string& GetErrors() + { + return _errorStr; + } + + void MG_Error(const char* txt="") + { + SMESH_Comment msg("\nMeshGems error. "); + msg << txt << "\n"; + AddError( msg.c_str() ); + } + + bool SetParam( const std::string& param, const std::string& value ) + { + status_t ret = hexa_set_param( _session, param.c_str(), value.c_str() ); +#ifdef _DEBUG_ + //std::cout << param << " = " << value << std::endl; +#endif + return ( ret == STATUS_OK ); + } + + bool Cancelled() + { + return _cancelled_flag; + } + + int ReadNbSubDomains() + { + integer nb = 0; + status_t ret = mesh_get_subdomain_count( _hexa_mesh, & nb ); + + if ( ret != STATUS_OK ) MG_Error("mesh_get_subdomain_count problem"); + return nb; + } + + int ReadNbNodes() + { + _corners.clear(); + + integer nb = 0; + status_t ret = mesh_get_vertex_count( _hexa_mesh, & nb ); + + if ( ret != STATUS_OK ) MG_Error("mesh_get_vertex_count problem"); + return nb; + } + + int ReadNbEdges() + { + integer nb = 0; + status_t ret = mesh_get_edge_count( _hexa_mesh, & nb ); + + if ( ret != STATUS_OK ) MG_Error("mesh_get_edge_count problem"); + return nb; + } + + int ReadNbTria() + { + integer nb = 0; + status_t ret = mesh_get_triangle_count( _hexa_mesh, & nb ); + + if ( ret != STATUS_OK ) MG_Error("mesh_get_triangle_count problem"); + return nb; + } + + int ReadNbQuads() + { + integer nb = 0; + status_t ret = mesh_get_quadrangle_count( _hexa_mesh, & nb ); + + if ( ret != STATUS_OK ) MG_Error("mesh_get_quadrangle_count problem"); + return nb; + } + + int ReadNbTetra() + { + integer nb = 0; + status_t ret = mesh_get_tetrahedron_count( _hexa_mesh, & nb ); + + if ( ret != STATUS_OK ) MG_Error("mesh_get_tetrahedron_count problem"); + return nb; + } + + int ReadNbHexa() + { + integer nb = 0; + status_t ret = mesh_get_hexahedron_count( _hexa_mesh, & nb ); + + if ( ret != STATUS_OK ) MG_Error("mesh_get_hexahedron_count problem"); + return nb; + } + + int ReadNbCorners() + { + return _corners.size(); + } + + void ResetCounter() + { + _count = 1; + } + + void ReadSubDomain( int* nbNodes, int* faceInd, int* ori, int* domain ) + { + integer tag, seed_type, seed_idx, seed_orientation; + status_t ret = mesh_get_subdomain_description( _hexa_mesh, _count, + &tag, &seed_type, &seed_idx, &seed_orientation); + + if ( ret != STATUS_OK ) MG_Error( "unable to get a sub-domain description"); + + *nbNodes = 3; + *faceInd = seed_idx; + *domain = tag; + *ori = seed_orientation; + + ++_count; + } + void ReadNodeXYZ( double* x, double* y, double *z, int* /*domain*/ ) + { + real coo[3]; + status_t ret = mesh_get_vertex_coordinates( _hexa_mesh, _count, coo ); + if ( ret != STATUS_OK ) MG_Error( "unable to get resulting vertices" ); + + *x = coo[0]; + *y = coo[1]; + *z = coo[2]; + + integer isCorner = 0; + ret = mesh_get_vertex_corner_property( _hexa_mesh, _count, &isCorner); + if (ret != STATUS_OK) MG_Error( "unable to get resulting vertex property" ); + if ( isCorner ) + _corners.push_back( _count ); + + ++_count; + } + + void ReadEdgeNodes( int* node1, int* node2, int* domain ) + { + integer vtx[2], tag; + status_t ret = mesh_get_edge_vertices( _hexa_mesh, _count, vtx); + if (ret != STATUS_OK) MG_Error( "unable to get resulting edge" ); + + *node1 = vtx[0]; + *node2 = vtx[1]; + + ret = mesh_get_edge_tag( _hexa_mesh, _count, &tag ); + if (ret != STATUS_OK) MG_Error( "unable to get resulting edge tag" ); + + *domain = tag; + + ++_count; + } + + void ReadTriaNodes( int* node1, int* node2, int* node3, int* domain ) + { + integer vtx[3], tag; + status_t ret = mesh_get_triangle_vertices( _hexa_mesh, _count, vtx); + if (ret != STATUS_OK) MG_Error( "unable to get resulting triangle" ); + + *node1 = vtx[0]; + *node2 = vtx[1]; + *node3 = vtx[2]; + + ret = mesh_get_triangle_tag( _hexa_mesh, _count, &tag ); + if (ret != STATUS_OK) MG_Error( "unable to get resulting triangle tag" ); + + *domain = tag; + + ++_count; + } + + void ReadQuadNodes( int* node1, int* node2, int* node3, int* node4, int* domain ) + { + integer vtx[4], tag; + status_t ret = mesh_get_quadrangle_vertices( _hexa_mesh, _count, vtx); + if (ret != STATUS_OK) MG_Error( "unable to get resulting quadrangle" ); + + *node1 = vtx[0]; + *node2 = vtx[1]; + *node3 = vtx[2]; + *node4 = vtx[3]; + + ret = mesh_get_quadrangle_tag( _hexa_mesh, _count, &tag ); + if (ret != STATUS_OK) MG_Error( "unable to get resulting quadrangle tag" ); + + *domain = tag; + + ++_count; + } + + void ReadTetraNodes( int* node1, int* node2, int* node3, int* node4, int* domain ) + { + integer vtx[4], tag; + status_t ret = mesh_get_tetrahedron_vertices( _hexa_mesh, _count, vtx); + if (ret != STATUS_OK) MG_Error( "unable to get resulting tetrahedron" ); + + *node1 = vtx[0]; + *node2 = vtx[1]; + *node3 = vtx[2]; + *node4 = vtx[3]; + + ret = mesh_get_tetrahedron_tag( _hexa_mesh, _count, &tag ); + if (ret != STATUS_OK) MG_Error( "unable to get resulting tetrahedron tag" ); + + *domain = tag; + + ++_count; + } + + void ReadHexaNodes( int* node1, int* node2, int* node3, int* node4, + int* node5, int* node6, int* node7, int* node8, int* domain ) + { + integer vtx[8], tag; + status_t ret = mesh_get_hexahedron_vertices( _hexa_mesh, _count, vtx); + if (ret != STATUS_OK) MG_Error( "unable to get resulting hexahedron" ); + + *node1 = vtx[0]; + *node2 = vtx[1]; + *node3 = vtx[2]; + *node4 = vtx[3]; + *node5 = vtx[4]; + *node6 = vtx[5]; + *node7 = vtx[6]; + *node8 = vtx[7]; + + ret = mesh_get_hexahedron_tag( _hexa_mesh, _count, &tag ); + if (ret != STATUS_OK) MG_Error( "unable to get resulting hexahedron tag" ); + + *domain = tag; + + ++_count; + } + + void ReadCorner( int* node ) + { + if ( _count <= ReadNbCorners() ) + *node = _corners[ _count - 1 ]; + else + *node = 0; + + ++_count; + } + + void SetNbVertices( int nb ) + { + _xyz.reserve( _xyz.capacity() + nb ); + } + + void SetNbEdges( int nb ) + { + _edgeNodesTags.reserve( nb * 3 ); + } + + void SetNbTria( int nb ) + { + _triaNodesTags.reserve( nb * 4 ); + } + + void SetNbReqVertices( int nb ) + { + _nodeSize.reserve( nb ); + } + + void SetNbReqEdges( int nb ) + { + _nbRequiredEdges = nb; + } + + void SetNbReqTria( int nb ) + { + _nbRequiredTria = nb; + } + + void AddNode( double x, double y, double z, int domain ) + { + _xyz.push_back( x ); + _xyz.push_back( y ); + _xyz.push_back( z ); + } + + void AddSizeAtNode( double size ) + { + _nodeSize.push_back( size ); + } + + void AddEdgeNodes( int node1, int node2, int domain ) + { + _edgeNodesTags.push_back( node1 ); + _edgeNodesTags.push_back( node2 ); + _edgeNodesTags.push_back( domain ); + } + + void AddTriaNodes( int node1, int node2, int node3, int domain ) + { + _triaNodesTags.push_back( node1 ); + _triaNodesTags.push_back( node2 ); + _triaNodesTags.push_back( node3 ); + _triaNodesTags.push_back( domain ); + } + + int NbNodes() + { + return _xyz.size() / 3; + } + + double* NodeCoord( int iNode ) + { + return & _xyz[ iNode * 3 ]; + } + + int NbEdges() + { + return _edgeNodesTags.size() / 3; + } + + int* GetEdgeNodes( int iEdge ) + { + return & _edgeNodesTags[ iEdge * 3 ]; + } + + int GetEdgeTag( int iEdge ) + { + return _edgeNodesTags[ iEdge * 3 + 2 ]; + } + + int NbTriangles() + { + return _triaNodesTags.size() / 4; + } + + int * GetTriaNodes( int iTria ) + { + return & _triaNodesTags[ iTria * 4 ]; + } + + int GetTriaTag( int iTria ) + { + return _triaNodesTags[ iTria * 4 + 3 ]; + } + + int IsVertexRequired( int iNode ) + { + return ! ( iNode < int( _xyz.size() - _nodeSize.size() )); + } + + double GetSizeAtVertex( int iNode ) + { + return IsVertexRequired( iNode ) ? _nodeSize[ iNode - _xyz.size() + _nodeSize.size() ] : 0.; + } +}; + +namespace // functions called by MG library to exchange with the application +{ + status_t get_vertex_count(integer * nbvtx, void *user_data) + { + MG_Hexotic_API::LibData* data = (MG_Hexotic_API::LibData *) user_data; + *nbvtx = data->NbNodes(); + + return STATUS_OK; + } + + status_t get_vertex_coordinates(integer ivtx, real * xyz, void *user_data) + { + MG_Hexotic_API::LibData* data = (MG_Hexotic_API::LibData *) user_data; + double* coord = data->NodeCoord( ivtx-1 ); + for (int j = 0; j < 3; j++) + xyz[j] = coord[j]; + + return STATUS_OK; + } + status_t get_edge_count(integer * nbedge, void *user_data) + { + MG_Hexotic_API::LibData* data = (MG_Hexotic_API::LibData *) user_data; + *nbedge = data->NbEdges(); + + return STATUS_OK; + } + + status_t get_edge_vertices(integer iedge, integer * vedge, void *user_data) + { + MG_Hexotic_API::LibData* data = (MG_Hexotic_API::LibData *) user_data; + int* nodes = data->GetEdgeNodes( iedge-1 ); + vedge[0] = nodes[0]; + vedge[1] = nodes[1]; + + return STATUS_OK; + } + + status_t get_edge_tag(integer iedge, integer * tag, void *user_data) + { + MG_Hexotic_API::LibData* data = (MG_Hexotic_API::LibData *) user_data; + * tag = data->GetEdgeTag( iedge-1 ); + + return STATUS_OK; + } + + status_t get_triangle_count(integer * nbtri, void *user_data) + { + MG_Hexotic_API::LibData* data = (MG_Hexotic_API::LibData *) user_data; + *nbtri = data->NbTriangles(); + + return STATUS_OK; + } + + status_t get_triangle_vertices(integer itri, integer * vtri, void *user_data) + { + MG_Hexotic_API::LibData* data = (MG_Hexotic_API::LibData *) user_data; + int* nodes = data->GetTriaNodes( itri-1 ); + vtri[0] = nodes[0]; + vtri[1] = nodes[1]; + vtri[2] = nodes[2]; + + return STATUS_OK; + } + + status_t get_triangle_tag(integer itri, integer * tag, void *user_data) + { + MG_Hexotic_API::LibData* data = (MG_Hexotic_API::LibData *) user_data; + * tag = data->GetTriaTag( itri-1 ); + + return STATUS_OK; + } + + // status_t get_triangle_extra_vertices(integer itri, integer * typetri, + // integer * evtri, void *user_data) + // { + // int j; + // MG_Hexotic_API::LibData* data = (MG_Hexotic_API::LibData *) user_data; + + // if (1) { + // /* We want to describe a linear "3 nodes" triangle */ + // *typetri = MESHGEMS_MESH_ELEMENT_TYPE_TRIA3; + // } else { + // /* We want to describe a quadratic "6 nodes" triangle */ + // *typetri = MESHGEMS_MESH_ELEMENT_TYPE_TRIA6; + // for (j = 0; j < 3; j++) + // evtri[j] = 0; /* the j'th quadratic vertex index of the itri'th triangle */ + // } + + // return STATUS_OK; + // } + + // status_t get_tetrahedron_count(integer * nbtetra, void *user_data) + // { + // MG_Hexotic_API::LibData* data = (MG_Hexotic_API::LibData *) user_data; + + // *nbtetra = 0; /* the number of tetra in your input mesh (0 if you describe a surface mesh) */ + + // return STATUS_OK; + // } + + // status_t get_tetrahedron_vertices(integer itetra, integer * vtetra, + // void *user_data) + // { + // int j; + // MG_Hexotic_API::LibData* data = (MG_Hexotic_API::LibData *) user_data; + + // for (j = 0; j < 4; j++) + // vtetra[j] = 0; /* the j'th vertex index of the itetra'th tetrahedron */ + + // return STATUS_OK; + // } + + status_t get_vertex_required_property(integer ivtx, integer * rvtx, void *user_data) + { + MG_Hexotic_API::LibData* data = (MG_Hexotic_API::LibData *) user_data; + *rvtx = data->IsVertexRequired( ivtx - 1 ); + + return STATUS_OK; + } + + status_t get_vertex_weight(integer ivtx, real * wvtx, void *user_data) + { + MG_Hexotic_API::LibData* data = (MG_Hexotic_API::LibData *) user_data; + *wvtx = data->GetSizeAtVertex( ivtx - 1 ); + + return STATUS_OK; + } + + status_t my_message_cb(message_t * msg, void *user_data) + { + char *desc; + message_get_description(msg, &desc); + + MG_Hexotic_API::LibData* data = (MG_Hexotic_API::LibData *) user_data; + data->AddError( desc ); + + // Compute progress + // corresponding messages are: + // " | Analyzing the surface mesh |" => 1 % + // " | Building and conforming the octree |" => 8 % + // " | Subdomains and boundary recovery |" => 15% + // " | Mesh bending and smoothing |" => 45% + // " | Final mesh statistics |" => 99% + + double newProgress = std::min( 0.99, data->_progress + data->_msgCost ); + if ( strlen( desc ) > 25 ) + { + if ( strncmp( desc+3, "Analyzing the surface mesh", 26 ) == 0 ) + newProgress = 0.01, data->_msgCost = ( 0.08 - 0.01 ) / 10; + else if ( strncmp( desc+3, "Building and conforming the octree", 34 ) == 0 ) + newProgress = 0.08, data->_msgCost = ( 0.15 - 0.08 ) / 100; + else if ( strncmp( desc+3, "Subdomains and boundary recovery", 32 ) == 0 ) + newProgress = 0.15, data->_msgCost = ( 0.45 - 0.15 ) / 20; + else if ( strncmp( desc+3, "Mesh bending and smoothing", 26 ) == 0 ) + newProgress = 0.45, data->_msgCost = ( 0.99 - 0.45 ) / 65; + else if ( strncmp( desc+3, "Final mesh statistics", 21 ) == 0 ) + newProgress = 0.99; + } + data->_progress = std::max( data->_progress, newProgress ); + + return STATUS_OK; + } + + status_t my_interrupt_callback(integer *interrupt_status, void *user_data) + { + MG_Hexotic_API::LibData* data = (MG_Hexotic_API::LibData *) user_data; + *interrupt_status = ( data->Cancelled() ? INTERRUPT_STOP : INTERRUPT_CONTINUE ); + + return STATUS_OK; + } + +} // end namespace + + +void MG_Hexotic_API::LibData::Init() +{ + status_t ret; + + // Create the meshgems working context + _context = context_new(); + if ( !_context ) MG_Error( "unable to create a new context" ); + + // Set the message callback for the _context. + ret = context_set_message_callback( _context, my_message_cb, this ); + if ( ret != STATUS_OK ) MG_Error("in context_set_message_callback"); + + // Create the structure holding the callbacks giving access to triangle mesh + _tria_mesh = mesh_new( _context ); + if ( !_tria_mesh ) MG_Error("unable to create a new mesh"); + + // Set callbacks to provide triangle mesh data + mesh_set_get_vertex_count( _tria_mesh, get_vertex_count, this ); + mesh_set_get_vertex_coordinates( _tria_mesh, get_vertex_coordinates, this ); + mesh_set_get_vertex_required_property( _tria_mesh, get_vertex_required_property, this ); + mesh_set_get_edge_count( _tria_mesh, get_edge_count, this); + mesh_set_get_edge_vertices( _tria_mesh, get_edge_vertices, this ); + mesh_set_get_edge_tag( _tria_mesh, get_edge_tag, this ); + mesh_set_get_triangle_count( _tria_mesh, get_triangle_count, this ); + mesh_set_get_triangle_vertices( _tria_mesh, get_triangle_vertices, this ); + mesh_set_get_triangle_tag( _tria_mesh, get_triangle_tag, this ); + + // Create a hexa session + _session = hexa_session_new( _context ); + if ( !_session ) MG_Error( "unable to create a new hexa session"); + + ret = hexa_set_interrupt_callback( _session, my_interrupt_callback, this ); + if ( ret != STATUS_OK ) MG_Error("in hexa_set_interrupt_callback"); + +} + +bool MG_Hexotic_API::LibData::Compute() +{ + // Set surface mesh + status_t ret = hexa_set_surface_mesh( _session, _tria_mesh ); + if ( ret != STATUS_OK ) MG_Error( "unable to set surface mesh"); + + // Set a sizemap + if ( !_nodeSize.empty() ) + { + _sizemap = meshgems_sizemap_new( _tria_mesh, meshgems_sizemap_type_iso_mesh_vertex, + (void*) &get_vertex_weight, this ); + if ( !_sizemap ) MG_Error("unable to create a new sizemap"); + + ret = hexa_set_sizemap( _session, _sizemap ); + if ( ret != STATUS_OK ) MG_Error( "unable to set sizemap"); + } + + ////////////////////////////////////////////////////////////////////////////////////////// + // const char* file = "/tmp/ghs3d_IN.mesh"; + // mesh_write_mesh( _tria_mesh,file); + // std::cout << std::endl << std::endl << "Write " << file << std::endl << std::endl << std::endl; + + ret = hexa_compute_mesh( _session ); + if ( ret != STATUS_OK ) return false; + + ret = hexa_get_mesh( _session, &_hexa_mesh); + if (ret != STATUS_OK) MG_Error( "unable to get resulting mesh"); + + ////////////////////////////////////////////////////////////////////////////////////////// + // file = "/tmp/ghs3d_OUT.mesh"; + // mesh_write_mesh( _hexa_mesh,file); + // std::cout << std::endl << std::endl << "Write " << file << std::endl << std::endl << std::endl; + + return true; +} + + +#endif // ifdef USE_MG_LIBS + + +//================================================================================ +/*! + * \brief Constructor + */ +//================================================================================ + +MG_Hexotic_API::MG_Hexotic_API(volatile bool& cancelled_flag, double& progress) +{ +#ifdef USE_MG_LIBS + _useLib = true; + _libData = new LibData( cancelled_flag, progress ); + _libData->Init(); +#endif + if ( getenv("MG_HEXA_USE_EXE")) + _useLib = false; +} + +//================================================================================ +/*! + * \brief Destructor + */ +//================================================================================ + +MG_Hexotic_API::~MG_Hexotic_API() +{ +#ifdef USE_MG_LIBS + delete _libData; + _libData = 0; +#endif + std::set::iterator id = _openFiles.begin(); + for ( ; id != _openFiles.end(); ++id ) + ::GmfCloseMesh( *id ); + _openFiles.clear(); +} + +//================================================================================ +/*! + * \brief Return the way of MG usage + */ +//================================================================================ + +bool MG_Hexotic_API::IsLibrary() +{ + return _useLib; +} + +//================================================================================ +/*! + * \brief Switch to usage of MG-Hexa executable + */ +//================================================================================ + +void MG_Hexotic_API::SetUseExecutable() +{ + _useLib = false; +} + +//================================================================================ +/*! + * \brief Compute the hexa mesh + * \param [in] cmdLine - a command to run mg_hexa.exe + * \return bool - Ok or not + */ +//================================================================================ + +bool MG_Hexotic_API::Compute( const std::string& cmdLine, std::string& errStr ) +{ + if ( _useLib ) { +#ifdef USE_MG_LIBS + + // split cmdLine + std::istringstream strm( cmdLine ); + std::istream_iterator sIt( strm ), sEnd; + std::vector< std::string > args( sIt, sEnd ); + + // set parameters + std::string param, value; + for ( size_t i = 1; i < args.size(); ++i ) + { + // look for a param name; it starts from "-" + param = args[i]; + if ( param.size() < 2 || param[0] != '-') + continue; + while ( param[0] == '-') + param = param.substr( 1 ); + + value = ""; + while ( i+1 < args.size() && args[i+1][0] != '-' ) + { + if ( !value.empty() ) value += " "; + value += args[++i]; + } + if ( !_libData->SetParam( param, value )) + std::cout << "Warning: wrong param: '" << param <<"' = '" << value << "'" << std::endl; + } + + // compute + return _libData->Compute(); +#endif + } + + int err = system( cmdLine.c_str() ); // run + + if ( err ) + errStr = SMESH_Comment("system(mg-hexa.exe ...) command failed with error: ") + << strerror( errno ); + + GetLog(); // write a log file + _logFile = ""; // not to write it again + + return !err; + +} + +//================================================================================ +/*! + * \brief Prepare for reading a mesh data + */ +//================================================================================ + +int MG_Hexotic_API::GmfOpenMesh(const char* theFile, int rdOrWr, int * ver, int * dim) +{ + if ( _useLib ) { +#ifdef USE_MG_LIBS + return 1; +#endif + } + int id = ::GmfOpenMesh(theFile, rdOrWr, ver, dim ); + _openFiles.insert( id ); + return id; +} + +//================================================================================ +/*! + * \brief Return nb of entities + */ +//================================================================================ + +int MG_Hexotic_API::GmfStatKwd( int iMesh, GmfKwdCod what ) +{ + if ( _useLib ) { +#ifdef USE_MG_LIBS + switch ( what ) + { + case GmfSubDomainFromGeom: return _libData->ReadNbSubDomains(); + case GmfVertices: return _libData->ReadNbNodes(); + case GmfEdges: return _libData->ReadNbEdges(); + case GmfTriangles: return _libData->ReadNbTria(); + case GmfQuadrilaterals: return _libData->ReadNbQuads(); + case GmfTetrahedra: return _libData->ReadNbTetra(); + case GmfHexahedra: return _libData->ReadNbHexa(); + case GmfCorners: return _libData->ReadNbCorners(); + default: return 0; + } + return 0; +#endif + } + return ::GmfStatKwd( iMesh, what ); +} + +//================================================================================ +/*! + * \brief Prepare for reading some data + */ +//================================================================================ + +void MG_Hexotic_API::GmfGotoKwd( int iMesh, GmfKwdCod what ) +{ + if ( _useLib ) { +#ifdef USE_MG_LIBS + _libData->ResetCounter(); + return; +#endif + } + ::GmfGotoKwd( iMesh, what ); +} + +//================================================================================ +/*! + * \brief Return index of a domain identified by a triangle normal + * \param [in] iMesh - mesh file index + * \param [in] what - must be GmfSubDomainFromGeom + * \param [out] nbNodes - nb nodes in a face + * \param [out] faceInd - face index + * \param [out] ori - face orientation + * \param [out] domain - domain index + * \param [in] dummy - an artificial param used to discriminate from GmfGetLin() reading + * a triangle + */ +//================================================================================ + +void MG_Hexotic_API::GmfGetLin( int iMesh, GmfKwdCod what, int* nbNodes, int* faceInd, int* ori, int* domain, int dummy ) +{ + if ( _useLib ) { +#ifdef USE_MG_LIBS + _libData->ReadSubDomain( nbNodes, faceInd, ori, domain ); + return; +#endif + } + ::GmfGetLin( iMesh, what, nbNodes, faceInd, ori, domain ); +} + +//================================================================================ +/*! + * \brief Return coordinates of a next node + */ +//================================================================================ + +void MG_Hexotic_API::GmfGetLin(int iMesh, GmfKwdCod what, + double* x, double* y, double *z, int* domain ) +{ + if ( _useLib ) { +#ifdef USE_MG_LIBS + _libData->ReadNodeXYZ( x, y, z, domain ); + return; +#endif + } + ::GmfGetLin(iMesh, what, x, y, z, domain ); +} + +//================================================================================ +/*! + * \brief Return coordinates of a next node + */ +//================================================================================ + +void MG_Hexotic_API::GmfGetLin(int iMesh, GmfKwdCod what, + float* x, float* y, float *z, int* domain ) +{ + if ( _useLib ) { +#ifdef USE_MG_LIBS + double X,Y,Z; + _libData->ReadNodeXYZ( &X, &Y, &Z, domain ); + *x = X; + *y = Y; + *z = Z; + return; +#endif + } + ::GmfGetLin(iMesh, what, x, y, z, domain ); +} + +//================================================================================ +/*! + * \brief Return node index of a next corner + */ +//================================================================================ + +void MG_Hexotic_API::GmfGetLin(int iMesh, GmfKwdCod what, int* node ) +{ + if ( _useLib ) { +#ifdef USE_MG_LIBS + _libData->ReadCorner( node ); + return; +#endif + } + ::GmfGetLin(iMesh, what, node ); +} + +//================================================================================ +/*! + * \brief Return node indices of a next edge + */ +//================================================================================ + +void MG_Hexotic_API::GmfGetLin(int iMesh, GmfKwdCod what, int* node1, int* node2, int* domain ) +{ + if ( _useLib ) { +#ifdef USE_MG_LIBS + _libData->ReadEdgeNodes( node1, node2, domain ); + return; +#endif + } + ::GmfGetLin( iMesh, what, node1, node2, domain ); +} + +//================================================================================ +/*! + * \brief Return node indices of a next triangle + */ +//================================================================================ + +void MG_Hexotic_API::GmfGetLin(int iMesh, GmfKwdCod what, + int* node1, int* node2, int* node3, int* domain ) +{ + if ( _useLib ) { +#ifdef USE_MG_LIBS + _libData->ReadTriaNodes( node1, node2, node3, domain ); + return; +#endif + } + ::GmfGetLin(iMesh, what, node1, node2, node3, domain ); +} + +//================================================================================ +/*! + * \brief Return node indices of a next tetrahedron or quadrangle + */ +//================================================================================ + +void MG_Hexotic_API::GmfGetLin(int iMesh, GmfKwdCod what, + int* node1, int* node2, int* node3, int* node4, int* domain ) +{ + if ( _useLib ) { +#ifdef USE_MG_LIBS + if ( what == GmfQuadrilaterals ) + _libData->ReadQuadNodes( node1, node2, node3, node4, domain ); + else + _libData->ReadTetraNodes( node1, node2, node3, node4, domain ); + return; +#endif + } + ::GmfGetLin(iMesh, what, node1, node2, node3, node4, domain ); +} + +//================================================================================ +/*! + * \brief Return node indices of a next hexahedron + */ +//================================================================================ + +void MG_Hexotic_API::GmfGetLin(int iMesh, GmfKwdCod what, + int* node1, int* node2, int* node3, int* node4, + int* node5, int* node6, int* node7, int* node8, + int* domain ) +{ + if ( _useLib ) { +#ifdef USE_MG_LIBS + _libData->ReadHexaNodes( node1, node2, node3, node4, + node5, node6, node7, node8, domain ); + return; +#endif + } + ::GmfGetLin(iMesh, what, node1, node2, node3, node4, node5, node6, node7, node8, domain ); +} + +//================================================================================ +/*! + * \brief Prepare for passing data to MeshGems + */ +//================================================================================ + +int MG_Hexotic_API::GmfOpenMesh(const char* theFile, int rdOrWr, int ver, int dim) +{ + if ( _useLib ) { +#ifdef USE_MG_LIBS + return 1; +#endif + } + int id = ::GmfOpenMesh(theFile, rdOrWr, ver, dim); + _openFiles.insert( id ); + return id; +} + +//================================================================================ +/*! + * \brief Set number of entities + */ +//================================================================================ + +void MG_Hexotic_API::GmfSetKwd(int iMesh, GmfKwdCod what, int nb ) +{ + if ( _useLib ) { +#ifdef USE_MG_LIBS + switch ( what ) { + case GmfVertices: _libData->SetNbVertices( nb ); break; + case GmfEdges: _libData->SetNbEdges ( nb ); break; + case GmfRequiredEdges: _libData->SetNbReqEdges( nb ); break; + case GmfTriangles: _libData->SetNbTria ( nb ); break; + case GmfRequiredTriangles: _libData->SetNbReqTria ( nb ); break; + default:; + } + return; +#endif + } + ::GmfSetKwd(iMesh, what, nb ); +} + +//================================================================================ +/*! + * \brief Add coordinates of a node + */ +//================================================================================ + +void MG_Hexotic_API::GmfSetLin(int iMesh, GmfKwdCod what, double x, double y, double z, int domain) +{ + if ( _useLib ) { +#ifdef USE_MG_LIBS + _libData->AddNode( x, y, z, domain ); + return; +#endif + } + ::GmfSetLin(iMesh, what, x, y, z, domain); +} + +//================================================================================ +/*! + * \brief Set number of field entities + * \param [in] iMesh - solution file index + * \param [in] what - solution type + * \param [in] nbNodes - nb of entities + * \param [in] nbTypes - nb of data entries in each entity + * \param [in] type - types of the data entries + * + * Used to prepare to storing size at nodes + */ +//================================================================================ + +void MG_Hexotic_API::GmfSetKwd(int iMesh, GmfKwdCod what, int nbNodes, int dummy, int type[] ) +{ + if ( _useLib ) { +#ifdef USE_MG_LIBS + if ( what == GmfSolAtVertices ) _libData->SetNbReqVertices( nbNodes ); + return; +#endif + } + ::GmfSetKwd(iMesh, what, nbNodes, dummy, type ); +} + +//================================================================================ +/*! + * \brief Add solution data + */ +//================================================================================ + +void MG_Hexotic_API::GmfSetLin(int iMesh, GmfKwdCod what, double vals[]) +{ + if ( _useLib ) { +#ifdef USE_MG_LIBS + _libData->AddSizeAtNode( vals[0] ); + return; +#endif + } + ::GmfSetLin(iMesh, what, vals); +} + +//================================================================================ +/*! + * \brief Add edge nodes + */ +//================================================================================ + +void MG_Hexotic_API::GmfSetLin(int iMesh, GmfKwdCod what, int node1, int node2, int domain ) +{ + if ( _useLib ) { +#ifdef USE_MG_LIBS + _libData->AddEdgeNodes( node1, node2, domain ); + return; +#endif + } + ::GmfSetLin(iMesh, what, node1, node2, domain ); +} + +//================================================================================ +/*! + * \brief Add a 'required' flag + */ +//================================================================================ + +void MG_Hexotic_API::GmfSetLin(int iMesh, GmfKwdCod what, int id ) +{ + if ( _useLib ) { +#ifdef USE_MG_LIBS + return; +#endif + } + ::GmfSetLin(iMesh, what, id ); +} + +//================================================================================ +/*! + * \brief Add triangle nodes + */ +//================================================================================ + +void MG_Hexotic_API::GmfSetLin(int iMesh, GmfKwdCod what, int node1, int node2, int node3, int domain ) +{ + if ( _useLib ) { +#ifdef USE_MG_LIBS + _libData->AddTriaNodes( node1, node2, node3, domain ); + return; +#endif + } + ::GmfSetLin(iMesh, what, node1, node2, node3, domain ); +} + +//================================================================================ +/*! + * \brief Close a file + */ +//================================================================================ + +void MG_Hexotic_API::GmfCloseMesh( int iMesh ) +{ + if ( _useLib ) { +#ifdef USE_MG_LIBS + return; +#endif + } + ::GmfCloseMesh( iMesh ); + _openFiles.erase( iMesh ); +} + +//================================================================================ +/*! + * \brief Return true if the log is not empty + */ +//================================================================================ + +bool MG_Hexotic_API::HasLog() +{ + if ( _useLib ) { +#ifdef USE_MG_LIBS + return !_libData->GetErrors().empty(); +#endif + } + SMESH_File file( _logFile ); + return file.size() > 0; +} + +//================================================================================ +/*! + * \brief Return log contents + */ +//================================================================================ + +std::string MG_Hexotic_API::GetLog() +{ + if ( _useLib ) { +#ifdef USE_MG_LIBS + const std::string& err = _libData->GetErrors(); + if ( !_logFile.empty() && !err.empty() ) + { + SMESH_File file( _logFile, /*openForReading=*/false ); + file.openForWriting(); + file.write( err.c_str(), err.size() ); + } + return err; +#endif + } + SMESH_File file( _logFile ); + return file.getPos(); +} diff --git a/src/HexoticPlugin/MG_Hexotic_API.hxx b/src/HexoticPlugin/MG_Hexotic_API.hxx new file mode 100644 index 0000000..5e25999 --- /dev/null +++ b/src/HexoticPlugin/MG_Hexotic_API.hxx @@ -0,0 +1,86 @@ +// Copyright (C) 2004-2016 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#ifndef __MG_Hexotic_IO_HXX__ +#define __MG_Hexotic_IO_HXX__ + +extern "C" +{ +#include "libmesh5.h" +} +#include +#include + +/*! + * \brief Class providing a transparent switch between MG_Hexotic usage as + * a library and as an executable. API of libmesh5 inherited. + */ +class MG_Hexotic_API +{ +public: + + MG_Hexotic_API( volatile bool& cancelled_flag, double& progress ); + ~MG_Hexotic_API(); + + bool IsLibrary(); + bool IsExecutable() { return !IsLibrary(); } + void SetUseExecutable(); + + // IN to MESHGEMS + int GmfOpenMesh(const char* theFile, int rdOrWr, int ver, int dim); + void GmfSetKwd(int iMesh, GmfKwdCod what, int nb ); + void GmfSetLin(int iMesh, GmfKwdCod what, double x, double y, double z, int domain); + void GmfSetKwd(int iMesh, GmfKwdCod what, int nbNodes, int dummy, int type[] ); // sol type + void GmfSetLin(int iMesh, GmfKwdCod what, double vals[]); // sol + void GmfSetLin(int iMesh, GmfKwdCod what, int node1, int node2, int domain ); // edge + void GmfSetLin(int iMesh, GmfKwdCod what, int id ); // required + void GmfSetLin(int iMesh, GmfKwdCod what, int node1, int node2, int node3, int domain ); // tria + + bool Compute( const std::string& cmdLine, std::string& errStr ); + + // OUT from MESHGEMS + int GmfOpenMesh(const char* theFile, int rdOrWr, int * ver, int * dim); + int GmfStatKwd( int iMesh, GmfKwdCod what ); + void GmfGotoKwd( int iMesh, GmfKwdCod what ); + void GmfGetLin( int iMesh, GmfKwdCod what, int* nbNodes, int* faceInd, int* ori, int* domain, int dummy ); + void GmfGetLin(int iMesh, GmfKwdCod what, float* x, float* y, float *z, int* domain ); + void GmfGetLin(int iMesh, GmfKwdCod what, double* x, double* y, double *z, int* domain ); + void GmfGetLin(int iMesh, GmfKwdCod what, int* node ); + void GmfGetLin(int iMesh, GmfKwdCod what, int* node1, int* node2, int* domain ); + void GmfGetLin(int iMesh, GmfKwdCod what, int* node1, int* node2, int* node3, int* domain ); + void GmfGetLin(int iMesh, GmfKwdCod what, int* node1, int* node2, int* node3, int* node4, int* domain ); + void GmfGetLin(int iMesh, GmfKwdCod what, int* node1, int* node2, int* node3, int* node4, int* node5, int* node6, int* node7, int* node8, int* domain ); + void GmfCloseMesh( int iMesh ); + + void SetLogFile( const std::string& logFileName ) { _logFile = logFileName; } + bool HasLog(); + std::string GetLog(); + + + struct LibData; + +private: + + bool _useLib; + LibData* _libData; + std::set _openFiles; + std::string _logFile; +}; + +#endif