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
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.
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.
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.
23 #include <BRepFeat_MakeCylindricalHole.ixx>
26 #include <LocOpe_CurveShapeIntersector.hxx>
27 #include <LocOpe_PntFace.hxx>
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>
39 #include <Geom_Curve.hxx>
42 #include <BRepTools.hxx>
44 #include <Precision.hxx>
45 #include <BRepBndLib.hxx>
49 static void Baryc(const TopoDS_Shape&,
52 static void BoxParameters(const TopoDS_Shape&,
58 //=======================================================================
61 //=======================================================================
63 void BRepFeat_MakeCylindricalHole::Perform(const Standard_Real Radius)
65 if (Object().IsNull() || !myAxDef) {
66 Standard_ConstructionError::Raise();
69 myIsBlind = Standard_False;
70 myStatus = BRepFeat_NoError;
72 LocOpe_CurveShapeIntersector theASI(myAxis,Object());
73 if (!theASI.IsDone() || theASI.NbPoints() <= 0) {
74 myStatus = BRepFeat_InvalidPlacement;
78 //TopTools_ListOfShape theList;
79 //for (Standard_Integer i=1; i<= theASI.NbPoints(); i++) {
80 // theList.Append(theASI.Point(i).Face());
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,
94 // Probably it is better to make cut directly
99 B.Add(theTool,theCylinder.Shell());
100 theTool.Closed(Standard_True);
102 myTopFace = theCylinder.TopFace();
103 myBotFace = theCylinder.BottomFace();
104 myValidate = Standard_False;
106 // BRepTools::Dump(theTool,cout);
107 Standard_Boolean Fuse = Standard_False;
111 BOPAlgo_Builder::Perform();
112 //myBuilder.Perform(theTool,theList,Fuse);
113 // myBuilder.PerformResult();
117 //=======================================================================
118 //function : PerformThruNext
120 //=======================================================================
122 void BRepFeat_MakeCylindricalHole::PerformThruNext(const Standard_Real Radius,
123 const Standard_Boolean Cont)
126 if (Object().IsNull() || !myAxDef) {
127 Standard_ConstructionError::Raise();
130 myIsBlind = Standard_False;
132 myStatus = BRepFeat_NoError;
134 LocOpe_CurveShapeIntersector theASI(myAxis,Object());
135 if (!theASI.IsDone()) {
136 myStatus = BRepFeat_InvalidPlacement;
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);
145 if (theOr == TopAbs_FORWARD) {
146 First = theASI.Point(IndFrom).Parameter();
147 ok = theASI.LocalizeAfter(IndTo,theOr,IndFrom,IndTo);
149 if (theOr != TopAbs_REVERSED) {
153 Last = theASI.Point(IndTo).Parameter();
158 else { // TopAbs_REVERSED
159 Last = theASI.Point(IndTo).Parameter();
160 ok = theASI.LocalizeBefore(IndFrom,theOr,IndFrom,IndTo);
162 if (theOr != TopAbs_FORWARD) {
166 First = theASI.Point(IndFrom).Parameter();
172 myStatus = BRepFeat_InvalidPlacement;
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());
182 else if (prm > Last) {
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,
199 TopoDS_Solid theTool;
200 B.MakeSolid(theTool);
201 B.Add(theTool,theCylinder.Shell());
202 theTool.Closed(Standard_True);
204 myTopFace = theCylinder.TopFace();
205 myBotFace = theCylinder.BottomFace();
207 // BRepTools::Dump(theTool,cout);
208 Standard_Boolean Fuse = Standard_False;
209 //myBuilder.Perform(theTool,theList,Fuse);
210 //myBuilder.BuildPartsOfTool();
213 BOPAlgo_Builder::Perform();
214 TopTools_ListOfShape parts;
218 Standard_Integer nbparts = 0;
219 TopTools_ListIteratorOfListOfShape its(parts);
220 for (; its.More(); its.Next()) {
224 myStatus = BRepFeat_InvalidPlacement;
228 if (nbparts >= 2) { // preserve the smallest as parameter
231 Standard_Real parbar,parmin = Last;
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) {
238 tokeep = its.Value();
242 if (tokeep.IsNull()) { // preserve the closest interval
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 ) {
251 tokeep = its.Value();
253 else { // parbar > Last
254 if (parbar - Last < dmin) {
256 tokeep = its.Value();
262 for (its.Initialize(parts); its.More(); its.Next()) {
263 //if (!tokeep.IsSame(its.Value())) {
264 // myBuilder.RemovePart(its.Value());
266 if (tokeep.IsSame(its.Value())) {
267 KeepPart(its.Value());
272 // myBuilder.PerformResult();
275 //=======================================================================
276 //function : PerformUntilEnd
278 //=======================================================================
280 void BRepFeat_MakeCylindricalHole::PerformUntilEnd(const Standard_Real Radius,
281 const Standard_Boolean Cont)
284 if (Object().IsNull() || !myAxDef) {
285 Standard_ConstructionError::Raise();
288 myIsBlind = Standard_False;
290 myStatus = BRepFeat_NoError;
292 LocOpe_CurveShapeIntersector theASI(myAxis,Object());
293 if (!theASI.IsDone()) {
294 myStatus = BRepFeat_InvalidPlacement;
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);
304 if (theOr == TopAbs_REVERSED) {
305 ok = theASI.LocalizeBefore(IndFrom,theOr,IndFrom,IndTo); // on reset
306 // It is possible to search for the next.
308 if ( ok && theOr == TopAbs_FORWARD) {
309 First = theASI.Point(IndFrom).Parameter();
310 ok = theASI.LocalizeBefore(theASI.NbPoints()+1,theOr,IndFrom,IndTo);
312 if (theOr != TopAbs_REVERSED) {
316 Last = theASI.Point(IndTo).Parameter();
322 myStatus = BRepFeat_InvalidPlacement;
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());
332 else if (prm > Last) {
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,
349 TopoDS_Solid theTool;
350 B.MakeSolid(theTool);
351 B.Add(theTool,theCylinder.Shell());
352 theTool.Closed(Standard_True);
354 myTopFace = theCylinder.TopFace();
355 myBotFace = theCylinder.BottomFace();
357 // BRepTools::Dump(theTool,cout);
358 Standard_Boolean Fuse = Standard_False;
359 //myBuilder.Perform(theTool,theList,Fuse);
360 //myBuilder.BuildPartsOfTool();
363 BOPAlgo_Builder::Perform();
364 TopTools_ListOfShape parts;
367 Standard_Integer nbparts = 0;
368 TopTools_ListIteratorOfListOfShape its(parts);
369 for (; its.More(); its.Next()) {
373 myStatus = BRepFeat_InvalidPlacement;
377 if (nbparts >= 2) { // preserve everything above the First
378 Standard_Real parbar;
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());
391 //=======================================================================
394 //=======================================================================
396 void BRepFeat_MakeCylindricalHole::Perform(const Standard_Real Radius,
397 const Standard_Real PFrom,
398 const Standard_Real PTo,
399 const Standard_Boolean Cont)
402 if (Object().IsNull() || !myAxDef) {
403 Standard_ConstructionError::Raise();
406 myIsBlind = Standard_False;
408 myStatus = BRepFeat_NoError;
410 LocOpe_CurveShapeIntersector theASI(myAxis,Object());
411 if (!theASI.IsDone()) {
412 myStatus = BRepFeat_InvalidPlacement;
416 Standard_Real thePFrom,thePTo;
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);
431 if (theOr == TopAbs_REVERSED) {
432 ok = theASI.LocalizeBefore(IndFrom,theOr,IndFrom,IndTo); // reset
433 // It is possible to find the next.
435 if ( ok && theOr == TopAbs_FORWARD) {
436 First = theASI.Point(IndFrom).Parameter();
437 ok = theASI.LocalizeBefore(thePTo,theOr,IndFrom,IndTo);
439 if (theOr == TopAbs_FORWARD) {
440 ok = theASI.LocalizeAfter(IndTo,theOr,IndFrom,IndTo);
442 if (ok && theOr == TopAbs_REVERSED) {
443 Last = theASI.Point(IndTo).Parameter();
450 myStatus = BRepFeat_InvalidPlacement;
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());
460 else if (prm > Last) {
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();
472 gp_Pnt p4_ao1(theOrig); gp_Ax2 a4_ao1(p4_ao1,myAxis.Direction());
473 BRepPrim_Cylinder theCylinder(a4_ao1,
478 TopoDS_Solid theTool;
479 B.MakeSolid(theTool);
480 B.Add(theTool,theCylinder.Shell());
481 theTool.Closed(Standard_True);
483 myTopFace = theCylinder.TopFace();
484 myBotFace = theCylinder.BottomFace();
486 // BRepTools::Dump(theTool,cout);
487 Standard_Boolean Fuse = Standard_False;
488 //myBuilder.Perform(theTool,theList,Fuse);
489 //myBuilder.BuildPartsOfTool();
492 BOPAlgo_Builder::Perform();
493 TopTools_ListOfShape parts;
496 Standard_Integer nbparts = 0;
497 TopTools_ListIteratorOfListOfShape its(parts);
498 for (; its.More(); its.Next()) {
502 myStatus = BRepFeat_InvalidPlacement;
506 if (nbparts >= 2) { // preserve parts between First and Last
509 Standard_Real parbar;
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());
522 //=======================================================================
523 //function : PerformBlind
525 //=======================================================================
527 void BRepFeat_MakeCylindricalHole::PerformBlind(const Standard_Real Radius,
528 const Standard_Real Length,
529 const Standard_Boolean Cont)
532 if (Object().IsNull() || !myAxDef || Length <= 0.) {
533 Standard_ConstructionError::Raise();
536 myIsBlind = Standard_True;
538 myStatus = BRepFeat_NoError;
540 LocOpe_CurveShapeIntersector theASI(myAxis,Object());
541 if (!theASI.IsDone()) {
542 myStatus = BRepFeat_InvalidPlacement;
546 // Standard_Real First,prm;
548 Standard_Integer IndFrom,IndTo;
549 TopAbs_Orientation theOr;
550 Standard_Boolean ok = theASI.LocalizeAfter(0.,theOr,IndFrom,IndTo);
553 if (theOr == TopAbs_REVERSED) {
554 ok = theASI.LocalizeBefore(IndFrom,theOr,IndFrom,IndTo); // reset
555 // it is possible to find the next
557 ok = ok && theOr == TopAbs_FORWARD;
560 myStatus = BRepFeat_InvalidPlacement;
564 // check a priori the length of the hole
565 Standard_Integer IFNext,ITNext;
566 ok = theASI.LocalizeAfter(IndTo,theOr,IFNext,ITNext);
568 myStatus = BRepFeat_InvalidPlacement;
571 if (theASI.Point(IFNext).Parameter() <= Length) {
572 myStatus = BRepFeat_HoleTooLong;
576 TopTools_ListOfShape theList;
578 for (Standard_Integer i=IndFrom; i<= IndTo; i++) {
579 theList.Append(theASI.Point(i).Face());
582 // version for advanced control
583 for (Standard_Integer i=IndFrom; i<= ITNext; i++) {
584 theList.Append(theASI.Point(i).Face());
587 First = theASI.Point(IndFrom).Parameter();
589 //// It is not possible to use infinite cylinder for topological operations.
590 Standard_Real PMin,PMax;
591 BoxParameters(Object(),myAxis,PMin,PMax);
593 myStatus = BRepFeat_InvalidPlacement;
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,
606 TopoDS_Solid theTool;
607 B.MakeSolid(theTool);
608 B.Add(theTool,theCylinder.Shell());
609 theTool.Closed(Standard_True);
611 myTopFace = theCylinder.TopFace();
614 // BRepTools::Dump(theTool,cout);
615 Standard_Boolean Fuse = Standard_False;
616 //myBuilder.Perform(theTool,theList,Fuse);
617 //myBuilder.BuildPartsOfTool();
620 BOPAlgo_Builder::Perform();
621 TopTools_ListOfShape parts;
624 Standard_Integer nbparts = 0;
625 TopTools_ListIteratorOfListOfShape its(parts);
626 for (; its.More(); its.Next()) {
630 myStatus = BRepFeat_InvalidPlacement;
634 if (nbparts >= 2) { // preserve the smallest as parameter along the axis
636 Standard_Real parbar,parmin = RealLast();
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) {
643 tokeep = its.Value();
647 if (tokeep.IsNull()) { // preserve the closest interval
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();
659 for (its.Initialize(parts); its.More(); its.Next()) {
660 if (tokeep.IsSame(its.Value())) {
661 KeepPart(its.Value());
668 //=======================================================================
671 //=======================================================================
673 void BRepFeat_MakeCylindricalHole::Build ()
675 if (myStatus == BRepFeat_NoError) {
677 if (!ErrorStatus()) {
678 myStatus = (myValidate) ? Validate() : BRepFeat_NoError;
679 if (myStatus == BRepFeat_NoError) {
684 myStatus = BRepFeat_InvalidPlacement; // why not
690 //=======================================================================
691 //function : Validate
693 //=======================================================================
695 BRepFeat_Status BRepFeat_MakeCylindricalHole::Validate ()
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) ) {
706 thestat = BRepFeat_HoleTooLong;
710 for (; ex.More(); ex.Next()) {
711 if (ex.Current().IsSame(myTopFace) ) {
712 return BRepFeat_InvalidPlacement;
715 for (ex.ReInit(); ex.More(); ex.Next()) {
716 if (ex.Current().IsSame(myBotFace) ) {
717 return BRepFeat_InvalidPlacement;
726 void Baryc(const TopoDS_Shape& S, gp_Pnt& B)
728 TopExp_Explorer exp(S,TopAbs_EDGE);
729 gp_XYZ Bar(0.,0.,0.);
731 Handle(Geom_Curve) C;
732 Standard_Real prm,First,Last;
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();
748 Bar.Divide((Standard_Real)nbp);
753 void BoxParameters(const TopoDS_Shape& S,
755 Standard_Real& parmin,
756 Standard_Real& parmax)
759 // calculate the parameters of a bounding box in the direction of the axis of the hole
761 BRepBndLib::Add(S,B);
763 B.Get(c[0],c[2],c[4],c[1],c[3],c[5]);
765 Standard_Integer i,j,k;
767 parmax = RealFirst();
769 for (i=0; i<=1; i++) {
771 for (j=2; j<=3; j++) {
773 for (k=4; k<=5; k++) {
775 param = ElCLib::LineParameter(Axis,P);
776 parmin = Min(param,parmin);
777 parmax = Max(param,parmax);