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