0027272: FixMissingSeam function creates G1 seam curves
authorgka <gka@opencascade.com>
Tue, 12 Apr 2016 13:34:34 +0000 (16:34 +0300)
committerbugmaster <bugmaster@opencascade.com>
Fri, 15 Apr 2016 07:59:52 +0000 (10:59 +0300)
Method BRepLib::EncodeRegularity() is improved to set regularity GeomAbs_CN for edges lying on the same-domain surfaces (where derivatives on both surfaces are equal in all points).

DRAW command getedgeregularity is added to query regularity of the edge on specified faces.
DRAW command edgeregul is removed (this functionality is provided by command encoderegularity).

Added tests: bugs modalg_6 bug27272, bug27383_1, bug27383_2

Correction of shape name in test case for issue CR27272

src/BRepFeat/BRepFeat.cxx
src/BRepLib/BRepLib.cxx
src/BRepTest/BRepTest_SurfaceCommands.cxx
src/BRepTest/BRepTest_TopologyCommands.cxx
src/SWDRAW/SWDRAW_ShapeTool.cxx
tests/bugs/modalg_6/bug27272 [new file with mode: 0644]
tests/bugs/modalg_6/bug27383_1 [new file with mode: 0644]
tests/bugs/modalg_6/bug27383_2 [new file with mode: 0644]

index e4afcea..63ebee5 100644 (file)
@@ -23,7 +23,6 @@
 #include <BRepBuilderAPI.hxx>
 #include <BRepFeat.hxx>
 #include <BRepLib_MakeFace.hxx>
-#include <BRepLProp.hxx>
 #include <BRepTools.hxx>
 #include <BRepTopAdaptor_FClass2d.hxx>
 #include <ElSLib.hxx>
index b60055f..d6bac85 100644 (file)
@@ -88,6 +88,7 @@
 #include <TopTools_ListIteratorOfListOfShape.hxx>
 #include <TopTools_MapOfShape.hxx>
 #include <TShort_HArray1OfShortReal.hxx>
+#include <TColgp_Array1OfXY.hxx>
 
 // TODO - not thread-safe static variables
 static Standard_Real thePrecision = Precision::Confusion();     
@@ -1580,17 +1581,15 @@ Standard_Boolean BRepLib::OrientClosedSolid(TopoDS_Solid& solid)
 
   return Standard_True;
 }
-
 //=======================================================================
 //function : tgtfaces
 //purpose  : check the angle at the border between two squares.
 //           Two shares should have a shared front edge.
 //=======================================================================
