1 // Created by: Peter KURNEV
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
16 #include <BOPAlgo_BOP.hxx>
17 #include <BOPAlgo_BuilderSolid.hxx>
18 #include <BOPAlgo_PaveFiller.hxx>
19 #include <BOPAlgo_Alerts.hxx>
20 #include <BOPCol_DataMapOfShapeShape.hxx>
21 #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
22 #include <BOPCol_IndexedMapOfShape.hxx>
23 #include <BOPCol_ListOfShape.hxx>
24 #include <BOPCol_MapOfShape.hxx>
25 #include <BOPDS_DS.hxx>
26 #include <BOPTools.hxx>
27 #include <BOPTools_AlgoTools.hxx>
28 #include <BOPTools_AlgoTools3D.hxx>
29 #include <BOPTools_Set.hxx>
30 #include <BOPTools_SetMapHasher.hxx>
31 #include <BRep_Builder.hxx>
32 #include <BRep_Tool.hxx>
33 #include <NCollection_DataMap.hxx>
34 #include <TopAbs_ShapeEnum.hxx>
35 #include <TopExp_Explorer.hxx>
36 #include <TopoDS_Compound.hxx>
37 #include <TopoDS_Edge.hxx>
38 #include <TopoDS_Iterator.hxx>
39 #include <TopoDS_Shape.hxx>
41 typedef NCollection_IndexedDataMap
44 BOPTools_SetMapHasher> BOPTools_IndexedDataMapOfSetShape;
47 TopAbs_ShapeEnum TypeToExplore(const Standard_Integer theDim);
50 void CollectContainers(const TopoDS_Shape& theS,
51 BOPCol_ListOfShape& theLSC);
54 void RemoveDuplicates(BOPCol_ListOfShape& theContainers);
57 void RemoveDuplicates(BOPCol_ListOfShape& theContainers,
58 const TopAbs_ShapeEnum theType);
61 Standard_Integer NbCommonItemsInMap(const BOPCol_MapOfShape& theM1,
62 const BOPCol_MapOfShape& theM2);
65 void MapFacesToBuildSolids(const TopoDS_Shape& theSol,
66 BOPCol_IndexedDataMapOfShapeListOfShape& theMFS,
67 BOPCol_IndexedMapOfShape& theMFI);
69 //=======================================================================
72 //=======================================================================
73 BOPAlgo_BOP::BOPAlgo_BOP()
74 : BOPAlgo_ToolsProvider()
78 //=======================================================================
81 //=======================================================================
82 BOPAlgo_BOP::BOPAlgo_BOP(const Handle(NCollection_BaseAllocator)& theAllocator)
83 : BOPAlgo_ToolsProvider(theAllocator)
87 //=======================================================================
90 //=======================================================================
91 BOPAlgo_BOP::~BOPAlgo_BOP()
94 //=======================================================================
97 //=======================================================================
98 void BOPAlgo_BOP::Clear()
100 myOperation=BOPAlgo_UNKNOWN;
104 BOPAlgo_ToolsProvider::Clear();
106 //=======================================================================
107 //function : SetOperation
109 //=======================================================================
110 void BOPAlgo_BOP::SetOperation(const BOPAlgo_Operation theOperation)
112 myOperation=theOperation;
114 //=======================================================================
115 //function : Operation
117 //=======================================================================
118 BOPAlgo_Operation BOPAlgo_BOP::Operation()const
122 //=======================================================================
123 //function : CheckData
125 //=======================================================================
126 void BOPAlgo_BOP::CheckData()
128 Standard_Integer i, j, iDim, aNbArgs, aNbTools;
129 Standard_Boolean bFuse;
130 BOPCol_ListIteratorOfListOfShape aItLS;
132 if (!(myOperation==BOPAlgo_COMMON ||
133 myOperation==BOPAlgo_FUSE ||
134 myOperation==BOPAlgo_CUT||
135 myOperation==BOPAlgo_CUT21)) {
136 // non-licit operation
137 AddError (new BOPAlgo_AlertBOPNotSet);
141 aNbArgs=myArguments.Extent();
143 // invalid number of Arguments
144 AddError (new BOPAlgo_AlertTooFewArguments);
148 aNbTools=myTools.Extent();
150 // invalid number of Tools
151 AddError (new BOPAlgo_AlertTooFewArguments);
160 bFuse = (myOperation == BOPAlgo_FUSE);
162 // The rules for different types of operations are the following:
163 // 1. FUSE: All arguments and tools should have the same dimension;
164 // 2. CUT: The MAXIMAL dimension of the ARGUMENTS should be less
165 // or equal to the MINIMAL dimension of the TOOLS;
166 // 3. CUT21: The MINIMAL dimension of ARGUMENTS should be grater
167 // or equal to the MAXIMAL dimension of the TOOLS;
168 // 4. COMMON: The arguments and tools could have any dimensions.
170 Standard_Integer iDimMin[2], iDimMax[2];
171 Standard_Boolean bHasValid[2] = {Standard_False, Standard_False};
173 for (i=0; i<2; ++i) {
174 const BOPCol_ListOfShape& aLS=(!i)? myArguments : myTools;
175 aItLS.Initialize(aLS);
176 for (j=0; aItLS.More(); aItLS.Next(), ++j) {
177 const TopoDS_Shape& aS=aItLS.Value();
178 Standard_Boolean bIsEmpty = BOPTools_AlgoTools3D::IsEmptyShape(aS);
180 AddWarning(new BOPAlgo_AlertEmptyShape (aS));
184 iDim = BOPTools_AlgoTools::Dimension(aS);
186 // non-homogeneous argument
187 AddError (new BOPAlgo_AlertBOPNotAllowed);
191 bHasValid[i] = Standard_True;
199 if (iDim < iDimMin[i]) {
202 else if (iDim > iDimMax[i]) {
206 if (bFuse && (iDimMin[i] != iDimMax[i])) {
207 // non-homogeneous argument
208 AddError (new BOPAlgo_AlertBOPNotAllowed);
214 if (bHasValid[0] && bHasValid[1]) {
215 if (((myOperation == BOPAlgo_FUSE) && (iDimMax[0] != iDimMax[1])) ||
216 ((myOperation == BOPAlgo_CUT) && (iDimMax[0] > iDimMin[1])) ||
217 ((myOperation == BOPAlgo_CUT21) && (iDimMin[0] < iDimMax[1])) )
219 // non-licit operation for the arguments
220 AddError (new BOPAlgo_AlertBOPNotAllowed);
223 myDims[0] = iDimMin[0];
224 myDims[1] = iDimMin[1];
227 //=======================================================================
228 //function : TreatEmtpyShape
230 //=======================================================================
231 Standard_Boolean BOPAlgo_BOP::TreatEmptyShape()
233 if (! GetReport()->HasAlert (STANDARD_TYPE(BOPAlgo_AlertEmptyShape)))
235 return Standard_False;
238 // Find non-empty objects
239 BOPCol_ListOfShape aLValidObjs;
240 BOPCol_ListIteratorOfListOfShape aItLS(myArguments);
241 for (; aItLS.More(); aItLS.Next()) {
242 if (!BOPTools_AlgoTools3D::IsEmptyShape(aItLS.Value())) {
243 aLValidObjs.Append(aItLS.Value());
247 // Find non-empty tools
248 BOPCol_ListOfShape aLValidTools;
249 aItLS.Initialize(myTools);
250 for (; aItLS.More() ; aItLS.Next()) {
251 if (!BOPTools_AlgoTools3D::IsEmptyShape(aItLS.Value())) {
252 aLValidTools.Append(aItLS.Value());
256 Standard_Boolean bHasValidObj = (aLValidObjs .Extent() > 0);
257 Standard_Boolean bHasValidTool = (aLValidTools.Extent() > 0);
259 if (bHasValidObj && bHasValidTool) {
260 // We need to continue the operation to obtain the result
261 return Standard_False;
264 if (!bHasValidObj && !bHasValidTool) {
265 // All shapes are empty shapes, the result will always be empty shape
266 return Standard_True;
269 // One of the groups of arguments consists of empty shapes only,
270 // so we can build the result of operation right away just by
271 // choosing the list of shapes to add to result, depending on
272 // the type of the operation
273 BOPCol_ListOfShape *pLResult = NULL;
275 switch (myOperation) {
277 // Add not empty shapes into result
278 pLResult = bHasValidObj ? &aLValidObjs : &aLValidTools;
281 // Add objects into result
282 pLResult = &aLValidObjs;
285 // Add tools into result
286 pLResult = &aLValidTools;
289 // Common will be empty
296 aItLS.Initialize(*pLResult);
297 for (; aItLS.More(); aItLS.Next()) {
298 BRep_Builder().Add(myShape, aItLS.Value());
301 return Standard_True;
303 //=======================================================================
304 //function : BuildResult
306 //=======================================================================
307 void BOPAlgo_BOP::BuildResult(const TopAbs_ShapeEnum theType)
309 TopAbs_ShapeEnum aType;
311 BOPCol_MapOfShape aM;
312 BOPCol_ListIteratorOfListOfShape aIt, aItIm;
314 const BOPCol_ListOfShape& aLA=myDS->Arguments();
316 for (; aIt.More(); aIt.Next()) {
317 const TopoDS_Shape& aS=aIt.Value();
318 aType=aS.ShapeType();
319 if (aType==theType) {
320 if (myImages.IsBound(aS)){
321 const BOPCol_ListOfShape& aLSIm=myImages.Find(aS);
322 aItIm.Initialize(aLSIm);
323 for (; aItIm.More(); aItIm.Next()) {
324 const TopoDS_Shape& aSIm=aItIm.Value();
326 aBB.Add(myShape, aSIm);
332 aBB.Add(myShape, aS);
338 //=======================================================================
341 //=======================================================================
342 void BOPAlgo_BOP::Perform()
344 Handle(NCollection_BaseAllocator) aAllocator;
345 BOPAlgo_PaveFiller* pPF;
346 BOPCol_ListIteratorOfListOfShape aItLS;
348 GetReport()->Clear();
350 if (myEntryPoint==1) {
358 NCollection_BaseAllocator::CommonBaseAllocator();
359 BOPCol_ListOfShape aLS(aAllocator);
361 aItLS.Initialize(myArguments);
362 for (; aItLS.More(); aItLS.Next()) {
363 const TopoDS_Shape& aS=aItLS.Value();
367 aItLS.Initialize(myTools);
368 for (; aItLS.More(); aItLS.Next()) {
369 const TopoDS_Shape& aS=aItLS.Value();
373 pPF=new BOPAlgo_PaveFiller(aAllocator);
374 pPF->SetArguments(aLS);
375 pPF->SetRunParallel(myRunParallel);
376 pPF->SetProgressIndicator(myProgressIndicator);
377 pPF->SetFuzzyValue(myFuzzyValue);
378 pPF->SetNonDestructive(myNonDestructive);
379 pPF->SetGlue(myGlue);
384 PerformInternal(*pPF);
386 //=======================================================================
387 //function : PerformInternal1
389 //=======================================================================
390 void BOPAlgo_BOP::PerformInternal1(const BOPAlgo_PaveFiller& theFiller)
392 myPaveFiller=(BOPAlgo_PaveFiller*)&theFiller;
393 myDS=myPaveFiller->PDS();
394 myContext=myPaveFiller->Context();
395 myFuzzyValue = myPaveFiller->FuzzyValue();
396 myNonDestructive = myPaveFiller->NonDestructive();
410 if (GetReport()->HasAlert (STANDARD_TYPE(BOPAlgo_AlertEmptyShape)))
412 Standard_Boolean bDone = TreatEmptyShape();
420 FillImagesVertices();
425 BuildResult(TopAbs_VERTEX);
435 BuildResult(TopAbs_EDGE);
441 FillImagesContainers(TopAbs_WIRE);
446 BuildResult(TopAbs_WIRE);
457 BuildResult(TopAbs_FACE);
463 FillImagesContainers(TopAbs_SHELL);
468 BuildResult(TopAbs_SHELL);
479 BuildResult(TopAbs_SOLID);
485 FillImagesContainers(TopAbs_COMPSOLID);
490 BuildResult(TopAbs_COMPSOLID);
496 FillImagesCompounds();
501 BuildResult(TopAbs_COMPOUND);
518 //=======================================================================
521 //=======================================================================
522 void BOPAlgo_BOP::BuildRC()
524 TopAbs_ShapeEnum aType;
528 aBB.MakeCompound(aC);
531 if (myOperation == BOPAlgo_FUSE) {
532 BOPCol_MapOfShape aMFence;
533 aType = TypeToExplore(myDims[0]);
534 TopExp_Explorer aExp(myShape, aType);
535 for (; aExp.More(); aExp.Next()) {
536 const TopoDS_Shape& aS = aExp.Current();
537 if (aMFence.Add(aS)) {
545 // B. Common, Cut, Cut21
547 Standard_Integer i, j, aNb, iDim;
548 Standard_Boolean bCheckEdges, bContains, bCut21, bCommon;
549 BOPCol_ListIteratorOfListOfShape aItLS;
551 // prepare the building elements of arguments to get its splits
552 BOPCol_IndexedMapOfShape aMArgs, aMTools;
553 for (i = 0; i < 2; ++i) {
554 const BOPCol_ListOfShape& aLS = !i ? myArguments : myTools;
555 BOPCol_IndexedMapOfShape& aMS = !i ? aMArgs : aMTools;
556 aItLS.Initialize(aLS);
557 for (; aItLS.More(); aItLS.Next()) {
558 const TopoDS_Shape& aS = aItLS.Value();
559 iDim = BOPTools_AlgoTools::Dimension(aS);
563 aType = TypeToExplore(iDim);
564 BOPTools::MapShapes(aS, aType, aMS);
568 bCheckEdges = Standard_False;
570 // get splits of building elements
571 BOPCol_IndexedMapOfShape aMArgsIm, aMToolsIm;
572 BOPTools_IndexedDataMapOfSetShape aMSetArgs, aMSetTools;
574 for (i = 0; i < 2; ++i) {
575 const BOPCol_IndexedMapOfShape& aMS = !i ? aMArgs : aMTools;
576 BOPCol_IndexedMapOfShape& aMSIm = !i ? aMArgsIm : aMToolsIm;
577 BOPTools_IndexedDataMapOfSetShape& aMSet = !i ? aMSetArgs : aMSetTools;
580 for (j = 1; j <= aNb; ++j) {
581 const TopoDS_Shape& aS = aMS(j);
582 aType = aS.ShapeType();
583 if (aType == TopAbs_EDGE) {
584 const TopoDS_Edge& aE = *(TopoDS_Edge*)&aS;
585 bCheckEdges = Standard_True;
586 if (BRep_Tool::Degenerated(aE)) {
591 if (myImages.IsBound(aS)) {
592 const BOPCol_ListOfShape& aLSIm = myImages.Find(aS);
593 aItLS.Initialize(aLSIm);
594 for (; aItLS.More(); aItLS.Next()) {
595 const TopoDS_Shape& aSIm = aItLS.Value();
601 if (aS.ShapeType() == TopAbs_SOLID) {
603 aST.Add(aS, TopAbs_FACE);
604 if (!aMSet.Contains(aST)) {
612 // compare the maps and make the result
614 Standard_Integer iDimMin, iDimMax;
616 iDimMin = Min(myDims[0], myDims[1]);
617 bCommon = (myOperation == BOPAlgo_COMMON);
618 bCut21 = (myOperation == BOPAlgo_CUT21);
620 const BOPCol_IndexedMapOfShape& aMIt = bCut21 ? aMToolsIm : aMArgsIm;
621 const BOPCol_IndexedMapOfShape& aMCheck = bCut21 ? aMArgsIm : aMToolsIm;
622 const BOPTools_IndexedDataMapOfSetShape& aMSetCheck = bCut21 ? aMSetArgs : aMSetTools;
624 BOPCol_IndexedMapOfShape aMCheckExp, aMItExp;
628 for (i = 1; i <= aNb; ++i) {
629 const TopoDS_Shape& aS = aMIt(i);
630 iDimMax = BOPTools_AlgoTools::Dimension(aS);
631 for (iDim = iDimMin; iDim < iDimMax; ++iDim) {
632 aType = TypeToExplore(iDim);
633 BOPTools::MapShapes(aS, aType, aMItExp);
642 aNb = aMCheck.Extent();
643 for (i = 1; i <= aNb; ++i) {
644 const TopoDS_Shape& aS = aMCheck(i);
645 iDimMax = BOPTools_AlgoTools::Dimension(aS);
646 for (iDim = iDimMin; iDim < iDimMax; ++iDim) {
647 aType = TypeToExplore(iDim);
648 BOPTools::MapShapes(aS, aType, aMCheckExp);
653 aNb = aMItExp.Extent();
654 for (i = 1; i <= aNb; ++i) {
655 const TopoDS_Shape& aS = aMItExp(i);
657 bContains = aMCheckExp.Contains(aS);
658 if (!bContains && aS.ShapeType() == TopAbs_SOLID) {
660 aST.Add(aS, TopAbs_FACE);
661 bContains = aMSetCheck.Contains(aST);
676 // filter result for COMMON operation
678 BOPCol_MapOfShape aMFence;
679 TopExp_Explorer aExp;
681 aBB.MakeCompound(aCx);
683 for (iDim = 3; iDim >= iDimMin; --iDim) {
684 aType = TypeToExplore(iDim);
685 aExp.Init(aC, aType);
686 for (; aExp.More(); aExp.Next()) {
687 const TopoDS_Shape& aS = aExp.Current();
688 if (aMFence.Add(aS)) {
690 BOPTools::MapShapes(aS, aMFence);
702 // The squats around degenerated edges
703 Standard_Integer nVD;
704 BOPCol_IndexedMapOfShape aMVC;
707 BOPTools::MapShapes(aC, TopAbs_VERTEX, aMVC);
710 aNb = myDS->NbSourceShapes();
711 for (i = 0; i < aNb; ++i) {
712 const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
713 aType = aSI.ShapeType();
714 if (aType != TopAbs_EDGE) {
718 const TopoDS_Edge& aE = *((TopoDS_Edge*)&aSI.Shape());
719 if (!BRep_Tool::Degenerated(aE)) {
723 nVD = aSI.SubShapes().First();
724 const TopoDS_Shape& aVD = myDS->Shape(nVD);
726 if (!aMVC.Contains(aVD)) {
730 if (myDS->IsNewShape(nVD)) {
734 if (myDS->HasInterf(nVD)) {
743 //=======================================================================
744 //function : BuildShape
746 //=======================================================================
747 void BOPAlgo_BOP::BuildShape()
751 if ((myOperation == BOPAlgo_FUSE) && (myDims[0] == 3)) {
757 TopAbs_ShapeEnum aType, aT1, aT2;
758 BOPCol_ListOfShape aLSC, aLCB;
759 BOPCol_ListIteratorOfListOfShape aItLS, aItLSIm, aItLCB;
762 TopoDS_Shape aRC, aRCB;
764 BOPCol_MapOfShape aMSRC;
765 BOPTools::MapShapes(myRC, aMSRC);
767 // collect images of containers
768 for (i = 0; i < 2; ++i) {
769 const BOPCol_ListOfShape& aLS = !i ? myArguments : myTools;
771 aItLS.Initialize(aLS);
772 for (; aItLS.More(); aItLS.Next()) {
773 const TopoDS_Shape& aS = aItLS.Value();
775 CollectContainers(aS, aLSC);
779 BOPCol_ListOfShape aLCRes;
780 aItLS.Initialize(aLSC);
781 for (; aItLS.More(); aItLS.Next()) {
782 const TopoDS_Shape& aSC = aItLS.Value();
784 BOPTools_AlgoTools::MakeContainer(TopAbs_COMPOUND, aRC);
787 for (; aIt.More(); aIt.Next()) {
788 const TopoDS_Shape& aS = aIt.Value();
789 if (myImages.IsBound(aS)) {
790 const BOPCol_ListOfShape& aLSIm = myImages.Find(aS);
792 aItLSIm.Initialize(aLSIm);
793 for (; aItLSIm.More(); aItLSIm.Next()) {
794 const TopoDS_Shape& aSIm = aItLSIm.Value();
795 if (aMSRC.Contains(aSIm)) {
800 else if (aMSRC.Contains(aS)) {
805 aType = aSC.ShapeType();
824 BOPTools_AlgoTools::MakeConnexityBlocks(aRC, aT1, aT2, aLCB);
825 if (aLCB.IsEmpty()) {
829 aItLCB.Initialize(aLCB);
830 for (; aItLCB.More(); aItLCB.Next()) {
831 BOPTools_AlgoTools::MakeContainer(aType, aRCB);
833 const TopoDS_Shape& aCB = aItLCB.Value();
835 for (; aIt.More(); aIt.Next()) {
836 const TopoDS_Shape& aCBS = aIt.Value();
840 if (aType == TopAbs_WIRE) {
842 BOPTools_AlgoTools::OrientEdgesOnWire(aRCB);
844 else if (aType == TopAbs_SHELL) {
845 BOPTools_AlgoTools::OrientFacesOnShell(aRCB);
848 aRCB.Orientation(aSC.Orientation());
854 RemoveDuplicates(aLCRes);
856 // add containers to result
857 TopoDS_Compound aResult;
858 aBB.MakeCompound(aResult);
860 aItLS.Initialize(aLCRes);
861 for (; aItLS.More(); aItLS.Next()) {
862 aBB.Add(aResult, aItLS.Value());
865 // add the rest of the shapes into result
866 BOPCol_MapOfShape aMSResult;
867 BOPTools::MapShapes(aResult, aMSResult);
869 aIt.Initialize(myRC);
870 for (; aIt.More(); aIt.Next()) {
871 const TopoDS_Shape& aS = aIt.Value();
872 if (aMSResult.Add(aS)) {
873 aBB.Add(aResult, aS);
879 //=======================================================================
880 //function : BuildSolid
882 //=======================================================================
883 void BOPAlgo_BOP::BuildSolid()
886 BOPCol_ListOfShape aLSC;
888 BOPCol_ListIteratorOfListOfShape aItLS;
889 TopExp_Explorer aExp;
892 // Get solids from input arguments
893 BOPCol_MapOfShape aMSA;
894 // Map the arguments to find shared faces
895 BOPCol_IndexedDataMapOfShapeListOfShape aMFS;
896 for (Standard_Integer i = 0; i < 2; ++i) {
897 const BOPCol_ListOfShape& aLSA = (i) ? myArguments : myTools;
898 aItLS.Initialize(aLSA);
899 for (; aItLS.More(); aItLS.Next()) {
900 const TopoDS_Shape& aSA = aItLS.Value();
901 aExp.Init(aSA, TopAbs_SOLID);
902 for (; aExp.More(); aExp.Next()) {
903 const TopoDS_Shape& aSol = aExp.Current();
905 BOPTools::MapShapesAndAncestors(aSol, TopAbs_FACE, TopAbs_SOLID, aMFS);
908 // get Compsolids from input arguments
909 CollectContainers(aSA, aLSC);
913 // Find solids in input arguments sharing faces with other solids
914 BOPCol_MapOfShape aMTSols;
915 Standard_Integer i, aNb = aMFS.Extent();
916 for (i = 1; i < aNb; ++i) {
917 const BOPCol_ListOfShape& aLSols = aMFS(i);
918 if (aLSols.Extent() > 1) {
919 aItLS.Initialize(aLSols);
920 for(; aItLS.More(); aItLS.Next()) {
921 aMTSols.Add(aItLS.Value());
926 // Possibly untouched solids - to be added to results as is
927 BOPCol_IndexedMapOfShape aMUSols;
928 // Use map to chose the most outer faces to build result solids
931 BOPCol_IndexedMapOfShape aMFI;
933 TopoDS_Iterator aIt(myRC);
934 for (; aIt.More(); aIt.Next()) {
935 const TopoDS_Shape& aSx = aIt.Value();
936 if (aMSA.Contains(aSx)) {
937 if (!aMTSols.Contains(aSx)) {
943 MapFacesToBuildSolids(aSx, aMFS, aMFI);
944 } // for (; aIt.More(); aIt.Next()) {
946 // Process possibly untouched solids.
947 // Really untouched solids will be added into result as is.
948 // Others will be processed by BuilderSolid.
949 BOPTools_IndexedDataMapOfSetShape aDMSTS;
951 aNb = aMUSols.Extent();
952 for (i = 1; i <= aNb; ++i) {
953 const TopoDS_Shape& aSx = aMUSols(i);
955 aExp.Init(aSx, TopAbs_FACE);
956 for (; aExp.More(); aExp.Next()) {
957 if (aMFS.Contains(aExp.Current())) {
963 MapFacesToBuildSolids(aSx, aMFS, aMFI);
967 aST.Add(aSx, TopAbs_FACE);
968 if (!aDMSTS.Contains(aST)) {
969 aDMSTS.Add(aST, aSx);
974 BOPCol_IndexedDataMapOfShapeListOfShape aMEF;
975 // Split faces will be added in the end
976 // to avoid errors in BuilderSolid algorithm
977 BOPCol_ListOfShape aLF, aLFx;
979 for (i = 1; i <= aNb; ++i) {
980 const BOPCol_ListOfShape& aLSx = aMFS(i);
981 if (aLSx.Extent() == 1) {
982 const TopoDS_Shape& aFx = aMFS.FindKey(i);
983 BOPTools::MapShapesAndAncestors(aFx, TopAbs_EDGE, TopAbs_FACE, aMEF);
984 if (IsBoundSplits(aFx, aMEF)){
992 // Faces to build result solids
993 BOPCol_ListOfShape aSFS;
994 aItLS.Initialize(aLF);
995 for(; aItLS.More(); aItLS.Next()) {
996 const TopoDS_Shape& aFx = aItLS.Value();
1001 aItLS.Initialize(aLFx);
1002 for (; aItLS.More(); aItLS.Next()) {
1003 const TopoDS_Shape& aFx = aItLS.Value();
1008 aNb = aMFI.Extent();
1009 for (i = 1; i <= aNb; ++i) {
1010 TopoDS_Shape aFx = aMFI.FindKey(i);
1011 aSFS.Append(aFx.Oriented(TopAbs_FORWARD));
1012 aSFS.Append(aFx.Oriented(TopAbs_REVERSED));
1016 BOPTools_AlgoTools::MakeContainer(TopAbs_COMPOUND, aRC);
1017 if (aSFS.Extent()) {
1018 // Build solids from set of faces
1019 BOPAlgo_BuilderSolid aSB;
1020 aSB.SetContext(myContext);
1021 aSB.SetShapes(aSFS);
1023 if (aSB.HasErrors()) {
1024 AddError (new BOPAlgo_AlertSolidBuilderFailed); // SolidBuilder failed
1028 const BOPCol_ListOfShape& aLSR = aSB.Areas();
1030 // add new solids to result
1031 aItLS.Initialize(aLSR);
1032 for (; aItLS.More(); aItLS.Next()) {
1033 const TopoDS_Shape& aSR = aItLS.Value();
1038 // add untouched solids to result
1039 aNb = aDMSTS.Extent();
1040 for (i = 1; i <= aNb; ++i) {
1041 const TopoDS_Shape& aSx = aDMSTS(i);
1045 if (aLSC.IsEmpty()) {
1046 // no Compsolids in arguments
1051 // build new Compsolids from new solids containing splits
1052 // of faces from arguments of type Compsolid
1054 TopoDS_Shape aResult;
1055 BOPTools_AlgoTools::MakeContainer(TopAbs_COMPOUND, aResult);
1057 aIt.Initialize(aRC);
1059 // no solids in the result
1064 const TopoDS_Shape& aSol1 = aIt.Value();
1067 // optimization for one solid in the result
1070 BOPTools_AlgoTools::MakeContainer(TopAbs_COMPSOLID, aCS);
1071 aBB.Add(aCS, aSol1);
1073 aBB.Add(aResult, aCS);
1078 // get splits of faces of the Compsolid arguments
1079 BOPCol_MapOfShape aMFCs;
1080 aItLS.Initialize(aLSC);
1081 for (; aItLS.More(); aItLS.Next()) {
1082 const TopoDS_Shape& aCs = aItLS.Value();
1083 aExp.Init(aCs, TopAbs_FACE);
1084 for (; aExp.More(); aExp.Next()) {
1085 const TopoDS_Shape& aF = aExp.Current();
1086 const BOPCol_ListOfShape* pLFIm = myImages.Seek(aF);
1091 BOPCol_ListIteratorOfListOfShape aItLFIm(*pLFIm);
1092 for (; aItLFIm.More(); aItLFIm.Next()) {
1093 aMFCs.Add(aItLFIm.Value());
1099 // build connexity blocks from new solids
1100 BOPCol_ListOfShape aLCBS;
1101 BOPTools_AlgoTools::MakeConnexityBlocks(aRC, TopAbs_FACE, TopAbs_SOLID, aLCBS);
1103 aItLS.Initialize(aLCBS);
1104 for (; aItLS.More(); aItLS.Next()) {
1105 const TopoDS_Shape& aCB = aItLS.Value();
1107 // check if the Compsolid should be created
1108 aExp.Init(aCB, TopAbs_FACE);
1109 for (; aExp.More(); aExp.Next()) {
1110 if (aMFCs.Contains(aExp.Current())) {
1116 // add solids directly into result as their origins are not Compsolids
1117 for (aIt.Initialize(aCB); aIt.More(); aIt.Next()) {
1118 aBB.Add(aResult, aIt.Value());
1125 BOPTools_AlgoTools::MakeContainer(TopAbs_COMPSOLID, aCS);
1127 aIt.Initialize(aCB);
1128 for (; aIt.More(); aIt.Next()) {
1129 aBB.Add(aCS, aIt.Value());
1132 aBB.Add(aResult, aCS);
1137 //=======================================================================
1138 //function : IsBoundSplits
1140 //=======================================================================
1141 Standard_Boolean BOPAlgo_BOP::IsBoundSplits
1142 (const TopoDS_Shape& aS,
1143 BOPCol_IndexedDataMapOfShapeListOfShape& aMEF)
1145 Standard_Boolean bRet = Standard_False;
1146 if (mySplits.IsBound(aS) || myOrigins.IsBound(aS)) {
1150 BOPCol_ListIteratorOfListOfShape aIt;
1151 Standard_Integer aNbLS;
1152 TopAbs_Orientation anOr;
1154 //check face aF may be connected to face from mySplits
1155 TopExp_Explorer aExp(aS, TopAbs_EDGE);
1156 for (; aExp.More(); aExp.Next()) {
1157 const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aExp.Current()));
1159 anOr = aE.Orientation();
1160 if (anOr==TopAbs_INTERNAL) {
1164 if (BRep_Tool::Degenerated(aE)) {
1168 const BOPCol_ListOfShape& aLS=aMEF.FindFromKey(aE);
1169 aNbLS = aLS.Extent();
1174 aIt.Initialize(aLS);
1175 for (; aIt.More(); aIt.Next()) {
1176 const TopoDS_Shape& aSx = aIt.Value();
1177 if (mySplits.IsBound(aSx) || myOrigins.IsBound(aS)) {
1185 //=======================================================================
1186 //function : TypeToExplore
1188 //=======================================================================
1189 TopAbs_ShapeEnum TypeToExplore(const Standard_Integer theDim)
1191 TopAbs_ShapeEnum aRet;
1212 //=======================================================================
1213 //function : CollectContainers
1215 //=======================================================================
1216 void CollectContainers(const TopoDS_Shape& theS,
1217 BOPCol_ListOfShape& theLSC)
1219 TopAbs_ShapeEnum aType = theS.ShapeType();
1220 if (aType == TopAbs_WIRE ||
1221 aType == TopAbs_SHELL ||
1222 aType == TopAbs_COMPSOLID) {
1223 theLSC.Append(theS);
1227 if (aType != TopAbs_COMPOUND) {
1231 TopoDS_Iterator aIt(theS);
1232 for (; aIt.More(); aIt.Next()) {
1233 const TopoDS_Shape& aS = aIt.Value();
1234 CollectContainers(aS, theLSC);
1238 //=======================================================================
1239 //function : RemoveDuplicates
1240 //purpose : Filters the containers with identical contents
1241 //=======================================================================
1242 void RemoveDuplicates(BOPCol_ListOfShape& theContainers)
1244 RemoveDuplicates(theContainers, TopAbs_WIRE);
1245 RemoveDuplicates(theContainers, TopAbs_SHELL);
1246 RemoveDuplicates(theContainers, TopAbs_COMPSOLID);
1249 //=======================================================================
1250 //function : RemoveDuplicates
1251 //purpose : Filters the containers of given type with identical contents
1252 //=======================================================================
1253 void RemoveDuplicates(BOPCol_ListOfShape& theContainers,
1254 const TopAbs_ShapeEnum theType)
1256 // get containers of given type
1257 BOPCol_ListOfShape aLC;
1258 BOPCol_ListIteratorOfListOfShape aItLC(theContainers);
1259 for (; aItLC.More(); aItLC.Next()) {
1260 const TopoDS_Shape& aC = aItLC.Value();
1261 if (aC.ShapeType() == theType) {
1266 if (aLC.IsEmpty()) {
1270 // map containers to compare its contents
1271 NCollection_IndexedDataMap<TopoDS_Shape, BOPCol_MapOfShape> aContents;
1273 aItLC.Initialize(aLC);
1274 for (; aItLC.More(); aItLC.Next()) {
1275 const TopoDS_Shape& aC = aItLC.Value();
1277 BOPCol_MapOfShape& aMC = aContents(aContents.Add(aC, BOPCol_MapOfShape()));
1279 TopoDS_Iterator aIt(aC);
1280 for (; aIt.More(); aIt.Next()) {
1281 aMC.Add(aIt.Value());
1285 // compare the contents of the containers and find duplicates
1286 BOPCol_MapOfShape aDuplicates;
1288 Standard_Integer i, j, aNb = aContents.Extent();
1289 for (i = 1; i <= aNb; ++i) {
1290 const TopoDS_Shape& aCi = aContents.FindKey(i);
1291 if (aDuplicates.Contains(aCi)) {
1294 const BOPCol_MapOfShape& aMi = aContents(i);
1295 Standard_Integer aNbi = aMi.Extent();
1297 for (j = i + 1; j <= aNb; ++j) {
1298 const TopoDS_Shape& aCj = aContents.FindKey(j);
1299 if (aDuplicates.Contains(aCj)) {
1302 const BOPCol_MapOfShape& aMj = aContents(j);
1303 Standard_Integer aNbj = aMj.Extent();
1305 Standard_Integer aNbCommon = NbCommonItemsInMap(aMi, aMj);
1307 if (aNbj == aNbCommon) {
1308 aDuplicates.Add(aCj);
1312 if (aNbi == aNbCommon) {
1313 aDuplicates.Add(aCi);
1319 if (aDuplicates.IsEmpty()) {
1323 // remove duplicating containers
1324 aItLC.Initialize(theContainers);
1325 for (; aItLC.More(); ) {
1326 const TopoDS_Shape& aC = aItLC.Value();
1327 if (aDuplicates.Contains(aC)) {
1328 theContainers.Remove(aItLC);
1335 //=======================================================================
1336 //function : NbCommonItemsInMap
1337 //purpose : Counts the items contained in both maps
1338 //=======================================================================
1339 Standard_Integer NbCommonItemsInMap(const BOPCol_MapOfShape& theM1,
1340 const BOPCol_MapOfShape& theM2)
1342 const BOPCol_MapOfShape* aMap1 = &theM1;
1343 const BOPCol_MapOfShape* aMap2 = &theM2;
1345 if (theM2.Extent() < theM1.Extent()) {
1350 Standard_Integer iCommon = 0;
1351 for (BOPCol_MapIteratorOfMapOfShape aIt(*aMap1); aIt.More(); aIt.Next()) {
1352 if (aMap2->Contains(aIt.Value())) {
1358 //=======================================================================
1359 //function : MapFacesToBuildSolids
1360 //purpose : Stores the faces of the given solid into outgoing maps:
1361 // <theMFS> - not internal faces with reference to solid;
1362 // <theMFI> - internal faces.
1363 //=======================================================================
1364 void MapFacesToBuildSolids(const TopoDS_Shape& theSol,
1365 BOPCol_IndexedDataMapOfShapeListOfShape& theMFS,
1366 BOPCol_IndexedMapOfShape& theMFI)
1368 TopExp_Explorer aExp(theSol, TopAbs_FACE);
1369 for (; aExp.More(); aExp.Next()) {
1370 const TopoDS_Shape& aF = aExp.Current();
1372 if (aF.Orientation() == TopAbs_INTERNAL) {
1377 BOPCol_ListOfShape* pLSol = theMFS.ChangeSeek(aF);
1379 pLSol = &theMFS(theMFS.Add(aF, BOPCol_ListOfShape()));
1380 pLSol->Append(theSol);
1383 const TopoDS_Shape& aF1 = theMFS.FindKey(theMFS.FindIndex(aF));
1384 if (aF1.Orientation() != aF.Orientation()) {
1385 pLSol->Append(theSol);