]> OCCT Git - occt-copy.git/commitdiff
0028189: Result of Boolean operation is non-manifold wire
authoremv <emv@opencascade.com>
Thu, 29 Dec 2016 12:42:08 +0000 (15:42 +0300)
committeremv <emv@opencascade.com>
Fri, 7 Jul 2017 07:02:10 +0000 (10:02 +0300)
1. The result of Boolean operation on the arguments of collection type, containers WIRE/SHELL/COMPSOLID, is also a collection.
The containers of type WIRE included into result should now also (as the SHELLs) have coherent orientation of its sub-shapes.
For that the new method has been implemented (BOPTools_AlgoTools::OrientEdgesOnWire(TopoDS_Shape&)) which reorients edges for correct ordering.
The duplicating containers, i.e. containers with the contents completely included in other containers, are now avoided in the result of BOP.
2. The result of Fuse operation on Compsolids is now also will be Compsolid.
3. Documentation has been updated.
4. New test cases for the issue.
5. Adjusting test cases to current behavior.

Correction of test case bugs/modalg_4/bug726_2 according to the new behavior

43 files changed:
dox/dev_guides/upgrade/upgrade.md
dox/user_guides/boolean_operations/boolean_operations.md
src/BOPAlgo/BOPAlgo_BOP.cxx
src/BOPTest/BOPTest_UtilityCommands.cxx
src/BOPTools/BOPTools_AlgoTools.cxx
src/BOPTools/BOPTools_AlgoTools.hxx
tests/boolean/bcommon_2d/F3
tests/boolean/bcommon_2d/F4
tests/boolean/bcommon_2d/F5
tests/boolean/bcommon_2d/N8
tests/boolean/bcommon_2d/N9
tests/boolean/bcommon_2d/O1
tests/boolean/bcommon_2d/O7
tests/boolean/bopcommon_2d/F3
tests/boolean/bopcommon_2d/F4
tests/boolean/bopcommon_2d/F5
tests/boolean/bopcommon_2d/N8
tests/boolean/bopcommon_2d/N9
tests/boolean/bopcommon_2d/O1
tests/boolean/bopcommon_2d/O7
tests/boolean/bopcommon_complex/L3
tests/boolean/bopcommon_complex/L6
tests/boolean/bopcommon_complex/L7
tests/boolean/bopcommon_complex/L8
tests/boolean/bopcommon_complex/L9
tests/boolean/bopcommon_complex/M3
tests/boolean/bopcommon_complex/M4
tests/boolean/bopcommon_complex/M5
tests/boolean/bopcommon_complex/M6
tests/boolean/bopfuse_complex/O2
tests/boolean/bopfuse_complex/O3
tests/bugs/modalg_1/bug13538
tests/bugs/modalg_4/bug726_2
tests/bugs/modalg_6/bug26980
tests/bugs/modalg_6/bug28189_1 [new file with mode: 0644]
tests/bugs/modalg_6/bug28189_2 [new file with mode: 0644]
tests/bugs/modalg_6/bug28189_3 [new file with mode: 0644]
tests/bugs/modalg_6/bug28189_4 [new file with mode: 0644]
tests/bugs/modalg_6/bug28189_5 [new file with mode: 0644]
tests/bugs/modalg_6/bug28189_6 [new file with mode: 0644]
tests/bugs/modalg_6/bug28189_7 [new file with mode: 0644]
tests/bugs/modalg_6/bug28189_8 [new file with mode: 0644]
tests/bugs/modalg_6/bug28189_9 [new file with mode: 0644]

index 44472210cea129cd5d42d168d924f7d5b75206d4..6d8739e1f5b6b33c969ada94841cff0fa4d3a9ec 100644 (file)
@@ -1103,3 +1103,8 @@ The following classes have been changed:
 *  The last optional argument *RemoveInvalidFaces* has been removed from the constructor of class  *BRepOffset_MakeOffset* and method *Initialize*.
 * The public method *BOPDS_DS::VerticesOnIn* has been renamed into *SubShapesOnIn* and the new output parameter *theCommonPB* has been added.
 
+@section upgrade_occt720 Upgrade to OCCT 7.2.0
+
+@subsection upgrade_720_Result_Of_BOP_On_Containers Result of Boolean operations on containers
+
+* The result of Boolean operations on arguments of collection types (WIRE/SHELL/COMPSOLID) is now filtered from duplicating containers.
\ No newline at end of file
index 92c49aa2312447c0496d523d378334e1ce15ad20..0b900176efbd11417df4d44725e87a2431a7add6 100644 (file)
@@ -1080,9 +1080,11 @@ The input data for this step is a *BOPAlgo_Builder* object after building result
 * The result of the operation *Cut12* for arguments *S1* and *S2* contains the parts of argument *S1* that have state **OUT** relative to the opposite argument *S2*.
 * The result of the operation *Cut21* for arguments *S1* and *S2* contains the parts of argument *S2* that have state **OUT** relative to the opposite argument *S1*.
 * For the arguments of collection type (WIRE, SHELL, COMPSOLID) the type will be passed in the result. For example, the result of Common operation between Shell and Wire will be a compound containing Wire.
