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_Tools.hxx>
20 #include <BOPAlgo_Alerts.hxx>
21 #include <BOPDS_DS.hxx>
22 #include <BOPTools_AlgoTools.hxx>
23 #include <BOPTools_AlgoTools3D.hxx>
24 #include <BOPTools_IndexedDataMapOfSetShape.hxx>
25 #include <BOPTools_Set.hxx>
26 #include <BOPTools_SetMapHasher.hxx>
27 #include <BRep_Builder.hxx>
28 #include <BRep_Tool.hxx>
29 #include <NCollection_DataMap.hxx>
30 #include <TopAbs_ShapeEnum.hxx>
32 #include <TopExp_Explorer.hxx>
33 #include <TopoDS_Compound.hxx>
34 #include <TopoDS_Edge.hxx>
35 #include <TopoDS_Iterator.hxx>
36 #include <TopoDS_Shape.hxx>
37 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
38 #include <TopTools_IndexedMapOfShape.hxx>
39 #include <TopTools_ListOfShape.hxx>
40 #include <TopTools_MapOfShape.hxx>
43 TopAbs_ShapeEnum TypeToExplore(const Standard_Integer theDim);
46 void CollectContainers(const TopoDS_Shape& theS,
47 TopTools_ListOfShape& theLSC);
50 void RemoveDuplicates(TopTools_ListOfShape& theContainers);
53 void RemoveDuplicates(TopTools_ListOfShape& theContainers,
54 const TopAbs_ShapeEnum theType);
57 Standard_Integer NbCommonItemsInMap(const TopTools_MapOfShape& theM1,
58 const TopTools_MapOfShape& theM2);
61 void MapFacesToBuildSolids(const TopoDS_Shape& theSol,
62 TopTools_IndexedDataMapOfShapeListOfShape& theMFS,
63 TopTools_IndexedMapOfShape& theMFI);
65 //=======================================================================
68 //=======================================================================
69 BOPAlgo_BOP::BOPAlgo_BOP()
70 : BOPAlgo_ToolsProvider()
74 //=======================================================================
77 //=======================================================================
78 BOPAlgo_BOP::BOPAlgo_BOP(const Handle(NCollection_BaseAllocator)& theAllocator)
79 : BOPAlgo_ToolsProvider(theAllocator)
83 //=======================================================================
86 //=======================================================================
87 BOPAlgo_BOP::~BOPAlgo_BOP()
90 //=======================================================================
93 //=======================================================================
94 void BOPAlgo_BOP::Clear()
96 myOperation=BOPAlgo_UNKNOWN;
100 BOPAlgo_ToolsProvider::Clear();
102 //=======================================================================
103 //function : SetOperation
105 //=======================================================================
106 void BOPAlgo_BOP::SetOperation(const BOPAlgo_Operation theOperation)
108 myOperation=theOperation;
110 //=======================================================================
111 //function : Operation
113 //=======================================================================
114 BOPAlgo_Operation BOPAlgo_BOP::Operation()const
118 //=======================================================================
119 //function : CheckData
121 //=======================================================================
122 void BOPAlgo_BOP::CheckData()
124 Standard_Integer i, j, iDim, aNbArgs, aNbTools;
125 Standard_Boolean bFuse;
126 TopTools_ListIteratorOfListOfShape aItLS;
128 if (!(myOperation==BOPAlgo_COMMON ||
129 myOperation==BOPAlgo_FUSE ||
130 myOperation==BOPAlgo_CUT||
131 myOperation==BOPAlgo_CUT21)) {
132 // non-licit operation
133 AddError (new BOPAlgo_AlertBOPNotSet);
137 aNbArgs=myArguments.Extent();
139 // invalid number of Arguments
140 AddError (new BOPAlgo_AlertTooFewArguments);
144 aNbTools=myTools.Extent();
146 // invalid number of Tools
147 AddError (new BOPAlgo_AlertTooFewArguments);
156 bFuse = (myOperation == BOPAlgo_FUSE);
158 // The rules for different types of operations are the following:
159 // 1. FUSE: All arguments and tools should have the same dimension;
160 // 2. CUT: The MAXIMAL dimension of the ARGUMENTS should be less
161 // or equal to the MINIMAL dimension of the TOOLS;
162 // 3. CUT21: The MINIMAL dimension of ARGUMENTS should be grater
163 // or equal to the MAXIMAL dimension of the TOOLS;
164 // 4. COMMON: The arguments and tools could have any dimensions.
166 Standard_Integer iDimMin[2], iDimMax[2];
167 Standard_Boolean bHasValid[2] = {Standard_False, Standard_False};
169 for (i=0; i<2; ++i) {
170 const TopTools_ListOfShape& aLS=(!i)? myArguments : myTools;
171 aItLS.Initialize(aLS);
172 for (j=0; aItLS.More(); aItLS.Next(), ++j) {
173 const TopoDS_Shape& aS=aItLS.Value();
174 Standard_Boolean bIsEmpty = BOPTools_AlgoTools3D::IsEmptyShape(aS);
176 AddWarning(new BOPAlgo_AlertEmptyShape (aS));
180 iDim = BOPTools_AlgoTools::Dimension(aS);
182 // non-homogeneous argument
183 AddError (new BOPAlgo_AlertBOPNotAllowed);
187 bHasValid[i] = Standard_True;
195 if (iDim < iDimMin[i]) {
198 else if (iDim > iDimMax[i]) {
202 if (bFuse && (iDimMin[i] != iDimMax[i])) {
203 // non-homogeneous argument
204 AddError (new BOPAlgo_AlertBOPNotAllowed);
210 if (bHasValid[0] && bHasValid[1]) {
211 if (((myOperation == BOPAlgo_FUSE) && (iDimMax[0] != iDimMax[1])) ||
212 ((myOperation == BOPAlgo_CUT) && (iDimMax[0] > iDimMin[1])) ||
213 ((myOperation == BOPAlgo_CUT21) && (iDimMin[0] < iDimMax[1])) )
215 // non-licit operation for the arguments
216 AddError (new BOPAlgo_AlertBOPNotAllowed);
219 myDims[0] = iDimMin[0];
220 myDims[1] = iDimMin[1];
223 //=======================================================================
224 //function : TreatEmtpyShape
226 //=======================================================================
227 Standard_Boolean BOPAlgo_BOP::TreatEmptyShape()
229 if (! GetReport()->HasAlert (STANDARD_TYPE(BOPAlgo_AlertEmptyShape)))
231 return Standard_False;
234 // Find non-empty objects
235 TopTools_ListOfShape aLValidObjs;
236 TopTools_ListIteratorOfListOfShape aItLS(myArguments);
237 for (; aItLS.More(); aItLS.Next()) {
238 if (!BOPTools_AlgoTools3D::IsEmptyShape(aItLS.Value())) {
239 aLValidObjs.Append(aItLS.Value());
243 // Find non-empty tools
244 TopTools_ListOfShape aLValidTools;
245 aItLS.Initialize(myTools);
246 for (; aItLS.More() ; aItLS.Next()) {
247 if (!BOPTools_AlgoTools3D::IsEmptyShape(aItLS.Value())) {
248 aLValidTools.Append(aItLS.Value());
252 Standard_Boolean bHasValidObj = (aLValidObjs .Extent() > 0);
253 Standard_Boolean bHasValidTool = (aLValidTools.Extent() > 0);
255 if (bHasValidObj && bHasValidTool) {
256 // We need to continue the operation to obtain the result
257 return Standard_False;
260 if (!bHasValidObj && !bHasValidTool) {
261 // All shapes are empty shapes, the result will always be empty shape
262 return Standard_True;
265 // One of the groups of arguments consists of empty shapes only,
266 // so we can build the result of operation right away just by
267 // choosing the list of shapes to add to result, depending on
268 // the type of the operation
269 TopTools_ListOfShape *pLResult = NULL;
271 switch (myOperation) {
273 // Add not empty shapes into result
274 pLResult = bHasValidObj ? &aLValidObjs : &aLValidTools;
277 // Add objects into result
278 pLResult = &aLValidObjs;
281 // Add tools into result
282 pLResult = &aLValidTools;
285 // Common will be empty
292 aItLS.Initialize(*pLResult);
293 for (; aItLS.More(); aItLS.Next()) {
294 BRep_Builder().Add(myShape, aItLS.Value());
297 return Standard_True;
299 //=======================================================================
300 //function : BuildResult
302 //=======================================================================
303 void BOPAlgo_BOP::BuildResult(const TopAbs_ShapeEnum theType)
305 TopAbs_ShapeEnum aType;
307 TopTools_MapOfShape aM;
308 TopTools_ListIteratorOfListOfShape aIt, aItIm;
310 const TopTools_ListOfShape& aLA=myDS->Arguments();
312 for (; aIt.More(); aIt.Next()) {
313 const TopoDS_Shape& aS=aIt.Value();
314 aType=aS.ShapeType();
315 if (aType==theType) {
316 if (myImages.IsBound(aS)){
317 const TopTools_ListOfShape& aLSIm=myImages.Find(aS);
318 aItIm.Initialize(aLSIm);
319 for (; aItIm.More(); aItIm.Next()) {
320 const TopoDS_Shape& aSIm=aItIm.Value();
322 aBB.Add(myShape, aSIm);
328 aBB.Add(myShape, aS);
334 //=======================================================================
337 //=======================================================================
338 void BOPAlgo_BOP::Perform()
340 Handle(NCollection_BaseAllocator) aAllocator;
341 BOPAlgo_PaveFiller* pPF;
342 TopTools_ListIteratorOfListOfShape aItLS;
344 GetReport()->Clear();
346 if (myEntryPoint==1) {
354 NCollection_BaseAllocator::CommonBaseAllocator();
355 TopTools_ListOfShape aLS(aAllocator);
357 aItLS.Initialize(myArguments);
358 for (; aItLS.More(); aItLS.Next()) {
359 const TopoDS_Shape& aS=aItLS.Value();
363 aItLS.Initialize(myTools);
364 for (; aItLS.More(); aItLS.Next()) {
365 const TopoDS_Shape& aS=aItLS.Value();
369 pPF=new BOPAlgo_PaveFiller(aAllocator);
370 pPF->SetArguments(aLS);
371 pPF->SetRunParallel(myRunParallel);
372 pPF->SetProgressIndicator(myProgressIndicator);
373 pPF->SetFuzzyValue(myFuzzyValue);
374 pPF->SetNonDestructive(myNonDestructive);
375 pPF->SetGlue(myGlue);
376 pPF->SetUseOBB(myUseOBB);
381 PerformInternal(*pPF);
383 //=======================================================================
384 //function : PerformInternal1
386 //=======================================================================
387 void BOPAlgo_BOP::PerformInternal1(const BOPAlgo_PaveFiller& theFiller)
389 myPaveFiller=(BOPAlgo_PaveFiller*)&theFiller;
390 myDS=myPaveFiller->PDS();
391 myContext=myPaveFiller->Context();
392 myFuzzyValue = myPaveFiller->FuzzyValue();
393 myNonDestructive = myPaveFiller->NonDestructive();
407 if (GetReport()->HasAlert (STANDARD_TYPE(BOPAlgo_AlertEmptyShape)))
409 Standard_Boolean bDone = TreatEmptyShape();
417 FillImagesVertices();
422 BuildResult(TopAbs_VERTEX);
432 BuildResult(TopAbs_EDGE);
438 FillImagesContainers(TopAbs_WIRE);
443 BuildResult(TopAbs_WIRE);
454 BuildResult(TopAbs_FACE);
460 FillImagesContainers(TopAbs_SHELL);
465 BuildResult(TopAbs_SHELL);
476 BuildResult(TopAbs_SOLID);
482 FillImagesContainers(TopAbs_COMPSOLID);
487 BuildResult(TopAbs_COMPSOLID);
493 FillImagesCompounds();
498 BuildResult(TopAbs_COMPOUND);
515 //=======================================================================
518 //=======================================================================
519 void BOPAlgo_BOP::BuildRC()
521 TopAbs_ShapeEnum aType;
525 aBB.MakeCompound(aC);
528 if (myOperation == BOPAlgo_FUSE) {
529 TopTools_MapOfShape aMFence;
530 aType = TypeToExplore(myDims[0]);
531 TopExp_Explorer aExp(myShape, aType);
532 for (; aExp.More(); aExp.Next()) {
533 const TopoDS_Shape& aS = aExp.Current();
534 if (aMFence.Add(aS)) {
542 // B. Common, Cut, Cut21
544 Standard_Integer i, j, aNb, iDim;
545 Standard_Boolean bCheckEdges, bContains, bCut21, bCommon;
546 TopTools_ListIteratorOfListOfShape aItLS;
548 // prepare the building elements of arguments to get its splits
549 TopTools_IndexedMapOfShape aMArgs, aMTools;
550 for (i = 0; i < 2; ++i) {
551 const TopTools_ListOfShape& aLS = !i ? myArguments : myTools;
552 TopTools_IndexedMapOfShape& aMS = !i ? aMArgs : aMTools;
553 aItLS.Initialize(aLS);
554 for (; aItLS.More(); aItLS.Next()) {
555 const TopoDS_Shape& aS = aItLS.Value();
556 iDim = BOPTools_AlgoTools::Dimension(aS);
560 aType = TypeToExplore(iDim);
561 TopExp::MapShapes(aS, aType, aMS);
565 bCheckEdges = Standard_False;
567 // get splits of building elements
568 TopTools_IndexedMapOfShape aMArgsIm, aMToolsIm;
569 BOPTools_IndexedDataMapOfSetShape aMSetArgs, aMSetTools;
571 for (i = 0; i < 2; ++i) {
572 const TopTools_IndexedMapOfShape& aMS = !i ? aMArgs : aMTools;
573 TopTools_IndexedMapOfShape& aMSIm = !i ? aMArgsIm : aMToolsIm;
574 BOPTools_IndexedDataMapOfSetShape& aMSet = !i ? aMSetArgs : aMSetTools;
577 for (j = 1; j <= aNb; ++j) {
578 const TopoDS_Shape& aS = aMS(j);
579 aType = aS.ShapeType();
580 if (aType == TopAbs_EDGE) {
581 const TopoDS_Edge& aE = *(TopoDS_Edge*)&aS;
582 bCheckEdges = Standard_True;
583 if (BRep_Tool::Degenerated(aE)) {
588 if (myImages.IsBound(aS)) {
589 const TopTools_ListOfShape& aLSIm = myImages.Find(aS);
590 aItLS.Initialize(aLSIm);
591 for (; aItLS.More(); aItLS.Next()) {
592 const TopoDS_Shape& aSIm = aItLS.Value();
598 if (aS.ShapeType() == TopAbs_SOLID) {
600 aST.Add(aS, TopAbs_FACE);
601 if (!aMSet.Contains(aST)) {
609 // compare the maps and make the result
611 Standard_Integer iDimMin, iDimMax;
613 iDimMin = Min(myDims[0], myDims[1]);
614 bCommon = (myOperation == BOPAlgo_COMMON);
615 bCut21 = (myOperation == BOPAlgo_CUT21);
617 const TopTools_IndexedMapOfShape& aMIt = bCut21 ? aMToolsIm : aMArgsIm;
618 const TopTools_IndexedMapOfShape& aMCheck = bCut21 ? aMArgsIm : aMToolsIm;
619 const BOPTools_IndexedDataMapOfSetShape& aMSetCheck = bCut21 ? aMSetArgs : aMSetTools;
621 TopTools_IndexedMapOfShape aMCheckExp, aMItExp;
625 for (i = 1; i <= aNb; ++i) {
626 const TopoDS_Shape& aS = aMIt(i);
627 iDimMax = BOPTools_AlgoTools::Dimension(aS);
628 for (iDim = iDimMin; iDim < iDimMax; ++iDim) {
629 aType = TypeToExplore(iDim);
630 TopExp::MapShapes(aS, aType, aMItExp);
639 aNb = aMCheck.Extent();
640 for (i = 1; i <= aNb; ++i) {
641 const TopoDS_Shape& aS = aMCheck(i);
642 iDimMax = BOPTools_AlgoTools::Dimension(aS);
643 for (iDim = iDimMin; iDim < iDimMax; ++iDim) {
644 aType = TypeToExplore(iDim);
645 TopExp::MapShapes(aS, aType, aMCheckExp);
650 aNb = aMItExp.Extent();
651 for (i = 1; i <= aNb; ++i) {
652 const TopoDS_Shape& aS = aMItExp(i);
654 bContains = aMCheckExp.Contains(aS);
655 if (!bContains && aS.ShapeType() == TopAbs_SOLID) {
657 aST.Add(aS, TopAbs_FACE);
658 bContains = aMSetCheck.Contains(aST);
673 // filter result for COMMON operation
675 TopTools_MapOfShape aMFence;
676 TopExp_Explorer aExp;
678 aBB.MakeCompound(aCx);
680 for (iDim = 3; iDim >= iDimMin; --iDim) {
681 aType = TypeToExplore(iDim);
682 aExp.Init(aC, aType);
683 for (; aExp.More(); aExp.Next()) {
684 const TopoDS_Shape& aS = aExp.Current();
685 if (aMFence.Add(aS)) {
687 TopExp::MapShapes(aS, aMFence);
699 // The squats around degenerated edges
700 Standard_Integer nVD;
701 TopTools_IndexedMapOfShape aMVC;
704 TopExp::MapShapes(aC, TopAbs_VERTEX, aMVC);
707 aNb = myDS->NbSourceShapes();
708 for (i = 0; i < aNb; ++i) {
709 const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
710 aType = aSI.ShapeType();
711 if (aType != TopAbs_EDGE) {
715 const TopoDS_Edge& aE = *((TopoDS_Edge*)&aSI.Shape());
716 if (!BRep_Tool::Degenerated(aE)) {
720 nVD = aSI.SubShapes().First();
721 const TopoDS_Shape& aVD = myDS->Shape(nVD);
723 if (!aMVC.Contains(aVD)) {
727 if (myDS->IsNewShape(nVD)) {
731 if (myDS->HasInterf(nVD)) {
740 //=======================================================================
741 //function : BuildShape
743 //=======================================================================
744 void BOPAlgo_BOP::BuildShape()
748 if ((myOperation == BOPAlgo_FUSE) && (myDims[0] == 3)) {
754 TopAbs_ShapeEnum aType, aT1, aT2;
755 TopTools_ListOfShape aLSC, aLCB;
756 TopTools_ListIteratorOfListOfShape aItLS, aItLSIm, aItLCB;
759 TopoDS_Shape aRC, aRCB;
761 TopTools_MapOfShape aMSRC;
762 TopExp::MapShapes(myRC, aMSRC);
764 // collect images of containers
765 for (i = 0; i < 2; ++i) {
766 const TopTools_ListOfShape& aLS = !i ? myArguments : myTools;
768 aItLS.Initialize(aLS);
769 for (; aItLS.More(); aItLS.Next()) {
770 const TopoDS_Shape& aS = aItLS.Value();
772 CollectContainers(aS, aLSC);
776 TopTools_ListOfShape aLCRes;
777 TopTools_MapOfShape aMInpFence;
778 aItLS.Initialize(aLSC);
779 for (; aItLS.More(); aItLS.Next()) {
780 const TopoDS_Shape& aSC = aItLS.Value();
783 BOPTools_AlgoTools::MakeContainer(TopAbs_COMPOUND, aRC);
786 for (; aIt.More(); aIt.Next()) {
787 const TopoDS_Shape& aS = aIt.Value();
788 if (myImages.IsBound(aS)) {
789 const TopTools_ListOfShape& aLSIm = myImages.Find(aS);
791 aItLSIm.Initialize(aLSIm);
792 for (; aItLSIm.More(); aItLSIm.Next()) {
793 const TopoDS_Shape& aSIm = aItLSIm.Value();
794 if (aMSRC.Contains(aSIm)) {
799 else if (aMSRC.Contains(aS)) {
804 aType = aSC.ShapeType();
823 BOPTools_AlgoTools::MakeConnexityBlocks(aRC, aT1, aT2, aLCB);
824 if (aLCB.IsEmpty()) {
828 aItLCB.Initialize(aLCB);
829 for (; aItLCB.More(); aItLCB.Next()) {
830 BOPTools_AlgoTools::MakeContainer(aType, aRCB);
832 const TopoDS_Shape& aCB = aItLCB.Value();
834 for (; aIt.More(); aIt.Next()) {
835 const TopoDS_Shape& aCBS = aIt.Value();
839 if (aType == TopAbs_WIRE) {
841 BOPTools_AlgoTools::OrientEdgesOnWire(aRCB);
843 else if (aType == TopAbs_SHELL) {
844 BOPTools_AlgoTools::OrientFacesOnShell(aRCB);
847 aRCB.Orientation(aSC.Orientation());
853 RemoveDuplicates(aLCRes);
855 // add containers to result
856 TopoDS_Compound aResult;
857 aBB.MakeCompound(aResult);
859 aItLS.Initialize(aLCRes);
860 for (; aItLS.More(); aItLS.Next()) {
861 aBB.Add(aResult, aItLS.Value());
864 // create map of containers
865 TopTools_MapOfShape aMSResult;
866 TopExp::MapShapes(aResult, aMSResult);
868 // get input non-container shapes
869 TopTools_ListOfShape aLSNonCont;
870 for (i = 0; i < 2; ++i)
872 const TopTools_ListOfShape& aLS = !i ? myArguments : myTools;
873 aItLS.Initialize(aLS);
874 for (; aItLS.More(); aItLS.Next())
876 const TopoDS_Shape& aS = aItLS.Value();
877 BOPAlgo_Tools::TreatCompound(aS, aMInpFence, aLSNonCont);
881 // put non-container shapes in the result
882 aItLS.Initialize(aLSNonCont);
883 for (; aItLS.More(); aItLS.Next())
885 const TopoDS_Shape& aS = aItLS.Value();
886 if (myImages.IsBound(aS))
888 const TopTools_ListOfShape& aLSIm = myImages.Find(aS);
889 aItLSIm.Initialize(aLSIm);
890 for (; aItLSIm.More(); aItLSIm.Next())
892 const TopoDS_Shape& aSIm = aItLSIm.Value();
893 if (aMSRC.Contains(aSIm) && aMSResult.Add(aSIm))
894 aBB.Add(aResult, aSIm);
897 else if (aMSRC.Contains(aS) && aMSResult.Add(aS))
898 aBB.Add(aResult, aS);
903 //=======================================================================
904 //function : BuildSolid
906 //=======================================================================
907 void BOPAlgo_BOP::BuildSolid()
910 TopTools_ListOfShape aLSC;
912 TopTools_ListIteratorOfListOfShape aItLS;
913 TopExp_Explorer aExp;
916 // Get solids from input arguments
917 TopTools_MapOfShape aMSA;
918 // Map the arguments to find shared faces
919 TopTools_IndexedDataMapOfShapeListOfShape aMFS;
920 for (Standard_Integer i = 0; i < 2; ++i) {
921 const TopTools_ListOfShape& aLSA = (i) ? myArguments : myTools;
922 aItLS.Initialize(aLSA);
923 for (; aItLS.More(); aItLS.Next()) {
924 const TopoDS_Shape& aSA = aItLS.Value();
925 aExp.Init(aSA, TopAbs_SOLID);
926 for (; aExp.More(); aExp.Next()) {
927 const TopoDS_Shape& aSol = aExp.Current();
929 TopExp::MapShapesAndAncestors(aSol, TopAbs_FACE, TopAbs_SOLID, aMFS);
932 // get Compsolids from input arguments
933 CollectContainers(aSA, aLSC);
937 // Find solids in input arguments sharing faces with other solids
938 TopTools_MapOfShape aMTSols;
939 Standard_Integer i, aNb = aMFS.Extent();
940 for (i = 1; i < aNb; ++i) {
941 const TopTools_ListOfShape& aLSols = aMFS(i);
942 if (aLSols.Extent() > 1) {
943 aItLS.Initialize(aLSols);
944 for(; aItLS.More(); aItLS.Next()) {
945 aMTSols.Add(aItLS.Value());
950 // Possibly untouched solids - to be added to results as is
951 TopTools_IndexedMapOfShape aMUSols;
952 // Use map to chose the most outer faces to build result solids
955 TopTools_IndexedMapOfShape aMFI;
957 TopoDS_Iterator aIt(myRC);
958 for (; aIt.More(); aIt.Next()) {
959 const TopoDS_Shape& aSx = aIt.Value();
960 if (aMSA.Contains(aSx)) {
961 if (!aMTSols.Contains(aSx)) {
967 MapFacesToBuildSolids(aSx, aMFS, aMFI);
968 } // for (; aIt.More(); aIt.Next()) {
970 // Process possibly untouched solids.
971 // Really untouched solids will be added into result as is.
972 // Others will be processed by BuilderSolid.
973 BOPTools_IndexedDataMapOfSetShape aDMSTS;
975 aNb = aMUSols.Extent();
976 for (i = 1; i <= aNb; ++i) {
977 const TopoDS_Shape& aSx = aMUSols(i);
979 aExp.Init(aSx, TopAbs_FACE);
980 for (; aExp.More(); aExp.Next()) {
981 if (aMFS.Contains(aExp.Current())) {
987 MapFacesToBuildSolids(aSx, aMFS, aMFI);
991 aST.Add(aSx, TopAbs_FACE);
992 if (!aDMSTS.Contains(aST)) {
993 aDMSTS.Add(aST, aSx);
998 TopTools_IndexedDataMapOfShapeListOfShape aMEF;
999 // Fill the list of faces to build the result solids
1000 TopTools_ListOfShape aSFS;
1001 aNb = aMFS.Extent();
1002 for (i = 1; i <= aNb; ++i) {
1003 const TopTools_ListOfShape& aLSx = aMFS(i);
1004 if (aLSx.Extent() == 1) {
1005 const TopoDS_Shape& aFx = aMFS.FindKey(i);
1006 TopExp::MapShapesAndAncestors(aFx, TopAbs_EDGE, TopAbs_FACE, aMEF);
1011 aNb = aMFI.Extent();
1012 for (i = 1; i <= aNb; ++i) {
1013 TopoDS_Shape aFx = aMFI.FindKey(i);
1014 aSFS.Append(aFx.Oriented(TopAbs_FORWARD));
1015 aSFS.Append(aFx.Oriented(TopAbs_REVERSED));
1019 BOPTools_AlgoTools::MakeContainer(TopAbs_COMPOUND, aRC);
1020 if (aSFS.Extent()) {
1021 // Build solids from set of faces
1022 BOPAlgo_BuilderSolid aSB;
1023 aSB.SetContext(myContext);
1024 aSB.SetShapes(aSFS);
1026 if (aSB.HasErrors()) {
1027 AddError (new BOPAlgo_AlertSolidBuilderFailed); // SolidBuilder failed
1031 const TopTools_ListOfShape& aLSR = aSB.Areas();
1033 // add new solids to result
1034 aItLS.Initialize(aLSR);
1035 for (; aItLS.More(); aItLS.Next()) {
1036 const TopoDS_Shape& aSR = aItLS.Value();
1041 // add untouched solids to result
1042 aNb = aDMSTS.Extent();
1043 for (i = 1; i <= aNb; ++i) {
1044 const TopoDS_Shape& aSx = aDMSTS(i);
1048 if (aLSC.IsEmpty()) {
1049 // no Compsolids in arguments
1054 // build new Compsolids from new solids containing splits
1055 // of faces from arguments of type Compsolid
1057 TopoDS_Shape aResult;
1058 BOPTools_AlgoTools::MakeContainer(TopAbs_COMPOUND, aResult);
1060 aIt.Initialize(aRC);
1062 // no solids in the result
1067 const TopoDS_Shape& aSol1 = aIt.Value();
1070 // optimization for one solid in the result
1073 BOPTools_AlgoTools::MakeContainer(TopAbs_COMPSOLID, aCS);
1074 aBB.Add(aCS, aSol1);
1076 aBB.Add(aResult, aCS);
1081 // get splits of faces of the Compsolid arguments
1082 TopTools_MapOfShape aMFCs;
1083 aItLS.Initialize(aLSC);
1084 for (; aItLS.More(); aItLS.Next()) {
1085 const TopoDS_Shape& aCs = aItLS.Value();
1086 aExp.Init(aCs, TopAbs_FACE);
1087 for (; aExp.More(); aExp.Next()) {
1088 const TopoDS_Shape& aF = aExp.Current();
1089 const TopTools_ListOfShape* pLFIm = myImages.Seek(aF);
1094 TopTools_ListIteratorOfListOfShape aItLFIm(*pLFIm);
1095 for (; aItLFIm.More(); aItLFIm.Next()) {
1096 aMFCs.Add(aItLFIm.Value());
1102 // build connexity blocks from new solids
1103 TopTools_ListOfShape aLCBS;
1104 BOPTools_AlgoTools::MakeConnexityBlocks(aRC, TopAbs_FACE, TopAbs_SOLID, aLCBS);
1106 aItLS.Initialize(aLCBS);
1107 for (; aItLS.More(); aItLS.Next()) {
1108 const TopoDS_Shape& aCB = aItLS.Value();
1110 // check if the Compsolid should be created
1111 aExp.Init(aCB, TopAbs_FACE);
1112 for (; aExp.More(); aExp.Next()) {
1113 if (aMFCs.Contains(aExp.Current())) {
1119 // add solids directly into result as their origins are not Compsolids
1120 for (aIt.Initialize(aCB); aIt.More(); aIt.Next()) {
1121 aBB.Add(aResult, aIt.Value());
1128 BOPTools_AlgoTools::MakeContainer(TopAbs_COMPSOLID, aCS);
1130 aIt.Initialize(aCB);
1131 for (; aIt.More(); aIt.Next()) {
1132 aBB.Add(aCS, aIt.Value());
1135 aBB.Add(aResult, aCS);
1140 //=======================================================================
1141 //function : TypeToExplore
1143 //=======================================================================
1144 TopAbs_ShapeEnum TypeToExplore(const Standard_Integer theDim)
1146 TopAbs_ShapeEnum aRet;
1167 //=======================================================================
1168 //function : CollectContainers
1170 //=======================================================================
1171 void CollectContainers(const TopoDS_Shape& theS,
1172 TopTools_ListOfShape& theLSC)
1174 TopAbs_ShapeEnum aType = theS.ShapeType();
1175 if (aType == TopAbs_WIRE ||
1176 aType == TopAbs_SHELL ||
1177 aType == TopAbs_COMPSOLID) {
1178 theLSC.Append(theS);
1182 if (aType != TopAbs_COMPOUND) {
1186 TopoDS_Iterator aIt(theS);
1187 for (; aIt.More(); aIt.Next()) {
1188 const TopoDS_Shape& aS = aIt.Value();
1189 CollectContainers(aS, theLSC);
1193 //=======================================================================
1194 //function : RemoveDuplicates
1195 //purpose : Filters the containers with identical contents
1196 //=======================================================================
1197 void RemoveDuplicates(TopTools_ListOfShape& theContainers)
1199 RemoveDuplicates(theContainers, TopAbs_WIRE);
1200 RemoveDuplicates(theContainers, TopAbs_SHELL);
1201 RemoveDuplicates(theContainers, TopAbs_COMPSOLID);
1204 //=======================================================================
1205 //function : RemoveDuplicates
1206 //purpose : Filters the containers of given type with identical contents
1207 //=======================================================================
1208 void RemoveDuplicates(TopTools_ListOfShape& theContainers,
1209 const TopAbs_ShapeEnum theType)
1211 // get containers of given type
1212 TopTools_ListOfShape aLC;
1213 TopTools_ListIteratorOfListOfShape aItLC(theContainers);
1214 for (; aItLC.More(); aItLC.Next()) {
1215 const TopoDS_Shape& aC = aItLC.Value();
1216 if (aC.ShapeType() == theType) {
1221 if (aLC.IsEmpty()) {
1225 // map containers to compare its contents
1226 NCollection_IndexedDataMap<TopoDS_Shape, TopTools_MapOfShape> aContents;
1228 aItLC.Initialize(aLC);
1229 for (; aItLC.More(); aItLC.Next()) {
1230 const TopoDS_Shape& aC = aItLC.Value();
1232 TopTools_MapOfShape& aMC = aContents(aContents.Add(aC, TopTools_MapOfShape()));
1234 TopoDS_Iterator aIt(aC);
1235 for (; aIt.More(); aIt.Next()) {
1236 aMC.Add(aIt.Value());
1240 // compare the contents of the containers and find duplicates
1241 TopTools_MapOfShape aDuplicates;
1243 Standard_Integer i, j, aNb = aContents.Extent();
1244 for (i = 1; i <= aNb; ++i) {
1245 const TopoDS_Shape& aCi = aContents.FindKey(i);
1246 if (aDuplicates.Contains(aCi)) {
1249 const TopTools_MapOfShape& aMi = aContents(i);
1250 Standard_Integer aNbi = aMi.Extent();
1252 for (j = i + 1; j <= aNb; ++j) {
1253 const TopoDS_Shape& aCj = aContents.FindKey(j);
1254 if (aDuplicates.Contains(aCj)) {
1257 const TopTools_MapOfShape& aMj = aContents(j);
1258 Standard_Integer aNbj = aMj.Extent();
1260 Standard_Integer aNbCommon = NbCommonItemsInMap(aMi, aMj);
1262 if (aNbj == aNbCommon) {
1263 aDuplicates.Add(aCj);
1267 if (aNbi == aNbCommon) {
1268 aDuplicates.Add(aCi);
1274 if (aDuplicates.IsEmpty()) {
1278 // remove duplicating containers
1279 aItLC.Initialize(theContainers);
1280 for (; aItLC.More(); ) {
1281 const TopoDS_Shape& aC = aItLC.Value();
1282 if (aDuplicates.Contains(aC)) {
1283 theContainers.Remove(aItLC);
1290 //=======================================================================
1291 //function : NbCommonItemsInMap
1292 //purpose : Counts the items contained in both maps
1293 //=======================================================================
1294 Standard_Integer NbCommonItemsInMap(const TopTools_MapOfShape& theM1,
1295 const TopTools_MapOfShape& theM2)
1297 const TopTools_MapOfShape* aMap1 = &theM1;
1298 const TopTools_MapOfShape* aMap2 = &theM2;
1300 if (theM2.Extent() < theM1.Extent()) {
1305 Standard_Integer iCommon = 0;
1306 for (TopTools_MapIteratorOfMapOfShape aIt(*aMap1); aIt.More(); aIt.Next()) {
1307 if (aMap2->Contains(aIt.Value())) {
1313 //=======================================================================
1314 //function : MapFacesToBuildSolids
1315 //purpose : Stores the faces of the given solid into outgoing maps:
1316 // <theMFS> - not internal faces with reference to solid;
1317 // <theMFI> - internal faces.
1318 //=======================================================================
1319 void MapFacesToBuildSolids(const TopoDS_Shape& theSol,
1320 TopTools_IndexedDataMapOfShapeListOfShape& theMFS,
1321 TopTools_IndexedMapOfShape& theMFI)
1323 TopExp_Explorer aExp(theSol, TopAbs_FACE);
1324 for (; aExp.More(); aExp.Next()) {
1325 const TopoDS_Shape& aF = aExp.Current();
1327 if (aF.Orientation() == TopAbs_INTERNAL) {
1332 TopTools_ListOfShape* pLSol = theMFS.ChangeSeek(aF);
1334 pLSol = &theMFS(theMFS.Add(aF, TopTools_ListOfShape()));
1335 pLSol->Append(theSol);
1338 const TopoDS_Shape& aF1 = theMFS.FindKey(theMFS.FindIndex(aF));
1339 if (aF1.Orientation() != aF.Orientation()) {
1340 pLSol->Append(theSol);