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 <BOPCol_DataMapOfShapeShape.hxx>
20 #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
21 #include <BOPCol_IndexedMapOfShape.hxx>
22 #include <BOPCol_ListOfShape.hxx>
23 #include <BOPCol_MapOfShape.hxx>
24 #include <BOPDS_DS.hxx>
25 #include <BOPTools.hxx>
26 #include <BOPTools_AlgoTools.hxx>
27 #include <BOPTools_AlgoTools3D.hxx>
28 #include <BOPTools_Set.hxx>
29 #include <BOPTools_SetMapHasher.hxx>
30 #include <BRep_Builder.hxx>
31 #include <BRep_Tool.hxx>
32 #include <NCollection_DataMap.hxx>
33 #include <TopAbs_ShapeEnum.hxx>
34 #include <TopExp_Explorer.hxx>
35 #include <TopoDS_Compound.hxx>
36 #include <TopoDS_Edge.hxx>
37 #include <TopoDS_Iterator.hxx>
38 #include <TopoDS_Shape.hxx>
40 typedef NCollection_IndexedDataMap
43 BOPTools_SetMapHasher> BOPTools_IndexedDataMapOfSetShape;
46 TopAbs_ShapeEnum TypeToExplore(const Standard_Integer theDim);
49 void CollectContainers(const TopoDS_Shape& theS,
50 BOPCol_ListOfShape& theLSC);
53 void RemoveDuplicates(BOPCol_ListOfShape& theContainers);
56 void RemoveDuplicates(BOPCol_ListOfShape& theContainers,
57 const TopAbs_ShapeEnum theType);
60 Standard_Integer NbCommonItemsInMap(const BOPCol_MapOfShape& theM1,
61 const BOPCol_MapOfShape& theM2);
64 void MapFacesToBuildSolids(const TopoDS_Shape& theSol,
65 BOPCol_IndexedDataMapOfShapeListOfShape& theMFS,
66 BOPCol_IndexedMapOfShape& theMFI);
68 //=======================================================================
71 //=======================================================================
72 BOPAlgo_BOP::BOPAlgo_BOP()
76 myMapTools(100, myAllocator)
80 //=======================================================================
83 //=======================================================================
84 BOPAlgo_BOP::BOPAlgo_BOP
85 (const Handle(NCollection_BaseAllocator)& theAllocator)
87 BOPAlgo_Builder(theAllocator),
89 myMapTools(100, myAllocator)
93 //=======================================================================
96 //=======================================================================
97 BOPAlgo_BOP::~BOPAlgo_BOP()
100 //=======================================================================
103 //=======================================================================
104 void BOPAlgo_BOP::Clear()
106 myOperation=BOPAlgo_UNKNOWN;
112 BOPAlgo_Builder::Clear();
114 //=======================================================================
115 //function : SetOperation
117 //=======================================================================
118 void BOPAlgo_BOP::SetOperation(const BOPAlgo_Operation theOperation)
120 myOperation=theOperation;
122 //=======================================================================
123 //function : Operation
125 //=======================================================================
126 BOPAlgo_Operation BOPAlgo_BOP::Operation()const
130 //=======================================================================
133 //=======================================================================
134 void BOPAlgo_BOP::AddTool(const TopoDS_Shape& theShape)
136 if (myMapTools.Add(theShape)) {
137 myTools.Append(theShape);
140 //=======================================================================
141 //function : SetTools
143 //=======================================================================
144 void BOPAlgo_BOP::SetTools(const BOPCol_ListOfShape& theShapes)
146 BOPCol_ListIteratorOfListOfShape aIt;
149 aIt.Initialize(theShapes);
150 for (; aIt.More(); aIt.Next()) {
151 const TopoDS_Shape& aS = aIt.Value();
155 //=======================================================================
156 //function : CheckData
158 //=======================================================================
159 void BOPAlgo_BOP::CheckData()
161 Standard_Integer i, j, iDim, aNbArgs, aNbTools;
162 Standard_Boolean bFlag, bFuse;
163 BOPCol_ListIteratorOfListOfShape aItLS;
167 if (!(myOperation==BOPAlgo_COMMON ||
168 myOperation==BOPAlgo_FUSE ||
169 myOperation==BOPAlgo_CUT||
170 myOperation==BOPAlgo_CUT21)) {
171 // non-licit operation
176 aNbArgs=myArguments.Extent();
178 // invalid number of Arguments
183 aNbTools=myTools.Extent();
185 // invalid number of Tools
195 myErrorStatus=myPaveFiller->ErrorStatus();
200 bFuse = (myOperation == BOPAlgo_FUSE);
202 // The rules for different types of operations are the following:
203 // 1. FUSE: All arguments and tools should have the same dimension;
204 // 2. CUT: The MAXIMAL dimension of the ARGUMENTS should be less
205 // or equal to the MINIMAL dimension of the TOOLS;
206 // 3. CUT21: The MINIMAL dimension of ARGUMENTS should be grater
207 // or equal to the MAXIMAL dimension of the TOOLS;
208 // 4. COMMON: The arguments and tools could have any dimensions.
210 Standard_Integer iDimMin[2], iDimMax[2];
212 for (i=0; i<2; ++i) {
213 const BOPCol_ListOfShape& aLS=(!i)? myArguments : myTools;
214 aItLS.Initialize(aLS);
215 for (j=0; aItLS.More(); aItLS.Next(), ++j) {
216 const TopoDS_Shape& aS=aItLS.Value();
217 bFlag=BOPTools_AlgoTools3D::IsEmptyShape(aS);
222 iDim=BOPTools_AlgoTools::Dimension(aS);
224 // non-homogenious argument
235 if (iDim < iDimMin[i]) {
238 else if (iDim > iDimMax[i]) {
242 if (bFuse && (iDimMin[i] != iDimMax[i])) {
243 // non-homogenious argument
250 if (((myOperation == BOPAlgo_FUSE) && (iDimMax[0] != iDimMax[1])) ||
251 ((myOperation == BOPAlgo_CUT) && (iDimMax[0] > iDimMin[1])) ||
252 ((myOperation == BOPAlgo_CUT21) && (iDimMin[0] < iDimMax[1])) ) {
253 // non-licit operation for the arguments
258 myDims[0] = iDimMin[0];
259 myDims[1] = iDimMin[1];
261 //=======================================================================
264 //=======================================================================
265 void BOPAlgo_BOP::Prepare()
268 BOPAlgo_Builder::Prepare();
270 if(myWarningStatus == 2) {
273 BOPCol_ListIteratorOfListOfShape aItLS;
275 switch(myOperation) {
277 for (i=0; i<2; ++i) {
278 const BOPCol_ListOfShape& aLS=(!i)? myArguments : myTools;
279 aItLS.Initialize(aLS);
280 for (; aItLS.More(); aItLS.Next()) {
281 const TopoDS_Shape& aS=aItLS.Value();
282 aBB.Add(myShape, aS);
289 aItLS.Initialize(myArguments);
290 for (; aItLS.More(); aItLS.Next()) {
291 const TopoDS_Shape& aS=aItLS.Value();
292 if(!BOPTools_AlgoTools3D::IsEmptyShape(aS)) {
293 aBB.Add(myShape, aS);
299 case BOPAlgo_CUT21: {
300 aItLS.Initialize(myTools);
301 for (; aItLS.More(); aItLS.Next()) {
302 const TopoDS_Shape& aS=aItLS.Value();
303 if(!BOPTools_AlgoTools3D::IsEmptyShape(aS)) {
304 aBB.Add(myShape, aS);
315 //=======================================================================
316 //function : BuildResult
318 //=======================================================================
319 void BOPAlgo_BOP::BuildResult(const TopAbs_ShapeEnum theType)
321 TopAbs_ShapeEnum aType;
323 BOPCol_MapOfShape aM;
324 BOPCol_ListIteratorOfListOfShape aIt, aItIm;
328 const BOPCol_ListOfShape& aLA=myDS->Arguments();
330 for (; aIt.More(); aIt.Next()) {
331 const TopoDS_Shape& aS=aIt.Value();
332 aType=aS.ShapeType();
333 if (aType==theType) {
334 if (myImages.IsBound(aS)){
335 const BOPCol_ListOfShape& aLSIm=myImages.Find(aS);
336 aItIm.Initialize(aLSIm);
337 for (; aItIm.More(); aItIm.Next()) {
338 const TopoDS_Shape& aSIm=aItIm.Value();
340 aBB.Add(myShape, aSIm);
346 aBB.Add(myShape, aS);
352 //=======================================================================
355 //=======================================================================
356 void BOPAlgo_BOP::Perform()
358 Handle(NCollection_BaseAllocator) aAllocator;
359 BOPAlgo_PaveFiller* pPF;
360 BOPCol_ListIteratorOfListOfShape aItLS;
364 if (myEntryPoint==1) {
372 NCollection_BaseAllocator::CommonBaseAllocator();
373 BOPCol_ListOfShape aLS(aAllocator);
375 aItLS.Initialize(myArguments);
376 for (; aItLS.More(); aItLS.Next()) {
377 const TopoDS_Shape& aS=aItLS.Value();
381 aItLS.Initialize(myTools);
382 for (; aItLS.More(); aItLS.Next()) {
383 const TopoDS_Shape& aS=aItLS.Value();
387 pPF=new BOPAlgo_PaveFiller(aAllocator);
388 pPF->SetArguments(aLS);
389 pPF->SetRunParallel(myRunParallel);
390 pPF->SetProgressIndicator(myProgressIndicator);
391 pPF->SetFuzzyValue(myFuzzyValue);
392 pPF->SetNonDestructive(myNonDestructive);
393 pPF->SetGlue(myGlue);
398 PerformInternal(*pPF);
400 //=======================================================================
401 //function : PerformInternal1
403 //=======================================================================
404 void BOPAlgo_BOP::PerformInternal1(const BOPAlgo_PaveFiller& theFiller)
409 myPaveFiller=(BOPAlgo_PaveFiller*)&theFiller;
410 myDS=myPaveFiller->PDS();
411 myContext=myPaveFiller->Context();
412 myFuzzyValue = myPaveFiller->FuzzyValue();
413 myNonDestructive = myPaveFiller->NonDestructive();
417 if (myErrorStatus && !myWarningStatus) {
427 if(myWarningStatus == 2) {
432 FillImagesVertices();
437 BuildResult(TopAbs_VERTEX);
447 BuildResult(TopAbs_EDGE);
453 FillImagesContainers(TopAbs_WIRE);
458 BuildResult(TopAbs_WIRE);
469 BuildResult(TopAbs_FACE);
475 FillImagesContainers(TopAbs_SHELL);
480 BuildResult(TopAbs_SHELL);
491 BuildResult(TopAbs_SOLID);
497 FillImagesContainers(TopAbs_COMPSOLID);
502 BuildResult(TopAbs_COMPSOLID);
508 FillImagesCompounds();
513 BuildResult(TopAbs_COMPOUND);
530 //=======================================================================
533 //=======================================================================
534 void BOPAlgo_BOP::BuildRC()
536 TopAbs_ShapeEnum aType;
542 aBB.MakeCompound(aC);
545 if (myOperation == BOPAlgo_FUSE) {
546 BOPCol_MapOfShape aMFence;
547 aType = TypeToExplore(myDims[0]);
548 TopExp_Explorer aExp(myShape, aType);
549 for (; aExp.More(); aExp.Next()) {
550 const TopoDS_Shape& aS = aExp.Current();
551 if (aMFence.Add(aS)) {
559 // B. Common, Cut, Cut21
561 Standard_Integer i, j, aNb, iDim;
562 Standard_Boolean bCheckEdges, bContains, bCut21, bCommon;
563 BOPCol_ListIteratorOfListOfShape aItLS;
565 // prepare the building elements of arguments to get its splits
566 BOPCol_IndexedMapOfShape aMArgs, aMTools;
567 for (i = 0; i < 2; ++i) {
568 const BOPCol_ListOfShape& aLS = !i ? myArguments : myTools;
569 BOPCol_IndexedMapOfShape& aMS = !i ? aMArgs : aMTools;
570 aItLS.Initialize(aLS);
571 for (; aItLS.More(); aItLS.Next()) {
572 const TopoDS_Shape& aS = aItLS.Value();
573 iDim = BOPTools_AlgoTools::Dimension(aS);
574 aType = TypeToExplore(iDim);
575 BOPTools::MapShapes(aS, aType, aMS);
579 bCheckEdges = Standard_False;
581 // get splits of building elements
582 BOPCol_IndexedMapOfShape aMArgsIm, aMToolsIm;
583 BOPTools_IndexedDataMapOfSetShape aMSetArgs, aMSetTools;
585 for (i = 0; i < 2; ++i) {
586 const BOPCol_IndexedMapOfShape& aMS = !i ? aMArgs : aMTools;
587 BOPCol_IndexedMapOfShape& aMSIm = !i ? aMArgsIm : aMToolsIm;
588 BOPTools_IndexedDataMapOfSetShape& aMSet = !i ? aMSetArgs : aMSetTools;
591 for (j = 1; j <= aNb; ++j) {
592 const TopoDS_Shape& aS = aMS(j);
593 aType = aS.ShapeType();
594 if (aType == TopAbs_EDGE) {
595 const TopoDS_Edge& aE = *(TopoDS_Edge*)&aS;
596 bCheckEdges = Standard_True;
597 if (BRep_Tool::Degenerated(aE)) {
602 if (myImages.IsBound(aS)) {
603 const BOPCol_ListOfShape& aLSIm = myImages.Find(aS);
604 aItLS.Initialize(aLSIm);
605 for (; aItLS.More(); aItLS.Next()) {
606 const TopoDS_Shape& aSIm = aItLS.Value();
612 if (aS.ShapeType() == TopAbs_SOLID) {
614 aST.Add(aS, TopAbs_FACE);
615 if (!aMSet.Contains(aST)) {
623 // compare the maps and make the result
625 Standard_Integer iDimMin, iDimMax;
627 iDimMin = Min(myDims[0], myDims[1]);
628 bCommon = (myOperation == BOPAlgo_COMMON);
629 bCut21 = (myOperation == BOPAlgo_CUT21);
631 const BOPCol_IndexedMapOfShape& aMIt = bCut21 ? aMToolsIm : aMArgsIm;
632 const BOPCol_IndexedMapOfShape& aMCheck = bCut21 ? aMArgsIm : aMToolsIm;
633 const BOPTools_IndexedDataMapOfSetShape& aMSetCheck = bCut21 ? aMSetArgs : aMSetTools;
635 BOPCol_IndexedMapOfShape aMCheckExp, aMItExp;
639 for (i = 1; i <= aNb; ++i) {
640 const TopoDS_Shape& aS = aMIt(i);
641 iDimMax = BOPTools_AlgoTools::Dimension(aS);
642 for (iDim = iDimMin; iDim < iDimMax; ++iDim) {
643 aType = TypeToExplore(iDim);
644 BOPTools::MapShapes(aS, aType, aMItExp);
653 aNb = aMCheck.Extent();
654 for (i = 1; i <= aNb; ++i) {
655 const TopoDS_Shape& aS = aMCheck(i);
656 iDimMax = BOPTools_AlgoTools::Dimension(aS);
657 for (iDim = iDimMin; iDim < iDimMax; ++iDim) {
658 aType = TypeToExplore(iDim);
659 BOPTools::MapShapes(aS, aType, aMCheckExp);
664 aNb = aMItExp.Extent();
665 for (i = 1; i <= aNb; ++i) {
666 const TopoDS_Shape& aS = aMItExp(i);
668 bContains = aMCheckExp.Contains(aS);
669 if (!bContains && aS.ShapeType() == TopAbs_SOLID) {
671 aST.Add(aS, TopAbs_FACE);
672 bContains = aMSetCheck.Contains(aST);
687 // filter result for COMMON operation
689 BOPCol_MapOfShape aMFence;
690 TopExp_Explorer aExp;
692 aBB.MakeCompound(aCx);
694 for (iDim = 3; iDim >= iDimMin; --iDim) {
695 aType = TypeToExplore(iDim);
696 aExp.Init(aC, aType);
697 for (; aExp.More(); aExp.Next()) {
698 const TopoDS_Shape& aS = aExp.Current();
699 if (aMFence.Add(aS)) {
701 BOPTools::MapShapes(aS, aMFence);
713 // The squats around degenerated edges
714 Standard_Integer nVD;
715 BOPCol_IndexedMapOfShape aMVC;
718 BOPTools::MapShapes(aC, TopAbs_VERTEX, aMVC);
721 aNb = myDS->NbSourceShapes();
722 for (i = 0; i < aNb; ++i) {
723 const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
724 aType = aSI.ShapeType();
725 if (aType != TopAbs_EDGE) {
729 const TopoDS_Edge& aE = *((TopoDS_Edge*)&aSI.Shape());
730 if (!BRep_Tool::Degenerated(aE)) {
734 nVD = aSI.SubShapes().First();
735 const TopoDS_Shape& aVD = myDS->Shape(nVD);
737 if (!aMVC.Contains(aVD)) {
741 if (myDS->IsNewShape(nVD)) {
745 if (myDS->HasInterf(nVD)) {
754 //=======================================================================
755 //function : BuildShape
757 //=======================================================================
758 void BOPAlgo_BOP::BuildShape()
762 if ((myOperation == BOPAlgo_FUSE) && (myDims[0] == 3)) {
768 TopAbs_ShapeEnum aType, aT1, aT2;
769 BOPCol_ListOfShape aLSC, aLCB;
770 BOPCol_ListIteratorOfListOfShape aItLS, aItLSIm, aItLCB;
773 TopoDS_Shape aRC, aRCB;
775 BOPCol_MapOfShape aMSRC;
776 BOPTools::MapShapes(myRC, aMSRC);
778 // collect images of containers
779 for (i = 0; i < 2; ++i) {
780 const BOPCol_ListOfShape& aLS = !i ? myArguments : myTools;
782 aItLS.Initialize(aLS);
783 for (; aItLS.More(); aItLS.Next()) {
784 const TopoDS_Shape& aS = aItLS.Value();
786 CollectContainers(aS, aLSC);
790 BOPCol_ListOfShape aLCRes;
791 aItLS.Initialize(aLSC);
792 for (; aItLS.More(); aItLS.Next()) {
793 const TopoDS_Shape& aSC = aItLS.Value();
795 BOPTools_AlgoTools::MakeContainer(TopAbs_COMPOUND, aRC);
798 for (; aIt.More(); aIt.Next()) {
799 const TopoDS_Shape& aS = aIt.Value();
800 if (myImages.IsBound(aS)) {
801 const BOPCol_ListOfShape& aLSIm = myImages.Find(aS);
803 aItLSIm.Initialize(aLSIm);
804 for (; aItLSIm.More(); aItLSIm.Next()) {
805 const TopoDS_Shape& aSIm = aItLSIm.Value();
806 if (aMSRC.Contains(aSIm)) {
811 else if (aMSRC.Contains(aS)) {
816 aType = aSC.ShapeType();
835 BOPTools_AlgoTools::MakeConnexityBlocks(aRC, aT1, aT2, aLCB);
836 if (aLCB.IsEmpty()) {
840 aItLCB.Initialize(aLCB);
841 for (; aItLCB.More(); aItLCB.Next()) {
842 BOPTools_AlgoTools::MakeContainer(aType, aRCB);
844 const TopoDS_Shape& aCB = aItLCB.Value();
846 for (; aIt.More(); aIt.Next()) {
847 const TopoDS_Shape& aCBS = aIt.Value();
851 if (aType == TopAbs_WIRE) {
853 BOPTools_AlgoTools::OrientEdgesOnWire(aRCB);
855 else if (aType == TopAbs_SHELL) {
856 BOPTools_AlgoTools::OrientFacesOnShell(aRCB);
859 aRCB.Orientation(aSC.Orientation());
865 RemoveDuplicates(aLCRes);
867 // add containers to result
868 TopoDS_Compound aResult;
869 aBB.MakeCompound(aResult);
871 aItLS.Initialize(aLCRes);
872 for (; aItLS.More(); aItLS.Next()) {
873 aBB.Add(aResult, aItLS.Value());
876 // add the rest of the shapes into result
877 BOPCol_MapOfShape aMSResult;
878 BOPTools::MapShapes(aResult, aMSResult);
880 aIt.Initialize(myRC);
881 for (; aIt.More(); aIt.Next()) {
882 const TopoDS_Shape& aS = aIt.Value();
883 if (aMSResult.Add(aS)) {
884 aBB.Add(aResult, aS);
890 //=======================================================================
891 //function : BuildSolid
893 //=======================================================================
894 void BOPAlgo_BOP::BuildSolid()
897 BOPCol_ListOfShape aLSC;
899 BOPCol_ListIteratorOfListOfShape aItLS;
900 TopExp_Explorer aExp;
905 // Get solids from input arguments
906 BOPCol_MapOfShape aMSA;
907 // Map the arguments to find shared faces
908 BOPCol_IndexedDataMapOfShapeListOfShape aMFS;
909 for (Standard_Integer i = 0; i < 2; ++i) {
910 const BOPCol_ListOfShape& aLSA = (i) ? myArguments : myTools;
911 aItLS.Initialize(aLSA);
912 for (; aItLS.More(); aItLS.Next()) {
913 const TopoDS_Shape& aSA = aItLS.Value();
914 aExp.Init(aSA, TopAbs_SOLID);
915 for (; aExp.More(); aExp.Next()) {
916 const TopoDS_Shape& aSol = aExp.Current();
918 BOPTools::MapShapesAndAncestors(aSol, TopAbs_FACE, TopAbs_SOLID, aMFS);
921 // get Compsolids from input arguments
922 CollectContainers(aSA, aLSC);
926 // Find solids in input arguments sharing faces with other solids
927 BOPCol_MapOfShape aMTSols;
928 Standard_Integer i, aNb = aMFS.Extent();
929 for (i = 1; i < aNb; ++i) {
930 const BOPCol_ListOfShape& aLSols = aMFS(i);
931 if (aLSols.Extent() > 1) {
932 aItLS.Initialize(aLSols);
933 for(; aItLS.More(); aItLS.Next()) {
934 aMTSols.Add(aItLS.Value());
939 // Possibly untouched solids - to be added to results as is
940 BOPCol_IndexedMapOfShape aMUSols;
941 // Use map to chose the most outer faces to build result solids
944 BOPCol_IndexedMapOfShape aMFI;
946 TopoDS_Iterator aIt(myRC);
947 for (; aIt.More(); aIt.Next()) {
948 const TopoDS_Shape& aSx = aIt.Value();
949 if (aMSA.Contains(aSx)) {
950 if (!aMTSols.Contains(aSx)) {
956 MapFacesToBuildSolids(aSx, aMFS, aMFI);
957 } // for (; aIt.More(); aIt.Next()) {
959 // Process possibly untouched solids.
960 // Really untouched solids will be added into result as is.
961 // Others will be processed by BuilderSolid.
962 BOPTools_IndexedDataMapOfSetShape aDMSTS;
964 aNb = aMUSols.Extent();
965 for (i = 1; i <= aNb; ++i) {
966 const TopoDS_Shape& aSx = aMUSols(i);
968 aExp.Init(aSx, TopAbs_FACE);
969 for (; aExp.More(); aExp.Next()) {
970 if (aMFS.Contains(aExp.Current())) {
976 MapFacesToBuildSolids(aSx, aMFS, aMFI);
980 aST.Add(aSx, TopAbs_FACE);
981 if (!aDMSTS.Contains(aST)) {
982 aDMSTS.Add(aST, aSx);
987 BOPCol_IndexedDataMapOfShapeListOfShape aMEF;
988 // Split faces will be added in the end
989 // to avoid errors in BuilderSolid algorithm
990 BOPCol_ListOfShape aLF, aLFx;
992 for (i = 1; i <= aNb; ++i) {
993 const BOPCol_ListOfShape& aLSx = aMFS(i);
994 if (aLSx.Extent() == 1) {
995 const TopoDS_Shape& aFx = aMFS.FindKey(i);
996 BOPTools::MapShapesAndAncestors(aFx, TopAbs_EDGE, TopAbs_FACE, aMEF);
997 if (IsBoundSplits(aFx, aMEF)){
1005 // Faces to build result solids
1006 BOPCol_ListOfShape aSFS;
1007 aItLS.Initialize(aLF);
1008 for(; aItLS.More(); aItLS.Next()) {
1009 const TopoDS_Shape& aFx = aItLS.Value();
1014 aItLS.Initialize(aLFx);
1015 for (; aItLS.More(); aItLS.Next()) {
1016 const TopoDS_Shape& aFx = aItLS.Value();
1021 aNb = aMFI.Extent();
1022 for (i = 1; i <= aNb; ++i) {
1023 TopoDS_Shape aFx = aMFI.FindKey(i);
1024 aSFS.Append(aFx.Oriented(TopAbs_FORWARD));
1025 aSFS.Append(aFx.Oriented(TopAbs_REVERSED));
1029 BOPTools_AlgoTools::MakeContainer(TopAbs_COMPOUND, aRC);
1030 if (aSFS.Extent()) {
1031 // Build solids from set of faces
1032 BOPAlgo_BuilderSolid aSB;
1033 aSB.SetContext(myContext);
1034 aSB.SetShapes(aSFS);
1036 if (aSB.ErrorStatus()) {
1037 myErrorStatus = 30; // SolidBuilder failed
1041 const BOPCol_ListOfShape& aLSR = aSB.Areas();
1043 // add new solids to result
1044 aItLS.Initialize(aLSR);
1045 for (; aItLS.More(); aItLS.Next()) {
1046 const TopoDS_Shape& aSR = aItLS.Value();
1051 // add untouched solids to result
1052 aNb = aDMSTS.Extent();
1053 for (i = 1; i <= aNb; ++i) {
1054 const TopoDS_Shape& aSx = aDMSTS(i);
1058 if (aLSC.IsEmpty()) {
1059 // no Compsolids in arguments
1064 // build new Compsolids from new solids containing splits
1065 // of faces from arguments of type Compsolid
1067 TopoDS_Shape aResult;
1068 BOPTools_AlgoTools::MakeContainer(TopAbs_COMPOUND, aResult);
1070 aIt.Initialize(aRC);
1072 // no solids in the result
1077 const TopoDS_Shape& aSol1 = aIt.Value();
1080 // optimization for one solid in the result
1083 BOPTools_AlgoTools::MakeContainer(TopAbs_COMPSOLID, aCS);
1084 aBB.Add(aCS, aSol1);
1086 aBB.Add(aResult, aCS);
1091 // get splits of faces of the Compsolid arguments
1092 BOPCol_MapOfShape aMFCs;
1093 aItLS.Initialize(aLSC);
1094 for (; aItLS.More(); aItLS.Next()) {
1095 const TopoDS_Shape& aCs = aItLS.Value();
1096 aExp.Init(aCs, TopAbs_FACE);
1097 for (; aExp.More(); aExp.Next()) {
1098 const TopoDS_Shape& aF = aExp.Current();
1099 const BOPCol_ListOfShape* pLFIm = myImages.Seek(aF);
1104 BOPCol_ListIteratorOfListOfShape aItLFIm(*pLFIm);
1105 for (; aItLFIm.More(); aItLFIm.Next()) {
1106 aMFCs.Add(aItLFIm.Value());
1112 // build connexity blocks from new solids
1113 BOPCol_ListOfShape aLCBS;
1114 BOPTools_AlgoTools::MakeConnexityBlocks(aRC, TopAbs_FACE, TopAbs_SOLID, aLCBS);
1116 aItLS.Initialize(aLCBS);
1117 for (; aItLS.More(); aItLS.Next()) {
1118 const TopoDS_Shape& aCB = aItLS.Value();
1120 // check if the Compsolid should be created
1121 aExp.Init(aCB, TopAbs_FACE);
1122 for (; aExp.More(); aExp.Next()) {
1123 if (aMFCs.Contains(aExp.Current())) {
1129 // add solids directly into result as their origins are not Compsolids
1130 for (aIt.Initialize(aCB); aIt.More(); aIt.Next()) {
1131 aBB.Add(aResult, aIt.Value());
1138 BOPTools_AlgoTools::MakeContainer(TopAbs_COMPSOLID, aCS);
1140 aIt.Initialize(aCB);
1141 for (; aIt.More(); aIt.Next()) {
1142 aBB.Add(aCS, aIt.Value());
1145 aBB.Add(aResult, aCS);
1150 //=======================================================================
1151 //function : IsBoundSplits
1153 //=======================================================================
1154 Standard_Boolean BOPAlgo_BOP::IsBoundSplits
1155 (const TopoDS_Shape& aS,
1156 BOPCol_IndexedDataMapOfShapeListOfShape& aMEF)
1158 Standard_Boolean bRet = Standard_False;
1159 if (mySplits.IsBound(aS) || myOrigins.IsBound(aS)) {
1163 BOPCol_ListIteratorOfListOfShape aIt;
1164 Standard_Integer aNbLS;
1165 TopAbs_Orientation anOr;
1167 //check face aF may be connected to face from mySplits
1168 TopExp_Explorer aExp(aS, TopAbs_EDGE);
1169 for (; aExp.More(); aExp.Next()) {
1170 const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aExp.Current()));
1172 anOr = aE.Orientation();
1173 if (anOr==TopAbs_INTERNAL) {
1177 if (BRep_Tool::Degenerated(aE)) {
1181 const BOPCol_ListOfShape& aLS=aMEF.FindFromKey(aE);
1182 aNbLS = aLS.Extent();
1187 aIt.Initialize(aLS);
1188 for (; aIt.More(); aIt.Next()) {
1189 const TopoDS_Shape& aSx = aIt.Value();
1190 if (mySplits.IsBound(aSx) || myOrigins.IsBound(aS)) {
1198 //=======================================================================
1199 //function : TypeToExplore
1201 //=======================================================================
1202 TopAbs_ShapeEnum TypeToExplore(const Standard_Integer theDim)
1204 TopAbs_ShapeEnum aRet;
1225 //=======================================================================
1226 //function : CollectContainers
1228 //=======================================================================
1229 void CollectContainers(const TopoDS_Shape& theS,
1230 BOPCol_ListOfShape& theLSC)
1232 TopAbs_ShapeEnum aType = theS.ShapeType();
1233 if (aType == TopAbs_WIRE ||
1234 aType == TopAbs_SHELL ||
1235 aType == TopAbs_COMPSOLID) {
1236 theLSC.Append(theS);
1240 if (aType != TopAbs_COMPOUND) {
1244 TopoDS_Iterator aIt(theS);
1245 for (; aIt.More(); aIt.Next()) {
1246 const TopoDS_Shape& aS = aIt.Value();
1247 CollectContainers(aS, theLSC);
1251 //=======================================================================
1252 //function : RemoveDuplicates
1253 //purpose : Filters the containers with identical contents
1254 //=======================================================================
1255 void RemoveDuplicates(BOPCol_ListOfShape& theContainers)
1257 RemoveDuplicates(theContainers, TopAbs_WIRE);
1258 RemoveDuplicates(theContainers, TopAbs_SHELL);
1259 RemoveDuplicates(theContainers, TopAbs_COMPSOLID);
1262 //=======================================================================
1263 //function : RemoveDuplicates
1264 //purpose : Filters the containers of given type with identical contents
1265 //=======================================================================
1266 void RemoveDuplicates(BOPCol_ListOfShape& theContainers,
1267 const TopAbs_ShapeEnum theType)
1269 // get containers of given type
1270 BOPCol_ListOfShape aLC;
1271 BOPCol_ListIteratorOfListOfShape aItLC(theContainers);
1272 for (; aItLC.More(); aItLC.Next()) {
1273 const TopoDS_Shape& aC = aItLC.Value();
1274 if (aC.ShapeType() == theType) {
1279 if (aLC.IsEmpty()) {
1283 // map containers to compare its contents
1284 NCollection_IndexedDataMap<TopoDS_Shape, BOPCol_MapOfShape> aContents;
1286 aItLC.Initialize(aLC);
1287 for (; aItLC.More(); aItLC.Next()) {
1288 const TopoDS_Shape& aC = aItLC.Value();
1290 BOPCol_MapOfShape& aMC = aContents(aContents.Add(aC, BOPCol_MapOfShape()));
1292 TopoDS_Iterator aIt(aC);
1293 for (; aIt.More(); aIt.Next()) {
1294 aMC.Add(aIt.Value());
1298 // compare the contents of the containers and find duplicates
1299 BOPCol_MapOfShape aDuplicates;
1301 Standard_Integer i, j, aNb = aContents.Extent();
1302 for (i = 1; i <= aNb; ++i) {
1303 const TopoDS_Shape& aCi = aContents.FindKey(i);
1304 if (aDuplicates.Contains(aCi)) {
1307 const BOPCol_MapOfShape& aMi = aContents(i);
1308 Standard_Integer aNbi = aMi.Extent();
1310 for (j = i + 1; j <= aNb; ++j) {
1311 const TopoDS_Shape& aCj = aContents.FindKey(j);
1312 if (aDuplicates.Contains(aCj)) {
1315 const BOPCol_MapOfShape& aMj = aContents(j);
1316 Standard_Integer aNbj = aMj.Extent();
1318 Standard_Integer aNbCommon = NbCommonItemsInMap(aMi, aMj);
1320 if (aNbj == aNbCommon) {
1321 aDuplicates.Add(aCj);
1325 if (aNbi == aNbCommon) {
1326 aDuplicates.Add(aCi);
1332 if (aDuplicates.IsEmpty()) {
1336 // remove duplicating containers
1337 aItLC.Initialize(theContainers);
1338 for (; aItLC.More(); ) {
1339 const TopoDS_Shape& aC = aItLC.Value();
1340 if (aDuplicates.Contains(aC)) {
1341 theContainers.Remove(aItLC);
1348 //=======================================================================
1349 //function : NbCommonItemsInMap
1350 //purpose : Counts the items contained in both maps
1351 //=======================================================================
1352 Standard_Integer NbCommonItemsInMap(const BOPCol_MapOfShape& theM1,
1353 const BOPCol_MapOfShape& theM2)
1355 const BOPCol_MapOfShape* aMap1 = &theM1;
1356 const BOPCol_MapOfShape* aMap2 = &theM2;
1358 if (theM2.Extent() < theM1.Extent()) {
1363 Standard_Integer iCommon = 0;
1364 for (BOPCol_MapIteratorOfMapOfShape aIt(*aMap1); aIt.More(); aIt.Next()) {
1365 if (aMap2->Contains(aIt.Value())) {
1371 //=======================================================================
1372 //function : MapFacesToBuildSolids
1373 //purpose : Stores the faces of the given solid into outgoing maps:
1374 // <theMFS> - not internal faces with reference to solid;
1375 // <theMFI> - internal faces.
1376 //=======================================================================
1377 void MapFacesToBuildSolids(const TopoDS_Shape& theSol,
1378 BOPCol_IndexedDataMapOfShapeListOfShape& theMFS,
1379 BOPCol_IndexedMapOfShape& theMFI)
1381 TopExp_Explorer aExp(theSol, TopAbs_FACE);
1382 for (; aExp.More(); aExp.Next()) {
1383 const TopoDS_Shape& aF = aExp.Current();
1385 if (aF.Orientation() == TopAbs_INTERNAL) {
1390 BOPCol_ListOfShape* pLSol = theMFS.ChangeSeek(aF);
1392 pLSol = &theMFS(theMFS.Add(aF, BOPCol_ListOfShape()));
1393 pLSol->Append(theSol);
1396 const TopoDS_Shape& aF1 = theMFS.FindKey(theMFS.FindIndex(aF));
1397 if (aF1.Orientation() != aF.Orientation()) {
1398 pLSol->Append(theSol);