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
* 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.
+@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
* 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
@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}
#include <TopoDS_Edge.hxx>
#include <TopoDS_Iterator.hxx>
#include <TopoDS_Shape.hxx>
-#include <TopTools_ListIteratorOfListOfShape.hxx>
typedef NCollection_IndexedDataMap
<BOPTools_Set,
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);
//=======================================================================
//
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);
//
}
}
// make containers
+ BOPCol_ListOfShape aLCRes;
aItLS.Initialize(aLSC);
for (; aItLS.More(); aItLS.Next()) {
const TopoDS_Shape& aSC = aItLS.Value();
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()) {
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);
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);
}
}
BOPAlgo_BuilderSolid aSB;
BOPCol_MapOfShape aMSA, aMZ;
BOPTools_IndexedDataMapOfSetShape aDMSTS;
+ BOPCol_ListOfShape aLSC;
//
myErrorStatus=0;
//
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();
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
}
}
+//=======================================================================
+//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;
+}
#include <BOPTest.hxx>
+#include <BOPTools_AlgoTools.hxx>
#include <BOPTools_AlgoTools2D.hxx>
#include <DBRep.hxx>
#include <IntTools_Context.hxx>
#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**);
//=======================================================================
// Commands
theCommands.Add("attachpcurve", "attachpcurve eold enew face", __FILE__, attachpcurve, group);
+ theCommands.Add("edgestowire" , "edgestowire wire edges" , __FILE__, edgestowire , group);
}
//=======================================================================
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;
+}
#include <BOPCol_IndexedMapOfShape.hxx>
#include <BOPCol_MapOfShape.hxx>
+#include <BOPCol_MapOfOrientedShape.hxx>
#include <BOPTools.hxx>
#include <BOPTools_AlgoTools.hxx>
#include <BOPTools_AlgoTools2D.hxx>
#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>
}// 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:
//=======================================================================
//! 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>
bcommon result b a
-checkprops result -l 691.95
+checkprops result -l 345.975
checksection result
checknbshapes result -vertex 8 -edge 7 -t
bcommon result b a
-checkprops result -l 691.95
+checkprops result -l 345.975
checksection result
checknbshapes result -vertex 14 -edge 13 -t
bcommon result b a
-checkprops result -l 132.732
+checkprops result -l 66.3661
checksection result
checknbshapes result -vertex 2 -edge 1 -t
bcommon result b a
-checkprops result -l 287.575
+checkprops result -l 143.787
checksection result
checknbshapes result -vertex 2 -edge 1 -t
bcommon result b a
-checkprops result -l 287.575
+checkprops result -l 143.787
checksection result
checknbshapes result -vertex 2 -edge 1 -t
bcommon result b a
-checkprops result -l 159.8
+checkprops result -l 79.9002
checksection result
checknbshapes result -vertex 2 -edge 1 -t
bcommon result b a
-checkprops result -l 287.575
+checkprops result -l 143.787
checksection result
checknbshapes result -vertex 2 -edge 1 -t
bop a b
bopcommon result
-checkprops result -l 691.95
+checkprops result -l 345.975
checksection result
checknbshapes result -vertex 8 -edge 7 -t
bop a b
bopcommon result
-checkprops result -l 691.95
+checkprops result -l 345.975
checksection result
checknbshapes result -vertex 14 -edge 13 -t
bop a b
bopcommon result
-checkprops result -l 132.732
+checkprops result -l 66.3661
checksection result
checknbshapes result -vertex 2 -edge 1 -t
bop a b
bopcommon result
-checkprops result -l 287.575
+checkprops result -l 143.787
checksection result
checknbshapes result -vertex 2 -edge 1 -t
bop a b
bopcommon result
-checkprops result -l 287.575
+checkprops result -l 143.787
checksection result
checknbshapes result -vertex 2 -edge 1 -t
bop a b
bopcommon result
-checkprops result -l 159.8
+checkprops result -l 79.9002
checksection result
checknbshapes result -vertex 2 -edge 1 -t
bop a b
bopcommon result
-checkprops result -l 287.575
+checkprops result -l 143.787
checksection result
checknbshapes result -vertex 2 -edge 1 -t
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
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
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
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
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
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
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
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
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
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
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
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
-puts "TODO OCC12345 ALL: Faulty shapes in variables faulty_1 to faulty_"
puts "TODO OCC12345 ALL: Error : The area of result shape is"
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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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"
+}
--- /dev/null
+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"
+}
--- /dev/null
+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
--- /dev/null
+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"
+}
+