-* For the arguments of collection type (WIRE, SHELL, COMPSOLID) containing overlapping parts the overlapping parts passed into result will be repeated for each container from the input shapes containing such parts.
-* The result of the operation Fuse for the arguments of collection type (WIRE, SHELL, COMPSOLID) will contain the same number of containers as the arguments. The overlapping parts (EDGES/FACES/SOLIDS) will be shared among them. For example, the result of Fuse operation between two wires will be two wires sharing coinciding edges if any.
-* The result of the operation Common for the arguments of collection type (WIRE, SHELL, COMPSOLID) will consist of the containers containing the same overlapping parts. For example, the result of Common operation between two fully/partially overlapping wires will be two wires containing the same edges.
+* For the arguments of collection type (WIRE, SHELL, COMPSOLID) containing overlapping parts the overlapping parts passed into result will be repeated for each container from the input shapes containing such parts. The containers completely included in other containers will be avoided in the result.
+* For the arguments of collection type (WIRE, SHELL, COMPSOLID) the containers included into result will have the same orientation as the original containers from arguments. In case of duplication its orientation will be defined by the orientation of the first container in arguments. Each container included into result will have coherent orientation of its sub-shapes.
+* The result of the operation Fuse for the arguments of collection type (WIRE, SHELL) will consist of the shapes of the same collection type. The overlapping parts (EDGES/FACES) will be shared among containers, but duplicating containers will be avoided in the result. For example, the result of Fuse operation between two fully coinciding wires will be one wire, but the result of Fuse operation between two partially coinciding wires will be two wires sharing coinciding edges.
+* The result of the operation Fuse for the arguments of type COMPSOLID will consist of the compound containing COMPSOLIDs created from connexity blocks of fused solids.
+* The result of the operation Common for the arguments of collection type (WIRE, SHELL, COMPSOLID) will consist of the unique containers containing the overlapping parts. For example, the result of Common operation between two fully overlapping wires will be one wire containing all splits of edges. The number of wires in the result of Common operation between two partially overlapping wires will be equal to the number of connexity blocks of overlapping edges.
 
 @subsection occt_algorithms_9_4 Examples
 
@@ -1555,7 +1557,7 @@ Let us consider two Wires that have overlapping edges, *W1* is the object and *W
 
 @figure{/user_guides/boolean_operations/images/boolean_image140.png}
        
-* The result of *Common* operation is a compound containing two Wires both consisting of an overlapping edge. The new Wires are created from the objects:
+* The result of *Common* operation is a compound containing one Wire consisting of an overlapping edge. The new Wire is created from the objects:
 
 @figure{/user_guides/boolean_operations/images/boolean_image141.png}   
 
index 932877185a67cdd094432031184127dbe402190f..301267e9c9a1db6897b9aca11b240852ed31ba22 100644 (file)
@@ -36,7 +36,6 @@
 #include <TopoDS_Edge.hxx>
 #include <TopoDS_Iterator.hxx>
 #include <TopoDS_Shape.hxx>
-#include <TopTools_ListIteratorOfListOfShape.hxx>
 
 typedef NCollection_IndexedDataMap
   <BOPTools_Set,
@@ -49,6 +48,17 @@ static
 static
   void CollectContainers(const TopoDS_Shape& theS,
                          BOPCol_ListOfShape& theLSC);
+//
+static
+  void RemoveDuplicates(BOPCol_ListOfShape& theContainers);
+//
+static
+  void RemoveDuplicates(BOPCol_ListOfShape& theContainers,
+                        const TopAbs_ShapeEnum theType);
+//
+static
+  Standard_Integer NbCommonItemsInMap(const BOPCol_MapOfShape& theM1,
+                                      const BOPCol_MapOfShape& theM2);
 
 
 //=======================================================================
@@ -733,15 +743,12 @@ void BOPAlgo_BOP::BuildShape()
   //
   Standard_Integer i;
   TopAbs_ShapeEnum aType, aT1, aT2;
-  TopTools_ListOfShape aLSC, aLCB;
+  BOPCol_ListOfShape aLSC, aLCB;
   BOPCol_ListIteratorOfListOfShape aItLS, aItLSIm, aItLCB;
   TopoDS_Iterator aIt;
   BRep_Builder aBB;
   TopoDS_Shape aRC, aRCB;
   //
-  TopoDS_Compound aResult;
-  aBB.MakeCompound(aResult);
-  //
   BOPCol_MapOfShape aMSRC;
   BOPTools::MapShapes(myRC, aMSRC);
   //
@@ -757,6 +764,7 @@ void BOPAlgo_BOP::BuildShape()
     }
   }
   // make containers
