0026619: Tolerances of operands are modified using bop
[occt.git] / src / BOPAlgo / BOPAlgo_BOP.cxx
1 // Created by: Peter KURNEV
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
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.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15
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>
39 #include <TopTools_ListIteratorOfListOfShape.hxx>
40
41 typedef NCollection_IndexedDataMap
42   <BOPTools_Set,
43   TopoDS_Shape,
44   BOPTools_SetMapHasher> BOPTools_IndexedDataMapOfSetShape;
45 //
46 static
47   TopAbs_ShapeEnum TypeToExplore(const Standard_Integer theDim);
48 //
49 static
50   void CollectContainers(const TopoDS_Shape& theS,
51                          BOPCol_ListOfShape& theLSC);
52
53
54 //=======================================================================
55 //function : 
56 //purpose  : 
57 //=======================================================================
58 BOPAlgo_BOP::BOPAlgo_BOP()
59 :
60   BOPAlgo_Builder(),
61   myTools(myAllocator),
62   myMapTools(100, myAllocator)
63 {
64   Clear();
65 }
66 //=======================================================================
67 //function : 
68 //purpose  : 
69 //=======================================================================
70 BOPAlgo_BOP::BOPAlgo_BOP
71   (const Handle(NCollection_BaseAllocator)& theAllocator)
72 :
73   BOPAlgo_Builder(theAllocator),
74   myTools(myAllocator),
75   myMapTools(100, myAllocator)
76 {
77   Clear();
78 }
79 //=======================================================================
80 //function : ~
81 //purpose  : 
82 //=======================================================================
83 BOPAlgo_BOP::~BOPAlgo_BOP()
84 {
85 }
86 //=======================================================================
87 //function : Clear
88 //purpose  : 
89 //=======================================================================
90 void BOPAlgo_BOP::Clear()
91 {
92   myOperation=BOPAlgo_UNKNOWN;
93   myTools.Clear();
94   myMapTools.Clear();
95   myDims[0]=-1;
96   myDims[1]=-1;
97   //
98   BOPAlgo_Builder::Clear();
99 }
100 //=======================================================================
101 //function : SetOperation
102 //purpose  : 
103 //=======================================================================
104 void BOPAlgo_BOP::SetOperation(const BOPAlgo_Operation theOperation)
105 {
106   myOperation=theOperation;
107 }
108 //=======================================================================
109 //function : Operation
110 //purpose  : 
111 //=======================================================================
112 BOPAlgo_Operation BOPAlgo_BOP::Operation()const
113 {
114   return myOperation;
115 }
116 //=======================================================================
117 //function : AddTool
118 //purpose  : 
119 //=======================================================================
120 void BOPAlgo_BOP::AddTool(const TopoDS_Shape& theShape)
121 {
122   if (myMapTools.Add(theShape)) {
123     myTools.Append(theShape);
124   }
125 }
126 //=======================================================================
127 //function : SetTools
128 //purpose  : 
129 //=======================================================================
130 void BOPAlgo_BOP::SetTools(const BOPCol_ListOfShape& theShapes)
131 {
132   BOPCol_ListIteratorOfListOfShape aIt;
133   //
134   myTools.Clear();
135   aIt.Initialize(theShapes);
136   for (; aIt.More(); aIt.Next()) {
137     const TopoDS_Shape& aS = aIt.Value();
138     AddTool(aS);
139   }
140 }
141 //=======================================================================
142 //function : CheckData
143 //purpose  : 
144 //=======================================================================
145 void BOPAlgo_BOP::CheckData()
146 {
147   Standard_Integer i, j, iDim, aNbArgs, aNbTools;
148   Standard_Boolean bFlag, bFuse;
149   BOPCol_ListIteratorOfListOfShape aItLS;
150   //
151   myErrorStatus=0;
152   //
153   if (!(myOperation==BOPAlgo_COMMON ||
154         myOperation==BOPAlgo_FUSE || 
155         myOperation==BOPAlgo_CUT|| 
156         myOperation==BOPAlgo_CUT21)) {
157     // non-licit operation
158     myErrorStatus=14;
159     return;
160   }
161   //
162   aNbArgs=myArguments.Extent();
163   if (!aNbArgs) {
164     // invalid number of Arguments
165     myErrorStatus=100; 
166     return;
167   }
168   //
169   aNbTools=myTools.Extent();
170   if (!aNbTools) { 
171     // invalid number of Tools
172     myErrorStatus=100;
173     return;
174   }
175   //
176   if (!myPaveFiller) {
177     myErrorStatus=101; 
178     return;
179   }
180   //
181   myErrorStatus=myPaveFiller->ErrorStatus();
182   if (myErrorStatus) {
183     return;
184   }
185   //
186   bFuse = (myOperation == BOPAlgo_FUSE);
187   //
188   // The rules for different types of operations are the following:
189   // 1. FUSE:   All arguments and tools should have the same dimension;
190   // 2. CUT:    The MAXIMAL dimension of the ARGUMENTS should be less
191   //            or equal to the MINIMAL dimension of the TOOLS;
192   // 3. CUT21:  The MINIMAL dimension of ARGUMENTS should be grater
193   //            or equal to the MAXIMAL dimension of the TOOLS;
194   // 4. COMMON: The arguments and tools could have any dimensions.
195   //
196   Standard_Integer iDimMin[2], iDimMax[2];
197   //
198   for (i=0; i<2; ++i) {
199     const BOPCol_ListOfShape& aLS=(!i)? myArguments : myTools;
200     aItLS.Initialize(aLS);
201     for (j=0; aItLS.More(); aItLS.Next(), ++j) {
202       const TopoDS_Shape& aS=aItLS.Value();
203       bFlag=BOPTools_AlgoTools3D::IsEmptyShape(aS);
204       if(bFlag) {
205         myWarningStatus=2;
206       }
207       //
208       iDim=BOPTools_AlgoTools::Dimension(aS);
209       if (iDim<0) {
210         // non-homogenious argument
211         myErrorStatus=13; 
212         return;
213       }
214       //
215       if (!j) {
216         iDimMin[i] = iDim;
217         iDimMax[i] = iDim;
218         continue;
219       }
220       //
221       if (iDim < iDimMin[i]) {
222         iDimMin[i] = iDim;
223       }
224       else if (iDim > iDimMax[i]) {
225         iDimMax[i] = iDim;
226       }
227       //
228       if (bFuse && (iDimMin[i] != iDimMax[i])) {
229         // non-homogenious argument
230         myErrorStatus=13;
231         return;
232       }
233     }
234   }
235   //
236   if (((myOperation == BOPAlgo_FUSE)  && (iDimMax[0] != iDimMax[1])) ||
237       ((myOperation == BOPAlgo_CUT)   && (iDimMax[0] >  iDimMin[1])) ||
238       ((myOperation == BOPAlgo_CUT21) && (iDimMin[0] <  iDimMax[1])) ) {
239     // non-licit operation for the arguments
240     myErrorStatus=14;
241     return;
242   }
243   //
244   myDims[0] = iDimMin[0];
245   myDims[1] = iDimMin[1];
246 }
247 //=======================================================================
248 //function : Prepare
249 //purpose  : 
250 //=======================================================================
251 void BOPAlgo_BOP::Prepare()
252 {
253   //
254   BOPAlgo_Builder::Prepare();
255   //
256   if(myWarningStatus == 2) {
257     Standard_Integer i;
258     BRep_Builder aBB;
259     BOPCol_ListIteratorOfListOfShape aItLS;
260     //
261     switch(myOperation) {
262       case BOPAlgo_FUSE: {
263         for (i=0; i<2; ++i) {
264           const BOPCol_ListOfShape& aLS=(!i)? myArguments : myTools;
265           aItLS.Initialize(aLS);
266           for (; aItLS.More(); aItLS.Next()) {
267             const TopoDS_Shape& aS=aItLS.Value();
268             aBB.Add(myShape, aS);
269           }
270         }
271       }
272         break;
273       //  
274       case BOPAlgo_CUT: {
275         aItLS.Initialize(myArguments);
276         for (; aItLS.More(); aItLS.Next()) {
277           const TopoDS_Shape& aS=aItLS.Value();
278           if(!BOPTools_AlgoTools3D::IsEmptyShape(aS)) {
279             aBB.Add(myShape, aS);
280           } 
281         }
282       }
283         break;
284       
285       case BOPAlgo_CUT21: {
286         aItLS.Initialize(myTools);
287         for (; aItLS.More(); aItLS.Next()) {
288           const TopoDS_Shape& aS=aItLS.Value();
289           if(!BOPTools_AlgoTools3D::IsEmptyShape(aS)) {
290             aBB.Add(myShape, aS);
291           } 
292         }
293       }
294         break;
295         //
296       default:
297         break;
298       }
299   }
300 }
301 //=======================================================================
302 //function : BuildResult
303 //purpose  : 
304 //=======================================================================
305 void BOPAlgo_BOP::BuildResult(const TopAbs_ShapeEnum theType)
306 {
307   TopAbs_ShapeEnum aType;
308   BRep_Builder aBB;
309   BOPCol_MapOfShape aM;
310   BOPCol_ListIteratorOfListOfShape aIt, aItIm;
311   //
312   myErrorStatus=0;
313   //
314   const BOPCol_ListOfShape& aLA=myDS->Arguments();
315   aIt.Initialize(aLA);
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();
325           if (aM.Add(aSIm)) {
326             aBB.Add(myShape, aSIm);
327           }
328         }
329       }
330       else {
331         if (aM.Add(aS)) {
332           aBB.Add(myShape, aS);
333         }
334       }
335     }
336   }
337 }
338 //=======================================================================
339 //function : Perform
340 //purpose  : 
341 //=======================================================================
342 void BOPAlgo_BOP::Perform()
343 {
344   Handle(NCollection_BaseAllocator) aAllocator;
345   BOPAlgo_PaveFiller* pPF;
346   BOPCol_ListIteratorOfListOfShape aItLS;
347   //
348   myErrorStatus=0;
349   //
350   if (myEntryPoint==1) {
351     if (myPaveFiller) {
352       delete myPaveFiller;
353       myPaveFiller=NULL;
354     }
355   }
356   //
357   aAllocator=
358     NCollection_BaseAllocator::CommonBaseAllocator();
359   BOPCol_ListOfShape aLS(aAllocator);
360   //
361   aItLS.Initialize(myArguments);
362   for (; aItLS.More(); aItLS.Next()) {
363     const TopoDS_Shape& aS=aItLS.Value();
364     aLS.Append(aS);
365   }
366   //
367   aItLS.Initialize(myTools);
368   for (; aItLS.More(); aItLS.Next()) {
369     const TopoDS_Shape& aS=aItLS.Value();
370     aLS.Append(aS);
371   }
372   //
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   //
380   pPF->Perform();
381   //
382   myEntryPoint=1;
383   PerformInternal(*pPF);
384 }
385 //=======================================================================
386 //function : PerformInternal1
387 //purpose  : 
388 //=======================================================================
389 void BOPAlgo_BOP::PerformInternal1(const BOPAlgo_PaveFiller& theFiller)
390 {
391   myErrorStatus=0;
392   myWarningStatus=0;
393   //
394   myPaveFiller=(BOPAlgo_PaveFiller*)&theFiller;
395   myDS=myPaveFiller->PDS();
396   myContext=myPaveFiller->Context();
397   //
398   // 1. CheckData
399   CheckData();
400   if (myErrorStatus && !myWarningStatus) {
401     return;
402   }
403   //
404   // 2. Prepare
405   Prepare();
406   if (myErrorStatus) {
407     return;
408   }
409   //
410   if(myWarningStatus == 2) {
411     return;
412   }
413   // 3. Fill Images
414   // 3.1 Vertices
415   FillImagesVertices();
416   if (myErrorStatus) {
417     return;
418   }
419   //
420   BuildResult(TopAbs_VERTEX);
421   if (myErrorStatus) {
422     return;
423   }
424   // 3.2 Edges
425   FillImagesEdges();
426   if (myErrorStatus) {
427     return;
428   }
429   //
430   BuildResult(TopAbs_EDGE);
431   if (myErrorStatus) {
432     return;
433   }
434   //
435   // 3.3 Wires
436   FillImagesContainers(TopAbs_WIRE);
437   if (myErrorStatus) {
438     return;
439   }
440   //
441   BuildResult(TopAbs_WIRE);
442   if (myErrorStatus) {
443     return;
444   }
445   //
446   // 3.4 Faces
447   FillImagesFaces();
448   if (myErrorStatus) {
449     return;
450   }
451   
452   BuildResult(TopAbs_FACE);
453   if (myErrorStatus) {
454     return;
455   }
456   //
457   // 3.5 Shells
458   FillImagesContainers(TopAbs_SHELL);
459   if (myErrorStatus) {
460     return;
461   }
462   //
463   BuildResult(TopAbs_SHELL);
464   if (myErrorStatus) {
465     return;
466   }
467   //
468   // 3.6 Solids
469   FillImagesSolids();
470   if (myErrorStatus) {
471     return;
472   }
473   //
474   BuildResult(TopAbs_SOLID);
475   if (myErrorStatus) {
476     return;
477   }
478   //
479   // 3.7 CompSolids
480   FillImagesContainers(TopAbs_COMPSOLID);
481   if (myErrorStatus) {
482     return;
483   }
484   //
485   BuildResult(TopAbs_COMPSOLID);
486   if (myErrorStatus) {
487     return;
488   }
489   //
490   // 3.8 Compounds
491   FillImagesCompounds();
492   if (myErrorStatus) {
493     return;
494   }
495   //
496   BuildResult(TopAbs_COMPOUND);
497   if (myErrorStatus) {
498     return;
499   }
500   //
501   // 4.BuildShape;
502   BuildShape();
503   if (myErrorStatus) {
504     return;
505   }
506   // 
507   // 5.History
508   PrepareHistory();
509   //
510   // 6 Post-treatment 
511   PostTreat();
512 }
513 //=======================================================================
514 //function : BuildRC
515 //purpose  : 
516 //=======================================================================
517 void BOPAlgo_BOP::BuildRC()
518 {
519   TopAbs_ShapeEnum aType;
520   TopoDS_Compound aC;
521   BRep_Builder aBB;
522   //
523   myErrorStatus = 0;
524   //
525   aBB.MakeCompound(aC);
526   //
527   // A. Fuse
528   if (myOperation == BOPAlgo_FUSE) {
529     BOPCol_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)) {
535         aBB.Add(aC, aS);
536       }
537     }
538     myRC = aC;
539     return;
540   }
541   //
542   // B. Common, Cut, Cut21
543   //
544   Standard_Integer i, j, aNb, iDim;
545   Standard_Boolean bCheckEdges, bContains, bCut21, bCommon;
546   BOPCol_IndexedMapOfShape aMArgs, aMTools;
547   BOPCol_IndexedMapOfShape aMArgsIm, aMToolsIm;
548   BOPCol_ListIteratorOfListOfShape aItLS;
549   //
550   for (i = 0; i < 2; ++i) {
551     const BOPCol_ListOfShape& aLS = !i ? myArguments : myTools;
552     BOPCol_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);
557       aType = TypeToExplore(iDim);
558       BOPTools::MapShapes(aS, aType, aMS);
559     }
560   }
561   //
562   bCheckEdges = Standard_False;
563   //
564   for (i = 0; i < 2; ++i) {
565     const BOPCol_IndexedMapOfShape& aMS = !i ? aMArgs : aMTools;
566     BOPCol_IndexedMapOfShape& aMSIm = !i ? aMArgsIm : aMToolsIm;
567     //
568     aNb = aMS.Extent();
569     for (j = 1; j <= aNb; ++j) {
570       const TopoDS_Shape& aS = aMS(j);
571       aType = aS.ShapeType();
572       if (aType == TopAbs_EDGE) {
573         const TopoDS_Edge& aE = *(TopoDS_Edge*)&aS;
574         bCheckEdges = Standard_True;
575         if (BRep_Tool::Degenerated(aE)) {
576           continue;
577         }
578       }
579       //
580       if (myImages.IsBound(aS)) {
581         const BOPCol_ListOfShape& aLSIm = myImages.Find(aS);
582         aItLS.Initialize(aLSIm);
583         for (; aItLS.More(); aItLS.Next()) {
584           const TopoDS_Shape& aSIm = aItLS.Value();
585           aMSIm.Add(aSIm);
586         }
587       }
588       else {
589         aMSIm.Add(aS);
590       }
591     }
592   }
593   //
594   // compare the maps and make the result
595   //
596   Standard_Integer iDimMin, iDimMax;
597   //
598   iDimMin = Min(myDims[0], myDims[1]);
599   bCommon = (myOperation == BOPAlgo_COMMON);
600   bCut21  = (myOperation == BOPAlgo_CUT21);
601   //
602   const BOPCol_IndexedMapOfShape& aMIt = bCut21 ? aMToolsIm : aMArgsIm;
603   const BOPCol_IndexedMapOfShape& aMCheck = bCut21 ? aMArgsIm : aMToolsIm;
604   //
605   BOPCol_IndexedMapOfShape aMCheckExp, aMItExp;
606   //
607   if (bCommon) {
608     aNb = aMIt.Extent();
609     for (i = 1; i <= aNb; ++i) {
610       const TopoDS_Shape& aS = aMIt(i);
611       iDimMax = BOPTools_AlgoTools::Dimension(aS);
612       for (iDim = iDimMin; iDim < iDimMax; ++iDim) {
613         aType = TypeToExplore(iDim);
614         BOPTools::MapShapes(aS, aType, aMItExp);
615       }
616       aMItExp.Add(aS);
617     }
618   }
619   else {
620     aMItExp = aMIt;
621   }
622   //
623   aNb = aMCheck.Extent();
624   for (i = 1; i <= aNb; ++i) {
625     const TopoDS_Shape& aS = aMCheck(i);
626     iDimMax = BOPTools_AlgoTools::Dimension(aS);
627     for (iDim = iDimMin; iDim < iDimMax; ++iDim) {
628       aType = TypeToExplore(iDim);
629       BOPTools::MapShapes(aS, aType, aMCheckExp);
630     }
631     aMCheckExp.Add(aS);
632   }
633   //
634   aNb = aMItExp.Extent();
635   for (i = 1; i <= aNb; ++i) {
636     const TopoDS_Shape& aS = aMItExp(i);
637     //
638     bContains = aMCheckExp.Contains(aS);
639     if (bCommon) {
640       if (bContains) {
641         aBB.Add(aC, aS);
642       }
643     }
644     else {
645       if (!bContains) {
646         aBB.Add(aC, aS);
647       }
648     }
649   }
650   //
651   // filter result for COMMON operation
652   if (bCommon) {
653     BOPCol_MapOfShape aMFence;
654     TopExp_Explorer aExp;
655     TopoDS_Compound aCx;
656     aBB.MakeCompound(aCx);
657     //
658     for (iDim = 3; iDim >= iDimMin; --iDim) {
659       aType = TypeToExplore(iDim);
660       aExp.Init(aC, aType);
661       for (; aExp.More(); aExp.Next()) {
662         const TopoDS_Shape& aS = aExp.Current();
663         if (aMFence.Add(aS)) {
664           aBB.Add(aCx, aS);
665           BOPTools::MapShapes(aS, aMFence);
666         }
667       }
668     }
669     aC = aCx;
670   }
671   //
672   if (!bCheckEdges) {
673     myRC = aC;
674     return;
675   }
676   //
677   // The squats around degenerated edges
678   Standard_Integer nVD;
679   BOPCol_IndexedMapOfShape aMVC;
680   //
681   // 1. Vertices of aC
682   BOPTools::MapShapes(aC, TopAbs_VERTEX, aMVC);
683   //
684   // 2. DE candidates
685   aNb = myDS->NbSourceShapes();
686   for (i = 0; i < aNb; ++i) {
687     const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
688     aType = aSI.ShapeType();
689     if (aType != TopAbs_EDGE) {
690       continue;
691     }
692     //
693     const TopoDS_Edge& aE = *((TopoDS_Edge*)&aSI.Shape());
694     if (!BRep_Tool::Degenerated(aE)) {
695       continue;
696     }
697     //
698     nVD = aSI.SubShapes().First();
699     const TopoDS_Shape& aVD = myDS->Shape(nVD);
700     //
701     if (!aMVC.Contains(aVD)) {
702       continue;
703     }
704     //
705     if (myDS->IsNewShape(nVD)) {
706       continue;
707     }
708     //
709     if (myDS->HasInterf(nVD)) {
710       continue;
711     }
712     //
713     aBB.Add(aC, aE);
714   }
715   //
716   myRC=aC;
717 }
718 //=======================================================================
719 //function : BuildShape
720 //purpose  : 
721 //=======================================================================
722 void BOPAlgo_BOP::BuildShape()
723 {
724   BuildRC();
725   //
726   if ((myOperation == BOPAlgo_FUSE) && (myDims[0] == 3)) {
727     BuildSolid();
728     return;
729   }
730   //
731   Standard_Integer i;
732   TopAbs_ShapeEnum aType, aT1, aT2;
733   TopTools_ListOfShape aLSC, aLCB;
734   BOPCol_ListIteratorOfListOfShape aItLS, aItLSIm, aItLCB;
735   TopoDS_Iterator aIt;
736   BRep_Builder aBB;
737   TopoDS_Shape aRC, aRCB;
738   //
739   TopoDS_Compound aResult;
740   aBB.MakeCompound(aResult);
741   //
742   BOPCol_MapOfShape aMSRC, aMFence;
743   BOPTools::MapShapes(myRC, aMSRC);
744   //
745   // collect images of containers
746   for (i = 0; i < 2; ++i) {
747     const BOPCol_ListOfShape& aLS = !i ? myArguments : myTools;
748     //
749     aItLS.Initialize(aLS);
750     for (; aItLS.More(); aItLS.Next()) {
751       const TopoDS_Shape& aS = aItLS.Value();
752       //
753       CollectContainers(aS, aLSC);
754     }
755   }
756   // make containers
757   aItLS.Initialize(aLSC);
758   for (; aItLS.More(); aItLS.Next()) {
759     const TopoDS_Shape& aSC = aItLS.Value();
760     //
761     BOPTools_AlgoTools::MakeContainer(TopAbs_COMPOUND, aRC);
762     //
763     aIt.Initialize(aSC);
764     for (; aIt.More(); aIt.Next()) {
765       const TopoDS_Shape& aS = aIt.Value();
766       if (myImages.IsBound(aS)) {
767         const TopTools_ListOfShape& aLSIm = myImages.Find(aS);
768         //
769         aItLSIm.Initialize(aLSIm);
770         for (; aItLSIm.More(); aItLSIm.Next()) {
771           const TopoDS_Shape& aSIm = aItLSIm.Value();
772           if (aMSRC.Contains(aSIm) && aMFence.Add(aSIm)) {
773             aBB.Add(aRC, aSIm);
774           }
775         }
776       }
777       else if (aMSRC.Contains(aS) && aMFence.Add(aS)) {
778         aBB.Add(aRC, aS);
779       }
780     }
781     //
782     aType = aSC.ShapeType();
783     switch (aType) {
784       case TopAbs_WIRE: {
785         aT1 = TopAbs_VERTEX;
786         aT2 = TopAbs_EDGE;
787         break;
788       }
789       case TopAbs_SHELL: {
790         aT1 = TopAbs_EDGE;
791         aT2 = TopAbs_FACE;
792         break;
793       }
794       default: {
795         aT1 = TopAbs_FACE;
796         aT2 = TopAbs_SOLID;
797       }
798     }
799     //
800     aLCB.Clear();
801     BOPTools_AlgoTools::MakeConnexityBlocks(aRC, aT1, aT2, aLCB);
802     if (aLCB.IsEmpty()) {
803       continue;
804     }
805     //
806     aItLCB.Initialize(aLCB);
807     for (; aItLCB.More(); aItLCB.Next()) {
808       BOPTools_AlgoTools::MakeContainer(aType, aRCB);
809       //
810       const TopoDS_Shape& aCB = aItLCB.Value();
811       aIt.Initialize(aCB);
812       for (; aIt.More(); aIt.Next()) {
813         const TopoDS_Shape& aCBS = aIt.Value();
814         aBB.Add(aRCB, aCBS);
815       }
816       //
817       if (aType == TopAbs_SHELL) {
818         BOPTools_AlgoTools::OrientFacesOnShell(aRCB);
819       }
820       //
821       aBB.Add(aResult, aRCB);
822     }
823   }
824   //
825   // add the rest of the shapes into result
826   BOPCol_MapOfShape aMSResult;
827   BOPTools::MapShapes(aResult, aMSResult);
828   //
829   aIt.Initialize(myRC);
830   for (; aIt.More(); aIt.Next()) {
831     const TopoDS_Shape& aS = aIt.Value();
832     if (!aMSResult.Contains(aS)) {
833       aBB.Add(aResult, aS);
834     }
835   }
836   //
837   myShape = aResult;
838 }
839 //=======================================================================
840 //function : BuildSolid
841 //purpose  : 
842 //=======================================================================
843 void BOPAlgo_BOP::BuildSolid()
844 {
845   Standard_Boolean bHasInterf, bHasSharedFaces;
846   Standard_Integer i, aNbF, aNbSx, iX, iErr, aNbZ;
847   TopAbs_Orientation aOr, aOr1;
848   TopoDS_Iterator aIt;
849   TopoDS_Shape aRC;
850   BRep_Builder aBB;
851   TopExp_Explorer aExp;
852   BOPCol_IndexedMapOfShape aMFI;
853   BOPCol_IndexedDataMapOfShapeListOfShape aMFS, aMEF;
854   BOPCol_ListIteratorOfListOfShape aItLS;
855   BOPCol_ListOfShape aSFS;
856   BOPAlgo_BuilderSolid aSB; 
857   BOPCol_MapOfShape aMSA, aMZ;
858   BOPTools_IndexedDataMapOfSetShape aDMSTS;
859   //
860   myErrorStatus=0;
861   //
862   // Map of of Solids of Arguments
863   for (i=0; i<2; ++i) {
864     const BOPCol_ListOfShape& aLSA=(i) ? myArguments : myTools;
865     aItLS.Initialize(aLSA);
866     for (; aItLS.More(); aItLS.Next()) {
867       const TopoDS_Shape& aSA=aItLS.Value();
868       aExp.Init(aSA, TopAbs_SOLID);
869       for (; aExp.More(); aExp.Next()) {
870         const TopoDS_Shape& aZA=aExp.Current();
871         aMSA.Add(aZA);
872         //
873         BOPTools::MapShapesAndAncestors(aZA, 
874                                         TopAbs_FACE, 
875                                         TopAbs_SOLID, 
876                                         aMFS);
877       }
878     }
879   }
880   //
881   aNbF=aMFS.Extent();
882   for (i=1; i<aNbF; ++i) {
883     //const TopoDS_Shape& aFA=aMFZA.FindKey(i);
884     const BOPCol_ListOfShape& aLZA=aMFS(i);
885     aNbZ=aLZA.Extent();
886     if (aNbZ > 1) {
887       aItLS.Initialize(aLZA);
888       for(; aItLS.More(); aItLS.Next()) {
889         const TopoDS_Shape& aZA=aItLS.Value();
890         aMZ.Add(aZA);
891       }
892     }
893   }
894   //
895   aMFS.Clear();
896   //
897   aIt.Initialize(myRC);
898   for (; aIt.More(); aIt.Next()) {
899     const TopoDS_Shape& aSx=aIt.Value(); 
900     if (aMSA.Contains(aSx)) {
901       iX=myDS->Index(aSx);
902       bHasInterf=myDS->HasInterf(iX);
903       bHasSharedFaces=aMZ.Contains(aSx);
904       //
905       if (!bHasInterf && !bHasSharedFaces) {
906         // It means that the solid aSx will be added
907         // to the result as is. 
908         // The solid aSx will not participate 
909         // in creation of a new solid(s).
910         BOPTools_Set aST;
911         //
912         aST.Add(aSx, TopAbs_FACE);
913         //
914         if (!aDMSTS.Contains(aST)) {
915           aDMSTS.Add(aST, aSx);
916         }
917         
918         continue; 
919       }
920     } 
921     //
922     aExp.Init(aSx, TopAbs_FACE);
923     for (; aExp.More(); aExp.Next()) {
924       const TopoDS_Shape& aFx=aExp.Current();
925       //
926       aOr=aFx.Orientation();
927       if (aOr==TopAbs_INTERNAL) {
928         aMFI.Add(aFx);
929         continue;
930       }
931       //
932       if (!aMFS.Contains(aFx)) {
933         BOPCol_ListOfShape aLSx;
934         //
935         aLSx.Append(aSx);
936         aMFS.Add(aFx, aLSx);
937       }
938       else {
939         iX=aMFS.FindIndex(aFx);
940         const TopoDS_Shape& aFx1=aMFS.FindKey(iX);
941         aOr1=aFx1.Orientation();
942         if (aOr1!=aOr) {
943           BOPCol_ListOfShape& aLSx=aMFS.ChangeFromKey(aFx);
944           aLSx.Append(aSx);
945           aMFS.Add(aFx, aLSx);
946         }
947       }
948     }
949   } // for (; aIt.More(); aIt.Next()) {
950   //faces that will be added in the end;
951   BOPCol_ListOfShape aLF, aLFx; 
952   // SFS
953   aNbF=aMFS.Extent();
954   for (i=1; i<=aNbF; ++i) {
955     const TopoDS_Shape& aFx=aMFS.FindKey(i);
956     const BOPCol_ListOfShape& aLSx=aMFS(i);
957     aNbSx=aLSx.Extent();
958     if (aNbSx==1) {
959       BOPTools::MapShapesAndAncestors
960         (aFx,TopAbs_EDGE, TopAbs_FACE, aMEF);
961       if (IsBoundSplits(aFx, aMEF)){
962         aLFx.Append(aFx);
963         continue;
964       }
965       aLF.Append(aFx);
966     }
967   }
968
969   aItLS.Initialize(aLF);
970   for(; aItLS.More(); aItLS.Next()) {
971     const TopoDS_Shape& aFx=aItLS.Value();
972     aSFS.Append(aFx);
973   }
974   // add faces from aLFx to aSFS;
975   aItLS.Initialize(aLFx);
976   for (; aItLS.More(); aItLS.Next()) {
977     const TopoDS_Shape& aFx=aItLS.Value();
978     aSFS.Append(aFx);
979   }
980   //
981   aNbF=aMFI.Extent();
982   for (i=1; i<=aNbF; ++i) {
983     TopoDS_Shape aFx;
984     //
985     aFx=aMFI.FindKey(i);
986     aFx.Orientation(TopAbs_FORWARD);
987     aSFS.Append(aFx);
988     aFx.Orientation(TopAbs_REVERSED);
989     aSFS.Append(aFx);
990   }
991   //
992   // BuilderSolid
993   BOPTools_AlgoTools::MakeContainer(TopAbs_COMPOUND, aRC);  
994   //
995   aSB.SetContext(myContext);
996   aSB.SetShapes(aSFS);
997   aSB.Perform();
998   iErr=aSB.ErrorStatus();
999   if (iErr) {
1000     myErrorStatus=30; // SolidBuilder failed
1001     return;
1002   }
1003   //
1004   const BOPCol_ListOfShape& aLSR=aSB.Areas();
1005   //
1006   aItLS.Initialize(aLSR);
1007   for (; aItLS.More(); aItLS.Next()) {
1008     const TopoDS_Shape& aSR=aItLS.Value();
1009     aBB.Add(aRC, aSR);
1010   }
1011   //
1012   aNbSx = aDMSTS.Extent();
1013   for (i = 1; i <= aNbSx; ++i) {
1014     const TopoDS_Shape& aSx = aDMSTS(i);
1015     aBB.Add(aRC, aSx);
1016   }
1017   //
1018   myShape=aRC;
1019 }
1020 //=======================================================================
1021 //function : IsBoundSplits
1022 //purpose  : 
1023 //=======================================================================
1024 Standard_Boolean BOPAlgo_BOP::IsBoundSplits
1025   (const TopoDS_Shape& aS,
1026    BOPCol_IndexedDataMapOfShapeListOfShape& aMEF)
1027 {
1028   Standard_Boolean bRet = Standard_False;
1029   if (mySplits.IsBound(aS) || myOrigins.IsBound(aS)) {
1030     return !bRet;
1031   }
1032
1033   BOPCol_ListIteratorOfListOfShape aIt;
1034   Standard_Integer aNbLS;
1035   TopAbs_Orientation anOr;
1036   //
1037   //check face aF may be connected to face from mySplits
1038   TopExp_Explorer aExp(aS, TopAbs_EDGE);
1039   for (; aExp.More(); aExp.Next()) {
1040     const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aExp.Current()));
1041     //
1042     anOr = aE.Orientation();
1043     if (anOr==TopAbs_INTERNAL) {
1044       continue;
1045     }
1046     //
1047     if (BRep_Tool::Degenerated(aE)) {
1048       continue;
1049     }
1050     //
1051     const BOPCol_ListOfShape& aLS=aMEF.FindFromKey(aE);
1052     aNbLS = aLS.Extent();
1053     if (!aNbLS) {
1054       continue;
1055     }
1056     //
1057     aIt.Initialize(aLS);
1058     for (; aIt.More(); aIt.Next()) {
1059       const TopoDS_Shape& aSx = aIt.Value();
1060       if (mySplits.IsBound(aSx) || myOrigins.IsBound(aS)) {
1061         return !bRet;
1062       }
1063     }
1064   }
1065   //
1066   return bRet;
1067 }
1068 //=======================================================================
1069 //function : TypeToExplore
1070 //purpose  : 
1071 //=======================================================================
1072 TopAbs_ShapeEnum TypeToExplore(const Standard_Integer theDim)
1073 {
1074   TopAbs_ShapeEnum aRet;
1075   //
1076   switch(theDim) {
1077   case 0:
1078     aRet=TopAbs_VERTEX;
1079     break;
1080   case 1:
1081     aRet=TopAbs_EDGE;
1082     break;
1083   case 2:
1084     aRet=TopAbs_FACE;
1085     break;
1086   case 3:
1087     aRet=TopAbs_SOLID;
1088     break;
1089   default:
1090     aRet=TopAbs_SHAPE;
1091     break;
1092   }
1093   return aRet;
1094 }
1095 //=======================================================================
1096 //function : CollectContainers
1097 //purpose  : 
1098 //=======================================================================
1099 void CollectContainers(const TopoDS_Shape& theS,
1100                        BOPCol_ListOfShape& theLSC)
1101 {
1102   TopAbs_ShapeEnum aType = theS.ShapeType();
1103   if (aType == TopAbs_WIRE ||
1104       aType == TopAbs_SHELL ||
1105       aType == TopAbs_COMPSOLID) {
1106     theLSC.Append(theS);
1107     return;
1108   }
1109   //
1110   if (aType != TopAbs_COMPOUND) {
1111     return;
1112   }
1113   //
1114   TopoDS_Iterator aIt(theS);
1115   for (; aIt.More(); aIt.Next()) {
1116     const TopoDS_Shape& aS = aIt.Value();
1117     CollectContainers(aS, theLSC);
1118   }
1119 }
1120