]> OCCT Git - occt-copy.git/commitdiff
0028414: Data Exchange - Step entity not correctly read CR28414
authorskl <skl@opencascade.com>
Wed, 18 Nov 2020 08:25:19 +0000 (11:25 +0300)
committerskl <skl@opencascade.com>
Thu, 3 Dec 2020 07:05:48 +0000 (10:05 +0300)
Fix + test.
For entity FACE_BOUND if surface is torus and orientation is True temporary natural bound is created. Later in the ShapeFix_Face this bound is removed but special flag myTorusReverseFlag is activated. Value of this flag is used for decision what part of torus must be used.

src/ShapeFix/ShapeFix_Face.cxx
src/ShapeFix/ShapeFix_Face.hxx
src/StepToTopoDS/StepToTopoDS_TranslateFace.cxx
tests/bugs/step/bug28414 [new file with mode: 0644]

index f0ad0e3ed1a42756154fc801014613778fcccbc4..614d91859313cd13d7766955de5e47767cc427fc 100644 (file)
@@ -62,6 +62,7 @@
 #include <NCollection_Array1.hxx>
 #include <Precision.hxx>
 #include <ShapeAnalysis.hxx>
+#include <ShapeAnalysis_Curve.hxx>
 #include <ShapeAnalysis_Edge.hxx>
 #include <ShapeAnalysis_Surface.hxx>
 #include <ShapeAnalysis_Wire.hxx>
@@ -134,6 +135,7 @@ ShapeFix_Face::ShapeFix_Face()
   myFwd = Standard_True;
   myStatus = 0;
   myFixWire = new ShapeFix_Wire;
+  myTorusReverseFlag = Standard_True;
   ClearModes();
 }
 
@@ -147,6 +149,7 @@ ShapeFix_Face::ShapeFix_Face(const TopoDS_Face &face)
   myFwd = Standard_True;
   myStatus = 0;
   myFixWire = new ShapeFix_Wire;
+  myTorusReverseFlag = Standard_True;
   ClearModes();
   Init( face );
 }
@@ -238,6 +241,7 @@ void ShapeFix_Face::Init (const Handle(ShapeAnalysis_Surface)& surf,
 {
   myStatus = 0;
   mySurf = surf;
+  myTorusReverseFlag = Standard_True;
   SetPrecision ( preci );
   BRep_Builder B;
   B.MakeFace ( myFace, mySurf->Surface(), ::Precision::Confusion() );
@@ -255,8 +259,57 @@ void ShapeFix_Face::Init (const TopoDS_Face& face)
 {
   myStatus = 0;
   mySurf = new ShapeAnalysis_Surface ( BRep_Tool::Surface (face) );
+  myTorusReverseFlag = Standard_True;
   myFwd = ( face.Orientation() != TopAbs_REVERSED );
   myFace = face;
+
+  if (mySurf->Surface()->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)))
+  {
+    // it is needed to check if face includes temporary created natural bound.
+    // this bound was created in order to detect cases where face has only one
+    // wire and this wire is outer. it means that if material is placed out of it
+    // this wire haven`t be reversed - for such face must be created correct
+    // natural bound and existed wire becames hole.
+    // temporary natural bound must be removed.
+    TopoDS_Wire outW;
+    Standard_Integer nbw = 0;
+    for (TopExp_Explorer exp(myFace, TopAbs_WIRE); exp.More(); exp.Next())
+    {
+      nbw++;
+      TopoDS_Wire aW = TopoDS::Wire(exp.Current());
+      TopExp_Explorer ex(aW, TopAbs_EDGE);
+      Bnd_Box2d aBox;
+      ShapeAnalysis_Edge sae;
+      ShapeAnalysis_Curve sac;
+      for (; ex.More(); ex.Next()) {
+        TopoDS_Edge edge = TopoDS::Edge(ex.Current());
+        Handle(Geom2d_Curve) c2d;
+        Standard_Real f, l;
+        if (!sae.PCurve(edge, myFace, c2d, f, l, Standard_False)) continue;
+        sac.FillBndBox(c2d, f, l, 20, Standard_True, aBox);
+      }
+      if (aBox.IsVoid()) continue;
+      Standard_Real UMin, VMin, UMax, VMax;
+      aBox.Get(UMin, VMin, UMax, VMax);
+      Standard_Boolean hasOutW =
+        fabs(UMin) < Precision::PConfusion() && fabs(2 * M_PI - UMax) < Precision::PConfusion() &&
+        fabs(VMin) < Precision::PConfusion() && fabs(2 * M_PI - VMax) < Precision::PConfusion();
+      if (hasOutW)
+      {
+        // it is a temporary added natural bound
+        myTorusReverseFlag = Standard_False;
+        outW = aW;
+      }
+    }
+    if (nbw==2 && !myTorusReverseFlag)
+    {
+      // remove temporary added natural bound
+      BRep_Builder B;
+      myFace.Free(Standard_True);
+      B.Remove(myFace, outW);
+    }
+  }
+
   myShape = myFace;
 //  myFace = TopoDS::Face(face.EmptyCopied());
 //  for (TopoDS_Iterator ws (face,Standard_False); ws.More(); ws.Next())
@@ -1098,17 +1151,36 @@ Standard_Boolean ShapeFix_Face::FixOrientation(TopTools_DataMapOfShapeListOfShap
     TopoDS_Face af = TopoDS::Face ( dummy );
     af.Orientation ( TopAbs_FORWARD );
     B.Add (af,ws.Value(1));
-    
+
     if ((myFixAddNaturalBoundMode != 1 ||
       !IsSurfaceUVPeriodic(mySurf->Adaptor3d())) &&
       !ShapeAnalysis::IsOuterBound(af))
     {
-      Handle(ShapeExtend_WireData) sbdw =
-        new ShapeExtend_WireData(TopoDS::Wire(ws.Value(1)));
-      sbdw->Reverse(myFace);
-      ws.SetValue(1, sbdw->Wire());
-      SendWarning(sbdw->Wire(), Message_Msg("FixAdvFace.FixOrientation.MSG5"));// Wire on face was reversed
-      done = Standard_True;
+      Standard_Boolean needReverse = Standard_True;
+      if (mySurf->Surface()->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)))
+      {
+        // detect situation when we have to use special flag for decision
+        // what part of torus must be used
+        Standard_Real SUF, SUL, SVF, SVL;
+        mySurf->Bounds(SUF, SUL, SVF, SVL);
+        Standard_Real aUmin, aUmax, aVmin, aVmax;
+        ShapeAnalysis::GetFaceUVBounds(myFace, aUmin, aUmax, aVmin, aVmax);
+        Standard_Boolean isInUmin = (aUmin > (SUF - Precision::PConfusion())) && (aUmin < (SUL + Precision::PConfusion()));
+        Standard_Boolean isInUmax = (aUmax > (SUF - Precision::PConfusion())) && (aUmax < (SUL + Precision::PConfusion()));
+        if ((isInUmin && !isInUmax) || (!isInUmin && isInUmax))
+        {
+          needReverse = myTorusReverseFlag;
+        }
+      }
+      if (needReverse)
+      {
+        Handle(ShapeExtend_WireData) sbdw =
+          new ShapeExtend_WireData(TopoDS::Wire(ws.Value(1)));
+        sbdw->Reverse(myFace);
+        ws.SetValue(1, sbdw->Wire());
+        SendWarning(sbdw->Wire(), Message_Msg("FixAdvFace.FixOrientation.MSG5"));// Wire on face was reversed
+        done = Standard_True;
+      }
     }
   }
   // in case of several wires, perform complex analysis
