Merge tag 'V8_3_0a2' into ngr/python3_dev

Version 8.3.0 alpha 2
This commit is contained in:
Nicolas Geimer 2017-03-20 18:20:10 +01:00
commit 0003e6b4fc
30 changed files with 1006 additions and 572 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -26,6 +26,9 @@ merging.</li>
cells</b> check-box prevents merging medium nodes of quadratic cells</b> check-box prevents merging medium nodes of quadratic
elements with corner nodes. This check-box is enabled provided elements with corner nodes. This check-box is enabled provided
that the selected mesh includes quadratic elements.</li> that the selected mesh includes quadratic elements.</li>
<li>Activation of <b>Avoid making holes</b> check-box prevents merging
nodes that make elements invalid (but not degenerated) and hence
removed. Thus, no holes in place of removed elements appear. </li>
<li><b>Exclude groups from detection</b> group allows to ignore the <li><b>Exclude groups from detection</b> group allows to ignore the
nodes which belong to the specified mesh groups. This control is nodes which belong to the specified mesh groups. This control is
active provided that the mesh includes groups.</li> active provided that the mesh includes groups.</li>

View File

@ -689,7 +689,8 @@ module SMESH
raises (SALOME::SALOME_Exception); raises (SALOME::SALOME_Exception);
void MergeNodes (in array_of_long_array GroupsOfNodes, void MergeNodes (in array_of_long_array GroupsOfNodes,
in SMESH::ListOfIDSources NodesToKeep) in SMESH::ListOfIDSources NodesToKeep,
in boolean AvoidMakingHoles)
raises (SALOME::SALOME_Exception); raises (SALOME::SALOME_Exception);
/*! /*!

View File

@ -69,7 +69,7 @@ namespace
}; };
typedef NCollection_DataMap<gp_Pnt,SMDS_MeshNode*,Hasher> TDataMapOfPntNodePtr; typedef NCollection_DataMap<gp_Pnt,SMDS_MeshNode*,Hasher> TDataMapOfPntNodePtr;
const int HEADER_SIZE = 84; const int HEADER_SIZE = 84; // 80 chars + int
const int SIZEOF_STL_FACET = 50; const int SIZEOF_STL_FACET = 50;
const int ASCII_LINES_PER_FACET = 7; const int ASCII_LINES_PER_FACET = 7;
const int SIZE_OF_FLOAT = 4; 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) static Standard_Real readFloat(SMESH_File& theFile)
{ {
union { union {
Standard_Boolean i; int i;
Standard_ShortReal f; float f;
} u; } u;
const char* c = theFile; const char* c = theFile;
u.i = 0;
u.i = c[0] & 0xFF; u.i = c[0] & 0xFF;
u.i |= (c[1] & 0xFF) << 0x08; u.i |= (c[1] & 0xFF) << 0x08;
u.i |= (c[2] & 0xFF) << 0x10; u.i |= (c[2] & 0xFF) << 0x10;
@ -212,6 +213,23 @@ Driver_Mesh::Status DriverSTL_R_SMDS_Mesh::readAscii(SMESH_File& theFile) const
{ {
Status aResult = DRS_OK; 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<std::string&>( 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 // get the file size
long filesize = theFile.size(); long filesize = theFile.size();
theFile.close(); theFile.close();
@ -221,7 +239,8 @@ Driver_Mesh::Status DriverSTL_R_SMDS_Mesh::readAscii(SMESH_File& theFile) const
// count the number of lines // count the number of lines
Standard_Integer nbLines = 0; Standard_Integer nbLines = 0;
for (long ipos = 0; ipos < filesize; ++ipos) { for (long ipos = 0; ipos < filesize; ++ipos)
{
if (getc(file) == '\n') if (getc(file) == '\n')
nbLines++; nbLines++;
} }
@ -236,8 +255,8 @@ Driver_Mesh::Status DriverSTL_R_SMDS_Mesh::readAscii(SMESH_File& theFile) const
while (getc(file) != '\n'); while (getc(file) != '\n');
// main reading // main reading
for (Standard_Integer iTri = 0; iTri < nbTri; ++iTri) { for (Standard_Integer iTri = 0; iTri < nbTri; ++iTri)
{
// skipping the facet normal // skipping the facet normal
Standard_ShortReal normal[3]; Standard_ShortReal normal[3];
fscanf(file,"%*s %*s %f %f %f\n",&normal[0],&normal[1],&normal[2]); fscanf(file,"%*s %*s %f %f %f\n",&normal[0],&normal[1],&normal[2]);
@ -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 // 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); 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<std::string&>( 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 // skip the header
file += HEADER_SIZE; file += HEADER_SIZE;

View File

@ -35,6 +35,7 @@ class MESHDRIVERSTL_EXPORT DriverSTL_R_SMDS_Mesh: public Driver_SMDS_Mesh
DriverSTL_R_SMDS_Mesh(); DriverSTL_R_SMDS_Mesh();
virtual Status Perform(); virtual Status Perform();
void SetIsCreateFaces( const bool theIsCreate = true ); void SetIsCreateFaces( const bool theIsCreate = true );
std::string GetName() const { return myName; }
private: private:
// PRIVATE METHODS // PRIVATE METHODS
@ -45,6 +46,7 @@ class MESHDRIVERSTL_EXPORT DriverSTL_R_SMDS_Mesh: public Driver_SMDS_Mesh
// PRIVATE FIELDS // PRIVATE FIELDS
bool myIsCreateFaces; bool myIsCreateFaces;
bool myIsAscii; bool myIsAscii;
std::string myName;
}; };
#endif #endif

View File

@ -485,7 +485,8 @@ Driver_Mesh::Status DriverSTL_W_SMDS_Mesh::writeAscii() const
SMESH_File aFile( myFile, /*openForReading=*/false ); SMESH_File aFile( myFile, /*openForReading=*/false );
aFile.openForWriting(); aFile.openForWriting();
std::string buf("solid\n"); std::string buf("solid ");
buf += myName + "\n";
aFile.writeRaw( buf.c_str(), buf.size() ); aFile.writeRaw( buf.c_str(), buf.size() );
char sval[128]; char sval[128];
@ -520,7 +521,8 @@ Driver_Mesh::Status DriverSTL_W_SMDS_Mesh::writeAscii() const
" endfacet\n", 21 ); " endfacet\n", 21 );
} }
} }
aFile.writeRaw ("endsolid\n" , 9 ); buf = "endsolid " + myName + "\n";
aFile.writeRaw( buf.c_str(), buf.size() );
return aResult; return aResult;
} }
@ -554,6 +556,11 @@ Driver_Mesh::Status DriverSTL_W_SMDS_Mesh::writeBinary() const
} }
} }
std::string sval( LABEL_SIZE, ' ' ); std::string sval( LABEL_SIZE, ' ' );
if ( !myName.empty() )
{
sval = "name: " + myName;
sval.resize( LABEL_SIZE, ' ' );
}
aFile.write( sval.c_str(), LABEL_SIZE ); aFile.write( sval.c_str(), LABEL_SIZE );
// write number of triangles // write number of triangles

View File

@ -45,6 +45,7 @@ class MESHDRIVERSTL_EXPORT DriverSTL_W_SMDS_Mesh: public Driver_SMDS_Mesh
~DriverSTL_W_SMDS_Mesh(); ~DriverSTL_W_SMDS_Mesh();
virtual Status Perform(); virtual Status Perform();
void SetIsAscii( const bool theIsAscii = false ); void SetIsAscii( const bool theIsAscii = false );
void SetName( const std::string name ) { myName = name; }
private: private:
// PRIVATE METHODS // PRIVATE METHODS
@ -57,6 +58,7 @@ class MESHDRIVERSTL_EXPORT DriverSTL_W_SMDS_Mesh: public Driver_SMDS_Mesh
private: private:
// PRIVATE FIELDS // PRIVATE FIELDS
bool myIsAscii; bool myIsAscii;
std::string myName;
int myNbVolumeTrias; int myNbVolumeTrias;
std::vector<const SMDS_MeshElement*> myVolumeFacets; // tmp faces std::vector<const SMDS_MeshElement*> myVolumeFacets; // tmp faces
}; };

View File

@ -472,7 +472,8 @@ SMDS_VolumeTool::~SMDS_VolumeTool()
//======================================================================= //=======================================================================
bool SMDS_VolumeTool::Set (const SMDS_MeshElement* theVolume, bool SMDS_VolumeTool::Set (const SMDS_MeshElement* theVolume,
const bool ignoreCentralNodes) const bool ignoreCentralNodes,
const std::vector<const SMDS_MeshNode*>* otherNodes)
{ {
// reset fields // reset fields
myVolume = 0; myVolume = 0;
@ -510,11 +511,22 @@ bool SMDS_VolumeTool::Set (const SMDS_MeshElement* theVolume,
} }
// set nodes // set nodes
int iNode = 0;
myVolumeNodes.resize( myVolume->NbNodes() ); myVolumeNodes.resize( myVolume->NbNodes() );
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(); SMDS_ElemIteratorPtr nodeIt = myVolume->nodesIterator();
while ( nodeIt->more() ) while ( nodeIt->more() )
myVolumeNodes[ iNode++ ] = static_cast<const SMDS_MeshNode*>( nodeIt->next() ); myVolumeNodes[ iNode++ ] = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
}
// check validity // check validity
if ( !setFace(0) ) if ( !setFace(0) )

View File