+  BOPCol_ListOfShape aLCRes;
   aItLS.Initialize(aLSC);
   for (; aItLS.More(); aItLS.Next()) {
     const TopoDS_Shape& aSC = aItLS.Value();
@@ -767,7 +775,7 @@ void BOPAlgo_BOP::BuildShape()
     for (; aIt.More(); aIt.Next()) {
       const TopoDS_Shape& aS = aIt.Value();
       if (myImages.IsBound(aS)) {
-        const TopTools_ListOfShape& aLSIm = myImages.Find(aS);
+        const BOPCol_ListOfShape& aLSIm = myImages.Find(aS);
         //
         aItLSIm.Initialize(aLSIm);
         for (; aItLSIm.More(); aItLSIm.Next()) {
@@ -817,14 +825,31 @@ void BOPAlgo_BOP::BuildShape()
         aBB.Add(aRCB, aCBS);
       }
       //
-      if (aType == TopAbs_SHELL) {
+      if (aType == TopAbs_WIRE) {
+        // reorient wire
+        BOPTools_AlgoTools::OrientEdgesOnWire(aRCB);
+      }
+      else if (aType == TopAbs_SHELL) {
         BOPTools_AlgoTools::OrientFacesOnShell(aRCB);
       }
       //
-      aBB.Add(aResult, aRCB);
+      aRCB.Orientation(aSC.Orientation());
+      //
+      aLCRes.Append(aRCB);
     }
   }
   //
+  RemoveDuplicates(aLCRes);
+  //
+  // add containers to result
+  TopoDS_Compound aResult;
+  aBB.MakeCompound(aResult);
+  //
+  aItLS.Initialize(aLCRes);
+  for (; aItLS.More(); aItLS.Next()) {
+    aBB.Add(aResult, aItLS.Value());
+  }
+  //
   // add the rest of the shapes into result
   BOPCol_MapOfShape aMSResult;
   BOPTools::MapShapes(aResult, aMSResult);
@@ -832,7 +857,7 @@ void BOPAlgo_BOP::BuildShape()
   aIt.Initialize(myRC);
   for (; aIt.More(); aIt.Next()) {
     const TopoDS_Shape& aS = aIt.Value();
-    if (!aMSResult.Contains(aS)) {
+    if (aMSResult.Add(aS)) {
       aBB.Add(aResult, aS);
     }
   }
@@ -859,6 +884,7 @@ void BOPAlgo_BOP::BuildSolid()
   BOPAlgo_BuilderSolid aSB; 
   BOPCol_MapOfShape aMSA, aMZ;
   BOPTools_IndexedDataMapOfSetShape aDMSTS;
+  BOPCol_ListOfShape aLSC;
   //
   myErrorStatus=0;
   //
@@ -868,6 +894,9 @@ void BOPAlgo_BOP::BuildSolid()
     aItLS.Initialize(aLSA);
     for (; aItLS.More(); aItLS.Next()) {
       const TopoDS_Shape& aSA=aItLS.Value();
+      //
+      CollectContainers(aSA, aLSC);
+      //
       aExp.Init(aSA, TopAbs_SOLID);
       for (; aExp.More(); aExp.Next()) {
         const TopoDS_Shape& aZA=aExp.Current();
@@ -1018,7 +1047,87 @@ void BOPAlgo_BOP::BuildSolid()
     aBB.Add(aRC, aSx);
   }
   //
-  myShape=aRC;
+  if (aLSC.IsEmpty()) {
+    // no Compsolids in arguments
+    myShape=aRC;
+    return;
+  }
+  //
+  // build new Compsolids from new solids containing splits
+  // of faces from arguments of type Compsolid
+  //
+  TopoDS_Shape aResult;
+  BOPTools_AlgoTools::MakeContainer(TopAbs_COMPOUND, aResult);
+  //
+  // optimization for one solid in the result
+  if (aLSR.Extent() == 1 && !aNbSx) {
+    TopoDS_Shape aCS;
+    BOPTools_AlgoTools::MakeContainer(TopAbs_COMPSOLID, aCS);
+    aBB.Add(aCS, aLSR.First());
+    //
+    aBB.Add(aResult, aCS);
+    myShape = aResult;
+    return;
+  }
+  //
+  // get splits of faces of the Compsolid arguments
+  BOPCol_MapOfShape aMFCs;
+  aItLS.Initialize(aLSC);
+  for (; aItLS.More(); aItLS.Next()) {
+    const TopoDS_Shape& aCs = aItLS.Value();
+    aExp.Init(aCs, TopAbs_FACE);
+    for (; aExp.More(); aExp.Next()) {
+      const TopoDS_Shape& aF = aExp.Current();
+      const BOPCol_ListOfShape* pLFIm = myImages.Seek(aF);
+      if (!pLFIm) {
+        aMFCs.Add(aF);
+      }
+      else {
+        BOPCol_ListIteratorOfListOfShape aItLFIm(*pLFIm);
+        for (; aItLFIm.More(); aItLFIm.Next()) {
+          aMFCs.Add(aItLFIm.Value());
+        }
+      }
+    }
+  }
+  //
+  // build connexity blocks from new solids
+  BOPCol_ListOfShape aLCBS;
+  BOPTools_AlgoTools::MakeConnexityBlocks(aRC, TopAbs_FACE, TopAbs_SOLID, aLCBS);
+  //
+  aItLS.Initialize(aLCBS);
+  for (; aItLS.More(); aItLS.Next()) {
+    const TopoDS_Shape& aCB = aItLS.Value();
+    //
+    // check if the Compsolid should be created
+    aExp.Init(aCB, TopAbs_FACE);
+    for (; aExp.More(); aExp.Next()) {
+      if (aMFCs.Contains(aExp.Current())) {
+        break;
+      }
+    }
+    //
+    if (!aExp.More()) {
+      // add solids directly into result as their origins are not Compsolids
+      for (aIt.Initialize(aCB); aIt.More(); aIt.Next()) {
+        aBB.Add(aResult, aIt.Value());
+      }
+      continue;
+    }
+    //
+    // make Compsolid
+    TopoDS_Shape aCS;
+    BOPTools_AlgoTools::MakeContainer(TopAbs_COMPSOLID, aCS);
+    //
+    aIt.Initialize(aCB);
+    for (; aIt.More(); aIt.Next()) {
+      aBB.Add(aCS, aIt.Value());
+    }
+    //
+    aBB.Add(aResult, aCS);
+  }
+  //
+  myShape = aResult;
 }
 //=======================================================================
 //function : IsBoundSplits
@@ -1121,3 +1230,123 @@ void CollectContainers(const TopoDS_Shape& theS,
   }
 }
 
+//=======================================================================
+//function : RemoveDuplicates
+//purpose  : Filters the containers with identical contents
+//=======================================================================
+void RemoveDuplicates(BOPCol_ListOfShape& theContainers)
+{
+  RemoveDuplicates(theContainers, TopAbs_WIRE);
+  RemoveDuplicates(theContainers, TopAbs_SHELL);
+  RemoveDuplicates(theContainers, TopAbs_COMPSOLID);
+}
+
+//=======================================================================
+//function : RemoveDuplicates
+//purpose  : Filters the containers of given type with identical contents
+//=======================================================================
+void RemoveDuplicates(BOPCol_ListOfShape& theContainers,
+                      const TopAbs_ShapeEnum theType)
+{
+  // get containers of given type
+  BOPCol_ListOfShape aLC;
+  BOPCol_ListIteratorOfListOfShape aItLC(theContainers);
+  for (; aItLC.More(); aItLC.Next()) {
+    const TopoDS_Shape& aC = aItLC.Value();
+    if (aC.ShapeType() == theType) {
+      aLC.Append(aC);
+    }
+  }
+  //
+  if (aLC.IsEmpty()) {
+    return;
+  }
+  //
+  // map containers to compare its contents
+  NCollection_IndexedDataMap<TopoDS_Shape, BOPCol_MapOfShape> aContents;
+  //
+  aItLC.Initialize(aLC);
+  for (; aItLC.More(); aItLC.Next()) {
+    const TopoDS_Shape& aC = aItLC.Value();
+    //
+    BOPCol_MapOfShape& aMC = aContents(aContents.Add(aC, BOPCol_MapOfShape()));
+    //
+    TopoDS_Iterator aIt(aC);
+    for (; aIt.More(); aIt.Next()) {
+      aMC.Add(aIt.Value());
+    }
+  }
+  //
+  // compare the contents of the containers and find duplicates
+  BOPCol_MapOfShape aDuplicates;
+  //
+  Standard_Integer i, j, aNb = aContents.Extent();
+  for (i = 1; i <= aNb; ++i) {
+    const TopoDS_Shape& aCi = aContents.FindKey(i);
+    if (aDuplicates.Contains(aCi)) {
+      continue;
+    }
+    const BOPCol_MapOfShape& aMi = aContents(i);
+    Standard_Integer aNbi = aMi.Extent();
+    //
+    for (j = i + 1; j <= aNb; ++j) {
+      const TopoDS_Shape& aCj = aContents.FindKey(j);
+      if (aDuplicates.Contains(aCj)) {
+        continue;
+      }
+      const BOPCol_MapOfShape& aMj = aContents(j);
+      Standard_Integer aNbj = aMj.Extent();
+      //
+      Standard_Integer aNbCommon = NbCommonItemsInMap(aMi, aMj);
+      //
+      if (aNbj == aNbCommon) {
+        aDuplicates.Add(aCj);
+        continue;
+      }
+      //
+      if (aNbi == aNbCommon) {
+        aDuplicates.Add(aCi);
+        break;
+      }
+    }
+  }
+  //
+  if (aDuplicates.IsEmpty()) {
+    return;
+  }
+  //
+  // remove duplicating containers
+  aItLC.Initialize(theContainers);
+  for (; aItLC.More(); ) {
+    const TopoDS_Shape& aC = aItLC.Value();
+    if (aDuplicates.Contains(aC)) {
+      theContainers.Remove(aItLC);
+      continue;
+    }
+    aItLC.Next();
+  }
+}
+
+//=======================================================================
+//function : NbCommonItemsInMap
+//purpose  : Counts the items contained in both maps
+//=======================================================================
+Standard_Integer NbCommonItemsInMap(const BOPCol_MapOfShape& theM1,
+                                    const BOPCol_MapOfShape& theM2)
+{
+  const BOPCol_MapOfShape* aMap1 = &theM1;
+  const BOPCol_MapOfShape* aMap2 = &theM2;
+  //
+  if (theM2.Extent() < theM1.Extent()) {
+    aMap1 = &theM2;
+    aMap2 = &theM1;
+  }
+  //
+  Standard_Integer iCommon = 0;
+  for (BOPCol_MapIteratorOfMapOfShape aIt(*aMap1); aIt.More(); aIt.Next()) {
+    if (aMap2->Contains(aIt.Value())) {
+      ++iCommon;
+    }
+  }
+  return iCommon;
+}
index 970fb105e6d23f5c60521270cb53902d18a32e04..0d51aa1bf5b9a02b802c7d8d23c75106b35b94b4 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <BOPTest.hxx>
 
+#include <BOPTools_AlgoTools.hxx>
 #include <BOPTools_AlgoTools2D.hxx>
 #include <DBRep.hxx>
 #include <IntTools_Context.hxx>
@@ -23,8 +24,8 @@
 #include <TopoDS_Face.hxx>
 #include <TopoDS_Shape.hxx>
 
-static Standard_Integer attachpcurve   (Draw_Interpretor&, Standard_Integer, const char**);
-
+static Standard_Integer attachpcurve (Draw_Interpretor&, Standard_Integer, const char**);
+static Standard_Integer edgestowire  (Draw_Interpretor&, Standard_Integer, const char**);
 
 
 //=======================================================================
@@ -41,6 +42,7 @@ static Standard_Integer attachpcurve   (Draw_Interpretor&, Standard_Integer, con
   // Commands
   
   theCommands.Add("attachpcurve", "attachpcurve eold enew face", __FILE__, attachpcurve, group);
+  theCommands.Add("edgestowire" , "edgestowire wire edges"     , __FILE__, edgestowire , group);
 }
 
 //=======================================================================
@@ -102,3 +104,27 @@ static Standard_Integer attachpcurve(Draw_Interpretor& theDI,
 
   return 0;
 }
+
+//=======================================================================
+//function : edgestowire
+//purpose  : Orients the edges to make wire
+//=======================================================================
+static Standard_Integer edgestowire(Draw_Interpretor& theDI,
+                                    Standard_Integer  theNArg,
+                                    const char ** theArgVal)
+{
+  if (theNArg != 3) {
+    theDI << "Use: edgestowire wire edges\n";
+    return 1;
+  }
+  //
+  TopoDS_Shape anEdges = DBRep::Get(theArgVal[2]);
+  if (anEdges.IsNull()) {
+    theDI << "no edges\n";
+    return 1;
+  }
+  //
+  BOPTools_AlgoTools::OrientEdgesOnWire(anEdges);
+  DBRep::Set(theArgVal[1], anEdges);
+  return 0;
+}
index d695831fe7fef17ce97f46544f10a0ff2ad32938..85be6dac95f6ea6504327b93eb437885c5b60ab6 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <BOPCol_IndexedMapOfShape.hxx>
 #include <BOPCol_MapOfShape.hxx>
+#include <BOPCol_MapOfOrientedShape.hxx>
 #include <BOPTools.hxx>
 #include <BOPTools_AlgoTools.hxx>
 #include <BOPTools_AlgoTools2D.hxx>
@@ -54,6 +55,7 @@
 #include <TopAbs_Orientation.hxx>
 #include <TopExp.hxx>
 #include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
 #include <TopoDS_Compound.hxx>
 #include <TopoDS_CompSolid.hxx>
 #include <TopoDS_Edge.hxx>
@@ -197,6 +199,94 @@ void BOPTools_AlgoTools::MakeConnexityBlocks
   }// for (; aIt.More(); aIt.Next()) 
 }
 //=======================================================================
