0026418: Unjustified limitation on tolerance of a input shape in BRepOffset_MakeOffset
authoraml <aml@opencascade.com>
Tue, 21 Jul 2015 08:19:14 +0000 (11:19 +0300)
committerbugmaster <bugmaster@opencascade.com>
Tue, 21 Jul 2015 08:20:27 +0000 (11:20 +0300)
Performance improvements and regression elimination.
Handling of degenerated case added.

Update of test-case offset faces_type_a A2 according to the new behavior
Test-case for issue #26418

src/BRepOffset/BRepOffset_MakeOffset.cxx
src/BRepOffset/BRepOffset_Tool.cxx
src/Geom/Geom_OffsetSurface.cxx
tests/bugs/modalg_6/bug26418_1 [new file with mode: 0644]
tests/bugs/modalg_6/bug26418_2 [new file with mode: 0644]
tests/bugs/modalg_6/bug26418_3 [new file with mode: 0644]
tests/bugs/modalg_6/bug26418_4 [new file with mode: 0644]
tests/offset/faces_type_a/A2

index e3312e8..9539271 100644 (file)
@@ -657,8 +657,6 @@ static void EvalMax(const TopoDS_Shape& S, Standard_Real& Tol)
     Standard_Real        TolV = BRep_Tool::Tolerance(V); 
     if (TolV > Tol) Tol = TolV;
   }
-  //Patch
-  Tol *= 5.;
 }
 
 //=======================================================================
@@ -688,10 +686,9 @@ void BRepOffset_MakeOffset::MakeOffsetShape()
   // Preanalyse.
   // ------------
   EvalMax(myShape,myTol);
-  if (myTol > Abs(myOffset*0.5)) {
-    Standard_ConstructionError::Raise("BRepOffset_MakeOffset : Tol > Offset");
-  }
-  Standard_Real TolAngle = 4*ASin(myTol/Abs(myOffset*0.5));
+  // There are possible second variant: analytical continuation of arcsin.
+  Standard_Real TolAngleCoeff = Min(myTol/Abs(myOffset*0.5), 1.0);
+  Standard_Real TolAngle = 4*ASin(TolAngleCoeff);
   myAnalyse.Perform(myShape,TolAngle);
   //---------------------------------------------------
   // Construction of Offset from preanalysis.
