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 const TopoDS_Shape& aObject=myArguments.First();
60 if (aObject.IsNull() || !myAxDef) {
61 Standard_ConstructionError::Raise();
64 myIsBlind = Standard_False;
65 myStatus = BRepFeat_NoError;
67 LocOpe_CurveShapeIntersector theASI(myAxis,aObject);
68 if (!theASI.IsDone() || theASI.NbPoints() <= 0) {
69 myStatus = BRepFeat_InvalidPlacement;
73 //TopTools_ListOfShape theList;
74 //for (Standard_Integer i=1; i<= theASI.NbPoints(); i++) {
75 // theList.Append(theASI.Point(i).Face());
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,
89 // Probably it is better to make cut directly
94 B.Add(theTool,theCylinder.Shell());
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_BOP::Perform();
109 //=======================================================================
110 //function : PerformThruNext
112 //=======================================================================
114 void BRepFeat_MakeCylindricalHole::PerformThruNext(const Standard_Real Radius,
115 const Standard_Boolean Cont)
118 const TopoDS_Shape& aObject=myArguments.First();
119 if (aObject.IsNull() || !myAxDef) {
120 Standard_ConstructionError::Raise();
123 myIsBlind = Standard_False;
125 myStatus = BRepFeat_NoError;
127 LocOpe_CurveShapeIntersector theASI(myAxis,aObject);
128 if (!theASI.IsDone()) {
129 myStatus = BRepFeat_InvalidPlacement;
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);
138 if (theOr == TopAbs_FORWARD) {
139 First = theASI.Point(IndFrom).Parameter();
140 ok = theASI.LocalizeAfter(IndTo,theOr,IndFrom,IndTo);
142 if (theOr != TopAbs_REVERSED) {
146 Last = theASI.Point(IndTo).Parameter();
151 else { // TopAbs_REVERSED
152 Last = theASI.Point(IndTo).Parameter();
153 ok = theASI.LocalizeBefore(IndFrom,theOr,IndFrom,IndTo);
155 if (theOr != TopAbs_FORWARD) {
159 First = theASI.Point(IndFrom).Parameter();
165 myStatus = BRepFeat_InvalidPlacement;
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());
175 else if (prm > Last) {
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,
192 TopoDS_Solid theTool;
193 B.MakeSolid(theTool);
194 B.Add(theTool,theCylinder.Shell());
196 myTopFace = theCylinder.TopFace();
197 myBotFace = theCylinder.BottomFace();
199 // BRepTools::Dump(theTool,cout);
200 Standard_Boolean Fuse = Standard_False;
201 //myBuilder.Perform(theTool,theList,Fuse);
202 //myBuilder.BuildPartsOfTool();
205 BOPAlgo_Builder::Perform();
206 TopTools_ListOfShape parts;
210 Standard_Integer nbparts = 0;
211 TopTools_ListIteratorOfListOfShape its(parts);
212 for (; its.More(); its.Next()) {
216 myStatus = BRepFeat_InvalidPlacement;
220 if (nbparts >= 2) { // preserve the smallest as parameter
223 Standard_Real parbar,parmin = Last;
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) {
230 tokeep = its.Value();
234 if (tokeep.IsNull()) { // preserve the closest interval
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 ) {
243 tokeep = its.Value();
245 else { // parbar > Last
246 if (parbar - Last < dmin) {
248 tokeep = its.Value();
254 for (its.Initialize(parts); its.More(); its.Next()) {
255 //if (!tokeep.IsSame(its.Value())) {
256 // myBuilder.RemovePart(its.Value());
258 if (tokeep.IsSame(its.Value())) {
259 KeepPart(its.Value());
264 // myBuilder.PerformResult();
267 //=======================================================================
268 //function : PerformUntilEnd
270 //=======================================================================
272 void BRepFeat_MakeCylindricalHole::PerformUntilEnd(const Standard_Real Radius,
273 const Standard_Boolean Cont)
276 const TopoDS_Shape& aObject=myArguments.First();
277 if (aObject.IsNull() || !myAxDef) {
278 Standard_ConstructionError::Raise();
281 myIsBlind = Standard_False;
283 myStatus = BRepFeat_NoError;
285 LocOpe_CurveShapeIntersector theASI(myAxis,aObject);
286 if (!theASI.IsDone()) {
287 myStatus = BRepFeat_InvalidPlacement;
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);
297 if (theOr == TopAbs_REVERSED) {
298 ok = theASI.LocalizeBefore(IndFrom,theOr,IndFrom,IndTo); // on reset
299 // It is possible to search for the next.
301 if ( ok && theOr == TopAbs_FORWARD) {
302 First = theASI.Point(IndFrom).Parameter();
303 ok = theASI.LocalizeBefore(theASI.NbPoints()+1,theOr,IndFrom,IndTo);
305 if (theOr != TopAbs_REVERSED) {
309 Last = theASI.Point(IndTo).Parameter();
315 myStatus = BRepFeat_InvalidPlacement;
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());
325 else if (prm > Last) {
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,
342 TopoDS_Solid theTool;
343 B.MakeSolid(theTool);
344 B.Add(theTool,theCylinder.Shell());
346 myTopFace = theCylinder.TopFace();
347 myBotFace = theCylinder.BottomFace();
349 // BRepTools::Dump(theTool,cout);
350 Standard_Boolean Fuse = Standard_False;
351 //myBuilder.Perform(theTool,theList,Fuse);
352 //myBuilder.BuildPartsOfTool();
355 BOPAlgo_Builder::Perform();
356 TopTools_ListOfShape parts;
359 Standard_Integer nbparts = 0;
360 TopTools_ListIteratorOfListOfShape its(parts);
361 for (; its.More(); its.Next()) {
365 myStatus = BRepFeat_InvalidPlacement;
369 if (nbparts >= 2) { // preserve everything above the First
370 Standard_Real parbar;
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());
383 //=======================================================================
386 //=======================================================================
388 void BRepFeat_MakeCylindricalHole::Perform(const Standard_Real Radius,
389 const Standard_Real PFrom,
390 const Standard_Real PTo,
391 const Standard_Boolean Cont)
394 const TopoDS_Shape& aObject=myArguments.First();
395 if (aObject.IsNull() || !myAxDef) {
396 Standard_ConstructionError::Raise();
399 myIsBlind = Standard_False;
401 myStatus = BRepFeat_NoError;
403 LocOpe_CurveShapeIntersector theASI(myAxis,aObject);
404 if (!theASI.IsDone()) {
405 myStatus = BRepFeat_InvalidPlacement;
409 Standard_Real thePFrom,thePTo;
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);
424 if (theOr == TopAbs_REVERSED) {
425 ok = theASI.LocalizeBefore(IndFrom,theOr,IndFrom,IndTo); // reset
426 // It is possible to find the next.
428 if ( ok && theOr == TopAbs_FORWARD) {
429 First = theASI.Point(IndFrom).Parameter();
430 ok = theASI.LocalizeBefore(thePTo,theOr,IndFrom,IndTo);
432 if (theOr == TopAbs_FORWARD) {
433 ok = theASI.LocalizeAfter(IndTo,theOr,IndFrom,IndTo);
435 if (ok && theOr == TopAbs_REVERSED) {
436 Last = theASI.Point(IndTo).Parameter();
443 myStatus = BRepFeat_InvalidPlacement;
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());
453 else if (prm > Last) {
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();
465 gp_Pnt p4_ao1(theOrig); gp_Ax2 a4_ao1(p4_ao1,myAxis.Direction());
466 BRepPrim_Cylinder theCylinder(a4_ao1,
471 TopoDS_Solid theTool;
472 B.MakeSolid(theTool);
473 B.Add(theTool,theCylinder.Shell());
475 myTopFace = theCylinder.TopFace();
476 myBotFace = theCylinder.BottomFace();
478 // BRepTools::Dump(theTool,cout);
479 Standard_Boolean Fuse = Standard_False;
480 //myBuilder.Perform(theTool,theList,Fuse);
481 //myBuilder.BuildPartsOfTool();
484 BOPAlgo_Builder::Perform();
485 TopTools_ListOfShape parts;
488 Standard_Integer nbparts = 0;
489 TopTools_ListIteratorOfListOfShape its(parts);
490 for (; its.More(); its.Next()) {
494 myStatus = BRepFeat_InvalidPlacement;
498 if (nbparts >= 2) { // preserve parts between First and Last
501 Standard_Real parbar;
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());
514 //=======================================================================
515 //function : PerformBlind
517 //=======================================================================
519 void BRepFeat_MakeCylindricalHole::PerformBlind(const Standard_Real Radius,
520 const Standard_Real Length,
521 const Standard_Boolean Cont)
524 const TopoDS_Shape& aObject=myArguments.First();
525 if (aObject.IsNull() || !myAxDef || Length <= 0.) {
526 Standard_ConstructionError::Raise();
529 myIsBlind = Standard_True;
531 myStatus = BRepFeat_NoError;
533 LocOpe_CurveShapeIntersector theASI(myAxis,aObject);
534 if (!theASI.IsDone()) {
535 myStatus = BRepFeat_InvalidPlacement;
539 // Standard_Real First,prm;
541 Standard_Integer IndFrom,IndTo;
542 TopAbs_Orientation theOr;
543 Standard_Boolean ok = theASI.LocalizeAfter(0.,theOr,IndFrom,IndTo);
546 if (theOr == TopAbs_REVERSED) {
547 ok = theASI.LocalizeBefore(IndFrom,theOr,IndFrom,IndTo); // reset
548 // it is possible to find the next
550 ok = ok && theOr == TopAbs_FORWARD;
553 myStatus = BRepFeat_InvalidPlacement;
557 // check a priori the length of the hole
558 Standard_Integer IFNext,ITNext;
559 ok = theASI.LocalizeAfter(IndTo,theOr,IFNext,ITNext);
561 myStatus = BRepFeat_InvalidPlacement;
564 if (theASI.Point(IFNext).Parameter() <= Length) {
565 myStatus = BRepFeat_HoleTooLong;
569 TopTools_ListOfShape theList;
571 for (Standard_Integer i=IndFrom; i<= IndTo; i++) {
572 theList.Append(theASI.Point(i).Face());
575 // version for advanced control
576 for (Standard_Integer i=IndFrom; i<= ITNext; i++) {
577 theList.Append(theASI.Point(i).Face());
580 First = theASI.Point(IndFrom).Parameter();
582 //// It is not possible to use infinite cylinder for topological operations.
583 Standard_Real PMin,PMax;
584 BoxParameters(aObject,myAxis,PMin,PMax);
586 myStatus = BRepFeat_InvalidPlacement;
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,
599 TopoDS_Solid theTool;
600 B.MakeSolid(theTool);
601 B.Add(theTool,theCylinder.Shell());
603 myTopFace = theCylinder.TopFace();
606 // BRepTools::Dump(theTool,cout);
607 Standard_Boolean Fuse = Standard_False;
608 //myBuilder.Perform(theTool,theList,Fuse);
609 //myBuilder.BuildPartsOfTool();
612 BOPAlgo_Builder::Perform();
613 TopTools_ListOfShape parts;
616 Standard_Integer nbparts = 0;
617 TopTools_ListIteratorOfListOfShape its(parts);
618 for (; its.More(); its.Next()) {
622 myStatus = BRepFeat_InvalidPlacement;
626 if (nbparts >= 2) { // preserve the smallest as parameter along the axis
628 Standard_Real parbar,parmin = RealLast();
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) {
635 tokeep = its.Value();
639 if (tokeep.IsNull()) { // preserve the closest interval
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();
651 for (its.Initialize(parts); its.More(); its.Next()) {
652 if (tokeep.IsSame(its.Value())) {
653 KeepPart(its.Value());
660 //=======================================================================
663 //=======================================================================
665 void BRepFeat_MakeCylindricalHole::Build ()
667 if (myStatus == BRepFeat_NoError) {
669 if (!ErrorStatus()) {
670 myStatus = (myValidate) ? Validate() : BRepFeat_NoError;
671 if (myStatus == BRepFeat_NoError) {
676 myStatus = BRepFeat_InvalidPlacement; // why not
682 //=======================================================================
683 //function : Validate
685 //=======================================================================
687 BRepFeat_Status BRepFeat_MakeCylindricalHole::Validate ()
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) ) {
698 thestat = BRepFeat_HoleTooLong;
702 for (; ex.More(); ex.Next()) {
703 if (ex.Current().IsSame(myTopFace) ) {
704 return BRepFeat_InvalidPlacement;
707 for (ex.ReInit(); ex.More(); ex.Next()) {
708 if (ex.Current().IsSame(myBotFace) ) {
709 return BRepFeat_InvalidPlacement;
718 void Baryc(const TopoDS_Shape& S, gp_Pnt& B)
720 TopExp_Explorer exp(S,TopAbs_EDGE);
721 gp_XYZ Bar(0.,0.,0.);
723 Handle(Geom_Curve) C;
724 Standard_Real prm,First,Last;
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();
740 Bar.Divide((Standard_Real)nbp);
745 void BoxParameters(const TopoDS_Shape& S,
747 Standard_Real& parmin,
748 Standard_Real& parmax)
751 // calculate the parameters of a bounding box in the direction of the axis of the hole
753 BRepBndLib::Add(S,B);
755 B.Get(c[0],c[2],c[4],c[1],c[3],c[5]);
757 Standard_Integer i,j,k;
759 parmax = RealFirst();
761 for (i=0; i<=1; i++) {
763 for (j=2; j<=3; j++) {
765 for (k=4; k<=5; k++) {
767 param = ElCLib::LineParameter(Axis,P);
768 parmin = Min(param,parmin);
769 parmax = Max(param,parmax);