From 2ac4e1beee073adcde693f9e1d18338db22317c0 Mon Sep 17 00:00:00 2001 From: asuraven Date: Mon, 20 Dec 2021 19:27:09 +0300 Subject: [PATCH] 0032744: Modeling Algorithms - Endless loop in GCPnts_UniformDeflection fixed finish criteria in CPnts_UniformDeflection::Perform() --- src/CPnts/CPnts_UniformDeflection.cxx | 228 +++++++++++++++----------- src/QABugs/QABugs_20.cxx | 41 +++++ tests/bugs/modalg_7/bug32744 | 9 + 3 files changed, 181 insertions(+), 97 deletions(-) create mode 100644 tests/bugs/modalg_7/bug32744 diff --git a/src/CPnts/CPnts_UniformDeflection.cxx b/src/CPnts/CPnts_UniformDeflection.cxx index d58cfbcf98..d3d6225688 100644 --- a/src/CPnts/CPnts_UniformDeflection.cxx +++ b/src/CPnts/CPnts_UniformDeflection.cxx @@ -89,139 +89,173 @@ static void D22d(const Standard_Address C, const Standard_Real U, void CPnts_UniformDeflection::Perform() { gp_Pnt P, P1, P2; -// gp_Vec V1, V2, VV1, VV2, VV; gp_Vec V1, V2, VV; Standard_Real Un1; Standard_Real NormD1, NormD2; myIPoint = -1; myNbPoints = -1; - - while ( (myNbPoints<2) && (!myFinish) ) { - - myNbPoints = myNbPoints + 1; + + const Standard_Real anEspilon = Epsilon(myFirstParam); + + while ( (myNbPoints<2) && (!myFinish) ) + { + ++myNbPoints; myParams[myNbPoints] = myFirstParam; if (my3d) + { D23d(myCurve, myFirstParam, myPoints[myNbPoints], V1, V2); + } else + { D22d(myCurve, myFirstParam, myPoints[myNbPoints], V1, V2); - P = myPoints[myNbPoints] ; + } + P = myPoints[myNbPoints]; NormD1 = V1.Magnitude(); - if (NormD1 < myTolCur || V2.Magnitude() < myTolCur) { + if (NormD1 < myTolCur || V2.Magnitude() < myTolCur) + { // singularity on the tangent or null curvature myDu = Min(myDwmax, 1.5 * myDu); } - else { + else + { NormD2 = V2.CrossMagnitude(V1); - if (NormD2 / NormD1 < myDeflection) { // collinearity of derivatives - myDu = Min(myDwmax, 1.5 * myDu); + if (NormD2 / NormD1 < myDeflection) + { + // collinearity of derivatives + myDu = Min(myDwmax, 1.5 * myDu); } - else { - myDu = Sqrt(8.* myDeflection * NormD1 / NormD2 ); - myDu = Min(Max(myDu, myTolCur), myDwmax); + else + { + myDu = Sqrt(8.* myDeflection * NormD1 / NormD2); + myDu = Min(Max(myDu, myTolCur), myDwmax); } } // check if the arrow is observed if WithControl - - if (myControl) { + if (myControl) + { myDu = Min(myDu, myLastParam-myFirstParam); - if (my3d) { - - D03d(myCurve, myFirstParam + myDu,P); - D03d(myCurve, myFirstParam + (myDu / 2.0),P1); + if (my3d) + { + D03d(myCurve, myFirstParam + myDu,P); + D03d(myCurve, myFirstParam + (myDu / 2.0), P1); } - else { - - D02d(myCurve, myFirstParam + myDu,P); - D02d(myCurve, myFirstParam + (myDu / 2.0),P1); + else + { + D02d(myCurve, myFirstParam + myDu,P); + D02d(myCurve, myFirstParam + (myDu / 2.0), P1); } V1= gp_Vec(myPoints[myNbPoints], P); NormD1 = V1.Magnitude(); - if (NormD1 >= myDeflection) { - V2 = gp_Vec(myPoints[myNbPoints], P1); - NormD2 = V2.CrossMagnitude(V1) / NormD1; - - // passing of arrow starting from which the redivision is done is arbitrary - // probably it will be necessary to readjust it (differentiate the first point - // from the others) this test does not work on the points of inflexion - - if (NormD2 > myDeflection / 5.0) { - NormD2 = Max(NormD2, 1.1 * myDeflection); - myDu = myDu * Sqrt(myDeflection / NormD2); - myDu = Min(Max(myDu, myTolCur), myDwmax); - } + if (NormD1 >= myDeflection) + { + V2 = gp_Vec(myPoints[myNbPoints], P1); + NormD2 = V2.CrossMagnitude(V1) / NormD1; + + // passing of arrow starting from which the redivision is done is arbitrary + // probably it will be necessary to readjust it (differentiate the first point + // from the others) this test does not work on the points of inflexion + if (NormD2 > myDeflection / 5.0) + { + NormD2 = Max(NormD2, 1.1 * myDeflection); + myDu = myDu * Sqrt(myDeflection / NormD2); + myDu = Min(Max(myDu, myTolCur), myDwmax); + } } } - myFirstParam = myFirstParam + myDu; - myFinish = (myLastParam - myFirstParam < myTolCur) || (myDu == 0.); + myFirstParam += myDu; + myFinish = myLastParam - myFirstParam < myTolCur || + Abs(myDu) < myTolCur || + // to avoid less than double precision endless increment + myDu < anEspilon; } - if (myFinish) { + if (myFinish) + { // the last point is corrected if control - if (myControl && (myNbPoints == 1) ) { + if (myControl && (myNbPoints == 1) ) + { Un1 = myParams[0]; - if (myLastParam - Un1 < 0.33*(myLastParam-myFirstParam)) { - myFirstParam = (myLastParam + Un1) / 2.0; - myParams[0]= myFirstParam; - myParams[1]= myLastParam; - if (my3d) { - D03d(myCurve, myParams[0], myPoints[0]); - D03d(myCurve, myParams[1], myPoints[1]); - } - else { - D02d(myCurve, myParams[0], myPoints[0]); + if (myLastParam - Un1 < 0.33*(myLastParam-myFirstParam)) + { + myFirstParam = (myLastParam + Un1) / 2.0; + myParams[0] = myFirstParam; + myParams[1] = myLastParam; + if (my3d) + { + D03d(myCurve, myParams[0], myPoints[0]); + D03d(myCurve, myParams[1], myPoints[1]); + } + else + { + D02d(myCurve, myParams[0], myPoints[0]); D02d(myCurve, myParams[1], myPoints[1]); - } + } } - else { - if (my3d) { - D23d(myCurve, myLastParam, P1, V1, V2); - } - else { - D22d(myCurve, myLastParam, P1, V1, V2); - } - P = myPoints[0] ; - VV = gp_Vec(P1, P); - NormD1 = VV.Magnitude(); - if ( NormD1 < myDeflection) { - myParams[1]= myLastParam; - myPoints[1]= P1 ; - } - else { - myFirstParam = (myLastParam * (myParams[1] - Un1) + Un1 * myDu) - /(myFirstParam -Un1); - if (my3d) - D03d(myCurve, myFirstParam, P2); - else - D02d(myCurve, myFirstParam, P2); - - if ((VV.CrossMagnitude(gp_Vec(P2, P)) / NormD1 < myDeflection) && - (Un1 >= myLastParam - myDwmax) ) { - // point n is removed - myParams[1]= myLastParam; - myPoints[1] = P1 ; - } - else { - myParams[1]=myFirstParam; - myPoints[1] = P2 ; - myParams[2]=myLastParam; - myPoints[2] = P1 ; - myNbPoints = myNbPoints +1; - } - } + else + { + if (my3d) + { + D23d(myCurve, myLastParam, P1, V1, V2); + } + else + { + D22d(myCurve, myLastParam, P1, V1, V2); + } + P = myPoints[0]; + VV = gp_Vec(P1, P); + NormD1 = VV.Magnitude(); + if (NormD1 < myDeflection) + { + myParams[1] = myLastParam; + myPoints[1] = P1; + } + else + { + myFirstParam = (myLastParam * (myParams[1] - Un1) + Un1 * myDu) / (myFirstParam - Un1); + if (my3d) + { + D03d(myCurve, myFirstParam, P2); + } + else + { + D02d(myCurve, myFirstParam, P2); + } + if ((VV.CrossMagnitude(gp_Vec(P2, P)) / NormD1 < myDeflection) && + (Un1 >= myLastParam - myDwmax) ) + { + // point n is removed + myParams[1] = myLastParam; + myPoints[1] = P1; + } + else + { + myParams[1] = myFirstParam; + myPoints[1] = P2; + myParams[2] = myLastParam; + myPoints[2] = P1; + ++myNbPoints; + } + } } } - else { - myNbPoints = myNbPoints +1 ; - if (myNbPoints >= 3) myNbPoints = 2; - myParams[myNbPoints]= myLastParam; - if (my3d) { - D03d(myCurve, myLastParam, myPoints[myNbPoints]); - } - else { - D02d(myCurve, myLastParam, myPoints[myNbPoints]); - } + else + { + ++myNbPoints; + if (myNbPoints >= 3) + { + myNbPoints = 2; + } + myParams[myNbPoints] = myLastParam; + if (my3d) + { + D03d(myCurve, myLastParam, myPoints[myNbPoints]); + } + else + { + D02d(myCurve, myLastParam, myPoints[myNbPoints]); + } } } } diff --git a/src/QABugs/QABugs_20.cxx b/src/QABugs/QABugs_20.cxx index 4647e76614..4248cd2b2e 100644 --- a/src/QABugs/QABugs_20.cxx +++ b/src/QABugs/QABugs_20.cxx @@ -4148,6 +4148,41 @@ static Standard_Integer OCC29406 (Draw_Interpretor&, Standard_Integer, const cha return 0; } +#include +#include +static Standard_Integer OCC32744(Draw_Interpretor& theDi, Standard_Integer theNbArgs, const char** theArgVec) +{ + if (theNbArgs != 2) + { + theDi << "Syntax error: wrong number of arguments!\n"; + return 1; + } + + const TopoDS_Shape& aShape = DBRep::Get(theArgVec[1]); + if (aShape.IsNull()) + { + theDi << " Null Shape is not allowed here\n"; + return 1; + } + else if (aShape.ShapeType() != TopAbs_EDGE) + { + theDi << " Shape type must be EDGE\n"; + return 1; + } + + const TopoDS_Edge& anEdge = TopoDS::Edge(aShape); + BRepCheck_Analyzer analyzer(anEdge); + if (analyzer.IsValid()) + { + Standard_Real firstParam = 0., lastParam = 0.; + Handle(Geom_Curve) pCurve = BRep_Tool::Curve(anEdge, firstParam, lastParam); + GeomAdaptor_Curve curveAdaptor(pCurve, firstParam, lastParam); + GCPnts_UniformDeflection uniformAbs(curveAdaptor, 0.001, firstParam, lastParam); + } + + return 0; +} + void QABugs::Commands_20(Draw_Interpretor& theCommands) { const char *group = "QABugs"; @@ -4234,5 +4269,11 @@ void QABugs::Commands_20(Draw_Interpretor& theCommands) { theCommands.Add ("OCC29406", "Tests the case when newly set axis for gp_Ax3 is parallel to one of current axis", __FILE__, OCC29406, group); + + theCommands.Add("OCC32744", + "Tests avoid Endless loop in GCPnts_UniformDeflection", + __FILE__, + OCC32744, group); + return; } diff --git a/tests/bugs/modalg_7/bug32744 b/tests/bugs/modalg_7/bug32744 new file mode 100644 index 0000000000..17b37f1e10 --- /dev/null +++ b/tests/bugs/modalg_7/bug32744 @@ -0,0 +1,9 @@ +puts "=================================================" +puts "0032744: Modeling Algorithms -Endless loop in GCPnts_UniformDeflection" +puts "=================================================" +puts "" + +pload QAcommands +# test execution time must be within the cpulimit +restore [locate_data_file bug32744.brep] s +OCC32744 s \ No newline at end of file