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