-
-static Standard_Boolean tgtfaces(const TopoDS_Edge& Ed,
+static GeomAbs_Shape tgtfaces(const TopoDS_Edge& Ed,
   const TopoDS_Face& F1,
   const TopoDS_Face& F2,
-  const Standard_Real ta,
+  const Standard_Real theAngleTol,
   const Standard_Boolean couture)
 {
   // Check if pcurves exist on both faces of edge
@@ -1598,20 +1597,31 @@ static Standard_Boolean tgtfaces(const TopoDS_Edge& Ed,
   Handle(Geom2d_Curve) aCurve;
   aCurve = BRep_Tool::CurveOnSurface(Ed,F1,aFirst,aLast);
   if(aCurve.IsNull())
-    return Standard_False;
+    return GeomAbs_C0;
   aCurve = BRep_Tool::CurveOnSurface(Ed,F2,aFirst,aLast);
   if(aCurve.IsNull())
-    return Standard_False;
-
+    return GeomAbs_C0;
+  
   Standard_Real u;
   TopoDS_Edge E = Ed;
   BRepAdaptor_Surface aBAS1(F1,Standard_False);
   BRepAdaptor_Surface aBAS2(F2,Standard_False);
-  Handle(BRepAdaptor_HSurface) HS1 = new BRepAdaptor_HSurface(aBAS1);
+  
+  // seam edge on elementary surface is always CN
+  Standard_Boolean isElementary =
+    (aBAS1.Surface().Surface()->IsKind(STANDARD_TYPE(Geom_ElementarySurface)) &&
+     aBAS1.Surface().Surface()->IsKind(STANDARD_TYPE(Geom_ElementarySurface)));
+  if (couture && isElementary)
+  {
+    return GeomAbs_CN;
+  }
+  
+  Handle(BRepAdaptor_HSurface) HS1 = new BRepAdaptor_HSurface (aBAS1);
   Handle(BRepAdaptor_HSurface) HS2;
   if(couture) HS2 = HS1;
   else HS2 = new BRepAdaptor_HSurface(aBAS2);
-
+  //case when edge lies on the one face
+  
   E.Orientation(TopAbs_FORWARD);
   Handle(BRepAdaptor_HCurve2d) HC2d1 = new BRepAdaptor_HCurve2d();
   HC2d1->ChangeCurve2d().Initialize(E,F1);
@@ -1623,8 +1633,7 @@ static Standard_Boolean tgtfaces(const TopoDS_Edge& Ed,
 
   Standard_Boolean rev1 = (F1.Orientation() == TopAbs_REVERSED);
   Standard_Boolean rev2 = (F2.Orientation() == TopAbs_REVERSED);
-  Standard_Real f,l,eps, angmax = -M_PI;
-  Standard_Real ang =0.;
+  Standard_Real f,l,eps;
   BRep_Tool::Range(E,f,l);
   Extrema_LocateExtPC ext;
   Standard_Boolean IsInitialized = Standard_False;
@@ -1634,34 +1643,55 @@ static Standard_Boolean tgtfaces(const TopoDS_Edge& Ed,
   l -= eps; // points of pointed squares.
   gp_Pnt2d p;
   gp_Pnt pp1,pp2;//,PP;
-  gp_Vec du,dv;
+  gp_Vec du1, dv1, d2u1, d2v1, d2uv1;
+  gp_Vec du2, dv2, d2u2, d2v2, d2uv2;
   gp_Vec d1,d2;
   Standard_Real uu, vv, norm;
 
   Standard_Integer i;
-  Standard_Boolean Nok;
-  for(i = 0; (i<= 20) && (angmax<=ta) ; i++){
+  GeomAbs_Shape aCont = (isElementary ? GeomAbs_CN : GeomAbs_C2);
+  for(i = 0; i<= 20 && aCont > GeomAbs_C0; i++)
+  {
     // First suppose that this is sameParameter
-    Nok = Standard_True;
     u = f + (l-f)*i/20;
+
+    // take derivatives of surfaces at the same u, and compute normals
     HC2d1->D0(u,p);
-    HS1->D1(p.X(),p.Y(),pp1,du,dv);
-    d1 = (du.Crossed(dv));
+    HS1->D2 (p.X(), p.Y(), pp1, du1, dv1, d2u1, d2v1, d2uv1);
+    d1 = (du1.Crossed(dv1));
     norm = d1.Magnitude(); 
     if (norm > 1.e-12) d1 /= norm;
-    else Nok=Standard_False;
+    else continue; // skip degenerated point
     if(rev1) d1.Reverse();
 
     HC2d2->D0(u,p);
-    HS2->D1(p.X(), p.Y(), pp2, du, dv);
-    d2 = (du.Crossed(dv));
+    HS2->D2 (p.X(), p.Y(), pp2, du2, dv2, d2u2, d2v2, d2uv2);
+    d2 = (du2.Crossed(dv2));
     norm = d2.Magnitude();
-    if (norm> 1.e-12) d2 /= norm;
-    else Nok=Standard_False;
+    if (norm > 1.e-12) d2 /= norm;
+    else continue; // skip degenerated point
     if(rev2) d2.Reverse();
-    if (Nok) ang = d1.Angle(d2);
 
-    if (Nok &&(ang > ta)) { // Refine by projection
+    // check 
+    Standard_Real ang = d1.Angle(d2);
+
+    // check special case of precise equality of derivatives,
+    // occurring when edge connects two faces built on equally 
+    // defined surfaces (e.g. seam-like edges on periodic surfaces, 
+    // or planar faces on the same plane)
+    if (aCont >= GeomAbs_C2 && ang < Precision::Angular() &&
+        d2u1 .IsEqual (d2u2,  Precision::PConfusion(), Precision::Angular()) &&
+        d2v1 .IsEqual (d2v2,  Precision::PConfusion(), Precision::Angular()) &&
+        d2uv1.IsEqual (d2uv2, Precision::PConfusion(), Precision::Angular()))
+    {
+      continue;
+    }
+
+    aCont = GeomAbs_G1;
+
+    // Refine by projection
+    if (ang > theAngleTol)
+    {
       if (! IsInitialized ) {
         ext.Initialize(C2,f,l,Precision::PConfusion());
         IsInitialized = Standard_True;
@@ -1673,20 +1703,20 @@ static Standard_Boolean tgtfaces(const TopoDS_Edge& Ed,
 
         HC2d2->D0(v,p);
         p.Coord(uu,vv);
-        HS2->D1(p.X(), p.Y(), pp2, du, dv);
-        d2 = (du.Crossed(dv));
+        HS2->D1(p.X(), p.Y(), pp2, du2, dv2);
+        d2 = (du2.Crossed(dv2));
         norm = d2.Magnitude();
         if (norm> 1.e-12) d2 /= norm;
-        else Nok = Standard_False;
+        else continue; // degenerated point
         if(rev2) d2.Reverse();
-        if (Nok) ang = d1.Angle(d2);
+        ang = d1.Angle(d2);
       }
+      if (ang > theAngleTol)
+        return GeomAbs_C0;
     }
-    if(ang >= angmax) angmax = ang;
   }     
 
-  return (angmax<=ta);
-
+  return aCont;
 }
 
 
@@ -1735,9 +1765,8 @@ void BRepLib::EncodeRegularity(const TopoDS_Shape& S,
       if(BRep_Tool::Continuity(E,F1,F2)<=GeomAbs_C0){
 
         try {
-          if(tgtfaces(E, F1, F2, TolAng, couture)){
-            B.Continuity(E,F1,F2,GeomAbs_G1);
-          }
+          GeomAbs_Shape aCont = tgtfaces(E, F1, F2, TolAng, couture);
+          B.Continuity(E,F1,F2,aCont);
         }
         catch(Standard_Failure)
         {
@@ -1760,9 +1789,9 @@ void BRepLib::EncodeRegularity(TopoDS_Edge& E,
   BRep_Builder B;
   if(BRep_Tool::Continuity(E,F1,F2)<=GeomAbs_C0){
     try {
-      if( tgtfaces(E, F1, F2, TolAng, F1.IsEqual(F2))) {
-        B.Continuity(E,F1,F2,GeomAbs_G1);
-      }
+      GeomAbs_Shape aCont = tgtfaces(E, F1, F2, TolAng, F1.IsEqual(F2));
+      B.Continuity(E,F1,F2,aCont);
+      
     }
     catch(Standard_Failure)
     {
index d4c792e..dfe883e 100644 (file)
@@ -539,6 +539,41 @@ static Standard_Integer encoderegularity (Draw_Interpretor& ,
   return 0;
 }
 
+static Standard_Integer getedgeregul
+  (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
+{
+  if( argc < 3)
+  {
+    cout<<"Invalid number of arguments. Should be: checkedgeregularity edge face1 [face2]"<<endl;
+    return 1;
+  }
+  
+  TopoDS_Shape anEdge =  DBRep::Get(argv[1],TopAbs_EDGE);
+  TopoDS_Shape aFace1 = DBRep::Get(argv[2],TopAbs_FACE);
+  TopoDS_Shape aFace2 = (argc > 3  ? DBRep::Get(argv[3],TopAbs_FACE) : aFace1);
+  if( anEdge.IsNull() || aFace1.IsNull() || aFace2.IsNull())
+  {
+    cout<<"Invalid number of arguments. Should be: getedgeregularity edge face1 [face2]"<<endl;
+    return 1;
+  }
+  GeomAbs_Shape aRegularity = BRep_Tool::Continuity(TopoDS::Edge(anEdge), TopoDS::Face(aFace1),  TopoDS::Face(aFace2));
+  TCollection_AsciiString aStrReg("Regularity of edge : ");
+  switch( aRegularity)
+  {
+    default:
+    case GeomAbs_C0 : aStrReg += "C0"; break;
+    case GeomAbs_G1 : aStrReg += "G1"; break;
+    case GeomAbs_C1 : aStrReg += "C1"; break;
+    case GeomAbs_G2 : aStrReg += "G2"; break;
+    case GeomAbs_C2 : aStrReg += "C2"; break;
+    case GeomAbs_C3 : aStrReg += "C3"; break;
+    case GeomAbs_CN : aStrReg += "CN"; break;
+  };
+
+  di<<aStrReg.ToCString()<<"\n";
+  return 0; // Done
+}
 
 //=======================================================================
 //function : SurfaceCommands
@@ -594,5 +629,6 @@ void  BRepTest::SurfaceCommands(Draw_Interpretor& theCommands)
 
   theCommands.Add ("fastsewing", "fastsewing result [-tol <value>] <list_of_faces>", 
                                                 __FILE__, fastsewing, g);
+  theCommands.Add ("getedgeregularity", "getedgeregularity edge face1 [face2]",  __FILE__,getedgeregul,g);
 }
 
index d3a8355..71d34dd 100644 (file)
@@ -32,7 +32,6 @@
 #include <BRepPrimAPI_MakeHalfSpace.hxx>
 #include <BRepAlgo_FaceRestrictor.hxx>
 #include <BRepExtrema_ExtPF.hxx>
-#include <BRepLProp_SLProps.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
 #include <TopoDS.hxx>
 #include <TopoDS_Edge.hxx>
index 2549049..099f58b 100644 (file)
@@ -182,31 +182,6 @@ static Standard_Integer XSHAPE_ssolid
   return 0; // Done
 }
 
-
-static Standard_Integer XSHAPE_edgeregul
-  (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
-{
-  //cky/rln 03.02.99 To eliminate dependence of SWDRAW on TKXSBase (to use only ShapeHealing)
-  Standard_Real tolang = Precision::Angular(); // = Interface_Static::RVal("XSTEP.encoderegularity.angle");
-//  if (argc < 3) di<<"Current value for regularity angle : "<<tolang<<"\n";
-  if (argc < 3) {
-    di<<"Donner nom de shape.\n + option : angle en radian, sinon la valeur courante est prise\n";
-    return 0;
-  }
-  Standard_CString arg1 = argv[1];
-  Standard_CString arg2 = argv[2];
-  if (argc > 2) tolang = Draw::Atof (arg2);
-  if (tolang <= 0) {
-    di<<"Not a suitable value : "<<tolang<<"\n";
-    return 1 /* Error */;
-  }
-  TopoDS_Shape Shape = DBRep::Get(arg1);
-  if (Shape.IsNull()) { di<<"Shape unknown : "<<arg1<<"\n"; return 1 /* Error */; }
-
-  BRepLib::EncodeRegularity (Shape,tolang);
-  return 0; // Done
-}
-
 static Standard_Integer samerange (Draw_Interpretor& di,  Standard_Integer argc, const char** argv)  
 {
   if ( argc ==2 ) {
@@ -263,9 +238,6 @@ void  SWDRAW_ShapeTool::InitCommands (Draw_Interpretor& theCommands)
   theCommands.Add ("ssolid","nom shell + nouveau nom solid",
                   __FILE__,XSHAPE_ssolid,g);
 
-  theCommands.Add ("edgeregul","shape val",
-                  __FILE__,XSHAPE_edgeregul,g);
-
   theCommands.Add ("samerange","{ shape | result curve2d first last newfirst newlast }",
                   __FILE__,samerange,g);
 }
diff --git a/tests/bugs/modalg_6/bug27272 b/tests/bugs/modalg_6/bug27272
new file mode 100644 (file)
index 0000000..e470664
--- /dev/null
@@ -0,0 +1,17 @@
+puts "========"
+puts "0027272: FixMissingSeam function creates G1 seam curves"
+puts "========"
+puts ""
+puts "Check regularity setting after FixMissingSeam (original problem)"
+
+restore [locate_data_file bug27272_SeamTest_unfixed.brep] a
+fixshape res a 1.e-7 1.
+encoderegularity res
+
+explode res f
+explode res_3 e
+explode res_4 e
+if { ! [regexp "CN" [getedgeregularity res_3_2 res_3]] ||
+     ! [regexp "CN" [getedgeregularity res_4_2 res_4]] } {
+  puts "Error: Invalid regularity of the seam edge, expected CN"
+}
diff --git a/tests/bugs/modalg_6/bug27383_1 b/tests/bugs/modalg_6/bug27383_1
new file mode 100644 (file)
index 0000000..07c316c
--- /dev/null
@@ -0,0 +1,29 @@
+puts "========"
+puts "0027383: Modeling - improve handling of regularity on edges"
+puts "========"
+puts ""
+puts "Check regularity setting on edges between same-domain faces after fuse"
+
+# fuse of two boxes
+pload MODELING
+box b1 10 10 10
+box b2 5 5 0 10 10 10
+bfuse r b1 b2
+explode r f
+explode r_7 e
+getedgeregularity r_7_3 r_3 r_7 ;# returns C0: regularity is not set at all
+encoderegularity r
+
+explode res f
+explode res_3 e
+explode res_4 e
+if { ! [regexp "CN" [getedgeregularity r_7_3 r_3 r_7]] } {
+  puts "Error: Invalid regularity of the edge, expected CN"
+}
+
+# make image in HLR mode as illustration
+pload VISUALIZATION
+vdisplay r
+vfit
+vhlr on
+vdump ${imagedir}/${test_image}.png
diff --git a/tests/bugs/modalg_6/bug27383_2 b/tests/bugs/modalg_6/bug27383_2
new file mode 100644 (file)
index 0000000..54e8b44
--- /dev/null
@@ -0,0 +1,25 @@
+puts "========"
+puts "0027383: Modeling - improve handling of regularity on edges"
+puts "========"
+puts ""
+puts "Check regularity setting on edges of cylinder split by angle"
+
+# split of cylinder
+pload MODELING
+pcylinder p 2 10
+DT_SplitAngle r p
+
+explode r f
+explode r_1 e
+getedgeregularity r_1_2 r_1 r_2 ;# returns C0: regularity is not set at all
+encoderegularity r
+if { ! [regexp "CN" [getedgeregularity r_1_2 r_1 r_2]] } {
+  puts "Error: Invalid regularity of the edge, expected CN"
+}
+
+# make image in HLR mode as illustration
+pload VISUALIZATION
+vdisplay r
+vfit
+vhlr on
+vdump ${imagedir}/${test_image}.png