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
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #include <BRepFeat_MakeCylindricalHole.ixx>
20 #include <LocOpe_CurveShapeIntersector.hxx>
21 #include <LocOpe_PntFace.hxx>
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>
33 #include <Geom_Curve.hxx>
36 #include <BRepTools.hxx>
38 #include <Precision.hxx>
39 #include <BRepBndLib.hxx>
43 static void Baryc(const TopoDS_Shape&,
46 static void BoxParameters(const TopoDS_Shape&,
52 //=======================================================================
55 //=======================================================================
57 void BRepFeat_MakeCylindricalHole::Perform(const Standard_Real Radius)
59 if (Object().IsNull() || !myAxDef) {
60 Standard_ConstructionError::Raise();
63 myIsBlind = Standard_False;
64 myStatus = BRepFeat_NoError;
66 LocOpe_CurveShapeIntersector theASI(myAxis,Object());
67 if (!theASI.IsDone() || theASI.NbPoints() <= 0) {
68 myStatus = BRepFeat_InvalidPlacement;
72 //TopTools_ListOfShape theList;
73 //for (Standard_Integer i=1; i<= theASI.NbPoints(); i++) {
74 // theList.Append(theASI.Point(i).Face());
77 // It is not possible to use infinite cylinder for topological operations.
78 Standard_Real PMin,PMax;
79 BoxParameters(Object(),myAxis,PMin,PMax);
80 Standard_Real Heigth = 2.*(PMax-PMin);
81 gp_XYZ theOrig = myAxis.Location().XYZ();
82 theOrig += ((3.*PMin-PMax)/2.) * myAxis.Direction().XYZ();
83 gp_Pnt p1_ao1(theOrig); gp_Ax2 a1_ao1(p1_ao1,myAxis.Direction());
84 BRepPrim_Cylinder theCylinder(a1_ao1,
88 // Probably it is better to make cut directly
93 B.Add(theTool,theCylinder.Shell());
94 theTool.Closed(Standard_True);
96 myTopFace = theCylinder.TopFace();
97 myBotFace = theCylinder.BottomFace();
98 myValidate = Standard_False;
100 // BRepTools::Dump(theTool,cout);
101 Standard_Boolean Fuse = Standard_False;
105 BOPAlgo_Builder::Perform();
106 //myBuilder.Perform(theTool,theList,Fuse);
107 // myBuilder.PerformResult();
111 //=======================================================================
112 //function : PerformThruNext
114 //=======================================================================
116 void BRepFeat_MakeCylindricalHole::PerformThruNext(const Standard_Real Radius,
117 const Standard_Boolean Cont)
120 if (Object().IsNull() || !myAxDef) {
121 Standard_ConstructionError::Raise();
124 myIsBlind = Standard_False;
126 myStatus = BRepFeat_NoError;
128 LocOpe_CurveShapeIntersector theASI(myAxis,Object());
129 if (!theASI.IsDone()) {
130 myStatus = BRepFeat_InvalidPlacement;
134 Standard_Real First=0.,Last=0.;
135 Standard_Integer IndFrom,IndTo;
136 TopAbs_Orientation theOr;
137 Standard_Boolean ok = theASI.LocalizeAfter(0.,theOr,IndFrom,IndTo);
139 if (theOr == TopAbs_FORWARD) {
140 First = theASI.Point(IndFrom).Parameter();
141 ok = theASI.LocalizeAfter(IndTo,theOr,IndFrom,IndTo);
143 if (theOr != TopAbs_REVERSED) {
147 Last = theASI.Point(IndTo).Parameter();
152 else { // TopAbs_REVERSED
153 Last = theASI.Point(IndTo).Parameter();
154 ok = theASI.LocalizeBefore(IndFrom,theOr,IndFrom,IndTo);
156 if (theOr != TopAbs_FORWARD) {
160 First = theASI.Point(IndFrom).Parameter();
166 myStatus = BRepFeat_InvalidPlacement;
170 /*TopTools_ListOfShape theList;
171 for (Standard_Integer i=1; i<= theASI.NbPoints(); i++) {
172 prm = theASI.Point(i).Parameter();
173 if (prm >= First && prm <= Last) {
174 theList.Append(theASI.Point(i).Face());
176 else if (prm > Last) {
181 // It is not possible to use infinite cylinder for topological operations.
182 Standard_Real PMin,PMax;
183 BoxParameters(Object(),myAxis,PMin,PMax);
184 Standard_Real Heigth = 2.*(PMax-PMin);
185 gp_XYZ theOrig = myAxis.Location().XYZ();
186 theOrig += ((3.*PMin-PMax)/2.) * myAxis.Direction().XYZ();
187 gp_Pnt p2_ao1(theOrig); gp_Ax2 a2_ao1(p2_ao1,myAxis.Direction());
188 BRepPrim_Cylinder theCylinder(a2_ao1,
193 TopoDS_Solid theTool;
194 B.MakeSolid(theTool);
195 B.Add(theTool,theCylinder.Shell());
196 theTool.Closed(Standard_True);
198 myTopFace = theCylinder.TopFace();
199 myBotFace = theCylinder.BottomFace();
201 // BRepTools::Dump(theTool,cout);
202 Standard_Boolean Fuse = Standard_False;
203 //myBuilder.Perform(theTool,theList,Fuse);
204 //myBuilder.BuildPartsOfTool();
207 BOPAlgo_Builder::Perform();
208 TopTools_ListOfShape parts;
212 Standard_Integer nbparts = 0;
213 TopTools_ListIteratorOfListOfShape its(parts);
214 for (; its.More(); its.Next()) {
218 myStatus = BRepFeat_InvalidPlacement;
222 if (nbparts >= 2) { // preserve the smallest as parameter
225 Standard_Real parbar,parmin = Last;
227 for (its.Initialize(parts); its.More(); its.Next()) {
228 Baryc(its.Value(),Barycentre);
229 parbar = ElCLib::LineParameter(myAxis,Barycentre);
230 if (parbar >= First && parbar <= Last && parbar <= parmin) {
232 tokeep = its.Value();
236 if (tokeep.IsNull()) { // preserve the closest interval
238 Standard_Real dmin = RealLast();
239 for (its.Initialize(parts); its.More(); its.Next()) {
240 Baryc(its.Value(),Barycentre);
241 parbar = ElCLib::LineParameter(myAxis,Barycentre);
242 if (parbar < First) {
243 if (First - parbar < dmin ) {
245 tokeep = its.Value();
247 else { // parbar > Last
248 if (parbar - Last < dmin) {
250 tokeep = its.Value();
256 for (its.Initialize(parts); its.More(); its.Next()) {
257 //if (!tokeep.IsSame(its.Value())) {
258 // myBuilder.RemovePart(its.Value());
260 if (tokeep.IsSame(its.Value())) {
261 KeepPart(its.Value());
266 // myBuilder.PerformResult();
269 //=======================================================================
270 //function : PerformUntilEnd
272 //=======================================================================
274 void BRepFeat_MakeCylindricalHole::PerformUntilEnd(const Standard_Real Radius,
275 const Standard_Boolean Cont)
278 if (Object().IsNull() || !myAxDef) {
279 Standard_ConstructionError::Raise();
282 myIsBlind = Standard_False;
284 myStatus = BRepFeat_NoError;
286 LocOpe_CurveShapeIntersector theASI(myAxis,Object());
287 if (!theASI.IsDone()) {
288 myStatus = BRepFeat_InvalidPlacement;
292 Standard_Real First=0,Last=0,prm;
293 Standard_Integer IndFrom,IndTo;
294 TopAbs_Orientation theOr;
295 Standard_Boolean ok = theASI.LocalizeAfter(0.,theOr,IndFrom,IndTo);
298 if (theOr == TopAbs_REVERSED) {
299 ok = theASI.LocalizeBefore(IndFrom,theOr,IndFrom,IndTo); // on reset
300 // It is possible to search for the next.
302 if ( ok && theOr == TopAbs_FORWARD) {
303 First = theASI.Point(IndFrom).Parameter();
304 ok = theASI.LocalizeBefore(theASI.NbPoints()+1,theOr,IndFrom,IndTo);
306 if (theOr != TopAbs_REVERSED) {
310 Last = theASI.Point(IndTo).Parameter();
316 myStatus = BRepFeat_InvalidPlacement;
320 TopTools_ListOfShape theList;
321 for (Standard_Integer i=1; i<= theASI.NbPoints(); i++) {
322 prm = theASI.Point(i).Parameter();
323 if (prm >= First && prm <= Last) {
324 theList.Append(theASI.Point(i).Face());
326 else if (prm > Last) {
331 // It is not possible to use infinite cylinder for topological operations.
332 Standard_Real PMin,PMax;
333 BoxParameters(Object(),myAxis,PMin,PMax);
334 Standard_Real Heigth = 2.*(PMax-PMin);
335 gp_XYZ theOrig = myAxis.Location().XYZ();
336 theOrig += ((3.*PMin-PMax)/2.) * myAxis.Direction().XYZ();
337 gp_Pnt p3_ao1(theOrig); gp_Ax2 a3_ao1(p3_ao1,myAxis.Direction());
338 BRepPrim_Cylinder theCylinder(a3_ao1,
343 TopoDS_Solid theTool;
344 B.MakeSolid(theTool);
345 B.Add(theTool,theCylinder.Shell());
346 theTool.Closed(Standard_True);
348 myTopFace = theCylinder.TopFace();
349 myBotFace = theCylinder.BottomFace();
351 // BRepTools::Dump(theTool,cout);
352 Standard_Boolean Fuse = Standard_False;
353 //myBuilder.Perform(theTool,theList,Fuse);
354 //myBuilder.BuildPartsOfTool();
357 BOPAlgo_Builder::Perform();
358 TopTools_ListOfShape parts;
361 Standard_Integer nbparts = 0;
362 TopTools_ListIteratorOfListOfShape its(parts);
363 for (; its.More(); its.Next()) {
367 myStatus = BRepFeat_InvalidPlacement;
371 if (nbparts >= 2) { // preserve everything above the First
372 Standard_Real parbar;
374 for (its.Initialize(parts); its.More(); its.Next()) {
375 Baryc(its.Value(),Barycentre);
376 parbar = ElCLib::LineParameter(myAxis,Barycentre);
377 if (parbar > First) {
378 KeepPart(its.Value());
385 //=======================================================================
388 //=======================================================================
390 void BRepFeat_MakeCylindricalHole::Perform(const Standard_Real Radius,
391 const Standard_Real PFrom,
392 const Standard_Real PTo,
393 const Standard_Boolean Cont)
396 if (Object().IsNull() || !myAxDef) {
397 Standard_ConstructionError::Raise();
400 myIsBlind = Standard_False;
402 myStatus = BRepFeat_NoError;
404 LocOpe_CurveShapeIntersector theASI(myAxis,Object());
405 if (!theASI.IsDone()) {
406 myStatus = BRepFeat_InvalidPlacement;
410 Standard_Real thePFrom,thePTo;
420 Standard_Real First=0,Last=0,prm;
421 Standard_Integer IndFrom,IndTo;
422 TopAbs_Orientation theOr;
423 Standard_Boolean ok = theASI.LocalizeAfter(thePFrom,theOr,IndFrom,IndTo);
425 if (theOr == TopAbs_REVERSED) {
426 ok = theASI.LocalizeBefore(IndFrom,theOr,IndFrom,IndTo); // reset
427 // It is possible to find the next.
429 if ( ok && theOr == TopAbs_FORWARD) {
430 First = theASI.Point(IndFrom).Parameter();
431 ok = theASI.LocalizeBefore(thePTo,theOr,IndFrom,IndTo);
433 if (theOr == TopAbs_FORWARD) {
434 ok = theASI.LocalizeAfter(IndTo,theOr,IndFrom,IndTo);
436 if (ok && theOr == TopAbs_REVERSED) {
437 Last = theASI.Point(IndTo).Parameter();
444 myStatus = BRepFeat_InvalidPlacement;
448 TopTools_ListOfShape theList;
449 for (Standard_Integer i=1; i<= theASI.NbPoints(); i++) {
450 prm = theASI.Point(i).Parameter();
451 if (prm >= First && prm <= Last) {
452 theList.Append(theASI.Point(i).Face());
454 else if (prm > Last) {
459 // // It is not possible to use infinite cylinder for topological operations.
460 Standard_Real PMin,PMax;
461 BoxParameters(Object(),myAxis,PMin,PMax);
462 Standard_Real Heigth = 2.*(PMax-PMin);
463 gp_XYZ theOrig = myAxis.Location().XYZ();
464 theOrig += ((3.*PMin-PMax)/2.) * myAxis.Direction().XYZ();
466 gp_Pnt p4_ao1(theOrig); gp_Ax2 a4_ao1(p4_ao1,myAxis.Direction());
467 BRepPrim_Cylinder theCylinder(a4_ao1,
472 TopoDS_Solid theTool;
473 B.MakeSolid(theTool);
474 B.Add(theTool,theCylinder.Shell());
475 theTool.Closed(Standard_True);
477 myTopFace = theCylinder.TopFace();
478 myBotFace = theCylinder.BottomFace();
480 // BRepTools::Dump(theTool,cout);
481 Standard_Boolean Fuse = Standard_False;
482 //myBuilder.Perform(theTool,theList,Fuse);
483 //myBuilder.BuildPartsOfTool();
486 BOPAlgo_Builder::Perform();
487 TopTools_ListOfShape parts;
490 Standard_Integer nbparts = 0;
491 TopTools_ListIteratorOfListOfShape its(parts);
492 for (; its.More(); its.Next()) {
496 myStatus = BRepFeat_InvalidPlacement;
500 if (nbparts >= 2) { // preserve parts between First and Last
503 Standard_Real parbar;
505 for (its.Initialize(parts); its.More(); its.Next()) {
506 Baryc(its.Value(),Barycentre);
507 parbar = ElCLib::LineParameter(myAxis,Barycentre);
508 if (!(parbar < First || parbar > Last)) {
509 KeepPart(its.Value());
516 //=======================================================================
517 //function : PerformBlind
519 //=======================================================================
521 void BRepFeat_MakeCylindricalHole::PerformBlind(const Standard_Real Radius,
522 const Standard_Real Length,
523 const Standard_Boolean Cont)
526 if (Object().IsNull() || !myAxDef || Length <= 0.) {
527 Standard_ConstructionError::Raise();
530 myIsBlind = Standard_True;
532 myStatus = BRepFeat_NoError;
534 LocOpe_CurveShapeIntersector theASI(myAxis,Object());
535 if (!theASI.IsDone()) {
536 myStatus = BRepFeat_InvalidPlacement;
540 // Standard_Real First,prm;
542 Standard_Integer IndFrom,IndTo;
543 TopAbs_Orientation theOr;
544 Standard_Boolean ok = theASI.LocalizeAfter(0.,theOr,IndFrom,IndTo);
547 if (theOr == TopAbs_REVERSED) {
548 ok = theASI.LocalizeBefore(IndFrom,theOr,IndFrom,IndTo); // reset
549 // it is possible to find the next
551 ok = ok && theOr == TopAbs_FORWARD;
554 myStatus = BRepFeat_InvalidPlacement;
558 // check a priori the length of the hole
559 Standard_Integer IFNext,ITNext;
560 ok = theASI.LocalizeAfter(IndTo,theOr,IFNext,ITNext);
562 myStatus = BRepFeat_InvalidPlacement;
565 if (theASI.Point(IFNext).Parameter() <= Length) {
566 myStatus = BRepFeat_HoleTooLong;
570 TopTools_ListOfShape theList;
572 for (Standard_Integer i=IndFrom; i<= IndTo; i++) {
573 theList.Append(theASI.Point(i).Face());
576 // version for advanced control
577 for (Standard_Integer i=IndFrom; i<= ITNext; i++) {
578 theList.Append(theASI.Point(i).Face());
581 First = theASI.Point(IndFrom).Parameter();
583 //// It is not possible to use infinite cylinder for topological operations.
584 Standard_Real PMin,PMax;
585 BoxParameters(Object(),myAxis,PMin,PMax);
587 myStatus = BRepFeat_InvalidPlacement;
591 Standard_Real Heigth = 3.*(Length-PMin)/2.;
592 gp_XYZ theOrig = myAxis.Location().XYZ();
593 theOrig += ((3.*PMin-Length)/2.) * myAxis.Direction().XYZ();
594 gp_Pnt p5_ao1(theOrig); gp_Ax2 a5_ao1(p5_ao1,myAxis.Direction());
595 BRepPrim_Cylinder theCylinder(a5_ao1,
600 TopoDS_Solid theTool;
601 B.MakeSolid(theTool);
602 B.Add(theTool,theCylinder.Shell());
603 theTool.Closed(Standard_True);
605 myTopFace = theCylinder.TopFace();
608 // BRepTools::Dump(theTool,cout);
609 Standard_Boolean Fuse = Standard_False;
610 //myBuilder.Perform(theTool,theList,Fuse);
611 //myBuilder.BuildPartsOfTool();
614 BOPAlgo_Builder::Perform();
615 TopTools_ListOfShape parts;
618 Standard_Integer nbparts = 0;
619 TopTools_ListIteratorOfListOfShape its(parts);
620 for (; its.More(); its.Next()) {
624 myStatus = BRepFeat_InvalidPlacement;
628 if (nbparts >= 2) { // preserve the smallest as parameter along the axis
630 Standard_Real parbar,parmin = RealLast();
632 for (its.Initialize(parts); its.More(); its.Next()) {
633 Baryc(its.Value(),Barycentre);
634 parbar = ElCLib::LineParameter(myAxis,Barycentre);
635 if (parbar >= First && parbar <= parmin) {
637 tokeep = its.Value();
641 if (tokeep.IsNull()) { // preserve the closest interval
643 Standard_Real dmin = RealLast();
644 for (its.Initialize(parts); its.More(); its.Next()) {
645 Baryc(its.Value(),Barycentre);
646 parbar = ElCLib::LineParameter(myAxis,Barycentre);
647 if (Abs(First - parbar) < dmin ) {
648 dmin = Abs(First-parbar);
649 tokeep = its.Value();
653 for (its.Initialize(parts); its.More(); its.Next()) {
654 if (tokeep.IsSame(its.Value())) {
655 KeepPart(its.Value());
662 //=======================================================================
665 //=======================================================================
667 void BRepFeat_MakeCylindricalHole::Build ()
669 if (myStatus == BRepFeat_NoError) {
671 if (!ErrorStatus()) {
672 myStatus = (myValidate) ? Validate() : BRepFeat_NoError;
673 if (myStatus == BRepFeat_NoError) {
678 myStatus = BRepFeat_InvalidPlacement; // why not
684 //=======================================================================
685 //function : Validate
687 //=======================================================================
689 BRepFeat_Status BRepFeat_MakeCylindricalHole::Validate ()
691 BRepFeat_Status thestat = BRepFeat_NoError;
692 TopExp_Explorer ex(Shape(),TopAbs_FACE);
693 if (myIsBlind) { // limit of the hole
694 for (; ex.More(); ex.Next()) {
695 if (ex.Current().IsSame(myTopFace) ) {
700 thestat = BRepFeat_HoleTooLong;
704 for (; ex.More(); ex.Next()) {
705 if (ex.Current().IsSame(myTopFace) ) {
706 return BRepFeat_InvalidPlacement;
709 for (ex.ReInit(); ex.More(); ex.Next()) {
710 if (ex.Current().IsSame(myBotFace) ) {
711 return BRepFeat_InvalidPlacement;
720 void Baryc(const TopoDS_Shape& S, gp_Pnt& B)
722 TopExp_Explorer exp(S,TopAbs_EDGE);
723 gp_XYZ Bar(0.,0.,0.);
725 Handle(Geom_Curve) C;
726 Standard_Real prm,First,Last;
728 Standard_Integer i, nbp= 0;
729 for (; exp.More(); exp.Next()) {
730 // Calculate points by non-degenerated edges
731 const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
732 if (!BRep_Tool::Degenerated(E)) {
733 C = BRep_Tool::Curve(E,L,First,Last);
734 C = Handle(Geom_Curve)::DownCast(C->Transformed(L.Transformation()));
735 for (i=1;i<=11; i++) {
736 prm = ((11-i)*First + (i-1)*Last)/10.;
737 Bar += C->Value(prm).XYZ();
742 Bar.Divide((Standard_Real)nbp);
747 void BoxParameters(const TopoDS_Shape& S,
749 Standard_Real& parmin,
750 Standard_Real& parmax)
753 // calculate the parameters of a bounding box in the direction of the axis of the hole
755 BRepBndLib::Add(S,B);
757 B.Get(c[0],c[2],c[4],c[1],c[3],c[5]);
759 Standard_Integer i,j,k;
761 parmax = RealFirst();
763 for (i=0; i<=1; i++) {
765 for (j=2; j<=3; j++) {
767 for (k=4; k<=5; k++) {
769 param = ElCLib::LineParameter(Axis,P);
770 parmin = Min(param,parmin);
771 parmax = Max(param,parmax);