From 88c3accd1aadfb7b34297de59566d7a7d1535eb0 Mon Sep 17 00:00:00 2001 From: emv Date: Wed, 19 Jun 2019 08:54:50 +0300 Subject: [PATCH] 0030787: BRepOffsetAPI_MakePipeShell: hangs on the attached model Protect IntTools_EdgeEdge::FindSolutions method from cases where splitting edge on parts does not give bounding box decreasing. Use at least Epsilon from edges parameters as a step in BRepLib::FindValidRange. Test case for the issue. --- src/BRepLib/BRepLib_1.cxx | 20 +++++++++++++++----- src/IntTools/IntTools_EdgeEdge.cxx | 28 +++++++++++++++++++--------- src/IntTools/IntTools_EdgeEdge.hxx | 3 ++- tests/bugs/modalg_7/bug30787 | 21 +++++++++++++++++++++ 4 files changed, 57 insertions(+), 15 deletions(-) create mode 100644 tests/bugs/modalg_7/bug30787 diff --git a/src/BRepLib/BRepLib_1.cxx b/src/BRepLib/BRepLib_1.cxx index 30bcd8aedc..5fe6d8c177 100644 --- a/src/BRepLib/BRepLib_1.cxx +++ b/src/BRepLib/BRepLib_1.cxx @@ -55,6 +55,8 @@ static Standard_Boolean findNearestValidPoint( // // the general step is computed using general curve resolution Standard_Real aStep = theCurve.Resolution(theTol) * 1.01; + if (aStep < theEps) + aStep = theEps; // aD1Mag is a threshold to consider local derivative magnitude too small // and to accelerate going out of sphere // (inverse of resolution is the maximal derivative); @@ -159,11 +161,19 @@ Standard_Boolean BRepLib::FindValidRange if (theParV2 - theParV1 < Precision::PConfusion()) return Standard_False; - Standard_Real anEps = Max(Max(theCurve.Resolution(theTolE) * 0.1, - Epsilon(Max(Abs(theParV1), Abs(theParV2)))), - Precision::PConfusion()); + Standard_Boolean isInfParV1 = Precision::IsInfinite (theParV1), + isInfParV2 = Precision::IsInfinite (theParV2); - if (Precision::IsInfinite(theParV1)) + Standard_Real aMaxPar = 0.0; + if (!isInfParV1) + aMaxPar = Abs (theParV1); + if (!isInfParV2) + aMaxPar = Max (aMaxPar, Abs (theParV2)); + + Standard_Real anEps = Max (Max (theCurve.Resolution (theTolE) * 0.1, Epsilon (aMaxPar)), + Precision::PConfusion()); + + if (isInfParV1) theFirst = theParV1; else { @@ -174,7 +184,7 @@ Standard_Boolean BRepLib::FindValidRange return Standard_False; } - if (Precision::IsInfinite(theParV2)) + if (isInfParV2) theLast = theParV2; else { diff --git a/src/IntTools/IntTools_EdgeEdge.cxx b/src/IntTools/IntTools_EdgeEdge.cxx index 78ef6ab78d..148434915c 100644 --- a/src/IntTools/IntTools_EdgeEdge.cxx +++ b/src/IntTools/IntTools_EdgeEdge.cxx @@ -304,7 +304,7 @@ void IntTools_EdgeEdge::FindSolutions(IntTools_SequenceOfRanges& theRanges1, { Standard_Boolean bIsClosed2; Standard_Real aT11, aT12, aT21, aT22; - Bnd_Box aB2; + Bnd_Box aB1, aB2; // bSplit2 = Standard_False; myRange1.Range(aT11, aT12); @@ -313,7 +313,6 @@ void IntTools_EdgeEdge::FindSolutions(IntTools_SequenceOfRanges& theRanges1, bIsClosed2 = IsClosed(myGeom2, aT21, aT22, myTol2, myRes2); // if (bIsClosed2) { - Bnd_Box aB1; BndBuildBox(myCurve1, aT11, aT12, myTol1, aB1); // gp_Pnt aP = myGeom2->Value(aT21); @@ -321,8 +320,9 @@ void IntTools_EdgeEdge::FindSolutions(IntTools_SequenceOfRanges& theRanges1, } // if (!bIsClosed2) { + BndBuildBox(myCurve1, aT11, aT12, myTol1, aB1); BndBuildBox(myCurve2, aT21, aT22, myTol2, aB2); - FindSolutions(myRange1, myRange2, aB2, theRanges1, theRanges2); + FindSolutions(myRange1, aB1, myRange2, aB2, theRanges1, theRanges2); return; } // @@ -343,10 +343,11 @@ void IntTools_EdgeEdge::FindSolutions(IntTools_SequenceOfRanges& theRanges1, // for (i = 1; i <= aNb1; ++i) { const IntTools_Range& aR1 = aSegments1(i); + BndBuildBox(myCurve1, aR1.First(), aR1.Last(), myTol1, aB1); for (j = 1; j <= aNb2; ++j) { const IntTools_Range& aR2 = aSegments2(j); BndBuildBox(myCurve2, aR2.First(), aR2.Last(), myTol2, aB2); - FindSolutions(aR1, aR2, aB2, theRanges1, theRanges2); + FindSolutions(aR1, aB1, aR2, aB2, theRanges1, theRanges2); } } // @@ -358,6 +359,7 @@ void IntTools_EdgeEdge::FindSolutions(IntTools_SequenceOfRanges& theRanges1, //purpose : //======================================================================= void IntTools_EdgeEdge::FindSolutions(const IntTools_Range& theR1, + const Bnd_Box& theBox1, const IntTools_Range& theR2, const Bnd_Box& theBox2, IntTools_SequenceOfRanges& theRanges1, @@ -373,6 +375,7 @@ void IntTools_EdgeEdge::FindSolutions(const IntTools_Range& theR1, theR1.Range(aT11, aT12); theR2.Range(aT21, aT22); // + aB1 = theBox1; aB2 = theBox2; // bThin = Standard_False; @@ -385,9 +388,7 @@ void IntTools_EdgeEdge::FindSolutions(const IntTools_Range& theR1, aTB21 = aT21; aTB22 = aT22; // - //1. Build box for first edge and find parameters - // of the second one in that box - BndBuildBox(myCurve1, aT11, aT12, myTol1, aB1); + //1. Find parameters of the second edge in the box of first one bOut = aB1.IsOut(aB2); if (bOut) { break; @@ -435,7 +436,9 @@ void IntTools_EdgeEdge::FindSolutions(const IntTools_Range& theR1, ((aT21 - aTB21) < aSmallStep2) && ((aTB22 - aT22) < aSmallStep2)) { bStop = Standard_True; } - // + else + BndBuildBox (myCurve1, aT11, aT12, myTol1, aB1); + } while (!bStop); // if (bOut) { @@ -498,13 +501,20 @@ void IntTools_EdgeEdge::FindSolutions(const IntTools_Range& theR1, Standard_Integer i, aNb1; IntTools_SequenceOfRanges aSegments1; // + // Build box for first curve to compare + // the boxes of the splits with this one + BndBuildBox(myCurve1, aT11, aT12, myTol1, aB1); + const Standard_Real aB1SqExtent = aB1.SquareExtent(); + // IntTools_Range aR2(aT21, aT22); BndBuildBox(myCurve2, aT21, aT22, myTol2, aB2); // aNb1 = SplitRangeOnSegments(aT11, aT12, myRes1, 3, aSegments1); for (i = 1; i <= aNb1; ++i) { const IntTools_Range& aR1 = aSegments1(i); - FindSolutions(aR1, aR2, aB2, theRanges1, theRanges2); + BndBuildBox(myCurve1, aR1.First(), aR1.Last(), myTol1, aB1); + if (!aB1.IsOut(aB2) && (aNb1 == 1 || aB1.SquareExtent() < aB1SqExtent)) + FindSolutions(aR1, aB1, aR2, aB2, theRanges1, theRanges2); } } diff --git a/src/IntTools/IntTools_EdgeEdge.hxx b/src/IntTools/IntTools_EdgeEdge.hxx index ae68b8f39d..8dc80e35db 100644 --- a/src/IntTools/IntTools_EdgeEdge.hxx +++ b/src/IntTools/IntTools_EdgeEdge.hxx @@ -146,7 +146,8 @@ protected: //! Looking for the exact intersection ranges - Standard_EXPORT void FindSolutions (const IntTools_Range& theR1, + Standard_EXPORT void FindSolutions ( + const IntTools_Range& theR1, const Bnd_Box& theBox1, const IntTools_Range& theR2, const Bnd_Box& theBox2, IntTools_SequenceOfRanges& theRanges1, IntTools_SequenceOfRanges& theRanges2); diff --git a/tests/bugs/modalg_7/bug30787 b/tests/bugs/modalg_7/bug30787 new file mode 100644 index 0000000000..1fc401c409 --- /dev/null +++ b/tests/bugs/modalg_7/bug30787 @@ -0,0 +1,21 @@ +puts "TODO OCC30808 ALL: \\*\\* Exception \\*\\*.*" +puts "TODO OCC30808 ALL: An exception was caught" +puts "TODO OCC30808 ALL:TEST INCOMPLETE" + +puts "========" +puts "0030787: BRepOffsetAPI_MakePipeShell: hangs on the attached model" +puts "========" +puts "" + +cpulimit 300 + +circle profile 0 -1.81898940354586e-12 0 0 -0.999995598293478 -0.00296705134258169 1 0 0 25 +mkedge profile profile +wire profile profile + +restore [locate_data_file bug30787_spine.brep] path + +mksweep path +addsweep profile + +buildsweep result -C -S