@ -62,11 +62,13 @@ class SMDS_EXPORT SMDS_VolumeTool
const bool ignoreCentralNodes = true); const bool ignoreCentralNodes = true);
bool Set( const SMDS_MeshElement* theVolume, bool Set( const SMDS_MeshElement* theVolume,
const bool ignoreCentralNodes=true); const bool ignoreCentralNodes = true,
const std::vector<const SMDS_MeshNode*>* nodes = 0);
// Set volume. // Set volume.
// Return false if theVolume is not of type SMDSAbs_Volume. // Return false if theVolume is not of type SMDSAbs_Volume.
// ignoreCentralNodes makes skip nodes at face centers when returning // 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; const SMDS_MeshVolume* Element() const;
// return element // return element
@ -91,10 +93,10 @@ class SMDS_EXPORT SMDS_VolumeTool
// top and bottom faces are reversed. // top and bottom faces are reversed.
// Result of IsForward() and methods returning nodes change // 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 // Return array of volume nodes
int NbNodes() { return myVolumeNodes.size(); } int NbNodes() const { return myVolumeNodes.size(); }
// Return array of volume nodes // Return array of volume nodes
double GetSize() const; double GetSize() const;

View File

@ -559,7 +559,7 @@ int SMESH_Mesh::MEDToMesh(const char* theFileName, const char* theMeshName)
//purpose : //purpose :
//======================================================================= //=======================================================================
int SMESH_Mesh::STLToMesh(const char* theFileName) std::string SMESH_Mesh::STLToMesh(const char* theFileName)
{ {
if(_isShapeToMesh) if(_isShapeToMesh)
throw SALOME_Exception(LOCALIZED("a shape to mesh has already been defined")); 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.SetMeshId(-1);
myReader.Perform(); 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, void SMESH_Mesh::ExportSTL(const char * file,
const bool isascii, const bool isascii,
const char * name,
const SMESHDS_Mesh* meshPart) throw(SALOME_Exception) const SMESHDS_Mesh* meshPart) throw(SALOME_Exception)
{ {
Unexpect aCatch(SalomeException); Unexpect aCatch(SalomeException);
@ -1568,6 +1569,7 @@ void SMESH_Mesh::ExportSTL(const char * file,
myWriter.SetIsAscii( isascii ); myWriter.SetIsAscii( isascii );
myWriter.SetMesh( meshPart ? (SMESHDS_Mesh*) meshPart : _myMeshDS); myWriter.SetMesh( meshPart ? (SMESHDS_Mesh*) meshPart : _myMeshDS);
myWriter.SetMeshId(_id); myWriter.SetMeshId(_id);
if ( name ) myWriter.SetName( name );
myWriter.Perform(); myWriter.Perform();
} }

View File

@ -121,7 +121,7 @@ class SMESH_EXPORT SMESH_Mesh
int MEDToMesh(const char* theFileName, const char* theMeshName); 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); 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); const SMESHDS_Mesh* meshPart = 0) throw(SALOME_Exception);
void ExportSTL(const char * file, void ExportSTL(const char * file,
const bool isascii, const bool isascii,
const char * name = 0,
const SMESHDS_Mesh* meshPart = 0) throw(SALOME_Exception); const SMESHDS_Mesh* meshPart = 0) throw(SALOME_Exception);
void ExportCGNS(const char * file, void ExportCGNS(const char * file,
const SMESHDS_Mesh* mesh, const SMESHDS_Mesh* mesh,

View File

@ -6095,7 +6095,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet theElements[2],
aPrms.push_back( aT ); aPrms.push_back( aT );
} }
//Extrusion_Error err = //Extrusion_Error err =
MakeEdgePathPoints(aPrms, aTrackEdge, (aN1==theN1), fullList); makeEdgePathPoints(aPrms, aTrackEdge, (aN1==theN1), fullList);
} else if( aS.ShapeType() == TopAbs_WIRE ) { } else if( aS.ShapeType() == TopAbs_WIRE ) {
list< SMESH_subMesh* > LSM; list< SMESH_subMesh* > LSM;
TopTools_SequenceOfShape Edges; TopTools_SequenceOfShape Edges;
@ -6140,7 +6140,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet theElements[2],
} }
list<SMESH_MeshEditor_PathPoint> LPP; list<SMESH_MeshEditor_PathPoint> LPP;
//Extrusion_Error err = //Extrusion_Error err =
MakeEdgePathPoints(aPrms, aTrackEdge,(aN1->GetID()==startNid), LPP); makeEdgePathPoints(aPrms, aTrackEdge,(aN1->GetID()==startNid), LPP);
LLPPs.push_back(LPP); LLPPs.push_back(LPP);
UsedNums.Add(k); UsedNums.Add(k);
// update startN for search following egde // update startN for search following egde
@ -6183,7 +6183,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet theElements[2],
return EXTR_BAD_PATH_SHAPE; return EXTR_BAD_PATH_SHAPE;
} }
return MakeExtrElements(theElements, fullList, theHasAngles, theAngles, theLinearVariation, return makeExtrElements(theElements, fullList, theHasAngles, theAngles, theLinearVariation,
theHasRefPoint, theRefPoint, theMakeGroups); theHasRefPoint, theRefPoint, theMakeGroups);
} }
@ -6322,7 +6322,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet theElements[2],
TopoDS_Edge e = BRepBuilderAPI_MakeEdge( p1, p2 ); TopoDS_Edge e = BRepBuilderAPI_MakeEdge( p1, p2 );
list<SMESH_MeshEditor_PathPoint> LPP; list<SMESH_MeshEditor_PathPoint> LPP;
aPrms.clear(); aPrms.clear();
MakeEdgePathPoints(aPrms, e, (aNodesList[i-1]->GetID()==startNid), LPP); makeEdgePathPoints(aPrms, e, (aNodesList[i-1]->GetID()==startNid), LPP);
LLPPs.push_back(LPP); LLPPs.push_back(LPP);
if ( aNodesList[i-1]->GetID() == startNid ) startNid = aNodesList[i ]->GetID(); if ( aNodesList[i-1]->GetID() == startNid ) startNid = aNodesList[i ]->GetID();
else startNid = aNodesList[i-1]->GetID(); else startNid = aNodesList[i-1]->GetID();
@ -6380,7 +6380,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet theElements[2],
aPrms.push_back( aT ); aPrms.push_back( aT );
} }
//Extrusion_Error err = //Extrusion_Error err =
MakeEdgePathPoints(aPrms, aTrackEdge, (aN1==theN1), fullList); makeEdgePathPoints(aPrms, aTrackEdge, (aN1==theN1), fullList);
} }
else if( aS.ShapeType() == TopAbs_WIRE ) { else if( aS.ShapeType() == TopAbs_WIRE ) {
list< SMESH_subMesh* > LSM; list< SMESH_subMesh* > LSM;
@ -6439,7 +6439,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet theElements[2],
} }
list<SMESH_MeshEditor_PathPoint> LPP; list<SMESH_MeshEditor_PathPoint> LPP;
//Extrusion_Error err = //Extrusion_Error err =
MakeEdgePathPoints(aPrms, aTrackEdge, aN1isOK, LPP); makeEdgePathPoints(aPrms, aTrackEdge, aN1isOK, LPP);
LLPPs.push_back(LPP); LLPPs.push_back(LPP);
UsedNums.Add(k); UsedNums.Add(k);
// update startN for search following egde // update startN for search following egde
@ -6475,17 +6475,17 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet theElements[2],
return EXTR_BAD_PATH_SHAPE; return EXTR_BAD_PATH_SHAPE;
} }
return MakeExtrElements(theElements, fullList, theHasAngles, theAngles, theLinearVariation, return makeExtrElements(theElements, fullList, theHasAngles, theAngles, theLinearVariation,
theHasRefPoint, theRefPoint, theMakeGroups); theHasRefPoint, theRefPoint, theMakeGroups);
} }
//======================================================================= //=======================================================================
//function : MakeEdgePathPoints //function : makeEdgePathPoints
//purpose : auxiliary for ExtrusionAlongTrack //purpose : auxiliary for ExtrusionAlongTrack
//======================================================================= //=======================================================================
SMESH_MeshEditor::Extrusion_Error SMESH_MeshEditor::Extrusion_Error
SMESH_MeshEditor::MakeEdgePathPoints(std::list<double>& aPrms, SMESH_MeshEditor::makeEdgePathPoints(std::list<double>& aPrms,
const TopoDS_Edge& aTrackEdge, const TopoDS_Edge& aTrackEdge,
bool FirstIsStart, bool FirstIsStart,
list<SMESH_MeshEditor_PathPoint>& LPP) list<SMESH_MeshEditor_PathPoint>& LPP)
@ -6536,11 +6536,11 @@ SMESH_MeshEditor::MakeEdgePathPoints(std::list<double>& aPrms,
//======================================================================= //=======================================================================
//function : MakeExtrElements //function : makeExtrElements
//purpose : auxiliary for ExtrusionAlongTrack //purpose : auxiliary for ExtrusionAlongTrack
//======================================================================= //=======================================================================
SMESH_MeshEditor::Extrusion_Error SMESH_MeshEditor::Extrusion_Error
SMESH_MeshEditor::MakeExtrElements(TIDSortedElemSet theElemSets[2], SMESH_MeshEditor::makeExtrElements(TIDSortedElemSet theElemSets[2],
list<SMESH_MeshEditor_PathPoint>& fullList, list<SMESH_MeshEditor_PathPoint>& fullList,
const bool theHasAngles, const bool theHasAngles,
list<double>& theAngles, list<double>& theAngles,
@ -6553,7 +6553,7 @@ SMESH_MeshEditor::MakeExtrElements(TIDSortedElemSet theElemSets
// Angles // Angles
if( theHasAngles && !theAngles.empty() && theLinearVariation ) if( theHasAngles && !theAngles.empty() && theLinearVariation )
LinearAngleVariation(aNbTP-1, theAngles); linearAngleVariation(aNbTP-1, theAngles);
// fill vector of path points with angles // fill vector of path points with angles
vector<SMESH_MeshEditor_PathPoint> aPPs; vector<SMESH_MeshEditor_PathPoint> aPPs;
@ -6746,11 +6746,11 @@ SMESH_MeshEditor::MakeExtrElements(TIDSortedElemSet theElemSets
//======================================================================= //=======================================================================
//function : LinearAngleVariation //function : linearAngleVariation
//purpose : spread values over nbSteps //purpose : spread values over nbSteps
//======================================================================= //=======================================================================
void SMESH_MeshEditor::LinearAngleVariation(const int nbSteps, void SMESH_MeshEditor::linearAngleVariation(const int nbSteps,
list<double>& Angles) list<double>& Angles)
{ {
int nbAngles = Angles.size(); int nbAngles = Angles.size();
@ -7351,11 +7351,12 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes,
myLastCreatedElems.Clear(); myLastCreatedElems.Clear();
myLastCreatedNodes.Clear(); myLastCreatedNodes.Clear();
SMESHDS_Mesh* aMesh = GetMeshDS(); SMESHDS_Mesh* mesh = GetMeshDS();
TNodeNodeMap nodeNodeMap; // node to replace - new node TNodeNodeMap nodeNodeMap; // node to replace - new node
set<const SMDS_MeshElement*> elems; // all elements with changed nodes set<const SMDS_MeshElement*> elems; // all elements with changed nodes
list< int > rmElemIds, rmNodeIds; list< int > rmElemIds, rmNodeIds;
vector< ElemFeatures > newElemDefs;
// Fill nodeNodeMap and elems // Fill nodeNodeMap and elems
@ -7369,17 +7370,6 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes,
{ {
const SMDS_MeshNode* nToRemove = *nIt; const SMDS_MeshNode* nToRemove = *nIt;
nodeNodeMap.insert( make_pair( nToRemove, nToKeep )); 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(); SMDS_ElemIteratorPtr invElemIt = nToRemove->GetInverseElementIterator();
while ( invElemIt->more() ) { while ( invElemIt->more() ) {
const SMDS_MeshElement* elem = invElemIt->next(); const SMDS_MeshElement* elem = invElemIt->next();
@ -7387,53 +7377,164 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes,
} }
} }
} }
// Change element nodes or remove an element
set<const SMDS_MeshNode*> nodeSet; // Apply recursive replacements (BUG 0020185)
vector< const SMDS_MeshNode*> curNodes, uniqueNodes; TNodeNodeMap::iterator nnIt = nodeNodeMap.begin();
vector<int> iRepl; for ( ; nnIt != nodeNodeMap.end(); ++nnIt )
ElemFeatures elemType; {
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<const SMDS_MeshElement*> pbElems;
set<const SMDS_MeshElement*>::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<const SMDS_MeshNode*>( 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<const SMDS_MeshElement*>::iterator eIt = elems.begin(); set<const SMDS_MeshElement*>::iterator eIt = elems.begin();
for ( ; eIt != elems.end(); eIt++ ) for ( ; eIt != elems.end(); eIt++ )
{ {
const SMDS_MeshElement* elem = *eIt; const SMDS_MeshElement* elem = *eIt;
SMESHDS_SubMesh* sm = mesh->MeshElements( elem->getshapeId() );
bool keepElem = applyMerge( elem, newElemDefs, nodeNodeMap, /*noHoles=*/false );
if ( !keepElem )
rmElemIds.push_back( elem->GetID() );
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 );
}
}
}
// Remove bad elements, then equal nodes (order important)
Remove( rmElemIds, false );
Remove( rmNodeIds, true );
return;
}
//=======================================================================
//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
//=======================================================================
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
newElemDefs.resize(nbResElems);
newElemDefs[0].Init( elem );
newElemDefs[0].myNodes.clear();
set<const SMDS_MeshNode*> nodeSet;
vector< const SMDS_MeshNode*> curNodes;
vector< const SMDS_MeshNode*> & uniqueNodes = newElemDefs[0].myNodes;
vector<int> iRepl;
const int nbNodes = elem->NbNodes(); const int nbNodes = elem->NbNodes();
const int aShapeId = FindShape( elem );
SMDSAbs_EntityType entity = elem->GetEntityType(); SMDSAbs_EntityType entity = elem->GetEntityType();
nodeSet.clear();
curNodes.resize( nbNodes ); curNodes.resize( nbNodes );
uniqueNodes.resize( nbNodes ); uniqueNodes.resize( nbNodes );
iRepl.resize( nbNodes ); iRepl.resize( nbNodes );
int iUnique = 0, iCur = 0, nbRepl = 0; int iUnique = 0, iCur = 0, nbRepl = 0;
// get new seq of nodes // Get new seq of nodes
SMDS_ElemIteratorPtr itN = elem->nodesIterator(); SMDS_ElemIteratorPtr itN = elem->nodesIterator();
while ( itN->more() ) while ( itN->more() )
{ {
const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( itN->next() ); const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( itN->next() );
TNodeNodeMap::iterator nnIt = nodeNodeMap.find( n ); TNodeNodeMap::iterator nnIt = nodeNodeMap.find( n );
if ( nnIt != nodeNodeMap.end() ) { // n sticks if ( nnIt != nodeNodeMap.end() ) {
n = (*nnIt).second; n = (*nnIt).second;
{ ////////// BUG 0020185: begin
bool stopRecur = false;
set<const SMDS_MeshNode*> 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
} }
curNodes[ iCur ] = n; curNodes[ iCur ] = n;
bool isUnique = nodeSet.insert( n ).second; bool isUnique = nodeSet.insert( n ).second;
@ -7446,16 +7547,19 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes,
// Analyse element topology after replacement // Analyse element topology after replacement
bool isOk = true;
int nbUniqueNodes = nodeSet.size(); int nbUniqueNodes = nodeSet.size();
if ( nbNodes != nbUniqueNodes ) // some nodes stick if ( nbNodes != nbUniqueNodes ) // some nodes stick
{ {
if ( elem->IsPoly() ) // Polygons and Polyhedral volumes toRemove = true;
nbResElems = 0;
switch ( entity )
{ {
if ( elem->GetType() == SMDSAbs_Face ) // Polygon case SMDSEntity_Polygon:
case SMDSEntity_Quad_Polygon: // Polygon
{ {
elemType.Init( elem ); ElemFeatures* elemType = & newElemDefs[0];
const bool isQuad = elemType.myIsQuad; const bool isQuad = elemType->myIsQuad;
if ( isQuad ) if ( isQuad )
SMDS_MeshCell::applyInterlace // interlace medium and corner nodes SMDS_MeshCell::applyInterlace // interlace medium and corner nodes
( SMDS_MeshCell::interlacedSmdsOrder( SMDSEntity_Quad_Polygon, nbNodes ), curNodes ); ( SMDS_MeshCell::interlacedSmdsOrder( SMDSEntity_Quad_Polygon, nbNodes ), curNodes );
@ -7463,13 +7567,14 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes,
// a polygon can divide into several elements // a polygon can divide into several elements
vector<const SMDS_MeshNode *> polygons_nodes; vector<const SMDS_MeshNode *> polygons_nodes;
vector<int> quantities; vector<int> quantities;
int nbNew = SimplifyFace( curNodes, polygons_nodes, quantities ); nbResElems = SimplifyFace( curNodes, polygons_nodes, quantities );
if (nbNew > 0) newElemDefs.resize( nbResElems );
{ for ( int inode = 0, iface = 0; iface < nbResElems; iface++ )
vector<const SMDS_MeshNode *> face_nodes;
int inode = 0;
for (int iface = 0; iface < nbNew; iface++)
{ {
ElemFeatures* elemType = & newElemDefs[iface];
if ( iface ) elemType->Init( elem );
vector<const SMDS_MeshNode *>& face_nodes = elemType->myNodes;
int nbNewNodes = quantities[iface]; int nbNewNodes = quantities[iface];
face_nodes.assign( polygons_nodes.begin() + inode, face_nodes.assign( polygons_nodes.begin() + inode,
polygons_nodes.begin() + inode + nbNewNodes ); polygons_nodes.begin() + inode + nbNewNodes );
@ -7479,38 +7584,32 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes,
bool isValid = ( nbNewNodes % 2 == 0 ); bool isValid = ( nbNewNodes % 2 == 0 );
for ( int i = 0; i < nbNewNodes && isValid; ++i ) for ( int i = 0; i < nbNewNodes && isValid; ++i )
isValid = ( elem->IsMediumNode( face_nodes[i]) == bool( i % 2 )); isValid = ( elem->IsMediumNode( face_nodes[i]) == bool( i % 2 ));
elemType.SetQuad( isValid ); elemType->SetQuad( isValid );
if ( isValid ) // put medium nodes after corners if ( isValid ) // put medium nodes after corners
SMDS_MeshCell::applyInterlaceRev SMDS_MeshCell::applyInterlaceRev
( SMDS_MeshCell::interlacedSmdsOrder( SMDSEntity_Quad_Polygon, ( SMDS_MeshCell::interlacedSmdsOrder( SMDSEntity_Quad_Polygon,
nbNewNodes ), face_nodes ); nbNewNodes ), face_nodes );
} }
elemType.SetPoly(( nbNewNodes / ( elemType.myIsQuad + 1 ) > 4 )); elemType->SetPoly(( nbNewNodes / ( elemType->myIsQuad + 1 ) > 4 ));
SMDS_MeshElement* newElem = AddElement( face_nodes, elemType.SetID(-1));
if ( aShapeId )
aMesh->SetMeshElementOnShape(newElem, aShapeId);
} }
} nbUniqueNodes = newElemDefs[0].myNodes.size();
rmElemIds.push_back(elem->GetID()); break;
} // Polygon } // Polygon
else if ( elem->GetType() == SMDSAbs_Volume ) // Polyhedral volume case SMDSEntity_Polyhedra: // Polyhedral volume
{
if ( nbUniqueNodes >= 4 )
{ {
if ( nbUniqueNodes < 4 ) {
rmElemIds.push_back(elem->GetID());
}
else {
// each face has to be analyzed in order to check volume validity // each face has to be analyzed in order to check volume validity
const SMDS_VtkVolume* aPolyedre = dynamic_cast<const SMDS_VtkVolume*>( elem ); if ( const SMDS_VtkVolume* aPolyedre = dynamic_cast<const SMDS_VtkVolume*>( elem ))
if ( aPolyedre )
{ {
int nbFaces = aPolyedre->NbFaces(); int nbFaces = aPolyedre->NbFaces();
vector<const SMDS_MeshNode *> poly_nodes; vector<const SMDS_MeshNode *>& poly_nodes = newElemDefs[0].myNodes;
vector<int> quantities; vector<int> & quantities = newElemDefs[0].myPolyhedQuantities;
vector<const SMDS_MeshNode *> faceNodes; vector<const SMDS_MeshNode *> faceNodes;
poly_nodes.clear();
quantities.clear();
for (int iface = 1; iface <= nbFaces; iface++) for (int iface = 1; iface <= nbFaces; iface++)
{ {
@ -7527,54 +7626,39 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes,
SimplifyFace(faceNodes, poly_nodes, quantities); SimplifyFace(faceNodes, poly_nodes, quantities);
} }
if ( quantities.size() > 3 ) {
// TODO: remove coincident faces
}
if ( quantities.size() > 3 ) if ( quantities.size() > 3 )
{ {
const SMDS_MeshElement* newElem = // TODO: remove coincident faces
aMesh->AddPolyhedralVolume( poly_nodes, quantities ); nbResElems = 1;
myLastCreatedElems.Append( newElem ); nbUniqueNodes = newElemDefs[0].myNodes.size();
if ( aShapeId && newElem )
aMesh->SetMeshElementOnShape( newElem, aShapeId );
rmElemIds.push_back( elem->GetID() );
}
}
else {
rmElemIds.push_back( elem->GetID() );
} }
} }
} }
else {
} }
break;
continue;
} // poly element
// Regular elements // Regular elements
// TODO not all the possible cases are solved. Find something more generic? // TODO not all the possible cases are solved. Find something more generic?
switch ( entity ) {
case SMDSEntity_Edge: //////// EDGE case SMDSEntity_Edge: //////// EDGE
case SMDSEntity_Triangle: //// TRIANGLE case SMDSEntity_Triangle: //// TRIANGLE
case SMDSEntity_Quad_Triangle: case SMDSEntity_Quad_Triangle:
case SMDSEntity_Tetra: case SMDSEntity_Tetra:
case SMDSEntity_Quad_Tetra: // TETRAHEDRON case SMDSEntity_Quad_Tetra: // TETRAHEDRON
{ {
isOk = false;
break; break;
} }
case SMDSEntity_Quad_Edge: case SMDSEntity_Quad_Edge:
{ {
isOk = false; // to linear EDGE ???????
break; break;
} }
case SMDSEntity_Quadrangle: //////////////////////////////////// QUADRANGLE case SMDSEntity_Quadrangle: //////////////////////////////////// QUADRANGLE
{ {
if ( nbUniqueNodes < 3 ) if ( nbUniqueNodes < 3 )
isOk = false; toRemove = true;
else if ( nbRepl == 1 && curNodes[ iRepl[0]] == curNodes[( iRepl[0]+2 )%4 ]) else if ( nbRepl == 1 && curNodes[ iRepl[0]] == curNodes[( iRepl[0]+2 )%4 ])
isOk = false; // opposite nodes stick toRemove = true; // opposite nodes stick
else
toRemove = false;
break; break;
} }
case SMDSEntity_Quad_Quadrangle: // Quadratic QUADRANGLE case SMDSEntity_Quad_Quadrangle: // Quadratic QUADRANGLE
@ -7592,7 +7676,7 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes,
( iRepl[0] == 3 && iRepl[1] == 6 && curNodes[3] == curNodes[2] ) || ( iRepl[0] == 3 && iRepl[1] == 6 && curNodes[3] == curNodes[2] ) ||
( iRepl[0] == 3 && iRepl[1] == 7 && curNodes[3] == curNodes[0] ))) ( iRepl[0] == 3 && iRepl[1] == 7 && curNodes[3] == curNodes[0] )))
{ {
isOk = true; toRemove = false;
} }
break; break;
} }
@ -7611,19 +7695,18 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes,
( iRepl[0] == 3 && iRepl[1] == 6 && curNodes[3] == curNodes[2] ) || ( iRepl[0] == 3 && iRepl[1] == 6 && curNodes[3] == curNodes[2] ) ||
( iRepl[0] == 3 && iRepl[1] == 7 && curNodes[3] == curNodes[0] ))) ( iRepl[0] == 3 && iRepl[1] == 7 && curNodes[3] == curNodes[0] )))
{ {
isOk = true; toRemove = false;
} }
break; break;
} }
case SMDSEntity_Penta: ///////////////////////////////////// PENTAHEDRON case SMDSEntity_Penta: ///////////////////////////////////// PENTAHEDRON
{ {
isOk = false;
if ( nbUniqueNodes == 4 ) { if ( nbUniqueNodes == 4 ) {
// ---------------------------------> tetrahedron // ---------------------------------> tetrahedron
if ( curNodes[3] == curNodes[4] && if ( curNodes[3] == curNodes[4] &&
curNodes[3] == curNodes[5] ) { curNodes[3] == curNodes[5] ) {
// top nodes stick // top nodes stick
isOk = true; toRemove = false;
} }
else if ( curNodes[0] == curNodes[1] && else if ( curNodes[0] == curNodes[1] &&
curNodes[0] == curNodes[2] ) { curNodes[0] == curNodes[2] ) {
@ -7632,13 +7715,13 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes,
uniqueNodes[ 0 ] = curNodes [ 5 ]; uniqueNodes[ 0 ] = curNodes [ 5 ];
uniqueNodes[ 1 ] = curNodes [ 4 ]; uniqueNodes[ 1 ] = curNodes [ 4 ];
uniqueNodes[ 2 ] = curNodes [ 3 ]; uniqueNodes[ 2 ] = curNodes [ 3 ];
isOk = true; toRemove = false;
} }
else if (( curNodes[0] == curNodes[3] ) + else if (( curNodes[0] == curNodes[3] ) +
( curNodes[1] == curNodes[4] ) + ( curNodes[1] == curNodes[4] ) +
( curNodes[2] == curNodes[5] ) == 2 ) { ( curNodes[2] == curNodes[5] ) == 2 ) {
// a lateral face turns into a line // a lateral face turns into a line
isOk = true; toRemove = false;
} }
} }
else if ( nbUniqueNodes == 5 ) { else if ( nbUniqueNodes == 5 ) {
@ -7650,7 +7733,7 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes,
uniqueNodes[ 2 ] = curNodes[ 5 ]; uniqueNodes[ 2 ] = curNodes[ 5 ];
uniqueNodes[ 3 ] = curNodes[ 2 ]; uniqueNodes[ 3 ] = curNodes[ 2 ];
uniqueNodes[ 4 ] = curNodes[ 0 ]; uniqueNodes[ 4 ] = curNodes[ 0 ];
isOk = true; toRemove = false;
} }
if ( curNodes[1] == curNodes[4] ) if ( curNodes[1] == curNodes[4] )
{ {
@ -7659,7 +7742,7 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes,
uniqueNodes[ 2 ] = curNodes[ 5 ]; uniqueNodes[ 2 ] = curNodes[ 5 ];
uniqueNodes[ 3 ] = curNodes[ 3 ]; uniqueNodes[ 3 ] = curNodes[ 3 ];
uniqueNodes[ 4 ] = curNodes[ 1 ]; uniqueNodes[ 4 ] = curNodes[ 1 ];
isOk = true; toRemove = false;
} }
if ( curNodes[2] == curNodes[5] ) if ( curNodes[2] == curNodes[5] )
{ {
@ -7668,7 +7751,7 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes,
uniqueNodes[ 2 ] = curNodes[ 4 ]; uniqueNodes[ 2 ] = curNodes[ 4 ];
uniqueNodes[ 3 ] = curNodes[ 1 ]; uniqueNodes[ 3 ] = curNodes[ 1 ];
uniqueNodes[ 4 ] = curNodes[ 2 ]; uniqueNodes[ 4 ] = curNodes[ 2 ];
isOk = true; toRemove = false;
} }
} }
break; break;
@ -7676,7 +7759,6 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes,
case SMDSEntity_Hexa: case SMDSEntity_Hexa:
{ {
//////////////////////////////////// HEXAHEDRON //////////////////////////////////// HEXAHEDRON
isOk = false;
SMDS_VolumeTool hexa (elem); SMDS_VolumeTool hexa (elem);
hexa.SetExternalNormal(); hexa.SetExternalNormal();
if ( nbUniqueNodes == 4 && nbRepl == 4 ) { if ( nbUniqueNodes == 4 && nbRepl == 4 ) {
@ -7702,7 +7784,7 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes,
// ... and the opposite one - into a triangle. // ... and the opposite one - into a triangle.
// set a top node // set a top node
uniqueNodes.push_back( curNodes[ pickInd ]); uniqueNodes.push_back( curNodes[ pickInd ]);
isOk = true; toRemove = false;
} }
break; break;
} }
@ -7743,7 +7825,7 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes,
uniqueNodes[ iCur + 3 ] = curNodes[ indT[ j ]]; uniqueNodes[ iCur + 3 ] = curNodes[ indT[ j ]];
break; break;
} }
isOk = true; toRemove = false;
break; break;
} }
} }
@ -7769,18 +7851,20 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes,
// set a top node // set a top node
const int* indTop = hexa.GetFaceNodesIndices( iFace ); const int* indTop = hexa.GetFaceNodesIndices( iFace );
uniqueNodes.push_back( curNodes[indTop[ 0 ]]); uniqueNodes.push_back( curNodes[indTop[ 0 ]]);
isOk = true; toRemove = false;
} }
break; break;
} }
} }
} }
if ( !isOk && nbUniqueNodes > 4 ) { if ( toRemove && nbUniqueNodes > 4 ) {
////////////////// HEXAHEDRON ---> polyhedron ////////////////// HEXAHEDRON ---> polyhedron
hexa.SetExternalNormal(); hexa.SetExternalNormal();
vector<const SMDS_MeshNode *> poly_nodes; poly_nodes.reserve( 6 * 4 ); vector<const SMDS_MeshNode *>& poly_nodes = newElemDefs[0].myNodes;
vector<int> quantities; quantities.reserve( 6 ); vector<int> & quantities = newElemDefs[0].myPolyhedQuantities;
poly_nodes.reserve( 6 * 4 ); poly_nodes.clear();
quantities.reserve( 6 ); quantities.clear();
for ( int iFace = 0; iFace < 6; iFace++ ) for ( int iFace = 0; iFace < 6; iFace++ )
{ {
const int *ind = hexa.GetFaceNodesIndices( iFace ); // indices of face nodes const int *ind = hexa.GetFaceNodesIndices( iFace ); // indices of face nodes
@ -7803,53 +7887,38 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes,
} }
if ( quantities.size() >= 4 ) if ( quantities.size() >= 4 )
{ {
const SMDS_MeshElement* newElem = aMesh->AddPolyhedralVolume( poly_nodes, quantities ); nbResElems = 1;
myLastCreatedElems.Append( newElem ); nbUniqueNodes = poly_nodes.size();
if ( aShapeId && newElem ) newElemDefs[0].SetPoly(true);
aMesh->SetMeshElementOnShape( newElem, aShapeId );
rmElemIds.push_back( elem->GetID() );
} }
} }
break; break;
} // case HEXAHEDRON } // case HEXAHEDRON
default: default:
isOk = false; toRemove = true;
} // switch ( nbNodes )
} // switch ( entity )
if ( toRemove && nbResElems == 0 && avoidMakingHoles )
{
// 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 } // if ( nbNodes != nbUniqueNodes ) // some nodes stick
if ( isOk ) // a non-poly elem remains valid after sticking nodes
{
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 ); 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() );
}
} // loop on elements if ( !toRemove && nbResElems == 0 )
nbResElems = 1;
// Remove bad elements, then equal nodes (order important) newElemDefs.resize( nbResElems );
Remove( rmElemIds, false ); return !toRemove;
Remove( rmNodeIds, true );
return;
} }

