1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-09 18:50:54 +03:00

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.
This commit is contained in:
emv 2019-06-19 08:54:50 +03:00 committed by apn
parent 3c1b70842d
commit 88c3accd1a
4 changed files with 57 additions and 15 deletions

@ -55,6 +55,8 @@ static Standard_Boolean findNearestValidPoint(
// //
// the general step is computed using general curve resolution // the general step is computed using general curve resolution
Standard_Real aStep = theCurve.Resolution(theTol) * 1.01; Standard_Real aStep = theCurve.Resolution(theTol) * 1.01;
if (aStep < theEps)
aStep = theEps;
// aD1Mag is a threshold to consider local derivative magnitude too small // aD1Mag is a threshold to consider local derivative magnitude too small
// and to accelerate going out of sphere // and to accelerate going out of sphere
// (inverse of resolution is the maximal derivative); // (inverse of resolution is the maximal derivative);
@ -159,11 +161,19 @@ Standard_Boolean BRepLib::FindValidRange
if (theParV2 - theParV1 < Precision::PConfusion()) if (theParV2 - theParV1 < Precision::PConfusion())
return Standard_False; return Standard_False;
Standard_Real anEps = Max(Max(theCurve.Resolution(theTolE) * 0.1, Standard_Boolean isInfParV1 = Precision::IsInfinite (theParV1),
Epsilon(Max(Abs(theParV1), Abs(theParV2)))), isInfParV2 = Precision::IsInfinite (theParV2);
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()); Precision::PConfusion());
if (Precision::IsInfinite(theParV1)) if (isInfParV1)
theFirst = theParV1; theFirst = theParV1;
else else
{ {
@ -174,7 +184,7 @@ Standard_Boolean BRepLib::FindValidRange
return Standard_False; return Standard_False;
} }
if (Precision::IsInfinite(theParV2)) if (isInfParV2)
theLast = theParV2; theLast = theParV2;
else else
{ {

@ -304,7 +304,7 @@ void IntTools_EdgeEdge::FindSolutions(IntTools_SequenceOfRanges& theRanges1,
{ {
Standard_Boolean bIsClosed2; Standard_Boolean bIsClosed2;
Standard_Real aT11, aT12, aT21, aT22; Standard_Real aT11, aT12, aT21, aT22;
Bnd_Box aB2; Bnd_Box aB1, aB2;
// //
bSplit2 = Standard_False; bSplit2 = Standard_False;
myRange1.Range(aT11, aT12); myRange1.Range(aT11, aT12);
@ -313,7 +313,6 @@ void IntTools_EdgeEdge::FindSolutions(IntTools_SequenceOfRanges& theRanges1,
bIsClosed2 = IsClosed(myGeom2, aT21, aT22, myTol2, myRes2); bIsClosed2 = IsClosed(myGeom2, aT21, aT22, myTol2, myRes2);
// //
if (bIsClosed2) { if (bIsClosed2) {
Bnd_Box aB1;
BndBuildBox(myCurve1, aT11, aT12, myTol1, aB1); BndBuildBox(myCurve1, aT11, aT12, myTol1, aB1);
// //
gp_Pnt aP = myGeom2->Value(aT21); gp_Pnt aP = myGeom2->Value(aT21);
@ -321,8 +320,9 @@ void IntTools_EdgeEdge::FindSolutions(IntTools_SequenceOfRanges& theRanges1,
} }
// //
if (!bIsClosed2) { if (!bIsClosed2) {
BndBuildBox(myCurve1, aT11, aT12, myTol1, aB1);
BndBuildBox(myCurve2, aT21, aT22, myTol2, aB2); BndBuildBox(myCurve2, aT21, aT22, myTol2, aB2);
FindSolutions(myRange1, myRange2, aB2, theRanges1, theRanges2); FindSolutions(myRange1, aB1, myRange2, aB2, theRanges1, theRanges2);
return; return;
} }
// //
@ -343,10 +343,11 @@ void IntTools_EdgeEdge::FindSolutions(IntTools_SequenceOfRanges& theRanges1,
// //
for (i = 1; i <= aNb1; ++i) { for (i = 1; i <= aNb1; ++i) {
const IntTools_Range& aR1 = aSegments1(i); const IntTools_Range& aR1 = aSegments1(i);
BndBuildBox(myCurve1, aR1.First(), aR1.Last(), myTol1, aB1);
for (j = 1; j <= aNb2; ++j) { for (j = 1; j <= aNb2; ++j) {
const IntTools_Range& aR2 = aSegments2(j); const IntTools_Range& aR2 = aSegments2(j);
BndBuildBox(myCurve2, aR2.First(), aR2.Last(), myTol2, aB2); 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 : //purpose :
//======================================================================= //=======================================================================
void IntTools_EdgeEdge::FindSolutions(const IntTools_Range& theR1, void IntTools_EdgeEdge::FindSolutions(const IntTools_Range& theR1,
const Bnd_Box& theBox1,
const IntTools_Range& theR2, const IntTools_Range& theR2,
const Bnd_Box& theBox2, const Bnd_Box& theBox2,
IntTools_SequenceOfRanges& theRanges1, IntTools_SequenceOfRanges& theRanges1,
@ -373,6 +375,7 @@ void IntTools_EdgeEdge::FindSolutions(const IntTools_Range& theR1,
theR1.Range(aT11, aT12); theR1.Range(aT11, aT12);
theR2.Range(aT21, aT22); theR2.Range(aT21, aT22);
// //
aB1 = theBox1;
aB2 = theBox2; aB2 = theBox2;
// //
bThin = Standard_False; bThin = Standard_False;
@ -385,9 +388,7 @@ void IntTools_EdgeEdge::FindSolutions(const IntTools_Range& theR1,
aTB21 = aT21; aTB21 = aT21;
aTB22 = aT22; aTB22 = aT22;
// //
//1. Build box for first edge and find parameters //1. Find parameters of the second edge in the box of first one
// of the second one in that box
BndBuildBox(myCurve1, aT11, aT12, myTol1, aB1);
bOut = aB1.IsOut(aB2); bOut = aB1.IsOut(aB2);
if (bOut) { if (bOut) {
break; break;
@ -435,7 +436,9 @@ void IntTools_EdgeEdge::FindSolutions(const IntTools_Range& theR1,
((aT21 - aTB21) < aSmallStep2) && ((aTB22 - aT22) < aSmallStep2)) { ((aT21 - aTB21) < aSmallStep2) && ((aTB22 - aT22) < aSmallStep2)) {
bStop = Standard_True; bStop = Standard_True;
} }
// else
BndBuildBox (myCurve1, aT11, aT12, myTol1, aB1);
} while (!bStop); } while (!bStop);
// //
if (bOut) { if (bOut) {
@ -498,13 +501,20 @@ void IntTools_EdgeEdge::FindSolutions(const IntTools_Range& theR1,
Standard_Integer i, aNb1; Standard_Integer i, aNb1;
IntTools_SequenceOfRanges aSegments1; 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); IntTools_Range aR2(aT21, aT22);
BndBuildBox(myCurve2, aT21, aT22, myTol2, aB2); BndBuildBox(myCurve2, aT21, aT22, myTol2, aB2);
// //
aNb1 = SplitRangeOnSegments(aT11, aT12, myRes1, 3, aSegments1); aNb1 = SplitRangeOnSegments(aT11, aT12, myRes1, 3, aSegments1);
for (i = 1; i <= aNb1; ++i) { for (i = 1; i <= aNb1; ++i) {
const IntTools_Range& aR1 = aSegments1(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);
} }
} }

@ -146,7 +146,8 @@ protected:
//! Looking for the exact intersection ranges //! 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, const IntTools_Range& theR2, const Bnd_Box& theBox2,
IntTools_SequenceOfRanges& theRanges1, IntTools_SequenceOfRanges& theRanges2); IntTools_SequenceOfRanges& theRanges1, IntTools_SequenceOfRanges& theRanges2);

@ -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