0025354: Intersection operation
[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   //
354   pPF->Perform();
355   //
356   myEntryPoint=1;
357   PerformInternal(*pPF);
358 }
359 //=======================================================================
360 //function : PerformInternal1
361 //purpose  : 
362 //=======================================================================
363 void BOPAlgo_BOP::PerformInternal1(const BOPAlgo_PaveFiller& theFiller)
364 {
365   myErrorStatus=0;
366   myWarningStatus=0;
367   //
368   myPaveFiller=(BOPAlgo_PaveFiller*)&theFiller;
369   myDS=myPaveFiller->PDS();
370   myContext=myPaveFiller->Context();
371   //
372   // 1. CheckData
373   CheckData();
374   if (myErrorStatus && !myWarningStatus) {
375     return;
376   }
377   //
378   // 2. Prepare
379   Prepare();
380   if (myErrorStatus) {
381     return;
382   }
383   //
384   if(myWarningStatus == 2) {
385     return;
386   }
387   // 3. Fill Images
388   // 3.1 Vertices
389   FillImagesVertices();
390   if (myErrorStatus) {
391     return;
392   }
393   //
394   BuildResult(TopAbs_VERTEX);
395   if (myErrorStatus) {
396     return;
397   }
398   // 3.2 Edges
399   FillImagesEdges();
400   if (myErrorStatus) {
401     return;
402   }
403   //
404   BuildResult(TopAbs_EDGE);
405   if (myErrorStatus) {
406     return;
407   }
408   //
409   // 3.3 Wires
410   FillImagesContainers(TopAbs_WIRE);
411   if (myErrorStatus) {
412     return;
413   }
414   //
415   BuildResult(TopAbs_WIRE);
416   if (myErrorStatus) {
417     return;
418   }
419   //
420   // 3.4 Faces
421   FillImagesFaces();
422   if (myErrorStatus) {
423     return;
424   }
425   
426   BuildResult(TopAbs_FACE);
427   if (myErrorStatus) {
428     return;
429   }
430   //
431   // 3.5 Shells
432   FillImagesContainers(TopAbs_SHELL);
433   if (myErrorStatus) {
434     return;
435   }
436   //
437   BuildResult(TopAbs_SHELL);
438   if (myErrorStatus) {
439     return;
440   }
441   //
442   // 3.6 Solids
443   FillImagesSolids();
444   if (myErrorStatus) {
445     return;
446   }
447   //
448   BuildResult(TopAbs_SOLID);
449   if (myErrorStatus) {
450     return;
451   }
452   //
453   // 3.7 CompSolids
454   FillImagesContainers(TopAbs_COMPSOLID);
455   if (myErrorStatus) {
456     return;
457   }
458   //
459   BuildResult(TopAbs_COMPSOLID);
460   if (myErrorStatus) {
461     return;
462   }
463   //
464   // 3.8 Compounds
465   FillImagesCompounds();
466   if (myErrorStatus) {
467     return;
468   }
469   //
470   BuildResult(TopAbs_COMPOUND);
471   if (myErrorStatus) {
472     return;
473   }
474   //
475   // 4.BuildShape;
476   BuildShape();
477   if (myErrorStatus) {
478     return;
479   }
480   // 
481   // 5.History
482   PrepareHistory();
483   //
484   // 6 Post-treatment 
485   PostTreat();
486 }
487 //=======================================================================
488 //function : BuildRC
489 //purpose  : 
490 //=======================================================================
491 void BOPAlgo_BOP::BuildRC()
492 {
493   Standard_Boolean bFlag1, bFlag2, bIsBound;
494   Standard_Integer aDmin;
495   TopAbs_ShapeEnum aTmin;
496   TopoDS_Compound aC;
497   TopoDS_Shape aSAIm, aSTIm;
498   BRep_Builder aBB;
499   TopExp_Explorer aExp;
500   BOPCol_DataMapOfShapeShape aDMSSA;
501   BOPCol_ListIteratorOfListOfShape aItLS, aItIm; 
502   Standard_Boolean bHasInterf;
503   Standard_Integer iX;
504   BOPTools_DataMapOfSetShape aDMSTS;
505   //
506   myErrorStatus=0;
507   //
508   aBB.MakeCompound(aC);
509   //
510   // A. Fuse
511   if (myOperation==BOPAlgo_FUSE) {
512     aTmin=TypeToExplore(myDims[0]);
513     aExp.Init(myShape, aTmin);
514     for (; aExp.More(); aExp.Next()) {
515       const TopoDS_Shape& aS=aExp.Current();
516       aBB.Add(aC, aS);
517     }
518     myRC=aC;
519     return;
520   } 
521   //
522   aDmin=myDims[1];
523   if (myDims[0] < myDims[1]) {
524     aDmin=myDims[0];
525   }
526   aTmin=TypeToExplore(aDmin);
527   //
528   // B. Common, Cut, Cut21
529   //
530   bFlag1=(myOperation==BOPAlgo_COMMON || myOperation==BOPAlgo_CUT21);
531   bFlag2=(myOperation==BOPAlgo_CUT || myOperation==BOPAlgo_CUT21);
532   //
533   const BOPCol_ListOfShape& aLA=( bFlag1) ? myArguments : myTools;
534   aItLS.Initialize(aLA);
535   for (; aItLS.More(); aItLS.Next()) {
536     const TopoDS_Shape& aSA=aItLS.Value();
537     //
538     if (myImages.IsBound(aSA)){
539       const BOPCol_ListOfShape& aLSAIm=myImages.Find(aSA);
540       aItIm.Initialize(aLSAIm);
541       for (; aItIm.More(); aItIm.Next()) {
542         const TopoDS_Shape& aSAIm=aItIm.Value();
543         aExp.Init(aSAIm, aTmin);
544         for (; aExp.More(); aExp.Next()) {
545           const TopoDS_Shape aSIm=aExp.Current();
546           aDMSSA.Bind(aSIm, aSIm);
547         }
548       }
549     }
550     //
551     else {
552       aExp.Init(aSA, aTmin);
553       for (; aExp.More(); aExp.Next()) {
554         const TopoDS_Shape aSIm=aExp.Current();
555         aDMSSA.Bind(aSIm, aSIm);
556         if (aTmin==TopAbs_SOLID) {
557           iX=myDS->Index(aSIm);
558           bHasInterf=myDS->HasInterf(iX);
559           if (!bHasInterf) {
560             BOPTools_Set aST;
561             //
562             aST.Add(aSIm, TopAbs_FACE);
563             //
564             aDMSTS.Bind(aST, aSIm);
565           }
566         }
567       }
568     }
569   } //for (; aItLS.More(); aItLS.Next())
570   //
571   const BOPCol_ListOfShape& aLT=(!bFlag1) ? myArguments : myTools;
572   aItLS.Initialize(aLT);
573   for (; aItLS.More(); aItLS.Next()) {
574     const TopoDS_Shape& aST=aItLS.Value();
575     if (myImages.IsBound(aST)){
576       const BOPCol_ListOfShape& aLSTIm=myImages.Find(aST);
577       aItIm.Initialize(aLSTIm);
578       for (; aItIm.More(); aItIm.Next()) {
579         const TopoDS_Shape& aSTIm=aItIm.Value();
580         aExp.Init(aSTIm, aTmin);
581         for (; aExp.More(); aExp.Next()) {
582           const TopoDS_Shape aSIm=aExp.Current();
583           // skip degenerated edges
584           if (aTmin==TopAbs_EDGE) {
585             const TopoDS_Edge& aEIm=*((TopoDS_Edge*)&aSIm);
586             if (BRep_Tool::Degenerated(aEIm)) {
587               continue;
588             }
589           }
590           //
591           bIsBound=aDMSSA.IsBound(aSIm);
592           if (!bFlag2) { // ie common
593             if (bIsBound) {
594               const TopoDS_Shape& aSImA=aDMSSA.Find(aSIm);
595               aBB.Add(aC, aSImA);
596             }
597           }
598           else {// ie cut or cut21
599             if (!bIsBound) {
600               aBB.Add(aC, aSIm);
601             }
602           }
603         }
604       }
605     }// if (myImages.IsBound(aST)){
606     else {
607       aExp.Init(aST, aTmin);
608       for (; aExp.More(); aExp.Next()) {
609         const TopoDS_Shape aSIm=aExp.Current();
610         // skip degenerated edges
611         if (aTmin==TopAbs_EDGE) {
612           const TopoDS_Edge& aEIm=*((TopoDS_Edge*)&aSIm);
613           if (BRep_Tool::Degenerated(aEIm)) {
614             continue;
615           }
616         }
617         bIsBound=aDMSSA.IsBound(aSIm);
618         if (!bFlag2) { // ie common
619           if (bIsBound) {
620             const TopoDS_Shape& aSImA=aDMSSA.Find(aSIm);
621             aBB.Add(aC, aSImA);
622           }
623           else {
624              if (aTmin==TopAbs_SOLID) {
625                BOPTools_Set aST;
626                //
627                aST.Add(aSIm, TopAbs_FACE);
628                //
629                if (aDMSTS.IsBound(aST)) {
630                  const TopoDS_Shape& aSImA=aDMSTS.Find(aST);
631                  aBB.Add(aC, aSImA);
632                }
633              }
634           }
635         }
636         else {// ie cut or cut21
637           if (!bIsBound) {
638             if (aTmin==TopAbs_SOLID) {
639               BOPTools_Set aST;
640               //
641               aST.Add(aSIm, TopAbs_FACE);
642               //
643               bIsBound=aDMSTS.IsBound(aST); 
644             }
645             //
646             if (!bIsBound) {
647               aBB.Add(aC, aSIm);
648             }
649           }
650         }
651       }
652     }
653   } //for (; aItLS.More(); aItLS.Next())
654   //
655   // the squats around degeneracy
656   if (aTmin!=TopAbs_EDGE) {
657     myRC=aC;
658     return;
659   }
660   //---------------------------------------------------------
661   //
662   // The squats around degenerated edges
663   Standard_Integer i, aNbS, nVD;
664   TopAbs_ShapeEnum aType;
665   BOPCol_IndexedMapOfShape aMVC;
666   //
667   // 1. Vertices of aC
668   BOPTools::MapShapes(aC, TopAbs_VERTEX, aMVC);
669   //
670   // 2. DE candidates
671   aNbS=myDS->NbSourceShapes();
672   for (i=0; i<aNbS; ++i) {
673     const BOPDS_ShapeInfo& aSI=myDS->ShapeInfo(i);
674     aType=aSI.ShapeType();
675     if (aType!=aTmin) {
676       continue;
677     }
678     //
679     const TopoDS_Edge& aE=*((TopoDS_Edge*)&aSI.Shape());
680     if (!BRep_Tool::Degenerated(aE)) {
681       continue;
682     }
683     //
684     nVD=aSI.SubShapes().First();
685     const TopoDS_Shape& aVD=myDS->Shape(nVD);
686     //
687     if (!aMVC.Contains(aVD)) {
688       continue;
689     }
690     //
691     if (myDS->IsNewShape(nVD)) {
692       continue;
693     }
694     //
695     if (myDS->HasInterf(nVD)) {
696       continue;
697     }
698     //
699     aBB.Add(aC, aE);
700   }
701   //
702   myRC=aC;
703 }
704 //=======================================================================
705 //function : BuildShape
706 //purpose  : 
707 //=======================================================================
708 void BOPAlgo_BOP::BuildShape()
709 {
710   Standard_Integer aDmin, aNbLCB;
711   TopAbs_ShapeEnum aT1, aT2, aTR;
712   TopoDS_Shape aR, aRC;
713   TopoDS_Iterator aIt;
714   BRep_Builder aBB;
715   BOPCol_ListOfShape aLCB;
716   BOPCol_ListIteratorOfListOfShape aItLCB;
717   //
718   myErrorStatus=0;
719   //
720   BuildRC();
721   //
722   aDmin=myDims[1];
723   if (myDims[0]<myDims[1]) {
724     aDmin=myDims[0];
725   }
726   //
727   if (!aDmin) {
728     myShape=myRC;
729     return;
730   }
731   //
732   else if (aDmin==1 || aDmin==2) { //edges, faces 
733     aT1=TopAbs_VERTEX;
734     aT2=TopAbs_EDGE;
735     aTR=TopAbs_WIRE;
736     if (aDmin==2) {
737       aT1=TopAbs_EDGE;
738       aT2=TopAbs_FACE;
739       aTR=TopAbs_SHELL;
740     }
741     //
742     BOPTools_AlgoTools::MakeConnexityBlocks
743       (myRC, aT1, aT2, aLCB);
744     aNbLCB=aLCB.Extent();
745     if (!aNbLCB) {
746       myShape=myRC;
747       return;
748     }
749     //
750     BOPTools_AlgoTools::MakeContainer(TopAbs_COMPOUND, aRC);  
751     //
752     aItLCB.Initialize(aLCB);
753     for (; aItLCB.More(); aItLCB.Next()) {
754       BOPTools_AlgoTools::MakeContainer(aTR, aR);  
755       //
756       const TopoDS_Shape& aCB=aItLCB.Value();
757       aIt.Initialize(aCB);
758       for (; aIt.More(); aIt.Next()) {
759         const TopoDS_Shape& aS=aIt.Value();
760         aBB.Add(aR, aS);
761       }
762       //
763       if (aTR==TopAbs_SHELL) {
764         BOPTools_AlgoTools::OrientFacesOnShell(aR);
765       }
766       //
767       aBB.Add(aRC, aR);
768     }
769     myShape=aRC;
770   }// elase if (aDmin==1 || aDmin==2) {
771   
772   else {//aDmin=3
773     Standard_Integer aNbObjs, aNbTools;
774     //
775     aNbObjs=myArguments.Extent();
776     aNbTools=myTools.Extent();
777     //
778     if (aNbObjs==1 && aNbTools==1) {
779       if (myOperation==BOPAlgo_FUSE) {
780         BuildSolid();
781       }
782       else {
783         myShape=myRC;
784       }
785     }
786     else {
787       BuildSolid();
788     }
789   }
790 }
791 //=======================================================================
792 //function : BuildSolid
793 //purpose  : 
794 //=======================================================================
795 void BOPAlgo_BOP::BuildSolid()
796 {
797   Standard_Boolean bHasInterf, bHasSharedFaces;
798   Standard_Integer i, aNbF, aNbSx, iX, iErr, aNbZ;
799   TopAbs_Orientation aOr, aOr1;
800   TopoDS_Iterator aIt;
801   TopoDS_Shape aRC;
802   BRep_Builder aBB;
803   TopExp_Explorer aExp;
804   BOPCol_IndexedMapOfShape aMFI;
805   BOPCol_IndexedDataMapOfShapeListOfShape aMFS, aMEF;
806   BOPCol_ListIteratorOfListOfShape aItLS;
807   BOPCol_ListOfShape aSFS;
808   BOPAlgo_BuilderSolid aSB; 
809   BOPCol_MapOfShape aMSA, aMZ;
810   BOPTools_DataMapOfSetShape aDMSTS;
811   BOPTools_DataMapIteratorOfDataMapOfSetShape aItDMSTS;
812   //
813   myErrorStatus=0;
814   //
815   // Map of of Solids of Arguments
816   for (i=0; i<2; ++i) {
817     const BOPCol_ListOfShape& aLSA=(i) ? myArguments : myTools;
818     aItLS.Initialize(aLSA);
819     for (; aItLS.More(); aItLS.Next()) {
820       const TopoDS_Shape& aSA=aItLS.Value();
821       aExp.Init(aSA, TopAbs_SOLID);
822       for (; aExp.More(); aExp.Next()) {
823         const TopoDS_Shape& aZA=aExp.Current();
824         aMSA.Add(aZA);
825         //
826         BOPTools::MapShapesAndAncestors(aZA, 
827                                         TopAbs_FACE, 
828                                         TopAbs_SOLID, 
829                                         aMFS);
830       }
831     }
832   }
833   //
834   aNbF=aMFS.Extent();
835   for (i=1; i<aNbF; ++i) {
836     //const TopoDS_Shape& aFA=aMFZA.FindKey(i);
837     const BOPCol_ListOfShape& aLZA=aMFS(i);
838     aNbZ=aLZA.Extent();
839     if (aNbZ > 1) {
840       aItLS.Initialize(aLZA);
841       for(; aItLS.More(); aItLS.Next()) {
842         const TopoDS_Shape& aZA=aItLS.Value();
843         aMZ.Add(aZA);
844       }
845     }
846   }
847   //
848   aMFS.Clear();
849   //
850   aIt.Initialize(myRC);
851   for (; aIt.More(); aIt.Next()) {
852     const TopoDS_Shape& aSx=aIt.Value(); 
853     if (aMSA.Contains(aSx)) {
854       iX=myDS->Index(aSx);
855       bHasInterf=myDS->HasInterf(iX);
856       bHasSharedFaces=aMZ.Contains(aSx);
857       //
858       if (!bHasInterf && !bHasSharedFaces) {
859         // It means that the solid aSx will be added
860         // to the result as is. 
861         // The solid aSx will not participate 
862         // in creation of a new solid(s).
863         BOPTools_Set aST;
864         //
865         aST.Add(aSx, TopAbs_FACE);
866         //
867         if (!aDMSTS.IsBound(aST)) {
868           aDMSTS.Bind(aST, aSx);
869         }
870         
871         continue; 
872       }
873     } 
874     //
875     aExp.Init(aSx, TopAbs_FACE);
876     for (; aExp.More(); aExp.Next()) {
877       const TopoDS_Shape& aFx=aExp.Current();
878       //
879       aOr=aFx.Orientation();
880       if (aOr==TopAbs_INTERNAL) {
881         aMFI.Add(aFx);
882         continue;
883       }
884       //
885       if (!aMFS.Contains(aFx)) {
886         BOPCol_ListOfShape aLSx;
887         //
888         aLSx.Append(aSx);
889         aMFS.Add(aFx, aLSx);
890       }
891       else {
892         iX=aMFS.FindIndex(aFx);
893         const TopoDS_Shape& aFx1=aMFS.FindKey(iX);
894         aOr1=aFx1.Orientation();
895         if (aOr1!=aOr) {
896           BOPCol_ListOfShape& aLSx=aMFS.ChangeFromKey(aFx);
897           aLSx.Append(aSx);
898           aMFS.Add(aFx, aLSx);
899         }
900       }
901     }
902   } // for (; aIt.More(); aIt.Next()) {
903   //faces that will be added in the end;
904   BOPCol_ListOfShape aLF, aLFx; 
905   // SFS
906   aNbF=aMFS.Extent();
907   for (i=1; i<=aNbF; ++i) {
908     const TopoDS_Shape& aFx=aMFS.FindKey(i);
909     const BOPCol_ListOfShape& aLSx=aMFS(i);
910     aNbSx=aLSx.Extent();
911     if (aNbSx==1) {
912       BOPTools::MapShapesAndAncestors
913         (aFx,TopAbs_EDGE, TopAbs_FACE, aMEF);
914       if (IsBoundSplits(aFx, aMEF)){
915         aLFx.Append(aFx);
916         continue;
917       }
918       aLF.Append(aFx);
919     }
920   }
921
922   aItLS.Initialize(aLF);
923   for(; aItLS.More(); aItLS.Next()) {
924     const TopoDS_Shape& aFx=aItLS.Value();
925     aSFS.Append(aFx);
926   }
927   // add faces from aLFx to aSFS;
928   aItLS.Initialize(aLFx);
929   for (; aItLS.More(); aItLS.Next()) {
930     const TopoDS_Shape& aFx=aItLS.Value();
931     aSFS.Append(aFx);
932   }
933   //
934   aNbF=aMFI.Extent();
935   for (i=1; i<=aNbF; ++i) {
936     TopoDS_Shape aFx;
937     //
938     aFx=aMFI.FindKey(i);
939     aFx.Orientation(TopAbs_FORWARD);
940     aSFS.Append(aFx);
941     aFx.Orientation(TopAbs_REVERSED);
942     aSFS.Append(aFx);
943   }
944   //
945   // BuilderSolid
946   BOPTools_AlgoTools::MakeContainer(TopAbs_COMPOUND, aRC);  
947   //
948   aSB.SetContext(myContext);
949   aSB.SetShapes(aSFS);
950   aSB.Perform();
951   iErr=aSB.ErrorStatus();
952   if (iErr) {
953     myErrorStatus=30; // SolidBuilder failed
954     return;
955   }
956   //
957   const BOPCol_ListOfShape& aLSR=aSB.Areas();
958   //
959   aItLS.Initialize(aLSR);
960   for (; aItLS.More(); aItLS.Next()) {
961     const TopoDS_Shape& aSR=aItLS.Value();
962     aBB.Add(aRC, aSR);
963   }
964   //
965   aItDMSTS.Initialize(aDMSTS);
966   for (; aItDMSTS.More(); aItDMSTS.Next()) {
967     const TopoDS_Shape& aSx=aItDMSTS.Value();
968     aBB.Add(aRC, aSx);
969   }
970   //
971   myShape=aRC;
972 }
973 //=======================================================================
974 //function : IsBoundSplits
975 //purpose  : 
976 //=======================================================================
977 Standard_Boolean BOPAlgo_BOP::IsBoundSplits
978   (const TopoDS_Shape& aS,
979    BOPCol_IndexedDataMapOfShapeListOfShape& aMEF)
980 {
981   Standard_Boolean bRet = Standard_False;
982   if (mySplits.IsBound(aS) || myOrigins.IsBound(aS)) {
983     return !bRet;
984   }
985
986   BOPCol_ListIteratorOfListOfShape aIt;
987   Standard_Integer aNbLS;
988   TopAbs_Orientation anOr;
989   //
990   //check face aF may be connected to face from mySplits
991   TopExp_Explorer aExp(aS, TopAbs_EDGE);
992   for (; aExp.More(); aExp.Next()) {
993     const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aExp.Current()));
994     //
995     anOr = aE.Orientation();
996     if (anOr==TopAbs_INTERNAL) {
997       continue;
998     }
999     //
1000     if (BRep_Tool::Degenerated(aE)) {
1001       continue;
1002     }
1003     //
1004     const BOPCol_ListOfShape& aLS=aMEF.FindFromKey(aE);
1005     aNbLS = aLS.Extent();
1006     if (!aNbLS) {
1007       continue;
1008     }
1009     //
1010     aIt.Initialize(aLS);
1011     for (; aIt.More(); aIt.Next()) {
1012       const TopoDS_Shape& aSx = aIt.Value();
1013       if (mySplits.IsBound(aSx) || myOrigins.IsBound(aS)) {
1014         return !bRet;
1015       }
1016     }
1017   }
1018   //
1019   return bRet;
1020 }
1021 //=======================================================================
1022 //function : TypeToExplore
1023 //purpose  : 
1024 //=======================================================================
1025 TopAbs_ShapeEnum TypeToExplore(const Standard_Integer theDim)
1026 {
1027   TopAbs_ShapeEnum aRet;
1028   //
1029   switch(theDim) {
1030   case 0:
1031     aRet=TopAbs_VERTEX;
1032     break;
1033   case 1:
1034     aRet=TopAbs_EDGE;
1035     break;
1036   case 2:
1037     aRet=TopAbs_FACE;
1038     break;
1039   case 3:
1040     aRet=TopAbs_SOLID;
1041     break;
1042   default:
1043     aRet=TopAbs_SHAPE;
1044     break;
1045   }
1046   return aRet;
1047 }