1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-19 13:40:49 +03:00

0033171: Modeling Algorithms - Invalid result of faces unification

Avoid unification of the faces belonging to the different shells.
This commit is contained in:
Eugeny Maltchikov
2022-10-13 17:44:47 +03:00
committed by Vadim Glukhikh
parent eeba62cbd3
commit d444cc35c6
4 changed files with 208 additions and 4 deletions

View File

@@ -2745,6 +2745,26 @@ void ShapeUpgrade_UnifySameDomain::UnifyFaces()
for (Standard_Integer i = 1; i <= aFaceMap.Extent(); i++)
TopExp::MapShapesAndAncestors (aFaceMap(i), TopAbs_EDGE, TopAbs_FACE, aGMapEdgeFaces);
// creating map of face shells for the whole shape to avoid
// unification of faces belonging to the different shells
DataMapOfShapeMapOfShape aGMapFaceShells;
for (TopExp_Explorer anExp (myShape, TopAbs_SHELL); anExp.More(); anExp.Next())
{
const TopoDS_Shape& aShell = anExp.Current();
for (TopoDS_Iterator anItF (aShell); anItF.More(); anItF.Next())
{
const TopoDS_Shape& aF = anItF.Value();
if (TopTools_MapOfShape* pShells = aGMapFaceShells.ChangeSeek (aF))
{
pShells->Add (aShell);
}
else
{
(aGMapFaceShells.Bound (aF, TopTools_MapOfShape()))->Add (aShell);
}
}
}
// creating map of free boundaries
TopTools_MapOfShape aFreeBoundMap;
// look at only shells not belonging to solids
@@ -2766,7 +2786,7 @@ void ShapeUpgrade_UnifySameDomain::UnifyFaces()
// unify faces in each shell separately
TopExp_Explorer exps;
for (exps.Init(myShape, TopAbs_SHELL); exps.More(); exps.Next())
IntUnifyFaces(exps.Current(), aGMapEdgeFaces, aFreeBoundMap);
IntUnifyFaces(exps.Current(), aGMapEdgeFaces, aGMapFaceShells, aFreeBoundMap);
// gather all faces out of shells in one compound and unify them at once
BRep_Builder aBB;
@@ -2777,7 +2797,10 @@ void ShapeUpgrade_UnifySameDomain::UnifyFaces()
aBB.Add(aCmp, exps.Current());
if (nbf > 0)
IntUnifyFaces(aCmp, aGMapEdgeFaces, aFreeBoundMap);
{
// No connection to shells, thus no need to pass the face-shell map
IntUnifyFaces(aCmp, aGMapEdgeFaces, DataMapOfShapeMapOfShape(), aFreeBoundMap);
}
myShape = myContext->Apply(myShape);
}
@@ -2800,13 +2823,52 @@ static void SetFixWireModes(ShapeFix_Face& theSff)
aFixWire->FixSmallMode() = 0;
}
//=======================================================================
//function : isSameSets
//purpose : Compares two sets of shapes. Returns true if they are the same,
// false otherwise.
//=======================================================================
template<class Container>
static Standard_Boolean isSameSets(const Container* theFShells1,
const Container* theFShells2)
{
// If both are null - no problem
if (theFShells1 == nullptr && theFShells2 == nullptr)
{
return Standard_True;
}
// If only one is null - not the same
if (theFShells1 == nullptr || theFShells2 == nullptr)
{
return Standard_False;
}
// Both not null
if (theFShells1->Extent() != theFShells2->Extent())
{
return Standard_False;
}
// number of shells in each set should be very small in normal cases - max 2.
// thus just check if all objects of one are contained in the other and vice versa.
for (typename Container::Iterator it1(*theFShells1), it2(*theFShells2);
it1.More() && it2.More(); it1.Next(), it2.Next())
{
if (!theFShells1->Contains(it2.Value()) || !theFShells2->Contains(it1.Value()))
{
return Standard_False;
}
}
return Standard_True;
}
//=======================================================================
//function : IntUnifyFaces
//purpose :
//=======================================================================
void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape,
TopTools_IndexedDataMapOfShapeListOfShape& theGMapEdgeFaces,
const TopTools_IndexedDataMapOfShapeListOfShape& theGMapEdgeFaces,
const DataMapOfShapeMapOfShape& theGMapFaceShells,
const TopTools_MapOfShape& theFreeBoundMap)
{
// creating map of edge faces for the shape
@@ -2855,6 +2917,9 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
Standard_Real Uperiod = (aBaseSurface->IsUPeriodic())? aBaseSurface->UPeriod() : 0.;
Standard_Real Vperiod = (aBaseSurface->IsVPeriodic())? aBaseSurface->VPeriod() : 0.;
// Get shells connected to the face (in normal cases should not be more than 2)
const TopTools_MapOfShape* pFShells1 = theGMapFaceShells.Seek (aFace);
// find adjacent faces to union
Standard_Integer i;
for (i = 1; i <= edges.Length(); i++) {
@@ -2903,6 +2968,15 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
if (aProcessed.Contains(aCheckedFace))
continue;
// Get shells connected to the checked face
const TopTools_MapOfShape* pFShells2 = theGMapFaceShells.Seek (aCheckedFace);
// Faces can be unified only if the shells of faces connected to
// these faces are the same. Otherwise, topology would be broken.
if (!isSameSets (pFShells1, pFShells2))
{
continue;
}
if (bCheckNormals) {
// get normal of checked face using the same parameter on edge
gp_Dir aDN2;