0029234: BRepOffsetAPI_NormalProjection produces INTERNAL edges and vertices
authormsv <msv@opencascade.com>
Fri, 20 Oct 2017 15:59:01 +0000 (18:59 +0300)
committermsv <msv@opencascade.com>
Tue, 14 Nov 2017 13:52:41 +0000 (16:52 +0300)
Make the algorithm BRepOffsetAPI_NormalProjection use section operation instead of common to get the edge-result of projection to be in face restrictions.

Correct Boolean operation algorithm to produce correctly oriented result in the case of common between face and edge.

The algorithm ShapeUpgrade_UnifySameDomain has been patched to correctly gather same domain faces in a compound.

The TCL script snowflake.tcl has been corrected to get rid of dependence on the order of edges in the result of Boolean operation.

samples/tcl/snowflake.tcl
src/BOPAlgo/BOPAlgo_BOP.cxx
src/BOPAlgo/BOPAlgo_Builder_3.cxx
src/BOPAlgo/BOPAlgo_MakerVolume.cxx
src/BOPAlgo/BOPAlgo_Tools.cxx
src/BOPAlgo/BOPAlgo_Tools.hxx
src/BRepAlgo/BRepAlgo_NormalProjection.cxx
src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.cxx
src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.hxx
tests/bugs/modalg_7/bug29234 [new file with mode: 0644]

index 06eb89f..47dbe29 100644 (file)
@@ -59,12 +59,10 @@ prism f4 l2 0 -1 0
 compound f1 f2 f3 bc
 bfuse r bc f4
 bcut r r f5
-explode r e
-wire w r_4 r_1 r_20 r_21 r_22 r_23 r_24 r_25 r_26 r_7 r_30 r_31 r_32 r_33 r_27 r_28 r_29 r_11 r_38 r_34 r_35 r_36 r_37 r_16 r_17
-tcopy w w1
-tmirror w1 -6 0 0 0 1 0
-wire w w w1
-mkface w p w
+tcopy r r1
+tmirror r1 -6 0 0 0 1 0
+bfuse w r r1
+unifysamedom w w
 donly w
 
 # construct complete snowflake
index 1182d3c..4ae1cb0 100644 (file)
@@ -16,6 +16,7 @@
 #include <BOPAlgo_BOP.hxx>
 #include <BOPAlgo_BuilderSolid.hxx>
 #include <BOPAlgo_PaveFiller.hxx>
+#include <BOPAlgo_Tools.hxx>
 #include <BOPAlgo_Alerts.hxx>
 #include <BOPCol_DataMapOfShapeShape.hxx>
 #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
@@ -777,9 +778,11 @@ void BOPAlgo_BOP::BuildShape()
   }
   // make containers
   BOPCol_ListOfShape aLCRes;