index 9fc7d070a66097fc39610c5eae01186da51c737f..38e0541913c163302ee096c604e76954c3aa28fb 100644 (file)
@@ -280,7 +280,9 @@ private:
   Standard_Integer myAutoCorrectPrecisionMode;
   Standard_Integer myFixPeriodicDegenerated;
 
-
+  // flag for manage in special cases what part of torus must be used
+  // if face based on such surface has one wire
+  Standard_Boolean myTorusReverseFlag;
 };
 
 
index 8bf7a3ee4f38111a12996f9875018498843ccd9c..645d506f79a3f8d0c278b186a878e1dc43cb4e25 100644 (file)
@@ -317,6 +317,26 @@ void StepToTopoDS_TranslateFace::Init
     //:S4136   if (EL->NbEdgeList() != 1) STF.Closed() = Standard_False;
     //:S4136      }
 
+    if (GeomSurf->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)))
+    {
+      if (NbBnd == 1 && !FaceBound->IsKind(STANDARD_TYPE(StepShape_FaceOuterBound)) && FaceBound->Orientation())
+      {
+        // Create natural bound for face based on the toroidal surface
+        // in order to detect such cases in ShapeFix_Face
+        // We suggest that existed one boundary is outer and correct => if after
+        // future analysis we recieve that material out of it we have to create
+        // correct natural bound and existed wire becames hole.
+        // Later in the ShapeFix_Face this temporary bound will be removed but 
+        // special flag will be activated.
+        BRepBuilderAPI_MakeFace mf(GeomSurf, Precision());
+        for (TopoDS_Iterator it(mf); it.More(); it.Next())
+        {
+          TopoDS_Wire aW = TopoDS::Wire(it.Value());
+          B.Add(F, aW);
+        }
+      }
+    }
+
     TopoDS_Wire   W;
     myTranEdgeLoop.SetPrecision(Precision());  //gka
     myTranEdgeLoop.SetMaxTol(MaxTol());
diff --git a/tests/bugs/step/bug28414 b/tests/bugs/step/bug28414
new file mode 100644 (file)
index 0000000..a68f4e9
--- /dev/null
@@ -0,0 +1,18 @@
+puts "==================================================================="
+puts "0028414: Data Exchange - Step entity not correctly read"
+puts "==================================================================="
+puts ""
+
+stepread [locate_data_file bug28414_bug_toroidal_surface.stp] a *
+
+checkshape a_1 f
+
+checkprops a_1 -s 3593.35
+
+checkgravitycenter a_1 -s -30. 0. 137.993 0.001
+
+vinit
+vdisplay a_1
+vfit
+
+vdump $imagedir/${casename}.png