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.
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>
26 #include <Geom_Curve.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>
36 #include <TopoDS_Shape.hxx>
37 #include <TopoDS_Solid.hxx>
38 #include <TopTools_ListIteratorOfListOfShape.hxx>
39 #include <TopTools_ListOfShape.hxx>
41 static void Baryc(const TopoDS_Shape&,
44 static void BoxParameters(const TopoDS_Shape&,
50 //=======================================================================
53 //=======================================================================
55 void BRepFeat_MakeCylindricalHole::Perform(const Standard_Real Radius)
57 const TopoDS_Shape& aObject=myArguments.First();
58 if (aObject.IsNull() || !myAxDef) {
59 Standard_ConstructionError::Raise();
62 myIsBlind = Standard_False;
63 myStatus = BRepFeat_NoError;
65 LocOpe_CurveShapeIntersector theASI(myAxis,aObject);
66 if (!theASI.IsDone() || theASI.NbPoints() <= 0) {
67 myStatus = BRepFeat_InvalidPlacement;
71 //TopTools_ListOfShape theList;
72 //for (Standard_Integer i=1; i<= theASI.NbPoints(); i++) {
73 // theList.Append(theASI.Point(i).Face());
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,
87 // Probably it is better to make cut directly
92 B.Add(theTool,theCylinder.Shell());
94 myTopFace = theCylinder.TopFace();
95 myBotFace = theCylinder.BottomFace();
96 myValidate = Standard_False;
98 // BRepTools::Dump(theTool,cout);
99 Standard_Boolean Fuse = Standard_False;
103 BOPAlgo_BOP::Perform();
107 //=======================================================================
108 //function : PerformThruNext
110 //=======================================================================
112 void BRepFeat_MakeCylindricalHole::PerformThruNext(const Standard_Real Radius,
113 const Standard_Boolean Cont)
116 const TopoDS_Shape& aObject=myArguments.First();
117 if (aObject.IsNull() || !myAxDef) {
118 Standard_ConstructionError::Raise();
121 myIsBlind = Standard_False;
123 myStatus = BRepFeat_NoError;
125 LocOpe_CurveShapeIntersector theASI(myAxis,aObject);
126 if (!theASI.IsDone()) {
127 myStatus = BRepFeat_InvalidPlacement;
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);
136 if (theOr == TopAbs_FORWARD) {
137 First = theASI.Point(IndFrom).Parameter();
138 ok = theASI.LocalizeAfter(IndTo,theOr,IndFrom,IndTo);
140 if (theOr != TopAbs_REVERSED) {
144 Last = theASI.Point(IndTo).Parameter();
149 else { // TopAbs_REVERSED
150 Last = theASI.Point(IndTo).Parameter();
151 ok = theASI.LocalizeBefore(IndFrom,theOr,IndFrom,IndTo);
153 if (theOr != TopAbs_FORWARD) {
157 First = theASI.Point(IndFrom).Parameter();
163 myStatus = BRepFeat_InvalidPlacement;
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());
173 else if (prm > Last) {
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,
190 TopoDS_Solid theTool;
191 B.MakeSolid(theTool);
192 B.Add(theTool,theCylinder.Shell());
194 myTopFace = theCylinder.TopFace();
195 myBotFace = theCylinder.BottomFace();
197 // BRepTools::Dump(theTool,cout);
198 Standard_Boolean Fuse = Standard_False;
199 //myBuilder.Perform(theTool,theList,Fuse);
200 //myBuilder.BuildPartsOfTool();
203 BOPAlgo_Builder::Perform();
204 TopTools_ListOfShape parts;
208 Standard_Integer nbparts = 0;
209 TopTools_ListIteratorOfListOfShape its(parts);
210 for (; its.More(); its.Next()) {
214 myStatus = BRepFeat_InvalidPlacement;
218 if (nbparts >= 2) { // preserve the smallest as parameter
221 Standard_Real parbar,parmin = Last;
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) {
228 tokeep = its.Value();
232 if (tokeep.IsNull()) { // preserve the closest interval
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 ) {
241 tokeep = its.Value();
243 else { // parbar > Last
244 if (parbar - Last < dmin) {
246 tokeep = its.Value();
252 for (its.Initialize(parts); its.More(); its.Next()) {
253 //if (!tokeep.IsSame(its.Value())) {
254 // myBuilder.RemovePart(its.Value());
256 if (tokeep.IsSame(its.Value())) {
257 KeepPart(its.Value());
262 // myBuilder.PerformResult();
265 //=======================================================================
266 //function : PerformUntilEnd
268 //=======================================================================
270 void BRepFeat_MakeCylindricalHole::PerformUntilEnd(const Standard_Real Radius,
271 const Standard_Boolean Cont)
274 const TopoDS_Shape& aObject=myArguments.First();
275 if (aObject.IsNull() || !myAxDef) {
276 Standard_ConstructionError::Raise();
279 myIsBlind = Standard_False;
281 myStatus = BRepFeat_NoError;
283 LocOpe_CurveShapeIntersector theASI(myAxis,aObject);
284 if (!theASI.IsDone()) {
285 myStatus = BRepFeat_InvalidPlacement;
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);
295 if (theOr == TopAbs_REVERSED) {
296 ok = theASI.LocalizeBefore(IndFrom,theOr,IndFrom,IndTo); // on reset
297 // It is possible to search for the next.
299 if ( ok && theOr == TopAbs_FORWARD) {
300 First = theASI.Point(IndFrom).Parameter();
301 ok = theASI.LocalizeBefore(theASI.NbPoints()+1,theOr,IndFrom,IndTo);
303 if (theOr != TopAbs_REVERSED) {
307 Last = theASI.Point(IndTo).Parameter();
313 myStatus = BRepFeat_InvalidPlacement;
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());
323 else if (prm > Last) {
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,
340 TopoDS_Solid theTool;
341 B.MakeSolid(theTool);
342 B.Add(theTool,theCylinder.Shell());
344 myTopFace = theCylinder.TopFace();
345 myBotFace = theCylinder.BottomFace();
347 // BRepTools::Dump(theTool,cout);
348 Standard_Boolean Fuse = Standard_False;
349 //myBuilder.Perform(theTool,theList,Fuse);
350 //myBuilder.BuildPartsOfTool();
353 BOPAlgo_Builder::Perform();
354 TopTools_ListOfShape parts;
357 Standard_Integer nbparts = 0;
358 TopTools_ListIteratorOfListOfShape its(parts);
359 for (; its.More(); its.Next()) {
363 myStatus = BRepFeat_InvalidPlacement;
367 if (nbparts >= 2) { // preserve everything above the First
368 Standard_Real parbar;
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());
381 //=======================================================================
384 //=======================================================================
386 void BRepFeat_MakeCylindricalHole::Perform(const Standard_Real Radius,
387 const Standard_Real PFrom,
388 const Standard_Real PTo,
389 const Standard_Boolean Cont)
392 const TopoDS_Shape& aObject=myArguments.First();
393 if (aObject.IsNull() || !myAxDef) {
394 Standard_ConstructionError::Raise();
397 myIsBlind = Standard_False;
399 myStatus = BRepFeat_NoError;
401 LocOpe_CurveShapeIntersector theASI(myAxis,aObject);
402 if (!theASI.IsDone()) {
403 myStatus = BRepFeat_InvalidPlacement;
407 Standard_Real thePFrom,thePTo;
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);
422 if (theOr == TopAbs_REVERSED) {
423 ok = theASI.LocalizeBefore(IndFrom,theOr,IndFrom,IndTo); // reset
424 // It is possible to find the next.
426 if ( ok && theOr == TopAbs_FORWARD) {
427 First = theASI.Point(IndFrom).Parameter();
428 ok = theASI.LocalizeBefore(thePTo,theOr,IndFrom,IndTo);
430 if (theOr == TopAbs_FORWARD) {
431 ok = theASI.LocalizeAfter(IndTo,theOr,IndFrom,IndTo);
433 if (ok && theOr == TopAbs_REVERSED) {
434 Last = theASI.Point(IndTo).Parameter();
441 myStatus = BRepFeat_InvalidPlacement;
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());
451 else if (prm > Last) {
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();
463 gp_Pnt p4_ao1(theOrig); gp_Ax2 a4_ao1(p4_ao1,myAxis.Direction());
464 BRepPrim_Cylinder theCylinder(a4_ao1,
469 TopoDS_Solid theTool;
470 B.MakeSolid(theTool);
471 B.Add(theTool,theCylinder.Shell());
473 myTopFace = theCylinder.TopFace();
474 myBotFace = theCylinder.BottomFace();
476 // BRepTools::Dump(theTool,cout);
477 Standard_Boolean Fuse = Standard_False;
478 //myBuilder.Perform(theTool,theList,Fuse);
479 //myBuilder.BuildPartsOfTool();
482 BOPAlgo_Builder::Perform();
483 TopTools_ListOfShape parts;
486 Standard_Integer nbparts = 0;
487 TopTools_ListIteratorOfListOfShape its(parts);
488 for (; its.More(); its.Next()) {
492 myStatus = BRepFeat_InvalidPlacement;
496 if (nbparts >= 2) { // preserve parts between First and Last
499 Standard_Real parbar;
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());
512 //=======================================================================
513 //function : PerformBlind
515 //=======================================================================
517 void BRepFeat_MakeCylindricalHole::PerformBlind(const Standard_Real Radius,
518 const Standard_Real Length,
519 const Standard_Boolean Cont)
522 const TopoDS_Shape& aObject=myArguments.First();
523 if (aObject.IsNull() || !myAxDef || Length <= 0.) {
524 Standard_ConstructionError::Raise();
527 myIsBlind = Standard_True;
529 myStatus = BRepFeat_NoError;
531 LocOpe_CurveShapeIntersector theASI(myAxis,aObject);
532 if (!theASI.IsDone()) {
533 myStatus = BRepFeat_InvalidPlacement;
537 // Standard_Real First,prm;
539 Standard_Integer IndFrom,IndTo;
540 TopAbs_Orientation theOr;
541 Standard_Boolean ok = theASI.LocalizeAfter(0.,theOr,IndFrom,IndTo);
544 if (theOr == TopAbs_REVERSED) {
545 ok = theASI.LocalizeBefore(IndFrom,theOr,IndFrom,IndTo); // reset
546 // it is possible to find the next
548 ok = ok && theOr == TopAbs_FORWARD;
551 myStatus = BRepFeat_InvalidPlacement;
555 // check a priori the length of the hole
556 Standard_Integer IFNext,ITNext;
557 ok = theASI.LocalizeAfter(IndTo,theOr,IFNext,ITNext);
559 myStatus = BRepFeat_InvalidPlacement;
562 if (theASI.Point(IFNext).Parameter() <= Length) {
563 myStatus = BRepFeat_HoleTooLong;
567 TopTools_ListOfShape theList;
569 for (Standard_Integer i=IndFrom; i<= IndTo; i++) {
570 theList.Append(theASI.Point(i).Face());
573 // version for advanced control
574 for (Standard_Integer i=IndFrom; i<= ITNext; i++) {
575 theList.Append(theASI.Point(i).Face());
578 First = theASI.Point(IndFrom).Parameter();
580 //// It is not possible to use infinite cylinder for topological operations.
581 Standard_Real PMin,PMax;
582 BoxParameters(aObject,myAxis,PMin,PMax);
584 myStatus = BRepFeat_InvalidPlacement;
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,
597 TopoDS_Solid theTool;
598 B.MakeSolid(theTool);
599 B.Add(theTool,theCylinder.Shell());
601 myTopFace = theCylinder.TopFace();
604 // BRepTools::Dump(theTool,cout);
605 Standard_Boolean Fuse = Standard_False;
606 //myBuilder.Perform(theTool,theList,Fuse);
607 //myBuilder.BuildPartsOfTool();
610 BOPAlgo_Builder::Perform();
611 TopTools_ListOfShape parts;
614 Standard_Integer nbparts = 0;
615 TopTools_ListIteratorOfListOfShape its(parts);
616 for (; its.More(); its.Next()) {
620 myStatus = BRepFeat_InvalidPlacement;
624 if (nbparts >= 2) { // preserve the smallest as parameter along the axis
626 Standard_Real parbar,parmin = RealLast();
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) {
633 tokeep = its.Value();
637 if (tokeep.IsNull()) { // preserve the closest interval
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();
649 for (its.Initialize(parts); its.More(); its.Next()) {
650 if (tokeep.IsSame(its.Value())) {
651 KeepPart(its.Value());
658 //=======================================================================
661 //=======================================================================
663 void BRepFeat_MakeCylindricalHole::Build ()
665 if (myStatus == BRepFeat_NoError) {
667 if (!ErrorStatus()) {
668 myStatus = (myValidate) ? Validate() : BRepFeat_NoError;
669 if (myStatus == BRepFeat_NoError) {
674 myStatus = BRepFeat_InvalidPlacement; // why not
680 //=======================================================================
681 //function : Validate
683 //=======================================================================
685 BRepFeat_Status BRepFeat_MakeCylindricalHole::Validate ()
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) ) {
696 thestat = BRepFeat_HoleTooLong;
700 for (; ex.More(); ex.Next()) {
701 if (ex.Current().IsSame(myTopFace) ) {
702 return BRepFeat_InvalidPlacement;
705 for (ex.ReInit(); ex.More(); ex.Next()) {
706 if (ex.Current().IsSame(myBotFace) ) {
707 return BRepFeat_InvalidPlacement;
716 void Baryc(const TopoDS_Shape& S, gp_Pnt& B)
718 TopExp_Explorer exp(S,TopAbs_EDGE);
719 gp_XYZ Bar(0.,0.,0.);
721 Handle(Geom_Curve) C;
722 Standard_Real prm,First,Last;
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();
738 Bar.Divide((Standard_Real)nbp);
743 void BoxParameters(const TopoDS_Shape& S,
745 Standard_Real& parmin,
746 Standard_Real& parmax)
749 // calculate the parameters of a bounding box in the direction of the axis of the hole
751 BRepBndLib::Add(S,B);
753 B.Get(c[0],c[2],c[4],c[1],c[3],c[5]);
755 Standard_Integer i,j,k;
757 parmax = RealFirst();
759 for (i=0; i<=1; i++) {
761 for (j=2; j<=3; j++) {
763 for (k=4; k<=5; k++) {
765 param = ElCLib::LineParameter(Axis,P);
766 parmin = Min(param,parmin);
767 parmax = Max(param,parmax);