From 9dd045b97c68174d7ce52d592b239c6a1769e464 Mon Sep 17 00:00:00 2001 From: eap Date: Tue, 14 Mar 2017 15:43:27 +0300 Subject: [PATCH] 23258: [CEA 1804] Do not merge the middle nodes of quadratic elements Add AvoidMakingHoles argument in MergeNodes() + Save mesh name in STL file + Fix binary STL export after change of sizeof(Standard_Boolean) + Add Import menu to mesh component popup --- doc/salome/gui/SMESH/images/mergenodes.png | Bin 41388 -> 41290 bytes .../gui/SMESH/images/mergenodes_auto.png | Bin 29030 -> 30511 bytes doc/salome/gui/SMESH/input/merging_nodes.doc | 3 + idl/SMESH_MeshEditor.idl | 3 +- src/DriverSTL/DriverSTL_R_SMDS_Mesh.cxx | 52 +- src/DriverSTL/DriverSTL_R_SMDS_Mesh.h | 12 +- src/DriverSTL/DriverSTL_W_SMDS_Mesh.cxx | 13 +- src/DriverSTL/DriverSTL_W_SMDS_Mesh.h | 4 +- src/SMDS/SMDS_VolumeTool.cxx | 24 +- src/SMDS/SMDS_VolumeTool.hxx | 16 +- src/SMESH/SMESH_Mesh.cxx | 6 +- src/SMESH/SMESH_Mesh.hxx | 3 +- src/SMESH/SMESH_MeshEditor.cxx | 941 ++++++++++-------- src/SMESH/SMESH_MeshEditor.hxx | 31 +- src/SMESHGUI/SMESHGUI.cxx | 73 +- src/SMESHGUI/SMESHGUI_MergeDlg.cxx | 10 +- src/SMESHGUI/SMESHGUI_MergeDlg.h | 1 + src/SMESHGUI/SMESHGUI_Operations.h | 15 +- src/SMESHGUI/SMESH_msg_en.ts | 4 + src/SMESHUtils/CMakeLists.txt | 3 +- src/SMESHUtils/SMESH_DeMerge.cxx | 215 ++++ src/SMESHUtils/SMESH_MeshAlgos.hxx | 12 +- src/SMESH_I/SMESH_MeshEditor_i.cxx | 5 +- src/SMESH_I/SMESH_MeshEditor_i.hxx | 3 +- src/SMESH_I/SMESH_Mesh_i.cxx | 26 +- src/SMESH_SWIG/smeshBuilder.py | 13 +- 26 files changed, 959 insertions(+), 529 deletions(-) create mode 100644 src/SMESHUtils/SMESH_DeMerge.cxx diff --git a/doc/salome/gui/SMESH/images/mergenodes.png b/doc/salome/gui/SMESH/images/mergenodes.png index 5b34361cb92541527510a8644626ce88d4b24373..fc75f70dd9c5d91df331d56d70eeccf1ac1bfd7f 100644 GIT binary patch literal 41290 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

