]> OCCT Git - occt.git/commitdiff
0032744: Modeling Algorithms - Endless loop in GCPnts_UniformDeflection
authorasuraven <asuraven@opencascade.com>
Mon, 20 Dec 2021 16:27:09 +0000 (19:27 +0300)
committersmoskvin <smoskvin@opencascade.com>
Wed, 20 Jul 2022 12:53:27 +0000 (15:53 +0300)
fixed finish criteria in CPnts_UniformDeflection::Perform()

src/CPnts/CPnts_UniformDeflection.cxx
src/QABugs/QABugs_20.cxx
tests/bugs/modalg_7/bug32744 [new file with mode: 0644]

index d58cfbcf989a94054ae74642f4597a26186cdba7..d3d622568884c37dbd856ccdd3bf717cf91fe492 100644 (file)
@@ -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]);
+      }
     }
   }
 }
index 03488de8ed3e556f3913ec9775db9d78d2cb296a..c96981361d592810489e97b4c8bb9bb77678d055 100644 (file)
@@ -4172,6 +4172,41 @@ static Standard_Integer OCC29406 (Draw_Interpretor&, Standard_Integer, const cha
   return 0;
 }
 
+#include <BRepCheck_Analyzer.hxx>
+#include <GCPnts_UniformDeflection.hxx>
+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";
@@ -4258,5 +4293,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 (file)
index 0000000..17b37f1
--- /dev/null
@@ -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