View File

@ -88,6 +88,7 @@ public:
int myID; int myID;
double myBallDiameter; double myBallDiameter;
std::vector<int> myPolyhedQuantities; std::vector<int> myPolyhedQuantities;
std::vector<const SMDS_MeshNode*> myNodes; // not managed by ElemFeatures
SMESH_EXPORT ElemFeatures( SMDSAbs_ElementType type=SMDSAbs_All, bool isPoly=false, bool isQuad=false ) SMESH_EXPORT ElemFeatures( SMDSAbs_ElementType type=SMDSAbs_All, bool isPoly=false, bool isQuad=false )
:myType( type ), myIsPoly(isPoly), myIsQuad(isQuad), myID(-1), myBallDiameter(0) {} :myType( type ), myIsPoly(isPoly), myIsQuad(isQuad), myID(-1), myBallDiameter(0) {}
@ -750,6 +751,20 @@ public:
const size_t nbSteps, const size_t nbSteps,
SMESH_SequenceOfElemPtr& srcElements); 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 * \brief Create 1D and 2D elements around swept elements
* \param mapNewNodes - source nodes and ones generated from them * \param mapNewNodes - source nodes and ones generated from them
@ -782,11 +797,11 @@ public:
double Angle ()const { return myAngle; } double Angle ()const { return myAngle; }
double Parameter ()const { return myPrm; } double Parameter ()const { return myPrm; }
}; };
Extrusion_Error MakeEdgePathPoints(std::list<double>& aPrms, Extrusion_Error makeEdgePathPoints(std::list<double>& aPrms,
const TopoDS_Edge& aTrackEdge, const TopoDS_Edge& aTrackEdge,
bool aFirstIsStart, bool aFirstIsStart,
std::list<SMESH_MeshEditor_PathPoint>& aLPP); std::list<SMESH_MeshEditor_PathPoint>& aLPP);
Extrusion_Error MakeExtrElements(TIDSortedElemSet theElements[2], Extrusion_Error makeExtrElements(TIDSortedElemSet theElements[2],
std::list<SMESH_MeshEditor_PathPoint>& theFullList, std::list<SMESH_MeshEditor_PathPoint>& theFullList,
const bool theHasAngles, const bool theHasAngles,
std::list<double>& theAngles, std::list<double>& theAngles,
@ -794,7 +809,7 @@ public:
const bool theHasRefPoint, const bool theHasRefPoint,
const gp_Pnt& theRefPoint, const gp_Pnt& theRefPoint,
const bool theMakeGroups); const bool theMakeGroups);
static void LinearAngleVariation(const int NbSteps, static void linearAngleVariation(const int NbSteps,
std::list<double>& theAngles); std::list<double>& theAngles);
bool doubleNodes( SMESHDS_Mesh* theMeshDS, bool doubleNodes( SMESHDS_Mesh* theMeshDS,

View File

@ -215,29 +215,34 @@ namespace
QStringList filter; QStringList filter;
std::string myExtension; 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( "MED_FILES_FILTER" ) + " (*.*med)" );
filter.append( QObject::tr( "ALL_FILES_FILTER" ) + " (*)" ); 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)" ); 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)" ); 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)" ); 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)" ); 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( "SAUV files (*.sauv*)" ) );
filter.append( QObject::tr( "All files (*)" ) ); 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_ASCII_FILES_FILTER" ) + " (*.mesh)" );
filter.append( QObject::tr( "GMF_BINARY_FILES_FILTER") + " (*.meshb)" ); filter.append( QObject::tr( "GMF_BINARY_FILES_FILTER") + " (*.meshb)" );
} }
@ -283,6 +288,7 @@ namespace
try { try {
switch ( theCommandID ) { switch ( theCommandID ) {
case SMESHOp::OpImportDAT: case SMESHOp::OpImportDAT:
case SMESHOp::OpPopupImportDAT:
{ {
// DAT format (currently unsupported) // DAT format (currently unsupported)
errors.append( QString( "%1 :\n\t%2" ).arg( filename ). errors.append( QString( "%1 :\n\t%2" ).arg( filename ).
@ -290,6 +296,7 @@ namespace
break; break;
} }
case SMESHOp::OpImportUNV: case SMESHOp::OpImportUNV:
case SMESHOp::OpPopupImportUNV:
{ {
// UNV format // UNV format
aMeshes->length( 1 ); aMeshes->length( 1 );
@ -300,6 +307,7 @@ namespace
break; break;
} }
case SMESHOp::OpImportMED: case SMESHOp::OpImportMED:
case SMESHOp::OpPopupImportMED:
{ {
// MED format // MED format
SMESH::DriverMED_ReadStatus res; SMESH::DriverMED_ReadStatus res;
@ -311,6 +319,7 @@ namespace
break; break;
} }
case SMESHOp::OpImportSTL: case SMESHOp::OpImportSTL:
case SMESHOp::OpPopupImportSTL:
{ {
// STL format // STL format
aMeshes->length( 1 ); aMeshes->length( 1 );
@ -321,8 +330,8 @@ namespace
} }
break; break;
} }
#ifdef WITH_CGNS
case SMESHOp::OpImportCGNS: case SMESHOp::OpImportCGNS:
case SMESHOp::OpPopupImportCGNS:
{ {
// CGNS format // CGNS format
SMESH::DriverMED_ReadStatus res; SMESH::DriverMED_ReadStatus res;
@ -333,8 +342,8 @@ namespace
} }
break; break;
} }
#endif
case SMESHOp::OpImportSAUV: case SMESHOp::OpImportSAUV:
case SMESHOp::OpPopupImportSAUV:
{ {
// SAUV format // SAUV format
SMESH::DriverMED_ReadStatus res; SMESH::DriverMED_ReadStatus res;
@ -346,6 +355,7 @@ namespace
break; break;
} }
case SMESHOp::OpImportGMF: case SMESHOp::OpImportGMF:
case SMESHOp::OpPopupImportGMF:
{ {
// GMF format // GMF format
SMESH::ComputeError_var res; SMESH::ComputeError_var res;
@ -433,12 +443,8 @@ namespace
theCommandID == SMESHOp::OpPopupExportUNV ); theCommandID == SMESHOp::OpPopupExportUNV );
const bool isSTL = ( theCommandID == SMESHOp::OpExportSTL || const bool isSTL = ( theCommandID == SMESHOp::OpExportSTL ||
theCommandID == SMESHOp::OpPopupExportSTL ); theCommandID == SMESHOp::OpPopupExportSTL );
#ifdef WITH_CGNS
const bool isCGNS= ( theCommandID == SMESHOp::OpExportCGNS || const bool isCGNS= ( theCommandID == SMESHOp::OpExportCGNS ||
theCommandID == SMESHOp::OpPopupExportCGNS ); theCommandID == SMESHOp::OpPopupExportCGNS );
#else
const bool isCGNS= false;
#endif
const bool isSAUV= ( theCommandID == SMESHOp::OpExportSAUV || const bool isSAUV= ( theCommandID == SMESHOp::OpExportSAUV ||
theCommandID == SMESHOp::OpPopupExportSAUV ); theCommandID == SMESHOp::OpPopupExportSAUV );
const bool isGMF = ( theCommandID == SMESHOp::OpExportGMF || const bool isGMF = ( theCommandID == SMESHOp::OpExportGMF ||
@ -2451,11 +2457,16 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
case SMESHOp::OpImportUNV: case SMESHOp::OpImportUNV:
case SMESHOp::OpImportMED: case SMESHOp::OpImportMED:
case SMESHOp::OpImportSTL: case SMESHOp::OpImportSTL:
#ifdef WITH_CGNS
case SMESHOp::OpImportCGNS: case SMESHOp::OpImportCGNS:
#endif
case SMESHOp::OpImportSAUV: case SMESHOp::OpImportSAUV:
case SMESHOp::OpImportGMF: 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; if(checkLock(aStudy)) break;
::ImportMeshesFromFile(GetSMESHGen(),theCommandID); ::ImportMeshesFromFile(GetSMESHGen(),theCommandID);
@ -2484,18 +2495,14 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
case SMESHOp::OpExportMED: case SMESHOp::OpExportMED:
case SMESHOp::OpExportUNV: case SMESHOp::OpExportUNV:
case SMESHOp::OpExportSTL: case SMESHOp::OpExportSTL:
#ifdef WITH_CGNS
case SMESHOp::OpExportCGNS: case SMESHOp::OpExportCGNS:
#endif
case SMESHOp::OpExportSAUV: case SMESHOp::OpExportSAUV:
case SMESHOp::OpExportGMF: case SMESHOp::OpExportGMF:
case SMESHOp::OpPopupExportDAT: case SMESHOp::OpPopupExportDAT:
case SMESHOp::OpPopupExportMED: case SMESHOp::OpPopupExportMED:
case SMESHOp::OpPopupExportUNV: case SMESHOp::OpPopupExportUNV:
case SMESHOp::OpPopupExportSTL: case SMESHOp::OpPopupExportSTL:
#ifdef WITH_CGNS
case SMESHOp::OpPopupExportCGNS: case SMESHOp::OpPopupExportCGNS:
#endif
case SMESHOp::OpPopupExportSAUV: case SMESHOp::OpPopupExportSAUV:
case SMESHOp::OpPopupExportGMF: case SMESHOp::OpPopupExportGMF:
{ {
@ -2671,9 +2678,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
extractContainers( sel_objects, to_process ); extractContainers( sel_objects, to_process );
try { try {
#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
OCC_CATCH_SIGNALS; OCC_CATCH_SIGNALS;
#endif
if (vtkwnd) { if (vtkwnd) {
SALOME_ListIteratorOfListIO It( to_process ); SALOME_ListIteratorOfListIO It( to_process );
for ( ; It.More(); It.Next()) 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::OpImportDAT, "IMPORT_DAT", "", (Qt::CTRL+Qt::Key_B) );
createSMESHAction( SMESHOp::OpImportUNV, "IMPORT_UNV", "", (Qt::CTRL+Qt::Key_I) ); createSMESHAction( SMESHOp::OpImportUNV, "IMPORT_UNV", "", (Qt::CTRL+Qt::Key_I) );
createSMESHAction( SMESHOp::OpImportMED, "IMPORT_MED", "", (Qt::CTRL+Qt::Key_M) ); createSMESHAction( SMESHOp::OpImportMED, "IMPORT_MED", "", (Qt::CTRL+Qt::Key_M) );
//createSMESHAction( 114, "NUM" );
createSMESHAction( SMESHOp::OpImportSTL, "IMPORT_STL" ); createSMESHAction( SMESHOp::OpImportSTL, "IMPORT_STL" );
#ifdef WITH_CGNS #ifdef WITH_CGNS
createSMESHAction( SMESHOp::OpImportCGNS, "IMPORT_CGNS" ); createSMESHAction( SMESHOp::OpImportCGNS, "IMPORT_CGNS" );
#endif #endif
createSMESHAction( SMESHOp::OpImportSAUV, "IMPORT_SAUV" ); createSMESHAction( SMESHOp::OpImportSAUV, "IMPORT_SAUV" );
createSMESHAction( SMESHOp::OpImportGMF, "IMPORT_GMF" ); 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::OpExportDAT, "DAT" );
createSMESHAction( SMESHOp::OpExportMED, "MED" ); createSMESHAction( SMESHOp::OpExportMED, "MED" );
createSMESHAction( SMESHOp::OpExportUNV, "UNV" ); createSMESHAction( SMESHOp::OpExportUNV, "UNV" );
@ -4364,6 +4377,7 @@ void SMESHGUI::initialize( CAM_Application* app )
group = pat.arg( SMESHGUI_Selection::typeName( SMESH::GROUP ) ), group = pat.arg( SMESHGUI_Selection::typeName( SMESH::GROUP ) ),
hypo = pat.arg( SMESHGUI_Selection::typeName( SMESH::HYPOTHESIS ) ), hypo = pat.arg( SMESHGUI_Selection::typeName( SMESH::HYPOTHESIS ) ),
algo = pat.arg( SMESHGUI_Selection::typeName( SMESH::ALGORITHM ) ), algo = pat.arg( SMESHGUI_Selection::typeName( SMESH::ALGORITHM ) ),
smesh = pat.arg( SMESHGUI_Selection::typeName( SMESH::COMPONENT ) ),
elems = QString( "'%1' '%2' '%3' '%4' '%5' '%6'" ). elems = QString( "'%1' '%2' '%3' '%4' '%5' '%6'" ).
arg( SMESHGUI_Selection::typeName( SMESH::SUBMESH_VERTEX ) ). arg( SMESHGUI_Selection::typeName( SMESH::SUBMESH_VERTEX ) ).
arg( SMESHGUI_Selection::typeName( SMESH::SUBMESH_EDGE ) ). 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::OpPopupExportDAT, OB, mesh_group, only_one_non_empty, anId );
createPopupItem( SMESHOp::OpDelete, OB, mesh_part + " " + hyp_alg ); createPopupItem( SMESHOp::OpDelete, OB, mesh_part + " " + hyp_alg );
createPopupItem( SMESHOp::OpDeleteGroup, OB, group ); 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 ); popupMgr()->insert( separator(), -1, 0 );
// popup for viewer // popup for viewer

View File

@ -135,7 +135,7 @@ SMESHGUI_BuildCompoundDlg::SMESHGUI_BuildCompoundDlg( SMESHGUI* theModule )
CheckBoxMerge = new QCheckBox(tr("MERGE_NODES_AND_ELEMENTS"), GroupArgs); CheckBoxMerge = new QCheckBox(tr("MERGE_NODES_AND_ELEMENTS"), GroupArgs);
TextLabelTol = new QLabel(tr("SMESH_TOLERANCE"), GroupArgs); TextLabelTol = new QLabel(tr("SMESH_TOLERANCE"), GroupArgs);
TextLabelTol->setAlignment(Qt::AlignCenter); //TextLabelTol->setAlignment(Qt::AlignCenter);
SpinBoxTol = new SMESHGUI_SpinBox(GroupArgs); SpinBoxTol = new SMESHGUI_SpinBox(GroupArgs);
SpinBoxTol->RangeStepAndValidator(0.0, COORD_MAX, 0.00001, "len_tol_precision" ); SpinBoxTol->RangeStepAndValidator(0.0, COORD_MAX, 0.00001, "len_tol_precision" );
@ -146,8 +146,8 @@ SMESHGUI_BuildCompoundDlg::SMESHGUI_BuildCompoundDlg( SMESHGUI* theModule )
GroupArgsLayout->addWidget(ComboBoxUnion, 1, 3); GroupArgsLayout->addWidget(ComboBoxUnion, 1, 3);
GroupArgsLayout->addWidget(CheckBoxCommon, 2, 0, 1, 4); GroupArgsLayout->addWidget(CheckBoxCommon, 2, 0, 1, 4);
GroupArgsLayout->addWidget(CheckBoxMerge, 3, 0, 1, 4); GroupArgsLayout->addWidget(CheckBoxMerge, 3, 0, 1, 4);
GroupArgsLayout->addWidget(TextLabelTol, 4, 0, 1, 2); GroupArgsLayout->addWidget(TextLabelTol, 4, 0);
GroupArgsLayout->addWidget(SpinBoxTol, 4, 2, 1, 2); GroupArgsLayout->addWidget(SpinBoxTol, 4, 1, 1, 3);
/***************************************************************/ /***************************************************************/
GroupButtons = new QGroupBox(this); GroupButtons = new QGroupBox(this);
@ -289,6 +289,8 @@ bool SMESHGUI_BuildCompoundDlg::ClickOnApply()
if (!isValid()) if (!isValid())
return false; return false;
SUIT_OverrideCursor aWaitCursor;
SMESH::SMESH_Mesh_var aMesh; SMESH::SMESH_Mesh_var aMesh;
if (!myMesh->_is_nil()) if (!myMesh->_is_nil())
@ -298,7 +300,6 @@ bool SMESHGUI_BuildCompoundDlg::ClickOnApply()
QStringList anEntryList; QStringList anEntryList;
try { try {
SUIT_OverrideCursor aWaitCursor;
aMesh = myMeshArray[0]->GetMesh(); aMesh = myMeshArray[0]->GetMesh();
aMesh->SetParameters( aParameters.join(":").toLatin1().constData() ); aMesh->SetParameters( aParameters.join(":").toLatin1().constData() );

View File

@ -191,6 +191,9 @@ SMESHGUI_MergeDlg::SMESHGUI_MergeDlg (SMESHGUI* theModule, int theAction)
SeparateCornersAndMedium = new QCheckBox(tr("SEPARATE_CORNERS_AND_MEDIUM"), NodeSpecWidget ); SeparateCornersAndMedium = new QCheckBox(tr("SEPARATE_CORNERS_AND_MEDIUM"), NodeSpecWidget );
SeparateCornersAndMedium->setEnabled( false ); SeparateCornersAndMedium->setEnabled( false );
AvoidMakingHoles = new QCheckBox(tr("AVOID_MAKING_HOLES"), NodeSpecWidget );
AvoidMakingHoles->setChecked( false );
QGridLayout* NodeSpecLayout = new QGridLayout(NodeSpecWidget); QGridLayout* NodeSpecLayout = new QGridLayout(NodeSpecWidget);
NodeSpecLayout->setSpacing(SPACING); NodeSpecLayout->setSpacing(SPACING);
NodeSpecLayout->setMargin(0); NodeSpecLayout->setMargin(0);
@ -198,6 +201,7 @@ SMESHGUI_MergeDlg::SMESHGUI_MergeDlg (SMESHGUI* theModule, int theAction)
NodeSpecLayout->addWidget(TextLabelTolerance, 0, 0 ); NodeSpecLayout->addWidget(TextLabelTolerance, 0, 0 );
NodeSpecLayout->addWidget(SpinBoxTolerance, 0, 1 ); NodeSpecLayout->addWidget(SpinBoxTolerance, 0, 1 );
NodeSpecLayout->addWidget(SeparateCornersAndMedium, 1, 0, 1, 2 ); NodeSpecLayout->addWidget(SeparateCornersAndMedium, 1, 0, 1, 2 );
NodeSpecLayout->addWidget(AvoidMakingHoles, 2, 0, 1, 2 );
/***************************************************************/ /***************************************************************/
// Exclude groups // Exclude groups
@ -585,7 +589,7 @@ bool SMESHGUI_MergeDlg::ClickOnApply()
} }
if( myAction == MERGE_NODES ) if( myAction == MERGE_NODES )
aMeshEditor->MergeNodes (aGroupsOfElements.inout(), nodesToKeep); aMeshEditor->MergeNodes( aGroupsOfElements.inout(), nodesToKeep, AvoidMakingHoles->isChecked() );
else else
aMeshEditor->MergeElements( aGroupsOfElements.inout() ); aMeshEditor->MergeElements( aGroupsOfElements.inout() );

View File

@ -130,6 +130,7 @@ private:
QWidget* NodeSpecWidget; QWidget* NodeSpecWidget;
SMESHGUI_SpinBox* SpinBoxTolerance; SMESHGUI_SpinBox* SpinBoxTolerance;
QCheckBox* SeparateCornersAndMedium; QCheckBox* SeparateCornersAndMedium;
QCheckBox* AvoidMakingHoles;
QGroupBox* GroupCoincident; QGroupBox* GroupCoincident;
//QWidget* GroupCoincidentWidget; //QWidget* GroupCoincidentWidget;

View File

@ -32,37 +32,36 @@ namespace SMESHOp {
OpShowScalarBar = 1022, // SHOW SCALAR BAR OpShowScalarBar = 1022, // SHOW SCALAR BAR
OpSaveDistribution = 1030, // SAVE DISTRIBUTION OpSaveDistribution = 1030, // SAVE DISTRIBUTION
OpShowDistribution = 1031, // SHOW DISTRIBUTION OpShowDistribution = 1031, // SHOW DISTRIBUTION
#ifndef DISABLE_PLOT2DVIEWER
OpPlotDistribution = 1032, // PLOT DISTRIBUTION OpPlotDistribution = 1032, // PLOT DISTRIBUTION
#endif
OpFileInformation = 1040, // POPUP MENU - FILE INFORMATION OpFileInformation = 1040, // POPUP MENU - FILE INFORMATION
// Import -------------------------//-------------------------------- // Import -------------------------//--------------------------------
OpImportDAT = 1100, // MENU FILE - IMPORT - DAT FILE OpImportDAT = 1100, // MENU FILE - IMPORT - DAT FILE
OpImportUNV = 1101, // MENU FILE - IMPORT - UNV FILE OpImportUNV = 1101, // MENU FILE - IMPORT - UNV FILE
OpImportMED = 1102, // MENU FILE - IMPORT - MED FILE OpImportMED = 1102, // MENU FILE - IMPORT - MED FILE
OpImportSTL = 1103, // MENU FILE - IMPORT - STL FILE OpImportSTL = 1103, // MENU FILE - IMPORT - STL FILE
#ifdef WITH_CGNS
OpImportCGNS = 1104, // MENU FILE - IMPORT - CGNS FILE OpImportCGNS = 1104, // MENU FILE - IMPORT - CGNS FILE
#endif
OpImportSAUV = 1105, // MENU FILE - IMPORT - SAUV FILE OpImportSAUV = 1105, // MENU FILE - IMPORT - SAUV FILE
OpImportGMF = 1106, // MENU FILE - IMPORT - GMF 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 -------------------------//-------------------------------- // Export -------------------------//--------------------------------
OpExportDAT = 1200, // MENU FILE - EXPORT - DAT FILE OpExportDAT = 1200, // MENU FILE - EXPORT - DAT FILE
OpExportMED = 1201, // MENU FILE - EXPORT - MED FILE OpExportMED = 1201, // MENU FILE - EXPORT - MED FILE
OpExportUNV = 1202, // MENU FILE - EXPORT - UNV FILE OpExportUNV = 1202, // MENU FILE - EXPORT - UNV FILE
OpExportSTL = 1203, // MENU FILE - EXPORT - STL FILE OpExportSTL = 1203, // MENU FILE - EXPORT - STL FILE
#ifdef WITH_CGNS
OpExportCGNS = 1204, // MENU FILE - EXPORT - CGNS FILE OpExportCGNS = 1204, // MENU FILE - EXPORT - CGNS FILE
#endif
OpExportSAUV = 1205, // MENU FILE - EXPORT - SAUV FILE OpExportSAUV = 1205, // MENU FILE - EXPORT - SAUV FILE
OpExportGMF = 1206, // MENU FILE - EXPORT - GMF FILE OpExportGMF = 1206, // MENU FILE - EXPORT - GMF FILE
OpPopupExportDAT = 1210, // POPUP MENU - EXPORT - DAT FILE OpPopupExportDAT = 1210, // POPUP MENU - EXPORT - DAT FILE
OpPopupExportMED = 1211, // POPUP MENU - EXPORT - MED FILE OpPopupExportMED = 1211, // POPUP MENU - EXPORT - MED FILE
OpPopupExportUNV = 1212, // POPUP MENU - EXPORT - UNV FILE OpPopupExportUNV = 1212, // POPUP MENU - EXPORT - UNV FILE
OpPopupExportSTL = 1213, // POPUP MENU - EXPORT - STL FILE OpPopupExportSTL = 1213, // POPUP MENU - EXPORT - STL FILE
#ifdef WITH_CGNS
OpPopupExportCGNS = 1214, // POPUP MENU - EXPORT - CGNS FILE OpPopupExportCGNS = 1214, // POPUP MENU - EXPORT - CGNS FILE
#endif
OpPopupExportSAUV = 1215, // POPUP MENU - EXPORT - SAUV FILE OpPopupExportSAUV = 1215, // POPUP MENU - EXPORT - SAUV FILE
OpPopupExportGMF = 1216, // POPUP MENU - EXPORT - GMF FILE OpPopupExportGMF = 1216, // POPUP MENU - EXPORT - GMF FILE
// Mesh ---------------------------//-------------------------------- // Mesh ---------------------------//--------------------------------

View File

@ -762,6 +762,7 @@ namespace SMESH
if ((anActor = CreateActor(aDocument,theEntry,true))) { if ((anActor = CreateActor(aDocument,theEntry,true))) {
bool needFitAll = noSmeshActors(theWnd); // fit for the first object only bool needFitAll = noSmeshActors(theWnd); // fit for the first object only
DisplayActor(theWnd,anActor); DisplayActor(theWnd,anActor);
anActor->SetVisibility(true);
aStudy->setVisibilityState(theEntry, Qtx::ShownState); aStudy->setVisibilityState(theEntry, Qtx::ShownState);
// FitAll(); - PAL16770(Display of a group performs an automatic fit all) // FitAll(); - PAL16770(Display of a group performs an automatic fit all)
if (needFitAll) FitAll(); if (needFitAll) FitAll();

View File

@ -5322,6 +5322,10 @@ Please select a group and try again</translation>
<source>SEPARATE_CORNERS_AND_MEDIUM</source> <source>SEPARATE_CORNERS_AND_MEDIUM</source>
<translation>No merge of corner and medium nodes of quadratic cells</translation> <translation>No merge of corner and medium nodes of quadratic cells</translation>
</message> </message>
<message>
<source>AVOID_MAKING_HOLES</source>
<translation>Avoid making holes</translation>
</message>
<message> <message>
<source>KEEP_NODES</source> <source>KEEP_NODES</source>
<translation>Nodes to keep during the merge</translation> <translation>Nodes to keep during the merge</translation>

View File

@ -83,6 +83,7 @@ SET(SMESHUtils_SOURCES
SMESH_MAT2d.cxx SMESH_MAT2d.cxx
SMESH_FreeBorders.cxx SMESH_FreeBorders.cxx
SMESH_ControlPnt.cxx SMESH_ControlPnt.cxx
SMESH_DeMerge.cxx
) )
# --- rules --- # --- rules ---

View File

@ -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<const SMDS_MeshNode*>::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:;
}
}

View File

@ -206,6 +206,16 @@ namespace SMESH_MeshAlgos
CoincidentFreeBorders & foundFreeBordes); 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 #endif

View File

@ -480,7 +480,6 @@ SMESH::long_array* SMESH_GroupBase_i::GetListOfID()
if ( 0 < aSize && aSize < 100 ) // for comfortable testing ;) if ( 0 < aSize && aSize < 100 ) // for comfortable testing ;)
std::sort( &aRes[0], &aRes[0]+aSize ); std::sort( &aRes[0], &aRes[0]+aSize );
} }
MESSAGE("get list of IDs of a vague group");
return aRes._retn(); return aRes._retn();
} }
@ -673,7 +672,6 @@ void SMESH_GroupBase_i::SetColorNumber(CORBA::Long color)
aGroupDS->SetColorGroup(color); aGroupDS->SetColorGroup(color);
TPythonDump()<<SMESH::SMESH_GroupBase_var(_this())<<".SetColorNumber( "<<color<<" )"; TPythonDump()<<SMESH::SMESH_GroupBase_var(_this())<<".SetColorNumber( "<<color<<" )";
} }
MESSAGE("set color number of a group");
return ; return ;
} }

