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