Salome HOME
This commit was generated by cvs2git to create tag 'StableState1'.
[modules/geom.git] / src / GEOMAlgo / GEOMAlgo_BuilderFace.cxx
1 // Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 // 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either 
7 // version 2.1 of the License.
8 // 
9 // This library is distributed in the hope that it will be useful 
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public  
15 // License along with this library; if not, write to the Free Software 
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 //
20 // File:        GEOMAlgo_BuilderFace.cxx
21 // Created:     
22 // Author:      Peter KURNEV
23
24 #include <GEOMAlgo_BuilderFace.ixx>
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.hxx>
40 #include <TopoDS_Shape.hxx>
41 #include <TopoDS_Wire.hxx>
42 #include <TopoDS_Edge.hxx>
43 #include <TopoDS_Vertex.hxx>
44
45 #include <BRep_Builder.hxx>
46 #include <BRep_Tool.hxx>
47 #include <BRepTools.hxx>
48
49 #include <TopExp.hxx>
50 #include <TopExp_Explorer.hxx>
51
52 #include <TopTools_MapOfShape.hxx>
53 #include <TopTools_MapIteratorOfMapOfShape.hxx>
54 #include <TopTools_MapOfOrientedShape.hxx>
55 #include <TopTools_MapIteratorOfMapOfOrientedShape.hxx>
56 #include <TopTools_ListOfShape.hxx>
57 #include <TopTools_ListIteratorOfListOfShape.hxx>
58 #include <TopTools_DataMapOfShapeShape.hxx>
59 #include <TopTools_IndexedMapOfShape.hxx>
60 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
61 #include <TopTools_DataMapOfShapeListOfShape.hxx>
62 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
63
64 #include <IntTools_FClass2d.hxx>
65 #include <IntTools_Context.hxx>
66
67 #include <BOPTools_Tools2D.hxx>
68 #include <BOP_WireEdgeSet.hxx>
69 #include <BOP_WESCorrector.hxx>
70
71 #include <NMTTools_ListOfCoupleOfShape.hxx>
72 #include <NMTTools_CoupleOfShape.hxx>
73 #include <NMTTools_ListIteratorOfListOfCoupleOfShape.hxx>
74
75 #include <GEOMAlgo_Tools3D.hxx>
76 #include <GEOMAlgo_BuilderTools.hxx>
77 #include <GEOMAlgo_WireEdgeSet.hxx>
78 #include <GEOMAlgo_WESCorrector.hxx>
79
80 //
81 static
82   Standard_Boolean IsGrowthWire(const TopoDS_Shape& ,
83
84                                 const TopTools_IndexedMapOfShape& );
85
86 static 
87   Standard_Boolean IsInside(const TopoDS_Shape& ,
88                             const TopoDS_Shape& ,
89                             IntTools_PContext& );
90 static
91   void MakeInternalWires(const TopTools_MapOfShape& ,
92                          TopTools_ListOfShape& );
93
94 //=======================================================================
95 //function : 
96 //purpose  : 
97 //=======================================================================
98   GEOMAlgo_BuilderFace::GEOMAlgo_BuilderFace()
99 :
100   GEOMAlgo_BuilderArea()
101 {
102 }
103 //=======================================================================
104 //function : ~
105 //purpose  : 
106 //=======================================================================
107   GEOMAlgo_BuilderFace::~GEOMAlgo_BuilderFace()
108 {
109 }
110 //=======================================================================
111 //function : SetFace
112 //purpose  : 
113 //=======================================================================
114   void GEOMAlgo_BuilderFace::SetFace(const TopoDS_Face& theFace)
115 {
116   myFace=theFace;
117 }
118 //=======================================================================
119 //function : Face
120 //purpose  : 
121 //=======================================================================
122   const TopoDS_Face& GEOMAlgo_BuilderFace::Face()const
123 {
124   return myFace;
125 }
126 //=======================================================================
127 //function : Perform
128 //purpose  : 
129 //=======================================================================
130   void GEOMAlgo_BuilderFace::Perform()
131 {
132   myErrorStatus=0;
133   //
134   if (myContext==NULL) {
135     myErrorStatus=11;// Null Context
136     return;
137   }
138   //
139   if (myFace.IsNull()) {
140     myErrorStatus=12;// Null face generix
141     return;
142   }
143   //
144   PerformShapesToAvoid();
145   if (myErrorStatus) {
146     return;
147   }
148   //
149   PerformLoops();
150   if (myErrorStatus) {
151     return;
152   }
153   //
154   PerformAreas();
155   if (myErrorStatus) {
156     return;
157   }
158   //
159   PerformInternalShapes();
160   if (myErrorStatus) {
161     return;
162   }
163 }
164 //=======================================================================
165 //function :PerformShapesToAvoid
166 //purpose  : 
167 //=======================================================================
168   void GEOMAlgo_BuilderFace::PerformShapesToAvoid()
169 {
170   Standard_Boolean bFound;
171   Standard_Integer i, iCnt, aNbV, aNbE;
172   TopTools_IndexedDataMapOfShapeListOfShape aMVE;
173   TopTools_ListIteratorOfListOfShape aIt;
174   //
175   myShapesToAvoid.Clear();
176   //
177   iCnt=0;
178   while (1) {
179     ++iCnt;
180     bFound=Standard_False;
181     //
182     // 1. MEF
183     aMVE.Clear();
184     aIt.Initialize (myShapes);
185     for (; aIt.More(); aIt.Next()) {
186       const TopoDS_Shape& aE=aIt.Value();
187       if (!myShapesToAvoid.Contains(aE)) {
188         TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
189       }
190       else {
191         int a=0;
192       }
193     }
194     aNbV=aMVE.Extent();
195     //
196     // 2. myEdgesToAvoid
197     for (i=1; i<=aNbV; ++i) {
198       const TopoDS_Vertex& aV=TopoDS::Vertex(aMVE.FindKey(i));
199       //
200       TopTools_ListOfShape& aLE=aMVE.ChangeFromKey(aV);
201       aNbE=aLE.Extent();
202       if (!aNbE) {
203         continue;
204       }
205       //
206       const TopoDS_Edge& aE1=TopoDS::Edge(aLE.First());
207       if (aNbE==1) {
208         if (BRep_Tool::Degenerated(aE1)) {
209           continue;
210         }
211         if (aV.Orientation()==TopAbs_INTERNAL) {
212           continue;
213         }
214         bFound=Standard_True;
215         myShapesToAvoid.Add(aE1);
216       }
217       else if (aNbE==2) {
218         const TopoDS_Edge& aE2=TopoDS::Edge(aLE.Last());
219         if (aE2.IsSame(aE1)) {
220           TopoDS_Vertex aV1x, aV2x;
221           //
222           TopExp::Vertices(aE1, aV1x, aV2x);
223           if (aV1x.IsSame(aV2x)) {
224             continue;
225           }
226           bFound=Standard_True;
227           myShapesToAvoid.Add(aE1);
228           myShapesToAvoid.Add(aE2);
229         }
230       }
231     }// for (i=1; i<=aNbE; ++i) {
232     //
233     if (!bFound) {
234       break;
235     }
236     //
237   }//while (1) 
238   //printf(" EdgesToAvoid=%d, iCnt=%d\n", EdgesToAvoid.Extent(), iCnt);
239 }  
240 //=======================================================================
241 //function : PerformLoops
242 //purpose  : 
243 //=======================================================================
244   void GEOMAlgo_BuilderFace::PerformLoops()
245 {
246   myErrorStatus=0;
247   //
248   Standard_Boolean bFlag;
249   Standard_Integer aNbEA;
250   TopTools_ListIteratorOfListOfShape aIt;
251   TopTools_MapIteratorOfMapOfOrientedShape aItM;
252   TopTools_IndexedDataMapOfShapeListOfShape aVEMap;
253   TopTools_MapOfOrientedShape aMAdded;
254   BRep_Builder aBB; 
255   GEOMAlgo_WireEdgeSet aWES;
256   GEOMAlgo_WESCorrector aWESCor;
257   //
258   // 1. Usual Wires 
259   myLoops.Clear();
260   aWES.SetFace(myFace);
261   //
262   aIt.Initialize (myShapes);
263   for (; aIt.More(); aIt.Next()) {
264     const TopoDS_Shape& aE=aIt.Value();
265     if (!myShapesToAvoid.Contains(aE)) {
266       aWES.AddStartElement(aE);
267     }
268   }
269   //
270   aWESCor.SetWES(aWES);
271   aWESCor.Perform();
272   //
273   GEOMAlgo_WireEdgeSet& aWESN=aWESCor.NewWES();
274   const TopTools_ListOfShape& aLW=aWESN.Shapes();
275   //
276   aIt.Initialize (aLW);
277   for (; aIt.More(); aIt.Next()) {
278     const TopoDS_Shape& aW=aIt.Value();
279     myLoops.Append(aW);
280   }
281   //
282   // 2. Internal Wires
283   myLoopsInternal.Clear();
284   //
285   aNbEA=myShapesToAvoid.Extent();
286   aItM.Initialize(myShapesToAvoid);
287   for (; aItM.More(); aItM.Next()) {
288     const TopoDS_Shape& aEE=aItM.Key();
289     TopExp::MapShapesAndAncestors(aEE, TopAbs_VERTEX, TopAbs_EDGE, aVEMap);
290   }
291   //
292   bFlag=Standard_True;
293   aItM.Initialize(myShapesToAvoid);
294   for (; aItM.More()&&bFlag; aItM.Next()) {
295     const TopoDS_Shape& aEE=aItM.Key();
296     if (!aMAdded.Add(aEE)) {
297       continue;
298     }
299     //
300     // make new wire
301     TopoDS_Wire aW;
302     aBB.MakeWire(aW);
303     aBB.Add(aW, aEE);
304     //
305     TopoDS_Iterator aItW (aW);
306     for (; aItW.More()&&bFlag; aItW.Next()) {
307       const TopoDS_Edge& aE=TopoDS::Edge(aItW.Value());
308       //
309       TopoDS_Iterator aItE(aE);
310       for (; aItE.More()&&bFlag; aItE.Next()) {
311         const TopoDS_Vertex& aV = TopoDS::Vertex(aItE.Value());
312         const TopTools_ListOfShape& aLE=aVEMap.FindFromKey(aV);
313         aIt.Initialize(aLE);
314         for (; aIt.More()&&bFlag; aIt.Next()) { 
315           const TopoDS_Shape& aEx=aIt.Value();
316           if (aMAdded.Add(aEx)) {
317             aBB.Add(aW, aEx);
318             if(aMAdded.Extent()==aNbEA) {
319               bFlag=!bFlag;
320             }
321           }
322         }//for (; aIt.More(); aIt.Next()) { 
323       }//for (; aItE.More(); aItE.Next()) {
324     }//for (; aItW.More(); aItW.Next()) {
325     myLoopsInternal.Append(aW);
326   }//for (; aItM.More(); aItM.Next()) {
327 }
328 //=======================================================================
329 //function : PerformAreas
330 //purpose  : 
331 //=======================================================================
332   void GEOMAlgo_BuilderFace::PerformAreas()
333 {
334   myErrorStatus=0;
335   //
336   Standard_Boolean bIsGrowth, bIsHole;
337   Standard_Real aTol;
338   TopTools_ListOfShape aNewFaces, aHoleWires; 
339   TopoDS_Shape anInfinitePointShape;
340   TopTools_DataMapOfShapeShape aInOutMap;
341   TopTools_DataMapOfShapeListOfShape aMSH;
342   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItMSH;
343   TopTools_ListIteratorOfListOfShape aIt1, aIt2;
344   TopTools_IndexedMapOfShape aMHE;
345   BRep_Builder aBB;
346   Handle(Geom_Surface) aS;
347   TopLoc_Location aLoc;
348   //
349   aTol=BRep_Tool::Tolerance(myFace);
350   aS=BRep_Tool::Surface(myFace, aLoc);
351   //
352   myAreas.Clear();
353   //
354   //  Draft faces [aNewFaces]
355   aIt1.Initialize(myLoops);
356   for ( ; aIt1.More(); aIt1.Next()) {
357     const TopoDS_Shape& aWire=aIt1.Value();
358     //
359     bIsGrowth=IsGrowthWire(aWire, aMHE);
360     if (bIsGrowth) {
361       // make a growth face from a wire
362       TopoDS_Face aFace;
363       aBB.MakeFace(aFace, aS, aLoc, aTol);
364       aBB.Add (aFace, aWire);
365       //
366       aNewFaces.Append (aFace);
367     }
368     else{
369       // check if a wire is a hole 
370       //XX
371       //bIsHole=IsHole(aWire, myFace, myContext);
372       bIsHole=GEOMAlgo_BuilderTools::IsHole(aWire, myFace);
373       //XX
374       if (bIsHole) {
375         aHoleWires.Append(aWire);
376         TopExp::MapShapes(aWire, TopAbs_EDGE, aMHE);
377       }
378       else {
379         // make a growth face from a wire
380         TopoDS_Face aFace;
381         aBB.MakeFace(aFace, aS, aLoc, aTol);
382         aBB.Add (aFace, aWire);
383         //
384         aNewFaces.Append (aFace);
385       }
386     }
387   }
388   //
389   // 2. Find outer growth shell that is most close to each hole shell
390   aIt2.Initialize(aHoleWires);
391   for (; aIt2.More(); aIt2.Next()) {
392     const TopoDS_Shape& aHole = aIt2.Value();
393     //
394     aIt1.Initialize(aNewFaces);
395     for ( ; aIt1.More(); aIt1.Next()) {
396       const TopoDS_Shape& aF=aIt1.Value();
397       //
398       if (!IsInside(aHole, aF, myContext)){
399         continue;
400       }
401       //
402       if ( aInOutMap.IsBound (aHole)){
403         const TopoDS_Shape& aF2=aInOutMap(aHole);
404         if (IsInside(aF, aF2, myContext)) {
405           aInOutMap.UnBind(aHole);
406           aInOutMap.Bind (aHole, aF);
407         }
408       }
409       else{
410         aInOutMap.Bind (aHole, aF);
411       }
412     }
413     //
414     // Add aHole to a map Face/ListOfHoles [aMSH]
415     if (aInOutMap.IsBound(aHole)){
416       const TopoDS_Shape& aF=aInOutMap(aHole);
417       if (aMSH.IsBound(aF)) {
418         TopTools_ListOfShape& aLH=aMSH.ChangeFind(aF);
419         aLH.Append(aHole);
420       }
421       else {
422         TopTools_ListOfShape aLH;
423         aLH.Append(aHole);
424         aMSH.Bind(aF, aLH);
425       }
426     }
427   }// for (; aIt2.More(); aIt2.Next())
428   //
429   // 3. Add aHoles to Faces
430   aItMSH.Initialize(aMSH);
431   for (; aItMSH.More(); aItMSH.Next()) {
432     TopoDS_Face aF=TopoDS::Face(aItMSH.Key());
433     //
434     const TopTools_ListOfShape& aLH=aItMSH.Value();
435     aIt2.Initialize(aLH);
436     for (; aIt2.More(); aIt2.Next()) {
437       const TopoDS_Shape& aHole = aIt2.Value();
438       aBB.Add (aF, aHole);
439     }
440     //
441     // update classifier 
442     aTol=BRep_Tool::Tolerance(aF);
443     IntTools_FClass2d& aClsf=myContext->FClass2d(aF);
444     aClsf.Init(aF, aTol);
445   }
446   //
447   // These aNewFaces are draft faces that 
448   // do not contain any internal shapes
449   //
450   myAreas.Append(aNewFaces);
451 }
452 //=======================================================================
453 //function : PerformInternalShapes
454 //purpose  : 
455 //=======================================================================
456   void GEOMAlgo_BuilderFace::PerformInternalShapes()
457 {
458   myErrorStatus=0;
459   //
460   Standard_Integer aNbWI=myLoopsInternal.Extent();
461   if (!aNbWI) {// nothing to do
462     return;
463   }
464   // 
465   //Standard_Real aTol;
466   BRep_Builder aBB;
467   TopTools_ListIteratorOfListOfShape aIt1, aIt2;
468   TopoDS_Iterator aIt; 
469   TopTools_MapOfShape aME, aMEP;
470   TopTools_MapIteratorOfMapOfShape aItME;
471   TopTools_IndexedDataMapOfShapeListOfShape aMVE;
472   TopTools_ListOfShape aLSI;
473   //
474   // 1. All internal edges
475   aIt1.Initialize(myLoopsInternal);
476   for (; aIt1.More(); aIt1.Next()) {
477     const TopoDS_Shape& aWire=aIt1.Value();
478     aIt.Initialize(aWire);
479     for (; aIt.More(); aIt.Next()) {
480       const TopoDS_Shape& aE=aIt.Value();
481       aME.Add(aE);
482     }
483   }
484   aNbWI=aME.Extent();
485   //
486   // 2 Process faces
487   aIt2.Initialize(myAreas);
488   for ( ; aIt2.More(); aIt2.Next()) {
489     TopoDS_Face& aF=TopoDS::Face(aIt2.Value());
490     //
491     aMVE.Clear();
492     TopExp::MapShapesAndAncestors(aF, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
493     //
494     // 2.1 Separate faces to process aMEP
495     aMEP.Clear();
496     aItME.Initialize(aME);
497     for (; aItME.More(); aItME.Next()) {
498       const TopoDS_Edge& aE=TopoDS::Edge(aItME.Key());
499       if (IsInside(aE, aF, myContext)) {
500         aMEP.Add(aE);
501       }
502     }
503     //
504     // 2.2 Make Internal Wires
505     aLSI.Clear();
506     MakeInternalWires(aMEP, aLSI);
507     //
508     // 2.3 Add them to aF
509     aIt1.Initialize(aLSI);
510     for (; aIt1.More(); aIt1.Next()) {
511       const TopoDS_Shape& aSI=aIt1.Value();
512       aBB.Add (aF, aSI);
513     }
514     //
515     // 2.4 Remove faces aMFP from aMF
516     aItME.Initialize(aMEP);
517     for (; aItME.More(); aItME.Next()) {
518       const TopoDS_Shape& aE=aItME.Key();
519       aME.Remove(aE);
520     }
521     //
522     aNbWI=aME.Extent();
523     if (!aNbWI) {
524       break;
525     }
526   } //for ( ; aIt2.More(); aIt2.Next()) {
527 }
528 //=======================================================================
529 //function : MakeInternalWires
530 //purpose  : 
531 //=======================================================================
532 void MakeInternalWires(const TopTools_MapOfShape& theME,
533                        TopTools_ListOfShape& theWires)
534 {
535   TopTools_MapIteratorOfMapOfShape aItM;
536   TopTools_MapOfShape aAddedMap;
537   TopTools_ListIteratorOfListOfShape aItE;
538   TopTools_IndexedDataMapOfShapeListOfShape aMVE;
539   BRep_Builder aBB;
540   //
541   aItM.Initialize(theME);
542   for (; aItM.More(); aItM.Next()) {
543     const TopoDS_Shape& aE=aItM.Key();
544     TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
545   }
546   //
547   aItM.Initialize(theME);
548   for (; aItM.More(); aItM.Next()) {
549     TopoDS_Shape aEE=aItM.Key();
550     if (!aAddedMap.Add(aEE)) {
551       continue;
552     }
553     //
554     // make a new shell
555     TopoDS_Wire aW;
556     aBB.MakeWire(aW);    
557     aEE.Orientation(TopAbs_INTERNAL);
558     aBB.Add(aW, aEE);
559     //
560     TopoDS_Iterator aItAdded (aW);
561     for (; aItAdded.More(); aItAdded.Next()) {
562       const TopoDS_Shape& aE =aItAdded.Value();
563       //
564       TopExp_Explorer aExp(aE, TopAbs_VERTEX);
565       for (; aExp.More(); aExp.Next()) {
566         const TopoDS_Shape& aV =aExp.Current();
567         const TopTools_ListOfShape& aLE=aMVE.FindFromKey(aV);
568         aItE.Initialize(aLE);
569         for (; aItE.More(); aItE.Next()) { 
570           TopoDS_Shape aEL=aItE.Value();
571           if (aAddedMap.Add(aEL)){
572             aEL.Orientation(TopAbs_INTERNAL);
573             aBB.Add(aW, aEL);
574           }
575         }
576       }
577     }
578     theWires.Append(aW);
579   }
580 }
581
582 //=======================================================================
583 //function : IsInside
584 //purpose  : 
585 //=======================================================================
586 Standard_Boolean IsInside(const TopoDS_Shape& theHole,
587                           const TopoDS_Shape& theF2,
588                           IntTools_PContext& theContext)
589 {
590   Standard_Real aT, aU, aV;
591   TopExp_Explorer aExp;
592   TopAbs_State aState=TopAbs_UNKNOWN;
593   gp_Pnt2d aP2D;
594   //
595   const TopoDS_Face& aF2=TopoDS::Face(theF2);
596   //
597   aExp.Init(theHole, TopAbs_EDGE);
598   if (aExp.More()){
599     const TopoDS_Edge& aE = TopoDS::Edge(aExp.Current());
600     aT=BOPTools_Tools2D::IntermediatePoint(aE);
601     BOPTools_Tools2D::PointOnSurface(aE, aF2, aT, aU, aV);
602     aP2D.SetCoord(aU, aV);
603     //
604     IntTools_FClass2d& aClsf=theContext->FClass2d(aF2);
605     aState=aClsf.Perform(aP2D);
606   }
607   return (aState==TopAbs_IN);
608 }
609 //=======================================================================
610 //function : IsGrowthWire
611 //purpose  : 
612 //=======================================================================
613 Standard_Boolean IsGrowthWire(const TopoDS_Shape& theWire,
614                               const TopTools_IndexedMapOfShape& theMHE)
615 {
616   Standard_Boolean bRet;
617   TopoDS_Iterator aIt;
618   // 
619   bRet=Standard_False;
620   if (theMHE.Extent()) {
621     aIt.Initialize(theWire);
622     for(; aIt.More(); aIt.Next()) {
623       const TopoDS_Shape& aE=aIt.Value();
624       if (theMHE.Contains(aE)) {
625         return !bRet;
626       }
627     }
628   }
629   return bRet;
630 }
631 //modified by NIZNHY-PKV Mon Sep 18 13:18:27 2006f
632 /*
633 static
634    Standard_Boolean IsHole(const TopoDS_Shape& ,
635                            const TopoDS_Face& , 
636                            IntTools_PContext& );
637 */
638 //modified by NIZNHY-PKV Mon Sep 18 13:18:34 2006t
639 //modified by NIZNHY-PKV Mon Sep 18 13:18:13 2006f
640 /*
641 //=======================================================================
642 //function : IsHole
643 //purpose  : 
644 //=======================================================================
645 Standard_Boolean IsHole(const TopoDS_Shape& theS2,
646                         const TopoDS_Face& theFace,
647                         IntTools_PContext& theContext)
648 {
649   Standard_Boolean bIsHole;
650   Standard_Real aTol;
651   Handle(Geom_Surface) aS;
652   TopLoc_Location aLoc;
653   TopoDS_Face aF;
654   BRep_Builder aBB;
655   //
656   aTol=BRep_Tool::Tolerance(theFace);
657   aS=BRep_Tool::Surface(theFace, aLoc);
658   aBB.MakeFace(aF, aS, aLoc, aTol);
659   aBB.Add (aF, theS2);
660   //
661   IntTools_FClass2d& aClsf=theContext->FClass2d(aF);
662   //
663   bIsHole=aClsf.IsHole();
664   //
665   return bIsHole;
666   //
667 }
668 */
669 //modified by NIZNHY-PKV Mon Sep 18 13:18:06 2006t
670
671 //BRepTools::Write(aFF, "ff");
672 //
673 //  ErrorStatus :
674 // 11 - Null Context
675 // 12 - Null face generix
676