View File

@ -4159,7 +4159,8 @@ FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr theObject,
//======================================================================= //=======================================================================
void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes, 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) throw (SALOME::SALOME_Exception)
{ {
SMESH_TRY; SMESH_TRY;
@ -4203,9 +4204,9 @@ void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfN
aTPythonDump << aNodeGroup; aTPythonDump << aNodeGroup;
} }
getEditor().MergeNodes( aListOfListOfNodes ); getEditor().MergeNodes( aListOfListOfNodes, AvoidMakingHoles );
aTPythonDump << "], " << NodesToKeep << ")"; aTPythonDump << "], " << NodesToKeep << ", " << AvoidMakingHoles << ")";
declareMeshModified( /*isReComputeSafe=*/false ); declareMeshModified( /*isReComputeSafe=*/false );

View File

@ -495,7 +495,8 @@ public:
CORBA::Boolean SeparateCornersAndMedium) CORBA::Boolean SeparateCornersAndMedium)
throw (SALOME::SALOME_Exception); throw (SALOME::SALOME_Exception);
void MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes, void MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes,
const SMESH::ListOfIDSources& NodesToKeep ) const SMESH::ListOfIDSources& NodesToKeep,
CORBA::Boolean AvoidMakingHoles )
throw (SALOME::SALOME_Exception); throw (SALOME::SALOME_Exception);
void FindEqualElements(SMESH::SMESH_IDSource_ptr Object, void FindEqualElements(SMESH::SMESH_IDSource_ptr Object,
SMESH::array_of_long_array_out GroupsOfElementsID) SMESH::array_of_long_array_out GroupsOfElementsID)

