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