index 80d2836..4ddb3c2 100644 (file)
@@ -1151,14 +1151,15 @@ static Handle(Geom2d_Curve) ConcatPCurves(const TopoDS_Edge& E1,
 //=======================================================================
 
 static TopoDS_Edge Glue(const TopoDS_Edge& E1,
-                       const TopoDS_Edge& E2,
-                       const TopoDS_Vertex& Vfirst,
-                       const TopoDS_Vertex& Vlast,
-                       const Standard_Boolean After,
-                       const TopoDS_Face& F1,
-                       const Standard_Boolean addPCurve1,
-                       const TopoDS_Face& F2,
-                       const Standard_Boolean addPCurve2)
+                        const TopoDS_Edge& E2,
+                        const TopoDS_Vertex& Vfirst,
+                        const TopoDS_Vertex& Vlast,
+                        const Standard_Boolean After,
+                        const TopoDS_Face& F1,
+                        const Standard_Boolean addPCurve1,
+                        const TopoDS_Face& F2,
+                        const Standard_Boolean addPCurve2,
+                        const Standard_Real theGlueTol)
 {
   Standard_Real Tol = 1.e-7;
   GeomAbs_Shape Continuity = GeomAbs_C1;
@@ -1196,7 +1197,7 @@ static TopoDS_Edge Glue(const TopoDS_Edge& E1,
       Handle(Geom_TrimmedCurve) TC1 = new Geom_TrimmedCurve( C1, first1, last1 );
       Handle(Geom_TrimmedCurve) TC2 = new Geom_TrimmedCurve( C2, first2, last2 );
       GeomConvert_CompCurveToBSplineCurve Concat( TC1 );
-      Concat.Add( TC2, Precision::Confusion(), After );
+      Concat.Add( TC2, theGlueTol, After );
       newCurve = Concat.BSplineCurve();
       if (newCurve->Continuity() < GeomAbs_C1)
        {
@@ -1484,6 +1485,7 @@ static TopoDS_Edge AssembleEdge(const BOPDS_PDS& pDS,
                                const TopTools_SequenceOfShape& EdgesForConcat)
 {
   TopoDS_Edge CurEdge = TopoDS::Edge( EdgesForConcat(1) );
+  Standard_Real aGlueTol = Precision::Confusion();
   for (Standard_Integer j = 2; j <= EdgesForConcat.Length(); j++)
     {
       TopoDS_Edge anEdge = TopoDS::Edge( EdgesForConcat(j) );
@@ -1508,6 +1510,7 @@ static TopoDS_Edge AssembleEdge(const BOPDS_PDS& pDS,
        {
          TopoDS_Vertex CV, V11, V12, V21, V22;
          TopExp::CommonVertex( CurEdge, anEdge, CV );
+          aGlueTol = BRep_Tool::Tolerance(CV);
          TopExp::Vertices( CurEdge, V11, V12 );
          TopExp::Vertices( anEdge,  V21, V22 );
          if (V11.IsSame(CV) && V21.IsSame(CV))
@@ -1532,9 +1535,8 @@ static TopoDS_Edge AssembleEdge(const BOPDS_PDS& pDS,
            }
        } //end of else (open wire)
       
-      TopoDS_Edge NewEdge = Glue(CurEdge, anEdge,
-                                Vfirst, Vlast, After,
-                                F1, addPCurve1, F2, addPCurve2);
+      TopoDS_Edge NewEdge = Glue(CurEdge, anEdge, Vfirst, Vlast, After,
+                                 F1, addPCurve1, F2, addPCurve2, aGlueTol);
       CurEdge = NewEdge;
     } //end of for (Standard_Integer j = 2; j <= EdgesForConcat.Length(); j++)
   
index e8a0ff5..770fc95 100644 (file)
@@ -1767,8 +1767,20 @@ void Geom_OffsetSurface::SetD0(const Standard_Real U, const Standard_Real V,
     CSLib::Normal(MaxOrder,DerNUV,MagTol,U,V,Umin,Umax,Vmin,Vmax,NStatus,Normal,OrderU,OrderV);
     if (NStatus == CSLib_Defined) 
       P.SetXYZ(P.XYZ() + offsetValue * signe * Normal.XYZ());
-    else 
+    else
+    {
+      if (NStatus == CSLib_InfinityOfSolutions &&
+          D1U.SquareMagnitude() + D1V.SquareMagnitude() > MagTol * MagTol)
+      {
+        // Use non-null derivative as normal direction in degenerated case.
+        gp_Vec aNorm = D1U.SquareMagnitude() > MagTol * MagTol ? D1U : D1V;
+        aNorm.Normalize();
+
+        P.SetXYZ(P.XYZ() + offsetValue * signe * aNorm.XYZ());
+        return;
+      }
       Geom_UndefinedValue::Raise();
+    }
 
   }
 }
@@ -1777,21 +1789,70 @@ void Geom_OffsetSurface::SetD0(const Standard_Real U, const Standard_Real V,
 //function : 
 //purpose  : private
 //=======================================================================/
-void Geom_OffsetSurface::SetD1(const Standard_Real U, const Standard_Real V, 
-  Pnt& P, 
-  Vec& D1U, Vec& D1V,
-  const Vec& d2u, const Vec& d2v, const Vec& d2uv ) const
+void Geom_OffsetSurface::SetD1(const Standard_Real U,
+                               const Standard_Real V, 
+                               Pnt& P,
+                               Vec& D1U, Vec& D1V, // First derivative
+                               const Vec& D2UU, const Vec& D2VV, const Vec& D2UV ) const // Second derivative
 {
-
   Standard_Real MagTol=0.000000001;
+
+  // Check offset side.
+  Handle(Geom_BSplineSurface) L;
+  Standard_Boolean AlongU = Standard_False,
+                   AlongV = Standard_False;
+  Standard_Boolean IsOpposite=Standard_False;
+  AlongU = UOsculatingSurface(U,V,IsOpposite,L); 
+  AlongV = VOsculatingSurface(U,V,IsOpposite,L);
+  Standard_Real signe = 1.0;
+  if ((AlongV || AlongU) && IsOpposite) 
+    signe = -1.0;
+
   Dir Normal;
   CSLib_NormalStatus NStatus;
   CSLib::Normal (D1U, D1V, MagTol, NStatus, Normal);
   Standard_Integer MaxOrder;
   if (NStatus == CSLib_Defined) 
+  {
     MaxOrder=0;
+
+    if (!AlongV && !AlongU)
+    {
+      // AlongU or AlongV leads to more complex D1 computation
+      // Try to compute D0 and D1 much simpler
+      P.SetXYZ(P.XYZ() + offsetValue * signe * Normal.XYZ());
+
+      gp_Vec aN0(Normal.XYZ()), aN1U, aN1V;
+      Standard_Real aScale = (D1U^D1V).Dot(aN0);
+      aN1U.SetX(D2UU.Y() * D1V.Z() + D1U.Y() * D2UV.Z() 
+              - D2UU.Z() * D1V.Y() - D1U.Z() * D2UV.Y());
+      aN1U.SetY((D2UU.X() * D1V.Z() + D1U.X() * D2UV.Z() 
+               - D2UU.Z() * D1V.X() - D1U.Z() * D2UV.X() ) * -1.0);
+      aN1U.SetZ(D2UU.X() * D1V.Y() + D1U.X() * D2UV.Y() 
+              - D2UU.Y() * D1V.X() - D1U.Y() * D2UV.X());
+      Standard_Real aScaleU = aN1U.Dot(aN0);
+      aN1U.Subtract(aScaleU * aN0);
+      aN1U /= aScale;
+
+      aN1V.SetX(D2UV.Y() * D1V.Z() + D2VV.Z() * D1U.Y() 
+              - D2UV.Z() * D1V.Y() - D2VV.Y() * D1U.Z());
+      aN1V.SetY((D2UV.X() * D1V.Z() + D2VV.Z() * D1U.X() 
+               - D2UV.Z() * D1V.X() - D2VV.X() * D1U.Z()) * -1.0);
+      aN1V.SetZ(D2UV.X() * D1V.Y() + D2VV.Y() * D1U.X() 
+              - D2UV.Y() * D1V.X() - D2VV.X() * D1U.Y());
+      Standard_Real aScaleV = aN1V.Dot(aN0);
+      aN1V.Subtract(aScaleV * aN0);
+      aN1V /= aScale;
+
+      D1U += offsetValue * signe * aN1U;
+      D1V += offsetValue * signe * aN1V;
+
+      return;
+    }
+  }
   else 
     MaxOrder=3;
+
   Standard_Integer OrderU,OrderV;
   TColgp_Array2OfVec DerNUV(0,MaxOrder+1,0,MaxOrder+1);
   TColgp_Array2OfVec DerSurf(0,MaxOrder+2,0,MaxOrder+2);
@@ -1799,17 +1860,9 @@ void Geom_OffsetSurface::SetD1(const Standard_Real U, const Standard_Real V,
   Bounds(Umin,Umax,Vmin,Vmax);
   DerSurf.SetValue(1, 0, D1U);
   DerSurf.SetValue(0, 1, D1V);
-  DerSurf.SetValue(1, 1, d2uv);
-  DerSurf.SetValue(2, 0, d2u);
-  DerSurf.SetValue(0, 2, d2v);
-  Handle(Geom_BSplineSurface) L;
-  Standard_Boolean AlongU = Standard_False,
-    AlongV = Standard_False;
-  Standard_Boolean IsOpposite=Standard_False;
-  Standard_Real signe = 1.;
-  AlongU = UOsculatingSurface(U,V,IsOpposite,L); 
-  AlongV = VOsculatingSurface(U,V,IsOpposite,L);
-  if ((AlongV || AlongU) && IsOpposite) signe = -1;
+  DerSurf.SetValue(1, 1, D2UV);
+  DerSurf.SetValue(2, 0, D2UU);
+  DerSurf.SetValue(0, 2, D2VV);
   derivatives(MaxOrder,2,U,V,basisSurf,1,1,AlongU,AlongV,L,DerNUV,DerSurf);
 
   CSLib::Normal(MaxOrder,DerNUV,MagTol,U,V,Umin,Umax,Vmin,Vmax,NStatus,Normal,OrderU,OrderV);
@@ -1821,7 +1874,6 @@ void Geom_OffsetSurface::SetD1(const Standard_Real U, const Standard_Real V,
     + offsetValue * signe * CSLib::DNNormal(1,0,DerNUV,OrderU,OrderV);
   D1V = DerSurf(0,1)
     + offsetValue * signe * CSLib::DNNormal(0,1,DerNUV,OrderU,OrderV);
-
 }
 
 //=======================================================================
diff --git a/tests/bugs/modalg_6/bug26418_1 b/tests/bugs/modalg_6/bug26418_1
new file mode 100644 (file)
index 0000000..7840113
--- /dev/null
@@ -0,0 +1,12 @@
+puts "========"
+puts "OCC26418"
+puts "========"
+puts ""
+#################################################################################
+# Unjustified limitation on tolerance of a input shape in BRepOffset_MakeOffset
+#################################################################################
+
+offsetparameter 1e-7 a i
+restore [locate_data_file OCC26418-extracted_Plate103contour.brep] sh
+offsetload sh 10
+offsetperform r
diff --git a/tests/bugs/modalg_6/bug26418_2 b/tests/bugs/modalg_6/bug26418_2
new file mode 100644 (file)
index 0000000..41a741b
--- /dev/null
@@ -0,0 +1,12 @@
+puts "========"
+puts "OCC26418"
+puts "========"
+puts ""
+#################################################################################
+# Unjustified limitation on tolerance of a input shape in BRepOffset_MakeOffset
+#################################################################################
+
+offsetparameter 1e-7 a i
+restore [locate_data_file OCC26418-extracted_Plate103contour.brep] sh
+offsetload sh 16
+offsetperform r
diff --git a/tests/bugs/modalg_6/bug26418_3 b/tests/bugs/modalg_6/bug26418_3
new file mode 100644 (file)
index 0000000..ae2b255
--- /dev/null
@@ -0,0 +1,12 @@
+puts "========"
+puts "OCC26418"
+puts "========"
+puts ""
+#################################################################################
+# Unjustified limitation on tolerance of a input shape in BRepOffset_MakeOffset
+#################################################################################
+
+offsetparameter 1e-7 a i
+restore [locate_data_file OCC26418-extracted_Plate310contour.brep] sh
+offsetload sh 10
+offsetperform r
diff --git a/tests/bugs/modalg_6/bug26418_4 b/tests/bugs/modalg_6/bug26418_4
new file mode 100644 (file)
index 0000000..023f98d
--- /dev/null
@@ -0,0 +1,12 @@
+puts "========"
+puts "OCC26418"
+puts "========"
+puts ""
+#################################################################################
+# Unjustified limitation on tolerance of a input shape in BRepOffset_MakeOffset
+#################################################################################
+
+offsetparameter 1e-7 a i
+restore [locate_data_file OCC26418-extracted_Plate310contour.brep] sh
+offsetload sh 15
+offsetperform r
index b365d14..059e4ee 100644 (file)
@@ -1,10 +1,7 @@
-puts "TODO OCC23068 ALL: An exception was caught"
-puts "TODO OCC23068 ALL: \\*\\* Exception \\*\\*"
-puts "TODO OCC23068 ALL: TEST INCOMPLETE"
 #old file fritesb
 
 restore [locate_data_file fritehaut] s
 OFFSETSHAPE -.004 {s_3} $calcul $type
 
 
-set volume 0
+set volume 0.000514386