0033661: Data Exchange, Step Import - Tessellated GDTs are not imported
[occt.git] / src / BOPAlgo / BOPAlgo_BuilderSolid.cxx
1 // Created by: Peter KURNEV
2 // Copyright (c) 2010-2014 OPEN CASCADE SAS
3 // Copyright (c) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE
4 // Copyright (c) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT,
5 //                         EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 //
7 // This file is part of Open CASCADE Technology software library.
8 //
9 // This library is free software; you can redistribute it and/or modify it under
10 // the terms of the GNU Lesser General Public License version 2.1 as published
11 // by the Free Software Foundation, with special exception defined in the file
12 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
13 // distribution for complete text of the license and disclaimer of any warranty.
14 //
15 // Alternatively, this file may be used under the terms of Open CASCADE
16 // commercial license or contractual agreement.
17 //
18 #include <BOPAlgo_BuilderSolid.hxx>
19 #include <BOPAlgo_ShellSplitter.hxx>
20 #include <BOPAlgo_Alerts.hxx>
21 #include <BOPAlgo_Tools.hxx>
22 #include <BOPTools_AlgoTools.hxx>
23 #include <BOPTools_BoxTree.hxx>
24 #include <BOPTools_Parallel.hxx>
25 #include <Bnd_Tools.hxx>
26 #include <BRep_Builder.hxx>
27 #include <BRep_Tool.hxx>
28 #include <BRepBndLib.hxx>
29 #include <BRepClass3d_SolidClassifier.hxx>
30 #include <IntTools_Context.hxx>
31 #include <NCollection_DataMap.hxx>
32 #include <NCollection_List.hxx>
33 #include <TopExp.hxx>
34 #include <TopExp_Explorer.hxx>
35 #include <TopoDS.hxx>
36 #include <TopoDS_Compound.hxx>
37 #include <TopoDS_Edge.hxx>
38 #include <TopoDS_Face.hxx>
39 #include <TopoDS_Iterator.hxx>
40 #include <TopoDS_Shape.hxx>
41 #include <TopoDS_Shell.hxx>
42 #include <TopoDS_Solid.hxx>
43 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
44 #include <TopTools_IndexedDataMapOfShapeShape.hxx>
45 #include <TColStd_ListOfInteger.hxx>
46 #include <TopTools_ListOfShape.hxx>
47 #include <TopTools_MapOfOrientedShape.hxx>
48 #include <TopTools_MapOfShape.hxx>
49
50 //
51 static
52   Standard_Boolean IsGrowthShell(const TopoDS_Shape& ,
53                                  const TopTools_IndexedMapOfShape& );
54 static
55   Standard_Boolean IsHole(const TopoDS_Shape& ,
56                           Handle(IntTools_Context)& );
57 static
58   Standard_Boolean IsInside(const TopoDS_Shape& ,
59                             const TopoDS_Shape& ,
60                             Handle(IntTools_Context)& );
61 static
62   void MakeInternalShells(const TopTools_IndexedMapOfShape& ,
63                           TopTools_ListOfShape& );
64
65 //=======================================================================
66 //function : 
67 //purpose  : 
68 //=======================================================================
69 BOPAlgo_BuilderSolid::BOPAlgo_BuilderSolid()
70 :
71   BOPAlgo_BuilderArea()
72 {
73 }
74 //=======================================================================
75 //function : 
76 //purpose  : 
77 //=======================================================================
78 BOPAlgo_BuilderSolid::BOPAlgo_BuilderSolid
79   (const Handle(NCollection_BaseAllocator)& theAllocator)
80 :
81   BOPAlgo_BuilderArea(theAllocator)
82 {
83 }
84 //=======================================================================
85 //function : ~
86 //purpose  : 
87 //=======================================================================
88 BOPAlgo_BuilderSolid::~BOPAlgo_BuilderSolid()
89 {
90 }
91 //=======================================================================
92 //function : Perform
93 //purpose  : 
94 //=======================================================================
95 void BOPAlgo_BuilderSolid::Perform(const Message_ProgressRange& theRange)
96 {
97   Message_ProgressScope aPS (theRange, NULL, 100);  
98
99   GetReport()->Clear();
100   //
101   if (myShapes.IsEmpty())
102     return;
103
104   if (myContext.IsNull()) {
105     myContext=new IntTools_Context;
106   }
107
108   myBoxes.Clear();
109
110   TopoDS_Compound aC;
111   BRep_Builder aBB;
112   TopTools_ListIteratorOfListOfShape aIt;
113   //
114   aBB.MakeCompound(aC);
115   aIt.Initialize(myShapes);
116   for(; aIt.More(); aIt.Next()) {
117     const TopoDS_Shape& aF=aIt.Value();
118     aBB.Add(aC, aF);
119   }
120   //
121   PerformShapesToAvoid (aPS.Next(1));
122   if (HasErrors()) {
123     return;
124   }
125   //
126   PerformLoops (aPS.Next(10));
127   if (HasErrors()) {
128     return;
129   }
130   //
131   PerformAreas (aPS.Next(80));
132   if (HasErrors()) {
133     return;
134   }
135   //
136   PerformInternalShapes (aPS.Next(9));
137 }
138 //=======================================================================
139 //function :PerformShapesToAvoid
140 //purpose  : 
141 //=======================================================================
142 void BOPAlgo_BuilderSolid::PerformShapesToAvoid(const Message_ProgressRange& theRange)
143 {
144   Standard_Boolean bFound;
145   Standard_Integer i, aNbE, aNbF;
146   TopAbs_Orientation aOrE;
147   TopTools_IndexedDataMapOfShapeListOfShape aMEF;
148   TopTools_ListIteratorOfListOfShape aIt;
149   //
150   myShapesToAvoid.Clear();
151   //
152   Message_ProgressScope aPS(theRange, NULL, 1);
153   //
154   for(;;) {
155     if (UserBreak(aPS)) {
156       return;
157     }
158     bFound=Standard_False;
159     //
160     // 1. MEF
161     aMEF.Clear();
162     aIt.Initialize (myShapes);
163     for (; aIt.More(); aIt.Next()) {
164       const TopoDS_Shape& aF=aIt.Value();
165       if (!myShapesToAvoid.Contains(aF)) {
166         TopExp::MapShapesAndAncestors(aF, 
167                                         TopAbs_EDGE, 
168                                         TopAbs_FACE, 
169                                         aMEF);
170       }
171     }
172     aNbE=aMEF.Extent();
173     //
174     // 2. myFacesToAvoid
175     for (i=1; i<=aNbE; ++i) {
176       const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aMEF.FindKey(i)));
177       if (BRep_Tool::Degenerated(aE)) {
178         continue;
179       }
180       //
181       TopTools_ListOfShape& aLF=aMEF.ChangeFromKey(aE);
182       aNbF=aLF.Extent();
183       if (!aNbF) {
184         continue;
185       }
186       //
187       aOrE=aE.Orientation();
188       //
189       const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First()));
190       if (aNbF==1) {
191         if (aOrE==TopAbs_INTERNAL) {
192           continue;
193         }
194         bFound=Standard_True;
195         myShapesToAvoid.Add(aF1);
196       }
197       else if (aNbF==2) {
198         const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aLF.Last()));
199         if (aF2.IsSame(aF1)) {
200           if (BRep_Tool::IsClosed(aE, aF1)) {
201             continue;
202           }
203           //
204           if (aOrE==TopAbs_INTERNAL) {
205             continue;
206           }
207           //
208           bFound=Standard_True;
209           myShapesToAvoid.Add(aF1);
210           myShapesToAvoid.Add(aF2);
211         }
212       }
213     }// for (i=1; i<=aNbE; ++i) {
214     //
215     if (!bFound) {
216       break;
217     }
218     //
219   }//for(;;) {
220 }  
221 //=======================================================================
222 //function : PerformLoops
223 //purpose  : 
224 //=======================================================================
225 void BOPAlgo_BuilderSolid::PerformLoops(const Message_ProgressRange& theRange)
226 {
227   Standard_Integer i, aNbSh;
228   TopTools_ListIteratorOfListOfShape aIt;
229   TopoDS_Iterator aItS;
230   Handle(NCollection_BaseAllocator) aAlr;
231   // 
232   myLoops.Clear();
233   //
234   aAlr=
235     NCollection_BaseAllocator::CommonBaseAllocator();
236   BOPAlgo_ShellSplitter aSSp(aAlr);
237   //
238   Message_ProgressScope aMainScope (theRange, "Building shells", 10); 
239
240   // 1. Shells Usual 
241   aIt.Initialize (myShapes);
242   for (; aIt.More(); aIt.Next()) {
243     const TopoDS_Face& aF=*((TopoDS_Face*)&aIt.Value());
244     if (myContext->IsInfiniteFace(aF)) {
245       TopoDS_Shell aSh;
246       BRep_Builder aBB;
247       //
248       aBB.MakeShell(aSh);
249       aBB.Add(aSh, aF);
250       myLoops.Append(aSh);
251       continue;
252     }
253     //
254     if (!myShapesToAvoid.Contains(aF)) {
255       aSSp.AddStartElement(aF);
256     }
257   }
258   //
259   aSSp.SetRunParallel(myRunParallel);
260   aSSp.Perform(aMainScope.Next(9));
261   if (aSSp.HasErrors()) {
262     // add warning status
263     if (aMainScope.More())
264     {
265       TopoDS_Compound aFacesSp;
266       BRep_Builder().MakeCompound(aFacesSp);
267       TopTools_ListIteratorOfListOfShape aItLF(aSSp.StartElements());
268       for (; aItLF.More(); aItLF.Next()) {
269         BRep_Builder().Add(aFacesSp, aItLF.Value());
270       }
271       AddWarning (new BOPAlgo_AlertShellSplitterFailed (aFacesSp));
272     }
273     return;
274   }
275   //
276   const TopTools_ListOfShape& aLSh=aSSp.Shells();
277   aIt.Initialize (aLSh);
278   for (; aIt.More(); aIt.Next()) {
279     const TopoDS_Shape& aSh=aIt.Value();
280     myLoops.Append(aSh);
281   }
282   //=================================================
283   //
284   // 2. Post Treatment
285   BRep_Builder aBB;
286   TopTools_MapOfOrientedShape AddedFacesMap;
287   TopTools_IndexedDataMapOfShapeListOfShape aEFMap;
288   TopTools_MapOfOrientedShape aMP;
289   //
290   // a. collect all edges that are in loops
291   aIt.Initialize (myLoops);
292   for (; aIt.More(); aIt.Next()) {
293     const TopoDS_Shape& aS=aIt.Value();
294     aItS.Initialize(aS);
295     for (; aItS.More(); aItS.Next()) {
296       const TopoDS_Shape& aF=aItS.Value();
297       aMP.Add(aF);
298     }
299   }
300   if (UserBreak (aMainScope)) {
301     return;
302   }
303   // 
304   // b. collect all edges that are to avoid
305   aNbSh = myShapesToAvoid.Extent();
306   for (i = 1; i <= aNbSh; ++i) {
307     const TopoDS_Shape& aF = myShapesToAvoid(i);
308     aMP.Add(aF);
309   }
310   //
311   // c. add all edges that are not processed to myShapesToAvoid
312   aIt.Initialize (myShapes);
313   for (; aIt.More(); aIt.Next()) {
314     const TopoDS_Face& aF=*((TopoDS_Face*)&aIt.Value());
315     if (!myContext->IsInfiniteFace(aF)) {
316       if (!aMP.Contains(aF)) {
317         myShapesToAvoid.Add(aF);
318       }
319     }
320   }
321   //=================================================
322   if (UserBreak (aMainScope)) {
323     return;
324   }
325   //
326   // 3.Internal Shells
327   myLoopsInternal.Clear();
328   //
329   aEFMap.Clear();
330   AddedFacesMap.Clear();
331   //
332   aNbSh = myShapesToAvoid.Extent();
333   for (i = 1; i <= aNbSh; ++i) {
334     const TopoDS_Shape& aFF = myShapesToAvoid(i);
335     TopExp::MapShapesAndAncestors(aFF, 
336         TopAbs_EDGE, TopAbs_FACE, 
337         aEFMap);
338   }
339   //
340   for (i = 1; i <= aNbSh; ++i) {
341     if (UserBreak(aMainScope)) {
342       return;
343     }
344     const TopoDS_Shape& aFF = myShapesToAvoid(i);
345     if (!AddedFacesMap.Add(aFF)) {
346       continue;
347     }
348     //
349     // make a new shell
350     TopExp_Explorer aExp;
351     TopoDS_Shell aShell;
352     aBB.MakeShell(aShell);
353     aBB.Add(aShell, aFF);
354     //
355     aItS.Initialize(aShell);
356     for (; aItS.More(); aItS.Next()) {
357       const TopoDS_Face& aF = (*(TopoDS_Face*)(&aItS.Value()));
358       //
359       aExp.Init(aF, TopAbs_EDGE);
360       for (; aExp.More(); aExp.Next()) {
361         const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aExp.Current()));
362         const TopTools_ListOfShape& aLF=aEFMap.FindFromKey(aE);
363         aIt.Initialize(aLF);
364         for (; aIt.More(); aIt.Next()) { 
365           const TopoDS_Face& aFL=(*(TopoDS_Face*)(&aIt.Value()));
366           if (AddedFacesMap.Add(aFL)){
367             aBB.Add(aShell, aFL);
368           }
369         }
370       }
371     }
372     aShell.Closed (BRep_Tool::IsClosed (aShell));
373     myLoopsInternal.Append(aShell);
374   }
375 }
376 //=======================================================================
377 //function : PerformAreas
378 //purpose  : 
379 //=======================================================================
380 void BOPAlgo_BuilderSolid::PerformAreas(const Message_ProgressRange& theRange)
381 {
382   myAreas.Clear();
383   BRep_Builder aBB;
384   // The new solids
385   TopTools_ListOfShape aNewSolids;
386   // The hole shells which has to be classified relatively new solids
387   TopTools_IndexedMapOfShape aHoleShells;
388   // Map of the faces of the hole shells for quick check of the growths.
389   // If the analyzed shell contains any of the hole faces, it is considered as growth.
390   TopTools_IndexedMapOfShape aMHF;
391
392   Message_ProgressScope aMainScope(theRange, "Building solids", 10);
393
394   // Analyze the shells
395   Message_ProgressScope aPSClass(aMainScope.Next(5), "Classify solids", myLoops.Size());
396   TopTools_ListIteratorOfListOfShape aItLL(myLoops);
397   for (; aItLL.More(); aItLL.Next(), aPSClass.Next())
398   {
399     if (UserBreak (aPSClass))
400     {
401       return;
402     }
403     const TopoDS_Shape& aShell = aItLL.Value();
404
405     Standard_Boolean bIsGrowth = IsGrowthShell(aShell, aMHF);
406     if (!bIsGrowth)
407     {
408       // Fast check did not give the result, run classification
409       bIsGrowth = !IsHole(aShell, myContext);
410     }
411
412     // Save the solid
413     if (bIsGrowth)
414     {
415       TopoDS_Solid aSolid;
416       aBB.MakeSolid(aSolid);
417       aBB.Add (aSolid, aShell);
418       aNewSolids.Append (aSolid);
419     }
420     else
421     {
422       aHoleShells.Add(aShell);
423       TopExp::MapShapes(aShell, TopAbs_FACE, aMHF);
424     }
425   }
426
427   if (aHoleShells.IsEmpty())
428   {
429     // No holes, stop the analysis
430     TopTools_ListIteratorOfListOfShape aItLS(aNewSolids);
431     for (; aItLS.More(); aItLS.Next())
432     {
433       const TopoDS_Shape& aSol = aItLS.Value();
434       myAreas.Append(aSol);
435       // Build box
436       Bnd_Box aBox;
437       BRepBndLib::Add(aSol, aBox);
438       myBoxes.Bind(aSol, aBox);
439     }
440     return;
441   }
442
443   // Classify holes relatively solids
444
445   // Prepare tree with the boxes of the hole shells
446   BOPTools_BoxTree aBBTree;
447   Standard_Integer i, aNbH = aHoleShells.Extent();
448   aBBTree.SetSize (aNbH);
449   for (i = 1; i <= aNbH; ++i)
450   {
451     const TopoDS_Shape& aHShell = aHoleShells(i);
452     //
453     Bnd_Box aBox;
454     BRepBndLib::Add(aHShell, aBox);
455     aBBTree.Add(i, Bnd_Tools::Bnd2BVH(aBox));
456
457     myBoxes.Bind(aHShell, aBox);
458   }
459
460   // Build BVH
461   aBBTree.Build();
462
463   // Find outer growth shell that is most close to each hole shell
464   TopTools_IndexedDataMapOfShapeShape aHoleSolidMap;
465
466   Message_ProgressScope aPSH(aMainScope.Next(4), "Adding holes", aNewSolids.Size());
467   TopTools_ListIteratorOfListOfShape aItLS(aNewSolids);
468   for (; aItLS.More(); aItLS.Next(), aPSH.Next())
469   {
470     if (UserBreak (aPSH))
471     {
472       return;
473     }
474     const TopoDS_Shape& aSolid = aItLS.Value();
475
476     // Build box
477     Bnd_Box aBox;
478     BRepBndLib::Add(aSolid, aBox);
479
480     myBoxes.Bind(aSolid, aBox);
481
482     BOPTools_BoxTreeSelector aSelector;
483     aSelector.SetBox(Bnd_Tools::Bnd2BVH(aBox));
484     aSelector.SetBVHSet (&aBBTree);
485     aSelector.Select();
486
487     const TColStd_ListOfInteger& aLI = aSelector.Indices();
488     TColStd_ListIteratorOfListOfInteger aItLI(aLI);
489     for (; aItLI.More(); aItLI.Next())
490     {
491       Standard_Integer k = aItLI.Value();
492       const TopoDS_Shape& aHole = aHoleShells(k);
493       // Check if it is inside
494       if (!IsInside(aHole, aSolid, myContext))
495         continue;
496
497       // Save the relation
498       TopoDS_Shape* pSolidWas = aHoleSolidMap.ChangeSeek(aHole);
499       if (pSolidWas)
500       {
501         if (IsInside(aSolid, *pSolidWas, myContext))
502         {
503           *pSolidWas = aSolid;
504         }
505       }
506       else
507       {
508         aHoleSolidMap.Add(aHole, aSolid);
509       }
510     }
511   }
512
513   // Make the back map from solids to holes
514   TopTools_IndexedDataMapOfShapeListOfShape aSolidHolesMap;
515
516   aNbH = aHoleSolidMap.Extent();
517   for (i = 1; i <= aNbH; ++i)
518   {
519     const TopoDS_Shape& aHole = aHoleSolidMap.FindKey(i);
520     const TopoDS_Shape& aSolid = aHoleSolidMap(i);
521     //
522     TopTools_ListOfShape* pLHoles = aSolidHolesMap.ChangeSeek(aSolid);
523     if (!pLHoles)
524       pLHoles = &aSolidHolesMap(aSolidHolesMap.Add(aSolid, TopTools_ListOfShape()));
525     pLHoles->Append(aHole);
526   }
527
528   // Add Holes to Solids and add them to myAreas
529   Message_ProgressScope aPSU (aMainScope.Next(), NULL, aNewSolids.Size());
530   aItLS.Initialize(aNewSolids);
531   for ( ; aItLS.More(); aItLS.Next(), aPSU.Next())
532   {
533     if (UserBreak (aPSU))
534     {
535       return;
536     }
537     TopoDS_Solid& aSolid = *(TopoDS_Solid*)&aItLS.Value();
538     const TopTools_ListOfShape* pLHoles = aSolidHolesMap.Seek(aSolid);
539     if (pLHoles)
540     {
541       // update solid
542       TopTools_ListIteratorOfListOfShape aItLH(*pLHoles);
543       for (; aItLH.More(); aItLH.Next())
544       {
545         const TopoDS_Shape& aHole = aItLH.Value();
546         aBB.Add(aSolid, aHole);
547       }
548
549       // update classifier
550       myContext->SolidClassifier(aSolid).Load(aSolid);
551     }
552
553     myAreas.Append(aSolid);
554   }
555
556   // Add holes that outside the solids to myAreas
557   aNbH = aHoleShells.Extent();
558   for (i = 1; i <= aNbH; ++i)
559   {
560     const TopoDS_Shape& aHole = aHoleShells(i);
561     if (!aHoleSolidMap.Contains(aHole))
562     {
563       TopoDS_Solid aSolid;
564       aBB.MakeSolid(aSolid);
565       aBB.Add (aSolid, aHole);
566       //
567       myAreas.Append(aSolid);
568       // Make an infinite box for the hole
569       Bnd_Box aBox;
570       aBox.SetWhole();
571       myBoxes.Bind(aSolid, aBox);
572     }
573
574     myBoxes.UnBind(aHole);
575   }
576 }
577 //=======================================================================
578 //function : PerformInternalShapes
579 //purpose  : 
580 //=======================================================================
581 void BOPAlgo_BuilderSolid::PerformInternalShapes(const Message_ProgressRange& theRange)
582 {
583   if (myAvoidInternalShapes)
584     // user-defined option to avoid internal parts is in force
585     return;
586
587   if (myLoopsInternal.IsEmpty())
588     // no internal parts
589     return;
590
591   Message_ProgressScope aMainScope (theRange, "Adding internal shapes", 2);
592
593   // Get all faces to classify
594   TopTools_IndexedMapOfShape aMFs;
595   TopTools_ListIteratorOfListOfShape aItLS(myLoopsInternal);
596   for (; aItLS.More(); aItLS.Next())
597   {
598     const TopoDS_Shape& aShell = aItLS.Value();
599     TopoDS_Iterator aIt(aShell);
600     for (; aIt.More(); aIt.Next())
601       aMFs.Add(aIt.Value());
602   }
603
604   BRep_Builder aBB;
605   // Check existence of the growths solids
606   if (myAreas.IsEmpty())
607   {
608     // No areas.
609     // Just make solid of the faces
610     TopoDS_Solid aSolid;
611     aBB.MakeSolid(aSolid);
612     //
613     TopTools_ListOfShape aLSI;
614     MakeInternalShells(aMFs, aLSI);
615     //
616     aItLS.Initialize(aLSI);
617     for (; aItLS.More(); aItLS.Next())
618       aBB.Add(aSolid, aItLS.Value());
619
620     myAreas.Append(aSolid);
621     return;
622   }
623
624   if (UserBreak (aMainScope))
625   {
626     return;
627   }
628
629   // Classify faces relatively solids
630
631   // Prepare list of faces to classify
632   TopTools_ListOfShape aLFaces;
633   Standard_Integer i, aNbF = aMFs.Extent();
634   for (i = 1; i <= aNbF; ++i)
635     aLFaces.Append(aMFs(i));
636
637   // Map of solids with IN faces
638   TopTools_IndexedDataMapOfShapeListOfShape aMSLF;
639
640   // Perform classification
641   BOPAlgo_Tools::ClassifyFaces(aLFaces,
642                                myAreas,
643                                myRunParallel,
644                                myContext,
645                                aMSLF,
646                                myBoxes,
647                                TopTools_DataMapOfShapeListOfShape(),
648                                aMainScope.Next());
649
650   // Update Solids by internal Faces
651
652   TopTools_MapOfShape aMFDone;
653
654   Standard_Integer aNbS = aMSLF.Extent();
655   Message_ProgressScope aPSLoop(aMainScope.Next(), NULL, aNbS);
656   for (i = 1; i <= aNbS; ++i, aPSLoop.Next())
657   {
658     if (UserBreak (aPSLoop))
659     {
660       return;
661     }
662     const TopoDS_Shape& aSolid = aMSLF.FindKey(i);
663     TopoDS_Shape *pSolid = (TopoDS_Shape*)&aSolid;
664
665     const TopTools_ListOfShape& aLF = aMSLF(i);
666     if (aLF.IsEmpty())
667       continue;
668
669     TopTools_IndexedMapOfShape aMF;
670     aItLS.Initialize(aLF);
671     for (; aItLS.More(); aItLS.Next())
672     {
673       const TopoDS_Shape& aF = aItLS.Value();
674       aMF.Add(aF);
675       aMFDone.Add(aF);
676     }
677     //
678     TopTools_ListOfShape aLSI;
679     MakeInternalShells(aMF, aLSI);
680     //
681     aItLS.Initialize(aLSI);
682     for (; aItLS.More(); aItLS.Next())
683     {
684       const TopoDS_Shape& aSI = aItLS.Value();
685       aBB.Add (*pSolid, aSI);
686     }
687   }
688
689   // Find all unclassified faces and warn the user about them.
690   // Do not put such faces into result as they will form not closed solid.
691   TopTools_IndexedMapOfShape aMFUnUsed;
692
693   for (i = 1; i <= aNbF; ++i)
694   {
695     const TopoDS_Shape& aF = aMFs(i);
696     if (!aMFDone.Contains(aF))
697       aMFUnUsed.Add(aF);
698   }
699
700   if (aMFUnUsed.Extent())
701   {
702     TopTools_ListOfShape aLSI;
703     MakeInternalShells(aMFUnUsed, aLSI);
704
705     TopoDS_Shape aWShape;
706     if (aLSI.Extent() == 1)
707       aWShape = aLSI.First();
708     else
709     {
710       aBB.MakeCompound(TopoDS::Compound(aWShape));
711       aItLS.Initialize(aLSI);
712       for (; aItLS.More(); aItLS.Next())
713         aBB.Add(aWShape, aItLS.Value());
714     }
715
716     AddWarning(new BOPAlgo_AlertSolidBuilderUnusedFaces(aWShape));
717   }
718 }
719 //=======================================================================
720 //function : MakeInternalShells
721 //purpose  : 
722 //=======================================================================
723 void MakeInternalShells(const TopTools_IndexedMapOfShape& theMF,
724                         TopTools_ListOfShape& theShells)
725 {
726   Standard_Integer i, aNbF;
727   BRep_Builder aBB;
728   TopTools_ListIteratorOfListOfShape aItF;
729   TopTools_IndexedDataMapOfShapeListOfShape aMEF;
730   TopTools_MapOfShape aAddedFacesMap;
731   //
732   aNbF = theMF.Extent();
733   for (i = 1; i <= aNbF; ++i) {
734     const TopoDS_Shape& aF = theMF(i);
735     TopExp::MapShapesAndAncestors(aF, 
736         TopAbs_EDGE, TopAbs_FACE, 
737         aMEF);
738   }
739   //
740   for (i = 1; i <= aNbF; ++i) {
741     TopoDS_Shape aFF = theMF(i);
742     if (!aAddedFacesMap.Add(aFF)) {
743       continue;
744     }
745     //
746     // make a new shell
747     TopoDS_Shell aShell;
748     aBB.MakeShell(aShell);    
749     aFF.Orientation(TopAbs_INTERNAL);
750     aBB.Add(aShell, aFF);
751     //
752     TopoDS_Iterator aItAddedF (aShell);
753     for (; aItAddedF.More(); aItAddedF.Next()) {
754       const TopoDS_Shape& aF =aItAddedF.Value();
755       //
756       TopExp_Explorer aEdgeExp(aF, TopAbs_EDGE);
757       for (; aEdgeExp.More(); aEdgeExp.Next()) {
758         const TopoDS_Shape& aE =aEdgeExp.Current();
759         const TopTools_ListOfShape& aLF=aMEF.FindFromKey(aE);
760         aItF.Initialize(aLF);
761         for (; aItF.More(); aItF.Next()) { 
762           TopoDS_Shape aFL=aItF.Value();
763           if (aAddedFacesMap.Add(aFL)){
764             aFL.Orientation(TopAbs_INTERNAL);
765             aBB.Add(aShell, aFL);
766           }
767         }
768       }
769     }
770     aShell.Closed (BRep_Tool::IsClosed (aShell));
771     theShells.Append(aShell);
772   }
773 }
774 //=======================================================================
775 //function : IsHole
776 //purpose  : 
777 //=======================================================================
778 Standard_Boolean IsHole(const TopoDS_Shape& theS2,
779                         Handle(IntTools_Context)& theContext)
780 {
781   TopoDS_Solid *pS2=(TopoDS_Solid *)&theS2;
782   BRepClass3d_SolidClassifier& aClsf=theContext->SolidClassifier(*pS2);
783   //
784   aClsf.PerformInfinitePoint(::RealSmall());
785   //
786   return (aClsf.State()==TopAbs_IN);
787 }
788 //=======================================================================
789 //function : IsInside
790 //purpose  : 
791 //=======================================================================
792 Standard_Boolean IsInside(const TopoDS_Shape& theS1,
793                           const TopoDS_Shape& theS2,
794                           Handle(IntTools_Context)& theContext)
795 {
796   TopExp_Explorer aExp;
797   TopAbs_State aState;
798   //
799   TopoDS_Solid *pS2=(TopoDS_Solid *)&theS2;
800   //
801   aExp.Init(theS1, TopAbs_FACE);
802   if (!aExp.More()){
803     BRepClass3d_SolidClassifier& aClsf=theContext->SolidClassifier(*pS2);
804     aClsf.PerformInfinitePoint(::RealSmall());
805     aState=aClsf.State();
806   }
807   else {
808     TopTools_IndexedMapOfShape aBounds;
809     TopExp::MapShapes(*pS2, TopAbs_EDGE, aBounds);
810     const TopoDS_Face& aF = (*(TopoDS_Face*)(&aExp.Current()));
811     aState=BOPTools_AlgoTools::ComputeState(aF, *pS2,
812                                             Precision::Confusion(),
813                                             aBounds, theContext);
814   }
815   return (aState==TopAbs_IN);
816 }
817 //=======================================================================
818 //function : IsGrowthShell
819 //purpose  : 
820 //=======================================================================
821 Standard_Boolean IsGrowthShell(const TopoDS_Shape& theShell,
822                                const TopTools_IndexedMapOfShape& theMHF)
823 {
824   if (theMHF.Extent())
825   {
826     TopoDS_Iterator aIt(theShell);
827     for(; aIt.More(); aIt.Next())
828     {
829       if (theMHF.Contains(aIt.Value()))
830         return Standard_True;
831     }
832   }
833   return Standard_False;
834 }