+// function: OrientEdgesOnWire
+// purpose: Reorient edges on wire for correct ordering
+//=======================================================================
+void BOPTools_AlgoTools::OrientEdgesOnWire(TopoDS_Shape& theWire)
+{
+  // make vertex-edges connexity map
+  BOPCol_IndexedDataMapOfShapeListOfShape aVEMap;
+  BOPTools::MapShapesAndAncestors(theWire, TopAbs_VERTEX, TopAbs_EDGE, aVEMap);
+  //
+  if (aVEMap.IsEmpty()) {
+    return;
+  }
+  //
+  BRep_Builder aBB;
+  // new wire
+  TopoDS_Wire aWire;
+  aBB.MakeWire(aWire);
+  // fence map
+  BOPCol_MapOfOrientedShape aMFence;
+  //
+  TopoDS_Iterator aIt(theWire);
+  for (; aIt.More(); aIt.Next()) {
+    const TopoDS_Edge& aEC = TopoDS::Edge(aIt.Value());
+    if (!aMFence.Add(aEC)) {
+      continue;
+    }
+    //
+    // add edge to a wire as it is
+    aBB.Add(aWire, aEC);
+    //
+    TopoDS_Vertex aV1, aV2;
+    TopExp::Vertices(aEC, aV1, aV2, Standard_True);
+    //
+    if (aV1.IsSame(aV2)) {
+      // closed edge, go to the next edge
+      continue;
+    }
+    //
+    // orient the adjacent edges
+    for (Standard_Integer i = 0; i < 2; ++i) {
+      TopoDS_Shape aVC = !i ? aV1 : aV2;
+      //
+      for (;;) {
+        const BOPCol_ListOfShape& aLE = aVEMap.FindFromKey(aVC);
+        if (aLE.Extent() != 2) {
+          // free vertex or multi-connexity, go to the next edge
+          break;
+        }
+        //
+        Standard_Boolean bStop = Standard_True;
+        //
+        BOPCol_ListIteratorOfListOfShape aItLE(aLE);
+        for (; aItLE.More(); aItLE.Next()) {
+          const TopoDS_Edge& aEN = TopoDS::Edge(aItLE.Value());
+          if (aMFence.Contains(aEN)) {
+            continue;
+          }
+          //
+          TopoDS_Vertex aVN1, aVN2;
+          TopExp::Vertices(aEN, aVN1, aVN2, Standard_True);
+          if (aVN1.IsSame(aVN2)) {
+            // closed edge, go to the next edge
+            break;
+          }
+          //
+          // change orientation if necessary and go to the next edges
+          if ((!i && aVC.IsSame(aVN2)) || (i && aVC.IsSame(aVN1))) {
+            aBB.Add(aWire, aEN);
+          }
+          else {
+            aBB.Add(aWire, aEN.Reversed());
+          }
+          aMFence.Add(aEN);
+          aVC = aVC.IsSame(aVN1) ? aVN2 : aVN1;
+          bStop = Standard_False;
+          break;
+        }
+        //
+        if (bStop) {
+          break;
+        }
+      }
+    }
+  }
+  //
+  theWire = aWire;
+}
+//=======================================================================
 // function: OrientFacesOnShell
 // purpose: 
 //=======================================================================
