0030055: BRepOffset_MakeOffset throws "TopoDS_Vertex hasn't gp_Pnt" in intersection...
authorakaftasev <akaftasev@opencascade.com>
Mon, 6 Feb 2023 11:15:35 +0000 (14:15 +0300)
committerakaftasev <akaftasev@opencascade.com>
Mon, 6 Feb 2023 11:15:35 +0000 (14:15 +0300)
Diagnostic of mixed connectivity of faces along common edge is added.
If algorithm finds such pair of faces, it stops working with special error code.

16 files changed:
src/BRepOffset/BRepOffset_Analyse.cxx
src/BRepOffset/BRepOffset_Error.hxx
src/BRepOffset/BRepOffset_MakeOffset.cxx
src/BRepTest/BRepTest_FeatureCommands.cxx
src/ChFiDS/ChFiDS_TypeOfConcavity.hxx
tests/bugs/modalg_2/bug5805_3
tests/bugs/modalg_2/bug5805_4
tests/bugs/modalg_2/bug5805_5
tests/bugs/modalg_3/bug5805_6
tests/offset/bugs/bug26288
tests/offset/bugs/bug27913
tests/offset/bugs/bug30055 [new file with mode: 0644]
tests/offset/bugs/bug5806
tests/offset/shape/A2
tests/offset/shape/A3
tests/perf/modalg/bug26443_1

index facfbed..cd8e269 100644 (file)
@@ -41,6 +41,7 @@
 #include <TopoDS_Vertex.hxx>
 #include <TopTools_MapOfShape.hxx>
 #include <ChFi3d.hxx>
+#include <LocalAnalysis_SurfaceContinuity.hxx>
 
 static void CorrectOrientationOfTangent(gp_Vec& TangVec,
                                         const TopoDS_Vertex& aVertex,
@@ -50,6 +51,12 @@ static void CorrectOrientationOfTangent(gp_Vec& TangVec,
   if (aVertex.IsSame(Vlast))
     TangVec.Reverse();
 }
+
+static Standard_Boolean CheckMixedContinuity (const TopoDS_Edge&  theEdge,
+                                              const TopoDS_Face&  theFace1,
+                                              const TopoDS_Face&  theFace2,
+                                              const Standard_Real theAngTol);
+
 //=======================================================================
 //function : BRepOffset_Analyse
 //purpose  : 
@@ -105,15 +112,168 @@ static void EdgeAnalyse(const TopoDS_Edge&         E,
   }
   else
   {
-    if (ChFi3d::IsTangentFaces(E, F1, F2)) //weak condition
-      ConnectType = ChFiDS_Tangential;
+    Standard_Boolean isTwoSplines = (aSurfType1 == GeomAbs_BSplineSurface || aSurfType1 == GeomAbs_BezierSurface) &&
+                                    (aSurfType2 == GeomAbs_BSplineSurface || aSurfType2 == GeomAbs_BezierSurface);
+    Standard_Boolean isMixedConcavity = Standard_False;
+    if (isTwoSplines)
+    {
+      Standard_Real anAngTol = 0.1;
+      isMixedConcavity = CheckMixedContinuity(E, F1, F2, anAngTol);
+    }
+
+    if (!isMixedConcavity)
+    {
+      if (ChFi3d::IsTangentFaces(E, F1, F2)) //weak condition
+      {
+        ConnectType = ChFiDS_Tangential;
+      }
+      else
+      {
+        ConnectType = ChFi3d::DefineConnectType(E, F1, F2, SinTol, Standard_False);
+      }
+    }
     else
-      ConnectType = ChFi3d::DefineConnectType(E, F1, F2, SinTol, Standard_False);
+    {
+      ConnectType = ChFiDS_Mixed;
+    }
   }
    
   I.Type(ConnectType);
   LI.Append(I);
 }
