c087235d11b0076be5ecf23615c8d9cd6841837e
[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.ixx>
19 //
20 #include <NCollection_List.hxx>
21 #include <NCollection_DataMap.hxx>
22 #include <NCollection_UBTreeFiller.hxx>
23 //
24 #include <gp_Pnt2d.hxx>
25 #include <gp_Pln.hxx>
26 #include <gp_Vec.hxx>
27 #include <gp_Dir.hxx>
28 #include <gp_Pnt.hxx>
29 //
30 #include <TColStd_MapIntegerHasher.hxx>
31 //
32 #include <Geom_Curve.hxx>
33 #include <Geom_Surface.hxx>
34 #include <Geom2d_Curve.hxx>
35 //
36 #include <TopAbs.hxx>
37 //
38 #include <TopoDS_Iterator.hxx>
39 #include <TopoDS_Face.hxx>
40 #include <TopoDS_Shape.hxx>
41 #include <TopoDS_Shell.hxx>
42 #include <TopoDS_Edge.hxx>
43 #include <TopoDS_Solid.hxx>
44 #include <TopoDS_Vertex.hxx>
45 #include <TopoDS_Compound.hxx>
46
47 #include <BRep_Builder.hxx>
48 #include <BRep_Tool.hxx>
49 //
50 #include <TopExp.hxx>
51 #include <TopExp_Explorer.hxx>
52 //
53 #include <BRepBndLib.hxx>
54 #include <BRepClass3d_SolidClassifier.hxx>
55 //
56 #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
57 #include <BOPCol_ListOfShape.hxx>
58 #include <BOPCol_MapOfOrientedShape.hxx>
59 #include <BOPCol_DataMapOfShapeShape.hxx>
60 #include <BOPCol_DataMapOfShapeListOfShape.hxx>
61 #include <BOPCol_MapOfShape.hxx>
62 #include <BOPCol_BoxBndTree.hxx>
63 #include <BOPCol_ListOfInteger.hxx>
64 //
65 #include <BOPTools.hxx>
66 #include <BOPTools_CoupleOfShape.hxx>
67 #include <BOPTools_AlgoTools.hxx>
68 //
69 #include <IntTools_Context.hxx>
70 //
71 #include <BOPAlgo_ShellSplitter.hxx>
72
73 static
74   Standard_Boolean IsGrowthShell(const TopoDS_Shape& ,
75                                  const BOPCol_IndexedMapOfShape& );
76 static
77   Standard_Boolean IsHole(const TopoDS_Shape& ,
78                           Handle(IntTools_Context)& );
79 static
80   Standard_Boolean IsInside(const TopoDS_Shape& ,
81                             const TopoDS_Shape& ,
82                             Handle(IntTools_Context)& );
83 static
84   void MakeInternalShells(const BOPCol_MapOfShape& ,
85                           BOPCol_ListOfShape& );
86
87 //=======================================================================
88 //class     : BOPAlgo_BuilderSolid_ShapeBox
89 //purpose   : Auxiliary class
90 //=======================================================================
91 class BOPAlgo_BuilderSolid_ShapeBox {
92  public:
93   BOPAlgo_BuilderSolid_ShapeBox() {
94     myIsHole=Standard_False;
95   };
96   //
97   ~BOPAlgo_BuilderSolid_ShapeBox() {
98   };
99   //
100   void SetShape(const TopoDS_Shape& aS) {
101     myShape=aS;
102   };
103   //
104   const TopoDS_Shape& Shape()const {
105     return myShape;
106   };
107   //
108   void SetBox(const Bnd_Box& aBox) {
109     myBox=aBox;
110   };
111   //
112   const Bnd_Box& Box()const {
113     return myBox;
114   };
115   //
116   void SetIsHole(const Standard_Boolean bFlag) {
117     myIsHole=bFlag;
118   };
119   //
120   Standard_Boolean IsHole()const {
121     return myIsHole;
122   };
123   //
124  protected:
125   Standard_Boolean myIsHole;
126   TopoDS_Shape myShape;
127   Bnd_Box myBox;
128 };
129 //
130 typedef NCollection_DataMap\
131   <Standard_Integer, BOPAlgo_BuilderSolid_ShapeBox, TColStd_MapIntegerHasher> \
132   BOPAlgo_DataMapOfIntegerBSSB; 
133 //
134 typedef BOPAlgo_DataMapOfIntegerBSSB::Iterator \
135   BOPAlgo_DataMapIteratorOfDataMapOfIntegerBSSB; 
136 //
137 //=======================================================================
138 //function : 
139 //purpose  : 
140 //=======================================================================
141 BOPAlgo_BuilderSolid::BOPAlgo_BuilderSolid()
142 :
143   BOPAlgo_BuilderArea()
144 {
145 }
146 //=======================================================================
147 //function : 
148 //purpose  : 
149 //=======================================================================
150 BOPAlgo_BuilderSolid::BOPAlgo_BuilderSolid
151   (const Handle(NCollection_BaseAllocator)& theAllocator)
152 :
153   BOPAlgo_BuilderArea(theAllocator)
154 {
155 }
156 //=======================================================================
157 //function : ~
158 //purpose  : 
159 //=======================================================================
160 BOPAlgo_BuilderSolid::~BOPAlgo_BuilderSolid()
161 {
162 }
163 //=======================================================================
164 //function : SetSolid 
165 //purpose  : 
166 //=======================================================================
167 void BOPAlgo_BuilderSolid::SetSolid(const TopoDS_Solid& aS)
168 {
169   mySolid=aS;
170 }
171 //=======================================================================
172 //function : Solid 
173 //purpose  : 
174 //=======================================================================
175 const TopoDS_Solid& BOPAlgo_BuilderSolid::Solid()const
176 {
177   return mySolid;
178 }
179 //=======================================================================
180 //function : Perform
181 //purpose  : 
182 //=======================================================================
183 void BOPAlgo_BuilderSolid::Perform()
184 {
185   myErrorStatus=0;
186   //
187   if (myContext.IsNull()) {
188     myContext=new IntTools_Context;
189   }
190   //
191   TopoDS_Compound aC;
192   BRep_Builder aBB;
193   BOPCol_ListIteratorOfListOfShape aIt;
194   //
195   aBB.MakeCompound(aC);
196   aIt.Initialize(myShapes);
197   for(; aIt.More(); aIt.Next()) {
198     const TopoDS_Shape& aF=aIt.Value();
199     aBB.Add(aC, aF);
200   }
201   //
202   UserBreak();
203   //
204   PerformShapesToAvoid();
205   if (myErrorStatus) {
206     return;
207   }
208   //
209   UserBreak();
210   //
211   PerformLoops();
212   if (myErrorStatus) {
213     return;
214   }
215   //
216   UserBreak();
217   //
218   PerformAreas();
219   if (myErrorStatus) {
220     return;
221   }
222   //
223   UserBreak();
224   //
225   PerformInternalShapes();
226   if (myErrorStatus) {
227     return;
228   }
229 }
230 //=======================================================================
231 //function :PerformShapesToAvoid
232 //purpose  : 
233 //=======================================================================
234 void BOPAlgo_BuilderSolid::PerformShapesToAvoid()
235 {
236   Standard_Boolean bFound;
237   Standard_Integer i, iCnt, aNbE, aNbF;
238   TopAbs_Orientation aOrE;
239   BOPCol_IndexedDataMapOfShapeListOfShape aMEF;
240   BOPCol_ListIteratorOfListOfShape aIt;
241   //
242   myShapesToAvoid.Clear();
243   //
244   iCnt=0;
245   for(;;) {
246     ++iCnt;
247     bFound=Standard_False;
248     //
249     // 1. MEF
250     aMEF.Clear();
251     aIt.Initialize (myShapes);
252     for (; aIt.More(); aIt.Next()) {
253       const TopoDS_Shape& aF=aIt.Value();
254       if (!myShapesToAvoid.Contains(aF)) {
255         BOPTools::MapShapesAndAncestors(aF, TopAbs_EDGE, TopAbs_FACE, aMEF);
256       }
257     }
258     aNbE=aMEF.Extent();
259     //
260     // 2. myFacesToAvoid
261     for (i=1; i<=aNbE; ++i) {
262       const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aMEF.FindKey(i)));
263       if (BRep_Tool::Degenerated(aE)) {
264         continue;
265       }
266       //
267       BOPCol_ListOfShape& aLF=aMEF.ChangeFromKey(aE);
268       aNbF=aLF.Extent();
269       if (!aNbF) {
270         continue;
271       }
272       //
273       aOrE=aE.Orientation();
274       //
275       const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First()));
276       if (aNbF==1) {
277         if (aOrE==TopAbs_INTERNAL) {
278           continue;
279         }
280         bFound=Standard_True;
281         myShapesToAvoid.Add(aF1);
282       }
283       else if (aNbF==2) {
284         const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aLF.Last()));
285         if (aF2.IsSame(aF1)) {
286           if (BRep_Tool::IsClosed(aE, aF1)) {
287             continue;
288           }
289           //
290           if (aOrE==TopAbs_INTERNAL) {
291             continue;
292           }
293           //
294           bFound=Standard_True;
295           myShapesToAvoid.Add(aF1);
296           myShapesToAvoid.Add(aF2);
297         }
298       }
299     }// for (i=1; i<=aNbE; ++i) {
300     //
301     if (!bFound) {
302       break;
303     }
304     //
305   }//for(;;) {
306 }  
307 //=======================================================================
308 //function : PerformLoops
309 //purpose  : 
310 //=======================================================================
311 void BOPAlgo_BuilderSolid::PerformLoops()
312 {
313   Standard_Integer iErr;
314   BOPCol_ListIteratorOfListOfShape aIt;
315   TopoDS_Iterator aItS;
316   BOPCol_MapIteratorOfMapOfOrientedShape aItM;
317   BOPAlgo_ShellSplitter aSSp;
318   // 
319   myErrorStatus=0;
320   myLoops.Clear();
321   //
322   // 1. Shells Usual
323   aIt.Initialize (myShapes);
324   for (; aIt.More(); aIt.Next()) {
325     const TopoDS_Shape& aF=aIt.Value();
326     if (!myShapesToAvoid.Contains(aF)) {
327       aSSp.AddStartElement(aF);
328     }
329   }
330   //
331   aSSp.SetRunParallel(myRunParallel);
332   aSSp.Perform();
333   iErr=aSSp.ErrorStatus();
334   if (iErr) {
335     return;
336   }
337   //
338   const BOPCol_ListOfShape& aLSh=aSSp.Shells();
339   aIt.Initialize (aLSh);
340   for (; aIt.More(); aIt.Next()) {
341     const TopoDS_Shape& aSh=aIt.Value();
342     myLoops.Append(aSh);
343   }
344   //=================================================
345   //
346   // 2. Post Treatment
347   Standard_Integer aNbFA;
348   BRep_Builder aBB;
349   BOPCol_MapOfOrientedShape AddedFacesMap;
350   BOPCol_IndexedDataMapOfShapeListOfShape aEFMap;
351   BOPCol_MapOfOrientedShape aMP;
352   //
353   // a. collect all edges that are in loops
354   aIt.Initialize (myLoops);
355   for (; aIt.More(); aIt.Next()) {
356     const TopoDS_Shape& aS=aIt.Value();
357     aItS.Initialize(aS);
358     for (; aItS.More(); aItS.Next()) {
359       const TopoDS_Shape& aF=aItS.Value();
360       aMP.Add(aF);
361     }
362   }
363   // 
364   // b. collect all edges that are to avoid
365   aItM.Initialize(myShapesToAvoid);
366   for (; aItM.More(); aItM.Next()) {
367     const TopoDS_Shape& aF=aItM.Key();
368     aMP.Add(aF);
369   }
370   //
371   // c. add all edges that are not processed to myShapesToAvoid
372   aIt.Initialize (myShapes);
373   for (; aIt.More(); aIt.Next()) {
374     const TopoDS_Shape& aF=aIt.Value();
375     if (!aMP.Contains(aF)) {
376       myShapesToAvoid.Add(aF);
377     }
378   }
379   //=================================================
380   //
381   // 3.Internal Shells
382   myLoopsInternal.Clear();
383   //
384   aEFMap.Clear();
385   AddedFacesMap.Clear();
386   //
387   aNbFA=myShapesToAvoid.Extent();
388   //
389   aItM.Initialize(myShapesToAvoid);
390   for (; aItM.More(); aItM.Next()) {
391     const TopoDS_Shape& aFF=aItM.Key();
392     BOPTools::MapShapesAndAncestors(aFF, 
393         TopAbs_EDGE, TopAbs_FACE, 
394         aEFMap);
395   }
396   //
397   aItM.Initialize(myShapesToAvoid);
398   for (; aItM.More(); aItM.Next()) {
399     const TopoDS_Shape& aFF=aItM.Key();
400     if (!AddedFacesMap.Add(aFF)) {
401       continue;
402     }
403     //
404     // make a new shell
405     TopoDS_Shell aShell;
406     aBB.MakeShell(aShell);
407     aBB.Add(aShell, aFF);
408     //
409     TopoDS_Iterator aItAddedF (aShell);
410     for (; aItAddedF.More(); aItAddedF.Next()) {
411       const TopoDS_Face& aF = (*(TopoDS_Face*)(&aItAddedF.Value()));
412       //
413       TopExp_Explorer aEdgeExp(aF, TopAbs_EDGE);
414       for (; aEdgeExp.More(); aEdgeExp.Next()) {
415         const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aEdgeExp.Current()));
416         const BOPCol_ListOfShape& aLF=aEFMap.FindFromKey(aE);
417         aIt.Initialize(aLF);
418         for (; aIt.More(); aIt.Next()) { 
419           const TopoDS_Face& aFL=(*(TopoDS_Face*)(&aIt.Value()));
420           if (AddedFacesMap.Add(aFL)){
421             aBB.Add(aShell, aFL);
422           }
423         }
424       }
425     }
426     myLoopsInternal.Append(aShell);
427   }
428 }
429 //=======================================================================
430 //function : PerformAreas
431 //purpose  : 
432 //=======================================================================
433 void BOPAlgo_BuilderSolid::PerformAreas()
434 {
435   Standard_Boolean bIsGrowth, bIsHole;
436   Standard_Integer k,aNbHoles;
437   BRep_Builder aBB; 
438   BOPCol_ListIteratorOfListOfShape aItLS;
439   BOPCol_ListOfShape aNewSolids, aHoleShells; 
440   BOPCol_DataMapOfShapeShape aInOutMap;
441   BOPCol_IndexedMapOfShape aMHF;
442   BOPCol_ListIteratorOfListOfInteger aItLI;
443   BOPCol_BoxBndTreeSelector aSelector;
444   BOPCol_BoxBndTree aBBTree;
445   NCollection_UBTreeFiller <Standard_Integer, Bnd_Box> aTreeFiller(aBBTree);
446   BOPAlgo_DataMapOfIntegerBSSB aDMISB(100);
447   BOPAlgo_DataMapIteratorOfDataMapOfIntegerBSSB aItDMISB;
448   BOPCol_DataMapOfShapeListOfShape aMSH;
449   BOPCol_DataMapIteratorOfDataMapOfShapeShape aItDMSS;
450   BOPCol_DataMapIteratorOfDataMapOfShapeListOfShape aItMSH;
451   //
452   myErrorStatus=0;
453   //
454   myAreas.Clear();
455   //
456   //  Draft solids [aNewSolids]
457   aItLS.Initialize(myLoops);
458   for (k=0; aItLS.More(); aItLS.Next(), ++k) {
459     TopoDS_Solid aSolid;
460     Bnd_Box aBox;
461     BOPAlgo_BuilderSolid_ShapeBox aSB;
462     //
463     const TopoDS_Shape& aShell = aItLS.Value();
464     aSB.SetShape(aShell);
465     //
466     BRepBndLib::Add(aShell, aBox);
467     bIsHole=Standard_False;
468     //
469     bIsGrowth=IsGrowthShell(aShell, aMHF);
470     if (bIsGrowth) {
471       // make a growth solid from a shell
472       aBB.MakeSolid(aSolid);
473       aBB.Add (aSolid, aShell);
474       //
475       aNewSolids.Append (aSolid);
476       aSB.SetShape(aSolid);
477     }
478     else{
479       // check if a shell is a hole
480       bIsHole=IsHole(aShell, myContext);
481       if (bIsHole) {
482         aHoleShells.Append(aShell);
483         BOPTools::MapShapes(aShell, TopAbs_FACE, aMHF);
484         aSB.SetShape(aShell);
485       }
486       else {
487         // make a growth solid from a shell
488         aBB.MakeSolid(aSolid);
489         aBB.Add (aSolid, aShell);
490         //
491         aNewSolids.Append (aSolid);
492         aSB.SetShape(aSolid);
493       }
494     }
495     //
496     aSB.SetBox(aBox);
497     aSB.SetIsHole(bIsHole);
498     aDMISB.Bind(k, aSB);
499   }  
500   //
501   // 2. Prepare TreeFiller
502   aItDMISB.Initialize(aDMISB);
503   for (; aItDMISB.More(); aItDMISB.Next()) {
504     k=aItDMISB.Key();
505     const BOPAlgo_BuilderSolid_ShapeBox& aSB=aItDMISB.Value();
506     //
507     bIsHole=aSB.IsHole();
508     if (bIsHole) {
509       const Bnd_Box& aBox=aSB.Box();
510       aTreeFiller.Add(k, aBox);
511     }
512   }
513   //
514   // 3. Shake TreeFiller
515   aTreeFiller.Fill();
516   //
517   // 4. Find outer growth shell that is most close 
518   //    to each hole shell
519   aItDMISB.Initialize(aDMISB);
520   for (; aItDMISB.More(); aItDMISB.Next()) {
521     k=aItDMISB.Key();
522     const BOPAlgo_BuilderSolid_ShapeBox& aSB=aItDMISB.Value();
523     bIsHole=aSB.IsHole();
524     if (bIsHole) {
525       continue;
526     }
527     //
528     const TopoDS_Shape aSolid=aSB.Shape();
529     const Bnd_Box& aBoxSolid=aSB.Box();
530     //
531     aSelector.Clear();
532     aSelector.SetBox(aBoxSolid);
533     //
534     aNbHoles=aBBTree.Select(aSelector);
535     //
536     const BOPCol_ListOfInteger& aLI=aSelector.Indices();
537     //
538     aItLI.Initialize(aLI);
539     for (; aItLI.More(); aItLI.Next()) {
540       k=aItLI.Value();
541       const BOPAlgo_BuilderSolid_ShapeBox& aSBk=aDMISB.Find(k);
542       const TopoDS_Shape& aHole=aSBk.Shape();
543       //
544       if (!IsInside(aHole, aSolid, myContext)){
545         continue;
546       }
547       //
548       if (aInOutMap.IsBound (aHole)){
549         const TopoDS_Shape& aHole2=aInOutMap(aHole);
550         if (IsInside(aHole, aHole2, myContext)) {
551           aInOutMap.UnBind(aHole);
552           aInOutMap.Bind (aHole, aSolid);
553         }
554       }
555       else{
556         aInOutMap.Bind(aHole, aSolid);
557       }
558     }
559   }//for (; aItDMISB.More(); aItDMISB.Next()) {
560   //
561   // 5. Map [Solid/Holes] -> aMSH 
562   aItDMSS.Initialize(aInOutMap);
563   for (; aItDMSS.More(); aItDMSS.Next()) {
564     const TopoDS_Shape& aHole=aItDMSS.Key();
565     const TopoDS_Shape& aSolid=aItDMSS.Value();
566     //
567     if (aMSH.IsBound(aSolid)) {
568       BOPCol_ListOfShape& aLH=aMSH.ChangeFind(aSolid);
569       aLH.Append(aHole);
570     }
571     else {
572       BOPCol_ListOfShape aLH;
573       aLH.Append(aHole);
574       aMSH.Bind(aSolid, aLH);
575     }
576   }
577   //
578   // 6. Add aHoles to Solids
579   aItMSH.Initialize(aMSH);
580   for (; aItMSH.More(); aItMSH.Next()) {
581     TopoDS_Solid aSolid=(*(TopoDS_Solid*)(&aItMSH.Key()));
582     //
583     const BOPCol_ListOfShape& aLH=aItMSH.Value();
584     aItLS.Initialize(aLH);
585     for (; aItLS.More(); aItLS.Next()) {
586       const TopoDS_Shape& aHole = aItLS.Value();
587       aBB.Add (aSolid, aHole);
588     }
589     //
590     // update classifier
591     BRepClass3d_SolidClassifier& aSC=
592       myContext->SolidClassifier(aSolid);
593     aSC.Load(aSolid);
594     //
595   }
596   //
597   // 7. These aNewSolids are draft solids that 
598   // do not contain any internal shapes
599   aItLS.Initialize(aNewSolids);
600   for ( ; aItLS.More(); aItLS.Next()) {
601     const TopoDS_Shape& aSx=aItLS.Value();
602     myAreas.Append(aSx);
603   }
604   // Add holes that outside the solids to myAreas
605   aItLS.Initialize(aHoleShells);
606   for (; aItLS.More(); aItLS.Next()) {
607     const TopoDS_Shape& aHole = aItLS.Value();
608     if (!aInOutMap.IsBound(aHole)){
609       TopoDS_Solid aSolid;
610       //
611       aBB.MakeSolid(aSolid);
612       aBB.Add (aSolid, aHole);
613       //
614       myAreas.Append(aSolid);
615     }
616   }
617 }
618 //=======================================================================
619 //function : PerformInternalShapes
620 //purpose  : 
621 //=======================================================================
622 void BOPAlgo_BuilderSolid::PerformInternalShapes()
623 {
624   myErrorStatus=0;
625   //
626   Standard_Integer aNbFI=myLoopsInternal.Extent();
627   if (!aNbFI) {// nothing to do
628     return;
629   }
630   // 
631   BRep_Builder aBB;
632   TopoDS_Iterator aIt;
633   BOPCol_ListIteratorOfListOfShape aShellIt, aSolidIt;
634   BOPCol_MapIteratorOfMapOfShape aItMF;
635   //
636   BOPCol_MapOfShape aMF, aMFP, aMFx;
637   BOPCol_IndexedDataMapOfShapeListOfShape aMEF;
638   BOPCol_ListOfShape aLSI;
639   //
640   // 1. All internal faces
641   aShellIt.Initialize(myLoopsInternal);
642   for (; aShellIt.More(); aShellIt.Next()) {
643     const TopoDS_Shape& aShell=aShellIt.Value();
644     aIt.Initialize(aShell);
645     for (; aIt.More(); aIt.Next()) {
646       const TopoDS_Shape& aF=aIt.Value();
647       aMF.Add(aF);
648     }
649   }
650   aNbFI=aMF.Extent();
651   //
652   // 2 Process solids
653   aSolidIt.Initialize(myAreas);
654   for ( ; aSolidIt.More(); aSolidIt.Next()) {
655     TopoDS_Solid& aSolid=(*(TopoDS_Solid*)(&aSolidIt.Value()));
656     //
657     TopExp_Explorer anExpSol(aSolid, TopAbs_FACE);;
658     for (; anExpSol.More(); anExpSol.Next()) {
659       const TopoDS_Shape& aF = anExpSol.Current();
660       TopoDS_Shape aFF=aF;
661       //
662       aFF.Orientation(TopAbs_FORWARD);
663       aMFx.Add(aFF);
664       aFF.Orientation(TopAbs_REVERSED);
665       aMFx.Add(aFF);
666     }
667     aMEF.Clear();
668     BOPTools::MapShapesAndAncestors(aSolid, 
669         TopAbs_EDGE, TopAbs_FACE, 
670         aMEF);
671     //
672     // 2.1 Separate faces to process aMFP
673     aMFP.Clear();
674     aItMF.Initialize(aMF);
675     for (; aItMF.More(); aItMF.Next()) {
676       const TopoDS_Face& aF=(*(TopoDS_Face*)(&aItMF.Key()));
677       if (!aMFx.Contains(aF)) {
678         if (BOPTools_AlgoTools::IsInternalFace(aF, 
679             aSolid, 
680             aMEF, 
681             1.e-14, 
682             myContext)) {
683           aMFP.Add(aF);
684         }
685       }
686     }
687     aMFx.Clear();
688     //
689     // 2.2 Make Internal Shells
690     aLSI.Clear();
691     MakeInternalShells(aMFP, aLSI);
692     //
693     // 2.3 Add them to aSolid
694     aShellIt.Initialize(aLSI);
695     for (; aShellIt.More(); aShellIt.Next()) {
696       const TopoDS_Shape& aSI=aShellIt.Value();
697       aBB.Add (aSolid, aSI);
698     }
699     //
700     // 2.4 Remove faces aMFP from aMF
701     aItMF.Initialize(aMFP);
702     for (; aItMF.More(); aItMF.Next()) {
703       const TopoDS_Shape& aF=aItMF.Key();
704       aMF.Remove(aF);
705     }
706     //
707     aNbFI=aMF.Extent();
708     if (!aNbFI) {
709       break;
710     }
711   } //for ( ; aSolidIt.More(); aSolidIt.Next()) {
712   if (aNbFI) {
713     TopoDS_Solid aSolid;
714     aBB.MakeSolid(aSolid);
715     //
716     MakeInternalShells(aMF, aLSI);
717     aShellIt.Initialize(aLSI);
718     for (; aShellIt.More(); aShellIt.Next()) {
719       const TopoDS_Shape& aSI=aShellIt.Value();
720       aBB.Add (aSolid, aSI);
721     }
722     myAreas.Append(aSolid);
723   }
724 }
725
726 //=======================================================================
727 //function : MakeInternalShells
728 //purpose  : 
729 //=======================================================================
730 void MakeInternalShells(const BOPCol_MapOfShape& theMF,
731                         BOPCol_ListOfShape& theShells)
732 {
733   BOPCol_ListIteratorOfListOfShape aItF;
734   BRep_Builder aBB;
735   //
736   BOPCol_IndexedDataMapOfShapeListOfShape aMEF;
737   BOPCol_MapIteratorOfMapOfShape aItM;
738   BOPCol_MapOfShape aAddedFacesMap;
739   //
740   aItM.Initialize(theMF);
741   for (; aItM.More(); aItM.Next()) {
742     const TopoDS_Shape& aF=aItM.Key();
743     BOPTools::MapShapesAndAncestors(aF, 
744         TopAbs_EDGE, TopAbs_FACE, 
745         aMEF);
746   }
747   //
748   aItM.Initialize(theMF);
749   for (; aItM.More(); aItM.Next()) {
750     TopoDS_Shape aFF=aItM.Key();
751     if (!aAddedFacesMap.Add(aFF)) {
752       continue;
753     }
754     //
755     // make a new shell
756     TopoDS_Shell aShell;
757     aBB.MakeShell(aShell);    
758     aFF.Orientation(TopAbs_INTERNAL);
759     aBB.Add(aShell, aFF);
760     //
761     TopoDS_Iterator aItAddedF (aShell);
762     for (; aItAddedF.More(); aItAddedF.Next()) {
763       const TopoDS_Shape& aF =aItAddedF.Value();
764       //
765       TopExp_Explorer aEdgeExp(aF, TopAbs_EDGE);
766       for (; aEdgeExp.More(); aEdgeExp.Next()) {
767         const TopoDS_Shape& aE =aEdgeExp.Current();
768         const BOPCol_ListOfShape& aLF=aMEF.FindFromKey(aE);
769         aItF.Initialize(aLF);
770         for (; aItF.More(); aItF.Next()) { 
771           TopoDS_Shape aFL=aItF.Value();
772           if (aAddedFacesMap.Add(aFL)){
773             aFL.Orientation(TopAbs_INTERNAL);
774             aBB.Add(aShell, aFL);
775           }
776         }
777       }
778     }
779     theShells.Append(aShell);
780   }
781 }
782 //=======================================================================
783 //function : IsHole
784 //purpose  : 
785 //=======================================================================
786 Standard_Boolean IsHole(const TopoDS_Shape& theS2,
787                         Handle(IntTools_Context)& theContext)
788 {
789   TopoDS_Solid *pS2=(TopoDS_Solid *)&theS2;
790   BRepClass3d_SolidClassifier& aClsf=theContext->SolidClassifier(*pS2);
791   //
792   aClsf.PerformInfinitePoint(::RealSmall());
793   //
794   return (aClsf.State()==TopAbs_IN);
795 }
796 //=======================================================================
797 //function : IsInside
798 //purpose  : 
799 //=======================================================================
800 Standard_Boolean IsInside(const TopoDS_Shape& theS1,
801                           const TopoDS_Shape& theS2,
802                           Handle(IntTools_Context)& theContext)
803 {
804   TopExp_Explorer aExp;
805   TopAbs_State aState;
806   //
807   TopoDS_Solid *pS2=(TopoDS_Solid *)&theS2;
808   //
809   aExp.Init(theS1, TopAbs_FACE);
810   if (!aExp.More()){
811     BRepClass3d_SolidClassifier& aClsf=theContext->SolidClassifier(*pS2);
812     aClsf.PerformInfinitePoint(::RealSmall());
813     aState=aClsf.State();
814   }
815   else {
816     BOPCol_IndexedMapOfShape aBounds;
817     BOPTools::MapShapes(*pS2, TopAbs_EDGE, aBounds);
818     const TopoDS_Face& aF = (*(TopoDS_Face*)(&aExp.Current()));
819     aState=BOPTools_AlgoTools::ComputeState(aF, *pS2, 1.e-14, 
820                                             aBounds, theContext);
821   }
822   return (aState==TopAbs_IN);
823 }
824 //=======================================================================
825 //function : IsGrowthShell
826 //purpose  : 
827 //=======================================================================
828 Standard_Boolean IsGrowthShell(const TopoDS_Shape& theShell,
829                                const BOPCol_IndexedMapOfShape& theMHF)
830 {
831   Standard_Boolean bRet;
832   TopoDS_Iterator aIt;
833   // 
834   bRet=Standard_False;
835   if (theMHF.Extent()) {
836     aIt.Initialize(theShell);
837     for(; aIt.More(); aIt.Next()) {
838       const TopoDS_Shape& aF=aIt.Value();
839       if (theMHF.Contains(aF)) {
840         return !bRet;
841       }
842     }
843   }
844   return bRet;
845 }