0025632: IGES writer looses face orientation
authorika <ika@opencascade.com>
Thu, 29 Jan 2015 11:13:29 +0000 (14:13 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 29 Jan 2015 11:15:30 +0000 (14:15 +0300)
Adding reversing surfaces before writing for reversed faces

Test case for issue CR25632

src/BRep/BRep_Builder.cxx
src/BRepToIGES/BRepToIGES_BRShell.cxx
tests/bugs/iges/bug25632 [new file with mode: 0755]

index b30c72f..f109a38 100644 (file)
@@ -235,11 +235,20 @@ static void UpdateCurves(BRep_ListOfCurveRepresentation& lcr,
   Handle(BRep_CurveRepresentation) cr;
   Handle(BRep_GCurve) GC;
   Standard_Real f = 0.,l = 0.;
+  Standard_Boolean rangeFound = Standard_False;
 
   while (itcr.More()) {
     GC = Handle(BRep_GCurve)::DownCast(itcr.Value());
     if ( !GC.IsNull() ) {
-      GC->Range(f,l);
+      if (GC->IsCurve3D()) {
+        GC->Range(f,l);
+        Standard_Boolean undefined = (Precision::IsPositiveInfinite(l) ||
+                                      Precision::IsNegativeInfinite(f));
+          
+        if (!undefined) {
+          rangeFound = Standard_True;
+        }
+      }
       Standard_Boolean iscos = GC->IsCurveOnSurface(S,L);
       if (iscos) break;
     }
@@ -257,7 +266,7 @@ static void UpdateCurves(BRep_ListOfCurveRepresentation& lcr,
     Handle(BRep_CurveOnClosedSurface) COS =
       new BRep_CurveOnClosedSurface(C1,C2,S,L,GeomAbs_C0);
     // test if there is already a range
-    if (!GC.IsNull()) {
+    if (rangeFound) {
       COS->SetRange(f,l);
     }
     lcr.Append(COS);
@@ -282,11 +291,20 @@ static void UpdateCurves(BRep_ListOfCurveRepresentation& lcr,
   Handle(BRep_CurveRepresentation) cr;
   Handle(BRep_GCurve) GC;
   Standard_Real f = 0.,l = 0.;
+  Standard_Boolean rangeFound = Standard_False;
 
   while (itcr.More()) {
     GC = Handle(BRep_GCurve)::DownCast(itcr.Value());
     if ( !GC.IsNull() ) {
-      GC->Range(f,l);
+      if (GC->IsCurve3D()) {
+        GC->Range(f,l);
+        Standard_Boolean undefined = (Precision::IsPositiveInfinite(l) ||
+                                      Precision::IsNegativeInfinite(f));
+          
+        if (!undefined) {
+          rangeFound = Standard_True;
+        }
+      }
       Standard_Boolean iscos = GC->IsCurveOnSurface(S,L);
       if (iscos) break;
     }
@@ -304,7 +322,7 @@ static void UpdateCurves(BRep_ListOfCurveRepresentation& lcr,
     Handle(BRep_CurveOnClosedSurface) COS =
       new BRep_CurveOnClosedSurface(C1,C2,S,L,GeomAbs_C0);
     // test if there is already a range
-    if (!GC.IsNull()) {
+    if (rangeFound) {
       COS->SetRange(f,l);
     }
     COS->SetUVPoints2(Pf,Pl);
index dcc9fd8..ed7ea18 100644 (file)
@@ -20,6 +20,7 @@
 #include <BRepToIGES_BRShell.ixx>
 #include <BRepToIGES_BRWire.hxx>
 
+#include <BRep_Builder.hxx>
 #include <BRep_Tool.hxx>
 #include <BRepTools.hxx>
 
@@ -33,6 +34,7 @@
 #include <Geom_Surface.hxx>
 #include <Geom_SurfaceOfRevolution.hxx>
 #include <Geom_ToroidalSurface.hxx>
+#include <Geom2d_Curve.hxx>
 
 #include <GeomToIGES_GeomSurface.hxx>
 
 
 #include <Interface_Macros.hxx>
 
+#include <NCollection_Map.hxx>
+#include <NCollection_IncAllocator.hxx>
+
 #include <TColStd_HSequenceOfTransient.hxx>
 
 #include <TopLoc_Location.hxx>
 
+#include <TopTools_ShapeMapHasher.hxx>
+
 #include <TopoDS.hxx>
 #include <TopoDS_Vertex.hxx>
 #include <TopoDS_Edge.hxx>
@@ -132,6 +139,74 @@ Handle(IGESData_IGESEntity) BRepToIGES_BRShell ::TransferFace(const TopoDS_Face&
   if ( start.IsNull()) {
     return res;
   }
+
+  // pour explorer la face , il faut la mettre fORWARD.
+  TopoDS_Face myface;
+  if (start.Orientation() == TopAbs_REVERSED) {
+    //create face with redirected surface
+    BRep_Builder B;
+    TopLoc_Location aLoc;
+    Handle(Geom_Surface) aSurf = BRep_Tool::Surface(start, aLoc);
+    aSurf = aSurf->UReversed();
+    Standard_Real U1, U2, V1, V2;
+    aSurf->Bounds(U1, U2, V1, V2);
+    Standard_Real aTol = BRep_Tool::Tolerance(start);
+    B.MakeFace(myface, aSurf, aLoc ,aTol);
+    // set specifics flags of a Face
+         B.NaturalRestriction(myface, BRep_Tool::NaturalRestriction(start));
+    //add wires
+    TopoDS_Wire anOuter = TopoDS::Wire(ShapeAlgo::AlgoContainer()->OuterWire(start));
+    TopExp_Explorer ex;
+    for (ex.Init(start,TopAbs_WIRE); ex.More(); ex.Next()) {
+      TopoDS_Wire W = TopoDS::Wire(ex.Current());
+      if (!W.IsNull() && W.IsSame(anOuter)) {
+        B.Add(myface, W);
+        break;
+      }
+    }     
+    for (ex.Init(start,TopAbs_WIRE); ex.More(); ex.Next()) {
+      TopoDS_Wire W = TopoDS::Wire(ex.Current());
+      if (!W.IsNull() && !W.IsSame(anOuter)) {
+        B.Add(myface, W);
+      }
+    }
+    // mirror pcurves
+    NCollection_Map<TopoDS_Shape, TopTools_ShapeMapHasher> aMap (101, new NCollection_IncAllocator);
+    for (ex.Init(myface,TopAbs_EDGE);ex.More(); ex.Next()) {
+      TopoDS_Edge anEdge = TopoDS::Edge(ex.Current());
+      if (!aMap.Add(anEdge))
+        // seam edge has been already updated
+        continue;
+      Standard_Real f, l;
+      Handle(Geom2d_Curve) aCurve1, aCurve2;
+      aCurve1 = BRep_Tool::CurveOnSurface(anEdge, start, f, l);
+      aTol = BRep_Tool::Tolerance(anEdge);
+      gp_Trsf2d T;
+      gp_Ax2d axis(gp_Pnt2d(0.5 * (U1 + U2), V1), gp_Dir2d(0.,1.));
+      T.SetMirror(axis);
+      if (!aCurve1.IsNull()) {
+        aCurve1 = Handle(Geom2d_Curve)::DownCast(aCurve1->Transformed(T));
+        if (BRepTools::IsReallyClosed(anEdge, start)) {
+          TopoDS_Edge revEdge = TopoDS::Edge(anEdge.Reversed());
+          aCurve2 = BRep_Tool::CurveOnSurface(revEdge, start, f, l);
+          if (!aCurve2.IsNull()) {
+            aCurve2 = Handle(Geom2d_Curve)::DownCast(aCurve2->Transformed(T));
+            B.UpdateEdge(anEdge, aCurve1, aCurve2, myface, aTol);
+          }
+          else {
+            B.UpdateEdge(anEdge, aCurve1, myface, aTol);
+          }
+        }
+        else {
+          B.UpdateEdge(anEdge, aCurve1, myface, aTol);
+        }
+      }
+    }
+  }
+  else {
+    myface = start;
+  }
+
   //Standard_Integer Nb = 0; //szv#4:S4163:12Mar99 unused
   Standard_Real Length = 1.;
   Handle(IGESData_IGESEntity) ISurf;
@@ -139,13 +214,13 @@ Handle(IGESData_IGESEntity) BRepToIGES_BRShell ::TransferFace(const TopoDS_Face&
   // returns the face surface
   // ------------------------
 
-  Handle(Geom_Surface) Surf = BRep_Tool::Surface(start);
+  Handle(Geom_Surface) Surf = BRep_Tool::Surface(myface);
   Handle(Geom_Surface) Surf1;
 
   if (!Surf.IsNull()) {
     Standard_Real U1, U2, V1, V2;
     // pour limiter les surfaces de base
-    BRepTools::UVBounds(start, U1, U2, V1, V2); 
+    BRepTools::UVBounds(myface, U1, U2, V1, V2);  
     GeomToIGES_GeomSurface GS;
     GS.SetModel(GetModel());
     ISurf = GS.TransferSurface(Surf, U1, U2, V1, V2);
@@ -172,16 +247,9 @@ Handle(IGESData_IGESEntity) BRepToIGES_BRShell ::TransferFace(const TopoDS_Face&
   Standard_Integer Imode = 0; 
   Standard_Integer Iprefer = 0; 
   Handle(IGESData_IGESEntity) ICurve2d;
-  // pour explorer la face , il faut la mettre fORWARD.
-  TopoDS_Face myface = start;
-  Standard_Boolean IsReversed = Standard_False;
-  if (start.Orientation() == TopAbs_REVERSED) {
-    myface.Reverse();
-    IsReversed = Standard_True;
-  }
 
   // outer wire
-//:n3  TopoDS_Wire Outer = BRepTools::OuterWire(myface);
+  //:n3  TopoDS_Wire Outer = BRepTools::OuterWire(myface);
   TopoDS_Wire Outer = ShapeAlgo::AlgoContainer()->OuterWire(myface); //:n3 
   Handle(IGESGeom_CurveOnSurface) IOuter = new IGESGeom_CurveOnSurface;
   if (!Outer.IsNull()) {
@@ -205,7 +273,7 @@ Handle(IGESData_IGESEntity) BRepToIGES_BRShell ::TransferFace(const TopoDS_Face&
     }
     else if (!W.IsSame(Outer)) {
       Handle(IGESData_IGESEntity) ICurve3d = 
-       BW.TransferWire(W, myface, ICurve2d, Length);
+             BW.TransferWire(W, myface, ICurve2d, Length);
       if ((!ICurve3d.IsNull()) && (!ICurve2d.IsNull())) Iprefer = 3; 
       if ((!ICurve3d.IsNull()) && (ICurve2d.IsNull())) Iprefer = 2; 
       if ((ICurve3d.IsNull()) && (!ICurve2d.IsNull())) Iprefer = 1; 
@@ -256,10 +324,7 @@ Handle(IGESData_IGESEntity) BRepToIGES_BRShell ::TransferFace(const TopoDS_Face&
     TrimmedSurf-> Init (ISurf, Flag, IOuter, Tab);
 
   res = TrimmedSurf;
-  if (IsReversed) myface.Reverse();
-
   SetShapeResult ( start, res );
-
   return res;
 }
 
diff --git a/tests/bugs/iges/bug25632 b/tests/bugs/iges/bug25632
new file mode 100755 (executable)
index 0000000..b42a1f8
--- /dev/null
@@ -0,0 +1,29 @@
+puts "============"
+puts "OCC25632"
+puts "============"
+puts ""
+#######################################################################
+# IGES writer looses face orientation
+#######################################################################
+
+plane p 0 0 0 0 0 1 1 0 0
+mkface f p 0 100 0 100
+
+smallview
+donly f
+
+normals f 100
+
+treverse f
+normals f 100
+
+xwd ${imagedir}/${test_image}_1.png
+
+testwriteiges ${imagedir}/bug25632_f.igs f
+testreadiges ${imagedir}/bug25632_f.igs ff
+
+donly ff
+
+normals ff 100
+
+xwd ${imagedir}/${test_image}_2.png