+//=======================================================================
+//function : CheckMixedConcavity
+//purpose  : 
+//=======================================================================
+Standard_Boolean CheckMixedContinuity (const TopoDS_Edge&  theEdge,
+                                       const TopoDS_Face&  theFace1,
+                                       const TopoDS_Face&  theFace2,
+                                       const Standard_Real theAngTol)
+{
+  Standard_Boolean aMixedCont = Standard_False;
+  GeomAbs_Shape aCurrOrder = BRep_Tool::Continuity(theEdge, theFace1, theFace2);
+  if (aCurrOrder > GeomAbs_C0)
+  {
+    //Method BRep_Tool::Continuity(...) always returns minimal continuity between faces
+    //so, if aCurrOrder > C0 it means that faces are tangent along whole edge.
+    return aMixedCont;
+  }
+  //But we caqnnot trust result, if it is C0. because this value set by default.
+  Standard_Real TolC0 = Max(0.001, 1.5*BRep_Tool::Tolerance(theEdge));
+
+  Standard_Real aFirst;
+  Standard_Real aLast;
+
+  Handle(Geom2d_Curve) aC2d1, aC2d2;
+
+  if (!theFace1.IsSame(theFace2) &&
+    BRep_Tool::IsClosed(theEdge, theFace1) &&
+    BRep_Tool::IsClosed(theEdge, theFace2))
+  {
+    //Find the edge in the face 1: this edge will have correct orientation
+    TopoDS_Edge anEdgeInFace1;
+    TopoDS_Face aFace1 = theFace1;
+    aFace1.Orientation(TopAbs_FORWARD);
+    TopExp_Explorer anExplo(aFace1, TopAbs_EDGE);
+    for (; anExplo.More(); anExplo.Next())
+    {
+      const TopoDS_Edge& anEdge = TopoDS::Edge(anExplo.Current());
+      if (anEdge.IsSame(theEdge))
+      {
+        anEdgeInFace1 = anEdge;
+        break;
+      }
+    }
+    if (anEdgeInFace1.IsNull())
+    {
+      return aMixedCont;
+    }
+
+    aC2d1 = BRep_Tool::CurveOnSurface(anEdgeInFace1, aFace1, aFirst, aLast);
+    TopoDS_Face aFace2 = theFace2;
+    aFace2.Orientation(TopAbs_FORWARD);
+    anEdgeInFace1.Reverse();
+    aC2d2 = BRep_Tool::CurveOnSurface(anEdgeInFace1, aFace2, aFirst, aLast);
+  }
+  else
+  {
+    // Obtaining of pcurves of edge on two faces.
+    aC2d1 = BRep_Tool::CurveOnSurface(theEdge, theFace1, aFirst, aLast);
+    //For the case of seam edge
+    TopoDS_Edge EE = theEdge;
+    if (theFace1.IsSame(theFace2))
+    {
+      EE.Reverse();
+    }
+    aC2d2 = BRep_Tool::CurveOnSurface(EE, theFace2, aFirst, aLast);
+  }
+
+  if (aC2d1.IsNull() || aC2d2.IsNull())
+  {
+    return aMixedCont;
+  }
+
+  // Obtaining of two surfaces from adjacent faces.
+  Handle(Geom_Surface) aSurf1 = BRep_Tool::Surface(theFace1);
+  Handle(Geom_Surface) aSurf2 = BRep_Tool::Surface(theFace2);
+
+  if (aSurf1.IsNull() || aSurf2.IsNull())
+  {
+    return aMixedCont;
+  }
+
+  Standard_Integer aNbSamples = 23;
+
+  // Computation of the continuity.
+  Standard_Real    aPar;
+  Standard_Real    aDelta = (aLast - aFirst) / (aNbSamples - 1);
+  Standard_Integer i, istart = 1;
+  Standard_Boolean isG1 = Standard_False;
+
+  for (i = 1, aPar = aFirst; i <= aNbSamples; i++, aPar += aDelta) 
+  {
+    if (i == aNbSamples) aPar = aLast;
+
+    LocalAnalysis_SurfaceContinuity aCont(aC2d1, aC2d2, aPar,
+      aSurf1, aSurf2, GeomAbs_G1, 0.001, TolC0, theAngTol, theAngTol, theAngTol);
+    if (aCont.IsDone())
+    {
+      istart = i + 1;
+      isG1 = aCont.IsG1();
+      break;
+    }
+  }
+
+  if (istart > aNbSamples / 2)
+  {
+    return aMixedCont;
+  }
+
+  for (i = istart, aPar = aFirst; i <= aNbSamples; i++, aPar += aDelta) 
+  {
+    if (i == aNbSamples) aPar = aLast;
+
+    LocalAnalysis_SurfaceContinuity aCont(aC2d1, aC2d2, aPar,
+      aSurf1, aSurf2, GeomAbs_G1, 0.001, TolC0, theAngTol, theAngTol, theAngTol);
+    if (!aCont.IsDone())
+    {
+      continue;
+    }
+
+    if (aCont.IsG1() == isG1)
+    {
+      continue;
+    }
+    else
+    {
+       aMixedCont = Standard_True;
+       break;
+    }
+  }
+
+  return aMixedCont;
+
+}
 
 //=======================================================================
 //function : BuildAncestors
