1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-05-16 10:54:53 +03:00

0031462: Modeling Algorithms - BOP result depends on the arguments order

Eliminate numerical instability by ensuring that the tolerance of intersection entities is slightly grater than the actual distance to the shapes creating the entity.
This commit is contained in:
emv 2020-03-30 16:33:53 +03:00 committed by rnv
parent b90477afe3
commit 33d9a6fa21
9 changed files with 95 additions and 24 deletions

View File

@ -225,6 +225,14 @@ void BOPAlgo_PaveFiller::IntersectVE
const Handle(BOPDS_PaveBlock)& aPB = theVEPairs.FindKey(i); const Handle(BOPDS_PaveBlock)& aPB = theVEPairs.FindKey(i);
Standard_Integer nE = aPB->OriginalEdge(); Standard_Integer nE = aPB->OriginalEdge();
// //
TColStd_MapOfInteger aMVPB;
const BOPDS_ListOfPaveBlock& aLPB = myDS->PaveBlocks (nE);
for (BOPDS_ListOfPaveBlock::Iterator itPB (aLPB); itPB.More(); itPB.Next())
{
aMVPB.Add (itPB.Value()->Pave1().Index());
aMVPB.Add (itPB.Value()->Pave2().Index());
}
const TColStd_ListOfInteger& aLV = theVEPairs(i); const TColStd_ListOfInteger& aLV = theVEPairs(i);
TColStd_ListIteratorOfListOfInteger aItLV(aLV); TColStd_ListIteratorOfListOfInteger aItLV(aLV);
for (; aItLV.More(); aItLV.Next()) { for (; aItLV.More(); aItLV.Next()) {
@ -233,6 +241,9 @@ void BOPAlgo_PaveFiller::IntersectVE
Standard_Integer nVSD = nV; Standard_Integer nVSD = nV;
myDS->HasShapeSD(nV, nVSD); myDS->HasShapeSD(nV, nVSD);
// //
if (aMVPB.Contains (nVSD))
continue;
BOPDS_Pair aPair(nVSD, nE); BOPDS_Pair aPair(nVSD, nE);
TColStd_ListOfInteger* pLI = aDMVSD.ChangeSeek(aPair); TColStd_ListOfInteger* pLI = aDMVSD.ChangeSeek(aPair);
if (pLI) { if (pLI) {
@ -287,7 +298,21 @@ void BOPAlgo_PaveFiller::IntersectVE
Standard_Integer nVx = UpdateVertex(nV, aTolVNew); Standard_Integer nVx = UpdateVertex(nV, aTolVNew);
// 2. Create new pave and add it as extra pave to pave block // 2. Create new pave and add it as extra pave to pave block
// for further splitting of the edge // for further splitting of the edge
const Handle(BOPDS_PaveBlock)& aPB = aVESolver.PaveBlock(); const BOPDS_ListOfPaveBlock& aLPB = myDS->PaveBlocks (nE);
// Find the appropriate one
Handle(BOPDS_PaveBlock) aPB;
BOPDS_ListOfPaveBlock::Iterator itPB (aLPB);
for (; itPB.More(); itPB.Next())
{
aPB = itPB.Value();
Standard_Real aT1, aT2;
aPB->Range (aT1, aT2);
if (aT > aT1 && aT < aT2)
break;
}
if (!itPB.More())
continue;
BOPDS_Pave aPave; BOPDS_Pave aPave;
aPave.SetIndex(nVx); aPave.SetIndex(nVx);
aPave.SetParameter(aT); aPave.SetParameter(aT);

View File

@ -2414,7 +2414,7 @@ void BOPAlgo_PaveFiller::PutPaveOnCurve
Standard_Integer nVUsed; Standard_Integer nVUsed;
Standard_Real aPTol, aDTol; Standard_Real aPTol, aDTol;
// //
aDTol = 1.e-12; aDTol = BOPTools_AlgoTools::DTolerance();
// //
GeomAdaptor_Curve aGAC(aIC.Curve()); GeomAdaptor_Curve aGAC(aIC.Curve());
aPTol = aGAC.Resolution(Max(aTolR3D, aTolV)); aPTol = aGAC.Resolution(Max(aTolR3D, aTolV));
@ -2459,7 +2459,8 @@ void BOPAlgo_PaveFiller::PutPaveOnCurve
aTolV = BRep_Tool::Tolerance(aV); aTolV = BRep_Tool::Tolerance(aV);
gp_Pnt aP2 = BRep_Tool::Pnt(aV); gp_Pnt aP2 = BRep_Tool::Pnt(aV);
Standard_Real aDist = aP1.Distance(aP2); Standard_Real aDist = aP1.Distance(aP2);
if (aDist > aTolV) { if (aTolV < aDist + aDTol)
{
BRep_Builder().UpdateVertex(aV, aDist + aDTol); BRep_Builder().UpdateVertex(aV, aDist + aDTol);
// //
if (!aMVTol.IsBound(nV)) { if (!aMVTol.IsBound(nV)) {
@ -2831,7 +2832,7 @@ void BOPAlgo_PaveFiller::PutClosingPaveOnCurve(BOPDS_Curve& aNC)
if (aDistVP > aTolV) if (aDistVP > aTolV)
{ {
Standard_Integer nVn = UpdateVertex(nV, aDistVP); Standard_Integer nVn = UpdateVertex(nV, aDistVP + BOPTools_AlgoTools::DTolerance());
if (nVn != nV) if (nVn != nV)
{ {
aPave.SetIndex(nVn); aPave.SetIndex(nVn);

View File

@ -784,7 +784,7 @@ void UpdateVertices(const TopoDS_Edge& aE,
aD2=aP3D.SquareDistance(aP3Dx); aD2=aP3D.SquareDistance(aP3Dx);
if (aD2>aTolV2) { if (aD2>aTolV2) {
aD=sqrt(aD2); aD=sqrt(aD2);
aBB.UpdateVertex(aV[j], aD); aBB.UpdateVertex(aV[j], aD + BOPTools_AlgoTools::DTolerance());
} }
} }
} }

View File

@ -1636,7 +1636,7 @@ void BOPTools_AlgoTools::MakeEdge(const IntTools_Curve& theIC,
TopoDS_Edge& theE) TopoDS_Edge& theE)
{ {
BRep_Builder aBB; BRep_Builder aBB;
Standard_Real aNeedTol = theTolR3D + 1e-12; Standard_Real aNeedTol = theTolR3D + BOPTools_AlgoTools::DTolerance();
// //
aBB.UpdateVertex(theV1, aNeedTol); aBB.UpdateVertex(theV1, aNeedTol);
aBB.UpdateVertex(theV2, aNeedTol); aBB.UpdateVertex(theV2, aNeedTol);

View File

@ -61,6 +61,15 @@ public:
DEFINE_STANDARD_ALLOC DEFINE_STANDARD_ALLOC
public: //! @name Constants
//! Additional tolerance (delta tolerance) is used in Boolean Operations
//! to ensure that the tolerance of new/old entities obtained
//! by intersection of two shapes is slightly bigger than the actual
//! distances to these shapes. It helps to avoid numerical instability
//! which may occur when comparing distances and tolerances.
static Standard_Real DTolerance() { return 1.e-12; }
public: //! @name Intersection of the vertices public: //! @name Intersection of the vertices
//! Intersects the vertex <theV1> with the point <theP> with tolerance <theTolP>. //! Intersects the vertex <theV1> with the point <theP> with tolerance <theTolP>.

View File

@ -823,7 +823,7 @@ void CorrectEdgeTolerance (const TopoDS_Edge& myShape,
Standard_Boolean SameRange = TE->SameRange(); Standard_Boolean SameRange = TE->SameRange();
Standard_Real First = myHCurve->FirstParameter(); Standard_Real First = myHCurve->FirstParameter();
Standard_Real Last = myHCurve->LastParameter(); Standard_Real Last = myHCurve->LastParameter();
Standard_Real Delta =1.e-12; Standard_Real Delta = BOPTools_AlgoTools::DTolerance();
Handle(BRep_TFace)& TF = *((Handle(BRep_TFace)*) &S.TShape()); Handle(BRep_TFace)& TF = *((Handle(BRep_TFace)*) &S.TShape());
const TopLoc_Location& Floc = S.Location(); const TopLoc_Location& Floc = S.Location();

View File

@ -42,7 +42,7 @@ void BOPTools_AlgoTools::UpdateVertex
(const TopoDS_Vertex& aVF, (const TopoDS_Vertex& aVF,
const TopoDS_Vertex& aNewVertex) const TopoDS_Vertex& aNewVertex)
{ {
Standard_Real aTolVF, aTolNewVertex, aDist, aDTol=1.e-12, aNewTol; Standard_Real aTolVF, aTolNewVertex, aDist, aNewTol;
// //
gp_Pnt aPVF=BRep_Tool::Pnt(aVF); gp_Pnt aPVF=BRep_Tool::Pnt(aVF);
gp_Pnt aPNewVertex=BRep_Tool::Pnt(aNewVertex); gp_Pnt aPNewVertex=BRep_Tool::Pnt(aNewVertex);
@ -54,7 +54,7 @@ void BOPTools_AlgoTools::UpdateVertex
if (aNewTol>aTolVF) { if (aNewTol>aTolVF) {
BRep_Builder BB; BRep_Builder BB;
BB.UpdateVertex (aVF, aNewTol+aDTol); BB.UpdateVertex (aVF, aNewTol + BOPTools_AlgoTools::DTolerance());
} }
} }
@ -66,7 +66,7 @@ void BOPTools_AlgoTools::UpdateVertex (const TopoDS_Edge& aE,
const Standard_Real aT, const Standard_Real aT,
const TopoDS_Vertex& aV) const TopoDS_Vertex& aV)
{ {
Standard_Real aTolV, aDist, aDTol=1.e-12, aFirst, aLast; Standard_Real aTolV, aDist, aFirst, aLast;
gp_Pnt aPc; gp_Pnt aPc;
gp_Pnt aPv=BRep_Tool::Pnt(aV); gp_Pnt aPv=BRep_Tool::Pnt(aV);
@ -77,7 +77,7 @@ void BOPTools_AlgoTools::UpdateVertex (const TopoDS_Edge& aE,
aDist=aPv.Distance(aPc); aDist=aPv.Distance(aPc);
if (aDist>aTolV) { if (aDist>aTolV) {
BRep_Builder BB; BRep_Builder BB;
BB.UpdateVertex (aV, aDist+aDTol); BB.UpdateVertex (aV, aDist + BOPTools_AlgoTools::DTolerance());
} }
} }
// //
@ -89,7 +89,7 @@ void BOPTools_AlgoTools::UpdateVertex (const IntTools_Curve& aC,
const Standard_Real aT, const Standard_Real aT,
const TopoDS_Vertex& aV) const TopoDS_Vertex& aV)
{ {
Standard_Real aTolV, aDist, aDTol=1.e-12; Standard_Real aTolV, aDist;
gp_Pnt aPc; gp_Pnt aPc;
gp_Pnt aPv=BRep_Tool::Pnt(aV); gp_Pnt aPv=BRep_Tool::Pnt(aV);
@ -100,7 +100,7 @@ void BOPTools_AlgoTools::UpdateVertex (const IntTools_Curve& aC,
aDist=aPv.Distance(aPc); aDist=aPv.Distance(aPc);
if (aDist>aTolV) { if (aDist>aTolV) {
BRep_Builder BB; BRep_Builder BB;
BB.UpdateVertex (aV, aDist+aDTol); BB.UpdateVertex (aV, aDist + BOPTools_AlgoTools::DTolerance());
} }
} }
//======================================================================= //=======================================================================
@ -265,7 +265,7 @@ void BOPTools_AlgoTools::MakeNewVertex(const TopoDS_Edge& aE1,
const TopoDS_Face& aF1, const TopoDS_Face& aF1,
TopoDS_Vertex& aNewVertex) TopoDS_Vertex& aNewVertex)
{ {
Standard_Real aTol1, aTol2, aMaxTol, delta=1.e-12; Standard_Real aTol1, aTol2, aMaxTol;
gp_Pnt aPnt; gp_Pnt aPnt;
PointOnEdge (aE1, aParm1, aPnt); PointOnEdge (aE1, aParm1, aPnt);
@ -273,8 +273,7 @@ void BOPTools_AlgoTools::MakeNewVertex(const TopoDS_Edge& aE1,
aTol1=BRep_Tool::Tolerance(aE1); aTol1=BRep_Tool::Tolerance(aE1);
aTol2=BRep_Tool::Tolerance(aF1); aTol2=BRep_Tool::Tolerance(aF1);
// //
//aMaxTol=(aTol1>aTol2)? aTol1 : aTol2; aMaxTol = aTol1 + aTol2 + BOPTools_AlgoTools::DTolerance();
aMaxTol=aTol1+aTol2+delta;
// //
BRep_Builder aBB; BRep_Builder aBB;
aBB.MakeVertex (aNewVertex, aPnt, aMaxTol); aBB.MakeVertex (aNewVertex, aPnt, aMaxTol);

View File

@ -0,0 +1,44 @@
puts "========"
puts "0031462: Modeling Algorithms - BOP result depends on the arguments order"
puts "========"
puts ""
restore [locate_data_file bug31462_obj.brep] s1
restore [locate_data_file bug31462_tools.brep] s2
tcopy s1 obj
tcopy s2 sx
bclearobjects
bcleartools
baddobjects obj
eval baddtools [explode sx]
bfillds
bsplit result1
checkshape result1
if {![regexp "This shape seems to be OK" [bopcheck result1]]} {
puts "Error: self-interfering result"
}
checknbshapes result1 -wire 19 -face 18 -shell 3 -solid 2
checkprops result1 -s 103.955 -v 38.7982
tcopy s1 obj
tcopy s2 sx
bclearobjects
bcleartools
baddobjects obj
explode sx
baddtools sx_4 sx_5 sx_6 sx_3 sx_2 sx_1
bfillds
bsplit result2
checkshape result2
if {![regexp "This shape seems to be OK" [bopcheck result2]]} {
puts "Error: self-interfering result"
}
checknbshapes result2 -ref [nbshapes result1]
checkprops result2 -equal result1
checkview -display result1 -2d -path ${imagedir}/${test_image}.png

View File

@ -4,13 +4,6 @@ puts "=========="
cpulimit 100 cpulimit 100
puts "TODO OCC30438 ALL: Error : The area of result shape is"
puts "TODO OCC30438 ALL: Error : The volume of result shape is"
puts "TODO OCC30438 ALL: Error : is WRONG because number of SHELL"
puts "TODO OCC30438 ALL: Error : is WRONG because number of SOLID"
puts "TODO OCC30438 ALL: Error: bopargcheck has found some faulties in result"
restore [locate_data_file bug29523_cut_extrudewire07.brep] sw restore [locate_data_file bug29523_cut_extrudewire07.brep] sw
restore [locate_data_file bug29523_cut_toolwire07.brep] tw restore [locate_data_file bug29523_cut_toolwire07.brep] tw
@ -219,7 +212,7 @@ if {[regexp "Faulties" [bopargcheck result]]} {
# the dimensions of the shape "result" are about 1.0e+5. # the dimensions of the shape "result" are about 1.0e+5.
# So, this tolerance seems to be OK. # So, this tolerance seems to be OK.
checkmaxtol result -ref 18.634531507134731 checkmaxtol result -ref 1.7319951447770465
smallview smallview
don result sw tw don result sw tw