From 7c693caa0115fc0834795eb096d0754ac404ba05 Mon Sep 17 00:00:00 2001 From: emv Date: Mon, 30 Mar 2020 16:33:53 +0300 Subject: [PATCH] [PATCH] 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. Original commit url: http://git.dev.opencascade.org/gitweb/?p=occt.git;a=commit;h=3f7e5e99d565e35f600da5f089b0fc7a3851fbde --- src/BOPAlgo/BOPAlgo_PaveFiller_2.cxx | 27 +++++++++++++++- src/BOPAlgo/BOPAlgo_PaveFiller_6.cxx | 7 +++-- src/BOPAlgo/BOPAlgo_PaveFiller_7.cxx | 2 +- src/BOPTools/BOPTools_AlgoTools.cxx | 2 +- src/BOPTools/BOPTools_AlgoTools.hxx | 9 ++++++ src/BOPTools/BOPTools_AlgoTools_1.cxx | 2 +- src/BOPTools/BOPTools_AlgoTools_2.cxx | 17 +++++------ tests/bugs/modalg_7/bug31462 | 44 +++++++++++++++++++++++++++ tests/evolved/voluved/HMC008 | 9 +----- 9 files changed, 95 insertions(+), 24 deletions(-) create mode 100644 tests/bugs/modalg_7/bug31462 diff --git a/src/BOPAlgo/BOPAlgo_PaveFiller_2.cxx b/src/BOPAlgo/BOPAlgo_PaveFiller_2.cxx index 13ec495cf2..1c9975ac73 100644 --- a/src/BOPAlgo/BOPAlgo_PaveFiller_2.cxx +++ b/src/BOPAlgo/BOPAlgo_PaveFiller_2.cxx @@ -225,6 +225,14 @@ void BOPAlgo_PaveFiller::IntersectVE const Handle(BOPDS_PaveBlock)& aPB = theVEPairs.FindKey(i); 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); TColStd_ListIteratorOfListOfInteger aItLV(aLV); for (; aItLV.More(); aItLV.Next()) { @@ -233,6 +241,9 @@ void BOPAlgo_PaveFiller::IntersectVE Standard_Integer nVSD = nV; myDS->HasShapeSD(nV, nVSD); // + if (aMVPB.Contains (nVSD)) + continue; + BOPDS_Pair aPair(nVSD, nE); TColStd_ListOfInteger* pLI = aDMVSD.ChangeSeek(aPair); if (pLI) { @@ -287,7 +298,21 @@ void BOPAlgo_PaveFiller::IntersectVE Standard_Integer nVx = UpdateVertex(nV, aTolVNew); // 2. Create new pave and add it as extra pave to pave block // 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; aPave.SetIndex(nVx); aPave.SetParameter(aT); diff --git a/src/BOPAlgo/BOPAlgo_PaveFiller_6.cxx b/src/BOPAlgo/BOPAlgo_PaveFiller_6.cxx index 5dc2772d12..044bbc83f0 100644 --- a/src/BOPAlgo/BOPAlgo_PaveFiller_6.cxx +++ b/src/BOPAlgo/BOPAlgo_PaveFiller_6.cxx @@ -2414,7 +2414,7 @@ void BOPAlgo_PaveFiller::PutPaveOnCurve Standard_Integer nVUsed; Standard_Real aPTol, aDTol; // - aDTol = 1.e-12; + aDTol = BOPTools_AlgoTools::DTolerance(); // GeomAdaptor_Curve aGAC(aIC.Curve()); aPTol = aGAC.Resolution(Max(aTolR3D, aTolV)); @@ -2459,7 +2459,8 @@ void BOPAlgo_PaveFiller::PutPaveOnCurve aTolV = BRep_Tool::Tolerance(aV); gp_Pnt aP2 = BRep_Tool::Pnt(aV); Standard_Real aDist = aP1.Distance(aP2); - if (aDist > aTolV) { + if (aTolV < aDist + aDTol) + { BRep_Builder().UpdateVertex(aV, aDist + aDTol); // if (!aMVTol.IsBound(nV)) { @@ -2831,7 +2832,7 @@ void BOPAlgo_PaveFiller::PutClosingPaveOnCurve(BOPDS_Curve& aNC) if (aDistVP > aTolV) { - Standard_Integer nVn = UpdateVertex(nV, aDistVP); + Standard_Integer nVn = UpdateVertex(nV, aDistVP + BOPTools_AlgoTools::DTolerance()); if (nVn != nV) { aPave.SetIndex(nVn); diff --git a/src/BOPAlgo/BOPAlgo_PaveFiller_7.cxx b/src/BOPAlgo/BOPAlgo_PaveFiller_7.cxx index dbbb975233..0b299eebc6 100644 --- a/src/BOPAlgo/BOPAlgo_PaveFiller_7.cxx +++ b/src/BOPAlgo/BOPAlgo_PaveFiller_7.cxx @@ -784,7 +784,7 @@ void UpdateVertices(const TopoDS_Edge& aE, aD2=aP3D.SquareDistance(aP3Dx); if (aD2>aTolV2) { aD=sqrt(aD2); - aBB.UpdateVertex(aV[j], aD); + aBB.UpdateVertex(aV[j], aD + BOPTools_AlgoTools::DTolerance()); } } } diff --git a/src/BOPTools/BOPTools_AlgoTools.cxx b/src/BOPTools/BOPTools_AlgoTools.cxx index a2724dfca6..3a037f4761 100644 --- a/src/BOPTools/BOPTools_AlgoTools.cxx +++ b/src/BOPTools/BOPTools_AlgoTools.cxx @@ -1636,7 +1636,7 @@ void BOPTools_AlgoTools::MakeEdge(const IntTools_Curve& theIC, TopoDS_Edge& theE) { BRep_Builder aBB; - Standard_Real aNeedTol = theTolR3D + 1e-12; + Standard_Real aNeedTol = theTolR3D + BOPTools_AlgoTools::DTolerance(); // aBB.UpdateVertex(theV1, aNeedTol); aBB.UpdateVertex(theV2, aNeedTol); diff --git a/src/BOPTools/BOPTools_AlgoTools.hxx b/src/BOPTools/BOPTools_AlgoTools.hxx index 77ad5e927e..4b83f42683 100644 --- a/src/BOPTools/BOPTools_AlgoTools.hxx +++ b/src/BOPTools/BOPTools_AlgoTools.hxx @@ -61,6 +61,15 @@ public: 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 //! Intersects the vertex with the point with tolerance . diff --git a/src/BOPTools/BOPTools_AlgoTools_1.cxx b/src/BOPTools/BOPTools_AlgoTools_1.cxx index 6b92221f4a..78e1a5e386 100644 --- a/src/BOPTools/BOPTools_AlgoTools_1.cxx +++ b/src/BOPTools/BOPTools_AlgoTools_1.cxx @@ -823,7 +823,7 @@ void CorrectEdgeTolerance (const TopoDS_Edge& myShape, Standard_Boolean SameRange = TE->SameRange(); Standard_Real First = myHCurve->FirstParameter(); 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()); const TopLoc_Location& Floc = S.Location(); diff --git a/src/BOPTools/BOPTools_AlgoTools_2.cxx b/src/BOPTools/BOPTools_AlgoTools_2.cxx index 4fd77e5012..d1b30637f3 100644 --- a/src/BOPTools/BOPTools_AlgoTools_2.cxx +++ b/src/BOPTools/BOPTools_AlgoTools_2.cxx @@ -42,7 +42,7 @@ void BOPTools_AlgoTools::UpdateVertex (const TopoDS_Vertex& aVF, 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 aPNewVertex=BRep_Tool::Pnt(aNewVertex); @@ -54,7 +54,7 @@ void BOPTools_AlgoTools::UpdateVertex if (aNewTol>aTolVF) { 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 TopoDS_Vertex& aV) { - Standard_Real aTolV, aDist, aDTol=1.e-12, aFirst, aLast; + Standard_Real aTolV, aDist, aFirst, aLast; gp_Pnt aPc; gp_Pnt aPv=BRep_Tool::Pnt(aV); @@ -77,7 +77,7 @@ void BOPTools_AlgoTools::UpdateVertex (const TopoDS_Edge& aE, aDist=aPv.Distance(aPc); if (aDist>aTolV) { 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 TopoDS_Vertex& aV) { - Standard_Real aTolV, aDist, aDTol=1.e-12; + Standard_Real aTolV, aDist; gp_Pnt aPc; gp_Pnt aPv=BRep_Tool::Pnt(aV); @@ -100,7 +100,7 @@ void BOPTools_AlgoTools::UpdateVertex (const IntTools_Curve& aC, aDist=aPv.Distance(aPc); if (aDist>aTolV) { 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, TopoDS_Vertex& aNewVertex) { - Standard_Real aTol1, aTol2, aMaxTol, delta=1.e-12; + Standard_Real aTol1, aTol2, aMaxTol; gp_Pnt aPnt; PointOnEdge (aE1, aParm1, aPnt); @@ -273,8 +273,7 @@ void BOPTools_AlgoTools::MakeNewVertex(const TopoDS_Edge& aE1, aTol1=BRep_Tool::Tolerance(aE1); aTol2=BRep_Tool::Tolerance(aF1); // - //aMaxTol=(aTol1>aTol2)? aTol1 : aTol2; - aMaxTol=aTol1+aTol2+delta; + aMaxTol = aTol1 + aTol2 + BOPTools_AlgoTools::DTolerance(); // BRep_Builder aBB; aBB.MakeVertex (aNewVertex, aPnt, aMaxTol); diff --git a/tests/bugs/modalg_7/bug31462 b/tests/bugs/modalg_7/bug31462 new file mode 100644 index 0000000000..5588be6d82 --- /dev/null +++ b/tests/bugs/modalg_7/bug31462 @@ -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 diff --git a/tests/evolved/voluved/HMC008 b/tests/evolved/voluved/HMC008 index aa0f6987d7..63c57b5117 100644 --- a/tests/evolved/voluved/HMC008 +++ b/tests/evolved/voluved/HMC008 @@ -4,13 +4,6 @@ puts "==========" 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_toolwire07.brep] tw @@ -219,7 +212,7 @@ if {[regexp "Faulties" [bopargcheck result]]} { # the dimensions of the shape "result" are about 1.0e+5. # So, this tolerance seems to be OK. -checkmaxtol result -ref 18.634531507134731 +checkmaxtol result -ref 1.7319951447770465 smallview don result sw tw