0024624: Lost word in license statement in source files
[occt.git] / src / BRepFeat / BRepFeat_MakeCylindricalHole.cxx
1 // Created on: 1995-05-30
2 // Created by: Jacques GOUSSARD
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <BRepFeat_MakeCylindricalHole.ixx>
18
19
20 #include <LocOpe_CurveShapeIntersector.hxx>
21 #include <LocOpe_PntFace.hxx>
22
23 #include <Bnd_Box.hxx>
24 #include <BRep_Builder.hxx>
25 #include <BRep_Tool.hxx>
26 #include <BRepPrim_Cylinder.hxx>
27 #include <TopTools_ListOfShape.hxx>
28 #include <TopTools_ListIteratorOfListOfShape.hxx>
29 #include <TopoDS_Solid.hxx>
30 #include <TopExp_Explorer.hxx>
31 #include <TopLoc_Location.hxx>
32
33 #include <Geom_Curve.hxx>
34
35 #include <ElCLib.hxx>
36 #include <BRepTools.hxx>
37 #include <TopoDS.hxx>
38 #include <Precision.hxx>
39 #include <BRepBndLib.hxx>
40
41
42
43 static void Baryc(const TopoDS_Shape&,
44                   gp_Pnt&);
45
46 static void BoxParameters(const TopoDS_Shape&,
47                           const gp_Ax1&,
48                           Standard_Real&,
49                           Standard_Real&);
50
51
52 //=======================================================================
53 //function : Perform
54 //purpose  : 
55 //=======================================================================
56
57 void BRepFeat_MakeCylindricalHole::Perform(const Standard_Real Radius)
58 {
59   if (Object().IsNull() || !myAxDef) {
60     Standard_ConstructionError::Raise();
61   }
62
63   myIsBlind = Standard_False;
64   myStatus = BRepFeat_NoError;
65
66   LocOpe_CurveShapeIntersector theASI(myAxis,Object());
67   if (!theASI.IsDone() || theASI.NbPoints() <= 0) {
68     myStatus = BRepFeat_InvalidPlacement;
69     return;
70   }
71   
72   //TopTools_ListOfShape theList;
73   //for (Standard_Integer i=1; i<= theASI.NbPoints(); i++) {
74   //  theList.Append(theASI.Point(i).Face());
75   //}
76
77   // It is not possible to use infinite cylinder for topological operations.
78   Standard_Real PMin,PMax;
79   BoxParameters(Object(),myAxis,PMin,PMax);
80   Standard_Real Heigth = 2.*(PMax-PMin);
81   gp_XYZ theOrig = myAxis.Location().XYZ();
82   theOrig += ((3.*PMin-PMax)/2.) * myAxis.Direction().XYZ();
83   gp_Pnt p1_ao1(theOrig); gp_Ax2 a1_ao1(p1_ao1,myAxis.Direction());
84   BRepPrim_Cylinder theCylinder(a1_ao1,
85                                 Radius,
86                                 Heigth);
87
88   // Probably it is better to make cut directly
89
90   BRep_Builder B;
91   TopoDS_Solid theTool;
92   B.MakeSolid(theTool);
93   B.Add(theTool,theCylinder.Shell());
94   theTool.Closed(Standard_True);
95
96   myTopFace = theCylinder.TopFace();
97   myBotFace = theCylinder.BottomFace();
98   myValidate = Standard_False;
99
100 //  BRepTools::Dump(theTool,cout);
101   Standard_Boolean Fuse = Standard_False;
102   //
103   AddTool(theTool);
104   SetOperation(Fuse);
105   BOPAlgo_Builder::Perform();
106   //myBuilder.Perform(theTool,theList,Fuse);
107 //  myBuilder.PerformResult();
108 }
109
110
111 //=======================================================================
112 //function : PerformThruNext
113 //purpose  : 
114 //=======================================================================
115
116 void BRepFeat_MakeCylindricalHole::PerformThruNext(const Standard_Real Radius,
117                                                    const Standard_Boolean Cont)
118 {
119
120   if (Object().IsNull() || !myAxDef) {
121     Standard_ConstructionError::Raise();
122   }
123
124   myIsBlind = Standard_False;
125   myValidate = Cont;
126   myStatus = BRepFeat_NoError;
127
128   LocOpe_CurveShapeIntersector theASI(myAxis,Object());
129   if (!theASI.IsDone()) {
130     myStatus = BRepFeat_InvalidPlacement;
131     return;
132   }
133   
134   Standard_Real First=0.,Last=0.;
135   Standard_Integer IndFrom,IndTo;
136   TopAbs_Orientation theOr;
137   Standard_Boolean ok = theASI.LocalizeAfter(0.,theOr,IndFrom,IndTo);
138   if (ok) {
139     if (theOr == TopAbs_FORWARD) {
140       First = theASI.Point(IndFrom).Parameter();
141       ok = theASI.LocalizeAfter(IndTo,theOr,IndFrom,IndTo);
142       if (ok) {
143         if (theOr != TopAbs_REVERSED) {
144           ok = Standard_False;
145         }
146         else {
147           Last = theASI.Point(IndTo).Parameter();
148         }
149       }
150       
151     }
152     else { // TopAbs_REVERSED
153       Last = theASI.Point(IndTo).Parameter();
154       ok = theASI.LocalizeBefore(IndFrom,theOr,IndFrom,IndTo);
155       if (ok) {
156         if (theOr != TopAbs_FORWARD) {
157           ok = Standard_False;
158         }
159         else {
160           First = theASI.Point(IndFrom).Parameter();
161         }
162       }
163     }
164   }
165   if (!ok) {
166     myStatus = BRepFeat_InvalidPlacement;
167     return;
168   }
169
170   /*TopTools_ListOfShape theList;
171   for (Standard_Integer i=1; i<= theASI.NbPoints(); i++) {
172     prm = theASI.Point(i).Parameter();
173     if (prm >= First && prm <= Last) {
174       theList.Append(theASI.Point(i).Face());
175     }
176     else if (prm > Last) {
177       break;
178     }
179   }*/
180
181   // It is not possible to use infinite cylinder for topological operations.
182   Standard_Real PMin,PMax;
183   BoxParameters(Object(),myAxis,PMin,PMax);
184   Standard_Real Heigth = 2.*(PMax-PMin);
185   gp_XYZ theOrig = myAxis.Location().XYZ();
186   theOrig += ((3.*PMin-PMax)/2.) * myAxis.Direction().XYZ();
187   gp_Pnt p2_ao1(theOrig); gp_Ax2 a2_ao1(p2_ao1,myAxis.Direction());
188   BRepPrim_Cylinder theCylinder(a2_ao1,
189                                 Radius,
190                                 Heigth);
191
192   BRep_Builder B;
193   TopoDS_Solid theTool;
194   B.MakeSolid(theTool);
195   B.Add(theTool,theCylinder.Shell());
196   theTool.Closed(Standard_True);
197
198   myTopFace = theCylinder.TopFace();
199   myBotFace = theCylinder.BottomFace();
200
201   //  BRepTools::Dump(theTool,cout);
202   Standard_Boolean Fuse = Standard_False;
203   //myBuilder.Perform(theTool,theList,Fuse);
204   //myBuilder.BuildPartsOfTool();
205   AddTool(theTool);
206   SetOperation(Fuse);
207   BOPAlgo_Builder::Perform();
208   TopTools_ListOfShape parts;
209   PartsOfTool(parts);
210
211
212   Standard_Integer nbparts = 0;
213   TopTools_ListIteratorOfListOfShape its(parts);
214   for (; its.More(); its.Next()) {
215     nbparts ++;
216   }
217   if (nbparts == 0) {
218     myStatus = BRepFeat_InvalidPlacement;
219     return;
220   }
221
222   if (nbparts >= 2) { // preserve the smallest as parameter 
223                       // along the axis
224     TopoDS_Shape tokeep;
225     Standard_Real parbar,parmin = Last;
226     gp_Pnt Barycentre;
227     for (its.Initialize(parts); its.More(); its.Next()) {
228       Baryc(its.Value(),Barycentre);
229       parbar = ElCLib::LineParameter(myAxis,Barycentre);
230       if (parbar >= First && parbar <= Last && parbar <= parmin) {
231         parmin = parbar;
232         tokeep = its.Value();
233       }
234     }
235
236     if (tokeep.IsNull()) { // preserve the closest interval
237
238       Standard_Real dmin = RealLast();
239       for (its.Initialize(parts); its.More(); its.Next()) {
240         Baryc(its.Value(),Barycentre);
241         parbar = ElCLib::LineParameter(myAxis,Barycentre);
242         if (parbar < First) {
243           if (First - parbar < dmin ) {
244             dmin = First-parbar;
245             tokeep = its.Value();
246           }
247           else { // parbar > Last
248             if (parbar - Last < dmin) {
249               dmin = parbar-Last;
250               tokeep = its.Value();
251             }
252           }
253         }
254       }
255     }
256     for (its.Initialize(parts); its.More(); its.Next()) {
257       //if (!tokeep.IsSame(its.Value())) {
258       //  myBuilder.RemovePart(its.Value());
259       //}
260       if (tokeep.IsSame(its.Value())) {
261         KeepPart(its.Value());
262         break;
263       }
264     }
265   }
266 //  myBuilder.PerformResult();
267 }
268
269 //=======================================================================
270 //function : PerformUntilEnd
271 //purpose  : 
272 //=======================================================================
273
274 void BRepFeat_MakeCylindricalHole::PerformUntilEnd(const Standard_Real Radius,
275                                                    const Standard_Boolean Cont)
276 {
277
278   if (Object().IsNull() || !myAxDef) {
279     Standard_ConstructionError::Raise();
280   }
281
282   myIsBlind = Standard_False;
283   myValidate = Cont;
284   myStatus = BRepFeat_NoError;
285
286   LocOpe_CurveShapeIntersector theASI(myAxis,Object());
287   if (!theASI.IsDone()) {
288     myStatus = BRepFeat_InvalidPlacement;
289     return;
290   }
291   
292   Standard_Real First=0,Last=0,prm;
293   Standard_Integer IndFrom,IndTo;
294   TopAbs_Orientation theOr;
295   Standard_Boolean ok = theASI.LocalizeAfter(0.,theOr,IndFrom,IndTo);
296   
297   if (ok) {
298     if (theOr == TopAbs_REVERSED) {
299       ok = theASI.LocalizeBefore(IndFrom,theOr,IndFrom,IndTo); // on reset
300       // It is possible to search for the next.
301     }
302     if ( ok && theOr == TopAbs_FORWARD) {
303       First = theASI.Point(IndFrom).Parameter();
304       ok = theASI.LocalizeBefore(theASI.NbPoints()+1,theOr,IndFrom,IndTo);
305       if (ok) {
306         if (theOr != TopAbs_REVERSED) {
307           ok = Standard_False;
308         }
309         else {
310           Last = theASI.Point(IndTo).Parameter();
311         }
312       }
313     }
314   }
315   if (!ok) {
316     myStatus = BRepFeat_InvalidPlacement;
317     return;
318   }
319
320   TopTools_ListOfShape theList;
321   for (Standard_Integer i=1; i<= theASI.NbPoints(); i++) {
322     prm = theASI.Point(i).Parameter();
323     if (prm >= First && prm <= Last) {
324       theList.Append(theASI.Point(i).Face());
325     }
326     else if (prm > Last) {
327       break;
328     }
329   }
330
331   // It is not possible to use infinite cylinder for topological operations.
332   Standard_Real PMin,PMax;
333   BoxParameters(Object(),myAxis,PMin,PMax);
334   Standard_Real Heigth = 2.*(PMax-PMin);
335   gp_XYZ theOrig = myAxis.Location().XYZ();
336   theOrig += ((3.*PMin-PMax)/2.) * myAxis.Direction().XYZ();
337   gp_Pnt p3_ao1(theOrig); gp_Ax2 a3_ao1(p3_ao1,myAxis.Direction());
338   BRepPrim_Cylinder theCylinder(a3_ao1,
339                                 Radius,
340                                 Heigth);
341
342   BRep_Builder B;
343   TopoDS_Solid theTool;
344   B.MakeSolid(theTool);
345   B.Add(theTool,theCylinder.Shell());
346   theTool.Closed(Standard_True);
347
348   myTopFace = theCylinder.TopFace();
349   myBotFace = theCylinder.BottomFace();
350
351   //  BRepTools::Dump(theTool,cout);
352   Standard_Boolean Fuse = Standard_False;
353   //myBuilder.Perform(theTool,theList,Fuse);
354   //myBuilder.BuildPartsOfTool();
355   AddTool(theTool);
356   SetOperation(Fuse);
357   BOPAlgo_Builder::Perform();
358   TopTools_ListOfShape parts;
359   PartsOfTool(parts);
360
361   Standard_Integer nbparts = 0;
362   TopTools_ListIteratorOfListOfShape its(parts);
363   for (; its.More(); its.Next()) {
364     nbparts ++;
365   }
366   if (nbparts == 0) {
367     myStatus = BRepFeat_InvalidPlacement;
368     return;
369   }
370
371   if (nbparts >= 2) { // preserve everything above the First 
372     Standard_Real parbar;
373     gp_Pnt Barycentre;
374     for (its.Initialize(parts); its.More(); its.Next()) {
375       Baryc(its.Value(),Barycentre);
376       parbar = ElCLib::LineParameter(myAxis,Barycentre);
377       if (parbar > First) {
378         KeepPart(its.Value());
379       }
380     }
381   }
382 }
383
384
385 //=======================================================================
386 //function : Perform
387 //purpose  : 
388 //=======================================================================
389
390 void BRepFeat_MakeCylindricalHole::Perform(const Standard_Real Radius,
391                                            const Standard_Real PFrom,
392                                            const Standard_Real PTo,
393                                            const Standard_Boolean Cont)
394 {
395
396   if (Object().IsNull() || !myAxDef) {
397     Standard_ConstructionError::Raise();
398   }
399
400   myIsBlind = Standard_False;
401   myValidate = Cont;
402   myStatus = BRepFeat_NoError;
403
404   LocOpe_CurveShapeIntersector theASI(myAxis,Object());
405   if (!theASI.IsDone()) {
406     myStatus = BRepFeat_InvalidPlacement;
407     return;
408   }
409
410   Standard_Real thePFrom,thePTo;
411   if (PFrom < PTo) {
412     thePFrom = PFrom;
413     thePTo   = PTo;
414   }
415   else {
416     thePFrom = PTo;
417     thePTo   = PFrom;
418   }
419
420   Standard_Real First=0,Last=0,prm;
421   Standard_Integer IndFrom,IndTo;
422   TopAbs_Orientation theOr;
423   Standard_Boolean ok = theASI.LocalizeAfter(thePFrom,theOr,IndFrom,IndTo);
424   if (ok) {
425     if (theOr == TopAbs_REVERSED) {
426       ok = theASI.LocalizeBefore(IndFrom,theOr,IndFrom,IndTo); // reset
427       // It is possible to find the next.
428     }
429     if ( ok && theOr == TopAbs_FORWARD) {
430       First = theASI.Point(IndFrom).Parameter();
431       ok = theASI.LocalizeBefore(thePTo,theOr,IndFrom,IndTo);
432       if (ok) {
433         if (theOr == TopAbs_FORWARD) {
434           ok = theASI.LocalizeAfter(IndTo,theOr,IndFrom,IndTo);
435         }
436         if (ok && theOr == TopAbs_REVERSED) {
437           Last = theASI.Point(IndTo).Parameter();
438         }
439       }
440     }
441   }
442
443   if (!ok) {
444     myStatus = BRepFeat_InvalidPlacement;
445     return;
446   }
447
448   TopTools_ListOfShape theList;
449   for (Standard_Integer i=1; i<= theASI.NbPoints(); i++) {
450     prm = theASI.Point(i).Parameter();
451     if (prm >= First && prm <= Last) {
452       theList.Append(theASI.Point(i).Face());
453     }
454     else if (prm > Last) {
455       break;
456     }
457   }
458
459   // // It is not possible to use infinite cylinder for topological operations.
460   Standard_Real PMin,PMax;
461   BoxParameters(Object(),myAxis,PMin,PMax);
462   Standard_Real Heigth = 2.*(PMax-PMin);
463   gp_XYZ theOrig = myAxis.Location().XYZ();
464   theOrig += ((3.*PMin-PMax)/2.) * myAxis.Direction().XYZ();
465
466   gp_Pnt p4_ao1(theOrig); gp_Ax2 a4_ao1(p4_ao1,myAxis.Direction());
467   BRepPrim_Cylinder theCylinder(a4_ao1,
468                                 Radius,
469                                 Heigth);
470
471   BRep_Builder B;
472   TopoDS_Solid theTool;
473   B.MakeSolid(theTool);
474   B.Add(theTool,theCylinder.Shell());
475   theTool.Closed(Standard_True);
476
477   myTopFace = theCylinder.TopFace();
478   myBotFace = theCylinder.BottomFace();
479
480   //  BRepTools::Dump(theTool,cout);
481   Standard_Boolean Fuse = Standard_False;
482   //myBuilder.Perform(theTool,theList,Fuse);
483   //myBuilder.BuildPartsOfTool();
484   AddTool(theTool);
485   SetOperation(Fuse);
486   BOPAlgo_Builder::Perform();
487   TopTools_ListOfShape parts;
488   PartsOfTool(parts);
489
490   Standard_Integer nbparts = 0;
491   TopTools_ListIteratorOfListOfShape its(parts);
492   for (; its.More(); its.Next()) {
493     nbparts ++;
494   }
495   if (nbparts == 0) {
496     myStatus = BRepFeat_InvalidPlacement;
497     return;
498   }
499
500   if (nbparts >= 2) { // preserve parts between First and Last
501
502     TopoDS_Shape tokeep;
503     Standard_Real parbar;
504     gp_Pnt Barycentre;
505     for (its.Initialize(parts); its.More(); its.Next()) {
506       Baryc(its.Value(),Barycentre);
507       parbar = ElCLib::LineParameter(myAxis,Barycentre);
508       if (!(parbar < First || parbar > Last)) {
509         KeepPart(its.Value());
510       }
511     }
512   }
513 }
514
515
516 //=======================================================================
517 //function : PerformBlind
518 //purpose  : 
519 //=======================================================================
520
521 void BRepFeat_MakeCylindricalHole::PerformBlind(const Standard_Real Radius,
522                                                 const Standard_Real Length,
523                                                 const Standard_Boolean Cont)
524 {
525
526   if (Object().IsNull() || !myAxDef || Length <= 0.) {
527     Standard_ConstructionError::Raise();
528   }
529
530   myIsBlind = Standard_True;
531   myValidate = Cont;
532   myStatus = BRepFeat_NoError;
533
534   LocOpe_CurveShapeIntersector theASI(myAxis,Object());
535   if (!theASI.IsDone()) {
536     myStatus = BRepFeat_InvalidPlacement;
537     return;
538   }
539   
540 //  Standard_Real First,prm;
541   Standard_Real First;
542   Standard_Integer IndFrom,IndTo;
543   TopAbs_Orientation theOr;
544   Standard_Boolean ok = theASI.LocalizeAfter(0.,theOr,IndFrom,IndTo);
545   
546   if (ok) {
547     if (theOr == TopAbs_REVERSED) {
548       ok = theASI.LocalizeBefore(IndFrom,theOr,IndFrom,IndTo); // reset
549       // it is possible to find the next
550     }
551     ok = ok && theOr == TopAbs_FORWARD;
552   }
553   if (!ok) {
554     myStatus = BRepFeat_InvalidPlacement;
555     return;
556   }
557
558   // check a priori the length of the hole
559   Standard_Integer IFNext,ITNext;
560   ok = theASI.LocalizeAfter(IndTo,theOr,IFNext,ITNext);
561   if (!ok) {
562     myStatus = BRepFeat_InvalidPlacement;
563     return;
564   }
565   if (theASI.Point(IFNext).Parameter() <= Length) {
566     myStatus = BRepFeat_HoleTooLong;
567     return;
568   }
569
570   TopTools_ListOfShape theList;
571 /*
572   for (Standard_Integer i=IndFrom; i<= IndTo; i++) {
573     theList.Append(theASI.Point(i).Face());
574   }
575 */
576   // version for advanced control
577   for (Standard_Integer i=IndFrom; i<= ITNext; i++) {
578     theList.Append(theASI.Point(i).Face());
579   }
580
581   First = theASI.Point(IndFrom).Parameter();
582
583   //// It is not possible to use infinite cylinder for topological operations.
584   Standard_Real PMin,PMax;
585   BoxParameters(Object(),myAxis,PMin,PMax);
586   if (PMin > Length) {
587     myStatus = BRepFeat_InvalidPlacement;
588     return;
589   }
590
591   Standard_Real Heigth = 3.*(Length-PMin)/2.;
592   gp_XYZ theOrig = myAxis.Location().XYZ();
593   theOrig += ((3.*PMin-Length)/2.) * myAxis.Direction().XYZ();
594   gp_Pnt p5_ao1(theOrig); gp_Ax2 a5_ao1(p5_ao1,myAxis.Direction());
595   BRepPrim_Cylinder theCylinder(a5_ao1,
596                                 Radius,
597                                 Heigth);
598
599   BRep_Builder B;
600   TopoDS_Solid theTool;
601   B.MakeSolid(theTool);
602   B.Add(theTool,theCylinder.Shell());
603   theTool.Closed(Standard_True);
604
605   myTopFace = theCylinder.TopFace();
606   myBotFace.Nullify();
607
608   //  BRepTools::Dump(theTool,cout);
609   Standard_Boolean Fuse = Standard_False;
610   //myBuilder.Perform(theTool,theList,Fuse);
611   //myBuilder.BuildPartsOfTool();
612   AddTool(theTool);
613   SetOperation(Fuse);
614   BOPAlgo_Builder::Perform();
615   TopTools_ListOfShape parts;
616   PartsOfTool(parts);
617
618   Standard_Integer nbparts = 0;
619   TopTools_ListIteratorOfListOfShape its(parts);
620   for (; its.More(); its.Next()) {
621     nbparts ++;
622   }
623   if (nbparts == 0) {
624     myStatus = BRepFeat_InvalidPlacement;
625     return;
626   }
627
628   if (nbparts >= 2) { // preserve the smallest as parameter along the axis
629     TopoDS_Shape tokeep;
630     Standard_Real parbar,parmin = RealLast();
631     gp_Pnt Barycentre;
632     for (its.Initialize(parts); its.More(); its.Next()) {
633       Baryc(its.Value(),Barycentre);
634       parbar = ElCLib::LineParameter(myAxis,Barycentre);
635       if (parbar >= First && parbar <= parmin) {
636         parmin = parbar;
637         tokeep = its.Value();
638       }
639     }
640
641     if (tokeep.IsNull()) { // preserve the closest interval
642
643       Standard_Real dmin = RealLast();
644       for (its.Initialize(parts); its.More(); its.Next()) {
645         Baryc(its.Value(),Barycentre);
646         parbar = ElCLib::LineParameter(myAxis,Barycentre);
647         if (Abs(First - parbar) < dmin ) {
648           dmin = Abs(First-parbar);
649           tokeep = its.Value();
650         }
651       }
652     }
653     for (its.Initialize(parts); its.More(); its.Next()) {
654       if (tokeep.IsSame(its.Value())) {
655         KeepPart(its.Value());
656         break;
657       }
658     }
659   }
660 }
661
662 //=======================================================================
663 //function : Build
664 //purpose  : 
665 //=======================================================================
666
667 void BRepFeat_MakeCylindricalHole::Build ()
668 {
669   if (myStatus == BRepFeat_NoError) {
670     PerformResult();
671     if (!ErrorStatus()) {
672       myStatus = (myValidate) ? Validate() : BRepFeat_NoError;
673       if (myStatus == BRepFeat_NoError) {
674         myShape = Shape();
675       }
676     }
677     else {
678       myStatus = BRepFeat_InvalidPlacement; // why not
679     }
680   }
681 }
682
683
684 //=======================================================================
685 //function : Validate
686 //purpose  : 
687 //=======================================================================
688
689 BRepFeat_Status BRepFeat_MakeCylindricalHole::Validate ()
690 {
691   BRepFeat_Status thestat = BRepFeat_NoError;
692   TopExp_Explorer ex(Shape(),TopAbs_FACE);
693   if (myIsBlind) { // limit of the hole
694     for (; ex.More(); ex.Next()) {
695       if (ex.Current().IsSame(myTopFace) ) {
696         break;
697       }
698     }
699     if (!ex.More()) {
700       thestat = BRepFeat_HoleTooLong;
701     }
702   }
703   else {
704     for (; ex.More(); ex.Next()) {
705       if (ex.Current().IsSame(myTopFace) ) {
706         return BRepFeat_InvalidPlacement;
707       }
708     }
709     for (ex.ReInit(); ex.More(); ex.Next()) {
710       if (ex.Current().IsSame(myBotFace) ) {
711         return BRepFeat_InvalidPlacement;
712       }
713     }
714   }
715   return thestat;
716 }
717
718
719
720 void Baryc(const TopoDS_Shape& S, gp_Pnt& B)
721 {
722   TopExp_Explorer exp(S,TopAbs_EDGE);
723   gp_XYZ Bar(0.,0.,0.);
724   TopLoc_Location L;
725   Handle(Geom_Curve) C;
726   Standard_Real prm,First,Last;
727
728   Standard_Integer i, nbp= 0;
729   for (; exp.More(); exp.Next()) {
730     // Calculate points by non-degenerated edges
731     const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
732     if (!BRep_Tool::Degenerated(E)) {
733       C = BRep_Tool::Curve(E,L,First,Last);
734       C = Handle(Geom_Curve)::DownCast(C->Transformed(L.Transformation()));
735       for (i=1;i<=11; i++) {
736         prm = ((11-i)*First + (i-1)*Last)/10.;
737         Bar += C->Value(prm).XYZ();
738         nbp++;
739       }
740     }
741   }
742   Bar.Divide((Standard_Real)nbp);
743   B.SetXYZ(Bar);
744 }
745
746
747 void BoxParameters(const TopoDS_Shape& S,
748                    const gp_Ax1& Axis,
749                    Standard_Real& parmin,
750                    Standard_Real& parmax)
751 {
752
753   // calculate the parameters of a bounding box in the direction of the axis of the hole
754   Bnd_Box B;
755   BRepBndLib::Add(S,B);
756   Standard_Real c[6];
757   B.Get(c[0],c[2],c[4],c[1],c[3],c[5]);
758   gp_Pnt P;
759   Standard_Integer i,j,k;
760   parmin = RealLast();
761   parmax = RealFirst();
762   Standard_Real param;
763   for (i=0; i<=1; i++) {
764     P.SetX(c[i]);
765     for (j=2; j<=3; j++) {
766       P.SetY(c[j]);
767       for (k=4; k<=5; k++) {
768         P.SetZ(c[k]);
769         param = ElCLib::LineParameter(Axis,P);
770         parmin = Min(param,parmin);
771         parmax = Max(param,parmax);
772       }
773     }
774   }
775 }