index e5dda91..517a8eb 100644 (file)
@@ -29,7 +29,8 @@ enum BRepOffset_Error
   BRepOffset_CannotTrimEdges,        //!< exception while trim edges
   BRepOffset_CannotFuseVertices,     //!< exception while fuse vertices
   BRepOffset_CannotExtentEdge,       //!< exception while extent edges
-  BRepOffset_UserBreak               //!< user break
+  BRepOffset_UserBreak,              //!< user break
+  BRepOffset_MixedConnectivity       //!< Different connectivity of faces along edge: partially C0 and tangent
 };
 
 #endif // _BRepOffset_Error_HeaderFile
index 5d4d00d..c499d74 100644 (file)
@@ -910,6 +910,19 @@ void BRepOffset_MakeOffset::MakeOffsetShape(const Message_ProgressRange& theRang
     myAnalyse.SetFaceOffsetMap (myFaceOffset);
   }
   myAnalyse.Perform(myFaceComp,TolAngle, aPS.Next(aSteps(PIOperation_Analyse)));
+  TopExp_Explorer anEExp(myFaceComp, TopAbs_EDGE);
+  for (; anEExp.More(); anEExp.Next())
+  {
+    const TopoDS_Edge& anE = TopoDS::Edge(anEExp.Current());
+    const BRepOffset_ListOfInterval& aLI = myAnalyse.Type(anE);
+    if (aLI.IsEmpty())
+      continue;
+    if (aLI.Last().Type() == ChFiDS_Mixed)
+    {
+      myError = BRepOffset_MixedConnectivity;
+      return;
+    }
+  }
   if (!aPS.More())
   {
     myError = BRepOffset_UserBreak;
@@ -2960,6 +2973,36 @@ void BRepOffset_MakeOffset::MakeMissingWalls (const Message_ProgressRange& theRa
       TopExp::Vertices(anEdge, V1, V2);
       Standard_Real aF, aL;
       const Handle(Geom_Curve) aC = BRep_Tool::Curve(anEdge, aF, aL);
+      if (V3.IsNull() && V4.IsNull())
+      {
+        // Initially offset edge is created without vertices.
+        // Then edge is trimmed by intersection line between  
+        // two adjacent extended offset faces and get vertices.
+        // When intersection lines are invalid for any reason, 
+        // (one of reson is mixed connectivity of faces)
+        // algoritm of cutting offset edge by intersection line 
+        // can fail and offset edge cannot get vertices.
+        // Follwing workaround is only to avoid exeption if V3 and V4 are Null
+        // Vertex points are invalid.
+        Standard_Real anOEF, anOEL;
+        TopAbs_Orientation anOEOri = OE.Orientation();
+        OE.Orientation(TopAbs_FORWARD);
+        Handle(Geom_Curve) anOEC = BRep_Tool::Curve(OE, anOEF, anOEL);
+        BRep_Builder aBB;
+        gp_Pnt aP1 = anOEC->Value(aF);
+        gp_Pnt aP2 = anOEC->Value(aL);
+        TopoDS_Vertex anOEV1, anOEV2;
+        Standard_Real aTol = Max(BRep_Tool::Tolerance(V1), BRep_Tool::Tolerance(V2));
+        aBB.MakeVertex(anOEV1, aP1, aTol);
+        anOEV1.Orientation(TopAbs_FORWARD);
+        aBB.MakeVertex(anOEV2, aP2, aTol);
+        anOEV2.Orientation(TopAbs_REVERSED);
+        aBB.Add(OE, anOEV1);
+        aBB.Add(OE, anOEV2);
+        aBB.Range(OE, aF, aL);
+        OE.Orientation(anOEOri);
+        TopExp::Vertices(OE, V4, V3);
+      }
       if (!aC.IsNull() &&
          (!aC->IsClosed() && !aC->IsPeriodic()))
       {
index 07eab33..102791e 100644 (file)
@@ -415,6 +415,11 @@ static void reportOffsetState(Draw_Interpretor& theCommands,
     theCommands << "ERROR. Can not extent edge.";
     break;
   }
+  case  BRepOffset_MixedConnectivity:
+  {
+    theCommands << "ERROR. Mixed connectivity of faces.";
+    break;
+  }
   default:
   {
     theCommands << "ERROR. offsetperform operation not done.";
@@ -974,7 +979,10 @@ Standard_Integer thickshell(Draw_Interpretor& theCommands,
   const BRepOffset_Error aRetCode = B.Error();
   reportOffsetState(theCommands, aRetCode);
 
-  DBRep::Set(a[1], B.Shape());
+  if (!B.Shape().IsNull())
+  {
+    DBRep::Set(a[1], B.Shape());
+  }
   return 0;
 }
 
@@ -1109,7 +1117,10 @@ Standard_Integer offsetshape(Draw_Interpretor& theCommands,
   const BRepOffset_Error aRetCode = B.Error();
   reportOffsetState(theCommands, aRetCode);
 
-  DBRep::Set(a[1], B.Shape());
+  if (!B.Shape().IsNull())
+  {
+    DBRep::Set(a[1], B.Shape());
+  }
 
   return 0;
 }
index 8c18553..e072a4b 100644 (file)
@@ -24,7 +24,8 @@ ChFiDS_Concave,
 ChFiDS_Convex,
 ChFiDS_Tangential,
 ChFiDS_FreeBound,
-ChFiDS_Other
+ChFiDS_Other,
+ChFiDS_Mixed
 };
 
 #endif // _ChFiDS_TypeOfConcavity_HeaderFile
index c45f552..5a613de 100755 (executable)
@@ -1,4 +1,4 @@
-puts "TODO OCC26556 ALL: ERROR. offsetperform operation not done."
+puts "TODO OCC26556 ALL: ERROR. Mixed connectivity of faces."
 
 puts "============"
 puts "OCC5805"
@@ -20,6 +20,7 @@ if { [catch { offsetshape result a -1 a_6 } catch_result] } {
    puts "Faulty ${BugNumber} : offsetshape is wrong"
 }
 
+if { [isdraw result] } {
 checkmaxtol result -min_tol 1.
 
 checkprops result -s 1185.03 
@@ -27,3 +28,4 @@ checkshape result
 
 checknbshapes result -vertex 10 -edge 15 -wire 7 -face 7 -shell 1 -solid 1 -compsolid 0 -compound 0 -shape 41
 checkview -display result -2d -path ${imagedir}/${test_image}.png
+}
index f883082..ae3b827 100755 (executable)
@@ -1,6 +1,4 @@
-puts "TODO OCC25925 ALL: ERROR. offsetperform operation not done."
-puts "TODO OCC25925 ALL: Tcl Exception:"
-puts "TODO OCC25925 ALL: TEST INCOMPLETE"
+puts "TODO OCC25925 ALL: ERROR. Mixed connectivity of faces."
 
 puts "============"
 puts "OCC5805"
@@ -25,6 +23,7 @@ if { [catch { offsetperform result } catch_result] } {
    puts "Faulty ${BugNumber} : offsetshape is wrong"
 }
 
+if { [isdraw result] } {
 checkmaxtol result -min_tol 1.
 
 checkprops result -s 1185.03 
@@ -32,3 +31,4 @@ checkshape result
 
 checknbshapes result -vertex 10 -edge 15 -wire 7 -face 7 -shell 1 -solid 1 -compsolid 0 -compound 0 -shape 41
 checkview -display result -2d -path ${imagedir}/${test_image}.png
+}
index db1e066..f72c337 100755 (executable)
@@ -1,3 +1,5 @@
+puts "TODO OCC25925 ALL: ERROR. Mixed connectivity of faces."
+
 puts "============"
 puts "OCC5805"
 puts "============"
@@ -21,6 +23,7 @@ if { [catch { offsetperform result } catch_result] } {
    puts "Faulty ${BugNumber} : offsetshape is wrong"
 }
 
+if { [isdraw result] } {
 checkmaxtol result -min_tol 1.
 
 checkprops result -s 876.584 
@@ -28,3 +31,5 @@ checkshape result
 
 checknbshapes result -vertex 10 -edge 15 -wire 7 -face 7 -shell 1 -solid 1 -compsolid 0 -compound 0 -shape 41
 checkview -display result -2d -path ${imagedir}/${test_image}.png
+}
\ No newline at end of file
index 544b538..79224e9 100755 (executable)
@@ -1,3 +1,5 @@
+puts "TODO OCC25925 ALL: ERROR. Mixed connectivity of faces."
+
 puts "============"
 puts "OCC5805"
 puts "============"
@@ -16,9 +18,12 @@ if { [catch { offsetshape result a -1 } catch_result] } {
    puts "Faulty ${BugNumber} : offsetshape is wrong"
 }
 
+if { [isdraw result] } {
 checkmaxtol result -min_tol 1.
 
 checkprops result -s 876.584
 checkshape result
 checknbshapes result -vertex 10 -edge 15 -wire 7 -face 7 -shell 1 -solid 1 -compsolid 0 -compound 0 -shape 41
 checkview -display result -2d -path ${imagedir}/${test_image}.png
+}
\ No newline at end of file
index 94cf6d3..f30e48c 100644 (file)
@@ -1,4 +1,5 @@
 puts "TODO OCC26030 ALL: Error : The offset cannot be built"
+puts "TODO OCC26030 ALL: ERROR. Mixed connectivity of faces."
 
 puts "========"
 puts "OCC26288"
index aca74b5..cf55817 100644 (file)
@@ -1,6 +1,5 @@
-puts "TODO OCC26577 All: Error :  is WRONG because number of EDGE entities in shape"
-puts "TODO OCC26577 All: Error :  is WRONG because number of SHELL entities in shape"
-
+puts "TODO OCC26577 All: ERROR. Mixed connectivity of faces."
+puts "TODO OCC26577 All: Error : The offset cannot be built."
 
 puts "=============================================================="
 puts "0027913: Sharing between edges was lost after offset operation"
@@ -12,9 +11,11 @@ offsetparameter 1e-7 p i
 offsetload s 10
 offsetperform result
 
-unifysamedom result_unif result
+if { [isdraw result] } {
+ unifysamedom result_unif result
 
-checkshape result
-checkview -display result_unif -2d -path ${imagedir}/${test_image}.png
+ checkshape result
+ checkview -display result_unif -2d -path ${imagedir}/${test_image}.png
 
-checknbshapes result -ref [lrange [nbshapes s] 8 19]
\ No newline at end of file
+ checknbshapes result -ref [lrange [nbshapes s] 8 19]
+}
diff --git a/tests/offset/bugs/bug30055 b/tests/offset/bugs/bug30055
new file mode 100644 (file)
index 0000000..ecba24c
--- /dev/null
@@ -0,0 +1,13 @@
+puts "REQUIRED All: ERROR. Mixed connectivity of faces."
+puts "REQUIRED All: Error : The offset cannot be built."
+puts "============"
+puts "0030055: BRepOffset_MakeOffset throws TopoDS_Vertex hasn't gp_Pnt in intersection mode"
+puts "============"
+
+restore [locate_data_file bug30055.brep] a
+
+thickshell result a 1 i
+
+if { [isdraw result] } {
+   puts "ERROR - result must not be buit"
+}
index 197a76f..f530ae2 100644 (file)
@@ -1,4 +1,6 @@
-puts "TODO OCC25925 ALL: ERROR. offsetperform operation not done."
+puts "TODO OCC25925 ALL: ERROR. Mixed connectivity of faces."
+puts "TODO OCC25925 ALL: Error : The offset cannot be built."
+
 puts "============"
 puts "OCC5806"
 puts "============"
@@ -28,11 +30,12 @@ explode resthru f
 if { [catch { offsetshape result resthru -0.5 resthru_6 resthru_7 } catch_result] } {
    puts "Faulty ${BugNumber} : offsetshape is wrong"
 }
+if { [isdraw result] } {
+  checkmaxtol result -min_tol 1.
 
-checkmaxtol result -min_tol 1.
-
-checkprops result -s 1116.06 
-checkshape result
+  checkprops result -s 1116.06 
+  checkshape result
 
-checknbshapes result -vertex 10 -edge 15 -wire 7 -face 7 -shell 1 -solid 1 -compsolid 0 -compound 0 -shape 41
-checkview -display result -2d -path ${imagedir}/${test_image}.png
+  checknbshapes result -vertex 10 -edge 15 -wire 7 -face 7 -shell 1 -solid 1 -compsolid 0 -  compound 0 -shape 41
+  checkview -display result -2d -path ${imagedir}/${test_image}.png
+}
index 383b150..2e37ae3 100644 (file)
@@ -1,7 +1,7 @@
 puts "TODO OCC23190 ALL: ERROR. C0 continuity of input data."
 puts "TODO OCC23190 ALL: Error: The command cannot be built"
-puts "TODO OCC23190 ALL: result is not a topological shape!!!"
-puts "TODO OCC23068 ALL: TEST INCOMPLETE"
+puts "TODO OCC23068 ALL: Error : The offset cannot be built."
+
 # Original bug : hkg60144/pro15325
 # Date : 17Juillet98
 
index 45d232d..4203f0a 100644 (file)
@@ -1,7 +1,7 @@
 puts "TODO OCC23190 ALL: ERROR. C0 continuity of input data."
 puts "TODO OCC23190 ALL: Error: The command cannot be built"
-puts "TODO OCC23190 ALL: result is not a topological shape!!!"
-puts "TODO OCC23068 ALL: TEST INCOMPLETE"
+puts "TODO OCC23068 ALL: Error : The offset cannot be built."
+
 # Original bug : cts21271
 # Date : 11Sept98
 
index 66b34a3..dae8547 100644 (file)
@@ -1,3 +1,5 @@
+puts "TODO OCC25925 ALL: ERROR. Mixed connectivity of faces."
+
 puts "========"
 puts "OCC26443"
 puts "========"
@@ -15,6 +17,8 @@ offsetshape r a -2
 dchrono h stop counter offsetshape
 fit
 
+if { [isdraw r] } {
 checkshape r
 checknbshapes r -ref [lrange [nbshapes a] 8 19]
 checkview -screenshot -2d -path ${imagedir}/${test_image}.png
+}