0024428: Implementation of LGPL license
[occt.git] / src / BOPAlgo / BOPAlgo_BuilderFace.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
10 // under the terms of the GNU Lesser General Public 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_BuilderFace.ixx>
19
20 #include <gp_Pnt2d.hxx>
21 #include <gp_Pln.hxx>
22 #include <gp_Vec.hxx>
23 #include <gp_Dir.hxx>
24 #include <gp_Pnt.hxx>
25
26 #include <Geom_Surface.hxx>
27
28 #include <TopAbs.hxx>
29 #include <TopLoc_Location.hxx>
30
31 #include <TopoDS_Iterator.hxx>
32 #include <TopoDS_Face.hxx>
33 #include <TopoDS_Shape.hxx>
34 #include <TopoDS_Wire.hxx>
35 #include <TopoDS_Edge.hxx>
36 #include <TopoDS_Vertex.hxx>
37
38 #include <BRep_Builder.hxx>
39 #include <BRep_Tool.hxx>
40 #include <BRepTools.hxx>
41
42 #include <TopExp.hxx>
43 #include <TopExp_Explorer.hxx>
44
45 #include <IntTools_FClass2d.hxx>
46 #include <BOPInt_Context.hxx>
47
48 //
49 #include <BOPTools_AlgoTools.hxx>
50 #include <BOPTools_AlgoTools2D.hxx>
51 #include <BOPAlgo_WireEdgeSet.hxx>
52 //
53 #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
54 #include <BOPTools.hxx>
55 #include <BOPCol_ListOfShape.hxx>
56 #include <BOPAlgo_WireSplitter.hxx>
57 #include <BOPCol_DataMapOfShapeShape.hxx>
58 #include <BOPCol_DataMapOfShapeListOfShape.hxx>
59 #include <BOPCol_MapOfShape.hxx>
60
61
62 static
63   Standard_Boolean IsGrowthWire(const TopoDS_Shape& ,
64                                 const BOPCol_IndexedMapOfShape& );
65
66 static 
67   Standard_Boolean IsInside(const TopoDS_Shape& ,
68                             const TopoDS_Shape& ,
69                             Handle(BOPInt_Context)& );
70 static
71   void MakeInternalWires(const BOPCol_MapOfShape& ,
72                          BOPCol_ListOfShape& );
73
74 //=======================================================================
75 //function : 
76 //purpose  : 
77 //=======================================================================
78   BOPAlgo_BuilderFace::BOPAlgo_BuilderFace()
79 :
80   BOPAlgo_BuilderArea()
81 {
82   myOrientation=TopAbs_EXTERNAL;
83 }
84 //=======================================================================
85 //function : 
86 //purpose  : 
87 //=======================================================================
88   BOPAlgo_BuilderFace::BOPAlgo_BuilderFace(const Handle(NCollection_BaseAllocator)& theAllocator)
89 :
90   BOPAlgo_BuilderArea(theAllocator)
91
92   myOrientation=TopAbs_EXTERNAL;
93 }
94 //=======================================================================
95 //function : ~
96 //purpose  : 
97 //=======================================================================
98   BOPAlgo_BuilderFace::~BOPAlgo_BuilderFace()
99 {
100 }
101 //=======================================================================
102 //function : SetFace
103 //purpose  : 
104 //=======================================================================
105   void BOPAlgo_BuilderFace::SetFace(const TopoDS_Face& theFace)
106 {
107   myOrientation=theFace.Orientation();
108   myFace=theFace;
109   myFace.Orientation(TopAbs_FORWARD);
110 }
111 //=======================================================================
112 //function : Orientation
113 //purpose  : 
114 //=======================================================================
115 TopAbs_Orientation BOPAlgo_BuilderFace::Orientation()const
116 {
117   return myOrientation;
118 }
119 //=======================================================================
120 //function : Face
121 //purpose  : 
122 //=======================================================================
123   const TopoDS_Face& BOPAlgo_BuilderFace::Face()const
124 {
125   return myFace;
126 }
127 //=======================================================================
128 //function : CheckData
129 //purpose  : 
130 //=======================================================================
131   void BOPAlgo_BuilderFace::CheckData()
132 {
133   myErrorStatus=0;
134   //
135   if (myContext.IsNull()) {
136     //myErrorStatus=11;// Null Context
137     //return;
138     myContext = new BOPInt_Context;
139   }
140   //
141   if (myFace.IsNull()) {
142     myErrorStatus=12;// Null face generix
143     return;
144   }
145 }
146 //=======================================================================
147 //function : Perform
148 //purpose  : 
149 //=======================================================================
150   void BOPAlgo_BuilderFace::Perform()
151 {
152   myErrorStatus=0;
153   //
154   CheckData();
155   if (myErrorStatus) {
156     return;
157   }
158   //
159   PerformShapesToAvoid();
160   if (myErrorStatus) {
161     return;
162   }
163   //
164   PerformLoops();
165   if (myErrorStatus) {
166     return;
167   }
168   //
169   PerformAreas();
170   if (myErrorStatus) {
171     return;
172   }
173   //
174   PerformInternalShapes();
175   if (myErrorStatus) {
176     return;
177   }
178 }
179 //=======================================================================
180 //function :PerformShapesToAvoid
181 //purpose  : 
182 //=======================================================================
183   void BOPAlgo_BuilderFace::PerformShapesToAvoid()
184 {
185   Standard_Boolean bFound;
186   Standard_Integer i, iCnt, aNbV, aNbE;
187   BOPCol_IndexedDataMapOfShapeListOfShape aMVE;
188   BOPCol_ListIteratorOfListOfShape aIt;
189   //
190   myShapesToAvoid.Clear();
191   //
192   iCnt=0;
193   for(;;) {
194     ++iCnt;
195     bFound=Standard_False;
196     //
197     // 1. MEF
198     aMVE.Clear();
199     aIt.Initialize (myShapes);
200     for (; aIt.More(); aIt.Next()) {
201       const TopoDS_Shape& aE=aIt.Value();
202       if (!myShapesToAvoid.Contains(aE)) {
203         BOPTools::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
204       }
205       //else {
206         //int a=0;
207       //}
208     }
209     aNbV=aMVE.Extent();
210     //
211     // 2. myEdgesToAvoid
212     for (i=1; i<=aNbV; ++i) {
213       const TopoDS_Vertex& aV=(*(TopoDS_Vertex *)(&aMVE.FindKey(i)));
214       //
215       BOPCol_ListOfShape& aLE=aMVE.ChangeFromKey(aV);
216       aNbE=aLE.Extent();
217       if (!aNbE) {
218         continue;
219       }
220       //
221       const TopoDS_Edge& aE1=(*(TopoDS_Edge *)(&aLE.First()));
222       if (aNbE==1) {
223         if (BRep_Tool::Degenerated(aE1)) {
224           continue;
225         }
226         if (aV.Orientation()==TopAbs_INTERNAL) {
227           continue;
228         }
229         bFound=Standard_True;
230         myShapesToAvoid.Add(aE1);
231       }
232       else if (aNbE==2) {
233         const TopoDS_Edge& aE2=(*(TopoDS_Edge *)(&aLE.Last()));
234         if (aE2.IsSame(aE1)) {
235           TopoDS_Vertex aV1x, aV2x;
236           //
237           TopExp::Vertices(aE1, aV1x, aV2x);
238           if (aV1x.IsSame(aV2x)) {
239             continue;
240           }
241           bFound=Standard_True;
242           myShapesToAvoid.Add(aE1);
243           myShapesToAvoid.Add(aE2);
244         }
245       }
246     }// for (i=1; i<=aNbE; ++i) {
247     //
248     if (!bFound) {
249       break;
250     }
251     //
252   }//while (1) 
253   //printf(" EdgesToAvoid=%d, iCnt=%d\n", EdgesToAvoid.Extent(), iCnt);
254 }  
255 //=======================================================================
256 //function : PerformLoops
257 //purpose  : 
258 //=======================================================================
259   void BOPAlgo_BuilderFace::PerformLoops()
260 {
261   myErrorStatus=0;
262   //
263   Standard_Boolean bFlag;
264   Standard_Integer iErr, aNbEA;
265   BOPCol_ListIteratorOfListOfShape aIt;
266   BOPCol_MapIteratorOfMapOfOrientedShape aItM;
267   BOPCol_IndexedDataMapOfShapeListOfShape aVEMap;
268   BOPCol_MapOfOrientedShape aMAdded;
269   TopoDS_Iterator aItW;
270   BRep_Builder aBB; 
271   BOPAlgo_WireEdgeSet aWES(myAllocator);
272   BOPAlgo_WireSplitter aWSp(myAllocator);
273   //
274   // 1. 
275   myLoops.Clear();
276   aWES.SetFace(myFace);
277   //
278   aIt.Initialize(myShapes);
279   for (; aIt.More(); aIt.Next()) {
280     const TopoDS_Shape& aE=aIt.Value();
281     if (!myShapesToAvoid.Contains(aE)) {
282       aWES.AddStartElement(aE);
283     }
284   }
285   //
286   aWSp.SetWES(aWES);
287   aWSp.Perform();
288   iErr=aWSp.ErrorStatus();
289   if (iErr) {
290     return;
291   }
292   //
293   const BOPCol_ListOfShape& aLW=aWES.Shapes();
294   aIt.Initialize (aLW);
295   for (; aIt.More(); aIt.Next()) {
296     const TopoDS_Shape& aW=aIt.Value();
297     myLoops.Append(aW);
298   }
299   // Post Treatment
300   BOPCol_MapOfOrientedShape aMEP;
301   // 
302   // a. collect all edges that are in loops
303   aIt.Initialize (myLoops);
304   for (; aIt.More(); aIt.Next()) {
305     const TopoDS_Shape& aW=aIt.Value();
306     aItW.Initialize(aW);
307     for (; aItW.More(); aItW.Next()) {
308       const TopoDS_Shape& aE=aItW.Value();
309       aMEP.Add(aE);
310     }
311   }
312   // 
313   // b. collect all edges that are to avoid
314   aItM.Initialize(myShapesToAvoid);
315   for (; aItM.More(); aItM.Next()) {
316     const TopoDS_Shape& aE=aItM.Key();
317     aMEP.Add(aE);
318   }
319   //
320   // c. add all edges that are not processed to myShapesToAvoid
321   aIt.Initialize (myShapes);
322   for (; aIt.More(); aIt.Next()) {
323     const TopoDS_Shape& aE=aIt.Value();
324     if (!aMEP.Contains(aE)) {
325       myShapesToAvoid.Add(aE);
326     }
327   }
328   //
329   // 2. Internal Wires
330   myLoopsInternal.Clear();
331   //
332   aNbEA=myShapesToAvoid.Extent();
333   aItM.Initialize(myShapesToAvoid);
334   for (; aItM.More(); aItM.Next()) {
335     const TopoDS_Shape& aEE=aItM.Key();
336     BOPTools::MapShapesAndAncestors(aEE, TopAbs_VERTEX, TopAbs_EDGE, aVEMap);
337   }
338   //
339   bFlag=Standard_True;
340   aItM.Initialize(myShapesToAvoid);
341   for (; aItM.More()&&bFlag; aItM.Next()) {
342     const TopoDS_Shape& aEE=aItM.Key();
343     if (!aMAdded.Add(aEE)) {
344       continue;
345     }
346     //
347     // make new wire
348     TopoDS_Wire aW;
349     aBB.MakeWire(aW);
350     aBB.Add(aW, aEE);
351     //
352     aItW.Initialize(aW);
353     for (; aItW.More()&&bFlag; aItW.Next()) {
354       const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&aItW.Value()));
355       //
356       TopoDS_Iterator aItE(aE);
357       for (; aItE.More()&&bFlag; aItE.Next()) {
358         const TopoDS_Vertex& aV = (*(TopoDS_Vertex *)(&aItE.Value()));
359         const BOPCol_ListOfShape& aLE=aVEMap.FindFromKey(aV);
360         aIt.Initialize(aLE);
361         for (; aIt.More()&&bFlag; aIt.Next()) { 
362           const TopoDS_Shape& aEx=aIt.Value();
363           if (aMAdded.Add(aEx)) {
364             aBB.Add(aW, aEx);
365             if(aMAdded.Extent()==aNbEA) {
366               bFlag=!bFlag;
367             }
368           }
369         }//for (; aIt.More(); aIt.Next()) { 
370       }//for (; aItE.More(); aItE.Next()) {
371     }//for (; aItW.More(); aItW.Next()) {
372     myLoopsInternal.Append(aW);
373   }//for (; aItM.More(); aItM.Next()) {
374 }
375 //=======================================================================
376 //function : PerformAreas
377 //purpose  : 
378 //=======================================================================
379   void BOPAlgo_BuilderFace::PerformAreas()
380 {
381   myErrorStatus=0;
382   //
383   Standard_Boolean bIsGrowth, bIsHole;
384   Standard_Real aTol;
385   TopoDS_Shape anInfinitePointShape;
386   //
387   BOPCol_ListOfShape aNewFaces, aHoleWires; 
388   BOPCol_DataMapOfShapeShape aInOutMap;
389   BOPCol_DataMapOfShapeListOfShape aMSH;
390   BOPCol_IndexedMapOfShape aMHE;
391
392   BOPCol_DataMapIteratorOfDataMapOfShapeListOfShape aItMSH;
393   BOPCol_ListIteratorOfListOfShape aIt1, aIt2;
394   BRep_Builder aBB;
395   Handle(Geom_Surface) aS;
396   TopLoc_Location aLoc;
397   //
398   aTol=BRep_Tool::Tolerance(myFace);
399   aS=BRep_Tool::Surface(myFace, aLoc);
400   //
401   myAreas.Clear();
402   //
403   //  Draft faces [aNewFaces]
404   aIt1.Initialize(myLoops);
405   for ( ; aIt1.More(); aIt1.Next()) {
406     const TopoDS_Shape& aWire=aIt1.Value();
407     //
408     bIsGrowth=IsGrowthWire(aWire, aMHE);
409     if (bIsGrowth) {
410       // make a growth face from a wire
411       TopoDS_Face aFace;
412       aBB.MakeFace(aFace, aS, aLoc, aTol);
413       aBB.Add (aFace, aWire);
414       //
415       aNewFaces.Append (aFace);
416     }
417     else{
418       // check if a wire is a hole 
419       //XX
420       TopoDS_Face aFace;
421       aBB.MakeFace(aFace, aS, aLoc, aTol);
422       aBB.Add (aFace, aWire);
423       //
424       IntTools_FClass2d& aClsf=myContext->FClass2d(aFace);
425       aClsf.Init(aFace, aTol);
426       //
427       bIsHole=aClsf.IsHole();
428       //
429       //bIsHole=BOPTools_AlgoTools::IsHole(aWire, myFace); 
430       //XX
431       if (bIsHole) {
432         aHoleWires.Append(aWire);
433         BOPTools::MapShapes(aWire, TopAbs_EDGE, aMHE);
434       }
435       else {
436         // make a growth face from a wire
437         TopoDS_Face aFace;
438         aBB.MakeFace(aFace, aS, aLoc, aTol);
439         aBB.Add (aFace, aWire);
440         //
441         aNewFaces.Append (aFace);
442       }
443     }
444   }
445   //
446   // 2. Find outer growth shell that is most close to each hole shell
447   aIt2.Initialize(aHoleWires);
448   for (; aIt2.More(); aIt2.Next()) {
449     const TopoDS_Shape& aHole = aIt2.Value();
450     //
451     aIt1.Initialize(aNewFaces);
452     for ( ; aIt1.More(); aIt1.Next()) {
453       const TopoDS_Shape& aF=aIt1.Value();
454       //
455       if (!IsInside(aHole, aF, myContext)){
456         continue;
457       }
458       //
459       if ( aInOutMap.IsBound (aHole)){
460         const TopoDS_Shape& aF2=aInOutMap(aHole);
461         if (IsInside(aF, aF2, myContext)) {
462           aInOutMap.UnBind(aHole);
463           aInOutMap.Bind (aHole, aF);
464         }
465       }
466       else{
467         aInOutMap.Bind (aHole, aF);
468       }
469     }
470     //
471     // Add aHole to a map Face/ListOfHoles [aMSH]
472     if (aInOutMap.IsBound(aHole)){
473       const TopoDS_Shape& aF=aInOutMap(aHole);
474       if (aMSH.IsBound(aF)) {
475         BOPCol_ListOfShape& aLH=aMSH.ChangeFind(aF);
476         aLH.Append(aHole);
477       }
478       else {
479         BOPCol_ListOfShape aLH;
480         aLH.Append(aHole);
481         aMSH.Bind(aF, aLH);
482       }
483     }
484   }// for (; aIt2.More(); aIt2.Next())
485   //
486   // 3. Add aHoles to Faces
487   aItMSH.Initialize(aMSH);
488   for (; aItMSH.More(); aItMSH.Next()) {
489     TopoDS_Face aF=(*(TopoDS_Face *)(&aItMSH.Key()));
490     //
491     const BOPCol_ListOfShape& aLH=aItMSH.Value();
492     aIt2.Initialize(aLH);
493     for (; aIt2.More(); aIt2.Next()) {
494       const TopoDS_Shape& aHole = aIt2.Value();
495       aBB.Add (aF, aHole);
496     }
497     //
498     // update classifier 
499     aTol=BRep_Tool::Tolerance(aF);
500     IntTools_FClass2d& aClsf=myContext->FClass2d(aF);
501     aClsf.Init(aF, aTol);
502   }
503   //
504   // These aNewFaces are draft faces that 
505   // do not contain any internal shapes
506   //
507   aIt1.Initialize(aNewFaces);
508   for ( ; aIt1.More(); aIt1.Next()) {
509     const TopoDS_Shape& aF=aIt1.Value();
510     myAreas.Append(aF);
511   }
512 }
513 //=======================================================================
514 //function : PerformInternalShapes
515 //purpose  : 
516 //=======================================================================
517   void BOPAlgo_BuilderFace::PerformInternalShapes()
518 {
519   myErrorStatus=0;
520   //
521   Standard_Integer aNbWI=myLoopsInternal.Extent();
522   if (!aNbWI) {// nothing to do
523     return;
524   }
525   // 
526   //Standard_Real aTol;
527   BRep_Builder aBB;
528   BOPCol_ListIteratorOfListOfShape aIt1, aIt2;
529   TopoDS_Iterator aIt; 
530   BOPCol_MapOfShape aME, aMEP;
531   BOPCol_MapIteratorOfMapOfShape aItME;
532   BOPCol_IndexedDataMapOfShapeListOfShape aMVE;
533   BOPCol_ListOfShape aLSI;
534   //
535   // 1. All internal edges
536   aIt1.Initialize(myLoopsInternal);
537   for (; aIt1.More(); aIt1.Next()) {
538     const TopoDS_Shape& aWire=aIt1.Value();
539     aIt.Initialize(aWire);
540     for (; aIt.More(); aIt.Next()) {
541       const TopoDS_Shape& aE=aIt.Value();
542       aME.Add(aE);
543     }
544   }
545   aNbWI=aME.Extent();
546   //
547   // 2 Process faces
548   aIt2.Initialize(myAreas);
549   for ( ; aIt2.More(); aIt2.Next()) {
550     TopoDS_Face& aF=(*(TopoDS_Face *)(&aIt2.Value()));
551     //
552     aMVE.Clear();
553     BOPTools::MapShapesAndAncestors(aF, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
554     //
555     // 2.1 Separate faces to process aMEP
556     aMEP.Clear();
557     aItME.Initialize(aME);
558     for (; aItME.More(); aItME.Next()) {
559       const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&aItME.Key()));
560       if (IsInside(aE, aF, myContext)) {
561         aMEP.Add(aE);
562       }
563     }
564     //
565     // 2.2 Make Internal Wires
566     aLSI.Clear();
567     MakeInternalWires(aMEP, aLSI);
568     //
569     // 2.3 Add them to aF
570     aIt1.Initialize(aLSI);
571     for (; aIt1.More(); aIt1.Next()) {
572       const TopoDS_Shape& aSI=aIt1.Value();
573       aBB.Add (aF, aSI);
574     }
575     //
576     // 2.4 Remove faces aMFP from aMF
577     aItME.Initialize(aMEP);
578     for (; aItME.More(); aItME.Next()) {
579       const TopoDS_Shape& aE=aItME.Key();
580       aME.Remove(aE);
581     }
582     //
583     aNbWI=aME.Extent();
584     if (!aNbWI) {
585       break;
586     }
587   } //for ( ; aIt2.More(); aIt2.Next()) {
588 }
589 //=======================================================================
590 //function : MakeInternalWires
591 //purpose  : 
592 //=======================================================================
593 void MakeInternalWires(const BOPCol_MapOfShape& theME,
594                        BOPCol_ListOfShape& theWires)
595 {
596   BOPCol_MapIteratorOfMapOfShape aItM;
597   BOPCol_MapOfShape aAddedMap;
598   BOPCol_ListIteratorOfListOfShape aItE;
599   BOPCol_IndexedDataMapOfShapeListOfShape aMVE;
600   BRep_Builder aBB;
601   //
602   aItM.Initialize(theME);
603   for (; aItM.More(); aItM.Next()) {
604     const TopoDS_Shape& aE=aItM.Key();
605     BOPTools::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
606   }
607   //
608   aItM.Initialize(theME);
609   for (; aItM.More(); aItM.Next()) {
610     TopoDS_Shape aEE=aItM.Key();
611     if (!aAddedMap.Add(aEE)) {
612       continue;
613     }
614     //
615     // make a new shell
616     TopoDS_Wire aW;
617     aBB.MakeWire(aW);    
618     aEE.Orientation(TopAbs_INTERNAL);
619     aBB.Add(aW, aEE);
620     //
621     TopoDS_Iterator aItAdded (aW);
622     for (; aItAdded.More(); aItAdded.Next()) {
623       const TopoDS_Shape& aE =aItAdded.Value();
624       //
625       TopExp_Explorer aExp(aE, TopAbs_VERTEX);
626       for (; aExp.More(); aExp.Next()) {
627         const TopoDS_Shape& aV =aExp.Current();
628         const BOPCol_ListOfShape& aLE=aMVE.FindFromKey(aV);
629         aItE.Initialize(aLE);
630         for (; aItE.More(); aItE.Next()) { 
631           TopoDS_Shape aEL=aItE.Value();
632           if (aAddedMap.Add(aEL)){
633             aEL.Orientation(TopAbs_INTERNAL);
634             aBB.Add(aW, aEL);
635           }
636         }
637       }
638     }
639     theWires.Append(aW);
640   }
641 }
642 //=======================================================================
643 //function : IsInside
644 //purpose  : 
645 //=======================================================================
646 Standard_Boolean IsInside(const TopoDS_Shape& theHole,
647                           const TopoDS_Shape& theF2,
648                           Handle(BOPInt_Context)& theContext)
649 {
650   Standard_Boolean bRet;
651   Standard_Real aT, aU, aV;
652   
653   TopAbs_State aState;
654   TopExp_Explorer aExp;
655   BOPCol_IndexedMapOfShape aME2;
656   gp_Pnt2d aP2D;
657   //
658   bRet=Standard_False;
659   aState=TopAbs_UNKNOWN;
660   const TopoDS_Face& aF2=(*(TopoDS_Face *)(&theF2));
661   //
662   BOPTools::MapShapes(aF2, TopAbs_EDGE, aME2);//AA
663   //
664   aExp.Init(theHole, TopAbs_EDGE);
665   if (aExp.More()) {
666     const TopoDS_Edge& aE =(*(TopoDS_Edge *)(&aExp.Current()));
667     if (aME2.Contains(aE)) {
668       return bRet;
669     }
670     if (!BRep_Tool::Degenerated(aE)) {
671       //
672       aT=BOPTools_AlgoTools2D::IntermediatePoint(aE);
673       BOPTools_AlgoTools2D::PointOnSurface(aE, aF2, aT, aU, aV);
674       aP2D.SetCoord(aU, aV);
675       //
676       IntTools_FClass2d& aClsf=theContext->FClass2d(aF2);
677       aState=aClsf.Perform(aP2D);
678       bRet=(aState==TopAbs_IN);
679     }
680   }
681   //
682   return bRet;
683 }
684
685 //=======================================================================
686 //function : IsGrowthWire
687 //purpose  : 
688 //=======================================================================
689 Standard_Boolean IsGrowthWire(const TopoDS_Shape& theWire,
690                               const BOPCol_IndexedMapOfShape& theMHE)
691 {
692   Standard_Boolean bRet;
693   TopoDS_Iterator aIt;
694   // 
695   bRet=Standard_False;
696   if (theMHE.Extent()) {
697     aIt.Initialize(theWire);
698     for(; aIt.More(); aIt.Next()) {
699       const TopoDS_Shape& aE=aIt.Value();
700       if (theMHE.Contains(aE)) {
701         return !bRet;
702       }
703     }
704   }
705   return bRet;
706 }
707
708 //BRepTools::Write(aFF, "ff");
709 //
710 //  ErrorStatus :
711 // 11 - Null Context
712 // 12 - Null face generix