]> SALOME platform Git repositories - modules/geom.git/blob - src/GEOMAlgo/GEOMAlgo_BuilderFace.cxx
Salome HOME
0021434: Boolean operations generate a shape with big vertex tolerance.
[modules/geom.git] / src / GEOMAlgo / GEOMAlgo_BuilderFace.cxx
1 // Copyright (C) 2007-2011  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21
22 // File:        GEOMAlgo_BuilderFace.cxx
23 // Author:      Peter KURNEV
24
25 #include <GEOMAlgo_BuilderFace.ixx>
26
27 #include <GEOMAlgo_Tools3D.hxx>
28 #include <GEOMAlgo_BuilderTools.hxx>
29 #include <GEOMAlgo_WireEdgeSet.hxx>
30 #include <GEOMAlgo_WESCorrector.hxx>
31
32 #include <NMTTools_ListOfCoupleOfShape.hxx>
33 #include <NMTTools_CoupleOfShape.hxx>
34 #include <NMTTools_ListIteratorOfListOfCoupleOfShape.hxx>
35
36 #include <Basics_OCCTVersion.hxx>
37
38 #include <gp_Pnt2d.hxx>
39 #include <gp_Pln.hxx>
40 #include <gp_Vec.hxx>
41 #include <gp_Dir.hxx>
42 #include <gp_Pnt.hxx>
43
44 #include <Geom_Surface.hxx>
45
46 #include <TopAbs.hxx>
47 #include <TopLoc_Location.hxx>
48
49 #include <TopoDS_Iterator.hxx>
50 #include <TopoDS_Face.hxx>
51 #include <TopoDS.hxx>
52 #include <TopoDS_Shape.hxx>
53 #include <TopoDS_Wire.hxx>
54 #include <TopoDS_Edge.hxx>
55 #include <TopoDS_Vertex.hxx>
56
57 #include <BRep_Builder.hxx>
58 #include <BRep_Tool.hxx>
59 #include <BRepTools.hxx>
60
61 #include <TopExp.hxx>
62 #include <TopExp_Explorer.hxx>
63
64 #include <TopTools_MapOfShape.hxx>
65 #include <TopTools_MapIteratorOfMapOfShape.hxx>
66 #include <TopTools_MapOfOrientedShape.hxx>
67 #include <TopTools_MapIteratorOfMapOfOrientedShape.hxx>
68 #include <TopTools_ListOfShape.hxx>
69 #include <TopTools_ListIteratorOfListOfShape.hxx>
70 #include <TopTools_DataMapOfShapeShape.hxx>
71 #include <TopTools_IndexedMapOfShape.hxx>
72 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
73 #include <TopTools_DataMapOfShapeListOfShape.hxx>
74 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
75
76 #include <IntTools_FClass2d.hxx>
77 #include <IntTools_Context.hxx>
78
79 #include <BOPTools_Tools2D.hxx>
80 #include <BOP_WireEdgeSet.hxx>
81 #include <BOP_WESCorrector.hxx>
82
83 //
84 static
85   Standard_Boolean IsGrowthWire(const TopoDS_Shape& ,
86
87                                 const TopTools_IndexedMapOfShape& );
88
89 static 
90   Standard_Boolean IsInside(const TopoDS_Shape& ,
91                             const TopoDS_Shape& ,
92 #if OCC_VERSION_LARGE > 0x06050200
93                             const Handle(IntTools_Context)& );
94 #else
95                             IntTools_PContext& );
96 #endif
97
98 static
99   void MakeInternalWires(const TopTools_MapOfShape& ,
100                          TopTools_ListOfShape& );
101
102 //=======================================================================
103 //function : 
104 //purpose  : 
105 //=======================================================================
106   GEOMAlgo_BuilderFace::GEOMAlgo_BuilderFace()
107 :
108   GEOMAlgo_BuilderArea()
109 {
110 }
111 //=======================================================================
112 //function : ~
113 //purpose  : 
114 //=======================================================================
115   GEOMAlgo_BuilderFace::~GEOMAlgo_BuilderFace()
116 {
117 }
118 //=======================================================================
119 //function : SetFace
120 //purpose  : 
121 //=======================================================================
122   void GEOMAlgo_BuilderFace::SetFace(const TopoDS_Face& theFace)
123 {
124   myFace=theFace;
125 }
126 //=======================================================================
127 //function : Face
128 //purpose  : 
129 //=======================================================================
130   const TopoDS_Face& GEOMAlgo_BuilderFace::Face()const
131 {
132   return myFace;
133 }
134 //=======================================================================
135 //function : Perform
136 //purpose  : 
137 //=======================================================================
138   void GEOMAlgo_BuilderFace::Perform()
139 {
140   myErrorStatus=0;
141   //
142 #if OCC_VERSION_LARGE <= 0x06050200
143   if (myContext==NULL) {
144     myErrorStatus=11;// Null Context
145     return;
146   }
147 #endif
148   //
149   if (myFace.IsNull()) {
150     myErrorStatus=12;// Null face generix
151     return;
152   }
153   //
154 #if OCC_VERSION_LARGE > 0x06050200
155   // Initialize the context
156   GEOMAlgo_BuilderArea::Perform();
157 #endif
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 GEOMAlgo_BuilderFace::PerformShapesToAvoid()
184 {
185   Standard_Boolean bFound;
186   Standard_Integer i, iCnt, aNbV, aNbE;
187   TopTools_IndexedDataMapOfShapeListOfShape aMVE;
188   TopTools_ListIteratorOfListOfShape aIt;
189   //
190   myShapesToAvoid.Clear();
191   //
192   iCnt=0;
193   while (1) {
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         TopExp::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       TopTools_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 GEOMAlgo_BuilderFace::PerformLoops()
260 {
261   myErrorStatus=0;
262   //
263   Standard_Boolean bFlag;
264   Standard_Integer aNbEA;
265   TopTools_ListIteratorOfListOfShape aIt;
266   TopTools_MapIteratorOfMapOfOrientedShape aItM;
267   TopTools_IndexedDataMapOfShapeListOfShape aVEMap;
268   TopTools_MapOfOrientedShape aMAdded;
269   TopoDS_Iterator aItW;
270   BRep_Builder aBB; 
271   GEOMAlgo_WireEdgeSet aWES;
272   GEOMAlgo_WESCorrector aWESCor;
273   //
274   // 1. Usual Wires 
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   aWESCor.SetWES(aWES);
287   aWESCor.Perform();
288   //
289   GEOMAlgo_WireEdgeSet& aWESN=aWESCor.NewWES();
290   const TopTools_ListOfShape& aLW=aWESN.Shapes();
291   //
292   aIt.Initialize (aLW);
293   for (; aIt.More(); aIt.Next()) {
294     const TopoDS_Shape& aW=aIt.Value();
295     myLoops.Append(aW);
296   }
297   //modified by NIZNHY-PKV Tue Aug  5 15:09:29 2008f
298   // Post Treatment
299   TopTools_MapOfOrientedShape aMEP;
300   // 
301   // a. collect all edges that are in loops
302   aIt.Initialize (myLoops);
303   for (; aIt.More(); aIt.Next()) {
304     const TopoDS_Shape& aW=aIt.Value();
305     aItW.Initialize(aW);
306     for (; aItW.More(); aItW.Next()) {
307       const TopoDS_Shape& aE=aItW.Value();
308       aMEP.Add(aE);
309     }
310   }
311   // 
312   // b. collect all edges that are to avoid
313   aItM.Initialize(myShapesToAvoid);
314   for (; aItM.More(); aItM.Next()) {
315     const TopoDS_Shape& aE=aItM.Key();
316     aMEP.Add(aE);
317   }
318   //
319   // c. add all edges that are not processed to myShapesToAvoid
320   aIt.Initialize (myShapes);
321   for (; aIt.More(); aIt.Next()) {
322     const TopoDS_Shape& aE=aIt.Value();
323     if (!aMEP.Contains(aE)) {
324       myShapesToAvoid.Add(aE);
325     }
326   }
327   //modified by NIZNHY-PKV Tue Aug  5 15:09:35 2008t
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     TopExp::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 TopTools_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 GEOMAlgo_BuilderFace::PerformAreas()
380 {
381   myErrorStatus=0;
382   //
383   Standard_Boolean bIsGrowth, bIsHole;
384   Standard_Real aTol;
385   TopTools_ListOfShape aNewFaces, aHoleWires; 
386   TopoDS_Shape anInfinitePointShape;
387   TopTools_DataMapOfShapeShape aInOutMap;
388   TopTools_DataMapOfShapeListOfShape aMSH;
389   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItMSH;
390   TopTools_ListIteratorOfListOfShape aIt1, aIt2;
391   TopTools_IndexedMapOfShape aMHE;
392   BRep_Builder aBB;
393   Handle(Geom_Surface) aS;
394   TopLoc_Location aLoc;
395   //
396   aTol=BRep_Tool::Tolerance(myFace);
397   aS=BRep_Tool::Surface(myFace, aLoc);
398   //
399   myAreas.Clear();
400   //
401   //  Draft faces [aNewFaces]
402   aIt1.Initialize(myLoops);
403   for ( ; aIt1.More(); aIt1.Next()) {
404     const TopoDS_Shape& aWire=aIt1.Value();
405     //
406     bIsGrowth=IsGrowthWire(aWire, aMHE);
407     if (bIsGrowth) {
408       // make a growth face from a wire
409       TopoDS_Face aFace;
410       aBB.MakeFace(aFace, aS, aLoc, aTol);
411       aBB.Add (aFace, aWire);
412       //
413       aNewFaces.Append (aFace);
414     }
415     else{
416       // check if a wire is a hole 
417       //XX
418       //bIsHole=IsHole(aWire, myFace, myContext);
419       bIsHole=GEOMAlgo_BuilderTools::IsHole(aWire, myFace);
420       //XX
421       if (bIsHole) {
422         aHoleWires.Append(aWire);
423         TopExp::MapShapes(aWire, TopAbs_EDGE, aMHE);
424       }
425       else {
426         // make a growth face from a wire
427         TopoDS_Face aFace;
428         aBB.MakeFace(aFace, aS, aLoc, aTol);
429         aBB.Add (aFace, aWire);
430         //
431         aNewFaces.Append (aFace);
432       }
433     }
434   }
435   //
436   // 2. Find outer growth shell that is most close to each hole shell
437   aIt2.Initialize(aHoleWires);
438   for (; aIt2.More(); aIt2.Next()) {
439     const TopoDS_Shape& aHole = aIt2.Value();
440     //
441     aIt1.Initialize(aNewFaces);
442     for ( ; aIt1.More(); aIt1.Next()) {
443       const TopoDS_Shape& aF=aIt1.Value();
444       //
445       if (!IsInside(aHole, aF, myContext)){
446         continue;
447       }
448       //
449       if ( aInOutMap.IsBound (aHole)){
450         const TopoDS_Shape& aF2=aInOutMap(aHole);
451         if (IsInside(aF, aF2, myContext)) {
452           aInOutMap.UnBind(aHole);
453           aInOutMap.Bind (aHole, aF);
454         }
455       }
456       else{
457         aInOutMap.Bind (aHole, aF);
458       }
459     }
460     //
461     // Add aHole to a map Face/ListOfHoles [aMSH]
462     if (aInOutMap.IsBound(aHole)){
463       const TopoDS_Shape& aF=aInOutMap(aHole);
464       if (aMSH.IsBound(aF)) {
465         TopTools_ListOfShape& aLH=aMSH.ChangeFind(aF);
466         aLH.Append(aHole);
467       }
468       else {
469         TopTools_ListOfShape aLH;
470         aLH.Append(aHole);
471         aMSH.Bind(aF, aLH);
472       }
473     }
474   }// for (; aIt2.More(); aIt2.Next())
475   //
476   // 3. Add aHoles to Faces
477   aItMSH.Initialize(aMSH);
478   for (; aItMSH.More(); aItMSH.Next()) {
479     TopoDS_Face aF=TopoDS::Face(aItMSH.Key());
480     //
481     const TopTools_ListOfShape& aLH=aItMSH.Value();
482     aIt2.Initialize(aLH);
483     for (; aIt2.More(); aIt2.Next()) {
484       const TopoDS_Shape& aHole = aIt2.Value();
485       aBB.Add (aF, aHole);
486     }
487     //
488     // update classifier 
489     aTol=BRep_Tool::Tolerance(aF);
490     IntTools_FClass2d& aClsf=myContext->FClass2d(aF);
491     aClsf.Init(aF, aTol);
492   }
493   //
494   // These aNewFaces are draft faces that 
495   // do not contain any internal shapes
496   //
497   myAreas.Append(aNewFaces);
498 }
499 //=======================================================================
500 //function : PerformInternalShapes
501 //purpose  : 
502 //=======================================================================
503   void GEOMAlgo_BuilderFace::PerformInternalShapes()
504 {
505   myErrorStatus=0;
506   //
507   Standard_Integer aNbWI=myLoopsInternal.Extent();
508   if (!aNbWI) {// nothing to do
509     return;
510   }
511   // 
512   //Standard_Real aTol;
513   BRep_Builder aBB;
514   TopTools_ListIteratorOfListOfShape aIt1, aIt2;
515   TopoDS_Iterator aIt; 
516   TopTools_MapOfShape aME, aMEP;
517   TopTools_MapIteratorOfMapOfShape aItME;
518   TopTools_IndexedDataMapOfShapeListOfShape aMVE;
519   TopTools_ListOfShape aLSI;
520   //
521   // 1. All internal edges
522   aIt1.Initialize(myLoopsInternal);
523   for (; aIt1.More(); aIt1.Next()) {
524     const TopoDS_Shape& aWire=aIt1.Value();
525     aIt.Initialize(aWire);
526     for (; aIt.More(); aIt.Next()) {
527       const TopoDS_Shape& aE=aIt.Value();
528       aME.Add(aE);
529     }
530   }
531   aNbWI=aME.Extent();
532   //
533   // 2 Process faces
534   aIt2.Initialize(myAreas);
535   for ( ; aIt2.More(); aIt2.Next()) {
536     TopoDS_Face& aF=TopoDS::Face(aIt2.Value());
537     //
538     aMVE.Clear();
539     TopExp::MapShapesAndAncestors(aF, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
540     //
541     // 2.1 Separate faces to process aMEP
542     aMEP.Clear();
543     aItME.Initialize(aME);
544     for (; aItME.More(); aItME.Next()) {
545       const TopoDS_Edge& aE=TopoDS::Edge(aItME.Key());
546       if (IsInside(aE, aF, myContext)) {
547         aMEP.Add(aE);
548       }
549     }
550     //
551     // 2.2 Make Internal Wires
552     aLSI.Clear();
553     MakeInternalWires(aMEP, aLSI);
554     //
555     // 2.3 Add them to aF
556     aIt1.Initialize(aLSI);
557     for (; aIt1.More(); aIt1.Next()) {
558       const TopoDS_Shape& aSI=aIt1.Value();
559       aBB.Add (aF, aSI);
560     }
561     //
562     // 2.4 Remove faces aMFP from aMF
563     aItME.Initialize(aMEP);
564     for (; aItME.More(); aItME.Next()) {
565       const TopoDS_Shape& aE=aItME.Key();
566       aME.Remove(aE);
567     }
568     //
569     aNbWI=aME.Extent();
570     if (!aNbWI) {
571       break;
572     }
573   } //for ( ; aIt2.More(); aIt2.Next()) {
574 }
575 //=======================================================================
576 //function : MakeInternalWires
577 //purpose  : 
578 //=======================================================================
579 void MakeInternalWires(const TopTools_MapOfShape& theME,
580                        TopTools_ListOfShape& theWires)
581 {
582   TopTools_MapIteratorOfMapOfShape aItM;
583   TopTools_MapOfShape aAddedMap;
584   TopTools_ListIteratorOfListOfShape aItE;
585   TopTools_IndexedDataMapOfShapeListOfShape aMVE;
586   BRep_Builder aBB;
587   //
588   aItM.Initialize(theME);
589   for (; aItM.More(); aItM.Next()) {
590     const TopoDS_Shape& aE=aItM.Key();
591     TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
592   }
593   //
594   aItM.Initialize(theME);
595   for (; aItM.More(); aItM.Next()) {
596     TopoDS_Shape aEE=aItM.Key();
597     if (!aAddedMap.Add(aEE)) {
598       continue;
599     }
600     //
601     // make a new shell
602     TopoDS_Wire aW;
603     aBB.MakeWire(aW);    
604     aEE.Orientation(TopAbs_INTERNAL);
605     aBB.Add(aW, aEE);
606     //
607     TopoDS_Iterator aItAdded (aW);
608     for (; aItAdded.More(); aItAdded.Next()) {
609       const TopoDS_Shape& aE =aItAdded.Value();
610       //
611       TopExp_Explorer aExp(aE, TopAbs_VERTEX);
612       for (; aExp.More(); aExp.Next()) {
613         const TopoDS_Shape& aV =aExp.Current();
614         const TopTools_ListOfShape& aLE=aMVE.FindFromKey(aV);
615         aItE.Initialize(aLE);
616         for (; aItE.More(); aItE.Next()) { 
617           TopoDS_Shape aEL=aItE.Value();
618           if (aAddedMap.Add(aEL)){
619             aEL.Orientation(TopAbs_INTERNAL);
620             aBB.Add(aW, aEL);
621           }
622         }
623       }
624     }
625     theWires.Append(aW);
626   }
627 }
628 //=======================================================================
629 //function : IsInside
630 //purpose  : 
631 //=======================================================================
632 Standard_Boolean IsInside(const TopoDS_Shape& theHole,
633                           const TopoDS_Shape& theF2,
634 #if OCC_VERSION_LARGE > 0x06050200
635                           const Handle(IntTools_Context)& theContext)
636 #else
637                           IntTools_PContext& theContext)
638 #endif
639 {
640   Standard_Boolean bRet;
641   Standard_Real aT, aU, aV;
642   
643   TopAbs_State aState;
644   TopExp_Explorer aExp;
645   TopTools_IndexedMapOfShape aME2;
646   gp_Pnt2d aP2D;
647   //
648   bRet=Standard_False;
649   aState=TopAbs_UNKNOWN;
650   const TopoDS_Face& aF2=TopoDS::Face(theF2);
651   //
652   TopExp::MapShapes(aF2, TopAbs_EDGE, aME2);
653   //
654   aExp.Init(theHole, TopAbs_EDGE);
655   if (aExp.More()) {
656     const TopoDS_Edge& aE = TopoDS::Edge(aExp.Current());
657     if (aME2.Contains(aE)) {
658       return bRet;
659     }
660     //
661     aT=BOPTools_Tools2D::IntermediatePoint(aE);
662     BOPTools_Tools2D::PointOnSurface(aE, aF2, aT, aU, aV);
663     aP2D.SetCoord(aU, aV);
664     //
665     IntTools_FClass2d& aClsf=theContext->FClass2d(aF2);
666     aState=aClsf.Perform(aP2D);
667     bRet=(aState==TopAbs_IN);
668   }
669   //
670   return bRet;
671 }
672
673 //=======================================================================
674 //function : IsGrowthWire
675 //purpose  : 
676 //=======================================================================
677 Standard_Boolean IsGrowthWire(const TopoDS_Shape& theWire,
678                               const TopTools_IndexedMapOfShape& theMHE)
679 {
680   Standard_Boolean bRet;
681   TopoDS_Iterator aIt;
682   // 
683   bRet=Standard_False;
684   if (theMHE.Extent()) {
685     aIt.Initialize(theWire);
686     for(; aIt.More(); aIt.Next()) {
687       const TopoDS_Shape& aE=aIt.Value();
688       if (theMHE.Contains(aE)) {
689         return !bRet;
690       }
691     }
692   }
693   return bRet;
694 }
695
696 //BRepTools::Write(aFF, "ff");
697 //
698 //  ErrorStatus :
699 // 11 - Null Context
700 // 12 - Null face generix
701
702 /*
703 //=======================================================================
704 //function : IsInside
705 //purpose  : 
706 //=======================================================================
707 Standard_Boolean IsInside(const TopoDS_Shape& theHole,
708                           const TopoDS_Shape& theF2,
709                           IntTools_PContext& theContext)
710 {
711   Standard_Real aT, aU, aV;
712   TopExp_Explorer aExp;
713   TopAbs_State aState=TopAbs_UNKNOWN;
714   gp_Pnt2d aP2D;
715   //
716   const TopoDS_Face& aF2=TopoDS::Face(theF2);
717   //
718   aExp.Init(theHole, TopAbs_EDGE);
719   if (aExp.More()){
720     const TopoDS_Edge& aE = TopoDS::Edge(aExp.Current());
721     aT=BOPTools_Tools2D::IntermediatePoint(aE);
722     BOPTools_Tools2D::PointOnSurface(aE, aF2, aT, aU, aV);
723     aP2D.SetCoord(aU, aV);
724     //
725     IntTools_FClass2d& aClsf=theContext->FClass2d(aF2);
726     aState=aClsf.Perform(aP2D);
727   }
728   return (aState==TopAbs_IN);
729 }
730 */