View File

@ -496,7 +496,13 @@ int SMESH_Mesh_i::ImportSTLFile( const char* theFileName )
SMESH_TRY; SMESH_TRY;
// Read mesh with name = <theMeshName> into SMESH_Mesh // Read mesh with name = <theMeshName> 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 ); 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()) TPythonDump() << SMESH::SMESH_Mesh_var(_this())
<< ".ExportSTL( r'" << file << "', " << isascii << " )"; << ".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 // Perform Export
PrepareForWriting( file ); PrepareForWriting( file );
_impl->ExportSTL(file, isascii); _impl->ExportSTL( file, isascii, name.in() );
} }
//================================================================================ //================================================================================
@ -3595,8 +3607,14 @@ void SMESH_Mesh_i::ExportPartToSTL(::SMESH::SMESH_IDSource_ptr meshPart,
PrepareForWriting(file); 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 ); SMESH_MeshPartDS partDS( meshPart );
_impl->ExportSTL(file, isascii, &partDS); _impl->ExportSTL( file, isascii, name.in(), &partDS );
TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportPartToSTL( " TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportPartToSTL( "
<< meshPart<< ", r'" << file << "', " << isascii << ")"; << meshPart<< ", r'" << file << "', " << isascii << ")";

View File

@ -4561,10 +4561,12 @@ class Mesh(metaclass=MeshMeta):
# @param NodesToKeep nodes to keep in the mesh: a list of groups, sub-meshes or node IDs. # @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, # If @a NodesToKeep does not include a node to keep for some group to merge,
# then the first node in the group is kept. # 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 # @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() # 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. ## Find the elements built on the same nodes.
# @param MeshOrSubMeshOrGroup Mesh or SubMesh, or Group of elements for searching # @param MeshOrSubMeshOrGroup Mesh or SubMesh, or Group of elements for searching
@ -5120,17 +5122,18 @@ class meshEditor(SMESH._objref_SMESH_MeshEditor):
def FindCoincidentNodesOnPart(self,*args): # a 3d arg added (SeparateCornerAndMediumNodes) def FindCoincidentNodesOnPart(self,*args): # a 3d arg added (SeparateCornerAndMediumNodes)
if len( args ) == 2: args += False, if len( args ) == 2: args += False,
return SMESH._objref_SMESH_MeshEditor.FindCoincidentNodesOnPart( self, *args ) 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: 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] NodesToKeep = args[1]
AvoidMakingHoles = args[2] if len( args ) == 3 else False
unRegister = genObjUnRegister() unRegister = genObjUnRegister()
if NodesToKeep: if NodesToKeep:
if isinstance( NodesToKeep, list ) and isinstance( NodesToKeep[0], int ): if isinstance( NodesToKeep, list ) and isinstance( NodesToKeep[0], int ):
NodesToKeep = self.MakeIDSource( NodesToKeep, SMESH.NODE ) NodesToKeep = self.MakeIDSource( NodesToKeep, SMESH.NODE )
if not isinstance( NodesToKeep, list ): if not isinstance( NodesToKeep, list ):
NodesToKeep = [ NodesToKeep ] NodesToKeep = [ NodesToKeep ]
return SMESH._objref_SMESH_MeshEditor.MergeNodes( self, args[0], NodesToKeep ) return SMESH._objref_SMESH_MeshEditor.MergeNodes( self, args[0], NodesToKeep, AvoidMakingHoles )
pass pass
omniORB.registerObjref(SMESH._objref_SMESH_MeshEditor._NP_RepositoryId, meshEditor) omniORB.registerObjref(SMESH._objref_SMESH_MeshEditor._NP_RepositoryId, meshEditor)

