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