1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-14 13:30:48 +03:00

Compare commits

...

1 Commits

Author SHA1 Message Date
emv
067edee488 0029324: Incomplete result of Volume Maker algorithm
When splitting the shells (BOPAlgo_ShellSplitter::SplitBlock()) on multi-connected edges avoid producing shell with odd number of faces on any edges.

Test case for the issue.
2017-11-15 10:45:14 +03:00
2 changed files with 142 additions and 95 deletions

View File

@@ -273,7 +273,7 @@ void BOPAlgo_ShellSplitter::SplitBlock(BOPTools_ConnexityBlock& aCB)
if (aMEFP.Contains(aE)) { if (aMEFP.Contains(aE)) {
const BOPCol_ListOfShape& aLFP = aMEFP.FindFromKey(aE); const BOPCol_ListOfShape& aLFP = aMEFP.FindFromKey(aE);
aNbFP = aLFP.Extent(); aNbFP = aLFP.Extent();
if (aNbFP > 1) { if (!(aNbFP % 2)) {
continue; continue;
} }
} }
@@ -397,134 +397,164 @@ void RefineShell(TopoDS_Shell& theShell,
BOPCol_ListOfShape& theLShSp) BOPCol_ListOfShape& theLShSp)
{ {
TopoDS_Iterator aIt(theShell); TopoDS_Iterator aIt(theShell);
if(!aIt.More()) { if (!aIt.More())
// No faces in the shell
return; return;
}
// // Find edges with more than two adjacent faces - branch edges -
// Find edges with more than 2 adjacent faces - branch edges -
// edges on which the input shell should be split // edges on which the input shell should be split
BOPCol_MapOfShape aMEStop; BOPCol_MapOfShape aMEStop;
// //
Standard_Integer i, aNbMEF = theMEF.Extent(); Standard_Integer i, aNbMEF = theMEF.Extent();
for (i = 1; i <= aNbMEF; ++i) { for (i = 1; i <= aNbMEF; ++i)
const TopoDS_Edge& aE = TopoDS::Edge(theMEF.FindKey(i)); {
const TopoDS_Shape& aE = theMEF.FindKey(i);
const BOPCol_ListOfShape& aLF = theMEF(i); const BOPCol_ListOfShape& aLF = theMEF(i);
if (aLF.Extent() > 2) { if (aLF.Extent() > 2)
{
aMEStop.Add(aE); aMEStop.Add(aE);
continue; continue;
} }
//
// check for internal edges - count faces, in which the edge // check for internal edges - count faces, in which the edge
// is internal, twice // is internal, twice
Standard_Integer aNbF = 0; Standard_Integer aNbF = 0;
BOPCol_ListIteratorOfListOfShape aItLF(aLF); BOPCol_ListIteratorOfListOfShape aItLF(aLF);
for (; aItLF.More() && aNbF <= 2; aItLF.Next()) { for (; aItLF.More() && aNbF <= 2; aItLF.Next())
const TopoDS_Face& aF = TopoDS::Face(aItLF.Value()); {
const TopoDS_Shape& aF = aItLF.Value();
++aNbF; ++aNbF;
TopExp_Explorer aExp(aF, TopAbs_EDGE); TopExp_Explorer aExp(aF, TopAbs_EDGE);
for (; aExp.More(); aExp.Next()) { for (; aExp.More(); aExp.Next())
{
const TopoDS_Shape& aEF = aExp.Current(); const TopoDS_Shape& aEF = aExp.Current();
if (aEF.IsSame(aE)) { if (aEF.IsSame(aE))
if (aEF.Orientation() == TopAbs_INTERNAL) { {
if (aEF.Orientation() == TopAbs_INTERNAL)
++aNbF; ++aNbF;
}
break; break;
} }
} }
} }
// //
if (aNbF > 2) { if (aNbF > 2)
aMEStop.Add(aE); aMEStop.Add(aE);
}
} }
// //
if (aMEStop.IsEmpty()) { if (aMEStop.IsEmpty())
{
theLShSp.Append(theShell); theLShSp.Append(theShell);
return; return;
} }
//
TopoDS_Builder aBB; // Try to split the shell on the branch edges
TopExp_Explorer aExp;
BOPCol_IndexedMapOfShape aMFB; // Global map of processed faces
BOPCol_MapOfOrientedShape aMFProcessed; BOPCol_MapOfOrientedShape aMFProcessed;
BOPCol_ListOfShape aLFP, aLFP1;
BOPCol_ListIteratorOfListOfShape aItLF, aItLFP; // Prepare copies of the iterator and map of processed faces
// // to have possibility to revert the process in case we have
// The first Face // produced the shell with an odd number of faces on edges
for (; aIt.More(); aIt.Next()) { TopoDS_Iterator aItSaved = aIt;
const TopoDS_Shape& aF1 = aIt.Value(); BOPCol_MapOfOrientedShape aMFPSaved;
if (!aMFProcessed.Add(aF1)) {
continue; for (; aIt.More();)
} {
// // Now the iteration will be performed on the global maps.
aMFB.Clear(); // If all is OK, the copies will be just updated for future use
aLFP.Clear();
// for (; aIt.More(); aIt.Next())
aMFB.Add(aF1); {
aLFP.Append(aF1); const TopoDS_Shape& aFStart = aIt.Value();
// if (!aMFProcessed.Add(aFStart))
// Trying to reach the branch point // Face already processed
for (;;) { continue;
aItLFP.Initialize(aLFP);
for (; aItLFP.More(); aItLFP.Next()) { // Build the block of faces connected by the edges not contained
const TopoDS_Shape& aFP = aItLFP.Value(); // in the <aMEStop> map starting with the face <aFStart>
// BOPCol_IndexedMapOfShape aMFBlock;
aExp.Init(aFP, TopAbs_EDGE); aMFBlock.Add(aFStart);
for (; aExp.More(); aExp.Next()) {
const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aExp.Current())); for (i = 1; i <= aMFBlock.Extent(); ++i)
if (aMEStop.Contains(aE)) { {
const TopoDS_Shape& aFP = aMFBlock(i);
// Analyze the edges of the face
TopExp_Explorer anExpE(aFP, TopAbs_EDGE);
for (; anExpE.More(); anExpE.Next())
{
const TopoDS_Edge& aE = TopoDS::Edge(anExpE.Current());
// Avoid branch edges
if (aMEStop.Contains(aE))
continue; continue;
}
// // Avoid internal edges
if (aE.Orientation() == TopAbs_INTERNAL) { if (aE.Orientation() == TopAbs_INTERNAL)
continue; continue;
}
// // Avoid degenerated edges
if (BRep_Tool::Degenerated(aE)) { if (BRep_Tool::Degenerated(aE))
continue; continue;
}
// // Get all faces containing the edge
const BOPCol_ListOfShape& aLF = theMEF.FindFromKey(aE); const BOPCol_ListOfShape& aLF = theMEF.FindFromKey(aE);
// BOPCol_ListIteratorOfListOfShape aItLF(aLF);
aItLF.Initialize(aLF); for (; aItLF.More(); aItLF.Next())
for (; aItLF.More(); aItLF.Next()) { {
const TopoDS_Shape& aFP1 = aItLF.Value(); const TopoDS_Shape& aFToAdd = aItLF.Value();
if (aFP1.IsSame(aFP)) { if (aMFProcessed.Add(aFToAdd))
continue; aMFBlock.Add(aFToAdd);
} }
if (aMFB.Contains(aFP1)) { }
continue;
}
//
if (aMFProcessed.Add(aFP1)) {
aMFB.Add(aFP1);
aLFP1.Append(aFP1);
}
}// for (; aItLF.More(); aItLF.Next()) {
}// for (; aExp.More(); aExp.Next()) {
} // for (; aItLFP.More(); aItLFP.Next()) {
//
//
if (aLFP1.IsEmpty()) {
break;
} }
//
aLFP.Clear(); // Analyze the produced block - check if it does not contain
aLFP.Append(aLFP1); // any edges with odd number of faces on it.
}// for (;;) { // If it is - check if these edges are contained in the <aMEStop> map
// // remove them and revert the process
Standard_Integer aNbMFB = aMFB.Extent();
if (aNbMFB) { Standard_Integer aNbFBlock = aMFBlock.Extent();
TopoDS_Shell aShSp; if (aNbFBlock)
aBB.MakeShell(aShSp); {
// Standard_Boolean bToRevert = Standard_False;
for (i = 1; i <= aNbMFB; ++i) { // Edge-Face map of the block
const TopoDS_Shape& aFB = aMFB(i); BOPCol_IndexedDataMapOfShapeListOfShape aBEFMap;
aBB.Add(aShSp, aFB);
} for (i = 1; i <= aNbFBlock; ++i)
theLShSp.Append(aShSp); BOPTools::MapShapesAndAncestors(aMFBlock(i), TopAbs_EDGE, TopAbs_FACE, aBEFMap);
}
}//for (; aIt.More(); aIt.Next()) { Standard_Integer aNb = aBEFMap.Extent();
for (i = 1; i <= aNb; ++i)
{
if (aBEFMap(i).Extent() % 2)
{
const TopoDS_Shape& anEOdd = aBEFMap.FindKey(i);
if (aMEStop.Remove(anEOdd))
bToRevert = Standard_True;
}
}
if (bToRevert)
{
aIt = aItSaved;
aMFProcessed = aMFPSaved;
break;
}
// Make the shell of the faces
TopoDS_Shell aShSp;
BRep_Builder().MakeShell(aShSp);
for (i = 1; i <= aNbFBlock; ++i)
BRep_Builder().Add(aShSp, aMFBlock(i));
theLShSp.Append(aShSp);
// Update the copies
aItSaved = aIt;
aMFPSaved = aMFProcessed;
} // if (aNbFBlock)
} // for (; aIt.More(); aIt.Next())
} // for (; aIt.More();)
} }
//======================================================================= //=======================================================================
//function : MakeShells //function : MakeShells

View File

@@ -0,0 +1,17 @@
puts "========"
puts "OCC29324"
puts "========"
puts ""
#################################################
# Incomplete result of Volume Maker algorithm
#################################################
restore [locate_data_file bug29324_faces.brep] lf
mkvolume result lf -c -ai
checkshape result
checknbshapes result -vertex 32 -edge 52 -wire 26 -face 24 -shell 3 -solid 3
checkprops result -s 343.2 -v 140.976
checkview -display result -2d -path ${imagedir}/${test_image}.png