mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-10 18:51:21 +03:00
0033227: Modeling Algorithm - BOPAlgo_BuilderSolid generates incomplete result
Deleted outer loop for shells. Added additional check of edges orientation for RefineShell().
This commit is contained in:
parent
cbf6b87074
commit
bffd568302
@ -248,167 +248,178 @@ void BOPAlgo_ShellSplitter::SplitBlock(BOPTools_ConnexityBlock& aCB)
|
|||||||
//
|
//
|
||||||
// Build the shells
|
// Build the shells
|
||||||
aItF.Initialize (aLFConnected);
|
aItF.Initialize (aLFConnected);
|
||||||
for (i = 1; aItF.More() && !bAllFacesTaken; aItF.Next(), ++i) {
|
for (i = 1; aItF.More() && !bAllFacesTaken; aItF.Next(), ++i)
|
||||||
|
{
|
||||||
const TopoDS_Shape& aFF = aItF.Value();
|
const TopoDS_Shape& aFF = aItF.Value();
|
||||||
if (!AddedFacesMap.Add(aFF)) {
|
if (!AddedFacesMap.Add(aFF)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// make a new shell
|
// make a new shell
|
||||||
TopoDS_Shell aShellStart;
|
TopoDS_Shell aShell;
|
||||||
aBB.MakeShell(aShellStart);
|
aBB.MakeShell(aShell);
|
||||||
aBB.Add(aShellStart, aFF);
|
aBB.Add(aShell, aFF);
|
||||||
|
|
||||||
|
aMEFP.Clear();
|
||||||
|
TopExp::MapShapesAndAncestors(aShell, TopAbs_EDGE, TopAbs_FACE, aMEFP);
|
||||||
//
|
//
|
||||||
TopTools_ListOfShape aLShells;
|
// loop on faces added to Shell;
|
||||||
aLShells.Append(aShellStart);
|
// add their neighbor faces to Shell and so on
|
||||||
//
|
aItS.Initialize(aShell);
|
||||||
TopTools_ListIteratorOfListOfShape aItLShells(aLShells);
|
for (; aItS.More(); aItS.Next()) {
|
||||||
for (; aItLShells.More(); aItLShells.Next()) {
|
const TopoDS_Face& aF = (*(TopoDS_Face*)(&aItS.Value()));
|
||||||
TopoDS_Shell& aShell = TopoDS::Shell(aItLShells.ChangeValue());
|
Standard_Boolean isBoundary = aBoundaryFaces.Contains (aF);
|
||||||
//
|
//
|
||||||
aMEFP.Clear();
|
// loop on edges of aF; find a good neighbor face of aF by aE
|
||||||
TopExp::MapShapesAndAncestors(aShell, TopAbs_EDGE, TopAbs_FACE, aMEFP);
|
aExp.Init(aF, TopAbs_EDGE);
|
||||||
//
|
for (; aExp.More(); aExp.Next()) {
|
||||||
// loop on faces added to Shell;
|
const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aExp.Current()));
|
||||||
// add their neighbor faces to Shell and so on
|
|
||||||
aItS.Initialize(aShell);
|
|
||||||
for (; aItS.More(); aItS.Next()) {
|
|
||||||
const TopoDS_Face& aF = (*(TopoDS_Face*)(&aItS.Value()));
|
|
||||||
Standard_Boolean isBoundary = aBoundaryFaces.Contains (aF);
|
|
||||||
//
|
//
|
||||||
// loop on edges of aF; find a good neighbor face of aF by aE
|
// proceed only free edges in this shell
|
||||||
aExp.Init(aF, TopAbs_EDGE);
|
if (aMEFP.Contains(aE)) {
|
||||||
for (; aExp.More(); aExp.Next()) {
|
const TopTools_ListOfShape& aLFP = aMEFP.FindFromKey(aE);
|
||||||
const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aExp.Current()));
|
aNbFP = aLFP.Extent();
|
||||||
//
|
if (aNbFP > 1) {
|
||||||
// proceed only free edges in this shell
|
|
||||||
if (aMEFP.Contains(aE)) {
|
|
||||||
const TopTools_ListOfShape& aLFP = aMEFP.FindFromKey(aE);
|
|
||||||
aNbFP = aLFP.Extent();
|
|
||||||
if (aNbFP > 1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// avoid processing of internal edges
|
|
||||||
anOr = aE.Orientation();
|
|
||||||
if (anOr == TopAbs_INTERNAL) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// avoid processing of degenerated edges
|
}
|
||||||
if (BRep_Tool::Degenerated(aE)) {
|
// avoid processing of internal edges
|
||||||
|
anOr = aE.Orientation();
|
||||||
|
if (anOr == TopAbs_INTERNAL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// avoid processing of degenerated edges
|
||||||
|
if (BRep_Tool::Degenerated(aE)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// candidate faces list
|
||||||
|
const TopTools_ListOfShape& aLF = aEFMap.FindFromKey(aE);
|
||||||
|
aNbLF = aLF.Extent();
|
||||||
|
if (!aNbLF) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// prepare for selecting the next face
|
||||||
|
// take only not-processed faces as a candidates
|
||||||
|
BOPTools_ListOfCoupleOfShape aLCSOff;
|
||||||
|
//
|
||||||
|
Standard_Integer aNbWaysInside = 0;
|
||||||
|
TopoDS_Face aSelF;
|
||||||
|
TopTools_ListIteratorOfListOfShape aItLF(aLF);
|
||||||
|
for (; aItLF.More(); aItLF.Next()) {
|
||||||
|
const TopoDS_Face& aFL = (*(TopoDS_Face*)(&aItLF.Value()));
|
||||||
|
if (aF.IsSame(aFL) || AddedFacesMap.Contains(aFL)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// candidate faces list
|
// find current edge in the face
|
||||||
const TopTools_ListOfShape& aLF = aEFMap.FindFromKey(aE);
|
if (!BOPTools_AlgoTools::GetEdgeOff(aE, aFL, aEL)) {
|
||||||
aNbLF = aLF.Extent();
|
|
||||||
if (!aNbLF) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// prepare for selecting the next face
|
if (isBoundary && !aBoundaryFaces.Contains (aFL))
|
||||||
// take only not-processed faces as a candidates
|
|
||||||
BOPTools_ListOfCoupleOfShape aLCSOff;
|
|
||||||
//
|
|
||||||
Standard_Integer aNbWaysInside = 0;
|
|
||||||
TopoDS_Face aSelF;
|
|
||||||
TopTools_ListIteratorOfListOfShape aItLF(aLF);
|
|
||||||
for (; aItLF.More(); aItLF.Next()) {
|
|
||||||
const TopoDS_Face& aFL = (*(TopoDS_Face*)(&aItLF.Value()));
|
|
||||||
if (aF.IsSame(aFL) || AddedFacesMap.Contains(aFL)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// find current edge in the face
|
|
||||||
if (!BOPTools_AlgoTools::GetEdgeOff(aE, aFL, aEL)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
if (isBoundary && !aBoundaryFaces.Contains (aFL))
|
|
||||||
{
|
|
||||||
++aNbWaysInside;
|
|
||||||
aSelF = aFL;
|
|
||||||
}
|
|
||||||
aCSOff.SetShape1(aEL);
|
|
||||||
aCSOff.SetShape2(aFL);
|
|
||||||
aLCSOff.Append(aCSOff);
|
|
||||||
}//for (; aItLF.More(); aItLF.Next()) {
|
|
||||||
//
|
|
||||||
aNbOff = aLCSOff.Extent();
|
|
||||||
if (!aNbOff){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// among all the adjacent faces chose one with the minimal
|
|
||||||
// angle to the current one
|
|
||||||
if (!isBoundary || aNbWaysInside != 1)
|
|
||||||
{
|
{
|
||||||
if (aNbOff == 1) {
|
++aNbWaysInside;
|
||||||
aSelF = (*(TopoDS_Face*)(&aLCSOff.First().Shape2()));
|
aSelF = aFL;
|
||||||
}
|
|
||||||
else if (aNbOff > 1) {
|
|
||||||
BOPTools_AlgoTools::GetFaceOff(aE, aF, aLCSOff, aSelF, aContext);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
//
|
aCSOff.SetShape1(aEL);
|
||||||
if (!aSelF.IsNull() && AddedFacesMap.Add(aSelF)) {
|
aCSOff.SetShape2(aFL);
|
||||||
aBB.Add(aShell, aSelF);
|
aLCSOff.Append(aCSOff);
|
||||||
TopExp::MapShapesAndAncestors(aSelF, TopAbs_EDGE, TopAbs_FACE, aMEFP);
|
}//for (; aItLF.More(); aItLF.Next()) {
|
||||||
}
|
|
||||||
} // for (; aExp.More(); aExp.Next()) {
|
|
||||||
} // for (; aItS.More(); aItS.Next()) {
|
|
||||||
//
|
|
||||||
// split the shell on multi-connected edges
|
|
||||||
TopTools_ListOfShape aLShSp;
|
|
||||||
RefineShell(aShell, aMEFP, aLShSp);
|
|
||||||
//
|
|
||||||
// collect the not closed shells for further processing
|
|
||||||
TopTools_ListOfShape aLShNC;
|
|
||||||
//
|
|
||||||
TopTools_ListIteratorOfListOfShape aItLShSp(aLShSp);
|
|
||||||
for (; aItLShSp.More(); aItLShSp.Next()) {
|
|
||||||
TopoDS_Shell& aShSp = *((TopoDS_Shell*)&aItLShSp.Value());
|
|
||||||
//
|
//
|
||||||
if (BRep_Tool::IsClosed(aShSp)) {
|
aNbOff = aLCSOff.Extent();
|
||||||
aShSp.Closed(Standard_True);
|
if (!aNbOff){
|
||||||
myLoops.Append(aShSp);
|
continue;
|
||||||
}
|
}
|
||||||
else {
|
//
|
||||||
aLShNC.Append(aShSp);
|
// among all the adjacent faces chose one with the minimal
|
||||||
}
|
// angle to the current one
|
||||||
}
|
if (!isBoundary || aNbWaysInside != 1)
|
||||||
//
|
{
|
||||||
bAllFacesTaken = (AddedFacesMap.Extent() == aNbShapes);
|
if (aNbOff == 1) {
|
||||||
if (bAllFacesTaken) {
|
aSelF = (*(TopoDS_Face*)(&aLCSOff.First().Shape2()));
|
||||||
break;
|
}
|
||||||
}
|
else if (aNbOff > 1) {
|
||||||
//
|
BOPTools_AlgoTools::GetFaceOff(aE, aF, aLCSOff, aSelF, aContext);
|
||||||
if (aLShSp.Extent() == 1) {
|
|
||||||
// not further processing of not closed shells is needed,
|
|
||||||
// as it will not bring any new results
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
Standard_Integer aNbShNC = aLShNC.Extent();
|
|
||||||
if (aNbShNC == 1) {
|
|
||||||
// try to complete the shell with other faces
|
|
||||||
aLShells.Append(aLShNC);
|
|
||||||
}
|
|
||||||
else if (aNbShNC > 1) {
|
|
||||||
// remove th faces of not closed shells from the map of processed faces
|
|
||||||
// and try to rebuild the shells using all not processed faces,
|
|
||||||
// because faces of one shell might be needed for building the other
|
|
||||||
TopTools_ListIteratorOfListOfShape aItLShNC(aLShNC);
|
|
||||||
for (; aItLShNC.More(); aItLShNC.Next()) {
|
|
||||||
TopoDS_Iterator aItNC(aItLShNC.Value());
|
|
||||||
for (; aItNC.More(); aItNC.Next()) {
|
|
||||||
AddedFacesMap.Remove(aItNC.Value());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
if (!aSelF.IsNull() && AddedFacesMap.Add(aSelF)) {
|
||||||
|
aBB.Add(aShell, aSelF);
|
||||||
|
TopExp::MapShapesAndAncestors(aSelF, TopAbs_EDGE, TopAbs_FACE, aMEFP);
|
||||||
|
}
|
||||||
|
} // for (; aExp.More(); aExp.Next()) {
|
||||||
|
} // for (; aItS.More(); aItS.Next()) {
|
||||||
|
//
|
||||||
|
// split the shell on multi-connected edges
|
||||||
|
TopTools_ListOfShape aLShSp;
|
||||||
|
RefineShell(aShell, aMEFP, aLShSp);
|
||||||
|
//
|
||||||
|
// collect the not closed shells for further processing
|
||||||
|
TopTools_ListOfShape aLShNC;
|
||||||
|
//
|
||||||
|
TopTools_ListIteratorOfListOfShape aItLShSp(aLShSp);
|
||||||
|
for (; aItLShSp.More(); aItLShSp.Next()) {
|
||||||
|
TopoDS_Shell& aShSp = *((TopoDS_Shell*)&aItLShSp.Value());
|
||||||
|
//
|
||||||
|
if (BRep_Tool::IsClosed(aShSp)) {
|
||||||
|
aShSp.Closed(Standard_True);
|
||||||
|
myLoops.Append(aShSp);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
aLShNC.Append(aShSp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
bAllFacesTaken = (AddedFacesMap.Extent() == aNbShapes);
|
||||||
|
if (bAllFacesTaken) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
if (aLShSp.Extent() == 1) {
|
||||||
|
// not further processing of not closed shells is needed,
|
||||||
|
// as it will not bring any new results
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
|
||||||
|
// remove th faces of not closed shells from the map of processed faces
|
||||||
|
// and try to rebuild the shells using all not processed faces,
|
||||||
|
// because faces of one shell might be needed for building the other
|
||||||
|
TopTools_ListIteratorOfListOfShape aItLShNC(aLShNC);
|
||||||
|
for (; aItLShNC.More(); aItLShNC.Next())
|
||||||
|
{
|
||||||
|
TopoDS_Iterator aItNC(aItLShNC.Value());
|
||||||
|
for (; aItNC.More(); aItNC.Next())
|
||||||
|
{
|
||||||
|
AddedFacesMap.Remove(aItNC.Value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // for (; aItF.More(); aItF.Next()) {
|
} // for (; aItF.More(); aItF.Next()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//=======================================================================
|
||||||
|
//function : FindShape
|
||||||
|
//purpose :
|
||||||
|
//=======================================================================
|
||||||
|
TopoDS_Shape FindShape (const TopoDS_Shape& theShapeToFind,
|
||||||
|
const TopoDS_Shape& theShape)
|
||||||
|
{
|
||||||
|
TopoDS_Shape aRes;
|
||||||
|
TopExp_Explorer anExp(theShape, theShapeToFind.ShapeType());
|
||||||
|
for (; anExp.More(); anExp.Next())
|
||||||
|
{
|
||||||
|
const TopoDS_Shape& aShape = anExp.Current();
|
||||||
|
if (aShape.IsSame(theShapeToFind))
|
||||||
|
{
|
||||||
|
aRes = aShape;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return aRes;
|
||||||
|
}
|
||||||
|
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
//function : RefineShell
|
//function : RefineShell
|
||||||
//purpose :
|
//purpose :
|
||||||
@ -434,6 +445,21 @@ void RefineShell(TopoDS_Shell& theShell,
|
|||||||
aMEStop.Add(aE);
|
aMEStop.Add(aE);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (aLF.Extent() == 2)
|
||||||
|
{
|
||||||
|
const TopoDS_Face& aF1 = TopoDS::Face(aLF.First());
|
||||||
|
const TopoDS_Face& aF2 = TopoDS::Face(aLF.Last());
|
||||||
|
|
||||||
|
TopoDS_Shape aE1 = FindShape(aE, aF1);
|
||||||
|
TopoDS_Shape aE2 = FindShape(aE, aF2);
|
||||||
|
|
||||||
|
if (aE1.Orientation() == aE2.Orientation())
|
||||||
|
{
|
||||||
|
aMEStop.Add(aE);
|
||||||
|
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
|
||||||
|
13
tests/bugs/modalg_8/bug33227
Normal file
13
tests/bugs/modalg_8/bug33227
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
puts "============"
|
||||||
|
puts "0033227: Modeling Algorithm - BOPAlgo_BuilderSolid generates incomplete result"
|
||||||
|
puts "============"
|
||||||
|
puts ""
|
||||||
|
|
||||||
|
restore [locate_data_file bug33227.brep] s
|
||||||
|
bopbsolid r s
|
||||||
|
compound r_2 r_3 res
|
||||||
|
|
||||||
|
checknbshapes res -shell 6 -solid 2
|
||||||
|
checkprops res -v 3.33117e+07
|
||||||
|
|
||||||
|
checkview -display res -2d -path ${imagedir}/${test_image}.png
|
Loading…
x
Reference in New Issue
Block a user