From 79e9ce0ec2ad3210dee57806bbbdb84ce2e9ccd1 Mon Sep 17 00:00:00 2001 From: abv Date: Mon, 7 Sep 2015 07:14:41 +0300 Subject: [PATCH] 0026627: [Regression] Shape Healing hangs as of OCC 6.8.0 Check for orientation of the solid corrected to ensure that cycle always finishes. Test case added: bugs modalg_6 bug26627 Tests boolean volumemaker A3, B5, B7 corrected (improvements) --- src/BRepClass3d/BRepClass3d_SClassifier.cxx | 114 ++++++++++---------- tests/boolean/volumemaker/A3 | 3 +- tests/boolean/volumemaker/B5 | 5 +- tests/boolean/volumemaker/B7 | 5 +- tests/bugs/modalg_6/bug26627 | 19 ++++ 5 files changed, 83 insertions(+), 63 deletions(-) create mode 100644 tests/bugs/modalg_6/bug26627 diff --git a/src/BRepClass3d/BRepClass3d_SClassifier.cxx b/src/BRepClass3d/BRepClass3d_SClassifier.cxx index 860db3b090..07833c17d5 100644 --- a/src/BRepClass3d/BRepClass3d_SClassifier.cxx +++ b/src/BRepClass3d/BRepClass3d_SClassifier.cxx @@ -33,6 +33,8 @@ #include #include +#include + // modified by NIZHNY-MKK Mon Jun 21 15:13:40 2004 static Standard_Boolean FaceNormal (const TopoDS_Face& aF, @@ -103,72 +105,76 @@ void BRepClass3d_SClassifier::PerformInfinitePoint(BRepClass3d_SolidExplorer& aS myFace.Nullify(); myState=2; - aSE.InitShell(); - if (aSE.MoreShell()) + // Collect faces in sequence to iterate + std::vector aFaces; + for (aSE.InitShell(); aSE.MoreShell(); aSE.NextShell()) { - aSE.InitFace(); - if (aSE.MoreFace()) + for (aSE.InitFace(); aSE.MoreFace(); aSE.NextFace()) { - TopoDS_Face aF = aSE.CurrentFace(); + aFaces.push_back (aSE.CurrentFace()); + } + } + + // iteratively try up to 10 probing points from each face + const int NB_MAX_POINTS_PER_FACE = 10; + for (int itry = 0; itry < NB_MAX_POINTS_PER_FACE; itry++) + { + for (std::vector::iterator iFace = aFaces.begin(); iFace != aFaces.end(); ++iFace) + { + TopoDS_Face aF = *iFace; + TopAbs_State aState = TopAbs_OUT; IntCurveSurface_TransitionOnCurve aTransition = IntCurveSurface_Tangent; - TopoDS_Face MinFace = aF; - for (;;) - { - aParam = 0.1 + 0.8 * aRandomGenerator.NextReal(); // random number in range [0.1, 0.9] - bFound = aSE.FindAPointInTheFace(aF, aPoint, aU, aV, aParam); - if (!bFound) - return; - if (!FaceNormal(aF, aU, aV, aDN)) - continue; - gp_Lin aLin(aPoint, -aDN); - Standard_Real parmin = RealLast(); - for (aSE.InitShell();aSE.MoreShell();aSE.NextShell()) { - if (aSE.RejectShell(aLin) == Standard_False) { - for (aSE.InitFace();aSE.MoreFace(); aSE.NextFace()) { - if (aSE.RejectFace(aLin) == Standard_False) { - TopoDS_Shape aLocalShape = aSE.CurrentFace(); - TopoDS_Face CurFace = TopoDS::Face(aLocalShape); - IntCurvesFace_Intersector& Intersector3d = aSE.Intersector(CurFace); - Intersector3d.Perform(aLin,-RealLast(),parmin); - - if(Intersector3d.IsDone()) { - if(Intersector3d.NbPnt()) { - Standard_Integer imin = 1; - for (Standard_Integer i = 2; i <= Intersector3d.NbPnt(); i++) - if (Intersector3d.WParameter(i) < Intersector3d.WParameter(imin)) - imin = i; - parmin = Intersector3d.WParameter(imin); - aState = Intersector3d.State(imin); - aTransition = Intersector3d.Transition(imin); - MinFace = CurFace; - } + aParam = 0.1 + 0.8 * aRandomGenerator.NextReal(); // random number in range [0.1, 0.9] + bFound = aSE.FindAPointInTheFace(aF, aPoint, aU, aV, aParam); + if (!bFound || !FaceNormal(aF, aU, aV, aDN)) + continue; + + gp_Lin aLin(aPoint, -aDN); + Standard_Real parmin = RealLast(); + for (aSE.InitShell();aSE.MoreShell();aSE.NextShell()) { + if (aSE.RejectShell(aLin) == Standard_False) { + for (aSE.InitFace();aSE.MoreFace(); aSE.NextFace()) { + if (aSE.RejectFace(aLin) == Standard_False) { + TopoDS_Shape aLocalShape = aSE.CurrentFace(); + TopoDS_Face CurFace = TopoDS::Face(aLocalShape); + IntCurvesFace_Intersector& Intersector3d = aSE.Intersector(CurFace); + Intersector3d.Perform(aLin,-RealLast(),parmin); + + if(Intersector3d.IsDone()) { + if(Intersector3d.NbPnt()) { + Standard_Integer imin = 1; + for (Standard_Integer i = 2; i <= Intersector3d.NbPnt(); i++) + if (Intersector3d.WParameter(i) < Intersector3d.WParameter(imin)) + imin = i; + parmin = Intersector3d.WParameter(imin); + aState = Intersector3d.State(imin); + aTransition = Intersector3d.Transition(imin); } } } } - else - myState = 1; - } //end of loop on the whole solid + } + else + myState = 1; + } //end of loop on the whole solid - if (aState == TopAbs_IN) - { - if (aTransition == IntCurveSurface_Out) { - //-- The line is going from inside the solid to outside - //-- the solid. - myState = 3; //-- IN -- - return; - } - else if (aTransition == IntCurveSurface_In) { - myState = 4; //-- OUT -- - return; - } + if (aState == TopAbs_IN) + { + if (aTransition == IntCurveSurface_Out) { + //-- The line is going from inside the solid to outside + //-- the solid. + myState = 3; //-- IN -- + return; + } + else if (aTransition == IntCurveSurface_In) { + myState = 4; //-- OUT -- + return; } - aF = MinFace; } - } //if (aSE.MoreFace()) - } //if (aSE.MoreShell()) + } // iteration by faces + } // iteration by points } //======================================================================= diff --git a/tests/boolean/volumemaker/A3 b/tests/boolean/volumemaker/A3 index a665eecff6..9aeac529d7 100644 --- a/tests/boolean/volumemaker/A3 +++ b/tests/boolean/volumemaker/A3 @@ -2,7 +2,6 @@ # plane unstable puts "TODO OCC26020 ALL: Error: bopcheck failed" -puts "TODO OCC26020 ALL: Faulty shapes in variables faulty_1 to faulty_" # planar face plane pln_f1 0 -870 -1.3877787807814457e-014 0 1 1.1102230246251565e-016 @@ -37,5 +36,5 @@ mkface f6 pln_f6 -1000000 1000000 -1000000 1000000 # make volume operation mkvolume result f1 f2 f3 f4 f5 f6 -set square 2.4e+013 +set square 1183220. diff --git a/tests/boolean/volumemaker/B5 b/tests/boolean/volumemaker/B5 index 64f680918c..06903f3eb5 100644 --- a/tests/boolean/volumemaker/B5 +++ b/tests/boolean/volumemaker/B5 @@ -1,8 +1,6 @@ # test script on make volume operation # plane -puts "TODO OCC26020 ALL: Error: bopcheck failed" - # planar face plane pln_f1 2949.26242211 -890 552.5 1.110223024625157e-016 -1 1.1102230246251563e-016 erase pln_f1 @@ -36,5 +34,4 @@ mkface f6 pln_f6 -1000000 1000000 -1000000 1000000 # make volume operation mkvolume result f1 f2 f3 f4 f5 f6 -set square 2.4e+013 - +set square 12400. diff --git a/tests/boolean/volumemaker/B7 b/tests/boolean/volumemaker/B7 index 795efc44d0..a6e9633541 100644 --- a/tests/boolean/volumemaker/B7 +++ b/tests/boolean/volumemaker/B7 @@ -1,8 +1,7 @@ # test script on make volume operation # plane -puts "TODO ?OCC26020 ALL: Faulty shapes in variables faulty_1 to faulty_" -puts "TODO ?OCC26020 ALL: Error: bopcheck failed" +puts "TODO OCC26020 ALL: Error: bopcheck failed" # planar face plane pln_f1 18.855982726712998 17.500000000800412 0 -0.96152394764524818 -0.27472112788189063 0 @@ -52,4 +51,4 @@ mkface f9 pln_f9 -1000000 1000000 -1000000 1000000 # make volume operation mkvolume result f1 f2 f3 f4 f5 f6 f7 f8 f9 -set square 2.75501e+013 +set square 1.3412e+013 diff --git a/tests/bugs/modalg_6/bug26627 b/tests/bugs/modalg_6/bug26627 new file mode 100644 index 0000000000..b33ce91368 --- /dev/null +++ b/tests/bugs/modalg_6/bug26627 @@ -0,0 +1,19 @@ +puts "##################################################" +puts "0026627: Shape Healing hangs as of OCC 6.8.0" +puts "##################################################" + +# load and check shape +restore [locate_data_file bug26627_fixed.brep] a +tolerance a +checkshape a + +# call fixshape -- it should finish in fraction of second +cpulimit 10 +fixshape result a 1e-6 + +# result should have positive volume +if { [regexp {Mass\s*:\s*([0-9.e+-]*)} [vprops result] dummy volume] } { + checkreal "Volume of the solid" $volume 4332.63 0.1 0. +} else { + puts "Error: cannot get volume of result!" +} -- 2.20.1