0030787: BRepOffsetAPI_MakePipeShell: hangs on the attached model
authoremv <emv@opencascade.com>
Wed, 19 Jun 2019 05:54:50 +0000 (08:54 +0300)
committerapn <apn@opencascade.com>
Tue, 25 Jun 2019 16:47:09 +0000 (19:47 +0300)
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
src/IntTools/IntTools_EdgeEdge.cxx
src/IntTools/IntTools_EdgeEdge.hxx
tests/bugs/modalg_7/bug30787 [new file with mode: 0644]

index 30bcd8a..5fe6d8c 100644 (file)
@@ -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
   {
index 78ef6ab..1484349 100644 (file)
@@ -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);
   }
 }
 
index ae68b8f..8dc80e3 100644 (file)
@@ -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 (file)
index 0000000..1fc401c
--- /dev/null
@@ -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