0028245: Result of Cells Builder algorithm becomes invalid after removal of internal...
authorimn <imn@opencascade.com>
Wed, 12 Jul 2017 07:52:41 +0000 (10:52 +0300)
committerbugmaster <bugmaster@opencascade.com>
Fri, 6 Oct 2017 07:28:23 +0000 (10:28 +0300)
When removing internal boundaries between faces of the same material do it once for the whole shape, and at this keep boundaries between areas with different material.

src/BOPAlgo/BOPAlgo_CellsBuilder.cxx
src/BOPAlgo/BOPAlgo_CellsBuilder.hxx
tests/boolean/cells_test/D5
tests/boolean/cells_test/K1 [new file with mode: 0644]

index ffc95d7..2692d7c 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <BRep_Builder.hxx>
 
+#include <TopExp.hxx>
 #include <TopExp_Explorer.hxx>
 
 #include <BOPTools.hxx>
@@ -39,6 +40,9 @@ static
   void MakeTypedContainers(const TopoDS_Shape& theSC,
                            TopoDS_Shape& theResult);
 
+static void CollectMaterialBoundaries(const BOPCol_ListOfShape& theLS,
+                                      TopTools_MapOfShape& theMapKeepBnd);
+
 //=======================================================================
 //function : empty constructor
 //purpose  : 