index feaf2509f85d9def2e39d1c075f313b000f664b1..dddfb07ae2ac80da80ba4585b4afc8cc970a358a 100644 (file)
@@ -193,8 +193,12 @@ public:
   //! theLCB (as list of compounds)
   //! in terms of connexity by the shapes of theType
   Standard_EXPORT static void MakeConnexityBlocks (const TopoDS_Shape& theS, const TopAbs_ShapeEnum theType1, const TopAbs_ShapeEnum theType2, BOPCol_ListOfShape& theLCB);
-  
-  Standard_EXPORT static void OrientFacesOnShell (TopoDS_Shape& theS);
+
+  //! Correctly orients edges on the wire
+  Standard_EXPORT static void OrientEdgesOnWire (TopoDS_Shape& theWire);
+
+  //! Correctly orients faces on the shell
+  Standard_EXPORT static void OrientFacesOnShell (TopoDS_Shape& theShell);
   
 
   //! Provides valid values of tolerances for the shape <theS>
index 69a6cecfbdc284a119b179219d1e3e0b1ae7c657..c4d4be1685ea1d95fdd6c4a1c41d051048e2b596 100644 (file)
@@ -3,7 +3,7 @@ restore [locate_data_file offset_wire_034.brep] b
 
 bcommon result b a
 
-checkprops result -l 691.95
+checkprops result -l 345.975
 checksection result
 checknbshapes result -vertex 8 -edge 7 -t
 
index dba135c2eb4ca0803e49647ff228ac5d74400bc3..d914dd080e179b8c5522b39ebe9aa7a8d74dcd64 100644 (file)
@@ -3,7 +3,7 @@ restore [locate_data_file case_3_wire2.brep] b
 
 bcommon result b a
 
-checkprops result -l 691.95
+checkprops result -l 345.975
 checksection result
 checknbshapes result -vertex 14 -edge 13 -t
 
index 3b29e74907381b8c31f8326a6ea304d9c6650c01..f50b1d41d64c6acf5fd81fd21ea7b9a1937c84ed 100644 (file)
@@ -3,7 +3,7 @@ restore [locate_data_file case_3_wire5.brep] b
 
 bcommon result b a
 
-checkprops result -l 132.732
+checkprops result -l 66.3661
 checksection result
 checknbshapes result -vertex 2 -edge 1 -t
 
index 5db9303c503829ff825cfb602a6ae1cf143e6693..d50c21f90c66dc16bc336f05d755f0c0d5b273e1 100644 (file)
@@ -3,7 +3,7 @@ restore [locate_data_file case_9_wire1.brep] b
 
 bcommon result b a
 
-checkprops result -l 287.575
+checkprops result -l 143.787
 checksection result
 checknbshapes result -vertex 2 -edge 1 -t
 
index 2e28b209c009e20b9614a682449b21e4b4d0f143..58d2f06811608d162776143f038cd8c60429d896 100644 (file)
@@ -3,7 +3,7 @@ restore [locate_data_file case_9_wire2.brep] b
 
 bcommon result b a
 
-checkprops result -l 287.575
+checkprops result -l 143.787
 checksection result
 checknbshapes result -vertex 2 -edge 1 -t
 
index 7726d9837e2110a3c4a37f24f4bd1a5991de8a15..59ebd0268a008bfa7b28acf457b426854c5c2c25 100644 (file)
@@ -3,7 +3,7 @@ restore [locate_data_file case_9_wire3.brep] b
 
 bcommon result b a
 
