mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-19 13:40:49 +03:00
0031639: Modeling Algorithms - Offset algorithm incorrectly fills one of the holes
Check if unclassified edge may be added as neutral (invalid in one split, valid in other) by checking the SD faces in which the edge was classified.
This commit is contained in:
@@ -60,6 +60,7 @@
|
||||
#include <BOPTools_AlgoTools3D.hxx>
|
||||
#include <BOPTools_AlgoTools.hxx>
|
||||
#include <BOPTools_AlgoTools2D.hxx>
|
||||
#include <BOPTools_Set.hxx>
|
||||
|
||||
#include <IntTools_Context.hxx>
|
||||
#include <IntTools_ShrunkRange.hxx>
|
||||
@@ -170,6 +171,15 @@ static
|
||||
TopTools_MapOfShape& theEdgesInvalidByVertex,
|
||||
TopTools_MapOfShape& theEdgesValidByVertex);
|
||||
|
||||
static
|
||||
void FindInvalidEdges (const TopTools_ListOfShape& theLFOffset,
|
||||
const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
|
||||
const TopTools_IndexedMapOfShape& theInvEdges,
|
||||
const TopTools_IndexedMapOfShape& theValidEdges,
|
||||
BRepOffset_DataMapOfShapeIndexedMapOfShape& theLocInvEdges,
|
||||
BRepOffset_DataMapOfShapeMapOfShape& theLocValidEdges,
|
||||
BRepOffset_DataMapOfShapeMapOfShape& theNeutralEdges);
|
||||
|
||||
static
|
||||
void FindInvalidFaces(TopTools_ListOfShape& theLFImages,
|
||||
const TopTools_IndexedMapOfShape& theInvEdges,
|
||||
@@ -994,7 +1004,11 @@ void BuildSplitsOfFaces(const TopTools_ListOfShape& theLF,
|
||||
if (theInvEdges.IsEmpty() && theArtInvFaces.IsEmpty() && aDMFMIE.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
//
|
||||
|
||||
// Additional step to find invalid edges by checking unclassified edges
|
||||
// in the splits of SD faces
|
||||
FindInvalidEdges (aLFDone, theFImages, theInvEdges, theValidEdges, aDMFMIE, aDMFMVE, aDMFMNE);
|
||||
|
||||
#ifdef OFFSET_DEBUG
|
||||
// show invalid edges
|
||||
TopoDS_Compound aCEInv1;
|
||||
@@ -1918,6 +1932,175 @@ void FindInvalidEdges(const TopoDS_Face& theF,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
static void addAsNeutral (const TopoDS_Shape& theE,
|
||||
const TopoDS_Shape& theFInv,
|
||||
const TopoDS_Shape& theFVal,
|
||||
BRepOffset_DataMapOfShapeIndexedMapOfShape& theLocInvEdges,
|
||||
BRepOffset_DataMapOfShapeMapOfShape& theLocValidEdges)
|
||||
{
|
||||
TopTools_IndexedMapOfShape* pMEInv = theLocInvEdges.ChangeSeek (theFInv);
|
||||
if (!pMEInv)
|
||||
pMEInv = theLocInvEdges.Bound (theFInv, TopTools_IndexedMapOfShape());
|
||||
pMEInv->Add (theE);
|
||||
|
||||
TopTools_MapOfShape* pMEVal = theLocValidEdges.ChangeSeek (theFVal);
|
||||
if (!pMEVal)
|
||||
pMEVal = theLocValidEdges.Bound (theFVal, TopTools_MapOfShape());
|
||||
pMEVal->Add (theE);
|
||||
}
|
||||
|
||||
}
|
||||
//=======================================================================
|
||||
//function : FindInvalidEdges
|
||||
//purpose : Additional method to look for invalid faces
|
||||
//=======================================================================
|
||||
void FindInvalidEdges (const TopTools_ListOfShape& theLFOffset,
|
||||
const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
|
||||
const TopTools_IndexedMapOfShape& theInvEdges,
|
||||
const TopTools_IndexedMapOfShape& theValidEdges,
|
||||
BRepOffset_DataMapOfShapeIndexedMapOfShape& theLocInvEdges,
|
||||
BRepOffset_DataMapOfShapeMapOfShape& theLocValidEdges,
|
||||
BRepOffset_DataMapOfShapeMapOfShape& theNeutralEdges)
|
||||
{
|
||||
// 1. Find edges unclassified in faces
|
||||
// 2. Find SD faces in which the same edge is classified
|
||||
// 3. Check if the edge is neutral in face in which it wasn't classified
|
||||
|
||||
NCollection_IndexedDataMap<TopoDS_Shape, TopTools_MapOfShape, TopTools_ShapeMapHasher> aMEUnclassified;
|
||||
TopTools_DataMapOfShapeShape aFSplitFOffset;
|
||||
|
||||
TopTools_IndexedDataMapOfShapeListOfShape anEFMap;
|
||||
for (TopTools_ListOfShape::Iterator itLFO (theLFOffset); itLFO.More(); itLFO.Next())
|
||||
{
|
||||
const TopoDS_Shape& aF = itLFO.Value();
|
||||
const TopTools_ListOfShape& aLFImages = theFImages.FindFromKey (aF);
|
||||
for (TopTools_ListOfShape::Iterator itLF (aLFImages); itLF.More(); itLF.Next())
|
||||
{
|
||||
const TopoDS_Shape& aFIm = itLF.Value();
|
||||
|
||||
TopExp::MapShapesAndAncestors (aFIm, TopAbs_EDGE, TopAbs_FACE, anEFMap);
|
||||
|
||||
const TopTools_IndexedMapOfShape* pMEInvalid = theLocInvEdges.Seek (aFIm);
|
||||
const TopTools_MapOfShape* pMEValid = theLocValidEdges.Seek (aFIm);
|
||||
|
||||
for (TopExp_Explorer expE (aFIm, TopAbs_EDGE); expE.More(); expE.Next())
|
||||
{
|
||||
const TopoDS_Shape& aE = expE.Current();
|
||||
if (theInvEdges.Contains (aE) != theValidEdges.Contains (aE))
|
||||
{
|
||||
// edge is classified in some face
|
||||
|
||||
if ((!pMEInvalid || !pMEInvalid->Contains (aE)) &&
|
||||
(!pMEValid || !pMEValid->Contains (aE)))
|
||||
{
|
||||
// but not in the current one
|
||||
TopTools_MapOfShape *pMap = aMEUnclassified.ChangeSeek (aE);
|
||||
if (!pMap)
|
||||
pMap = &aMEUnclassified (aMEUnclassified.Add (aE, TopTools_MapOfShape()));
|
||||
pMap->Add (aFIm);
|
||||
|
||||
aFSplitFOffset.Bind (aFIm, aF);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (aMEUnclassified.IsEmpty())
|
||||
return;
|
||||
|
||||
// Analyze unclassified edges
|
||||
const Standard_Integer aNbE = aMEUnclassified.Extent();
|
||||
for (Standard_Integer iE = 1; iE <= aNbE; ++iE)
|
||||
{
|
||||
const TopoDS_Shape& aE = aMEUnclassified.FindKey (iE);
|
||||
const TopTools_MapOfShape& aMFUnclassified = aMEUnclassified (iE);
|
||||
|
||||
const TopTools_ListOfShape& aLF = anEFMap.FindFromKey (aE);
|
||||
|
||||
for (TopTools_ListOfShape::Iterator itLF (aLF); itLF.More(); itLF.Next())
|
||||
{
|
||||
const TopoDS_Shape& aFClassified = itLF.Value();
|
||||
if (aMFUnclassified.Contains (aFClassified))
|
||||
continue;
|
||||
|
||||
BOPTools_Set anEdgeSetClass;
|
||||
anEdgeSetClass.Add (aFClassified, TopAbs_EDGE);
|
||||
|
||||
TopoDS_Shape aEClassified;
|
||||
FindShape (aE, aFClassified, aEClassified);
|
||||
TopAbs_Orientation anOriClass = aEClassified.Orientation();
|
||||
|
||||
gp_Dir aDNClass;
|
||||
BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (TopoDS::Edge (aEClassified), TopoDS::Face (aFClassified), aDNClass);
|
||||
|
||||
const TopTools_IndexedMapOfShape* pMEInvalid = theLocInvEdges.Seek (aFClassified);
|
||||
Standard_Boolean isInvalid = pMEInvalid && pMEInvalid->Contains (aE);
|
||||
|
||||
for (TopTools_MapOfShape::Iterator itM (aMFUnclassified); itM.More(); itM.Next())
|
||||
{
|
||||
const TopoDS_Shape& aFUnclassified = itM.Value();
|
||||
|
||||
BOPTools_Set anEdgeSetUnclass;
|
||||
anEdgeSetUnclass.Add (aFUnclassified, TopAbs_EDGE);
|
||||
|
||||
if (anEdgeSetClass.IsEqual (anEdgeSetUnclass))
|
||||
{
|
||||
gp_Dir aDNUnclass;
|
||||
BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (TopoDS::Edge (aE), TopoDS::Face (aFUnclassified), aDNUnclass);
|
||||
|
||||
Standard_Boolean isSameOri = aDNClass.IsEqual (aDNUnclass, Precision::Angular());
|
||||
|
||||
// Among other splits of the same face find those where the edge is contained with different
|
||||
// orientation
|
||||
const TopoDS_Shape& aFOffset = aFSplitFOffset.Find (aFUnclassified);
|
||||
const TopTools_ListOfShape& aLFSplits = theFImages.FindFromKey (aFOffset);
|
||||
TopTools_ListOfShape::Iterator itLFSp (aLFSplits);
|
||||
for (; itLFSp.More(); itLFSp.Next())
|
||||
{
|
||||
const TopoDS_Shape& aFSp = itLFSp.Value();
|
||||
|
||||
if (!aFSp.IsSame (aFUnclassified) && aMFUnclassified.Contains (aFSp))
|
||||
{
|
||||
TopoDS_Shape aEUnclassified;
|
||||
FindShape (aE, aFSp, aEUnclassified);
|
||||
|
||||
TopAbs_Orientation anOriUnclass = aEUnclassified.Orientation();
|
||||
if (!isSameOri)
|
||||
anOriUnclass = TopAbs::Reverse (anOriUnclass);
|
||||
|
||||
if (anOriClass != anOriUnclass)
|
||||
{
|
||||
// make the edge neutral for the face
|
||||
TopTools_MapOfShape* pMENeutral = theNeutralEdges.ChangeSeek (aFOffset);
|
||||
if (!pMENeutral)
|
||||
pMENeutral = theNeutralEdges.Bound (aFOffset, TopTools_MapOfShape());
|
||||
pMENeutral->Add (aE);
|
||||
|
||||
if (isInvalid && isSameOri)
|
||||
{
|
||||
// make edge invalid in aFUnclassified and valid in aFSp
|
||||
addAsNeutral (aE, aFClassified, aFSp, theLocInvEdges, theLocValidEdges);
|
||||
}
|
||||
else
|
||||
{
|
||||
// make edge invalid in aFSp and valid in aFUnclassified
|
||||
addAsNeutral (aE, aFSp, aFClassified, theLocInvEdges, theLocValidEdges);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (itLFSp.More())
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : FindInvalidFaces
|
||||
//purpose : Looking for the invalid faces by analyzing their invalid edges
|
||||
@@ -2014,7 +2197,7 @@ void FindInvalidFaces(TopTools_ListOfShape& theLFImages,
|
||||
//
|
||||
bValidLoc = pMVE && pMVE->Contains(aEIm);
|
||||
bInverted = theMEInverted.Contains(aEIm);
|
||||
if (!bInvalid && bTreatInvertedAsInvalid) {
|
||||
if (!bInvalid && !bInvalidLoc && bTreatInvertedAsInvalid) {
|
||||
bInvalid = bInverted;
|
||||
}
|
||||
//
|
||||
@@ -2023,7 +2206,7 @@ void FindInvalidFaces(TopTools_ListOfShape& theLFImages,
|
||||
}
|
||||
//
|
||||
bAllValid &= bValidLoc;
|
||||
bAllInvalid &= bInvalid;
|
||||
bAllInvalid &= (bInvalid || bInvalidLoc);
|
||||
bAllInvNeutral &= (bAllInvalid && bNeutral);
|
||||
bIsInvalidByInverted &= (bInvalidLoc || bInverted);
|
||||
}
|
||||
|
16
tests/offset/shape_type_i_c/XX1
Normal file
16
tests/offset/shape_type_i_c/XX1
Normal file
@@ -0,0 +1,16 @@
|
||||
puts "========"
|
||||
puts "0031639: Modeling Algorithms - Offset algorithm incorrectly fills one of the holes"
|
||||
puts "========"
|
||||
puts ""
|
||||
|
||||
restore [locate_data_file bug31639_input.brep] s
|
||||
offsetparameter 1e-7 c i r
|
||||
offsetload s 7
|
||||
offsetperform result
|
||||
|
||||
checkprops result -s 2.11103e+07 -v 1.43353e+09
|
||||
|
||||
unifysamedom result_unif result
|
||||
checknbshapes result_unif -wire 45 -face 41 -shell 1 -solid 1
|
||||
|
||||
checkview -display result_unif -2d -path ${imagedir}/${test_image}.png
|
16
tests/offset/shape_type_i_c/XX2
Normal file
16
tests/offset/shape_type_i_c/XX2
Normal file
@@ -0,0 +1,16 @@
|
||||
puts "========"
|
||||
puts "0031639: Modeling Algorithms - Offset algorithm incorrectly fills one of the holes"
|
||||
puts "========"
|
||||
puts ""
|
||||
|
||||
restore [locate_data_file bug31639_input_trim.brep] s
|
||||
offsetparameter 1e-7 c i r
|
||||
offsetload s 7
|
||||
offsetperform result
|
||||
|
||||
checkprops result -s 7.22731e+06 -v 2.57323e+08
|
||||
|
||||
unifysamedom result_unif result
|
||||
checknbshapes result_unif -wire 18 -face 17 -shell 1 -solid 1
|
||||
|
||||
checkview -display result_unif -2d -path ${imagedir}/${test_image}.png
|
23
tests/offset/shape_type_i_c/XX3
Normal file
23
tests/offset/shape_type_i_c/XX3
Normal file
@@ -0,0 +1,23 @@
|
||||
puts "========"
|
||||
puts "0031639: Modeling Algorithms - Offset algorithm incorrectly fills one of the holes"
|
||||
puts "========"
|
||||
puts ""
|
||||
|
||||
restore [locate_data_file bug31639_input.brep] s
|
||||
offsetparameter 1e-7 c i r
|
||||
offsetload s 0
|
||||
foreach f [explode s f] {
|
||||
mksurface surf $f
|
||||
regexp {Axis :([-0-9.+eE]*), ([-0-9.+eE]*), ([-0-9.+eE]*)} [dump surf] full x y z
|
||||
if {abs($x) > 1.e-7 || abs($y) > 1.e-7} {
|
||||
offsetonface $f 7
|
||||
}
|
||||
}
|
||||
offsetperform result
|
||||
|
||||
checkprops result -s 2.10662e+07 -v 1.42886e+09
|
||||
|
||||
unifysamedom result_unif result
|
||||
checknbshapes result_unif -wire 45 -face 41 -shell 1 -solid 1
|
||||
|
||||
checkview -display result_unif -2d -path ${imagedir}/${test_image}.png
|
Reference in New Issue
Block a user