0025184: Non-deterministic order of wires in the result of General Fuse
[occt.git] / src / BOPAlgo / BOPAlgo_BuilderFace.cxx
1 // Created by: Peter KURNEV
2 // Copyright (c) 2010-2012 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 //
8 // This file is part of Open CASCADE Technology software library.
9 //
10 // This library is free software; you can redistribute it and/or modify it under
11 // the terms of the GNU Lesser General Public License version 2.1 as published
12 // by the Free Software Foundation, with special exception defined in the file
13 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
14 // distribution for complete text of the license and disclaimer of any warranty.
15 //
16 // Alternatively, this file may be used under the terms of Open CASCADE
17 // commercial license or contractual agreement.
18
19 #include <BOPAlgo_BuilderFace.ixx>
20 //
21 #include <NCollection_UBTreeFiller.hxx>
22 #include <NCollection_DataMap.hxx>
23 //
24 #include <TColStd_MapIntegerHasher.hxx>
25 //
26 #include <gp_Pnt2d.hxx>
27 #include <gp_Pln.hxx>
28 #include <gp_Vec.hxx>
29 #include <gp_Dir.hxx>
30 #include <gp_Pnt.hxx>
31 //
32 #include <Geom_Surface.hxx>
33 //
34 #include <TopAbs.hxx>
35 #include <TopLoc_Location.hxx>
36 //
37 #include <TopoDS_Iterator.hxx>
38 #include <TopoDS_Face.hxx>
39 #include <TopoDS_Shape.hxx>
40 #include <TopoDS_Wire.hxx>
41 #include <TopoDS_Edge.hxx>
42 #include <TopoDS_Vertex.hxx>
43 //
44 #include <BRep_Builder.hxx>
45 #include <BRep_Tool.hxx>
46 #include <BRepTools.hxx>
47 //
48 #include <TopExp.hxx>
49 #include <TopExp_Explorer.hxx>
50
51 #include <IntTools_FClass2d.hxx>
52 #include <IntTools_Context.hxx>
53 //
54 #include <BOPTools_AlgoTools.hxx>
55 #include <BOPTools_AlgoTools2D.hxx>
56 #include <BOPAlgo_WireEdgeSet.hxx>
57 //
58 #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
59 #include <BOPTools.hxx>
60 #include <BOPCol_ListOfShape.hxx>
61 //
62 #include <BOPCol_DataMapOfShapeShape.hxx>
63 #include <BOPCol_DataMapOfShapeListOfShape.hxx>
64 #include <BOPCol_MapOfShape.hxx>
65 #include <BOPCol_Box2DBndTree.hxx>
66 //
67 #include <BOPAlgo_WireSplitter.hxx>
68
69 static
70   Standard_Boolean IsGrowthWire(const TopoDS_Shape& ,
71                                 const BOPCol_IndexedMapOfShape& );
72
73 static 
74   Standard_Boolean IsInside(const TopoDS_Shape& ,
75                             const TopoDS_Shape& ,
76                             Handle(IntTools_Context)& );
77 static
78   void MakeInternalWires(const BOPCol_MapOfShape& ,
79                          BOPCol_ListOfShape& );
80 static 
81   void GetWire(const TopoDS_Shape& , 
82         TopoDS_Shape& ); 
83 //
84
85 //
86 //=======================================================================
87 //class     : BOPAlgo_ShapeBox2D
88 //purpose   : Auxiliary class
89 //=======================================================================
90 class BOPAlgo_ShapeBox2D {
91  public:
92   BOPAlgo_ShapeBox2D() {
93     myIsHole=Standard_False;
94   };
95   //
96   ~BOPAlgo_ShapeBox2D() {
97   };
98   //
99   void SetShape(const TopoDS_Shape& aS) {
100     myShape=aS;
101   };
102   //
103   const TopoDS_Shape& Shape()const {
104     return myShape;
105   };
106   //
107   void SetBox2D(const Bnd_Box2d& aBox2D) {
108     myBox2D=aBox2D;
109   };
110   //
111   const Bnd_Box2d& Box2D()const {
112     return myBox2D;
113   };
114   //
115   void SetIsHole(const Standard_Boolean bFlag) {
116     myIsHole=bFlag;
117   };
118   //
119   Standard_Boolean IsHole()const {
120     return myIsHole;
121   };
122   //
123  protected:
124   Standard_Boolean myIsHole;
125   TopoDS_Shape myShape;
126   Bnd_Box2d myBox2D;
127 };
128 //
129 typedef NCollection_IndexedDataMap 
130   <Standard_Integer, 
131   BOPAlgo_ShapeBox2D, 
132   TColStd_MapIntegerHasher>  BOPAlgo_IndexedDataMapOfIntegerShapeBox2D; 
133
134 typedef NCollection_IndexedDataMap 
135   <TopoDS_Shape, 
136   TopoDS_Shape, 
137   TopTools_ShapeMapHasher> BOPCol_IndexedDataMapOfShapeShape; 
138 //
139 //=======================================================================
140 //function : 
141 //purpose  : 
142 //=======================================================================
143 BOPAlgo_BuilderFace::BOPAlgo_BuilderFace()
144 :
145   BOPAlgo_BuilderArea()
146 {
147   myOrientation=TopAbs_EXTERNAL;
148 }
149 //=======================================================================
150 //function : 
151 //purpose  : 
152 //=======================================================================
153 BOPAlgo_BuilderFace::BOPAlgo_BuilderFace
154   (const Handle(NCollection_BaseAllocator)& theAllocator)
155 :
156   BOPAlgo_BuilderArea(theAllocator)
157
158   myOrientation=TopAbs_EXTERNAL;
159 }
160 //=======================================================================
161 //function : ~
162 //purpose  : 
163 //=======================================================================
164   BOPAlgo_BuilderFace::~BOPAlgo_BuilderFace()
165 {
166 }
167 //=======================================================================
168 //function : SetFace
169 //purpose  : 
170 //=======================================================================
171 void BOPAlgo_BuilderFace::SetFace(const TopoDS_Face& theFace)
172 {
173   myOrientation=theFace.Orientation();
174   myFace=theFace;
175   myFace.Orientation(TopAbs_FORWARD);
176 }
177 //=======================================================================
178 //function : Orientation
179 //purpose  : 
180 //=======================================================================
181 TopAbs_Orientation BOPAlgo_BuilderFace::Orientation()const
182 {
183   return myOrientation;
184 }
185 //=======================================================================
186 //function : Face
187 //purpose  : 
188 //=======================================================================
189 const TopoDS_Face& BOPAlgo_BuilderFace::Face()const
190 {
191   return myFace;
192 }
193 //=======================================================================
194 //function : CheckData
195 //purpose  : 
196 //=======================================================================
197 void BOPAlgo_BuilderFace::CheckData()
198 {
199   myErrorStatus=0;
200   //
201   if (myFace.IsNull()) {
202     myErrorStatus=12;// Null face generix
203     return;
204   }
205   if (myContext.IsNull()) {
206     myContext = new IntTools_Context;
207   }
208 }
209 //=======================================================================
210 //function : Perform
211 //purpose  : 
212 //=======================================================================
213 void BOPAlgo_BuilderFace::Perform()
214 {
215   myErrorStatus=0;
216   //
217   CheckData();
218   if (myErrorStatus) {
219     return;
220   }
221   //
222   UserBreak();
223   //
224   PerformShapesToAvoid();
225   if (myErrorStatus) {
226     return;
227   }
228   //
229   UserBreak();
230   //
231   PerformLoops();
232   if (myErrorStatus) {
233     return;
234   }
235   //
236   UserBreak();
237   //
238   PerformAreas();
239   if (myErrorStatus) {
240     return;
241   }
242   //
243   UserBreak();
244   //
245   PerformInternalShapes();
246   if (myErrorStatus) {
247     return;
248   }
249 }
250 //=======================================================================
251 //function :PerformShapesToAvoid
252 //purpose  : 
253 //=======================================================================
254 void BOPAlgo_BuilderFace::PerformShapesToAvoid()
255 {
256   Standard_Boolean bFound;
257   Standard_Integer i, iCnt, aNbV, aNbE;
258   BOPCol_IndexedDataMapOfShapeListOfShape aMVE;
259   BOPCol_ListIteratorOfListOfShape aIt;
260   //
261   myShapesToAvoid.Clear();
262   //
263   iCnt=0;
264   for(;;) {
265     ++iCnt;
266     bFound=Standard_False;
267     //
268     // 1. MEF
269     aMVE.Clear();
270     aIt.Initialize (myShapes);
271     for (; aIt.More(); aIt.Next()) {
272       const TopoDS_Shape& aE=aIt.Value();
273       if (!myShapesToAvoid.Contains(aE)) {
274         BOPTools::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
275       }
276     }
277     aNbV=aMVE.Extent();
278     //
279     // 2. myEdgesToAvoid
280     for (i=1; i<=aNbV; ++i) {
281       const TopoDS_Vertex& aV=(*(TopoDS_Vertex *)(&aMVE.FindKey(i)));
282       //
283       BOPCol_ListOfShape& aLE=aMVE.ChangeFromKey(aV);
284       aNbE=aLE.Extent();
285       if (!aNbE) {
286         continue;
287       }
288       //
289       const TopoDS_Edge& aE1=(*(TopoDS_Edge *)(&aLE.First()));
290       if (aNbE==1) {
291         if (BRep_Tool::Degenerated(aE1)) {
292           continue;
293         }
294         if (aV.Orientation()==TopAbs_INTERNAL) {
295           continue;
296         }
297         bFound=Standard_True;
298         myShapesToAvoid.Add(aE1);
299       }
300       else if (aNbE==2) {
301         const TopoDS_Edge& aE2=(*(TopoDS_Edge *)(&aLE.Last()));
302         if (aE2.IsSame(aE1)) {
303           TopoDS_Vertex aV1x, aV2x;
304           //
305           TopExp::Vertices(aE1, aV1x, aV2x);
306           if (aV1x.IsSame(aV2x)) {
307             continue;
308           }
309           bFound=Standard_True;
310           myShapesToAvoid.Add(aE1);
311           myShapesToAvoid.Add(aE2);
312         }
313       }
314     }// for (i=1; i<=aNbE; ++i) {
315     //
316     if (!bFound) {
317       break;
318     }
319     //
320   }//while (1) 
321   //printf(" EdgesToAvoid=%d, iCnt=%d\n", EdgesToAvoid.Extent(), iCnt);
322 }  
323 //=======================================================================
324 //function : PerformLoops
325 //purpose  : 
326 //=======================================================================
327 void BOPAlgo_BuilderFace::PerformLoops()
328 {
329   myErrorStatus=0;
330   //
331   Standard_Boolean bFlag;
332   Standard_Integer iErr, aNbEA;
333   BOPCol_ListIteratorOfListOfShape aIt;
334   BOPCol_MapIteratorOfMapOfOrientedShape aItM;
335   BOPCol_IndexedDataMapOfShapeListOfShape aVEMap;
336   BOPCol_MapOfOrientedShape aMAdded;
337   TopoDS_Iterator aItW;
338   BRep_Builder aBB; 
339   BOPAlgo_WireEdgeSet aWES(myAllocator);
340   BOPAlgo_WireSplitter aWSp(myAllocator);
341   //
342   // 1. 
343   myLoops.Clear();
344   aWES.SetFace(myFace);
345   //
346   aIt.Initialize(myShapes);
347   for (; aIt.More(); aIt.Next()) {
348     const TopoDS_Shape& aE=aIt.Value();
349     if (!myShapesToAvoid.Contains(aE)) {
350       aWES.AddStartElement(aE);
351     }
352   }
353   //
354   aWSp.SetWES(aWES);
355   aWSp.SetRunParallel(myRunParallel);
356   aWSp.Perform();
357   iErr=aWSp.ErrorStatus();
358   if (iErr) {
359     return;
360   }
361   //
362   const BOPCol_ListOfShape& aLW=aWES.Shapes();
363   aIt.Initialize (aLW);
364   for (; aIt.More(); aIt.Next()) {
365     const TopoDS_Shape& aW=aIt.Value();
366     myLoops.Append(aW);
367   }
368   // Post Treatment
369   BOPCol_MapOfOrientedShape aMEP;
370   // 
371   // a. collect all edges that are in loops
372   aIt.Initialize (myLoops);
373   for (; aIt.More(); aIt.Next()) {
374     const TopoDS_Shape& aW=aIt.Value();
375     aItW.Initialize(aW);
376     for (; aItW.More(); aItW.Next()) {
377       const TopoDS_Shape& aE=aItW.Value();
378       aMEP.Add(aE);
379     }
380   }
381   // 
382   // b. collect all edges that are to avoid
383   aItM.Initialize(myShapesToAvoid);
384   for (; aItM.More(); aItM.Next()) {
385     const TopoDS_Shape& aE=aItM.Key();
386     aMEP.Add(aE);
387   }
388   //
389   // c. add all edges that are not processed to myShapesToAvoid
390   aIt.Initialize (myShapes);
391   for (; aIt.More(); aIt.Next()) {
392     const TopoDS_Shape& aE=aIt.Value();
393     if (!aMEP.Contains(aE)) {
394       myShapesToAvoid.Add(aE);
395     }
396   }
397   //
398   // 2. Internal Wires
399   myLoopsInternal.Clear();
400   //
401   aNbEA=myShapesToAvoid.Extent();
402   aItM.Initialize(myShapesToAvoid);
403   for (; aItM.More(); aItM.Next()) {
404     const TopoDS_Shape& aEE=aItM.Key();
405     BOPTools::MapShapesAndAncestors(aEE, 
406                                     TopAbs_VERTEX, 
407                                     TopAbs_EDGE, 
408                                     aVEMap);
409   }
410   //
411   bFlag=Standard_True;
412   aItM.Initialize(myShapesToAvoid);
413   for (; aItM.More()&&bFlag; aItM.Next()) {
414     const TopoDS_Shape& aEE=aItM.Key();
415     if (!aMAdded.Add(aEE)) {
416       continue;
417     }
418     //
419     // make new wire
420     TopoDS_Wire aW;
421     aBB.MakeWire(aW);
422     aBB.Add(aW, aEE);
423     //
424     aItW.Initialize(aW);
425     for (; aItW.More()&&bFlag; aItW.Next()) {
426       const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&aItW.Value()));
427       //
428       TopoDS_Iterator aItE(aE);
429       for (; aItE.More()&&bFlag; aItE.Next()) {
430         const TopoDS_Vertex& aV = (*(TopoDS_Vertex *)(&aItE.Value()));
431         const BOPCol_ListOfShape& aLE=aVEMap.FindFromKey(aV);
432         aIt.Initialize(aLE);
433         for (; aIt.More()&&bFlag; aIt.Next()) { 
434           const TopoDS_Shape& aEx=aIt.Value();
435           if (aMAdded.Add(aEx)) {
436             aBB.Add(aW, aEx);
437             if(aMAdded.Extent()==aNbEA) {
438               bFlag=!bFlag;
439             }
440           }
441         }//for (; aIt.More(); aIt.Next()) { 
442       }//for (; aItE.More(); aItE.Next()) {
443     }//for (; aItW.More(); aItW.Next()) {
444     myLoopsInternal.Append(aW);
445   }//for (; aItM.More(); aItM.Next()) {
446 }
447 //=======================================================================
448 //function : PerformAreas
449 //purpose  : 
450 //=======================================================================
451 void BOPAlgo_BuilderFace::PerformAreas()
452 {
453   Standard_Boolean bIsGrowth, bIsHole;
454   Standard_Integer k, aNbHoles, aNbDMISB, m, aNbMSH, aNbInOutMap;;
455   Standard_Real aTol;
456   TopLoc_Location aLoc;
457   Handle(Geom_Surface) aS;
458   BRep_Builder aBB;
459   TopoDS_Face aFace;
460   BOPCol_ListIteratorOfListOfInteger aItLI;
461   BOPCol_IndexedMapOfShape aMHE;
462   BOPCol_ListIteratorOfListOfShape aIt1;
463   BOPCol_IndexedDataMapOfShapeListOfShape aMSH;
464   BOPCol_IndexedDataMapOfShapeShape aInOutMap;
465   BOPAlgo_IndexedDataMapOfIntegerShapeBox2D aDMISB(100);
466   //
467   BOPCol_Box2DBndTreeSelector aSelector;
468   BOPCol_Box2DBndTree aBBTree;
469   NCollection_UBTreeFiller <Standard_Integer, Bnd_Box2d> aTreeFiller(aBBTree);
470   //
471   myErrorStatus=0;
472   //
473   aTol=BRep_Tool::Tolerance(myFace);
474   aS=BRep_Tool::Surface(myFace, aLoc);
475   //
476   myAreas.Clear();
477   //
478   // 1. Growthes and Holes -> aDMISB: [Index/ShapeBox2D]
479   aIt1.Initialize(myLoops);
480   for (k=0 ; aIt1.More(); aIt1.Next(), ++k) {
481     Bnd_Box2d aBox2D;
482     //
483     const TopoDS_Shape& aWire=aIt1.Value();
484     //
485     aBB.MakeFace(aFace, aS, aLoc, aTol);
486     aBB.Add (aFace, aWire);
487     BRepTools::AddUVBounds(aFace, aBox2D);
488     //
489     bIsGrowth=IsGrowthWire(aWire, aMHE);
490     if (bIsGrowth) {
491       bIsHole=Standard_False;
492     }
493     else{
494       // check if a wire is a hole 
495       IntTools_FClass2d& aClsf=myContext->FClass2d(aFace);
496       aClsf.Init(aFace, aTol);
497       //
498       bIsHole=aClsf.IsHole();
499       if (bIsHole) {
500         BOPTools::MapShapes(aWire, TopAbs_EDGE, aMHE);
501           //
502           bIsHole=Standard_True;
503       }
504       else {
505         bIsHole=Standard_False;
506       }
507     }
508     //
509     BOPAlgo_ShapeBox2D aSB2D;
510     //
511     aSB2D.SetShape(aFace);
512     aSB2D.SetBox2D(aBox2D);
513     aSB2D.SetIsHole(bIsHole);
514     //
515     aDMISB.Add(k, aSB2D);
516   }// for (k=0 ; aIt1.More(); aIt1.Next(), ++k) {
517   //
518   // 2. Prepare TreeFiller
519   aNbDMISB=aDMISB.Extent();
520   for (m=1; m<=aNbDMISB; ++m) { 
521     k=aDMISB.FindKey(m);
522     const BOPAlgo_ShapeBox2D& aSB2D=aDMISB.FindFromIndex(m);
523     //
524     bIsHole=aSB2D.IsHole();
525     if (bIsHole) {
526       const Bnd_Box2d& aBox2D=aSB2D.Box2D();
527       aTreeFiller.Add(k, aBox2D);
528     }
529   }
530   //
531   // 3. Shake TreeFiller
532   aTreeFiller.Fill();
533   //
534   // 4. Find outer growth shell that is most close 
535   //    to each hole shell
536   for (m=1; m<=aNbDMISB; ++m) {
537     const BOPAlgo_ShapeBox2D& aSB2D=aDMISB.FindFromIndex(m);
538     bIsHole=aSB2D.IsHole();
539     if (bIsHole) {
540       continue;
541     }
542     //
543     const Bnd_Box2d& aBox2DF=aSB2D.Box2D();
544     const TopoDS_Shape aF=aSB2D.Shape();
545     //
546     aSelector.Clear();
547     aSelector.SetBox(aBox2DF);
548     //
549     aNbHoles=aBBTree.Select(aSelector);
550     //
551     const BOPCol_ListOfInteger& aLI=aSelector.Indices();
552     //
553     aItLI.Initialize(aLI);
554     for (; aItLI.More(); aItLI.Next()) {
555       k=aItLI.Value();
556       const BOPAlgo_ShapeBox2D& aSB2Dk=aDMISB.FindFromKey(k);
557       const TopoDS_Shape& aHole=aSB2Dk.Shape();
558       //
559       if (!IsInside(aHole, aF, myContext)){
560         continue;
561       }
562       //
563       if (aInOutMap.Contains(aHole)){
564         TopoDS_Shape& aF2=aInOutMap.ChangeFromKey(aHole);
565         if (IsInside(aF, aF2, myContext)) {
566           aF2=aF;
567         }
568       }
569       else{
570         aInOutMap.Add(aHole, aF);
571       }
572     }
573   }// for (m=1; m<=aNbDMISB; ++m)
574   //
575   // 5. Map [Face/Holes] -> aMSH 
576   aNbInOutMap=aInOutMap.Extent();
577   for (m=1; m<=aNbInOutMap; ++m) {
578     const TopoDS_Shape& aHole=aInOutMap.FindKey(m);
579     const TopoDS_Shape& aF=aInOutMap.FindFromIndex(m);
580     //
581     if (aMSH.Contains(aF)) {
582       BOPCol_ListOfShape& aLH=aMSH.ChangeFromKey(aF);
583       aLH.Append(aHole);
584     }
585     else {
586       BOPCol_ListOfShape aLH;
587       aLH.Append(aHole);
588       aMSH.Add(aF, aLH);
589     }
590   }
591   //
592   // 6. Add aHoles to Faces
593   aNbMSH=aMSH.Extent();
594   for (m=1; m<=aNbMSH; ++m) {
595     TopoDS_Face aF=(*(TopoDS_Face *)(&aMSH.FindKey(m)));
596     const BOPCol_ListOfShape& aLH=aMSH.FindFromIndex(m);
597     //
598     aIt1.Initialize(aLH);
599     for (; aIt1.More(); aIt1.Next()) {
600       TopoDS_Shape aWHole;
601       //
602       const TopoDS_Shape& aFHole=aIt1.Value();
603       GetWire(aFHole, aWHole);
604       aBB.Add (aF, aWHole);
605     }
606     //
607     // update classifier 
608     aTol=BRep_Tool::Tolerance(aF);
609     IntTools_FClass2d& aClsf=myContext->FClass2d(aF);
610     aClsf.Init(aF, aTol);
611   }
612   //
613   // 7. Fill myAreas
614   //    NB:These aNewFaces are draft faces that 
615   //    do not contain any internal shapes
616   for (m=1; m<=aNbDMISB; ++m) {
617     const BOPAlgo_ShapeBox2D& aSB2D=aDMISB.FindFromIndex(m);
618     bIsHole=aSB2D.IsHole();
619     if (!bIsHole) {
620       const TopoDS_Shape aF=aSB2D.Shape();
621       myAreas.Append(aF);
622     }
623   }
624 }
625 //=======================================================================
626 //function : GetWire
627 //purpose  : 
628 //=======================================================================
629 void GetWire(const TopoDS_Shape& aF, TopoDS_Shape& aW) 
630 {
631   TopoDS_Shape aWx;
632   TopoDS_Iterator aIt;
633   //
634   aIt.Initialize(aF);
635   for (; aIt.More(); aIt.Next()) {
636     aW=aIt.Value();
637   }
638 }
639 //=======================================================================
640 //function : PerformInternalShapes
641 //purpose  : 
642 //=======================================================================
643 void BOPAlgo_BuilderFace::PerformInternalShapes()
644 {
645   myErrorStatus=0;
646   //
647   Standard_Integer aNbWI=myLoopsInternal.Extent();
648   if (!aNbWI) {// nothing to do
649     return;
650   }
651   // 
652   //Standard_Real aTol;
653   BRep_Builder aBB;
654   BOPCol_ListIteratorOfListOfShape aIt1, aIt2;
655   TopoDS_Iterator aIt; 
656   BOPCol_MapOfShape aME, aMEP;
657   BOPCol_MapIteratorOfMapOfShape aItME;
658   BOPCol_IndexedDataMapOfShapeListOfShape aMVE;
659   BOPCol_ListOfShape aLSI;
660   //
661   // 1. All internal edges
662   aIt1.Initialize(myLoopsInternal);
663   for (; aIt1.More(); aIt1.Next()) {
664     const TopoDS_Shape& aWire=aIt1.Value();
665     aIt.Initialize(aWire);
666     for (; aIt.More(); aIt.Next()) {
667       const TopoDS_Shape& aE=aIt.Value();
668       aME.Add(aE);
669     }
670   }
671   aNbWI=aME.Extent();
672   //
673   // 2 Process faces
674   aIt2.Initialize(myAreas);
675   for ( ; aIt2.More(); aIt2.Next()) {
676     TopoDS_Face& aF=(*(TopoDS_Face *)(&aIt2.Value()));
677     //
678     aMVE.Clear();
679     BOPTools::MapShapesAndAncestors(aF, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
680     //
681     // 2.1 Separate faces to process aMEP
682     aMEP.Clear();
683     aItME.Initialize(aME);
684     for (; aItME.More(); aItME.Next()) {
685       const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&aItME.Key()));
686       if (IsInside(aE, aF, myContext)) {
687         aMEP.Add(aE);
688       }
689     }
690     //
691     // 2.2 Make Internal Wires
692     aLSI.Clear();
693     MakeInternalWires(aMEP, aLSI);
694     //
695     // 2.3 Add them to aF
696     aIt1.Initialize(aLSI);
697     for (; aIt1.More(); aIt1.Next()) {
698       const TopoDS_Shape& aSI=aIt1.Value();
699       aBB.Add (aF, aSI);
700     }
701     //
702     // 2.4 Remove faces aMFP from aMF
703     aItME.Initialize(aMEP);
704     for (; aItME.More(); aItME.Next()) {
705       const TopoDS_Shape& aE=aItME.Key();
706       aME.Remove(aE);
707     }
708     //
709     aNbWI=aME.Extent();
710     if (!aNbWI) {
711       break;
712     }
713   } //for ( ; aIt2.More(); aIt2.Next()) {
714 }
715 //=======================================================================
716 //function : MakeInternalWires
717 //purpose  : 
718 //=======================================================================
719 void MakeInternalWires(const BOPCol_MapOfShape& theME,
720                        BOPCol_ListOfShape& theWires)
721 {
722   BOPCol_MapIteratorOfMapOfShape aItM;
723   BOPCol_MapOfShape aAddedMap;
724   BOPCol_ListIteratorOfListOfShape aItE;
725   BOPCol_IndexedDataMapOfShapeListOfShape aMVE;
726   BRep_Builder aBB;
727   //
728   aItM.Initialize(theME);
729   for (; aItM.More(); aItM.Next()) {
730     const TopoDS_Shape& aE=aItM.Key();
731     BOPTools::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
732   }
733   //
734   aItM.Initialize(theME);
735   for (; aItM.More(); aItM.Next()) {
736     TopoDS_Shape aEE=aItM.Key();
737     if (!aAddedMap.Add(aEE)) {
738       continue;
739     }
740     //
741     // make a new shell
742     TopoDS_Wire aW;
743     aBB.MakeWire(aW);    
744     aEE.Orientation(TopAbs_INTERNAL);
745     aBB.Add(aW, aEE);
746     //
747     TopoDS_Iterator aItAdded (aW);
748     for (; aItAdded.More(); aItAdded.Next()) {
749       const TopoDS_Shape& aE =aItAdded.Value();
750       //
751       TopExp_Explorer aExp(aE, TopAbs_VERTEX);
752       for (; aExp.More(); aExp.Next()) {
753         const TopoDS_Shape& aV =aExp.Current();
754         const BOPCol_ListOfShape& aLE=aMVE.FindFromKey(aV);
755         aItE.Initialize(aLE);
756         for (; aItE.More(); aItE.Next()) { 
757           TopoDS_Shape aEL=aItE.Value();
758           if (aAddedMap.Add(aEL)){
759             aEL.Orientation(TopAbs_INTERNAL);
760             aBB.Add(aW, aEL);
761           }
762         }
763       }
764     }
765     theWires.Append(aW);
766   }
767 }
768 //=======================================================================
769 //function : IsInside
770 //purpose  : 
771 //=======================================================================
772 Standard_Boolean IsInside(const TopoDS_Shape& theHole,
773                           const TopoDS_Shape& theF2,
774                           Handle(IntTools_Context)& theContext)
775 {
776   Standard_Boolean bRet;
777   Standard_Real aT, aU, aV;
778   
779   TopAbs_State aState;
780   TopExp_Explorer aExp;
781   BOPCol_IndexedMapOfShape aME2;
782   gp_Pnt2d aP2D;
783   //
784   bRet=Standard_False;
785   aState=TopAbs_UNKNOWN;
786   const TopoDS_Face& aF2=(*(TopoDS_Face *)(&theF2));
787   //
788   BOPTools::MapShapes(aF2, TopAbs_EDGE, aME2);//AA
789   //
790   aExp.Init(theHole, TopAbs_EDGE);
791   if (aExp.More()) {
792     const TopoDS_Edge& aE =(*(TopoDS_Edge *)(&aExp.Current()));
793     if (aME2.Contains(aE)) {
794       return bRet;
795     }
796     if (!BRep_Tool::Degenerated(aE)) {
797       //
798       aT=BOPTools_AlgoTools2D::IntermediatePoint(aE);
799       BOPTools_AlgoTools2D::PointOnSurface(aE, aF2, aT, aU, aV);
800       aP2D.SetCoord(aU, aV);
801       //
802       IntTools_FClass2d& aClsf=theContext->FClass2d(aF2);
803       aState=aClsf.Perform(aP2D);
804       bRet=(aState==TopAbs_IN);
805     }
806   }
807   //
808   return bRet;
809 }
810
811 //=======================================================================
812 //function : IsGrowthWire
813 //purpose  : 
814 //=======================================================================
815 Standard_Boolean IsGrowthWire(const TopoDS_Shape& theWire,
816                               const BOPCol_IndexedMapOfShape& theMHE)
817 {
818   Standard_Boolean bRet;
819   TopoDS_Iterator aIt;
820   // 
821   bRet=Standard_False;
822   if (theMHE.Extent()) {
823     aIt.Initialize(theWire);
824     for(; aIt.More(); aIt.Next()) {
825       const TopoDS_Shape& aE=aIt.Value();
826       if (theMHE.Contains(aE)) {
827         return !bRet;
828       }
829     }
830   }
831   return bRet;
832 }
833
834 //BRepTools::Write(aFF, "ff");
835 //
836 //  ErrorStatus :
837 // 11 - Null Context
838 // 12 - Null face generix