View File

@ -1865,14 +1865,18 @@ SMESH_ComputeErrorPtr _ViscousBuilder::Compute(SMESH_Mesh& theMesh,
size_t iSD = 0; size_t iSD = 0;
for ( iSD = 0; iSD < _sdVec.size(); ++iSD ) // find next SOLID to compute for ( iSD = 0; iSD < _sdVec.size(); ++iSD ) // find next SOLID to compute
if ( _sdVec[iSD]._before.IsEmpty() && if ( _sdVec[iSD]._before.IsEmpty() &&
!_sdVec[iSD]._solid.IsNull() &&
_sdVec[iSD]._n2eMap.empty() ) _sdVec[iSD]._n2eMap.empty() )
break; break;
if ( ! makeLayer(_sdVec[iSD]) ) // create _LayerEdge's if ( ! makeLayer(_sdVec[iSD]) ) // create _LayerEdge's
return _error; return _error;
if ( _sdVec[iSD]._n2eMap.size() == 0 ) if ( _sdVec[iSD]._n2eMap.size() == 0 ) // no layers in a SOLID
{
_sdVec[iSD]._solid.Nullify();
continue; continue;
}
if ( ! inflate(_sdVec[iSD]) ) // increase length of _LayerEdge's if ( ! inflate(_sdVec[iSD]) ) // increase length of _LayerEdge's
return _error; return _error;
@ -9049,7 +9053,7 @@ void _LayerEdge::Block( _SolidData& data )
minDist = Min( pSrc.SquareDistance( pTgtN ), minDist ); minDist = Min( pSrc.SquareDistance( pTgtN ), minDist );
minDist = Min( pTgt.SquareDistance( pSrcN ), minDist ); minDist = Min( pTgt.SquareDistance( pSrcN ), minDist );
double newMaxLen = edge->_maxLen + 0.5 * Sqrt( minDist ); double newMaxLen = edge->_maxLen + 0.5 * Sqrt( minDist );
if ( edge->_nodes[0]->getshapeId() == neibor->_nodes[0]->getshapeId() ) //if ( edge->_nodes[0]->getshapeId() == neibor->_nodes[0]->getshapeId() ) viscous_layers_00/A3
{ {
newMaxLen *= edge->_lenFactor / neibor->_lenFactor; newMaxLen *= edge->_lenFactor / neibor->_lenFactor;
} }