#17336 [CEA 17333] Mesh offset generates a segmentation violation

This commit is contained in:
eap 2020-03-18 15:36:19 +03:00
parent 230046ed89
commit 24a8566eb1
2 changed files with 58 additions and 6 deletions

View File

@ -712,6 +712,53 @@ namespace
return useOneNormal; return useOneNormal;
} }
//================================================================================
/*!
* \brief Remove small faces
*/
//================================================================================
void removeSmallFaces( SMDS_Mesh* theMesh,
SMESH_MeshAlgos::TElemIntPairVec& theNew2OldFaces,
const double theTol2 )
{
std::vector< SMESH_NodeXYZ > points(3);
std::vector< const SMDS_MeshNode* > nodes(3);
for ( SMDS_ElemIteratorPtr faceIt = theMesh->elementsIterator(); faceIt->more(); )
{
const SMDS_MeshElement* face = faceIt->next();
points.assign( face->begin_nodes(), face->end_nodes() );
SMESH_NodeXYZ* prevN = & points.back();
for ( size_t i = 0; i < points.size(); ++i )
{
double dist2 = ( *prevN - points[ i ]).SquareModulus();
if ( dist2 < theTol2 )
{
const SMDS_MeshNode* nToRemove =
(*prevN)->GetID() > points[ i ]->GetID() ? prevN->Node() : points[ i ].Node();
const SMDS_MeshNode* nToKeep =
nToRemove == points[ i ].Node() ? prevN->Node() : points[ i ].Node();
for ( SMDS_ElemIteratorPtr fIt = nToRemove->GetInverseElementIterator(); fIt->more(); )
{
const SMDS_MeshElement* f = fIt->next();
if ( f == face )
continue;
nodes.assign( f->begin_nodes(), f->end_nodes() );
nodes[ f->GetNodeIndex( nToRemove )] = nToKeep;
theMesh->ChangeElementNodes( f, &nodes[0], nodes.size() );
}
theNew2OldFaces[ face->GetID() ].first = 0;
theMesh->RemoveFreeElement( face );
break;
}
prevN = & points[ i ];
}
continue;
}
return;
}
} // namespace } // namespace
namespace SMESH_MeshAlgos namespace SMESH_MeshAlgos
@ -1239,6 +1286,8 @@ namespace SMESH_MeshAlgos
if ( !link2.IntNode() ) link2.myIntNode = link1.myIntNode; if ( !link2.IntNode() ) link2.myIntNode = link1.myIntNode;
cf1.AddPoint( link1, link2, myTol ); cf1.AddPoint( link1, link2, myTol );
if ( l1n1 ) link1.Set( l1n1, l1n2, face2 );
if ( l2n1 ) link2.Set( l2n1, l2n2, face2 );
cf2.AddPoint( link1, link2, myTol ); cf2.AddPoint( link1, link2, myTol );
} }
else else
@ -3251,6 +3300,8 @@ SMDS_Mesh* SMESH_MeshAlgos::MakeOffset( SMDS_ElemIteratorPtr theFaceIt,
// mark all new nodes located closer than theOffset from theSrcMesh // mark all new nodes located closer than theOffset from theSrcMesh
} }
removeSmallFaces( newMesh, theNew2OldFaces, tol*tol );
// ================================================== // ==================================================
// find self-intersections of new faces and fix them // find self-intersections of new faces and fix them
// ================================================== // ==================================================
@ -3261,8 +3312,9 @@ SMDS_Mesh* SMESH_MeshAlgos::MakeOffset( SMDS_ElemIteratorPtr theFaceIt,
Intersector intersector( newMesh, tol, normals ); Intersector intersector( newMesh, tol, normals );
std::vector< const SMDS_MeshElement* > closeFaces; std::vector< const SMDS_MeshElement* > closeFaces;
std::vector< const SMDS_MeshNode* > faceNodes; std::vector< SMESH_NodeXYZ > faceNodes;
Bnd_B3d faceBox; Bnd_B3d faceBox;
for ( size_t iF = 1; iF < theNew2OldFaces.size(); ++iF ) for ( size_t iF = 1; iF < theNew2OldFaces.size(); ++iF )
{ {
const SMDS_MeshElement* newFace = theNew2OldFaces[iF].first; const SMDS_MeshElement* newFace = theNew2OldFaces[iF].first;
@ -3277,7 +3329,7 @@ SMDS_Mesh* SMESH_MeshAlgos::MakeOffset( SMDS_ElemIteratorPtr theFaceIt,
closeFaces.clear(); closeFaces.clear();
faceBox.Clear(); faceBox.Clear();
for ( size_t i = 0; i < faceNodes.size(); ++i ) for ( size_t i = 0; i < faceNodes.size(); ++i )
faceBox.Add( SMESH_NodeXYZ( faceNodes[i] )); faceBox.Add( faceNodes[i] );
faceBox.Enlarge( tol ); faceBox.Enlarge( tol );
fSearcher->GetElementsInBox( faceBox, SMDSAbs_Face, closeFaces ); fSearcher->GetElementsInBox( faceBox, SMDSAbs_Face, closeFaces );
@ -3293,7 +3345,7 @@ SMDS_Mesh* SMESH_MeshAlgos::MakeOffset( SMDS_ElemIteratorPtr theFaceIt,
// do not intersect connected faces if they have no concave nodes // do not intersect connected faces if they have no concave nodes
int nbCommonNodes = 0; int nbCommonNodes = 0;
for ( size_t iN = 0; iN < faceNodes.size(); ++iN ) for ( size_t iN = 0; iN < faceNodes.size(); ++iN )
nbCommonNodes += ( closeFace->GetNodeIndex( faceNodes[iN] ) >= 0 ); nbCommonNodes += ( closeFace->GetNodeIndex( faceNodes[iN].Node() ) >= 0 );
if ( !isConcaveNode1 ) if ( !isConcaveNode1 )
{ {
@ -3312,7 +3364,7 @@ SMDS_Mesh* SMESH_MeshAlgos::MakeOffset( SMDS_ElemIteratorPtr theFaceIt,
intersector.Cut( newFace, closeFace, nbCommonNodes ); intersector.Cut( newFace, closeFace, nbCommonNodes );
} }
} }
intersector.MakeNewFaces( theNew2OldFaces, theNew2OldNodes, sign ); intersector.MakeNewFaces( theNew2OldFaces, theNew2OldNodes, sign, /*optimize=*/true );
return newMesh; return newMesh;
} }

View File

@ -6374,8 +6374,8 @@ class Mesh(metaclass = MeshMeta):
theValue,Parameters,hasVars = ParseParameters(Value) theValue,Parameters,hasVars = ParseParameters(Value)
mesh_groups = self.editor.Offset(theObject, Value, MakeGroups, CopyElements, NewMeshName) mesh_groups = self.editor.Offset(theObject, Value, MakeGroups, CopyElements, NewMeshName)
self.mesh.SetParameters(Parameters) self.mesh.SetParameters(Parameters)
# if mesh_groups[0]: if mesh_groups[0]:
# return Mesh( self.smeshpyD, self.geompyD, mesh_groups[0] ), mesh_groups[1] return Mesh( self.smeshpyD, self.geompyD, mesh_groups[0] ), mesh_groups[1]
return mesh_groups return mesh_groups
def FindCoincidentNodes (self, Tolerance, SeparateCornerAndMediumNodes=False): def FindCoincidentNodes (self, Tolerance, SeparateCornerAndMediumNodes=False):