+  BOPCol_MapOfShape aMInpFence;
   aItLS.Initialize(aLSC);
   for (; aItLS.More(); aItLS.Next()) {
     const TopoDS_Shape& aSC = aItLS.Value();
+    aMInpFence.Add(aSC);
     //
     BOPTools_AlgoTools::MakeContainer(TopAbs_COMPOUND, aRC);
     //
@@ -861,19 +864,44 @@ void BOPAlgo_BOP::BuildShape()
   for (; aItLS.More(); aItLS.Next()) {
     aBB.Add(aResult, aItLS.Value());
   }
-  //
-  // add the rest of the shapes into result
+
+  // create map of containers
   BOPCol_MapOfShape aMSResult;
   BOPTools::MapShapes(aResult, aMSResult);
-  //
-  aIt.Initialize(myRC);
-  for (; aIt.More(); aIt.Next()) {
-    const TopoDS_Shape& aS = aIt.Value();
-    if (aMSResult.Add(aS)) {
-      aBB.Add(aResult, aS);
+
+  // get input non-container shapes
+  BOPCol_ListOfShape aLSNonCont;
+  for (i = 0; i < 2; ++i)
+  {
+    const BOPCol_ListOfShape& aLS = !i ? myArguments : myTools;
+    aItLS.Initialize(aLS);
+    for (; aItLS.More(); aItLS.Next())
+    {
+      const TopoDS_Shape& aS = aItLS.Value();
+      BOPAlgo_Tools::TreatCompound(aS, aMInpFence, aLSNonCont);
     }
   }
-  //
+
+  // put non-container shapes in the result
+  aItLS.Initialize(aLSNonCont);
+  for (; aItLS.More(); aItLS.Next())
+  {
+    const TopoDS_Shape& aS = aItLS.Value();
+    if (myImages.IsBound(aS))
+    {
+      const BOPCol_ListOfShape& aLSIm = myImages.Find(aS);
+      aItLSIm.Initialize(aLSIm);
+      for (; aItLSIm.More(); aItLSIm.Next())
+      {
+        const TopoDS_Shape& aSIm = aItLSIm.Value();
+        if (aMSRC.Contains(aSIm) && aMSResult.Add(aSIm))
+          aBB.Add(aResult, aSIm);
+      }
+    }
+    else if (aMSRC.Contains(aS) && aMSResult.Add(aS))
+      aBB.Add(aResult, aS);
+  }
+
   myShape = aResult;
 }
 //=======================================================================
index 31ff3a3..a5035bd 100644 (file)
@@ -64,6 +64,7 @@
 #include <BOPTools_Set.hxx>
 //
 #include <BOPAlgo_BuilderSolid.hxx>
+#include <BOPAlgo_Tools.hxx>
 #include <NCollection_Array1.hxx>
 #include <NCollection_IncAllocator.hxx>
 
@@ -74,11 +75,6 @@ static
   void OwnInternalShapes(const TopoDS_Shape& ,
                          BOPCol_IndexedMapOfShape& );
 
-static
-  void TreatCompound(const TopoDS_Shape& theS,
-                     BOPCol_MapOfShape& aMFence,
-                     BOPCol_ListOfShape& theLS);
-
 //=======================================================================
 // BOPAlgo_BuilderSolid
 //
@@ -941,7 +937,7 @@ void BOPAlgo_Builder::FillInternalShapes()
   aIt.Initialize(aArguments);
   for (; aIt.More(); aIt.Next()) {
     const TopoDS_Shape& aS=aIt.Value();
-    TreatCompound(aS, aMFence, aLSC);
+    BOPAlgo_Tools::TreatCompound(aS, aMFence, aLSC);
   }
   aIt.Initialize(aLSC);
   for (; aIt.More(); aIt.Next()) {
@@ -1146,29 +1142,3 @@ void OwnInternalShapes(const TopoDS_Shape& theS,
     }
   }
 }
-//=======================================================================
-//function : TreatCompound
-//purpose  : 
-//=======================================================================
-void TreatCompound(const TopoDS_Shape& theS,
-                   BOPCol_MapOfShape& aMFence,
-                   BOPCol_ListOfShape& theLS)
-{
-  TopAbs_ShapeEnum aType;
-  //
-  aType = theS.ShapeType();
-  if (aType != TopAbs_COMPOUND) {
-    if (aMFence.Add(theS)) {
-      theLS.Append(theS);
-    }
-    return;
-  }
-  //
-  TopoDS_Iterator aIt;
-  //
-  aIt.Initialize(theS);
-  for (; aIt.More(); aIt.Next()) {
-    const TopoDS_Shape& aS = aIt.Value();
-    TreatCompound(aS, aMFence, theLS);
-  }
-}
index 695118a..2a7afbc 100644 (file)
@@ -16,6 +16,7 @@
 #include <BOPAlgo_BuilderSolid.hxx>
 #include <BOPAlgo_MakerVolume.hxx>
 #include <BOPAlgo_PaveFiller.hxx>
+#include <BOPAlgo_Tools.hxx>
 #include <BOPAlgo_Alerts.hxx>
 #include <BOPCol_DataMapOfShapeListOfShape.hxx>
 #include <BOPCol_ListOfShape.hxx>
 static
   void AddFace(const TopoDS_Shape& theF,
                BOPCol_ListOfShape& theLF);
-static
-  void TreatCompound(const TopoDS_Shape& theS,
-                     BOPCol_MapOfShape& aMFence,
-                     BOPCol_ListOfShape& theLS);
 
 //=======================================================================
 //function : CheckData
@@ -352,7 +349,7 @@ void BOPAlgo_MakerVolume::FillInternalShapes(const BOPCol_ListOfShape& theLSR)
   aIt.Initialize(anArguments);
   for (; aIt.More(); aIt.Next()) {
     const TopoDS_Shape& aS = aIt.Value();
-    TreatCompound(aS, aMFence, aLSC);
+    BOPAlgo_Tools::TreatCompound(aS, aMFence, aLSC);
   }
   //
   aIt.Initialize(aLSC);
@@ -440,26 +437,3 @@ void AddFace(const TopoDS_Shape& theF,
   aFF.Orientation(TopAbs_REVERSED);
   theLF.Append(aFF);
 }
-
-//=======================================================================
-//function : TreatCompound
-//purpose  : 
-//=======================================================================
-void TreatCompound(const TopoDS_Shape& theS,
-                   BOPCol_MapOfShape& aMFence,
-                   BOPCol_ListOfShape& theLS)
-{
-  TopAbs_ShapeEnum aType = theS.ShapeType();
-  if (aType != TopAbs_COMPOUND) {
-    if (aMFence.Add(theS)) {
-      theLS.Append(theS);
-    }
-    return;
-  }
-  //
-  TopoDS_Iterator aIt(theS);
-  for (; aIt.More(); aIt.Next()) {
-    const TopoDS_Shape& aS = aIt.Value();
-    TreatCompound(aS, aMFence, theLS);
-  }
-}
index 4a4484a..59490a7 100644 (file)
@@ -1089,3 +1089,26 @@ void BOPAlgo_Tools::IntersectVertices(const BOPCol_IndexedDataMapOfShapeReal& th
     }
   }
 }
