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