-checkprops result -l 159.8
+checkprops result -l 79.9002
 checksection result
 checknbshapes result -vertex 2 -edge 1 -t
 
index 8d35aa0f2c253c1d4c473ab9929d84f832b103bd..f8e15350458953371b477fea979fb50f469480bf 100644 (file)
@@ -3,7 +3,7 @@ restore [locate_data_file case_9_wire1.brep] b
 
 bcommon result b a
 
-checkprops result -l 287.575
+checkprops result -l 143.787
 checksection result
 checknbshapes result -vertex 2 -edge 1 -t
 
index 4c5fb8f07d16b0f86b00d0bf49f926684351182f..d5d8b00904d586937b46035a99a781319da7e3b6 100644 (file)
@@ -4,7 +4,7 @@ restore [locate_data_file offset_wire_034.brep] b
 bop a b
 bopcommon result
 
-checkprops result -l 691.95
+checkprops result -l 345.975
 checksection result
 checknbshapes result -vertex 8 -edge 7 -t
 
index e2feb823ae167dbeefa549cf2acd3d2a96203d96..370a6e1477f849789a7c7308c31756178dfd905c 100644 (file)
@@ -4,7 +4,7 @@ restore [locate_data_file case_3_wire2.brep] b
 bop a b
 bopcommon result
 
-checkprops result -l 691.95
+checkprops result -l 345.975
 checksection result
 checknbshapes result -vertex 14 -edge 13 -t
 
index 9232a1f79d6716f314af437adc6e86df0c71b5e3..440600962f8108b4aa52685e03c3c92ca699be5e 100644 (file)
@@ -4,7 +4,7 @@ restore [locate_data_file case_3_wire5.brep] b
 bop a b
 bopcommon result
 
-checkprops result -l 132.732
+checkprops result -l 66.3661
 checksection result
 checknbshapes result -vertex 2 -edge 1 -t
 
index ac0211ee91430f033da199a6969b38c58a934a5c..bd71120c227b62dc8071ac5b8074dcca14f9b4b8 100644 (file)
@@ -4,7 +4,7 @@ restore [locate_data_file case_9_wire1.brep] b
 bop a b
 bopcommon result
 
-checkprops result -l 287.575
+checkprops result -l 143.787
 checksection result
 checknbshapes result -vertex 2 -edge 1 -t
 
index deb67741537a027f9a0a3c1db1ac62be5133a0ee..90f6b6fb170c2b56130a0dcc152a6e1325c78662 100644 (file)
@@ -4,7 +4,7 @@ restore [locate_data_file case_9_wire2.brep] b
 bop a b
 bopcommon result
 
-checkprops result -l 287.575
+checkprops result -l 143.787
 checksection result
 checknbshapes result -vertex 2 -edge 1 -t
 
index 29f1692135b77aacefa3bc250d3a088df0c16cc4..fdb80c32f9007de3ca49df3384fefa43b65e70cb 100644 (file)
@@ -4,7 +4,7 @@ restore [locate_data_file case_9_wire3.brep] b
 bop a b
 bopcommon result
 
-checkprops result -l 159.8
+checkprops result -l 79.9002
 checksection result
 checknbshapes result -vertex 2 -edge 1 -t
 
index d2a930d92aad8c6e07dfdd01319186933bd21332..7827f872d67536e3230eeef83a26264d36ac229f 100644 (file)
@@ -4,7 +4,7 @@ restore [locate_data_file case_9_wire1.brep] b
 bop a b
 bopcommon result
 
-checkprops result -l 287.575
+checkprops result -l 143.787
 checksection result
 checknbshapes result -vertex 2 -edge 1 -t
 
index 4ccbc3fc233cf39b874badc6051287f342f31cec..ecfee328591de094343a17cf26152d2a70fc91ea 100644 (file)
@@ -4,5 +4,5 @@ restore [locate_data_file sh2a] b2
 bop b1 b2
 bopcommon result
 
-checkprops result -s 700
+checkprops result -s 350
 checkview -display result -2d -otherwise { b1 b2 } -s -path ${imagedir}/${test_image}.png
index fe929868c4317b0e27c45608371f9eff5f058722..a943daa42b76aa6242e2efd9927fdd8edbcd8b64 100644 (file)
@@ -4,5 +4,5 @@ restore [locate_data_file sh7] b2
 bop b1 b2
 bopcommon result
 
-checkprops result -s 200
+checkprops result -s 100
 checkview -display result -2d -otherwise { b1 b2 } -s -path ${imagedir}/${test_image}.png
index 59a063bda132cae460e310d18035255f7a89a035..56b4b6e70eba64527bf23f6891b5dde514ac7a97 100644 (file)
@@ -4,5 +4,5 @@ restore [locate_data_file sh8] b2
 bop b1 b2
 bopcommon result
 
-checkprops result -s 191.421
+checkprops result -s 95.7107
 checkview -display result -2d -otherwise { b1 b2 } -s -path ${imagedir}/${test_image}.png
index 7f639db3cdf19415cd560cbc0756a255c91e2f3b..74f3ab96fd0fb2179dad6b77f5696630d1a97457 100644 (file)
@@ -4,5 +4,5 @@ restore [locate_data_file sh9] b2
 bop b1 b2
 bopcommon result
 
-checkprops result -s 800
+checkprops result -s 400
 checkview -display result -2d -otherwise { b1 b2 } -s -path ${imagedir}/${test_image}.png
index 020028f9850d0cbbcb5f374113ae903a41943fa4..30ed85ff5d1bec32c0c2982ee0277c0f50502c08 100644 (file)
@@ -4,5 +4,5 @@ restore [locate_data_file shx] b2
 bop b1 b2
 bopcommon result
 
-checkprops result -s 662.742
+checkprops result -s 331.371
 checkview -display result -2d -otherwise { b1 b2 } -s -path ${imagedir}/${test_image}.png
index 49abd94a240c738b5f0aa7931e2217f811eeb75f..e1517435ce4466644b7ccb2c4b17eeaa4d476af3 100644 (file)
@@ -4,5 +4,5 @@ restore [locate_data_file sg2] b2
 bop b1 b2
 bopcommon result
 