+
+//=======================================================================
+//function : TreatCompound
+//purpose  : 
+//=======================================================================
+void BOPAlgo_Tools::TreatCompound(const TopoDS_Shape& theS,
+                                  BOPCol_MapOfShape& aMFence,
+                                  BOPCol_ListOfShape& theLS)
+{
+  TopAbs_ShapeEnum aType = theS.ShapeType();
+  if (aType != TopAbs_COMPOUND)
+  {
+    if (aMFence.Add(theS))
+      theLS.Append(theS);
+    return;
+  }
+  TopoDS_Iterator aIt(theS);
+  for (; aIt.More(); aIt.Next())
+  {
+    const TopoDS_Shape& aS = aIt.Value();
+    TreatCompound(aS, aMFence, theLS);
+  }
+}
index a43ab1f..36a8a79 100644 (file)
@@ -23,6 +23,8 @@
 #include <BOPDS_IndexedDataMapOfPaveBlockListOfInteger.hxx>
 #include <BOPCol_IndexedDataMapOfShapeReal.hxx>
 #include <BOPCol_ListOfListOfShape.hxx>
+#include <BOPCol_MapOfShape.hxx>
+#include <BOPCol_ListOfShape.hxx>
 #include <BOPDS_IndexedDataMapOfPaveBlockListOfPaveBlock.hxx>
 #include <BOPDS_PDS.hxx>
 #include <Standard_Integer.hxx>
@@ -155,6 +157,12 @@ public:
                                                 const Standard_Real theFuzzyValue,
                                                 BOPCol_ListOfListOfShape& theChains);
 
+  //! Collect in the output list recursively all non-compound subshapes of the first level
+  //! of the given shape theS. If a shape presents in the map theMFence it is skipped.
+  //! All shapes put in the output are also added into theMFence.
+  Standard_EXPORT static void TreatCompound(const TopoDS_Shape& theS,
+                                            BOPCol_MapOfShape& theMFence,
+                                            BOPCol_ListOfShape& theLS);
 };
 
 #endif // _BOPAlgo_Tools_HeaderFile
index 768ff46..319f0da 100644 (file)
@@ -24,7 +24,7 @@
 #include <BRepAdaptor_Surface.hxx>
 #include <BRepAlgo_NormalProjection.hxx>
 #include <BRepAlgo_SequenceOfSequenceOfInteger.hxx>
-#include <BRepAlgoAPI_Common.hxx>
+#include <BRepAlgoAPI_Section.hxx>
 #include <BRepLib_MakeEdge.hxx>
 #include <BRepLib_MakeVertex.hxx>
 #include <BRepLib_MakeWire.hxx>
