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