0026620: Shape healing unreasonably downgrades tolerance of a face
authoraml <aml@opencascade.com>
Thu, 22 Oct 2015 11:54:59 +0000 (14:54 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 22 Oct 2015 11:59:43 +0000 (14:59 +0300)
Added face support in SameParameter in classes ShapeAnalysis_Edge, ShapeFix_Edge.

Test case for issue CR26620

Minor correction.

src/ShapeAnalysis/ShapeAnalysis_Edge.cxx
src/ShapeAnalysis/ShapeAnalysis_Edge.hxx
src/ShapeFix/ShapeFix.cxx
src/ShapeFix/ShapeFix_Edge.cxx
src/ShapeFix/ShapeFix_Edge.hxx
src/ShapeFix/ShapeFix_Face.cxx
src/ShapeFix/ShapeFix_Shape.cxx
src/ShapeFix/ShapeFix_Wire.cxx
tests/bugs/heal/bug26620 [new file with mode: 0644]

index 45b4bc3..1cde3aa 100644 (file)
@@ -772,6 +772,19 @@ Standard_Boolean ShapeAnalysis_Edge::ComputeDeviation (const Adaptor3d_Curve& CR
   return OK;
 }
 
+//=======================================================================
+//function : CheckSameParameter
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean ShapeAnalysis_Edge::CheckSameParameter (const TopoDS_Edge& edge,
+                                                         Standard_Real& maxdev,
+                                                         const Standard_Integer NbControl)
+{
+  TopoDS_Face anEmptyFace;
+  return CheckSameParameter(edge, anEmptyFace, maxdev, NbControl);
+}
+
 
 //=======================================================================
 //function : CheckSameParameter
@@ -779,8 +792,9 @@ Standard_Boolean ShapeAnalysis_Edge::ComputeDeviation (const Adaptor3d_Curve& CR
 //=======================================================================
 
 Standard_Boolean ShapeAnalysis_Edge::CheckSameParameter (const TopoDS_Edge& edge,
-                                                           Standard_Real& maxdev,
-                                                           const Standard_Integer NbControl)
+                                                         const TopoDS_Face& face,
+                                                         Standard_Real& maxdev,
+                                                         const Standard_Integer NbControl)
 {
   myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
   if (BRep_Tool::Degenerated (edge)) return Standard_False;
@@ -814,12 +828,27 @@ Standard_Boolean ShapeAnalysis_Edge::CheckSameParameter (const TopoDS_Edge& edge
     return Standard_False;
   }
 
+  Handle(Geom_Surface) aFaceSurf;
+  TopLoc_Location L;
+  if ( !face.IsNull() )
+  {
+    aFaceSurf = BRep_Tool::Surface(face, L);
+  }
+
   // iterate on pcurves
   itcr.Initialize ( TE->Curves() );
-  for ( ; itcr.More(); itcr.Next() ) {
+  for ( ; itcr.More(); itcr.Next() )
+  {
     Handle(BRep_GCurve) GC = Handle(BRep_GCurve)::DownCast(itcr.Value());
     if ( GC.IsNull() || ! GC->IsCurveOnSurface() ) continue;
 
+    if ( !(face.IsNull()) ) // Face is not null.
+    {
+      // Check for different surface.
+      if (!GC->IsCurveOnSurface(aFaceSurf, GC->Location()))
+        continue;
+    }
+
     Standard_Real f, l;
     GC->Range ( f, l );
     Handle(Geom_Surface) Su = GC->Surface();
@@ -833,15 +862,18 @@ Standard_Boolean ShapeAnalysis_Edge::CheckSameParameter (const TopoDS_Edge& edge
     //Adaptor3d_CurveOnSurface ACS(GHPC,GAHS);
     Adaptor3d_CurveOnSurface ACS;
     ACS.Load(GHPC, GAHS);
-    if ( ! ComputeDeviation ( AC3d, ACS, SameParameter, maxdev, NbControl-1 ) ) {
+    if ( ! ComputeDeviation ( AC3d, ACS, SameParameter, maxdev, NbControl-1 ) )
+    {
       myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
     }
 
-    if ( GC->IsCurveOnClosedSurface() ) {
+    if ( GC->IsCurveOnClosedSurface() )
+    {
       GHPC->ChangeCurve2d().Load ( GC->PCurve2(), f, l ); // same bounds
       ACS.Load(GHPC, GAHS); // sans doute inutile
-      if ( ! ComputeDeviation ( AC3d, ACS, SameParameter, maxdev, NbControl-1 ) ) {
-       myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
+      if ( ! ComputeDeviation ( AC3d, ACS, SameParameter, maxdev, NbControl-1 ) )
+      {
+        myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
       }
     }
   }
index 1c0b556..1022a0e 100644 (file)
@@ -157,6 +157,15 @@ public:
   //! If deviation is greater than tolerance of the edge (i.e.
   //! incorrect flag) returns False, else returns True.
   Standard_EXPORT Standard_Boolean CheckSameParameter (const TopoDS_Edge& edge, Standard_Real& maxdev, const Standard_Integer NbControl = 23);
+
+  //! Checks the edge to be SameParameter.
+  //! Calculates the maximal deviation between 3d curve and each
+  //! pcurve of the edge on <NbControl> equidistant points (the same
+  //! algorithm as in BRepCheck; default value is 23 as in BRepCheck).
+  //! This deviation is returned in <maxdev> parameter.
+  //! If deviation is greater than tolerance of the edge (i.e.
+  //! incorrect flag) returns False, else returns True.
+  Standard_EXPORT Standard_Boolean CheckSameParameter (const TopoDS_Edge& theEdge, const TopoDS_Face& theFace, Standard_Real& theMaxdev, const Standard_Integer theNbControl = 23);
   
   //! Computes the maximal deviation between the two curve
   //! representations.
index d4a3b8e..4a4c4c8 100644 (file)
@@ -93,6 +93,9 @@ Standard_Boolean ShapeFix::SameParameter(const TopoDS_Shape& shape,
   for ( TopExp_Explorer anEdgeExp(shape, TopAbs_FACE); anEdgeExp.More(); anEdgeExp.Next() )
     ++aNbFaces;
 
+  TopTools_IndexedDataMapOfShapeListOfShape aMapEF;
+  TopExp::MapShapesAndAncestors(shape, TopAbs_EDGE, TopAbs_FACE, aMapEF);
+
   BRep_Builder B;
   //Standard_Integer nbexcp = 0; 
   Standard_Integer nbfail = 0,  numedge = 0; 
@@ -129,7 +132,21 @@ Standard_Boolean ShapeFix::SameParameter(const TopoDS_Shape& shape,
           B.SameParameter (E,Standard_False);
         }
 
-        sfe->FixSameParameter (E); // K2-SEP97
+        TopTools_ListOfShape aListOfFaces;
+        aMapEF.FindFromKey(E, aListOfFaces);
+        if (aListOfFaces.Extent() != 0)
+        {
+          TopTools_ListOfShape::Iterator aListOfFacesIt(aListOfFaces);
+          for ( ; aListOfFacesIt.More() ; aListOfFacesIt.Next())
+          {
+            TopoDS_Face aF = TopoDS::Face( aListOfFacesIt.Value() );
+            sfe->FixSameParameter (E, aF);
+          }
+        }
+        else
+        {
+          sfe->FixSameParameter (E); // K2-SEP97
+        }
 
         if (!BRep_Tool::SameParameter (E)) { ierr = 1; nbfail ++; }
         
index 55f8071..2723c57 100644 (file)
@@ -576,7 +576,7 @@ Standard_Boolean ShapeFix_Edge::FixAddPCurve (const TopoDS_Edge& edge,
 //purpose  : 
 //=======================================================================
 
- Standard_Boolean ShapeFix_Edge::FixVertexTolerance(const TopoDS_Edge& edge,
+Standard_Boolean ShapeFix_Edge::FixVertexTolerance(const TopoDS_Edge& edge,
                                                    const TopoDS_Face& face)
 {
   myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
@@ -699,6 +699,17 @@ Standard_Boolean ShapeFix_Edge::FixReversed2d (const TopoDS_Edge& edge,
   return Standard_True;
 }
 
+//=======================================================================
+//function : FixSameParameter
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean ShapeFix_Edge::FixSameParameter(const TopoDS_Edge& edge,
+                                                 const Standard_Real tolerance) 
+{
+  TopoDS_Face anEmptyFace;
+  return FixSameParameter(edge, anEmptyFace, tolerance);
+}
 
 //=======================================================================
 //function : FixSameParameter
@@ -706,10 +717,11 @@ Standard_Boolean ShapeFix_Edge::FixReversed2d (const TopoDS_Edge& edge,
 //=======================================================================
 
 Standard_Boolean ShapeFix_Edge::FixSameParameter(const TopoDS_Edge& edge,
+                                                 const TopoDS_Face& face,
                                                  const Standard_Real tolerance) 
 {
   myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
-
+  
   if ( BRep_Tool::Degenerated ( edge ) )
   {
     BRep_Builder B;
@@ -726,10 +738,10 @@ Standard_Boolean ShapeFix_Edge::FixSameParameter(const TopoDS_Edge& edge,
   TopoDS_Edge copyedge;
   TopoDS_Vertex V1 = sae.FirstVertex (edge);
   TopoDS_Vertex V2 = sae.LastVertex  (edge);
-  Standard_Real TolFV = ( V1.IsNull() ? 0. : BRep_Tool::Tolerance ( V1 ) );
-  Standard_Real TolLV = ( V2.IsNull() ? 0. : BRep_Tool::Tolerance ( V2 ) );
+  Standard_Real TolFV = ( V1.IsNull() ? 0.0 : BRep_Tool::Tolerance ( V1 ) );
+  Standard_Real TolLV = ( V2.IsNull() ? 0.0 : BRep_Tool::Tolerance ( V2 ) );
   Standard_Real tol = BRep_Tool::Tolerance (edge);
-
+  
   Standard_Boolean wasSP = BRep_Tool::SameParameter ( edge ), SP = Standard_False;
   {
     try
@@ -764,14 +776,23 @@ Standard_Boolean ShapeFix_Edge::FixSameParameter(const TopoDS_Edge& edge,
       myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
     }
   }
-
+  
   // compute deviation on the original pcurves
   Standard_Real maxdev;
   B.SameParameter ( edge, Standard_True );
-  sae.CheckSameParameter ( edge, maxdev );
+
+  // Should check all pcurves in case of non-sameparametrization input.
+  TopoDS_Face aFace = face;
+  if (!wasSP)
+  {
+    TopoDS_Face anEmptyFace;
+    aFace = anEmptyFace;
+  }
+
+  sae.CheckSameParameter ( edge, aFace, maxdev );
   if ( sae.Status ( ShapeExtend_FAIL2 ) )
     myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
-
+  
   // if BRepLib was OK, compare and select the best variant
   if ( SP )
   {
@@ -779,7 +800,7 @@ Standard_Boolean ShapeFix_Edge::FixSameParameter(const TopoDS_Edge& edge,
     sae.CheckSameParameter ( copyedge, BRLDev );
     myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
     if ( BRLTol < BRLDev ) BRLTol = BRLDev;
-
+    
     //chose the best result
     if ( BRLTol < maxdev )
     {
@@ -796,7 +817,7 @@ Standard_Boolean ShapeFix_Edge::FixSameParameter(const TopoDS_Edge& edge,
   //restore tolerances because they could be modified by BRepLib
   if ( ! V1.IsNull() ) SFST.SetTolerance ( V1, Max (maxdev, TolFV), TopAbs_VERTEX);
   if ( ! V2.IsNull() ) SFST.SetTolerance ( V2, Max (maxdev, TolLV), TopAbs_VERTEX);
-
+  
   if ( maxdev > tol )
   { 
     myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
index d5c052a..ba1a759 100644 (file)
@@ -173,6 +173,43 @@ public:
   //! DONE5 - if the edge resulting from BRepLib has been chosen, i.e. variant b. above
   //! (only for edges with not set SameParameter)
   Standard_EXPORT Standard_Boolean FixSameParameter (const TopoDS_Edge& edge, const Standard_Real tolerance = 0.0);
+
+  //! Tries to make edge SameParameter and sets corresponding
+  //! tolerance and SameParameter flag.
+  //! First, it makes edge same range if SameRange flag is not set.
+  //!
+  //! If flag SameParameter is set, this method calls the
+  //! function ShapeAnalysis_Edge::CheckSameParameter() that
+  //! calculates the maximal deviation of pcurves of the edge from
+  //! its 3d curve. If deviation > tolerance, the tolerance of edge
+  //! is increased to a value of deviation. If deviation < tolerance
+  //! nothing happens.
+  //!
+  //! If flag SameParameter is not set, this method chooses the best
+  //! variant (one that has minimal tolerance), either
+  //! a. only after computing deviation (as above) or
+  //! b. after calling standard procedure BRepLib::SameParameter
+  //! and computing deviation (as above). If <tolerance> > 0, it is
+  //! used as parameter for BRepLib::SameParameter, otherwise,
+  //! tolerance of the edge is used.
+  //!
+  //! Use    : Is to be called after all pcurves and 3d curve of the edge are
+  //! correctly computed
+  //! Remark : SameParameter flag is always set to True after this method
+  //! Returns: True, if something done, else False
+  //! Status : OK    - edge was initially SameParameter, nothing is done
+  //! FAIL1 - computation of deviation of pcurves from 3d curve has failed
+  //! FAIL2 - BRepLib::SameParameter() has failed
+  //! DONE1 - tolerance of the edge was increased
+  //! DONE2 - flag SameParameter was set to True (only if
+  //! BRepLib::SameParameter() did not set it)
+  //! DONE3 - edge was modified by BRepLib::SameParameter() to SameParameter
+  //! DONE4 - not used anymore
+  //! DONE5 - if the edge resulting from BRepLib has been chosen, i.e. variant b. above
+  //! (only for edges with not set SameParameter)
+  Standard_EXPORT Standard_Boolean FixSameParameter (const TopoDS_Edge& edge,
+                                                     const TopoDS_Face& face,
+                                                     const Standard_Real tolerance = 0.0);
   
   //! Returns the status (in the form of True/False) of last Fix
   Standard_EXPORT Standard_Boolean Status (const ShapeExtend_Status status) const;
index b40cc52..dd47622 100644 (file)
@@ -842,7 +842,7 @@ Standard_Boolean ShapeFix_Face::FixAddNaturalBound()
     Handle(ShapeFix_Edge) sfe = myFixWire->FixEdgeTool();
     for (TopExp_Explorer Eed (myFace, TopAbs_EDGE); Eed.More(); Eed.Next()) {
       TopoDS_Edge edg = TopoDS::Edge (Eed.Current());
-      sfe->FixVertexTolerance(edg);
+      sfe->FixVertexTolerance(edg, myFace);
     }
 
 //    B.UpdateFace (myFace,myPrecision);
index 459bc81..cca527e 100644 (file)
@@ -257,11 +257,15 @@ Standard_Boolean ShapeFix_Shape::Perform(const Handle(Message_ProgressIndicator)
       // for case when vertex belong to the different faces it is necessary to check vertices tolerances
       //after all fixes.
       //This fix it should be performed for example for case when cutting edge was performed.
-
       Handle(ShapeFix_Edge) sfe = FixEdgeTool();
-      TopExp_Explorer anExpE (myResult, TopAbs_EDGE);
-      for ( ; anExpE.More(); anExpE.Next()) 
-        sfe->FixVertexTolerance( TopoDS::Edge (anExpE.Current()));
+      TopExp_Explorer anExpF (myResult, TopAbs_FACE);
+      for ( ; anExpF.More(); anExpF.Next()) 
+      {
+        TopoDS_Face aF = TopoDS::Face(anExpF.Current());
+        TopExp_Explorer anExpE (aF, TopAbs_EDGE);
+        for ( ; anExpE.More(); anExpE.Next()) 
+          sfe->FixVertexTolerance( TopoDS::Edge (anExpE.Current()), aF);
+      }
     }
   }
   myResult = Context()->Apply(myResult);
index af37d90..7ae6c98 100644 (file)
@@ -416,7 +416,7 @@ Standard_Boolean ShapeFix_Wire::Perform()
   // TEMPORARILY without special mode !!!
   Handle(ShapeExtend_WireData) sbwd = WireData();
   for (Standard_Integer iedge = 1; iedge <= sbwd->NbEdges(); iedge++)
-    if ( myFixEdge->FixVertexTolerance (sbwd->Edge (iedge)) ) 
+    if ( myFixEdge->FixVertexTolerance (sbwd->Edge (iedge), Face()) ) 
     {
       Fixed = Standard_True;
     }
@@ -800,7 +800,7 @@ Standard_Boolean ShapeFix_Wire::FixEdgeCurves()
           }
         }
       }
-      myFixEdge->FixSameParameter ( sbwd->Edge(i) );
+      myFixEdge->FixSameParameter ( sbwd->Edge(i), Face());
       if ( myFixEdge->Status ( ShapeExtend_DONE ) ) 
        myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE8 );
       if ( myFixEdge->Status ( ShapeExtend_FAIL ) ) 
@@ -814,7 +814,7 @@ Standard_Boolean ShapeFix_Wire::FixEdgeCurves()
   {
     for ( i=1; i <= nb; i++)
     {
-      myFixEdge->FixVertexTolerance (sbwd->Edge (i), face);
+      myFixEdge->FixVertexTolerance (sbwd->Edge (i), Face());
       if ( myFixEdge->Status ( ShapeExtend_DONE ) ) 
         myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE8 );
       if ( myFixEdge->Status ( ShapeExtend_FAIL ) ) 
@@ -1778,7 +1778,7 @@ static Standard_Boolean TryNewPCurve (const TopoDS_Edge &E, const TopoDS_Face &f
 // no call to BRepLib:  B.SameParameter ( edge, Standard_False );
 
   Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge;
-  sfe->FixSameParameter ( edge ); 
+  sfe->FixSameParameter ( edge, face ); 
   c2d = BRep_Tool::CurveOnSurface ( edge, face, first, last );
   tol = BRep_Tool::Tolerance ( edge );
   return Standard_True;
diff --git a/tests/bugs/heal/bug26620 b/tests/bugs/heal/bug26620
new file mode 100644 (file)
index 0000000..0c33f3d
--- /dev/null
@@ -0,0 +1,26 @@
+puts "REQUIRED ALL: Faulty shapes in variables faulty_1 to"
+
+puts "============"
+puts "OCC26620"
+puts "============"
+puts ""
+#######################################################################
+## Shape healing unreasonably downgrades tolerance of a face
+#######################################################################
+
+restore [locate_data_file bug26620_ff.brep] ff
+
+puts "\nBefore shape healing"
+checkshape ff
+tolerance ff
+
+fixshape r ff
+
+puts "\nAfter shape healing"
+checkshape r
+regexp {Tolerance +MAX=([-0-9.+eE]+)} [tolerance r] full MaxTol
+
+set expected_MaxTolerance 0.1
+set tol_abs_MaxTolerance 0.5
+set tol_rel_MaxTolerance 0.5
+checkreal "MaxTolerance" ${MaxTol} ${expected_MaxTolerance} ${tol_abs_MaxTolerance} ${tol_rel_MaxTolerance}