@@ -481,9 +481,9 @@ void BRepAlgo_NormalProjection::SetDefaultParams()
             if (!Degenerated) {
               // Perform Boolean COMMON operation to get parts of projected edge
               // inside the face
-              BRepAlgoAPI_Common aCommon(Faces->Value(j), prj);
-              if (aCommon.IsDone()) {
-                const TopoDS_Shape& aRC = aCommon.Shape();
+              BRepAlgoAPI_Section aSection(Faces->Value(j), prj);
+              if (aSection.IsDone()) {
+                const TopoDS_Shape& aRC = aSection.Shape();
                 //
                 TopExp_Explorer aExpE(aRC, TopAbs_EDGE);
                 for (; aExpE.More(); aExpE.Next()) {
index 0ce6b76..5c2960f 100644 (file)
@@ -125,41 +125,6 @@ static Standard_Boolean IsLikeSeam(const TopoDS_Edge& anEdge,
   return Standard_False;
 }
 
-static Standard_Boolean CheckSharedEdgeOri(const TopoDS_Face& theF1,
-                                           const TopoDS_Face& theF2,
-                                           const TopoDS_Edge& theE)
-{
-  TopAbs_Orientation anEOri = theE.Orientation();
-  if (anEOri == TopAbs_EXTERNAL || anEOri == TopAbs_INTERNAL)
-    return Standard_False;
-
-  TopExp_Explorer Exp(theF1, TopAbs_EDGE);
-  for (;Exp.More();Exp.Next())
-  {
-    const TopoDS_Shape& aCE = Exp.Current();
-    if (aCE.IsSame(theE))
-    {
-      anEOri = aCE.Orientation(); 
-      break;
-    }
-  }
-
-  for (Exp.Init(theF2, TopAbs_EDGE);Exp.More();Exp.Next())
-  {
-    const TopoDS_Shape& aCE = Exp.Current();
-    if (aCE.IsSame(theE))
-    {
-      if (aCE.Orientation() == TopAbs::Reverse(anEOri))
-        return Standard_True;
-      else
-        return Standard_False;
-    }
-  }
-
-  return Standard_False;
-
-}
-
 //=======================================================================
 //function : AddOrdinaryEdges
 //purpose  : auxilary
@@ -1234,7 +1199,7 @@ void ShapeUpgrade_UnifySameDomain::UnifyFaces()
   // unify faces in each shell separately
   TopExp_Explorer exps;
   for (exps.Init(myShape, TopAbs_SHELL); exps.More(); exps.Next())
-    IntUnifyFaces(exps.Current(), aGMapEdgeFaces, Standard_False);
+    IntUnifyFaces(exps.Current(), aGMapEdgeFaces);
 
   // gather all faces out of shells in one compound and unify them at once
   BRep_Builder aBB;
@@ -1245,7 +1210,7 @@ void ShapeUpgrade_UnifySameDomain::UnifyFaces()
     aBB.Add(aCmp, exps.Current());
 
   if (nbf > 0)
-    IntUnifyFaces(aCmp, aGMapEdgeFaces, Standard_True);
+    IntUnifyFaces(aCmp, aGMapEdgeFaces);
   
   myShape = myContext->Apply(myShape);
 }
@@ -1274,8 +1239,7 @@ static void SetFixWireModes(ShapeFix_Face& theSff)
 //=======================================================================
 
 void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape,
-   TopTools_IndexedDataMapOfShapeListOfShape& theGMapEdgeFaces,
-   Standard_Boolean IsCheckSharedEdgeOri)
+   TopTools_IndexedDataMapOfShapeListOfShape& theGMapEdgeFaces)
 {
   // creating map of edge faces for the shape
   TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
@@ -1356,9 +1320,6 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
         if (aProcessed.Contains(anCheckedFace))
           continue;
 
-        if (IsCheckSharedEdgeOri && !CheckSharedEdgeOri(aFace, anCheckedFace, edge) )
-          continue;
-
         if (bCheckNormals) {
           // get normal of checked face using the same parameter on edge
           gp_Dir aDN2;
index 13f8c95..ea2db40 100644 (file)
@@ -133,8 +133,7 @@ protected:
   Standard_EXPORT void UnifyEdges();
 
   void IntUnifyFaces(const TopoDS_Shape& theInpShape,
-                     TopTools_IndexedDataMapOfShapeListOfShape& theGMapEdgeFaces,
-                     Standard_Boolean IsCheckSharedEdgeOri);
+                     TopTools_IndexedDataMapOfShapeListOfShape& theGMapEdgeFaces);
 
   //! Fills the history of the modifications during the operation.
   Standard_EXPORT void FillHistory();
diff --git a/tests/bugs/modalg_7/bug29234 b/tests/bugs/modalg_7/bug29234
new file mode 100644 (file)
index 0000000..00870d3
--- /dev/null
@@ -0,0 +1,31 @@
+puts "========"
+puts "OCC29234"
+puts "========"
+puts ""
+#################################################
+# BRepOffsetAPI_NormalProjection produces INTERNAL edges and vertices
+#################################################
+
+restore [locate_data_file bug29234_cyl_n_wire.brep] a
+explode a
+renamevar a_1 f
+renamevar a_2 w
+nproject r w f
+foreach e [explode r e] {
+  if [regexp "INTERNAL" [dtyp $e]] {
+    puts "Error: projection result contains edges oriented INTERNAL"
+    break
+  }
+} 
+don r
+fit
+checknbshapes r -m "projection result" -edge 4
+checkview -display r -2d -path ${imagedir}/${test_image}_1.png
+
+bcommon r1 f r
+foreach e [explode r1 e] {
+  if [regexp "INTERNAL" [dtyp $e]] {
+    puts "Error: result of common between face and edge contains edges oriented INTERNAL"
+    break
+  }
+}