-checkprops result -s 4188.79
+checkprops result -s 2094.4
 checkview -display result -2d -otherwise { b1 b2 } -s -path ${imagedir}/${test_image}.png
index 6caa88490e9ab1fe80a20e91ec683b6ac389b96e..03d1db6dffa74c24e4f663dd8f45622e75c61627 100644 (file)
@@ -4,5 +4,5 @@ restore [locate_data_file sf5] b2
 bop b1 b2
 bopcommon result
 
-checkprops result -s 3221.73
+checkprops result -s 1610.86
 checkview -display result -2d -otherwise { b1 b2 } -s -path ${imagedir}/${test_image}.png
index 19e809e8f274eee76cba6b67c37bc363b5db941f..7821f20549e463f1a6291fc7f4fb2f68fc62ef59 100644 (file)
@@ -4,5 +4,5 @@ restore [locate_data_file sf3] b2
 bop b1 b2
 bopcommon result
 
-checkprops result -s 3221.73
+checkprops result -s 1610.86
 checkview -display result -2d -otherwise { b1 b2 } -s -path ${imagedir}/${test_image}.png
index 37e7a1a24e601bff6cb1c3c26dbd6d5fc553d645..5b565cbaacd3623f1ffec48db0998c741a8788eb 100644 (file)
@@ -4,5 +4,5 @@ restore [locate_data_file sf55] b2
 bop b1 b2
 bopcommon result
 
-checkprops result -s 75398.2
+checkprops result -s 37699.1
 checkview -display result -2d -otherwise { b1 b2 } -s -path ${imagedir}/${test_image}.png
index db2ebd79ef2b34e2aec9128ebfe992e085af6b54..8a852cb0d63cd4487613b38d5c54871319360027 100644 (file)
@@ -4,5 +4,5 @@ restore [locate_data_file sf5] b2
 bop b1 b2
 bopfuse result
 
-checkprops result -s 64442.7
+checkprops result -s 62831.9
 checkview -display result -2d -otherwise { b1 b2 } -s -path ${imagedir}/${test_image}.png
index 32bf6aad6f7db11b9dfa17042cf212241661b42e..65ad2281bc2f9fbc2975cce05eb975cb5ed63034 100644 (file)
@@ -4,5 +4,5 @@ restore [locate_data_file sf3] b2
 bop b1 b2
 bopfuse result
 
-checkprops result -s 64442.7
+checkprops result -s 62831.9
 checkview -display result -2d -otherwise { b1 b2 } -s -path ${imagedir}/${test_image}.png
index e224ecaad3f4c02009283e48670b98abb88a3737..28148d030544a2ac1a4ee9a8c218baf1d1003d1a 100755 (executable)
@@ -15,8 +15,8 @@ explode b Sh
 bop a_1 b_1
 bopcommon result
 
-checkprops result -s 20000
+checkprops result -s 10000
 checkshape result
-checknbshapes result -vertex 4 -edge 4 -wire 1 -face 1 -shell 2 -solid 0 -compsolid 0 -compound 1 -shape 13
+checknbshapes result -vertex 4 -edge 4 -wire 1 -face 1 -shell 1 -solid 0 -compsolid 0 -compound 1 -shape 12
 set 2viewer 0
 
index c1636c26c21dd6887153dccd0a719765b9ae3a30..461c2e37f8625c2f1f2a163041f45e105d134e04 100755 (executable)
@@ -1,4 +1,3 @@
-puts "TODO OCC12345 ALL: Faulty shapes in variables faulty_1 to faulty_"
 puts "TODO OCC12345 ALL: Error : The area of result shape is"
 
 puts "========"
index 9816fcb8103cd4cc38b5b3877d2c03cbdf81e316..5066a6e3f2b3337a0b2c517400cc7f8b7a3d4ccb 100644 (file)
@@ -6,7 +6,7 @@ puts ""
 # Intersection part of Boolean algorithm spends much system time and system memory
 #################################
 
-set max_time 120
+set max_time 130
 set mem_max_wsetpeak 500000000
 
 
