Commit | Line | Data |
---|---|---|
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> | |
8c31bd38 | 40 | #include <BRepAdaptor_Surface.hxx> |
41 | #include <CSLib.hxx> | |
7fd59977 | 42 | |
43 | static void Baryc(const TopoDS_Shape&, | |
4e57c75e | 44 | gp_Pnt&); |
7fd59977 | 45 | |
46 | static void BoxParameters(const TopoDS_Shape&, | |
4e57c75e | 47 | const gp_Ax1&, |
48 | Standard_Real&, | |
49 | Standard_Real&); | |
7fd59977 | 50 | |
8c31bd38 | 51 | static Standard_Boolean GetOffset(const LocOpe_PntFace& PntInfo, |
52 | const Standard_Real Radius, | |
53 | const gp_Ax1& Axis, | |
54 | Standard_Real& outOff ); | |
55 | ||
56 | static void CreateCyl(const LocOpe_PntFace& PntInfoFirst, const LocOpe_PntFace& PntInfoLast, const Standard_Real Radius, | |
57 | const gp_Ax1& Axis, TopoDS_Shell& Cyl, TopoDS_Face& CylTopF, TopoDS_Face& CylBottF ); | |
58 | ||
7fd59977 | 59 | |
60 | //======================================================================= | |
61 | //function : Perform | |
62 | //purpose : | |
63 | //======================================================================= | |
64 | ||
65 | void BRepFeat_MakeCylindricalHole::Perform(const Standard_Real Radius) | |
66 | { | |
8620e18d | 67 | const TopoDS_Shape& aObject=myArguments.First(); |
68 | if (aObject.IsNull() || !myAxDef) { | |
9775fa61 | 69 | throw Standard_ConstructionError(); |
7fd59977 | 70 | } |
71 | ||
72 | myIsBlind = Standard_False; | |
73 | myStatus = BRepFeat_NoError; | |
74 | ||
8620e18d | 75 | LocOpe_CurveShapeIntersector theASI(myAxis,aObject); |
7fd59977 | 76 | if (!theASI.IsDone() || theASI.NbPoints() <= 0) { |
77 | myStatus = BRepFeat_InvalidPlacement; | |
78 | return; | |
79 | } | |
7fd59977 | 80 | |
0d969553 | 81 | // It is not possible to use infinite cylinder for topological operations. |
7fd59977 | 82 | Standard_Real PMin,PMax; |
8620e18d | 83 | BoxParameters(aObject,myAxis,PMin,PMax); |
7fd59977 | 84 | Standard_Real Heigth = 2.*(PMax-PMin); |
85 | gp_XYZ theOrig = myAxis.Location().XYZ(); | |
86 | theOrig += ((3.*PMin-PMax)/2.) * myAxis.Direction().XYZ(); | |
87 | gp_Pnt p1_ao1(theOrig); gp_Ax2 a1_ao1(p1_ao1,myAxis.Direction()); | |
88 | BRepPrim_Cylinder theCylinder(a1_ao1, | |
4e57c75e | 89 | Radius, |
90 | Heigth); | |
7fd59977 | 91 | |
0d969553 | 92 | // Probably it is better to make cut directly |
7fd59977 | 93 | |
94 | BRep_Builder B; | |
95 | TopoDS_Solid theTool; | |
96 | B.MakeSolid(theTool); | |
97 | B.Add(theTool,theCylinder.Shell()); | |
7fd59977 | 98 | |
99 | myTopFace = theCylinder.TopFace(); | |
100 | myBotFace = theCylinder.BottomFace(); | |
101 | myValidate = Standard_False; | |
102 | ||
04232180 | 103 | // BRepTools::Dump(theTool,std::cout); |
7fd59977 | 104 | Standard_Boolean Fuse = Standard_False; |
4e57c75e | 105 | // |
106 | AddTool(theTool); | |
107 | SetOperation(Fuse); | |
8620e18d | 108 | BOPAlgo_BOP::Perform(); |
7fd59977 | 109 | } |
110 | ||
111 | ||
112 | //======================================================================= | |
113 | //function : PerformThruNext | |
114 | //purpose : | |
115 | //======================================================================= | |
116 | ||
117 | void BRepFeat_MakeCylindricalHole::PerformThruNext(const Standard_Real Radius, | |
4e57c75e | 118 | const Standard_Boolean Cont) |
7fd59977 | 119 | { |
8620e18d | 120 | // |
121 | const TopoDS_Shape& aObject=myArguments.First(); | |
122 | if (aObject.IsNull() || !myAxDef) { | |
9775fa61 | 123 | throw Standard_ConstructionError(); |
7fd59977 | 124 | } |
125 | ||
126 | myIsBlind = Standard_False; | |
127 | myValidate = Cont; | |
128 | myStatus = BRepFeat_NoError; | |
129 | ||
8620e18d | 130 | LocOpe_CurveShapeIntersector theASI(myAxis,aObject); |
7fd59977 | 131 | if (!theASI.IsDone()) { |
132 | myStatus = BRepFeat_InvalidPlacement; | |
133 | return; | |
134 | } | |
135 | ||
7fd59977 | 136 | Standard_Integer IndFrom,IndTo; |
137 | TopAbs_Orientation theOr; | |
8c31bd38 | 138 | LocOpe_PntFace PntInfoFirst, PntInfoLast; |
7fd59977 | 139 | Standard_Boolean ok = theASI.LocalizeAfter(0.,theOr,IndFrom,IndTo); |
140 | if (ok) { | |
141 | if (theOr == TopAbs_FORWARD) { | |
8c31bd38 | 142 | PntInfoFirst = theASI.Point(IndFrom); |
7fd59977 | 143 | ok = theASI.LocalizeAfter(IndTo,theOr,IndFrom,IndTo); |
144 | if (ok) { | |
4e57c75e | 145 | if (theOr != TopAbs_REVERSED) { |
146 | ok = Standard_False; | |
147 | } | |
148 | else { | |
8c31bd38 | 149 | PntInfoLast = theASI.Point(IndTo); |
4e57c75e | 150 | } |
7fd59977 | 151 | } |
152 | ||
153 | } | |
154 | else { // TopAbs_REVERSED | |
8c31bd38 | 155 | PntInfoLast = theASI.Point(IndTo); |
7fd59977 | 156 | ok = theASI.LocalizeBefore(IndFrom,theOr,IndFrom,IndTo); |
157 | if (ok) { | |
4e57c75e | 158 | if (theOr != TopAbs_FORWARD) { |
159 | ok = Standard_False; | |
160 | } | |
161 | else { | |
8c31bd38 | 162 | PntInfoFirst = theASI.Point(IndFrom); |
4e57c75e | 163 | } |
7fd59977 | 164 | } |
165 | } | |
166 | } | |
167 | if (!ok) { | |
168 | myStatus = BRepFeat_InvalidPlacement; | |
169 | return; | |
170 | } | |
171 | ||
8c31bd38 | 172 | TopoDS_Shell Cyl; |
173 | CreateCyl(PntInfoFirst, PntInfoLast, Radius, myAxis, Cyl, myTopFace, myBotFace); | |
7fd59977 | 174 | |
175 | BRep_Builder B; | |
176 | TopoDS_Solid theTool; | |
177 | B.MakeSolid(theTool); | |
8c31bd38 | 178 | B.Add(theTool, Cyl); |
7fd59977 | 179 | |
7fd59977 | 180 | Standard_Boolean Fuse = Standard_False; |
4e57c75e | 181 | AddTool(theTool); |
182 | SetOperation(Fuse); | |
8c31bd38 | 183 | BOPAlgo_BOP::Perform(); |
4e57c75e | 184 | TopTools_ListOfShape parts; |
185 | PartsOfTool(parts); | |
7fd59977 | 186 | |
7fd59977 | 187 | Standard_Integer nbparts = 0; |
4e57c75e | 188 | TopTools_ListIteratorOfListOfShape its(parts); |
7fd59977 | 189 | for (; its.More(); its.Next()) { |
190 | nbparts ++; | |
191 | } | |
192 | if (nbparts == 0) { | |
193 | myStatus = BRepFeat_InvalidPlacement; | |
194 | return; | |
195 | } | |
196 | ||
0d969553 Y |
197 | if (nbparts >= 2) { // preserve the smallest as parameter |
198 | // along the axis | |
8c31bd38 | 199 | |
200 | Standard_Real First=PntInfoFirst.Parameter(); | |
201 | Standard_Real Last=PntInfoLast.Parameter(); | |
7fd59977 | 202 | TopoDS_Shape tokeep; |
203 | Standard_Real parbar,parmin = Last; | |
204 | gp_Pnt Barycentre; | |
4e57c75e | 205 | for (its.Initialize(parts); its.More(); its.Next()) { |
7fd59977 | 206 | Baryc(its.Value(),Barycentre); |
207 | parbar = ElCLib::LineParameter(myAxis,Barycentre); | |
208 | if (parbar >= First && parbar <= Last && parbar <= parmin) { | |
4e57c75e | 209 | parmin = parbar; |
210 | tokeep = its.Value(); | |
7fd59977 | 211 | } |
212 | } | |
213 | ||
0d969553 | 214 | if (tokeep.IsNull()) { // preserve the closest interval |
7fd59977 | 215 | |
216 | Standard_Real dmin = RealLast(); | |
4e57c75e | 217 | for (its.Initialize(parts); its.More(); its.Next()) { |
218 | Baryc(its.Value(),Barycentre); | |
219 | parbar = ElCLib::LineParameter(myAxis,Barycentre); | |
220 | if (parbar < First) { | |
221 | if (First - parbar < dmin ) { | |
222 | dmin = First-parbar; | |
223 | tokeep = its.Value(); | |
224 | } | |
225 | else { // parbar > Last | |
226 | if (parbar - Last < dmin) { | |
227 | dmin = parbar-Last; | |
228 | tokeep = its.Value(); | |
229 | } | |
230 | } | |
231 | } | |
7fd59977 | 232 | } |
233 | } | |
4e57c75e | 234 | for (its.Initialize(parts); its.More(); its.Next()) { |
4e57c75e | 235 | if (tokeep.IsSame(its.Value())) { |
236 | KeepPart(its.Value()); | |
237 | break; | |
7fd59977 | 238 | } |
239 | } | |
240 | } | |
7fd59977 | 241 | } |
242 | ||
243 | //======================================================================= | |
244 | //function : PerformUntilEnd | |
245 | //purpose : | |
246 | //======================================================================= | |
247 | ||
248 | void BRepFeat_MakeCylindricalHole::PerformUntilEnd(const Standard_Real Radius, | |
4e57c75e | 249 | const Standard_Boolean Cont) |
7fd59977 | 250 | { |
8620e18d | 251 | // |
252 | const TopoDS_Shape& aObject=myArguments.First(); | |
253 | if (aObject.IsNull() || !myAxDef) { | |
9775fa61 | 254 | throw Standard_ConstructionError(); |
7fd59977 | 255 | } |
256 | ||
257 | myIsBlind = Standard_False; | |
258 | myValidate = Cont; | |
259 | myStatus = BRepFeat_NoError; | |
260 | ||
8620e18d | 261 | LocOpe_CurveShapeIntersector theASI(myAxis,aObject); |
7fd59977 | 262 | if (!theASI.IsDone()) { |
263 | myStatus = BRepFeat_InvalidPlacement; | |
264 | return; | |
265 | } | |
8c31bd38 | 266 | |
7fd59977 | 267 | Standard_Integer IndFrom,IndTo; |
268 | TopAbs_Orientation theOr; | |
269 | Standard_Boolean ok = theASI.LocalizeAfter(0.,theOr,IndFrom,IndTo); | |
8c31bd38 | 270 | LocOpe_PntFace PntInfoFirst, PntInfoLast; |
271 | ||
7fd59977 | 272 | if (ok) { |
273 | if (theOr == TopAbs_REVERSED) { | |
0d969553 Y |
274 | ok = theASI.LocalizeBefore(IndFrom,theOr,IndFrom,IndTo); // on reset |
275 | // It is possible to search for the next. | |
7fd59977 | 276 | } |
277 | if ( ok && theOr == TopAbs_FORWARD) { | |
8c31bd38 | 278 | PntInfoFirst = theASI.Point(IndFrom); |
7fd59977 | 279 | ok = theASI.LocalizeBefore(theASI.NbPoints()+1,theOr,IndFrom,IndTo); |
280 | if (ok) { | |
4e57c75e | 281 | if (theOr != TopAbs_REVERSED) { |
282 | ok = Standard_False; | |
283 | } | |
284 | else { | |
8c31bd38 | 285 | PntInfoLast = theASI.Point(IndTo); |
4e57c75e | 286 | } |
7fd59977 | 287 | } |
288 | } | |
289 | } | |
290 | if (!ok) { | |
291 | myStatus = BRepFeat_InvalidPlacement; | |
292 | return; | |
293 | } | |
294 | ||
8c31bd38 | 295 | TopoDS_Shell Cyl; |
296 | CreateCyl(PntInfoFirst, PntInfoLast, Radius, myAxis, Cyl, myTopFace, myBotFace); | |
7fd59977 | 297 | |
298 | BRep_Builder B; | |
299 | TopoDS_Solid theTool; | |
300 | B.MakeSolid(theTool); | |
8c31bd38 | 301 | B.Add(theTool, Cyl); |
7fd59977 | 302 | |
7fd59977 | 303 | Standard_Boolean Fuse = Standard_False; |
4e57c75e | 304 | AddTool(theTool); |
305 | SetOperation(Fuse); | |
8c31bd38 | 306 | BOPAlgo_BOP::Perform(); |
4e57c75e | 307 | TopTools_ListOfShape parts; |
308 | PartsOfTool(parts); | |
7fd59977 | 309 | |
310 | Standard_Integer nbparts = 0; | |
4e57c75e | 311 | TopTools_ListIteratorOfListOfShape its(parts); |
7fd59977 | 312 | for (; its.More(); its.Next()) { |
313 | nbparts ++; | |
314 | } | |
315 | if (nbparts == 0) { | |
316 | myStatus = BRepFeat_InvalidPlacement; | |
317 | return; | |
318 | } | |
319 | ||
0d969553 | 320 | if (nbparts >= 2) { // preserve everything above the First |
7fd59977 | 321 | Standard_Real parbar; |
322 | gp_Pnt Barycentre; | |
4e57c75e | 323 | for (its.Initialize(parts); its.More(); its.Next()) { |
7fd59977 | 324 | Baryc(its.Value(),Barycentre); |
325 | parbar = ElCLib::LineParameter(myAxis,Barycentre); | |
8c31bd38 | 326 | if (parbar > PntInfoFirst.Parameter()) { |
4e57c75e | 327 | KeepPart(its.Value()); |
7fd59977 | 328 | } |
329 | } | |
330 | } | |
7fd59977 | 331 | } |
332 | ||
333 | ||
334 | //======================================================================= | |
335 | //function : Perform | |
336 | //purpose : | |
337 | //======================================================================= | |
338 | ||
339 | void BRepFeat_MakeCylindricalHole::Perform(const Standard_Real Radius, | |
4e57c75e | 340 | const Standard_Real PFrom, |
341 | const Standard_Real PTo, | |
342 | const Standard_Boolean Cont) | |
7fd59977 | 343 | { |
8620e18d | 344 | // |
345 | const TopoDS_Shape& aObject=myArguments.First(); | |
346 | if (aObject.IsNull() || !myAxDef) { | |
9775fa61 | 347 | throw Standard_ConstructionError(); |
7fd59977 | 348 | } |
349 | ||
350 | myIsBlind = Standard_False; | |
351 | myValidate = Cont; | |
352 | myStatus = BRepFeat_NoError; | |
353 | ||
8620e18d | 354 | LocOpe_CurveShapeIntersector theASI(myAxis,aObject); |
7fd59977 | 355 | if (!theASI.IsDone()) { |
356 | myStatus = BRepFeat_InvalidPlacement; | |
357 | return; | |
358 | } | |
359 | ||
360 | Standard_Real thePFrom,thePTo; | |
361 | if (PFrom < PTo) { | |
362 | thePFrom = PFrom; | |
363 | thePTo = PTo; | |
364 | } | |
365 | else { | |
366 | thePFrom = PTo; | |
367 | thePTo = PFrom; | |
368 | } | |
369 | ||
8c31bd38 | 370 | //Standard_Real First=0,Last=0,prm; |
371 | LocOpe_PntFace PntInfoFirst, PntInfoLast; | |
7fd59977 | 372 | Standard_Integer IndFrom,IndTo; |
373 | TopAbs_Orientation theOr; | |
374 | Standard_Boolean ok = theASI.LocalizeAfter(thePFrom,theOr,IndFrom,IndTo); | |
375 | if (ok) { | |
376 | if (theOr == TopAbs_REVERSED) { | |
0d969553 Y |
377 | ok = theASI.LocalizeBefore(IndFrom,theOr,IndFrom,IndTo); // reset |
378 | // It is possible to find the next. | |
7fd59977 | 379 | } |
380 | if ( ok && theOr == TopAbs_FORWARD) { | |
8c31bd38 | 381 | PntInfoFirst = theASI.Point(IndFrom); |
7fd59977 | 382 | ok = theASI.LocalizeBefore(thePTo,theOr,IndFrom,IndTo); |
383 | if (ok) { | |
4e57c75e | 384 | if (theOr == TopAbs_FORWARD) { |
385 | ok = theASI.LocalizeAfter(IndTo,theOr,IndFrom,IndTo); | |
386 | } | |
387 | if (ok && theOr == TopAbs_REVERSED) { | |
8c31bd38 | 388 | PntInfoLast = theASI.Point(IndTo); |
4e57c75e | 389 | } |
7fd59977 | 390 | } |
391 | } | |
392 | } | |
393 | ||
394 | if (!ok) { | |
395 | myStatus = BRepFeat_InvalidPlacement; | |
396 | return; | |
397 | } | |
398 | ||
8c31bd38 | 399 | TopoDS_Shell Cyl; |
400 | CreateCyl(PntInfoFirst, PntInfoLast, Radius, myAxis, Cyl, myTopFace, myBotFace); | |
7fd59977 | 401 | |
402 | BRep_Builder B; | |
403 | TopoDS_Solid theTool; | |
404 | B.MakeSolid(theTool); | |
8c31bd38 | 405 | B.Add(theTool, Cyl); |
7fd59977 | 406 | |
7fd59977 | 407 | Standard_Boolean Fuse = Standard_False; |
4e57c75e | 408 | AddTool(theTool); |
409 | SetOperation(Fuse); | |
8c31bd38 | 410 | BOPAlgo_BOP::Perform(); |
4e57c75e | 411 | TopTools_ListOfShape parts; |
412 | PartsOfTool(parts); | |
7fd59977 | 413 | |
414 | Standard_Integer nbparts = 0; | |
4e57c75e | 415 | TopTools_ListIteratorOfListOfShape its(parts); |
7fd59977 | 416 | for (; its.More(); its.Next()) { |
417 | nbparts ++; | |
418 | } | |
419 | if (nbparts == 0) { | |
420 | myStatus = BRepFeat_InvalidPlacement; | |
421 | return; | |
422 | } | |
423 | ||
0d969553 | 424 | if (nbparts >= 2) { // preserve parts between First and Last |
7fd59977 | 425 | |
426 | TopoDS_Shape tokeep; | |
427 | Standard_Real parbar; | |
428 | gp_Pnt Barycentre; | |
4e57c75e | 429 | for (its.Initialize(parts); its.More(); its.Next()) { |
7fd59977 | 430 | Baryc(its.Value(),Barycentre); |
431 | parbar = ElCLib::LineParameter(myAxis,Barycentre); | |
8c31bd38 | 432 | if (!(parbar < PntInfoFirst.Parameter() || parbar > PntInfoLast.Parameter())) { |
4e57c75e | 433 | KeepPart(its.Value()); |
7fd59977 | 434 | } |
435 | } | |
436 | } | |
7fd59977 | 437 | } |
438 | ||
439 | ||
440 | //======================================================================= | |
441 | //function : PerformBlind | |
442 | //purpose : | |
443 | //======================================================================= | |
444 | ||
445 | void BRepFeat_MakeCylindricalHole::PerformBlind(const Standard_Real Radius, | |
4e57c75e | 446 | const Standard_Real Length, |
447 | const Standard_Boolean Cont) | |
7fd59977 | 448 | { |
8620e18d | 449 | // |
450 | const TopoDS_Shape& aObject=myArguments.First(); | |
451 | if (aObject.IsNull() || !myAxDef || Length <= 0.) { | |
9775fa61 | 452 | throw Standard_ConstructionError(); |
7fd59977 | 453 | } |
454 | ||
455 | myIsBlind = Standard_True; | |
456 | myValidate = Cont; | |
457 | myStatus = BRepFeat_NoError; | |
458 | ||
8620e18d | 459 | LocOpe_CurveShapeIntersector theASI(myAxis,aObject); |
7fd59977 | 460 | if (!theASI.IsDone()) { |
461 | myStatus = BRepFeat_InvalidPlacement; | |
462 | return; | |
463 | } | |
464 | ||
7fd59977 | 465 | Standard_Real First; |
466 | Standard_Integer IndFrom,IndTo; | |
467 | TopAbs_Orientation theOr; | |
468 | Standard_Boolean ok = theASI.LocalizeAfter(0.,theOr,IndFrom,IndTo); | |
469 | ||
470 | if (ok) { | |
471 | if (theOr == TopAbs_REVERSED) { | |
0d969553 Y |
472 | ok = theASI.LocalizeBefore(IndFrom,theOr,IndFrom,IndTo); // reset |
473 | // it is possible to find the next | |
7fd59977 | 474 | } |
475 | ok = ok && theOr == TopAbs_FORWARD; | |
476 | } | |
477 | if (!ok) { | |
478 | myStatus = BRepFeat_InvalidPlacement; | |
479 | return; | |
480 | } | |
481 | ||
0d969553 | 482 | // check a priori the length of the hole |
7fd59977 | 483 | Standard_Integer IFNext,ITNext; |
484 | ok = theASI.LocalizeAfter(IndTo,theOr,IFNext,ITNext); | |
485 | if (!ok) { | |
486 | myStatus = BRepFeat_InvalidPlacement; | |
487 | return; | |
488 | } | |
489 | if (theASI.Point(IFNext).Parameter() <= Length) { | |
490 | myStatus = BRepFeat_HoleTooLong; | |
491 | return; | |
492 | } | |
493 | ||
494 | TopTools_ListOfShape theList; | |
8c31bd38 | 495 | |
0d969553 | 496 | // version for advanced control |
7fd59977 | 497 | for (Standard_Integer i=IndFrom; i<= ITNext; i++) { |
498 | theList.Append(theASI.Point(i).Face()); | |
499 | } | |
500 | ||
501 | First = theASI.Point(IndFrom).Parameter(); | |
502 | ||
0d969553 | 503 | //// It is not possible to use infinite cylinder for topological operations. |
7fd59977 | 504 | Standard_Real PMin,PMax; |
8620e18d | 505 | BoxParameters(aObject,myAxis,PMin,PMax); |
7fd59977 | 506 | if (PMin > Length) { |
507 | myStatus = BRepFeat_InvalidPlacement; | |
508 | return; | |
509 | } | |
510 | ||
511 | Standard_Real Heigth = 3.*(Length-PMin)/2.; | |
512 | gp_XYZ theOrig = myAxis.Location().XYZ(); | |
513 | theOrig += ((3.*PMin-Length)/2.) * myAxis.Direction().XYZ(); | |
514 | gp_Pnt p5_ao1(theOrig); gp_Ax2 a5_ao1(p5_ao1,myAxis.Direction()); | |
515 | BRepPrim_Cylinder theCylinder(a5_ao1, | |
4e57c75e | 516 | Radius, |
517 | Heigth); | |
7fd59977 | 518 | |
519 | BRep_Builder B; | |
520 | TopoDS_Solid theTool; | |
521 | B.MakeSolid(theTool); | |
522 | B.Add(theTool,theCylinder.Shell()); | |
7fd59977 | 523 | |
524 | myTopFace = theCylinder.TopFace(); | |
525 | myBotFace.Nullify(); | |
526 | ||
04232180 | 527 | // BRepTools::Dump(theTool,std::cout); |
7fd59977 | 528 | Standard_Boolean Fuse = Standard_False; |
4e57c75e | 529 | //myBuilder.Perform(theTool,theList,Fuse); |
530 | //myBuilder.BuildPartsOfTool(); | |
531 | AddTool(theTool); | |
532 | SetOperation(Fuse); | |
8c31bd38 | 533 | BOPAlgo_BOP::Perform(); |
4e57c75e | 534 | TopTools_ListOfShape parts; |
535 | PartsOfTool(parts); | |
7fd59977 | 536 | |
537 | Standard_Integer nbparts = 0; | |
4e57c75e | 538 | TopTools_ListIteratorOfListOfShape its(parts); |
7fd59977 | 539 | for (; its.More(); its.Next()) { |
540 | nbparts ++; | |
541 | } | |
542 | if (nbparts == 0) { | |
543 | myStatus = BRepFeat_InvalidPlacement; | |
544 | return; | |
545 | } | |
546 | ||
0d969553 | 547 | if (nbparts >= 2) { // preserve the smallest as parameter along the axis |
7fd59977 | 548 | TopoDS_Shape tokeep; |
549 | Standard_Real parbar,parmin = RealLast(); | |
550 | gp_Pnt Barycentre; | |
4e57c75e | 551 | for (its.Initialize(parts); its.More(); its.Next()) { |
7fd59977 | 552 | Baryc(its.Value(),Barycentre); |
553 | parbar = ElCLib::LineParameter(myAxis,Barycentre); | |
554 | if (parbar >= First && parbar <= parmin) { | |
4e57c75e | 555 | parmin = parbar; |
556 | tokeep = its.Value(); | |
7fd59977 | 557 | } |
558 | } | |
559 | ||
0d969553 | 560 | if (tokeep.IsNull()) { // preserve the closest interval |
7fd59977 | 561 | |
562 | Standard_Real dmin = RealLast(); | |
4e57c75e | 563 | for (its.Initialize(parts); its.More(); its.Next()) { |
564 | Baryc(its.Value(),Barycentre); | |
565 | parbar = ElCLib::LineParameter(myAxis,Barycentre); | |
566 | if (Abs(First - parbar) < dmin ) { | |
567 | dmin = Abs(First-parbar); | |
568 | tokeep = its.Value(); | |
569 | } | |
7fd59977 | 570 | } |
571 | } | |
4e57c75e | 572 | for (its.Initialize(parts); its.More(); its.Next()) { |
573 | if (tokeep.IsSame(its.Value())) { | |
574 | KeepPart(its.Value()); | |
575 | break; | |
7fd59977 | 576 | } |
577 | } | |
578 | } | |
7fd59977 | 579 | } |
580 | ||
7fd59977 | 581 | //======================================================================= |
582 | //function : Build | |
583 | //purpose : | |
584 | //======================================================================= | |
585 | ||
586 | void BRepFeat_MakeCylindricalHole::Build () | |
587 | { | |
588 | if (myStatus == BRepFeat_NoError) { | |
4e57c75e | 589 | PerformResult(); |
33ba8565 | 590 | if (!HasErrors()) { |
7fd59977 | 591 | myStatus = (myValidate) ? Validate() : BRepFeat_NoError; |
592 | if (myStatus == BRepFeat_NoError) { | |
4e57c75e | 593 | myShape = Shape(); |
7fd59977 | 594 | } |
595 | } | |
596 | else { | |
7fd59977 | 597 | myStatus = BRepFeat_InvalidPlacement; // why not |
598 | } | |
599 | } | |
7fd59977 | 600 | } |
601 | ||
602 | ||
603 | //======================================================================= | |
604 | //function : Validate | |
605 | //purpose : | |
606 | //======================================================================= | |
607 | ||
608 | BRepFeat_Status BRepFeat_MakeCylindricalHole::Validate () | |
609 | { | |
610 | BRepFeat_Status thestat = BRepFeat_NoError; | |
4e57c75e | 611 | TopExp_Explorer ex(Shape(),TopAbs_FACE); |
0d969553 | 612 | if (myIsBlind) { // limit of the hole |
7fd59977 | 613 | for (; ex.More(); ex.Next()) { |
614 | if (ex.Current().IsSame(myTopFace) ) { | |
4e57c75e | 615 | break; |
7fd59977 | 616 | } |
617 | } | |
618 | if (!ex.More()) { | |
619 | thestat = BRepFeat_HoleTooLong; | |
620 | } | |
621 | } | |
622 | else { | |
623 | for (; ex.More(); ex.Next()) { | |
624 | if (ex.Current().IsSame(myTopFace) ) { | |
4e57c75e | 625 | return BRepFeat_InvalidPlacement; |
7fd59977 | 626 | } |
627 | } | |
628 | for (ex.ReInit(); ex.More(); ex.Next()) { | |
629 | if (ex.Current().IsSame(myBotFace) ) { | |
4e57c75e | 630 | return BRepFeat_InvalidPlacement; |
7fd59977 | 631 | } |
632 | } | |
633 | } | |
634 | return thestat; | |
635 | } | |
636 | ||
637 | ||
638 | ||
639 | void Baryc(const TopoDS_Shape& S, gp_Pnt& B) | |
640 | { | |
641 | TopExp_Explorer exp(S,TopAbs_EDGE); | |
642 | gp_XYZ Bar(0.,0.,0.); | |
643 | TopLoc_Location L; | |
644 | Handle(Geom_Curve) C; | |
645 | Standard_Real prm,First,Last; | |
646 | ||
647 | Standard_Integer i, nbp= 0; | |
648 | for (; exp.More(); exp.Next()) { | |
0d969553 | 649 | // Calculate points by non-degenerated edges |
7fd59977 | 650 | const TopoDS_Edge& E = TopoDS::Edge(exp.Current()); |
651 | if (!BRep_Tool::Degenerated(E)) { | |
652 | C = BRep_Tool::Curve(E,L,First,Last); | |
653 | C = Handle(Geom_Curve)::DownCast(C->Transformed(L.Transformation())); | |
654 | for (i=1;i<=11; i++) { | |
4e57c75e | 655 | prm = ((11-i)*First + (i-1)*Last)/10.; |
656 | Bar += C->Value(prm).XYZ(); | |
657 | nbp++; | |
7fd59977 | 658 | } |
659 | } | |
660 | } | |
661 | Bar.Divide((Standard_Real)nbp); | |
662 | B.SetXYZ(Bar); | |
663 | } | |
664 | ||
665 | ||
666 | void BoxParameters(const TopoDS_Shape& S, | |
4e57c75e | 667 | const gp_Ax1& Axis, |
668 | Standard_Real& parmin, | |
669 | Standard_Real& parmax) | |
7fd59977 | 670 | { |
671 | ||
0d969553 | 672 | // calculate the parameters of a bounding box in the direction of the axis of the hole |
7fd59977 | 673 | Bnd_Box B; |
674 | BRepBndLib::Add(S,B); | |
675 | Standard_Real c[6]; | |
676 | B.Get(c[0],c[2],c[4],c[1],c[3],c[5]); | |
677 | gp_Pnt P; | |
678 | Standard_Integer i,j,k; | |
679 | parmin = RealLast(); | |
680 | parmax = RealFirst(); | |
681 | Standard_Real param; | |
682 | for (i=0; i<=1; i++) { | |
683 | P.SetX(c[i]); | |
684 | for (j=2; j<=3; j++) { | |
685 | P.SetY(c[j]); | |
686 | for (k=4; k<=5; k++) { | |
4e57c75e | 687 | P.SetZ(c[k]); |
688 | param = ElCLib::LineParameter(Axis,P); | |
689 | parmin = Min(param,parmin); | |
690 | parmax = Max(param,parmax); | |
7fd59977 | 691 | } |
692 | } | |
693 | } | |
694 | } | |
8c31bd38 | 695 | |
696 | Standard_Boolean GetOffset(const LocOpe_PntFace& PntInfo, const Standard_Real Radius, const gp_Ax1& Axis, Standard_Real& outOff ) | |
697 | { | |
698 | const TopoDS_Face& FF = PntInfo.Face(); | |
699 | BRepAdaptor_Surface FFA(FF); | |
700 | ||
701 | Standard_Real Up = PntInfo.UParameter(); | |
702 | Standard_Real Vp = PntInfo.VParameter(); | |
703 | gp_Pnt PP; | |
704 | gp_Vec D1U, D1V; | |
705 | FFA.D1(Up, Vp, PP, D1U, D1V); | |
706 | gp_Dir NormF; | |
707 | CSLib_NormalStatus stat; | |
708 | CSLib::Normal(D1U, D1V, Precision::Angular(), stat, NormF); | |
709 | if (stat != CSLib_Defined) | |
710 | return Standard_False; | |
711 | Standard_Real angle = Axis.Direction().Angle(NormF); | |
712 | if (Abs(M_PI/2. - angle) < Precision::Angular()) | |
713 | return Standard_False; | |
714 | outOff = Radius * Abs (tan(angle)); | |
715 | return Standard_True; | |
716 | } | |
717 | ||
718 | void CreateCyl(const LocOpe_PntFace& PntInfoFirst, const LocOpe_PntFace& PntInfoLast, const Standard_Real Radius, | |
719 | const gp_Ax1& Axis, TopoDS_Shell& Cyl, TopoDS_Face& CylTopF, TopoDS_Face& CylBottF ) | |
720 | { | |
721 | Standard_Real First=0, Last=0; | |
722 | double offF = 0., offL = 0.; | |
723 | Last = PntInfoLast.Parameter(); | |
724 | First = PntInfoFirst.Parameter(); | |
725 | Standard_Real Heigth = Last - First; | |
726 | ||
727 | if ( !GetOffset(PntInfoFirst, Radius, Axis, offF)) | |
728 | offF = Radius; | |
729 | if ( !GetOffset(PntInfoLast, Radius, Axis, offL)) | |
730 | offL = Radius; | |
731 | ||
732 | //create cylinder along the axis (myAxis); | |
733 | //from 'First - offF' to 'Last + offL' params | |
734 | gp_XYZ theOrig = PntInfoFirst.Pnt().XYZ() - offF * Axis.Direction().XYZ(); | |
735 | gp_Pnt p2_ao1(theOrig); | |
736 | gp_Ax2 a2_ao1(p2_ao1, Axis.Direction()); | |
737 | BRepPrim_Cylinder theCylinder(a2_ao1, Radius, Heigth + offF + offL); | |
738 | Cyl = theCylinder.Shell(); | |
739 | CylTopF = theCylinder.TopFace(); | |
740 | CylBottF = theCylinder.BottomFace(); | |
741 | } |