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