@@ -267,7 +271,8 @@ void BOPAlgo_CellsBuilder::AddToResult(const BOPCol_ListOfShape& theLSToTake,
   BOPCol_ListIteratorOfListOfShape aItLP(aParts);
   for (; aItLP.More(); aItLP.Next()) {
     const TopoDS_Shape& aPart = aItLP.Value();
-    if (aResParts.Add(aPart)) {
+    // provide uniqueness of the parts 
+    if (aResParts.Add(aPart) && !myShapeMaterial.IsBound(aPart)) {
       BRep_Builder().Add(myShape, aPart);
       bChanged = Standard_True;
     }
@@ -459,6 +464,8 @@ void BOPAlgo_CellsBuilder::RemoveInternalBoundaries()
   // try to remove the internal boundaries between the
   // shapes of the same material
   BOPCol_DataMapIteratorOfDataMapOfIntegerListOfShape aItM(myMaterials);
+  BOPCol_ListOfShape aLSUnify[2];
+  TopTools_MapOfShape aKeepMap[2];
   for (; aItM.More(); aItM.Next()) {
     Standard_Integer iMaterial = aItM.Key();
     BOPCol_ListOfShape& aLS = aItM.ChangeValue();
@@ -485,34 +492,65 @@ void BOPAlgo_CellsBuilder::RemoveInternalBoundaries()
         break;
       }
     }
-    //
-    BOPCol_ListOfShape aLSNew;
-    if (aItLS.More()) {
+
+    if (aItLS.More())
+    {
       // add the warning
+      TopoDS_Compound aMultiDimS;
+      aBB.MakeCompound(aMultiDimS);
+      aBB.Add(aMultiDimS, aLS.First());
+      aBB.Add(aMultiDimS, aItLS.Value());
+      AddWarning(new BOPAlgo_AlertRemovalOfIBForMDimShapes(aMultiDimS));
+    }
+    else
+    {
+      if (aType == TopAbs_EDGE || aType == TopAbs_FACE)
       {
-        TopoDS_Compound aMultiDimS;
-        aBB.MakeCompound(aMultiDimS);
-        aBB.Add(aMultiDimS, aLS.First());
-        aBB.Add(aMultiDimS, aItLS.Value());
-        //
-        AddWarning (new BOPAlgo_AlertRemovalOfIBForMDimShapes (aMultiDimS));
+        // for edges and faces, just collect shapes to unify them later after exiting the loop;
+        // collect boundaries of shapes of current material in the keep map
+        Standard_Integer iType = (aType == TopAbs_EDGE ? 0 : 1);
+        CollectMaterialBoundaries(aLS, aKeepMap[iType]);
+        // save shapes to unify later
+        BOPCol_ListOfShape aCopy(aLS);
+        aLSUnify[iType].Append(aCopy);
+        continue;
       }
-      aLSNew.Assign(aLS);
-    }
-    else {
-      if (RemoveInternals(aLS, aLSNew)) {
-        bChanged = Standard_True;
+      else
+      {
+        // aType is Solid;
+        // remove internal faces between solids of the same material just now
+        BOPCol_ListOfShape aLSNew;
+        if (RemoveInternals(aLS, aLSNew))
+        {
+          bChanged = Standard_True;
+          // update materials maps
+          for (aItLS.Initialize(aLSNew); aItLS.More(); aItLS.Next()) {
+            const TopoDS_Shape& aS = aItLS.Value();
+            myShapeMaterial.Bind(aS, iMaterial);
+          }
+          aLS.Assign(aLSNew);
+        }
       }
     }
-    //
-    // update materials maps and add new shapes to result
-    aItLS.Initialize(aLSNew);
-    for (; aItLS.More(); aItLS.Next()) {
+    // add shapes to result (multidimensional and solids)
+    for (aItLS.Initialize(aLS); aItLS.More(); aItLS.Next()) {
+      const TopoDS_Shape& aS = aItLS.Value();
+      aBB.Add(aResult, aS);
+    }
+  }
+
+  // remove internal boundaries for edges and faces
+  for (Standard_Integer iType = 0; iType < 2; ++iType)
+  {
+    if (aLSUnify[iType].IsEmpty())
+      continue;
+    BOPCol_ListOfShape aLSN;
+    if (RemoveInternals(aLSUnify[iType], aLSN, aKeepMap[iType]))
+      bChanged = Standard_True;
+    // add shapes to result ([unified] edges or faces)
+    for (BOPCol_ListIteratorOfListOfShape aItLS(aLSN); aItLS.More(); aItLS.Next()) {
       const TopoDS_Shape& aS = aItLS.Value();
       aBB.Add(aResult, aS);
-      if (!myShapeMaterial.IsBound(aS)) {
-        myShapeMaterial.Bind(aS, iMaterial);
-      }
     }
   }
   //
@@ -720,7 +758,8 @@ void BOPAlgo_CellsBuilder::MakeContainers()
 //purpose  : 
 //=======================================================================
 Standard_Boolean BOPAlgo_CellsBuilder::RemoveInternals(const BOPCol_ListOfShape& theLS,
-                                                       BOPCol_ListOfShape& theLSNew)
+                                                       BOPCol_ListOfShape& theLSNew,
+                                                       const TopTools_MapOfShape& theMapKeepBnd)
 {
   Standard_Boolean bRemoved = Standard_False;
   if (theLS.Extent() < 2) {
@@ -750,8 +789,8 @@ Standard_Boolean BOPAlgo_CellsBuilder::RemoveInternals(const BOPCol_ListOfShape&
     //
     bFaces = (aType == TopAbs_FACE);
     bEdges = (aType == TopAbs_EDGE);
-    //
     ShapeUpgrade_UnifySameDomain anUnify (aShape, bEdges, bFaces);
+    anUnify.KeepShapes(theMapKeepBnd);
     anUnify.Build();
     const TopoDS_Shape& aSNew = anUnify.Shape();
     //
@@ -783,14 +822,15 @@ Standard_Boolean BOPAlgo_CellsBuilder::RemoveInternals(const BOPCol_ListOfShape&
     aNb = aMG.Extent();
     for (i = 1; i <= aNb; ++i) {
       const TopoDS_Shape& aSS = aMG(i);
+      const Standard_Integer* pMaterial = myShapeMaterial.Seek(aSS);
       const TopTools_ListOfShape& aLSMod = anUnify.History()->Modified(aSS);
       TopTools_ListIteratorOfListOfShape aIt(aLSMod);
       for (; aIt.More(); aIt.Next()) {
         const TopoDS_Shape& aSU = aIt.Value();
-        if (!aSU.IsNull() && !aSS.IsSame(aSU)) {
-          myMapModified.Bind(aSS, aSU);
-          bRemoved = Standard_True;
-        }
+        myMapModified.Bind(aSS, aSU);
+        bRemoved = Standard_True;
+        if (pMaterial && !myShapeMaterial.IsBound(aSU))
+          myShapeMaterial.Bind(aSU, *pMaterial);
       }
     }
   }
@@ -1074,6 +1114,33 @@ void MakeTypedContainers(const TopoDS_Shape& theSC,
 }
 
 //=======================================================================
+//function : CollectMaterialBoundaries
+//purpose  : Add to theMapKeepBnd the boundary shapes of the area defined by shapes from the list
+//=======================================================================
+static void CollectMaterialBoundaries(const BOPCol_ListOfShape& theLS,
+                                      TopTools_MapOfShape& theMapKeepBnd)
+{
+  TopAbs_ShapeEnum aType = theLS.First().ShapeType();
+  TopAbs_ShapeEnum aTypeSubsh = (aType == TopAbs_FACE ? TopAbs_EDGE : TopAbs_VERTEX);
+  TopTools_IndexedDataMapOfShapeListOfShape aMapSubSh;
+  BOPCol_ListIteratorOfListOfShape anIt(theLS);
+  for (; anIt.More(); anIt.Next())
+  {
+    const TopoDS_Shape& aS = anIt.Value();
+    TopExp::MapShapesAndAncestors(aS, aTypeSubsh, aType, aMapSubSh);
+  }
+  for (int i = 1; i <= aMapSubSh.Extent(); i++)
+  {
+    // check if the subshape belongs to boundary of the area
+    if (aMapSubSh(i).Extent() == 1)
+    {
+      // add to theMapKeepBnd
+      theMapKeepBnd.Add(aMapSubSh.FindKey(i));
+    }
+  }
+}
+
+//=======================================================================
 //function : TypeToExplore
 //purpose  : 
 //=======================================================================
index 8cfff60..316d6d9 100644 (file)
@@ -23,7 +23,7 @@
 #include <TopoDS_Shape.hxx>
 
 #include <TopAbs_ShapeEnum.hxx>
-
+#include <TopTools_MapOfShape.hxx>
 #include <BOPAlgo_Builder.hxx>
 
 #include <BOPCol_ListOfShape.hxx>
@@ -265,7 +265,8 @@ class BOPAlgo_CellsBuilder : public BOPAlgo_Builder
   //! Removes internal boundaries between cells with the same material.<br>
   //! Returns TRUE if any internal boundaries have been removed.
   Standard_EXPORT Standard_Boolean RemoveInternals(const BOPCol_ListOfShape& theLS,
-                                                   BOPCol_ListOfShape& theLSNew);
+                                                   BOPCol_ListOfShape& theLSNew,
+                                                   const TopTools_MapOfShape& theMapKeepBnd = TopTools_MapOfShape());
 
   // fields
   TopoDS_Shape myAllParts;
@@ -273,9 +274,6 @@ class BOPAlgo_CellsBuilder : public BOPAlgo_Builder
   BOPCol_DataMapOfIntegerListOfShape myMaterials;
   BOPCol_DataMapOfShapeInteger myShapeMaterial;
   BOPCol_DataMapOfShapeShape myMapModified;
-
- private:
-
 };
 
 #endif //_BOPAlgo_CellsBuilder_HeaderFile
index d5eab13..a3e1dd7 100644 (file)
@@ -39,6 +39,10 @@ bcadd result f1 1 f2 1 f3 1 -m 2
 bcadd result f1 0 f2 1 f3 1 -m 2
 bcremoveint result
 
+if {![regexp {This shape seems to be OK.} [bopcheck result]]} {
+    puts "Error: result shape is self intersected"
+}
+
 donly result
 fit
 
diff --git a/tests/boolean/cells_test/K1 b/tests/boolean/cells_test/K1
new file mode 100644 (file)
index 0000000..ab831ec
--- /dev/null
@@ -0,0 +1,56 @@
+puts "=========="
+puts "OCC28245"
+puts "=========="
+puts ""
+#################################################################################################
+# Result of Cells Builder algorithm becomes invalid after removal of internal boundaries on faces
+#################################################################################################
+
+circle c1 0 0 0 0 0 1 10
+circle c2 10 0 0 0 0 1 10
+circle c3 5 9 0 0 0 1 10
+
+mkedge e1 c1
+mkedge e2 c2
+mkedge e3 c3
+
+wire w1 e1
+wire w2 e2
+wire w3 e3
+
+mkplane f1 w1
+mkplane f2 w2
+mkplane f3 w3
+
+bclearobjects
+bcleartools
+baddobjects f1 f2 f3
+bfillds
+bcbuild rx
+
+bcadd r1 f1 1 -m 1 -u
+bcadd r1 f2 1 -m 2 -u
+
+checknbshapes r1 -face 2
+checkprops r1 -s 505.482
+
+bcremoveall
+bcadd r2 f1 1 -m 1 -u
+bcadd r2 f2 1 -m 1 -u
+
+checknbshapes r2 -face 1
+checkprops r2 -s 505.482
+
+bcremoveall
+bcadd result f1 1 -m 1
+bcadd result f2 1 f3 0 -m 1
+bcadd result f3 1 f1 0 -m 2
+bcremoveint result
+
+set bcheck [bopcheck result]
+if {![regexp {This shape seems to be OK.} $bcheck]} {
+    puts "Error: result shape is self intersected"
+}
+
+checknbshapes result -edge 8 -face 2
+checkprops result -s 651.238