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