diff --git a/tests/bugs/modalg_6/bug28189_1 b/tests/bugs/modalg_6/bug28189_1
new file mode 100644 (file)
index 0000000..4f51c38
--- /dev/null
@@ -0,0 +1,38 @@
+puts "========"
+puts "OCC28189"
+puts "========"
+puts ""
+#################################################
+# Result of Boolean operation is non-manifold wire
+#################################################
+
+restore [locate_data_file bug28189_contour.brep] s
+restore [locate_data_file bug28189_solid.brep] c
+
+bcommon result s c
+
+checknbshapes result -vertex 3 -edge 2 -wire 1
+checkprops result -l 173.267
+
+# check orientation of edges in the resulting wire
+
+explode result e
+explode result_1 v
+explode result_2 v
+
+set cmp1 [compare result_1_1 result_2_1]
+set cmp2 [compare result_1_1 result_2_2]
+
+if {[regexp "same shapes" $cmp1]} {
+  if {[regexp "equal shapes" $cmp1]} {
+    puts "Error: Incorrect orientation of edges in wire"
+  }
+} elseif {[regexp "same shapes" $cmp2]} {
+  if {[regexp "equal shapes" $cmp2]} {
+    puts "Error: Incorrect orientation of edges in wire"
+  }
+} else {
+  puts "Error: No shared vertex"
+}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
\ No newline at end of file
diff --git a/tests/bugs/modalg_6/bug28189_2 b/tests/bugs/modalg_6/bug28189_2
new file mode 100644 (file)
index 0000000..6d878c4
--- /dev/null
@@ -0,0 +1,15 @@
+puts "========"
+puts "OCC28189"
+puts "========"
+puts ""
+#################################################
+# Result of Boolean operation is non-manifold wire
+#################################################
+
+box b1 10 10 10
+box b2 10 10 10
+eval compound [explode b1 w] b1
+eval compound [explode b1 w] b2
+bcommon result b1 b2
+
+checknbshapes result -wire 6
diff --git a/tests/bugs/modalg_6/bug28189_3 b/tests/bugs/modalg_6/bug28189_3
new file mode 100644 (file)
index 0000000..b2c2fd3
--- /dev/null
@@ -0,0 +1,15 @@
+puts "========"
+puts "OCC28189"
+puts "========"
+puts ""
+#################################################
+# Result of Boolean operation is non-manifold wire
+#################################################
+
+box b1 10 10 10
+box b2 10 10 10
+eval compound [explode b1 w] b1
+eval compound [explode b1 w] b2
+bfuse result b1 b2
+
+checknbshapes result -wire 6
diff --git a/tests/bugs/modalg_6/bug28189_4 b/tests/bugs/modalg_6/bug28189_4
new file mode 100644 (file)
index 0000000..76f51bf
--- /dev/null
@@ -0,0 +1,16 @@
+puts "========"
+puts "OCC28189"
+puts "========"
+puts ""
+#################################################
+# Result of Boolean operation is non-manifold wire
+#################################################
+
+box b1 10 10 10
+box b2 10 10 10
+eval compound [explode b1 w] b1
+eval compound [explode b1 w] b2
+ttranslate b2 5 0 0
+bcommon result b1 b2
+
+checknbshapes result -wire 4
diff --git a/tests/bugs/modalg_6/bug28189_5 b/tests/bugs/modalg_6/bug28189_5
new file mode 100644 (file)
index 0000000..ba17389
--- /dev/null
@@ -0,0 +1,16 @@
+puts "========"
+puts "OCC28189"
+puts "========"
+puts ""
+#################################################
+# Result of Boolean operation is non-manifold wire
+#################################################
+
+box b1 10 10 10
+box b2 10 10 10
+eval compound [explode b1 w] b1
+eval compound [explode b1 w] b2
+ttranslate b2 5 0 0
+bfuse result b1 b2
+
+checknbshapes result -wire 12
diff --git a/tests/bugs/modalg_6/bug28189_6 b/tests/bugs/modalg_6/bug28189_6
new file mode 100644 (file)
index 0000000..ec2593a
--- /dev/null
@@ -0,0 +1,41 @@
+puts "========"
+puts "OCC28189"
+puts "========"
+puts ""
+#################################################
+# Result of Boolean operation is non-manifold wire
+#################################################
+
+vertex v1 0 0 0
+vertex v2 1 0 0
+vertex v3 1 1 0
+vertex v4 0 1 0
+edge e1 v1 v2
+edge e2 v3 v2
+edge e3 v3 v4
+edge e4 v1 v4
+
+compound e1 e2 e3 e4 edges
+edgestowire result edges
+
+if {![regexp "WIRE" [whatis result]]} {
+  puts "Error: Wire is not created"
+}
+
+explode result
+
+if {![regexp "FORWARD" [whatis result_1]]} {
+  puts "Error: Incorrect orientation of edges in wire"
+}
+
+if {![regexp "REVERSED" [whatis result_2]]} {
+  puts "Error: Incorrect orientation of edges in wire"
+}
+
+if {![regexp "FORWARD" [whatis result_3]]} {
+  puts "Error: Incorrect orientation of edges in wire"
+}
+
+if {![regexp "REVERSED" [whatis result_4]]} {
+  puts "Error: Incorrect orientation of edges in wire"
+}
diff --git a/tests/bugs/modalg_6/bug28189_7 b/tests/bugs/modalg_6/bug28189_7
new file mode 100644 (file)
index 0000000..5fad480
--- /dev/null
@@ -0,0 +1,27 @@
+puts "========"
+puts "OCC28189"
+puts "========"
+puts ""
+#################################################
+# Result of Boolean operation is non-manifold wire
+#################################################
+
+polyline p1 0 0 0 1 0 0
+polyline p2 0 0 0 1 0 0
+
+orientation p1 R
+orientation p2 F
+
+bfuse result1 p1 p2
+explode result1
+
+if {![regexp "REVERSED" [whatis result1_1]]} {
+  puts "Error: Incorrect orientation of wire"
+}
+
+bcommon result2 p2 p1
+explode result2
+
+if {![regexp "FORWARD" [whatis result2_1]]} {
+  puts "Error: Incorrect orientation of wire"
+}
diff --git a/tests/bugs/modalg_6/bug28189_8 b/tests/bugs/modalg_6/bug28189_8
new file mode 100644 (file)
index 0000000..08e860c
--- /dev/null
@@ -0,0 +1,17 @@
+puts "========"
+puts "OCC28189"
+puts "========"
+puts ""
+#################################################
+# Result of Boolean operation is non-manifold wire
+#################################################
+
+box b1 10 10 10
+box b2 5 5 5 10 10 10
+shape c1 Cs
+shape c2 Cs
+add b1 c1
+add b2 c2
+
+bfuse result c1 c2
+checknbshapes result -compsolid 1 -solid 1
diff --git a/tests/bugs/modalg_6/bug28189_9 b/tests/bugs/modalg_6/bug28189_9
new file mode 100644 (file)
index 0000000..9a1de7b
--- /dev/null
@@ -0,0 +1,40 @@
+puts "========"
+puts "OCC28189"
+puts "========"
+puts ""
+#################################################
+# Result of Boolean operation is non-manifold wire
+#################################################
+
+box b1 10 10 10
+box b2 5 5 5 10 10 10
+box b3 20 0 0 10 10 10
+box b4 25 5 5 10 10 10
+shape c1 Cs
+shape c2 Cs
+add b1 c1
+add b2 c2
+
+bclearobjects
+bcleartools
+baddobjects c1 b3
+baddtools c2 b4
+bfillds
+bbop result 1
+
+checknbshapes result -solid 2 -compsolid 1
+
+explode result
+
+if {[regexp "COMPSOLID" [whatis result_1]]} {
+  if {![regexp "SOLID" [whatis result_2]]} {
+    puts "Error: Incorrect shape types in the result"
+  }
+} elseif {[regexp "SOLID" [whatis result_1]]} {
+  if {![regexp "COMPSOLID" [whatis result_2]]} {
+    puts "Error: Incorrect shape types in the result"
+  }
+} else {
+  puts "Error: Incorrect shape types in the result"
+}
+