15OSekl%M~2vKDl7oj{jQa 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 diff --git a/doc/salome/gui/SMESH/images/mergenodes_auto.png b/doc/salome/gui/SMESH/images/mergenodes_auto.png index 4f177f605fbce3dcea99859915a1fc8e84681e8b..e2704690873c304d78de876bf13fa0c7de3007bb 100644 GIT binary patch literal 30511 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 literal 29030 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 cells check-box prevents merging medium nodes of quadratic elements with corner nodes. This check-box is enabled provided that the selected mesh includes quadratic elements. +

  • Activation of Avoid making holes check-box prevents merging + nodes that make elements invalid (but not degenerated) and hence + removed. Thus, no holes in place of removed elements appear.
  • Exclude groups from detection group allows to ignore the nodes which belong to the specified mesh groups. This control is active provided that the mesh includes groups.
  • diff --git a/idl/SMESH_MeshEditor.idl b/idl/SMESH_MeshEditor.idl index 577e39c58..ea19b5ebe 100644 --- a/idl/SMESH_MeshEditor.idl +++ b/idl/SMESH_MeshEditor.idl @@ -689,7 +689,8 @@ module SMESH raises (SALOME::SALOME_Exception); void MergeNodes (in array_of_long_array GroupsOfNodes, - in SMESH::ListOfIDSources NodesToKeep) + in SMESH::ListOfIDSources NodesToKeep, + in boolean AvoidMakingHoles) raises (SALOME::SALOME_Exception); /*! diff --git a/src/DriverSTL/DriverSTL_R_SMDS_Mesh.cxx b/src/DriverSTL/DriverSTL_R_SMDS_Mesh.cxx index 9a531668c..ae7e48cca 100644 --- a/src/DriverSTL/DriverSTL_R_SMDS_Mesh.cxx +++ b/src/DriverSTL/DriverSTL_R_SMDS_Mesh.cxx @@ -69,7 +69,7 @@ namespace }; typedef NCollection_DataMap TDataMapOfPntNodePtr; - const int HEADER_SIZE = 84; + const int HEADER_SIZE = 84; // 80 chars + int const int SIZEOF_STL_FACET = 50; const int ASCII_LINES_PER_FACET = 7; const int SIZE_OF_FLOAT = 4; @@ -150,11 +150,12 @@ Driver_Mesh::Status DriverSTL_R_SMDS_Mesh::Perform() static Standard_Real readFloat(SMESH_File& theFile) { union { - Standard_Boolean i; - Standard_ShortReal f; + int i; + float f; } u; const char* c = theFile; + u.i = 0; u.i = c[0] & 0xFF; u.i |= (c[1] & 0xFF) << 0x08; u.i |= (c[2] & 0xFF) << 0x10; @@ -205,30 +206,48 @@ static SMDS_MeshNode* readNode(SMESH_File& theFile, //======================================================================= //function : readAscii -//purpose : +//purpose : //======================================================================= Driver_Mesh::Status DriverSTL_R_SMDS_Mesh::readAscii(SMESH_File& theFile) const { Status aResult = DRS_OK; + // get a solid name + if ( strncmp( "solid ", theFile, strlen("solid ")) == 0 ) // not empty + { + const char * header = theFile; + std::string& name = const_cast( myName ); + for ( header += strlen("solid "); !iscntrl( *header ); ++header ) + name.push_back( *header ); + + std::string::iterator i = name.begin(); + while ( i != name.end() && isspace( *i )) ++i; + name.erase( name.begin(), i ); + + size_t n = name.size(); + while ( n > 0 && isspace( name[ n - 1 ] )) --n; + name.resize( n ); + } + // get the file size long filesize = theFile.size(); theFile.close(); - // Open the file + // Open the file FILE* file = fopen( myFile.c_str(),"r"); // count the number of lines Standard_Integer nbLines = 0; - for (long ipos = 0; ipos < filesize; ++ipos) { + for (long ipos = 0; ipos < filesize; ++ipos) + { if (getc(file) == '\n') nbLines++; } // go back to the beginning of the file rewind(file); - + Standard_Integer nbTri = (nbLines / ASCII_LINES_PER_FACET); TDataMapOfPntNodePtr uniqnodes; @@ -236,8 +255,8 @@ Driver_Mesh::Status DriverSTL_R_SMDS_Mesh::readAscii(SMESH_File& theFile) const while (getc(file) != '\n'); // main reading - for (Standard_Integer iTri = 0; iTri < nbTri; ++iTri) { - + for (Standard_Integer iTri = 0; iTri < nbTri; ++iTri) + { // skipping the facet normal Standard_ShortReal normal[3]; fscanf(file,"%*s %*s %f %f %f\n",&normal[0],&normal[1],&normal[2]); @@ -278,7 +297,7 @@ Driver_Mesh::Status DriverSTL_R_SMDS_Mesh::readBinary(SMESH_File& file) const long filesize = file.size(); - if ( (filesize - HEADER_SIZE) % SIZEOF_STL_FACET !=0 + if ( (filesize - HEADER_SIZE) % SIZEOF_STL_FACET != 0 // Commented to allow reading small files (ex: 1 face) /*|| (filesize < STL_MIN_FILE_SIZE)*/) { Standard_NoMoreObject::Raise("DriverSTL_R_SMDS_MESH::readBinary (wrong file size)"); @@ -288,6 +307,19 @@ Driver_Mesh::Status DriverSTL_R_SMDS_Mesh::readBinary(SMESH_File& file) const // sometimes it is wrong, and with this technique we don't need to swap endians for integer Standard_Integer nbTri = ((filesize - HEADER_SIZE) / SIZEOF_STL_FACET); + // get a solid name + if ( strncmp( "name: ", file, strlen("name: ")) == 0 ) // name present + { + const char * header = file; + std::string& name = const_cast( myName ); + header += strlen("name: "); + name.assign( header, HEADER_SIZE - strlen("name: ") - 4); + + size_t n = name.size(); + while ( n > 0 && isspace( name[ n - 1 ] )) --n; + name.resize( n ); + } + // skip the header file += HEADER_SIZE; diff --git a/src/DriverSTL/DriverSTL_R_SMDS_Mesh.h b/src/DriverSTL/DriverSTL_R_SMDS_Mesh.h index 5459b5181..d30366bfb 100644 --- a/src/DriverSTL/DriverSTL_R_SMDS_Mesh.h +++ b/src/DriverSTL/DriverSTL_R_SMDS_Mesh.h @@ -35,16 +35,18 @@ class MESHDRIVERSTL_EXPORT DriverSTL_R_SMDS_Mesh: public Driver_SMDS_Mesh DriverSTL_R_SMDS_Mesh(); virtual Status Perform(); void SetIsCreateFaces( const bool theIsCreate = true ); + std::string GetName() const { return myName; } private: // PRIVATE METHODS - Status readAscii (SMESH_File& file) const; - Status readBinary(SMESH_File& file) const; - + Status readAscii (SMESH_File& file) const; + Status readBinary(SMESH_File& file) const; + private: // PRIVATE FIELDS - bool myIsCreateFaces; - bool myIsAscii; + bool myIsCreateFaces; + bool myIsAscii; + std::string myName; }; #endif diff --git a/src/DriverSTL/DriverSTL_W_SMDS_Mesh.cxx b/src/DriverSTL/DriverSTL_W_SMDS_Mesh.cxx index cb42a321b..333c72d96 100644 --- a/src/DriverSTL/DriverSTL_W_SMDS_Mesh.cxx +++ b/src/DriverSTL/DriverSTL_W_SMDS_Mesh.cxx @@ -176,7 +176,7 @@ static void writeFloat( const Standard_ShortReal& theVal, SMESH_File& ofile) { union { Standard_ShortReal f; - char c[4]; + char c[4]; } u; u.f = theVal; @@ -485,7 +485,8 @@ Driver_Mesh::Status DriverSTL_W_SMDS_Mesh::writeAscii() const SMESH_File aFile( myFile, /*openForReading=*/false ); aFile.openForWriting(); - std::string buf("solid\n"); + std::string buf("solid "); + buf += myName + "\n"; aFile.writeRaw( buf.c_str(), buf.size() ); char sval[128]; @@ -520,7 +521,8 @@ Driver_Mesh::Status DriverSTL_W_SMDS_Mesh::writeAscii() const " endfacet\n", 21 ); } } - aFile.writeRaw ("endsolid\n" , 9 ); + buf = "endsolid " + myName + "\n"; + aFile.writeRaw( buf.c_str(), buf.size() ); return aResult; } @@ -554,6 +556,11 @@ Driver_Mesh::Status DriverSTL_W_SMDS_Mesh::writeBinary() const } } std::string sval( LABEL_SIZE, ' ' ); + if ( !myName.empty() ) + { + sval = "name: " + myName; + sval.resize( LABEL_SIZE, ' ' ); + } aFile.write( sval.c_str(), LABEL_SIZE ); // write number of triangles diff --git a/src/DriverSTL/DriverSTL_W_SMDS_Mesh.h b/src/DriverSTL/DriverSTL_W_SMDS_Mesh.h index efc027be1..66c4741bf 100644 --- a/src/DriverSTL/DriverSTL_W_SMDS_Mesh.h +++ b/src/DriverSTL/DriverSTL_W_SMDS_Mesh.h @@ -45,6 +45,7 @@ class MESHDRIVERSTL_EXPORT DriverSTL_W_SMDS_Mesh: public Driver_SMDS_Mesh ~DriverSTL_W_SMDS_Mesh(); virtual Status Perform(); void SetIsAscii( const bool theIsAscii = false ); + void SetName( const std::string name ) { myName = name; } private: // PRIVATE METHODS @@ -56,7 +57,8 @@ class MESHDRIVERSTL_EXPORT DriverSTL_W_SMDS_Mesh: public Driver_SMDS_Mesh private: // PRIVATE FIELDS - bool myIsAscii; + bool myIsAscii; + std::string myName; int myNbVolumeTrias; std::vector myVolumeFacets; // tmp faces }; diff --git a/src/SMDS/SMDS_VolumeTool.cxx b/src/SMDS/SMDS_VolumeTool.cxx index d7dd7f826..f7857c3eb 100644 --- a/src/SMDS/SMDS_VolumeTool.cxx +++ b/src/SMDS/SMDS_VolumeTool.cxx @@ -471,8 +471,9 @@ SMDS_VolumeTool::~SMDS_VolumeTool() //purpose : Set volume to iterate on //======================================================================= -bool SMDS_VolumeTool::Set (const SMDS_MeshElement* theVolume, - const bool ignoreCentralNodes) +bool SMDS_VolumeTool::Set (const SMDS_MeshElement* theVolume, + const bool ignoreCentralNodes, + const std::vector* otherNodes) { // reset fields myVolume = 0; @@ -510,11 +511,22 @@ bool SMDS_VolumeTool::Set (const SMDS_MeshElement* theVolume, } // set nodes - int iNode = 0; myVolumeNodes.resize( myVolume->NbNodes() ); - SMDS_ElemIteratorPtr nodeIt = myVolume->nodesIterator(); - while ( nodeIt->more() ) - myVolumeNodes[ iNode++ ] = static_cast( nodeIt->next() ); + if ( otherNodes ) + { + if ( otherNodes->size() != myVolumeNodes.size() ) + return ( myVolume = 0 ); + for ( size_t i = 0; i < otherNodes->size(); ++i ) + if ( ! ( myVolumeNodes[i] = (*otherNodes)[0] )) + return ( myVolume = 0 ); + } + else + { + int iNode = 0; + SMDS_ElemIteratorPtr nodeIt = myVolume->nodesIterator(); + while ( nodeIt->more() ) + myVolumeNodes[ iNode++ ] = static_cast( nodeIt->next() ); + } // check validity if ( !setFace(0) ) diff --git a/src/SMDS/SMDS_VolumeTool.hxx b/src/SMDS/SMDS_VolumeTool.hxx index b42a0ae07..5c2c882f6 100644 --- a/src/SMDS/SMDS_VolumeTool.hxx +++ b/src/SMDS/SMDS_VolumeTool.hxx @@ -58,15 +58,17 @@ class SMDS_EXPORT SMDS_VolumeTool SMDS_VolumeTool (); ~SMDS_VolumeTool (); - SMDS_VolumeTool (const SMDS_MeshElement* theVolume, - const bool ignoreCentralNodes=true); + SMDS_VolumeTool( const SMDS_MeshElement* theVolume, + const bool ignoreCentralNodes = true); - bool Set (const SMDS_MeshElement* theVolume, - const bool ignoreCentralNodes=true); + bool Set( const SMDS_MeshElement* theVolume, + const bool ignoreCentralNodes = true, + const std::vector* nodes = NULL); // Set volume. // Return false if theVolume is not of type SMDSAbs_Volume. // ignoreCentralNodes makes skip nodes at face centers when returning - // nodes of faces of SMDSEntity_TriQuad_Hexa + // nodes of faces of SMDSEntity_TriQuad_Hexa. + // alternative nodes can be provided const SMDS_MeshVolume* Element() const; // return element @@ -91,10 +93,10 @@ class SMDS_EXPORT SMDS_VolumeTool // top and bottom faces are reversed. // Result of IsForward() and methods returning nodes change - const SMDS_MeshNode** GetNodes() { return &myVolumeNodes[0]; } + const SMDS_MeshNode** GetNodes() const { return (const SMDS_MeshNode**) &myVolumeNodes[0]; } // Return array of volume nodes - int NbNodes() { return myVolumeNodes.size(); } + int NbNodes() const { return myVolumeNodes.size(); } // Return array of volume nodes double GetSize() const; diff --git a/src/SMESH/SMESH_Mesh.cxx b/src/SMESH/SMESH_Mesh.cxx index 98725ba12..893a28aba 100644 --- a/src/SMESH/SMESH_Mesh.cxx +++ b/src/SMESH/SMESH_Mesh.cxx @@ -559,7 +559,7 @@ int SMESH_Mesh::MEDToMesh(const char* theFileName, const char* theMeshName) //purpose : //======================================================================= -int SMESH_Mesh::STLToMesh(const char* theFileName) +std::string SMESH_Mesh::STLToMesh(const char* theFileName) { if(_isShapeToMesh) throw SALOME_Exception(LOCALIZED("a shape to mesh has already been defined")); @@ -571,7 +571,7 @@ int SMESH_Mesh::STLToMesh(const char* theFileName) myReader.SetMeshId(-1); myReader.Perform(); - return 1; + return myReader.GetName(); } //================================================================================ @@ -1560,6 +1560,7 @@ void SMESH_Mesh::ExportUNV(const char * file, void SMESH_Mesh::ExportSTL(const char * file, const bool isascii, + const char * name, const SMESHDS_Mesh* meshPart) throw(SALOME_Exception) { Unexpect aCatch(SalomeException); @@ -1568,6 +1569,7 @@ void SMESH_Mesh::ExportSTL(const char * file, myWriter.SetIsAscii( isascii ); myWriter.SetMesh( meshPart ? (SMESHDS_Mesh*) meshPart : _myMeshDS); myWriter.SetMeshId(_id); + if ( name ) myWriter.SetName( name ); myWriter.Perform(); } diff --git a/src/SMESH/SMESH_Mesh.hxx b/src/SMESH/SMESH_Mesh.hxx index 1fd14f397..a8ec5dfae 100644 --- a/src/SMESH/SMESH_Mesh.hxx +++ b/src/SMESH/SMESH_Mesh.hxx @@ -121,7 +121,7 @@ class SMESH_EXPORT SMESH_Mesh int MEDToMesh(const char* theFileName, const char* theMeshName); - int STLToMesh(const char* theFileName); + std::string STLToMesh(const char* theFileName); int CGNSToMesh(const char* theFileName, const int theMeshIndex, std::string& theMeshName); @@ -263,6 +263,7 @@ class SMESH_EXPORT SMESH_Mesh const SMESHDS_Mesh* meshPart = 0) throw(SALOME_Exception); void ExportSTL(const char * file, const bool isascii, + const char * name = 0, const SMESHDS_Mesh* meshPart = 0) throw(SALOME_Exception); void ExportCGNS(const char * file, const SMESHDS_Mesh* mesh, diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index f4dd0d7db..38b2eeb9f 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -6095,7 +6095,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet theElements[2], aPrms.push_back( aT ); } //Extrusion_Error err = - MakeEdgePathPoints(aPrms, aTrackEdge, (aN1==theN1), fullList); + makeEdgePathPoints(aPrms, aTrackEdge, (aN1==theN1), fullList); } else if( aS.ShapeType() == TopAbs_WIRE ) { list< SMESH_subMesh* > LSM; TopTools_SequenceOfShape Edges; @@ -6140,7 +6140,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet theElements[2], } list LPP; //Extrusion_Error err = - MakeEdgePathPoints(aPrms, aTrackEdge,(aN1->GetID()==startNid), LPP); + makeEdgePathPoints(aPrms, aTrackEdge,(aN1->GetID()==startNid), LPP); LLPPs.push_back(LPP); UsedNums.Add(k); // update startN for search following egde @@ -6183,7 +6183,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet theElements[2], return EXTR_BAD_PATH_SHAPE; } - return MakeExtrElements(theElements, fullList, theHasAngles, theAngles, theLinearVariation, + return makeExtrElements(theElements, fullList, theHasAngles, theAngles, theLinearVariation, theHasRefPoint, theRefPoint, theMakeGroups); } @@ -6322,7 +6322,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet theElements[2], TopoDS_Edge e = BRepBuilderAPI_MakeEdge( p1, p2 ); list LPP; aPrms.clear(); - MakeEdgePathPoints(aPrms, e, (aNodesList[i-1]->GetID()==startNid), LPP); + makeEdgePathPoints(aPrms, e, (aNodesList[i-1]->GetID()==startNid), LPP); LLPPs.push_back(LPP); if ( aNodesList[i-1]->GetID() == startNid ) startNid = aNodesList[i ]->GetID(); else startNid = aNodesList[i-1]->GetID(); @@ -6380,7 +6380,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet theElements[2], aPrms.push_back( aT ); } //Extrusion_Error err = - MakeEdgePathPoints(aPrms, aTrackEdge, (aN1==theN1), fullList); + makeEdgePathPoints(aPrms, aTrackEdge, (aN1==theN1), fullList); } else if( aS.ShapeType() == TopAbs_WIRE ) { list< SMESH_subMesh* > LSM; @@ -6439,7 +6439,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet theElements[2], } list LPP; //Extrusion_Error err = - MakeEdgePathPoints(aPrms, aTrackEdge, aN1isOK, LPP); + makeEdgePathPoints(aPrms, aTrackEdge, aN1isOK, LPP); LLPPs.push_back(LPP); UsedNums.Add(k); // update startN for search following egde @@ -6475,17 +6475,17 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet theElements[2], return EXTR_BAD_PATH_SHAPE; } - return MakeExtrElements(theElements, fullList, theHasAngles, theAngles, theLinearVariation, + return makeExtrElements(theElements, fullList, theHasAngles, theAngles, theLinearVariation, theHasRefPoint, theRefPoint, theMakeGroups); } //======================================================================= -//function : MakeEdgePathPoints +//function : makeEdgePathPoints //purpose : auxiliary for ExtrusionAlongTrack //======================================================================= SMESH_MeshEditor::Extrusion_Error -SMESH_MeshEditor::MakeEdgePathPoints(std::list& aPrms, +SMESH_MeshEditor::makeEdgePathPoints(std::list& aPrms, const TopoDS_Edge& aTrackEdge, bool FirstIsStart, list& LPP) @@ -6536,11 +6536,11 @@ SMESH_MeshEditor::MakeEdgePathPoints(std::list& aPrms, //======================================================================= -//function : MakeExtrElements +//function : makeExtrElements //purpose : auxiliary for ExtrusionAlongTrack //======================================================================= SMESH_MeshEditor::Extrusion_Error -SMESH_MeshEditor::MakeExtrElements(TIDSortedElemSet theElemSets[2], +SMESH_MeshEditor::makeExtrElements(TIDSortedElemSet theElemSets[2], list& fullList, const bool theHasAngles, list& theAngles, @@ -6553,7 +6553,7 @@ SMESH_MeshEditor::MakeExtrElements(TIDSortedElemSet theElemSets // Angles if( theHasAngles && !theAngles.empty() && theLinearVariation ) - LinearAngleVariation(aNbTP-1, theAngles); + linearAngleVariation(aNbTP-1, theAngles); // fill vector of path points with angles vector aPPs; @@ -6746,11 +6746,11 @@ SMESH_MeshEditor::MakeExtrElements(TIDSortedElemSet theElemSets //======================================================================= -//function : LinearAngleVariation +//function : linearAngleVariation //purpose : spread values over nbSteps //======================================================================= -void SMESH_MeshEditor::LinearAngleVariation(const int nbSteps, +void SMESH_MeshEditor::linearAngleVariation(const int nbSteps, list& Angles) { int nbAngles = Angles.size(); @@ -7258,7 +7258,7 @@ void SMESH_MeshEditor::FindCoincidentNodes (TIDSortedNodeSet & theNodes, } else while ( nIt->more() ) - theNodes.insert( theNodes.end(),nIt->next() ); + theNodes.insert( theNodes.end(), nIt->next() ); } else if ( theSeparateCornersAndMedium ) // separate corners from medium nodes { @@ -7351,11 +7351,12 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes, myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); - SMESHDS_Mesh* aMesh = GetMeshDS(); + SMESHDS_Mesh* mesh = GetMeshDS(); TNodeNodeMap nodeNodeMap; // node to replace - new node set elems; // all elements with changed nodes list< int > rmElemIds, rmNodeIds; + vector< ElemFeatures > newElemDefs; // Fill nodeNodeMap and elems @@ -7369,17 +7370,6 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes, { const SMDS_MeshNode* nToRemove = *nIt; nodeNodeMap.insert( make_pair( nToRemove, nToKeep )); - if ( nToRemove != nToKeep ) - { - rmNodeIds.push_back( nToRemove->GetID() ); - AddToSameGroups( nToKeep, nToRemove, aMesh ); - // set _alwaysComputed to a sub-mesh of VERTEX to enable mesh computing - // after MergeNodes() w/o creating node in place of merged ones. - const SMDS_PositionPtr& pos = nToRemove->GetPosition(); - if ( pos && pos->GetTypeOfPosition() == SMDS_TOP_VERTEX ) - if ( SMESH_subMesh* sm = myMesh->GetSubMeshContaining( nToRemove->getshapeId() )) - sm->SetIsAlwaysComputed( true ); - } SMDS_ElemIteratorPtr invElemIt = nToRemove->GetInverseElementIterator(); while ( invElemIt->more() ) { const SMDS_MeshElement* elem = invElemIt->next(); @@ -7387,469 +7377,548 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes, } } } - // Change element nodes or remove an element - set nodeSet; - vector< const SMDS_MeshNode*> curNodes, uniqueNodes; - vector iRepl; - ElemFeatures elemType; + // Apply recursive replacements (BUG 0020185) + TNodeNodeMap::iterator nnIt = nodeNodeMap.begin(); + for ( ; nnIt != nodeNodeMap.end(); ++nnIt ) + { + const SMDS_MeshNode* nToKeep = nnIt->second; + TNodeNodeMap::iterator nnIt_i = nodeNodeMap.find( nToKeep ); + while ( nnIt_i != nodeNodeMap.end() && nnIt_i->second != nnIt->second ) + nToKeep = nnIt_i->second; + nnIt->second = nToKeep; + } + + if ( theAvoidMakingHoles ) + { + // find elements whose topology changes + + vector pbElems; + set::iterator eIt = elems.begin(); + for ( ; eIt != elems.end(); ++eIt ) + { + const SMDS_MeshElement* elem = *eIt; + SMDS_ElemIteratorPtr itN = elem->nodesIterator(); + while ( itN->more() ) + { + const SMDS_MeshNode* n = static_cast( itN->next() ); + TNodeNodeMap::iterator nnIt = nodeNodeMap.find( n ); + if ( nnIt != nodeNodeMap.end() && elem->GetNodeIndex( nnIt->second ) >= 0 ) + { + // several nodes of elem stick + pbElems.push_back( elem ); + break; + } + } + } + // exclude from merge nodes causing spoiling element + for ( size_t iLoop = 0; iLoop < pbElems.size(); ++iLoop ) // avoid infinite cycle + { + bool nodesExcluded = false; + for ( size_t i = 0; i < pbElems.size(); ++i ) + { + size_t prevNbMergeNodes = nodeNodeMap.size(); + if ( !applyMerge( pbElems[i], newElemDefs, nodeNodeMap, /*noHoles=*/true ) && + prevNbMergeNodes < nodeNodeMap.size() ) + nodesExcluded = true; + } + if ( !nodesExcluded ) + break; + } + } + + for ( nnIt = nodeNodeMap.begin(); nnIt != nodeNodeMap.end(); ++nnIt ) + { + const SMDS_MeshNode* nToRemove = nnIt->first; + const SMDS_MeshNode* nToKeep = nnIt->second; + if ( nToRemove != nToKeep ) + { + rmNodeIds.push_back( nToRemove->GetID() ); + AddToSameGroups( nToKeep, nToRemove, mesh ); + // set _alwaysComputed to a sub-mesh of VERTEX to enable further mesh computing + // w/o creating node in place of merged ones. + const SMDS_PositionPtr& pos = nToRemove->GetPosition(); + if ( pos && pos->GetTypeOfPosition() == SMDS_TOP_VERTEX ) + if ( SMESH_subMesh* sm = myMesh->GetSubMeshContaining( nToRemove->getshapeId() )) + sm->SetIsAlwaysComputed( true ); + } + } + + // Change element nodes or remove an element set::iterator eIt = elems.begin(); for ( ; eIt != elems.end(); eIt++ ) { const SMDS_MeshElement* elem = *eIt; - const int nbNodes = elem->NbNodes(); - const int aShapeId = FindShape( elem ); - SMDSAbs_EntityType entity = elem->GetEntityType(); + SMESHDS_SubMesh* sm = mesh->MeshElements( elem->getshapeId() ); - nodeSet.clear(); - curNodes.resize( nbNodes ); - uniqueNodes.resize( nbNodes ); - iRepl.resize( nbNodes ); - int iUnique = 0, iCur = 0, nbRepl = 0; + bool keepElem = applyMerge( elem, newElemDefs, nodeNodeMap, /*noHoles=*/false ); + if ( !keepElem ) + rmElemIds.push_back( elem->GetID() ); - // get new seq of nodes - SMDS_ElemIteratorPtr itN = elem->nodesIterator(); - while ( itN->more() ) - { - const SMDS_MeshNode* n = static_cast( itN->next() ); - - TNodeNodeMap::iterator nnIt = nodeNodeMap.find( n ); - if ( nnIt != nodeNodeMap.end() ) { // n sticks - n = (*nnIt).second; - { ////////// BUG 0020185: begin - bool stopRecur = false; - set nodesRecur; - nodesRecur.insert(n); - while (!stopRecur) { - TNodeNodeMap::iterator nnIt_i = nodeNodeMap.find( n ); - if ( nnIt_i != nodeNodeMap.end() ) { // n sticks - n = (*nnIt_i).second; - if (!nodesRecur.insert(n).second) { - // error: recursive dependency - stopRecur = true; - } - } - else - stopRecur = true; - } - } ////////// BUG 0020185: end + for ( size_t i = 0; i < newElemDefs.size(); ++i ) + { + if ( i > 0 || !mesh->ChangeElementNodes( elem, & + newElemDefs[i].myNodes[0], + newElemDefs[i].myNodes.size() )) + { + if ( i == 0 ) + { + newElemDefs[i].SetID( elem->GetID() ); + mesh->RemoveFreeElement(elem, sm, /*fromGroups=*/false); + if ( !keepElem ) rmElemIds.pop_back(); + } + else + { + newElemDefs[i].SetID( -1 ); + } + SMDS_MeshElement* newElem = this->AddElement( newElemDefs[i].myNodes, newElemDefs[i] ); + if ( sm && newElem ) + sm->AddElement( newElem ); + if ( elem != newElem ) + ReplaceElemInGroups( elem, newElem, mesh ); } - curNodes[ iCur ] = n; - bool isUnique = nodeSet.insert( n ).second; - if ( isUnique ) - uniqueNodes[ iUnique++ ] = n; - else - iRepl[ nbRepl++ ] = iCur; - iCur++; } + } - // Analyse element topology after replacement + // Remove bad elements, then equal nodes (order important) + Remove( rmElemIds, false ); + Remove( rmNodeIds, true ); - bool isOk = true; - int nbUniqueNodes = nodeSet.size(); - if ( nbNodes != nbUniqueNodes ) // some nodes stick - { - if ( elem->IsPoly() ) // Polygons and Polyhedral volumes - { - if ( elem->GetType() == SMDSAbs_Face ) // Polygon - { - elemType.Init( elem ); - const bool isQuad = elemType.myIsQuad; - if ( isQuad ) - SMDS_MeshCell::applyInterlace // interlace medium and corner nodes - ( SMDS_MeshCell::interlacedSmdsOrder( SMDSEntity_Quad_Polygon, nbNodes ), curNodes ); - - // a polygon can divide into several elements - vector polygons_nodes; - vector quantities; - int nbNew = SimplifyFace( curNodes, polygons_nodes, quantities ); - if (nbNew > 0) - { - vector face_nodes; - int inode = 0; - for (int iface = 0; iface < nbNew; iface++) - { - int nbNewNodes = quantities[iface]; - face_nodes.assign( polygons_nodes.begin() + inode, - polygons_nodes.begin() + inode + nbNewNodes ); - inode += nbNewNodes; - if ( isQuad ) // check if a result elem is a valid quadratic polygon - { - bool isValid = ( nbNewNodes % 2 == 0 ); - for ( int i = 0; i < nbNewNodes && isValid; ++i ) - isValid = ( elem->IsMediumNode( face_nodes[i]) == bool( i % 2 )); - elemType.SetQuad( isValid ); - if ( isValid ) // put medium nodes after corners - SMDS_MeshCell::applyInterlaceRev - ( SMDS_MeshCell::interlacedSmdsOrder( SMDSEntity_Quad_Polygon, - nbNewNodes ), face_nodes ); - } - elemType.SetPoly(( nbNewNodes / ( elemType.myIsQuad + 1 ) > 4 )); + return; +} - SMDS_MeshElement* newElem = AddElement( face_nodes, elemType.SetID(-1)); - if ( aShapeId ) - aMesh->SetMeshElementOnShape(newElem, aShapeId); - } - } - rmElemIds.push_back(elem->GetID()); +//======================================================================= +//function : applyMerge +//purpose : Compute new connectivity of an element after merging nodes +// \param [in] elems - the element +// \param [out] newElemDefs - definition(s) of result element(s) +// \param [inout] nodeNodeMap - nodes to merge +// \param [in] avoidMakingHoles - if true and and the element becomes invalid +// after merging (but not degenerated), removes nodes causing +// the invalidity from \a nodeNodeMap. +// \return bool - true if the element should be removed +//======================================================================= - } // Polygon +bool SMESH_MeshEditor::applyMerge( const SMDS_MeshElement* elem, + vector< ElemFeatures >& newElemDefs, + TNodeNodeMap& nodeNodeMap, + const bool avoidMakingHoles ) +{ + bool toRemove = false; // to remove elem + int nbResElems = 1; // nb new elements - else if ( elem->GetType() == SMDSAbs_Volume ) // Polyhedral volume - { - if ( nbUniqueNodes < 4 ) { - rmElemIds.push_back(elem->GetID()); - } - else { - // each face has to be analyzed in order to check volume validity - const SMDS_VtkVolume* aPolyedre = dynamic_cast( elem ); - if ( aPolyedre ) - { - int nbFaces = aPolyedre->NbFaces(); + newElemDefs.resize(nbResElems); + newElemDefs[0].Init( elem ); + newElemDefs[0].myNodes.clear(); - vector poly_nodes; - vector quantities; - vector faceNodes; + set nodeSet; + vector< const SMDS_MeshNode*> curNodes; + vector< const SMDS_MeshNode*> & uniqueNodes = newElemDefs[0].myNodes; + vector iRepl; - for (int iface = 1; iface <= nbFaces; iface++) - { - int nbFaceNodes = aPolyedre->NbFaceNodes(iface); - faceNodes.resize( nbFaceNodes ); - for (int inode = 1; inode <= nbFaceNodes; inode++) - { - const SMDS_MeshNode * faceNode = aPolyedre->GetFaceNode(iface, inode); - TNodeNodeMap::iterator nnIt = nodeNodeMap.find(faceNode); - if ( nnIt != nodeNodeMap.end() ) // faceNode sticks - faceNode = (*nnIt).second; - faceNodes[inode - 1] = faceNode; - } - SimplifyFace(faceNodes, poly_nodes, quantities); - } + const int nbNodes = elem->NbNodes(); + SMDSAbs_EntityType entity = elem->GetEntityType(); - if ( quantities.size() > 3 ) { - // TODO: remove coincident faces - } + curNodes.resize( nbNodes ); + uniqueNodes.resize( nbNodes ); + iRepl.resize( nbNodes ); + int iUnique = 0, iCur = 0, nbRepl = 0; - if ( quantities.size() > 3 ) - { - const SMDS_MeshElement* newElem = - aMesh->AddPolyhedralVolume( poly_nodes, quantities ); - myLastCreatedElems.Append( newElem ); - if ( aShapeId && newElem ) - aMesh->SetMeshElementOnShape( newElem, aShapeId ); - rmElemIds.push_back( elem->GetID() ); - } - } - else { - rmElemIds.push_back( elem->GetID() ); - } - } - } - else { - } + // Get new seq of nodes - continue; - } // poly element + SMDS_ElemIteratorPtr itN = elem->nodesIterator(); + while ( itN->more() ) + { + const SMDS_MeshNode* n = static_cast( itN->next() ); - // Regular elements - // TODO not all the possible cases are solved. Find something more generic? - switch ( entity ) { - case SMDSEntity_Edge: //////// EDGE - case SMDSEntity_Triangle: //// TRIANGLE - case SMDSEntity_Quad_Triangle: - case SMDSEntity_Tetra: - case SMDSEntity_Quad_Tetra: // TETRAHEDRON - { - isOk = false; - break; - } - case SMDSEntity_Quad_Edge: - { - isOk = false; // to linear EDGE ??????? - break; - } - case SMDSEntity_Quadrangle: //////////////////////////////////// QUADRANGLE + TNodeNodeMap::iterator nnIt = nodeNodeMap.find( n ); + if ( nnIt != nodeNodeMap.end() ) { + n = (*nnIt).second; + } + curNodes[ iCur ] = n; + bool isUnique = nodeSet.insert( n ).second; + if ( isUnique ) + uniqueNodes[ iUnique++ ] = n; + else + iRepl[ nbRepl++ ] = iCur; + iCur++; + } + + // Analyse element topology after replacement + + int nbUniqueNodes = nodeSet.size(); + if ( nbNodes != nbUniqueNodes ) // some nodes stick + { + toRemove = true; + nbResElems = 0; + + switch ( entity ) + { + case SMDSEntity_Polygon: + case SMDSEntity_Quad_Polygon: // Polygon + { + ElemFeatures* elemType = & newElemDefs[0]; + const bool isQuad = elemType->myIsQuad; + if ( isQuad ) + SMDS_MeshCell::applyInterlace // interlace medium and corner nodes + ( SMDS_MeshCell::interlacedSmdsOrder( SMDSEntity_Quad_Polygon, nbNodes ), curNodes ); + + // a polygon can divide into several elements + vector polygons_nodes; + vector quantities; + nbResElems = SimplifyFace( curNodes, polygons_nodes, quantities ); + newElemDefs.resize( nbResElems ); + for ( int inode = 0, iface = 0; iface < nbResElems; iface++ ) { - if ( nbUniqueNodes < 3 ) - isOk = false; - else if ( nbRepl == 1 && curNodes[ iRepl[0]] == curNodes[( iRepl[0]+2 )%4 ]) - isOk = false; // opposite nodes stick - break; - } - case SMDSEntity_Quad_Quadrangle: // Quadratic QUADRANGLE - { - // 1 5 2 - // +---+---+ - // | | - // 4+ +6 - // | | - // +---+---+ - // 0 7 3 - if (( nbUniqueNodes == 6 && nbRepl == 2 ) && - (( iRepl[0] == 1 && iRepl[1] == 4 && curNodes[1] == curNodes[0] ) || - ( iRepl[0] == 2 && iRepl[1] == 5 && curNodes[2] == curNodes[1] ) || - ( iRepl[0] == 3 && iRepl[1] == 6 && curNodes[3] == curNodes[2] ) || - ( iRepl[0] == 3 && iRepl[1] == 7 && curNodes[3] == curNodes[0] ))) - { - isOk = true; - } - break; - } - case SMDSEntity_BiQuad_Quadrangle: // Bi-Quadratic QUADRANGLE - { - // 1 5 2 - // +---+---+ - // | | - // 4+ 8+ +6 - // | | - // +---+---+ - // 0 7 3 - if (( nbUniqueNodes == 7 && nbRepl == 2 && iRepl[1] != 8 ) && - (( iRepl[0] == 1 && iRepl[1] == 4 && curNodes[1] == curNodes[0] ) || - ( iRepl[0] == 2 && iRepl[1] == 5 && curNodes[2] == curNodes[1] ) || - ( iRepl[0] == 3 && iRepl[1] == 6 && curNodes[3] == curNodes[2] ) || - ( iRepl[0] == 3 && iRepl[1] == 7 && curNodes[3] == curNodes[0] ))) + ElemFeatures* elemType = & newElemDefs[iface]; + if ( iface ) elemType->Init( elem ); + + vector& face_nodes = elemType->myNodes; + int nbNewNodes = quantities[iface]; + face_nodes.assign( polygons_nodes.begin() + inode, + polygons_nodes.begin() + inode + nbNewNodes ); + inode += nbNewNodes; + if ( isQuad ) // check if a result elem is a valid quadratic polygon { - isOk = true; - } - break; - } - case SMDSEntity_Penta: ///////////////////////////////////// PENTAHEDRON + bool isValid = ( nbNewNodes % 2 == 0 ); + for ( int i = 0; i < nbNewNodes && isValid; ++i ) + isValid = ( elem->IsMediumNode( face_nodes[i]) == bool( i % 2 )); + elemType->SetQuad( isValid ); + if ( isValid ) // put medium nodes after corners + SMDS_MeshCell::applyInterlaceRev + ( SMDS_MeshCell::interlacedSmdsOrder( SMDSEntity_Quad_Polygon, + nbNewNodes ), face_nodes ); + } + elemType->SetPoly(( nbNewNodes / ( elemType->myIsQuad + 1 ) > 4 )); + } + nbUniqueNodes = newElemDefs[0].myNodes.size(); + break; + } // Polygon + + case SMDSEntity_Polyhedra: // Polyhedral volume + { + if ( nbUniqueNodes >= 4 ) { - isOk = false; - if ( nbUniqueNodes == 4 ) { - // ---------------------------------> tetrahedron - if ( curNodes[3] == curNodes[4] && - curNodes[3] == curNodes[5] ) { - // top nodes stick - isOk = true; - } - else if ( curNodes[0] == curNodes[1] && - curNodes[0] == curNodes[2] ) { - // bottom nodes stick: set a top before - uniqueNodes[ 3 ] = uniqueNodes [ 0 ]; - uniqueNodes[ 0 ] = curNodes [ 5 ]; - uniqueNodes[ 1 ] = curNodes [ 4 ]; - uniqueNodes[ 2 ] = curNodes [ 3 ]; - isOk = true; - } - else if (( curNodes[0] == curNodes[3] ) + - ( curNodes[1] == curNodes[4] ) + - ( curNodes[2] == curNodes[5] ) == 2 ) { - // a lateral face turns into a line - isOk = true; - } - } - else if ( nbUniqueNodes == 5 ) { - // PENTAHEDRON --------------------> pyramid - if ( curNodes[0] == curNodes[3] ) - { - uniqueNodes[ 0 ] = curNodes[ 1 ]; - uniqueNodes[ 1 ] = curNodes[ 4 ]; - uniqueNodes[ 2 ] = curNodes[ 5 ]; - uniqueNodes[ 3 ] = curNodes[ 2 ]; - uniqueNodes[ 4 ] = curNodes[ 0 ]; - isOk = true; - } - if ( curNodes[1] == curNodes[4] ) + // each face has to be analyzed in order to check volume validity + if ( const SMDS_VtkVolume* aPolyedre = dynamic_cast( elem )) + { + int nbFaces = aPolyedre->NbFaces(); + + vector& poly_nodes = newElemDefs[0].myNodes; + vector & quantities = newElemDefs[0].myPolyhedQuantities; + vector faceNodes; + poly_nodes.clear(); + quantities.clear(); + + for (int iface = 1; iface <= nbFaces; iface++) { - uniqueNodes[ 0 ] = curNodes[ 0 ]; - uniqueNodes[ 1 ] = curNodes[ 2 ]; - uniqueNodes[ 2 ] = curNodes[ 5 ]; - uniqueNodes[ 3 ] = curNodes[ 3 ]; - uniqueNodes[ 4 ] = curNodes[ 1 ]; - isOk = true; + int nbFaceNodes = aPolyedre->NbFaceNodes(iface); + faceNodes.resize( nbFaceNodes ); + for (int inode = 1; inode <= nbFaceNodes; inode++) + { + const SMDS_MeshNode * faceNode = aPolyedre->GetFaceNode(iface, inode); + TNodeNodeMap::iterator nnIt = nodeNodeMap.find(faceNode); + if ( nnIt != nodeNodeMap.end() ) // faceNode sticks + faceNode = (*nnIt).second; + faceNodes[inode - 1] = faceNode; + } + SimplifyFace(faceNodes, poly_nodes, quantities); } - if ( curNodes[2] == curNodes[5] ) + + if ( quantities.size() > 3 ) { - uniqueNodes[ 0 ] = curNodes[ 0 ]; - uniqueNodes[ 1 ] = curNodes[ 3 ]; - uniqueNodes[ 2 ] = curNodes[ 4 ]; - uniqueNodes[ 3 ] = curNodes[ 1 ]; - uniqueNodes[ 4 ] = curNodes[ 2 ]; - isOk = true; + // TODO: remove coincident faces + nbResElems = 1; + nbUniqueNodes = newElemDefs[0].myNodes.size(); } } - break; } - case SMDSEntity_Hexa: + } + break; + + // Regular elements + // TODO not all the possible cases are solved. Find something more generic? + case SMDSEntity_Edge: //////// EDGE + case SMDSEntity_Triangle: //// TRIANGLE + case SMDSEntity_Quad_Triangle: + case SMDSEntity_Tetra: + case SMDSEntity_Quad_Tetra: // TETRAHEDRON + { + break; + } + case SMDSEntity_Quad_Edge: + { + break; + } + case SMDSEntity_Quadrangle: //////////////////////////////////// QUADRANGLE + { + if ( nbUniqueNodes < 3 ) + toRemove = true; + else if ( nbRepl == 1 && curNodes[ iRepl[0]] == curNodes[( iRepl[0]+2 )%4 ]) + toRemove = true; // opposite nodes stick + else + toRemove = false; + break; + } + case SMDSEntity_Quad_Quadrangle: // Quadratic QUADRANGLE + { + // 1 5 2 + // +---+---+ + // | | + // 4+ +6 + // | | + // +---+---+ + // 0 7 3 + if (( nbUniqueNodes == 6 && nbRepl == 2 ) && + (( iRepl[0] == 1 && iRepl[1] == 4 && curNodes[1] == curNodes[0] ) || + ( iRepl[0] == 2 && iRepl[1] == 5 && curNodes[2] == curNodes[1] ) || + ( iRepl[0] == 3 && iRepl[1] == 6 && curNodes[3] == curNodes[2] ) || + ( iRepl[0] == 3 && iRepl[1] == 7 && curNodes[3] == curNodes[0] ))) { - //////////////////////////////////// HEXAHEDRON - isOk = false; - SMDS_VolumeTool hexa (elem); - hexa.SetExternalNormal(); - if ( nbUniqueNodes == 4 && nbRepl == 4 ) { - //////////////////////// HEX ---> tetrahedron - for ( int iFace = 0; iFace < 6; iFace++ ) { - const int *ind = hexa.GetFaceNodesIndices( iFace ); // indices of face nodes - if (curNodes[ind[ 0 ]] == curNodes[ind[ 1 ]] && - curNodes[ind[ 0 ]] == curNodes[ind[ 2 ]] && - curNodes[ind[ 0 ]] == curNodes[ind[ 3 ]] ) { - // one face turns into a point ... - int pickInd = ind[ 0 ]; - int iOppFace = hexa.GetOppFaceIndex( iFace ); - ind = hexa.GetFaceNodesIndices( iOppFace ); - int nbStick = 0; - uniqueNodes.clear(); - for ( iCur = 0; iCur < 4 && nbStick < 2; iCur++ ) { - if ( curNodes[ind[ iCur ]] == curNodes[ind[ iCur + 1 ]] ) - nbStick++; - else - uniqueNodes.push_back( curNodes[ind[ iCur ]]); - } - if ( nbStick == 1 ) { - // ... and the opposite one - into a triangle. - // set a top node - uniqueNodes.push_back( curNodes[ pickInd ]); - isOk = true; - } - break; - } - } + toRemove = false; + } + break; + } + case SMDSEntity_BiQuad_Quadrangle: // Bi-Quadratic QUADRANGLE + { + // 1 5 2 + // +---+---+ + // | | + // 4+ 8+ +6 + // | | + // +---+---+ + // 0 7 3 + if (( nbUniqueNodes == 7 && nbRepl == 2 && iRepl[1] != 8 ) && + (( iRepl[0] == 1 && iRepl[1] == 4 && curNodes[1] == curNodes[0] ) || + ( iRepl[0] == 2 && iRepl[1] == 5 && curNodes[2] == curNodes[1] ) || + ( iRepl[0] == 3 && iRepl[1] == 6 && curNodes[3] == curNodes[2] ) || + ( iRepl[0] == 3 && iRepl[1] == 7 && curNodes[3] == curNodes[0] ))) + { + toRemove = false; + } + break; + } + case SMDSEntity_Penta: ///////////////////////////////////// PENTAHEDRON + { + if ( nbUniqueNodes == 4 ) { + // ---------------------------------> tetrahedron + if ( curNodes[3] == curNodes[4] && + curNodes[3] == curNodes[5] ) { + // top nodes stick + toRemove = false; + } + else if ( curNodes[0] == curNodes[1] && + curNodes[0] == curNodes[2] ) { + // bottom nodes stick: set a top before + uniqueNodes[ 3 ] = uniqueNodes [ 0 ]; + uniqueNodes[ 0 ] = curNodes [ 5 ]; + uniqueNodes[ 1 ] = curNodes [ 4 ]; + uniqueNodes[ 2 ] = curNodes [ 3 ]; + toRemove = false; + } + else if (( curNodes[0] == curNodes[3] ) + + ( curNodes[1] == curNodes[4] ) + + ( curNodes[2] == curNodes[5] ) == 2 ) { + // a lateral face turns into a line + toRemove = false; + } + } + else if ( nbUniqueNodes == 5 ) { + // PENTAHEDRON --------------------> pyramid + if ( curNodes[0] == curNodes[3] ) + { + uniqueNodes[ 0 ] = curNodes[ 1 ]; + uniqueNodes[ 1 ] = curNodes[ 4 ]; + uniqueNodes[ 2 ] = curNodes[ 5 ]; + uniqueNodes[ 3 ] = curNodes[ 2 ]; + uniqueNodes[ 4 ] = curNodes[ 0 ]; + toRemove = false; + } + if ( curNodes[1] == curNodes[4] ) + { + uniqueNodes[ 0 ] = curNodes[ 0 ]; + uniqueNodes[ 1 ] = curNodes[ 2 ]; + uniqueNodes[ 2 ] = curNodes[ 5 ]; + uniqueNodes[ 3 ] = curNodes[ 3 ]; + uniqueNodes[ 4 ] = curNodes[ 1 ]; + toRemove = false; + } + if ( curNodes[2] == curNodes[5] ) + { + uniqueNodes[ 0 ] = curNodes[ 0 ]; + uniqueNodes[ 1 ] = curNodes[ 3 ]; + uniqueNodes[ 2 ] = curNodes[ 4 ]; + uniqueNodes[ 3 ] = curNodes[ 1 ]; + uniqueNodes[ 4 ] = curNodes[ 2 ]; + toRemove = false; } - else if ( nbUniqueNodes == 6 && nbRepl == 2 ) { - //////////////////////// HEX ---> prism - int nbTria = 0, iTria[3]; - const int *ind; // indices of face nodes - // look for triangular faces - for ( int iFace = 0; iFace < 6 && nbTria < 3; iFace++ ) { - ind = hexa.GetFaceNodesIndices( iFace ); - TIDSortedNodeSet faceNodes; - for ( iCur = 0; iCur < 4; iCur++ ) - faceNodes.insert( curNodes[ind[iCur]] ); - if ( faceNodes.size() == 3 ) - iTria[ nbTria++ ] = iFace; - } - // check if triangles are opposite - if ( nbTria == 2 && iTria[0] == hexa.GetOppFaceIndex( iTria[1] )) - { - // set nodes of the bottom triangle - ind = hexa.GetFaceNodesIndices( iTria[ 0 ]); - vector indB; - for ( iCur = 0; iCur < 4; iCur++ ) - if ( ind[iCur] != iRepl[0] && ind[iCur] != iRepl[1]) - indB.push_back( ind[iCur] ); - if ( !hexa.IsForward() ) - std::swap( indB[0], indB[2] ); - for ( iCur = 0; iCur < 3; iCur++ ) - uniqueNodes[ iCur ] = curNodes[indB[iCur]]; - // set nodes of the top triangle - const int *indT = hexa.GetFaceNodesIndices( iTria[ 1 ]); - for ( iCur = 0; iCur < 3; ++iCur ) - for ( int j = 0; j < 4; ++j ) - if ( hexa.IsLinked( indB[ iCur ], indT[ j ] )) - { - uniqueNodes[ iCur + 3 ] = curNodes[ indT[ j ]]; - break; - } - isOk = true; + } + break; + } + case SMDSEntity_Hexa: + { + //////////////////////////////////// HEXAHEDRON + SMDS_VolumeTool hexa (elem); + hexa.SetExternalNormal(); + if ( nbUniqueNodes == 4 && nbRepl == 4 ) { + //////////////////////// HEX ---> tetrahedron + for ( int iFace = 0; iFace < 6; iFace++ ) { + const int *ind = hexa.GetFaceNodesIndices( iFace ); // indices of face nodes + if (curNodes[ind[ 0 ]] == curNodes[ind[ 1 ]] && + curNodes[ind[ 0 ]] == curNodes[ind[ 2 ]] && + curNodes[ind[ 0 ]] == curNodes[ind[ 3 ]] ) { + // one face turns into a point ... + int pickInd = ind[ 0 ]; + int iOppFace = hexa.GetOppFaceIndex( iFace ); + ind = hexa.GetFaceNodesIndices( iOppFace ); + int nbStick = 0; + uniqueNodes.clear(); + for ( iCur = 0; iCur < 4 && nbStick < 2; iCur++ ) { + if ( curNodes[ind[ iCur ]] == curNodes[ind[ iCur + 1 ]] ) + nbStick++; + else + uniqueNodes.push_back( curNodes[ind[ iCur ]]); + } + if ( nbStick == 1 ) { + // ... and the opposite one - into a triangle. + // set a top node + uniqueNodes.push_back( curNodes[ pickInd ]); + toRemove = false; + } break; } } - else if (nbUniqueNodes == 5 && nbRepl == 3 ) { - //////////////////// HEXAHEDRON ---> pyramid - for ( int iFace = 0; iFace < 6; iFace++ ) { - const int *ind = hexa.GetFaceNodesIndices( iFace ); // indices of face nodes - if (curNodes[ind[ 0 ]] == curNodes[ind[ 1 ]] && - curNodes[ind[ 0 ]] == curNodes[ind[ 2 ]] && - curNodes[ind[ 0 ]] == curNodes[ind[ 3 ]] ) { - // one face turns into a point ... - int iOppFace = hexa.GetOppFaceIndex( iFace ); - ind = hexa.GetFaceNodesIndices( iOppFace ); - uniqueNodes.clear(); - for ( iCur = 0; iCur < 4; iCur++ ) { - if ( curNodes[ind[ iCur ]] == curNodes[ind[ iCur + 1 ]] ) - break; - else - uniqueNodes.push_back( curNodes[ind[ iCur ]]); - } - if ( uniqueNodes.size() == 4 ) { - // ... and the opposite one is a quadrangle - // set a top node - const int* indTop = hexa.GetFaceNodesIndices( iFace ); - uniqueNodes.push_back( curNodes[indTop[ 0 ]]); - isOk = true; + } + else if ( nbUniqueNodes == 6 && nbRepl == 2 ) { + //////////////////////// HEX ---> prism + int nbTria = 0, iTria[3]; + const int *ind; // indices of face nodes + // look for triangular faces + for ( int iFace = 0; iFace < 6 && nbTria < 3; iFace++ ) { + ind = hexa.GetFaceNodesIndices( iFace ); + TIDSortedNodeSet faceNodes; + for ( iCur = 0; iCur < 4; iCur++ ) + faceNodes.insert( curNodes[ind[iCur]] ); + if ( faceNodes.size() == 3 ) + iTria[ nbTria++ ] = iFace; + } + // check if triangles are opposite + if ( nbTria == 2 && iTria[0] == hexa.GetOppFaceIndex( iTria[1] )) + { + // set nodes of the bottom triangle + ind = hexa.GetFaceNodesIndices( iTria[ 0 ]); + vector indB; + for ( iCur = 0; iCur < 4; iCur++ ) + if ( ind[iCur] != iRepl[0] && ind[iCur] != iRepl[1]) + indB.push_back( ind[iCur] ); + if ( !hexa.IsForward() ) + std::swap( indB[0], indB[2] ); + for ( iCur = 0; iCur < 3; iCur++ ) + uniqueNodes[ iCur ] = curNodes[indB[iCur]]; + // set nodes of the top triangle + const int *indT = hexa.GetFaceNodesIndices( iTria[ 1 ]); + for ( iCur = 0; iCur < 3; ++iCur ) + for ( int j = 0; j < 4; ++j ) + if ( hexa.IsLinked( indB[ iCur ], indT[ j ] )) + { + uniqueNodes[ iCur + 3 ] = curNodes[ indT[ j ]]; + break; } - break; + toRemove = false; + break; + } + } + else if (nbUniqueNodes == 5 && nbRepl == 3 ) { + //////////////////// HEXAHEDRON ---> pyramid + for ( int iFace = 0; iFace < 6; iFace++ ) { + const int *ind = hexa.GetFaceNodesIndices( iFace ); // indices of face nodes + if (curNodes[ind[ 0 ]] == curNodes[ind[ 1 ]] && + curNodes[ind[ 0 ]] == curNodes[ind[ 2 ]] && + curNodes[ind[ 0 ]] == curNodes[ind[ 3 ]] ) { + // one face turns into a point ... + int iOppFace = hexa.GetOppFaceIndex( iFace ); + ind = hexa.GetFaceNodesIndices( iOppFace ); + uniqueNodes.clear(); + for ( iCur = 0; iCur < 4; iCur++ ) { + if ( curNodes[ind[ iCur ]] == curNodes[ind[ iCur + 1 ]] ) + break; + else + uniqueNodes.push_back( curNodes[ind[ iCur ]]); } + if ( uniqueNodes.size() == 4 ) { + // ... and the opposite one is a quadrangle + // set a top node + const int* indTop = hexa.GetFaceNodesIndices( iFace ); + uniqueNodes.push_back( curNodes[indTop[ 0 ]]); + toRemove = false; + } + break; } } + } - if ( !isOk && nbUniqueNodes > 4 ) { - ////////////////// HEXAHEDRON ---> polyhedron - hexa.SetExternalNormal(); - vector poly_nodes; poly_nodes.reserve( 6 * 4 ); - vector quantities; quantities.reserve( 6 ); - for ( int iFace = 0; iFace < 6; iFace++ ) + if ( toRemove && nbUniqueNodes > 4 ) { + ////////////////// HEXAHEDRON ---> polyhedron + hexa.SetExternalNormal(); + vector& poly_nodes = newElemDefs[0].myNodes; + vector & quantities = newElemDefs[0].myPolyhedQuantities; + poly_nodes.reserve( 6 * 4 ); poly_nodes.clear(); + quantities.reserve( 6 ); quantities.clear(); + for ( int iFace = 0; iFace < 6; iFace++ ) + { + const int *ind = hexa.GetFaceNodesIndices( iFace ); // indices of face nodes + if ( curNodes[ind[0]] == curNodes[ind[2]] || + curNodes[ind[1]] == curNodes[ind[3]] ) { - const int *ind = hexa.GetFaceNodesIndices( iFace ); // indices of face nodes - if ( curNodes[ind[0]] == curNodes[ind[2]] || - curNodes[ind[1]] == curNodes[ind[3]] ) - { - quantities.clear(); - break; // opposite nodes stick - } - nodeSet.clear(); - for ( iCur = 0; iCur < 4; iCur++ ) - { - if ( nodeSet.insert( curNodes[ind[ iCur ]] ).second ) - poly_nodes.push_back( curNodes[ind[ iCur ]]); - } - if ( nodeSet.size() < 3 ) - poly_nodes.resize( poly_nodes.size() - nodeSet.size() ); - else - quantities.push_back( nodeSet.size() ); + quantities.clear(); + break; // opposite nodes stick } - if ( quantities.size() >= 4 ) + nodeSet.clear(); + for ( iCur = 0; iCur < 4; iCur++ ) { - const SMDS_MeshElement* newElem = aMesh->AddPolyhedralVolume( poly_nodes, quantities ); - myLastCreatedElems.Append( newElem ); - if ( aShapeId && newElem ) - aMesh->SetMeshElementOnShape( newElem, aShapeId ); - rmElemIds.push_back( elem->GetID() ); + if ( nodeSet.insert( curNodes[ind[ iCur ]] ).second ) + poly_nodes.push_back( curNodes[ind[ iCur ]]); } + if ( nodeSet.size() < 3 ) + poly_nodes.resize( poly_nodes.size() - nodeSet.size() ); + else + quantities.push_back( nodeSet.size() ); } - break; - } // case HEXAHEDRON + if ( quantities.size() >= 4 ) + { + nbResElems = 1; + nbUniqueNodes = poly_nodes.size(); + newElemDefs[0].SetPoly(true); + } + } + break; + } // case HEXAHEDRON - default: - isOk = false; - } // switch ( nbNodes ) + default: + toRemove = true; - } // if ( nbNodes != nbUniqueNodes ) // some nodes stick + } // switch ( entity ) - if ( isOk ) // a non-poly elem remains valid after sticking nodes + if ( toRemove && nbResElems == 0 && avoidMakingHoles ) { - if ( nbNodes != nbUniqueNodes || - !aMesh->ChangeElementNodes( elem, & curNodes[0], nbNodes )) - { - elemType.Init( elem ).SetID( elem->GetID() ); - - SMESHDS_SubMesh * sm = aShapeId > 0 ? aMesh->MeshElements(aShapeId) : 0; - aMesh->RemoveFreeElement(elem, sm, /*fromGroups=*/false); - - uniqueNodes.resize(nbUniqueNodes); - SMDS_MeshElement* newElem = this->AddElement( uniqueNodes, elemType ); - if ( sm && newElem ) - sm->AddElement( newElem ); - if ( elem != newElem ) - ReplaceElemInGroups( elem, newElem, aMesh ); - } - } - else { - // Remove invalid regular element or invalid polygon - rmElemIds.push_back( elem->GetID() ); + // erase from nodeNodeMap nodes whose merge spoils elem + vector< const SMDS_MeshNode* > noMergeNodes; + SMESH_MeshAlgos::DeMerge( elem, curNodes, noMergeNodes ); + for ( size_t i = 0; i < noMergeNodes.size(); ++i ) + nodeNodeMap.erase( noMergeNodes[i] ); } + + } // if ( nbNodes != nbUniqueNodes ) // some nodes stick - } // loop on elements + uniqueNodes.resize( nbUniqueNodes ); - // Remove bad elements, then equal nodes (order important) + if ( !toRemove && nbResElems == 0 ) + nbResElems = 1; - Remove( rmElemIds, false ); - Remove( rmNodeIds, true ); + newElemDefs.resize( nbResElems ); - return; + return !toRemove; } diff --git a/src/SMESH/SMESH_MeshEditor.hxx b/src/SMESH/SMESH_MeshEditor.hxx index fd0418c6a..663b6ae16 100644 --- a/src/SMESH/SMESH_MeshEditor.hxx +++ b/src/SMESH/SMESH_MeshEditor.hxx @@ -83,11 +83,12 @@ public: // -------------------------------------------------------------------------------- struct ElemFeatures //!< Features of element to create { - SMDSAbs_ElementType myType; - bool myIsPoly, myIsQuad; - int myID; - double myBallDiameter; - std::vector myPolyhedQuantities; + SMDSAbs_ElementType myType; + bool myIsPoly, myIsQuad; + int myID; + double myBallDiameter; + std::vector myPolyhedQuantities; + std::vector myNodes; // not managed by ElemFeatures SMESH_EXPORT ElemFeatures( SMDSAbs_ElementType type=SMDSAbs_All, bool isPoly=false, bool isQuad=false ) :myType( type ), myIsPoly(isPoly), myIsQuad(isQuad), myID(-1), myBallDiameter(0) {} @@ -750,6 +751,20 @@ public: const size_t nbSteps, SMESH_SequenceOfElemPtr& srcElements); + /*! + * \brief Computes new connectivity of an element after merging nodes + * \param [in] elems - the element + * \param [out] newElemDefs - definition(s) of result element(s) + * \param [inout] nodeNodeMap - nodes to merge + * \param [in] avoidMakingHoles - if true and and the element becomes invalid + * after merging (but not degenerated), removes nodes causing + * the invalidity from \a nodeNodeMap. + * \return bool - true if the element should be removed + */ + bool applyMerge( const SMDS_MeshElement* elems, + std::vector< ElemFeatures >& newElemDefs, + TNodeNodeMap& nodeNodeMap, + const bool avoidMakingHoles ); /*! * \brief Create 1D and 2D elements around swept elements * \param mapNewNodes - source nodes and ones generated from them @@ -782,11 +797,11 @@ public: double Angle ()const { return myAngle; } double Parameter ()const { return myPrm; } }; - Extrusion_Error MakeEdgePathPoints(std::list& aPrms, + Extrusion_Error makeEdgePathPoints(std::list& aPrms, const TopoDS_Edge& aTrackEdge, bool aFirstIsStart, std::list& aLPP); - Extrusion_Error MakeExtrElements(TIDSortedElemSet theElements[2], + Extrusion_Error makeExtrElements(TIDSortedElemSet theElements[2], std::list& theFullList, const bool theHasAngles, std::list& theAngles, @@ -794,7 +809,7 @@ public: const bool theHasRefPoint, const gp_Pnt& theRefPoint, const bool theMakeGroups); - static void LinearAngleVariation(const int NbSteps, + static void linearAngleVariation(const int NbSteps, std::list& theAngles); bool doubleNodes( SMESHDS_Mesh* theMeshDS, diff --git a/src/SMESHGUI/SMESHGUI.cxx b/src/SMESHGUI/SMESHGUI.cxx index 41d4c42bd..1f3435241 100644 --- a/src/SMESHGUI/SMESHGUI.cxx +++ b/src/SMESHGUI/SMESHGUI.cxx @@ -215,29 +215,34 @@ namespace QStringList filter; std::string myExtension; - if ( theCommandID == SMESHOp::OpImportMED ) { + if ( theCommandID == SMESHOp::OpImportMED || + theCommandID == SMESHOp::OpPopupImportMED ) { filter.append( QObject::tr( "MED_FILES_FILTER" ) + " (*.*med)" ); filter.append( QObject::tr( "ALL_FILES_FILTER" ) + " (*)" ); } - else if ( theCommandID == SMESHOp::OpImportUNV ) { + else if ( theCommandID == SMESHOp::OpImportUNV || + theCommandID == SMESHOp::OpPopupImportUNV ) { filter.append( QObject::tr( "IDEAS_FILES_FILTER" ) + " (*.unv)" ); } - else if ( theCommandID == SMESHOp::OpImportDAT ) { + else if ( theCommandID == SMESHOp::OpImportDAT || + theCommandID == SMESHOp::OpPopupImportDAT ) { filter.append( QObject::tr( "DAT_FILES_FILTER" ) + " (*.dat)" ); } - else if ( theCommandID == SMESHOp::OpImportSTL ) { + else if ( theCommandID == SMESHOp::OpImportSTL || + theCommandID == SMESHOp::OpPopupImportSTL ) { filter.append( QObject::tr( "STL_FILES_FILTER" ) + " (*.stl)" ); } - #ifdef WITH_CGNS - else if ( theCommandID == SMESHOp::OpImportCGNS ) { + else if ( theCommandID == SMESHOp::OpImportCGNS || + theCommandID == SMESHOp::OpPopupImportCGNS ) { filter.append( QObject::tr( "CGNS_FILES_FILTER" ) + " (*.cgns)" ); } - #endif - else if ( theCommandID == SMESHOp::OpImportSAUV ) { + else if ( theCommandID == SMESHOp::OpImportSAUV || + theCommandID == SMESHOp::OpPopupImportSAUV ) { filter.append( QObject::tr( "SAUV files (*.sauv*)" ) ); filter.append( QObject::tr( "All files (*)" ) ); } - else if ( theCommandID == SMESHOp::OpImportGMF ) { + else if ( theCommandID == SMESHOp::OpImportGMF || + theCommandID == SMESHOp::OpPopupImportGMF ) { filter.append( QObject::tr( "GMF_ASCII_FILES_FILTER" ) + " (*.mesh)" ); filter.append( QObject::tr( "GMF_BINARY_FILES_FILTER") + " (*.meshb)" ); } @@ -283,6 +288,7 @@ namespace try { switch ( theCommandID ) { case SMESHOp::OpImportDAT: + case SMESHOp::OpPopupImportDAT: { // DAT format (currently unsupported) errors.append( QString( "%1 :\n\t%2" ).arg( filename ). @@ -290,6 +296,7 @@ namespace break; } case SMESHOp::OpImportUNV: + case SMESHOp::OpPopupImportUNV: { // UNV format aMeshes->length( 1 ); @@ -300,6 +307,7 @@ namespace break; } case SMESHOp::OpImportMED: + case SMESHOp::OpPopupImportMED: { // MED format SMESH::DriverMED_ReadStatus res; @@ -311,6 +319,7 @@ namespace break; } case SMESHOp::OpImportSTL: + case SMESHOp::OpPopupImportSTL: { // STL format aMeshes->length( 1 ); @@ -321,8 +330,8 @@ namespace } break; } - #ifdef WITH_CGNS case SMESHOp::OpImportCGNS: + case SMESHOp::OpPopupImportCGNS: { // CGNS format SMESH::DriverMED_ReadStatus res; @@ -333,8 +342,8 @@ namespace } break; } - #endif case SMESHOp::OpImportSAUV: + case SMESHOp::OpPopupImportSAUV: { // SAUV format SMESH::DriverMED_ReadStatus res; @@ -346,6 +355,7 @@ namespace break; } case SMESHOp::OpImportGMF: + case SMESHOp::OpPopupImportGMF: { // GMF format SMESH::ComputeError_var res; @@ -433,12 +443,8 @@ namespace theCommandID == SMESHOp::OpPopupExportUNV ); const bool isSTL = ( theCommandID == SMESHOp::OpExportSTL || theCommandID == SMESHOp::OpPopupExportSTL ); -#ifdef WITH_CGNS const bool isCGNS= ( theCommandID == SMESHOp::OpExportCGNS || theCommandID == SMESHOp::OpPopupExportCGNS ); -#else - const bool isCGNS= false; -#endif const bool isSAUV= ( theCommandID == SMESHOp::OpExportSAUV || theCommandID == SMESHOp::OpPopupExportSAUV ); const bool isGMF = ( theCommandID == SMESHOp::OpExportGMF || @@ -2451,11 +2457,16 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) case SMESHOp::OpImportUNV: case SMESHOp::OpImportMED: case SMESHOp::OpImportSTL: -#ifdef WITH_CGNS case SMESHOp::OpImportCGNS: -#endif case SMESHOp::OpImportSAUV: case SMESHOp::OpImportGMF: + case SMESHOp::OpPopupImportDAT: + case SMESHOp::OpPopupImportUNV: + case SMESHOp::OpPopupImportMED: + case SMESHOp::OpPopupImportSTL: + case SMESHOp::OpPopupImportCGNS: + case SMESHOp::OpPopupImportSAUV: + case SMESHOp::OpPopupImportGMF: { if(checkLock(aStudy)) break; ::ImportMeshesFromFile(GetSMESHGen(),theCommandID); @@ -2484,18 +2495,14 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) case SMESHOp::OpExportMED: case SMESHOp::OpExportUNV: case SMESHOp::OpExportSTL: -#ifdef WITH_CGNS case SMESHOp::OpExportCGNS: -#endif case SMESHOp::OpExportSAUV: case SMESHOp::OpExportGMF: case SMESHOp::OpPopupExportDAT: case SMESHOp::OpPopupExportMED: case SMESHOp::OpPopupExportUNV: case SMESHOp::OpPopupExportSTL: -#ifdef WITH_CGNS case SMESHOp::OpPopupExportCGNS: -#endif case SMESHOp::OpPopupExportSAUV: case SMESHOp::OpPopupExportGMF: { @@ -2671,9 +2678,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) extractContainers( sel_objects, to_process ); try { -#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 OCC_CATCH_SIGNALS; -#endif if (vtkwnd) { SALOME_ListIteratorOfListIO It( to_process ); for ( ; It.More(); It.Next()) @@ -3821,13 +3826,21 @@ void SMESHGUI::initialize( CAM_Application* app ) //createSMESHAction( SMESHOp::OpImportDAT, "IMPORT_DAT", "", (Qt::CTRL+Qt::Key_B) ); createSMESHAction( SMESHOp::OpImportUNV, "IMPORT_UNV", "", (Qt::CTRL+Qt::Key_I) ); createSMESHAction( SMESHOp::OpImportMED, "IMPORT_MED", "", (Qt::CTRL+Qt::Key_M) ); - //createSMESHAction( 114, "NUM" ); createSMESHAction( SMESHOp::OpImportSTL, "IMPORT_STL" ); #ifdef WITH_CGNS createSMESHAction( SMESHOp::OpImportCGNS, "IMPORT_CGNS" ); #endif createSMESHAction( SMESHOp::OpImportSAUV, "IMPORT_SAUV" ); createSMESHAction( SMESHOp::OpImportGMF, "IMPORT_GMF" ); + createSMESHAction( SMESHOp::OpPopupImportUNV, "IMPORT_UNV"); + createSMESHAction( SMESHOp::OpPopupImportMED, "IMPORT_MED"); + createSMESHAction( SMESHOp::OpPopupImportSTL, "IMPORT_STL" ); +#ifdef WITH_CGNS + createSMESHAction( SMESHOp::OpPopupImportCGNS, "IMPORT_CGNS" ); +#endif + createSMESHAction( SMESHOp::OpPopupImportSAUV, "IMPORT_SAUV" ); + createSMESHAction( SMESHOp::OpPopupImportGMF, "IMPORT_GMF" ); + createSMESHAction( SMESHOp::OpExportDAT, "DAT" ); createSMESHAction( SMESHOp::OpExportMED, "MED" ); createSMESHAction( SMESHOp::OpExportUNV, "UNV" ); @@ -4364,6 +4377,7 @@ void SMESHGUI::initialize( CAM_Application* app ) group = pat.arg( SMESHGUI_Selection::typeName( SMESH::GROUP ) ), hypo = pat.arg( SMESHGUI_Selection::typeName( SMESH::HYPOTHESIS ) ), algo = pat.arg( SMESHGUI_Selection::typeName( SMESH::ALGORITHM ) ), + smesh = pat.arg( SMESHGUI_Selection::typeName( SMESH::COMPONENT ) ), elems = QString( "'%1' '%2' '%3' '%4' '%5' '%6'" ). arg( SMESHGUI_Selection::typeName( SMESH::SUBMESH_VERTEX ) ). arg( SMESHGUI_Selection::typeName( SMESH::SUBMESH_EDGE ) ). @@ -4442,6 +4456,17 @@ void SMESHGUI::initialize( CAM_Application* app ) createPopupItem( SMESHOp::OpPopupExportDAT, OB, mesh_group, only_one_non_empty, anId ); createPopupItem( SMESHOp::OpDelete, OB, mesh_part + " " + hyp_alg ); createPopupItem( SMESHOp::OpDeleteGroup, OB, group ); + + anId = popupMgr()->insert( tr( "MEN_IMPORT" ), -1, -1 ); // IMPORT submenu + createPopupItem( SMESHOp::OpPopupImportMED, OB, smesh, "", anId ); + createPopupItem( SMESHOp::OpPopupImportUNV, OB, smesh, "", anId ); + createPopupItem( SMESHOp::OpPopupImportSTL, OB, smesh, "", anId ); +#ifdef WITH_CGNS + createPopupItem( SMESHOp::OpPopupImportCGNS, OB, smesh, "", anId ); +#endif + createPopupItem( SMESHOp::OpPopupImportSAUV, OB, smesh, "", anId ); + createPopupItem( SMESHOp::OpPopupImportGMF, OB, smesh, "", anId ); + createPopupItem( SMESHOp::OpPopupImportDAT, OB, smesh, "", anId ); popupMgr()->insert( separator(), -1, 0 ); // popup for viewer diff --git a/src/SMESHGUI/SMESHGUI_MergeDlg.cxx b/src/SMESHGUI/SMESHGUI_MergeDlg.cxx index e5dcf5d12..2aba558af 100644 --- a/src/SMESHGUI/SMESHGUI_MergeDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_MergeDlg.cxx @@ -191,6 +191,9 @@ SMESHGUI_MergeDlg::SMESHGUI_MergeDlg (SMESHGUI* theModule, int theAction) SeparateCornersAndMedium = new QCheckBox(tr("SEPARATE_CORNERS_AND_MEDIUM"), NodeSpecWidget ); SeparateCornersAndMedium->setEnabled( false ); + AvoidMakingHoles = new QCheckBox(tr("AVOID_MAKING_HOLES"), NodeSpecWidget ); + AvoidMakingHoles->setChecked( false ); + QGridLayout* NodeSpecLayout = new QGridLayout(NodeSpecWidget); NodeSpecLayout->setSpacing(SPACING); NodeSpecLayout->setMargin(0); @@ -198,6 +201,7 @@ SMESHGUI_MergeDlg::SMESHGUI_MergeDlg (SMESHGUI* theModule, int theAction) NodeSpecLayout->addWidget(TextLabelTolerance, 0, 0 ); NodeSpecLayout->addWidget(SpinBoxTolerance, 0, 1 ); NodeSpecLayout->addWidget(SeparateCornersAndMedium, 1, 0, 1, 2 ); + NodeSpecLayout->addWidget(AvoidMakingHoles, 2, 0, 1, 2 ); /***************************************************************/ // Exclude groups @@ -585,12 +589,12 @@ bool SMESHGUI_MergeDlg::ClickOnApply() } if( myAction == MERGE_NODES ) - aMeshEditor->MergeNodes (aGroupsOfElements.inout(), nodesToKeep); + aMeshEditor->MergeNodes( aGroupsOfElements.inout(), nodesToKeep, AvoidMakingHoles->isChecked() ); else - aMeshEditor->MergeElements (aGroupsOfElements.inout()); + aMeshEditor->MergeElements( aGroupsOfElements.inout() ); if ( myTypeId == TYPE_AUTO ) { - if (myAction == MERGE_NODES ) + if ( myAction == MERGE_NODES ) SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_INFORMATION"), tr("SMESH_MERGED_NODES").arg(QString::number(ListCoincident->count()).toLatin1().data())); else diff --git a/src/SMESHGUI/SMESHGUI_MergeDlg.h b/src/SMESHGUI/SMESHGUI_MergeDlg.h index 5e827abc8..6b087b631 100644 --- a/src/SMESHGUI/SMESHGUI_MergeDlg.h +++ b/src/SMESHGUI/SMESHGUI_MergeDlg.h @@ -130,6 +130,7 @@ private: QWidget* NodeSpecWidget; SMESHGUI_SpinBox* SpinBoxTolerance; QCheckBox* SeparateCornersAndMedium; + QCheckBox* AvoidMakingHoles; QGroupBox* GroupCoincident; //QWidget* GroupCoincidentWidget; diff --git a/src/SMESHGUI/SMESHGUI_Operations.h b/src/SMESHGUI/SMESHGUI_Operations.h index df810f7df..89f53472b 100644 --- a/src/SMESHGUI/SMESHGUI_Operations.h +++ b/src/SMESHGUI/SMESHGUI_Operations.h @@ -32,37 +32,36 @@ namespace SMESHOp { OpShowScalarBar = 1022, // SHOW SCALAR BAR OpSaveDistribution = 1030, // SAVE DISTRIBUTION OpShowDistribution = 1031, // SHOW DISTRIBUTION -#ifndef DISABLE_PLOT2DVIEWER OpPlotDistribution = 1032, // PLOT DISTRIBUTION -#endif OpFileInformation = 1040, // POPUP MENU - FILE INFORMATION // Import -------------------------//-------------------------------- OpImportDAT = 1100, // MENU FILE - IMPORT - DAT FILE OpImportUNV = 1101, // MENU FILE - IMPORT - UNV FILE OpImportMED = 1102, // MENU FILE - IMPORT - MED FILE OpImportSTL = 1103, // MENU FILE - IMPORT - STL FILE -#ifdef WITH_CGNS OpImportCGNS = 1104, // MENU FILE - IMPORT - CGNS FILE -#endif OpImportSAUV = 1105, // MENU FILE - IMPORT - SAUV FILE OpImportGMF = 1106, // MENU FILE - IMPORT - GMF FILE + OpPopupImportDAT = 1120, // POPUP MENU - IMPORT - DAT FILE + OpPopupImportUNV = 1121, // POPUP MENU - IMPORT - UNV FILE + OpPopupImportMED = 1122, // POPUP MENU - IMPORT - MED FILE + OpPopupImportSTL = 1123, // POPUP MENU - IMPORT - STL FILE + OpPopupImportCGNS = 1124, // POPUP MENU - IMPORT - CGNS FILE + OpPopupImportSAUV = 1125, // POPUP MENU - IMPORT - SAUV FILE + OpPopupImportGMF = 1126, // POPUP MENU - IMPORT - GMF FILE // Export -------------------------//-------------------------------- OpExportDAT = 1200, // MENU FILE - EXPORT - DAT FILE OpExportMED = 1201, // MENU FILE - EXPORT - MED FILE OpExportUNV = 1202, // MENU FILE - EXPORT - UNV FILE OpExportSTL = 1203, // MENU FILE - EXPORT - STL FILE -#ifdef WITH_CGNS OpExportCGNS = 1204, // MENU FILE - EXPORT - CGNS FILE -#endif OpExportSAUV = 1205, // MENU FILE - EXPORT - SAUV FILE OpExportGMF = 1206, // MENU FILE - EXPORT - GMF FILE OpPopupExportDAT = 1210, // POPUP MENU - EXPORT - DAT FILE OpPopupExportMED = 1211, // POPUP MENU - EXPORT - MED FILE OpPopupExportUNV = 1212, // POPUP MENU - EXPORT - UNV FILE OpPopupExportSTL = 1213, // POPUP MENU - EXPORT - STL FILE -#ifdef WITH_CGNS OpPopupExportCGNS = 1214, // POPUP MENU - EXPORT - CGNS FILE -#endif OpPopupExportSAUV = 1215, // POPUP MENU - EXPORT - SAUV FILE OpPopupExportGMF = 1216, // POPUP MENU - EXPORT - GMF FILE // Mesh ---------------------------//-------------------------------- diff --git a/src/SMESHGUI/SMESH_msg_en.ts b/src/SMESHGUI/SMESH_msg_en.ts index bbbccbcfd..2a0601830 100644 --- a/src/SMESHGUI/SMESH_msg_en.ts +++ b/src/SMESHGUI/SMESH_msg_en.ts @@ -5322,6 +5322,10 @@ Please select a group and try again SEPARATE_CORNERS_AND_MEDIUM No merge of corner and medium nodes of quadratic cells + + AVOID_MAKING_HOLES + Avoid making holes + KEEP_NODES Nodes to keep during the merge diff --git a/src/SMESHUtils/CMakeLists.txt b/src/SMESHUtils/CMakeLists.txt index c21a8a6d5..3641d913c 100644 --- a/src/SMESHUtils/CMakeLists.txt +++ b/src/SMESHUtils/CMakeLists.txt @@ -83,7 +83,8 @@ SET(SMESHUtils_SOURCES SMESH_MAT2d.cxx SMESH_FreeBorders.cxx SMESH_ControlPnt.cxx -) + SMESH_DeMerge.cxx + ) # --- rules --- diff --git a/src/SMESHUtils/SMESH_DeMerge.cxx b/src/SMESHUtils/SMESH_DeMerge.cxx new file mode 100644 index 000000000..427ce5270 --- /dev/null +++ b/src/SMESHUtils/SMESH_DeMerge.cxx @@ -0,0 +1,215 @@ +// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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 +// +// File : SMESH_DeMerge.hxx +// Created : Fri Mar 10 16:06:54 2017 +// Author : Edward AGAPOV (eap) + +// Implementation of SMESH_MeshAlgos::DeMerge() + +#include "SMESH_MeshAlgos.hxx" + +#include "SMDS_VolumeTool.hxx" +#include "SMDS_MeshVolume.hxx" + +namespace +{ + bool isDegenFace(const std::vector< const SMDS_MeshNode* >& nodes) + { + // in a degenerated face each link sticks to another + + typedef std::map< SMESH_TLink , int > TLink2Nb; + TLink2Nb link2nb; + for ( size_t iPrev = nodes.size() - 1, i = 0; i < nodes.size(); iPrev = i++ ) + { + SMESH_TLink link( nodes[iPrev], nodes[i] ); + TLink2Nb::iterator l2n = link2nb.insert( std::make_pair( link, 0 )).first; + l2n->second++; + } + + if ( link2nb.size() == 1 ) + return true; + + for ( TLink2Nb::iterator l2n = link2nb.begin(); l2n != link2nb.end(); ++l2n ) + if ( l2n->second == 1 ) + return false; + + return true; + } + + void deMergeFace(const SMDS_MeshElement* face, + std::vector< const SMDS_MeshNode* >& newNodes, + std::vector< const SMDS_MeshNode* >& noMergeNodes) + { + if ( face->IsQuadratic() ) + { + const int nbCorners = face->NbCornerNodes(); + const int nbNodes = (int) newNodes.size(); + + // de-merge sticking medium nodes + for ( int i = 1; i < nbNodes; i += 2 ) // loop om medium nodes + { + int iPrev = ( i - 1 ); + int iNext = ( i + 1 ) % nbNodes; + if ( newNodes[ iPrev ] == newNodes[ iNext ] ) + { + if ( newNodes[ iPrev ] != newNodes[ i ] || nbCorners == 3 ) + { + // corners stick but the medium does not, or a link of triangle collapses + noMergeNodes.push_back( face->GetNode( iPrev / 2 )); + noMergeNodes.push_back( face->GetNode( iNext / 2 )); + noMergeNodes.push_back( face->GetNode( nbCorners + i / 2 )); + } + } + else if ( newNodes[ i ] == newNodes[ iPrev ] ) + { + // the medium node sticks to a neighbor corner one + noMergeNodes.push_back( face->GetNode( nbCorners + i / 2 )); + noMergeNodes.push_back( face->GetNode( iPrev / 2 )); + } + else if ( newNodes[ i ] == newNodes[ iNext ] ) + { + // the medium node sticks to a neighbor corner one + noMergeNodes.push_back( face->GetNode( nbCorners + i / 2 )); + noMergeNodes.push_back( face->GetNode( iNext / 2 )); + } + else + { + // find if the medium sticks to any other node + std::vector::iterator pos; + pos = std::find( newNodes.begin(), newNodes.begin() + iPrev, newNodes[i] ); + if ( pos == newNodes.begin() + iPrev ) + pos = std::find( newNodes.begin() + i + 1, newNodes.end(), newNodes[i] ); + if ( pos == newNodes.end() ) + continue; + + int iStick = std::distance( newNodes.begin(), pos ); + if ( iStick % 2 == 0 ) + { + // the medium sticks to a distant corner + noMergeNodes.push_back( face->GetNode( nbCorners + i / 2 )); + noMergeNodes.push_back( face->GetNode( iStick / 2 )); + } + else + { + // the medium sticks to a distant medium; + // it's OK if two links stick + int iPrev2 = ( iStick - 1 ); + int iNext2 = ( iStick + 1 ) % nbNodes; + if (( newNodes[ iPrev ] == newNodes[ iPrev2 ] && + newNodes[ iNext ] == newNodes[ iNext2 ] ) + || + ( newNodes[ iPrev ] == newNodes[ iNext2 ] && + newNodes[ iNext ] == newNodes[ iPrev2 ] )) + ; // OK + else + { + noMergeNodes.push_back( face->GetNode( nbCorners + i / 2 )); + noMergeNodes.push_back( face->GetNode( nbCorners + iStick / 2 )); + } + } + } + } + } + } // deMergeFace() + + bool isDegenVolume(const SMDS_VolumeTool& vt) + { + // TMP: it's necessary to use a topological check instead of a geometrical one + return vt.GetSize() < 1e-100; + } + + void deMergeVolume(const SMDS_VolumeTool& vt, + std::vector< const SMDS_MeshNode* >& noMergeNodes) + { + // temporary de-merge all nodes + for ( int i = 0; i < vt.NbNodes(); ++i ) + { + const SMDS_MeshNode* n = vt.GetNodes()[i]; + if ( n != vt.Element()->GetNode( i )) + noMergeNodes.push_back( n ); + } + } + +} // namespace + +//================================================================================ +/*! + * \brief Find nodes whose merge makes the element invalid. (Degenerated elem is OK) + * \param [in] elem - the element + * \param [in] newNodes - nodes of the element after the merge + * \param [out] noMergeNodes - nodes to undo merge + */ +//================================================================================ + +void SMESH_MeshAlgos::DeMerge(const SMDS_MeshElement* elem, + std::vector< const SMDS_MeshNode* >& newNodes, + std::vector< const SMDS_MeshNode* >& noMergeNodes) +{ + switch ( elem->GetType() ) + { + case SMDSAbs_Face: + { + if ( newNodes.size() <= 4 ) + return; // degenerated + + if ( elem->IsQuadratic() ) + SMDS_MeshCell::applyInterlace // interlace medium and corner nodes + ( SMDS_MeshCell::interlacedSmdsOrder( elem->GetEntityType(), newNodes.size() ), newNodes ); + + if ( isDegenFace( newNodes )) + return; + + deMergeFace( elem, newNodes, noMergeNodes ); + } + break; + + case SMDSAbs_Volume: + { + if ( newNodes.size() <= 4 ) + return; // degenerated + + SMDS_VolumeTool vt; + if ( !vt.Set( elem, /*skipCentral=*/true, &newNodes )) + return; // strange + + if ( isDegenVolume( vt )) + return; + + deMergeVolume( elem, noMergeNodes ); + } + break; + + case SMDSAbs_Edge: + { + if ( newNodes.size() == 3 ) + if (( newNodes[2] == newNodes[0] && newNodes[2] != newNodes[1] ) || + ( newNodes[2] == newNodes[1] && newNodes[2] != newNodes[0])) + { + // the medium node sticks to a corner + noMergeNodes.push_back( newNodes[2] ); + noMergeNodes.push_back( newNodes[ newNodes[2] == newNodes[1] ]); + } + } + break; + default:; + } +} diff --git a/src/SMESHUtils/SMESH_MeshAlgos.hxx b/src/SMESHUtils/SMESH_MeshAlgos.hxx index b6c3661b0..1114bfe02 100644 --- a/src/SMESHUtils/SMESH_MeshAlgos.hxx +++ b/src/SMESHUtils/SMESH_MeshAlgos.hxx @@ -206,6 +206,16 @@ namespace SMESH_MeshAlgos CoincidentFreeBorders & foundFreeBordes); -} // SMESH_MeshAlgos + /*! + * \brief Find nodes whose merge makes the element invalid + * + * (Implemented in SMESH_DeMerge.cxx) + */ + SMESHUtils_EXPORT + void DeMerge(const SMDS_MeshElement* elem, + std::vector< const SMDS_MeshNode* >& newNodes, + std::vector< const SMDS_MeshNode* >& noMergeNodes); + +} // namespace SMESH_MeshAlgos #endif diff --git a/src/SMESH_I/SMESH_MeshEditor_i.cxx b/src/SMESH_I/SMESH_MeshEditor_i.cxx index 990af7876..c0248c87e 100644 --- a/src/SMESH_I/SMESH_MeshEditor_i.cxx +++ b/src/SMESH_I/SMESH_MeshEditor_i.cxx @@ -4159,7 +4159,8 @@ FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr theObject, //======================================================================= void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes, - const SMESH::ListOfIDSources& NodesToKeep) + const SMESH::ListOfIDSources& NodesToKeep, + CORBA::Boolean AvoidMakingHoles) throw (SALOME::SALOME_Exception) { SMESH_TRY; @@ -4203,7 +4204,7 @@ void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfN aTPythonDump << aNodeGroup; } - getEditor().MergeNodes( aListOfListOfNodes ); + getEditor().MergeNodes( aListOfListOfNodes, AvoidMakingHoles ); aTPythonDump << "], " << NodesToKeep << ")"; diff --git a/src/SMESH_I/SMESH_MeshEditor_i.hxx b/src/SMESH_I/SMESH_MeshEditor_i.hxx index b7022a968..74eaa36ad 100644 --- a/src/SMESH_I/SMESH_MeshEditor_i.hxx +++ b/src/SMESH_I/SMESH_MeshEditor_i.hxx @@ -495,7 +495,8 @@ public: CORBA::Boolean SeparateCornersAndMedium) throw (SALOME::SALOME_Exception); void MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes, - const SMESH::ListOfIDSources& NodesToKeep ) + const SMESH::ListOfIDSources& NodesToKeep, + CORBA::Boolean AvoidMakingHoles ) throw (SALOME::SALOME_Exception); void FindEqualElements(SMESH::SMESH_IDSource_ptr Object, SMESH::array_of_long_array_out GroupsOfElementsID) diff --git a/src/SMESH_I/SMESH_Mesh_i.cxx b/src/SMESH_I/SMESH_Mesh_i.cxx index 887014be0..a075dadce 100644 --- a/src/SMESH_I/SMESH_Mesh_i.cxx +++ b/src/SMESH_I/SMESH_Mesh_i.cxx @@ -496,7 +496,13 @@ int SMESH_Mesh_i::ImportSTLFile( const char* theFileName ) SMESH_TRY; // Read mesh with name = into SMESH_Mesh - _impl->STLToMesh( theFileName ); + std::string name = _impl->STLToMesh( theFileName ); + if ( !name.empty() ) + { + SALOMEDS::Study_var study = _gen_i->GetCurrentStudy(); + SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( study, _this() ); + _gen_i->SetName( meshSO, name.c_str() ); + } SMESH_CATCH( SMESH::throwCorbaException ); @@ -3144,9 +3150,15 @@ void SMESH_Mesh_i::ExportSTL (const char *file, const bool isascii) TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportSTL( r'" << file << "', " << isascii << " )"; + CORBA::String_var name; + SALOMEDS::Study_var study = _gen_i->GetCurrentStudy(); + SALOMEDS::SObject_wrap so = _gen_i->ObjectToSObject( study, _this() ); + if ( !so->_is_nil() ) + name = so->GetName(); + // Perform Export - PrepareForWriting(file); - _impl->ExportSTL(file, isascii); + PrepareForWriting( file ); + _impl->ExportSTL( file, isascii, name.in() ); } //================================================================================ @@ -3595,8 +3607,14 @@ void SMESH_Mesh_i::ExportPartToSTL(::SMESH::SMESH_IDSource_ptr meshPart, PrepareForWriting(file); + CORBA::String_var name; + SALOMEDS::Study_var study = _gen_i->GetCurrentStudy(); + SALOMEDS::SObject_wrap so = _gen_i->ObjectToSObject( study, meshPart ); + if ( !so->_is_nil() ) + name = so->GetName(); + SMESH_MeshPartDS partDS( meshPart ); - _impl->ExportSTL(file, isascii, &partDS); + _impl->ExportSTL( file, isascii, name.in(), &partDS ); TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportPartToSTL( " << meshPart<< ", r'" << file << "', " << isascii << ")"; diff --git a/src/SMESH_SWIG/smeshBuilder.py b/src/SMESH_SWIG/smeshBuilder.py index 5b94cd28d..d87d0d553 100644 --- a/src/SMESH_SWIG/smeshBuilder.py +++ b/src/SMESH_SWIG/smeshBuilder.py @@ -4566,10 +4566,12 @@ class Mesh: # @param NodesToKeep nodes to keep in the mesh: a list of groups, sub-meshes or node IDs. # If @a NodesToKeep does not include a node to keep for some group to merge, # then the first node in the group is kept. + # @param AvoidMakingHoles prevent merging nodes which cause removal of elements becoming + # invalid # @ingroup l2_modif_trsf - def MergeNodes (self, GroupsOfNodes, NodesToKeep=[]): + def MergeNodes (self, GroupsOfNodes, NodesToKeep=[], AvoidMakingHoles=False): # NodesToKeep are converted to SMESH_IDSource in meshEditor.MergeNodes() - self.editor.MergeNodes(GroupsOfNodes,NodesToKeep) + self.editor.MergeNodes( GroupsOfNodes, NodesToKeep, AvoidMakingHoles ) ## Find the elements built on the same nodes. # @param MeshOrSubMeshOrGroup Mesh or SubMesh, or Group of elements for searching @@ -5125,17 +5127,18 @@ class meshEditor(SMESH._objref_SMESH_MeshEditor): def FindCoincidentNodesOnPart(self,*args): # a 3d arg added (SeparateCornerAndMediumNodes) if len( args ) == 2: args += False, return SMESH._objref_SMESH_MeshEditor.FindCoincidentNodesOnPart( self, *args ) - def MergeNodes(self,*args): # a 2nd arg added (NodesToKeep) + def MergeNodes(self,*args): # 2 args added (NodesToKeep,AvoidMakingHoles) if len( args ) == 1: - return SMESH._objref_SMESH_MeshEditor.MergeNodes( self, args[0], [] ) + return SMESH._objref_SMESH_MeshEditor.MergeNodes( self, args[0], [], False ) NodesToKeep = args[1] + AvoidMakingHoles = args[2] if len( args ) == 3 else False unRegister = genObjUnRegister() if NodesToKeep: if isinstance( NodesToKeep, list ) and isinstance( NodesToKeep[0], int ): NodesToKeep = self.MakeIDSource( NodesToKeep, SMESH.NODE ) if not isinstance( NodesToKeep, list ): NodesToKeep = [ NodesToKeep ] - return SMESH._objref_SMESH_MeshEditor.MergeNodes( self, args[0], NodesToKeep ) + return SMESH._objref_SMESH_MeshEditor.MergeNodes( self, args[0], NodesToKeep, AvoidMakingHoles ) pass omniORB.registerObjref(SMESH._objref_SMESH_MeshEditor._NP_RepositoryId, meshEditor) -- 2.39.2