0029663: Exception in BRepFill_PipeShell algorithm
authornbv <nbv@opencascade.com>
Thu, 29 Mar 2018 14:49:54 +0000 (17:49 +0300)
committerbugmaster <bugmaster@opencascade.com>
Mon, 9 Apr 2018 08:07:32 +0000 (11:07 +0300)
BRepFill_Sweep algorithm is improved to handle cases when generated revolution surface has degenerated point in the middle.

Added test bugs modalg_7 bug29663

TODO added in test bugs modalg_1 bug1477_11: here two additional self-intersecting faces are now created, previously missing from the result.

src/BRepFill/BRepFill_Sweep.cxx
tests/bugs/modalg_1/bug1477_11
tests/bugs/modalg_7/bug29663 [new file with mode: 0644]

index 07bd4fa..5e014f1 100644 (file)
@@ -859,24 +859,44 @@ static Standard_Boolean Filling(const TopoDS_Shape& EF,
   Prof1 = BRep_Tool::Curve(E1, f1, l1);
 //  Prof2 = BT.Curve(E2, f2, l2);
   Prof2 = BRep_Tool::Curve(E2, f2, l2);
+
+  // Indeed, both Prof1 and Prof2 are the same curves but in different positions
+
   gp_Pnt P1, P2, P;
-  gp_Pnt2d p1, p2;
-  gp_Trsf Tf;
-  Tf.SetTransformation(Axe);
-
-// Choose the angle of opening
-  P1 = Prof1->Value((f1+l1)/2);
-  P2 = Prof2->Value((f2+l2)/2);
-  P1.Transform(Tf);
-  P2.Transform(Tf);
-  p1.SetCoord(P1.Z(), P1.X());
-  p2.SetCoord(P2.Z(), P2.X());
-  gp_Vec2d v1(gp::Origin2d(), p1);
-  gp_Vec2d v2(gp::Origin2d(), p2);
-  if (v1.Magnitude() <= gp::Resolution() ||
-      v2.Magnitude() <= gp::Resolution())
+
+  // Choose the angle of opening
+  gp_Trsf aTf;
+  aTf.SetTransformation(Axe);
+
+  // Choose the furthest point from the "center of revolution"
+  // to provide correct angle measurement.
+  const Standard_Real aPrm[] = {f1, 0.5*(f1 + l1), l1};
+  const gp_Pnt aP1[] = {Prof1->Value(aPrm[0]).Transformed(aTf),
+                        Prof1->Value(aPrm[1]).Transformed(aTf),
+                        Prof1->Value(aPrm[2]).Transformed(aTf)};
+
+  Standard_Integer aMaxIdx = -1;
+  Standard_Real aMaxDist = RealFirst();
+  for (Standard_Integer i = 0; i < 3; i++)
+  {
+    const Standard_Real aDist = aP1[i].X()*aP1[i].X() + aP1[i].Z()*aP1[i].Z();
+    if (aDist > aMaxDist)
+    {
+      aMaxDist = aDist;
+      aMaxIdx = i;
+    }
+  }
+
+  const gp_Pnt aP2 = Prof2->Value(aPrm[aMaxIdx]).Transformed(aTf);
+  const gp_Vec2d aV1(aP1[aMaxIdx].Z(), aP1[aMaxIdx].X());
+  const gp_Vec2d aV2(aP2.Z(), aP2.X());
+  if (aV1.SquareMagnitude() <= gp::Resolution() ||
+      aV2.SquareMagnitude() <= gp::Resolution())
+  {
     return Standard_False;
-  Angle = v1.Angle(v2);
+  }
+
+  Angle = aV1.Angle(aV2);
 
   gp_Ax1 axe(Axe.Location(), Axe.YDirection());
 
@@ -887,7 +907,7 @@ static Standard_Boolean Filling(const TopoDS_Shape& EF,
 
   Handle(Geom_SurfaceOfRevolution) Rev = 
     new (Geom_SurfaceOfRevolution) (Prof1, axe);
-  
+
   Handle(Geom_Surface) Surf = 
     new (Geom_RectangularTrimmedSurface) (Rev, 0, Angle, f1, l1);
 
@@ -1185,19 +1205,40 @@ static Standard_Boolean Filling(const TopoDS_Shape& EF,
     B.MakeEdge(Aux2);
 
   // Set the orientation
-  gp_Vec D1U, D1V, N1, N2;
-  C1->D0( (f1+l1)/2, P2d);
-  Surf->D1(P2d.X(), P2d.Y(), P, D1U, D1V);
-  N1 = D1U^D1V;
-  
-//  C1 = BT.CurveOnSurface(E1, TopoDS::Face(F1), f2, l2);
-  C1 = BRep_Tool::CurveOnSurface(E1, TopoDS::Face(F1), f2, l2);
-  C1->D0( (f1+l1)/2, P2d);
-  Handle(BRepAdaptor_HSurface) AS = new BRepAdaptor_HSurface(TopoDS::Face(F1));
-  AS->D1(P2d.X(), P2d.Y(), P, D1U, D1V);
-  N2 = D1U^D1V;
+
+  // Provide correct normals computation
+  // (the normal will be computed not in 
+  // singularity point definitely).
+  Angle = RealFirst();
+  for (Standard_Integer i = 0; i < 3; i++)
+  {
+    gp_Vec D1U, D1V, N1, N2;
+    C1->D0(aPrm[i], P2d);
+    Surf->D1(P2d.X(), P2d.Y(), P, D1U, D1V);
+    N1 = D1U^D1V;
+
+    if (N1.SquareMagnitude() < Precision::SquareConfusion())
+      continue;
+
+    //  C1 = BT.CurveOnSurface(E1, TopoDS::Face(F1), f2, l2);
+    C1 = BRep_Tool::CurveOnSurface(E1, TopoDS::Face(F1), f2, l2);
+    C1->D0(aPrm[i], P2d);
+    Handle(BRepAdaptor_HSurface) AS = new BRepAdaptor_HSurface(TopoDS::Face(F1));
+    AS->D1(P2d.X(), P2d.Y(), P, D1U, D1V);
+    N2 = D1U^D1V;
+
+    if (N2.SquareMagnitude() < Precision::SquareConfusion())
+      continue;
+
+    Angle = N1.Angle(N2);
+
+    break;
+  }
   
-  if ( (F1.Orientation() == TopAbs_REVERSED) ^ (N1.Angle(N2)>M_PI/2) )
+  if (Angle == RealFirst())
+    return Standard_False;
+
+  if ( (F1.Orientation() == TopAbs_REVERSED) ^ (Angle>M_PI/2))
     Result.Orientation(TopAbs_REVERSED);
   else  Result.Orientation(TopAbs_FORWARD);
 
index cd0b079..d0984c4 100755 (executable)
@@ -8,6 +8,8 @@ puts ""
 # (case 11)
 ######################################################
 
+puts "TODO 29663 ALL: Faulty shapes in variables faulty_1 to faulty_4"
+
 restore [locate_data_file OCC1477-1.brep] s1 
 restore [locate_data_file OCC1477-2.brep] s2 
 
diff --git a/tests/bugs/modalg_7/bug29663 b/tests/bugs/modalg_7/bug29663
new file mode 100644 (file)
index 0000000..321de4b
--- /dev/null
@@ -0,0 +1,28 @@
+puts "========"
+puts "OCC29663"
+puts "========"
+puts ""
+#################################################
+# Exception in BRepFill_PipeShell algorithm
+#################################################
+
+restore [locate_data_file bug29523_cut_extrudewire08.brep] sw
+restore [locate_data_file bug29523_cut_toolwire08.brep] tw
+
+mksweep sw
+addsweep tw
+
+if { [catch {buildsweep rr -R} catch_result] } {
+    puts "Faulty OCC29663"
+}
+
+fixshape result rr
+
+checkshape result
+checkprops result -s 2.14316e+011
+
+checkmaxtol result -ref 0.070055357229360987
+
+checknbshapes result -shell 1 -face 201 -wire 201
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png