0023876: New Boolean Operation algorithm works incorrect with cylinder made by revolu...
[occt.git] / src / BOPTools / BOPTools_AlgoTools.cxx
... / ...
CommitLineData
1// Created by: Peter KURNEV
2// Copyright (c) 2010-2012 OPEN CASCADE SAS
3// Copyright (c) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE
4// Copyright (c) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT,
5// EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6//
7// The content of this file is subject to the Open CASCADE Technology Public
8// License Version 6.5 (the "License"). You may not use the content of this file
9// except in compliance with the License. Please obtain a copy of the License
10// at http://www.opencascade.org and read it completely before using this file.
11//
12// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
13// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
14//
15// The Original Code and all software distributed under the License is
16// distributed on an "AS IS" basis, without warranty of any kind, and the
17// Initial Developer hereby disclaims all such warranties, including without
18// limitation, any warranties of merchantability, fitness for a particular
19// purpose or non-infringement. Please see the License for the specific terms
20// and conditions governing the rights and limitations under the License.
21
22
23#include <BOPTools_AlgoTools.ixx>
24//
25#include <Precision.hxx>
26//
27#include <gp_Pnt.hxx>
28#include <gp_XYZ.hxx>
29#include <gp_Pnt2d.hxx>
30//
31#include <Geom2d_Curve.hxx>
32#include <Geom_Surface.hxx>
33#include <Geom_TrimmedCurve.hxx>
34#include <Geom_Curve.hxx>
35#include <GeomAPI_ProjectPointOnSurf.hxx>
36#include <Geom2dInt_Geom2dCurveTool.hxx>
37//
38#include <TopAbs_Orientation.hxx>
39//
40#include <TopoDS_Compound.hxx>
41#include <TopoDS_CompSolid.hxx>
42#include <TopoDS_Solid.hxx>
43#include <TopoDS_Shell.hxx>
44#include <TopoDS_Wire.hxx>
45//
46#include <BRep_Builder.hxx>
47#include <BRep_Tool.hxx>
48#include <BRepLib.hxx>
49#include <BRepAdaptor_Curve2d.hxx>
50#include <BRepClass3d_SolidClassifier.hxx>
51#include <TopExp.hxx>
52#include <TopExp_Explorer.hxx>
53//
54#include <IntTools_Tools.hxx>
55//
56#include <BOPTools_AlgoTools2D.hxx>
57#include <BOPTools_AlgoTools3D.hxx>
58//
59#include <BOPCol_IndexedMapOfShape.hxx>
60#include <BOPCol_MapOfShape.hxx>
61//
62#include <BOPTools.hxx>
63#include <BOPTools_CoupleOfShape.hxx>
64#include <BOPTools_ListOfCoupleOfShape.hxx>
65#include <Geom_SurfaceOfLinearExtrusion.hxx>
66#include <GeomAdaptor_Surface.hxx>
67#include <gp_Cylinder.hxx>
68#include <Geom_CylindricalSurface.hxx>
69#include <gp_Lin.hxx>
70#include <BOPInt_ShrunkRange.hxx>
71
72static
73 Standard_Real AngleWithRef(const gp_Dir& theD1,
74 const gp_Dir& theD2,
75 const gp_Dir& theDRef);
76static
77 inline Standard_Real fsqrt(Standard_Real val);
78
79static
80 Standard_Boolean FindFacePairs (const TopoDS_Edge& theE,
81 const BOPCol_ListOfShape& thLF,
82 BOPTools_ListOfCoupleOfShape& theLCFF,
83 Handle(BOPInt_Context)& theContext);
84static
85 TopAbs_Orientation Orientation(const TopoDS_Edge& anE,
86 const TopoDS_Face& aF);
87
88
89
90//=======================================================================
91// function: MakeConnexityBlocks
92// purpose:
93//=======================================================================
94 void BOPTools_AlgoTools::MakeConnexityBlocks (const TopoDS_Shape& theS,
95 const TopAbs_ShapeEnum theType1,
96 const TopAbs_ShapeEnum theType2,
97 BOPCol_ListOfShape& theLCB)
98{
99 Standard_Integer aNbF, aNbAdd, aNbAdd1, i;
100 BRep_Builder aBB;
101 TopoDS_Compound aC;
102 TopoDS_Iterator aIt;
103 TopExp_Explorer aExp;
104 BOPCol_MapOfShape aMP;
105 BOPCol_IndexedMapOfShape aMCB, aMAdd, aMAdd1;
106 BOPCol_IndexedDataMapOfShapeListOfShape aMEF;
107 BOPCol_ListIteratorOfListOfShape aItLF;
108 //
109 // 1. aMEF
110 BOPTools::MapShapesAndAncestors(theS, theType1, theType2, aMEF);
111 //
112 // 2. aMCB
113 aIt.Initialize(theS);
114 for (; aIt.More(); aIt.Next()) {
115 const TopoDS_Shape& aF1=aIt.Value();
116 if (aMP.Contains(aF1)) {
117 continue;
118 }
119 //
120 aMCB.Clear();
121 aMAdd.Clear();
122 aMAdd.Add(aF1);
123 //
124 while(1) {
125 aMAdd1.Clear();
126 //
127 aNbAdd = aMAdd.Extent();
128 for (i=1; i<=aNbAdd; ++i) {
129 const TopoDS_Shape& aF=aMAdd(i);
130 //
131 aExp.Init(aF, theType1);
132 for (; aExp.More(); aExp.Next()) {
133 const TopoDS_Shape& aE=aExp.Current();
134 //
135 const BOPCol_ListOfShape& aLF=aMEF.FindFromKey(aE);
136 aItLF.Initialize(aLF);
137 for (; aItLF.More(); aItLF.Next()) {
138 const TopoDS_Shape& aFx=aItLF.Value();
139 if (aFx.IsSame(aF)) {
140 continue;
141 }
142 if (aMCB.Contains(aFx)) {
143 continue;
144 }
145 aMAdd1.Add(aFx);
146 }
147 }//for (; aExp.More(); aExp.Next()){
148 aMCB.Add(aF);
149 }// for (i=1; i<=aNbAdd; ++i) {
150 //
151 aNbAdd1=aMAdd1.Extent();
152 if (!aNbAdd1) {
153 break;// ->make new CB from aMCB
154 }
155 //
156 aMAdd.Clear();
157 for (i=1; i<=aNbAdd1; ++i) {
158 const TopoDS_Shape& aFAdd = aMAdd1(i);
159 aMAdd.Add(aFAdd);
160 }
161 }//while(1) {
162 //
163 aNbF=aMCB.Extent();
164 if (aNbF) {
165 aBB.MakeCompound(aC);
166 //
167 for (i=1; i<=aNbF; ++i) {
168 const TopoDS_Shape& aF=aMCB(i);
169 aBB.Add(aC, aF);
170 aMP.Add(aF);
171 }
172 theLCB.Append(aC);
173 }
174 }// for (; aIt.More(); aIt.Next())
175}
176//=======================================================================
177// function: OrientFacesOnShell
178// purpose:
179//=======================================================================
180 void BOPTools_AlgoTools::OrientFacesOnShell (TopoDS_Shape& aShell)
181{
182 Standard_Boolean bIsProcessed1, bIsProcessed2;
183 Standard_Integer i, aNbE, aNbF, j;
184 TopAbs_Orientation anOrE1, anOrE2;
185 TopoDS_Face aF1x, aF2x;
186 TopoDS_Shape aShellNew;
187 BOPCol_IndexedDataMapOfShapeListOfShape aEFMap;
188 BOPCol_IndexedMapOfShape aProcessedFaces;
189 BRep_Builder aBB;
190 //
191 BOPTools_AlgoTools::MakeContainer(TopAbs_SHELL, aShellNew);
192 //
193 BOPTools::MapShapesAndAncestors(aShell, TopAbs_EDGE, TopAbs_FACE, aEFMap);
194 aNbE=aEFMap.Extent();
195 //
196 // One seam edge in aEFMap contains 2 equivalent faces.
197 for (i=1; i<=aNbE; ++i) {
198 BOPCol_ListOfShape& aLF=aEFMap.ChangeFromIndex(i);
199 aNbF=aLF.Extent();
200 if (aNbF>1) {
201 BOPCol_ListOfShape aLFTmp;
202 BOPCol_IndexedMapOfShape aFM;
203 //
204 BOPCol_ListIteratorOfListOfShape anIt(aLF);
205 for (; anIt.More(); anIt.Next()) {
206 const TopoDS_Shape& aF=anIt.Value();
207 if (!aFM.Contains(aF)) {
208 aFM.Add(aF);
209 aLFTmp.Append(aF);
210 }
211 }
212 aLF.Clear();
213 aLF=aLFTmp;
214 }
215 }
216 //
217 // Do
218 for (i=1; i<=aNbE; ++i) {
219 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aEFMap.FindKey(i)));
220 if (BRep_Tool::Degenerated(aE)) {
221 continue;
222 }
223 //
224 const BOPCol_ListOfShape& aLF=aEFMap.FindFromIndex(i);
225 aNbF=aLF.Extent();
226 if (aNbF!=2) {
227 continue;
228 }
229 //
230 TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First()));
231 TopoDS_Face& aF2=(*(TopoDS_Face*)(&aLF.Last()));
232 //
233 bIsProcessed1=aProcessedFaces.Contains(aF1);
234 bIsProcessed2=aProcessedFaces.Contains(aF2);
235 if (bIsProcessed1 && bIsProcessed2) {
236 continue;
237 }
238
239 if (!bIsProcessed1 && !bIsProcessed2) {
240 aProcessedFaces.Add(aF1);
241 aBB.Add(aShellNew, aF1);
242 bIsProcessed1=!bIsProcessed1;
243 }
244 //
245 aF1x=aF1;
246 if (bIsProcessed1) {
247 j=aProcessedFaces.FindIndex(aF1);
248 aF1x=(*(TopoDS_Face*)(&aProcessedFaces.FindKey(j)));
249 }
250 //
251 aF2x=aF2;
252 if (bIsProcessed2) {
253 j=aProcessedFaces.FindIndex(aF2);
254 aF2x=(*(TopoDS_Face*)(&aProcessedFaces.FindKey(j)));
255 }
256 //
257 anOrE1=Orientation(aE, aF1x);
258 anOrE2=Orientation(aE, aF2x);
259 //
260 if (bIsProcessed1 && !bIsProcessed2) {
261 if (anOrE1==anOrE2) {
262 if (!BRep_Tool::IsClosed(aE, aF1) &&
263 !BRep_Tool::IsClosed(aE, aF2)) {
264 aF2.Reverse();
265 }
266 }
267 aProcessedFaces.Add(aF2);
268 aBB.Add(aShellNew, aF2);
269 }
270 else if (!bIsProcessed1 && bIsProcessed2) {
271 if (anOrE1==anOrE2) {
272 if (!BRep_Tool::IsClosed(aE, aF1) &&
273 !BRep_Tool::IsClosed(aE, aF2)) {
274 aF1.Reverse();
275 }
276 }
277 aProcessedFaces.Add(aF1);
278 aBB.Add(aShellNew, aF1);
279 }
280 }
281 //
282 //
283 for (i=1; i<=aNbE; ++i) {
284 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aEFMap.FindKey(i)));
285 if (BRep_Tool::Degenerated(aE)) {
286 continue;
287 }
288 //
289 const BOPCol_ListOfShape& aLF=aEFMap.FindFromIndex(i);
290 aNbF=aLF.Extent();
291 if (aNbF!=2) {
292 BOPCol_ListIteratorOfListOfShape anIt(aLF);
293 for(; anIt.More(); anIt.Next()) {
294 const TopoDS_Face& aF=(*(TopoDS_Face*)(&anIt.Value()));
295 if (!aProcessedFaces.Contains(aF)) {
296 aProcessedFaces.Add(aF);
297 aBB.Add(aShellNew, aF);
298 }
299 }
300 }
301 }
302 aShell=aShellNew;
303}
304//=======================================================================
305//function : Orientation
306//purpose :
307//=======================================================================
308 TopAbs_Orientation Orientation(const TopoDS_Edge& anE,
309 const TopoDS_Face& aF)
310{
311 TopAbs_Orientation anOr=TopAbs_INTERNAL;
312
313 TopExp_Explorer anExp;
314 anExp.Init(aF, TopAbs_EDGE);
315 for (; anExp.More(); anExp.Next()) {
316 const TopoDS_Edge& anEF1=(*(TopoDS_Edge*)(&anExp.Current()));
317 if (anEF1.IsSame(anE)) {
318 anOr=anEF1.Orientation();
319 break;
320 }
321 }
322 return anOr;
323}
324
325////////////
326
327
328//=======================================================================
329// function: MakeConnexityBlock.
330// purpose:
331//=======================================================================
332 void BOPTools_AlgoTools::MakeConnexityBlock (BOPCol_ListOfShape& theLFIn,
333 BOPCol_IndexedMapOfShape& theMEAvoid,
334 BOPCol_ListOfShape& theLCB,
335 const Handle(NCollection_BaseAllocator)& theAllocator)
336{
337 Standard_Integer aNbF, aNbAdd1, aNbAdd, i;
338 TopExp_Explorer aExp;
339 BOPCol_ListIteratorOfListOfShape aIt;
340 //
341 BOPCol_IndexedMapOfShape aMCB(100, theAllocator);
342 BOPCol_IndexedMapOfShape aMAdd(100, theAllocator);
343 BOPCol_IndexedMapOfShape aMAdd1(100, theAllocator);
344 BOPCol_IndexedDataMapOfShapeListOfShape aMEF(100, theAllocator);
345 //
346 // 1. aMEF
347 aNbF=theLFIn.Extent();
348 aIt.Initialize(theLFIn);
349 for (; aIt.More(); aIt.Next()) {
350 const TopoDS_Shape& aF=aIt.Value();
351 BOPTools::MapShapesAndAncestors(aF, TopAbs_EDGE, TopAbs_FACE, aMEF);
352 }
353 //
354 // 2. aMCB
355 const TopoDS_Shape& aF1=theLFIn.First();
356 aMAdd.Add(aF1);
357 //
358 while(1) {
359 aMAdd1.Clear();
360 aNbAdd = aMAdd.Extent();
361 for (i=1; i<=aNbAdd; ++i) {
362 const TopoDS_Shape& aF=aMAdd(i);
363 //
364 //aMAdd1.Clear();
365 aExp.Init(aF, TopAbs_EDGE);
366 for (; aExp.More(); aExp.Next()) {
367 const TopoDS_Shape& aE=aExp.Current();
368 if (theMEAvoid.Contains(aE)){
369 continue;
370 }
371 //
372 const BOPCol_ListOfShape& aLF=aMEF.FindFromKey(aE);
373 aIt.Initialize(aLF);
374 for (; aIt.More(); aIt.Next()) {
375 const TopoDS_Shape& aFx=aIt.Value();
376 if (aFx.IsSame(aF)) {
377 continue;
378 }
379 if (aMCB.Contains(aFx)) {
380 continue;
381 }
382 aMAdd1.Add(aFx);
383 }
384 }//for (; aExp.More(); aExp.Next()){
385 aMCB.Add(aF);
386 }// for (i=1; i<=aNbAdd; ++i) {
387 //
388 aNbAdd1=aMAdd1.Extent();
389 if (!aNbAdd1) {
390 break;
391 }
392 //
393 aMAdd.Clear();
394 for (i=1; i<=aNbAdd1; ++i) {
395 const TopoDS_Shape& aFAdd=aMAdd1(i);
396 aMAdd.Add(aFAdd);
397 }
398 //
399 }//while(1) {
400
401 //
402 aNbF=aMCB.Extent();
403 for (i=1; i<=aNbF; ++i) {
404 const TopoDS_Shape& aF=aMCB(i);
405 theLCB.Append(aF);
406 }
407}
408//=======================================================================
409// function: ComputeStateByOnePoint
410// purpose:
411//=======================================================================
412 TopAbs_State BOPTools_AlgoTools::ComputeStateByOnePoint(const TopoDS_Shape& theS,
413 const TopoDS_Solid& theRef,
414 const Standard_Real theTol,
415 Handle(BOPInt_Context)& theContext)
416{
417 TopAbs_State aState;
418 TopAbs_ShapeEnum aType;
419 //
420 aState=TopAbs_UNKNOWN;
421 aType=theS.ShapeType();
422 if (aType==TopAbs_VERTEX) {
423 const TopoDS_Vertex& aV=(*(TopoDS_Vertex*)(&theS));
424 aState=BOPTools_AlgoTools::ComputeState(aV, theRef, theTol, theContext);
425 }
426 else if (aType==TopAbs_EDGE) {
427 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&theS));
428 aState=BOPTools_AlgoTools::ComputeState(aE, theRef, theTol, theContext);
429 }
430 return aState;
431}
432
433//=======================================================================
434// function: ComputeState
435// purpose:
436//=======================================================================
437 TopAbs_State BOPTools_AlgoTools::ComputeState(const TopoDS_Face& theF,
438 const TopoDS_Solid& theRef,
439 const Standard_Real theTol,
440 BOPCol_IndexedMapOfShape& theBounds,
441 Handle(BOPInt_Context)& theContext)
442{
443 TopAbs_State aState;
444 TopExp_Explorer aExp;
445 TopoDS_Edge aE1;
446 gp_Pnt2d aP2D;
447 gp_Pnt aP3D;
448 //
449 aState=TopAbs_UNKNOWN;
450 //
451 aExp.Init(theF, TopAbs_EDGE);
452 for (; aExp.More(); aExp.Next()) {
453 const TopoDS_Edge& aSE=(*(TopoDS_Edge*)(&aExp.Current()));
454 if (BRep_Tool::Degenerated(aSE)) {
455 continue;
456 }
457 //
458 if (!theBounds.Contains(aSE)) {
459 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aSE));
460 aState=BOPTools_AlgoTools::ComputeState(aE, theRef, theTol, theContext);
461 return aState;
462 }
463 if (aE1.IsNull()) {
464 aE1=(*(TopoDS_Edge*)(&aSE));
465 }
466 }
467 // !!<- process edges that are all on theRef
468 if (!aE1.IsNull()) {
469 BOPTools_AlgoTools3D::PointNearEdge(aE1, theF, aP2D, aP3D, theContext);
470 aState=BOPTools_AlgoTools::ComputeState(aP3D, theRef, theTol, theContext);
471 }
472 //
473 return aState;
474}
475//=======================================================================
476// function: ComputeState
477// purpose:
478//=======================================================================
479 TopAbs_State BOPTools_AlgoTools::ComputeState(const TopoDS_Vertex& theV,
480 const TopoDS_Solid& theRef,
481 const Standard_Real theTol,
482 Handle(BOPInt_Context)& theContext)
483{
484 TopAbs_State aState;
485 gp_Pnt aP3D;
486 //
487 aP3D=BRep_Tool::Pnt(theV);
488 aState=BOPTools_AlgoTools::ComputeState(aP3D, theRef, theTol, theContext);
489 return aState;
490}
491//=======================================================================
492// function: ComputeState
493// purpose:
494//=======================================================================
495 TopAbs_State BOPTools_AlgoTools::ComputeState(const TopoDS_Edge& theE,
496 const TopoDS_Solid& theRef,
497 const Standard_Real theTol,
498 Handle(BOPInt_Context)& theContext)
499{
500 Standard_Real aT1, aT2, aT = 0.;
501 TopAbs_State aState;
502 Handle(Geom_Curve) aC3D;
503 gp_Pnt aP3D;
504 //
505 aC3D = BRep_Tool::Curve(theE, aT1, aT2);
506 //
507 if(aC3D.IsNull()) {
508 //it means that we are in degenerated edge
509 const TopoDS_Vertex& aV = TopExp::FirstVertex(theE);
510 if(aV.IsNull()){
511 return TopAbs_UNKNOWN;
512 }
513 aP3D=BRep_Tool::Pnt(aV);
514 }
515 else {//usual case
516 Standard_Boolean bF2Inf, bL2Inf;
517 Standard_Real dT=10.;
518 //
519 bF2Inf = Precision::IsNegativeInfinite(aT1);
520 bL2Inf = Precision::IsPositiveInfinite(aT2);
521 //
522 if (bF2Inf && !bL2Inf) {
523 aT=aT2-dT;
524 }
525 else if (!bF2Inf && bL2Inf) {
526 aT=aT1+dT;
527 }
528 else if (bF2Inf && bL2Inf) {
529 aT=0.;
530 }
531 else {
532 aT=IntTools_Tools::IntermediatePoint(aT1, aT2);
533 }
534 aC3D->D0(aT, aP3D);
535 }
536 //
537 aState=BOPTools_AlgoTools::ComputeState(aP3D, theRef, theTol, theContext);
538 //
539 return aState;
540}
541//=======================================================================
542// function: ComputeState
543// purpose:
544//=======================================================================
545 TopAbs_State BOPTools_AlgoTools::ComputeState(const gp_Pnt& theP,
546 const TopoDS_Solid& theRef,
547 const Standard_Real theTol,
548 Handle(BOPInt_Context)& theContext)
549{
550 TopAbs_State aState;
551 //
552 BRepClass3d_SolidClassifier& aSC=theContext->SolidClassifier(theRef);
553 aSC.Perform(theP, theTol);
554 //
555 aState=aSC.State();
556 //
557 return aState;
558}
559//=======================================================================
560//function : IsInternalFace
561//purpose :
562//=======================================================================
563 Standard_Boolean BOPTools_AlgoTools::IsInternalFace(const TopoDS_Face& theFace,
564 const TopoDS_Solid& theSolid,
565 BOPCol_IndexedDataMapOfShapeListOfShape& theMEF,
566 const Standard_Real theTol,
567 Handle(BOPInt_Context)& theContext)
568{
569 Standard_Boolean bRet, bDegenerated;
570 Standard_Integer aNbF;
571 TopAbs_Orientation aOr;
572 TopoDS_Edge aEL;
573 TopExp_Explorer aExp;
574 BOPCol_ListIteratorOfListOfShape aItF;
575 //
576 bRet=Standard_False;
577 //
578 // 1 Try to find an edge from theFace in theMEF
579 aExp.Init(theFace, TopAbs_EDGE);
580 for(; aExp.More(); aExp.Next()) {
581 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
582 if (!theMEF.Contains(aE)) {
583 continue;
584 }
585 //
586 aOr=aE.Orientation();
587 if (aOr==TopAbs_INTERNAL) {
588 continue;
589 }
590 bDegenerated=BRep_Tool::Degenerated(aE);
591 if (bDegenerated){
592 continue;
593 }
594 // aE
595 BOPCol_ListOfShape& aLF=theMEF.ChangeFromKey(aE);
596 aNbF=aLF.Extent();
597 if (!aNbF) {
598 return bRet; // it can not be so
599 }
600 else if (aNbF==1) {
601 // aE is internal edge on aLF.First()
602 const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First()));
603 bRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aF1, aF1, theContext);
604 return bRet;
605 }
606 else if (aNbF==2) {
607 const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First()));
608 const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aLF.Last()));
609 //
610 if (aF2.IsSame(aF1) && BRep_Tool::IsClosed(aE, aF1)) {
611 // treat as it was for 1 face
612 bRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aF1, aF2, theContext);
613 return bRet;
614 }
615 }
616 if (aNbF%2) {
617 return bRet; // it can not be so
618 }
619 else { // aNbF=2,4,6,8,...
620 bRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aLF, theContext);
621 return bRet;
622 }
623 }//for(; aExp.More(); aExp.Next()) {
624 //
625 //========================================
626 // 2. Classify face using classifier
627 //
628 TopAbs_State aState;
629 BOPCol_IndexedMapOfShape aBounds;
630 //
631 aState=BOPTools_AlgoTools::ComputeState(theFace, theSolid, theTol, aBounds, theContext);
632 bRet=(aState==TopAbs_IN);
633 //
634 return bRet;
635}
636//=======================================================================
637//function : IsInternalFace
638//purpose :
639//=======================================================================
640 Standard_Boolean BOPTools_AlgoTools::IsInternalFace(const TopoDS_Face& theFace,
641 const TopoDS_Edge& theEdge,
642 BOPCol_ListOfShape& theLF,
643 Handle(BOPInt_Context)& theContext)
644{
645 Standard_Boolean bRet;
646 Standard_Boolean aNbF;
647 //
648 bRet=Standard_False;
649 //
650 aNbF=theLF.Extent();
651 if (aNbF==2) {
652 const TopoDS_Face& aF1=(*(TopoDS_Face*)(&theLF.First()));
653 const TopoDS_Face& aF2=(*(TopoDS_Face*)(&theLF.Last()));
654 bRet=BOPTools_AlgoTools::IsInternalFace(theFace, theEdge, aF1, aF2, theContext);
655 return bRet;
656 }
657 //
658 else {
659 BOPTools_ListOfCoupleOfShape aLCFF;
660 BOPTools_ListIteratorOfListOfCoupleOfShape aIt;
661 //
662 FindFacePairs(theEdge, theLF, aLCFF, theContext);
663 //
664 aIt.Initialize(aLCFF);
665 for (; aIt.More(); aIt.Next()) {
666 BOPTools_CoupleOfShape& aCSFF=aIt.ChangeValue();
667 //
668 const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aCSFF.Shape1()));
669 const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aCSFF.Shape2()));
670 bRet=BOPTools_AlgoTools::IsInternalFace(theFace, theEdge, aF1, aF2, theContext);
671 if (bRet) {
672 return bRet;
673 }
674 }
675 }
676 return bRet;
677}
678//=======================================================================
679//function : IsInternalFace
680//purpose :
681//=======================================================================
682 Standard_Boolean BOPTools_AlgoTools::IsInternalFace(const TopoDS_Face& theFace,
683 const TopoDS_Edge& theEdge,
684 const TopoDS_Face& theFace1,
685 const TopoDS_Face& theFace2,
686 Handle(BOPInt_Context)& theContext)
687{
688 Standard_Boolean bRet;
689 TopoDS_Edge aE1, aE2;
690 TopoDS_Face aFOff;
691 BOPTools_ListOfCoupleOfShape theLCSOff;
692 BOPTools_CoupleOfShape aCS1, aCS2;
693 //
694 BOPTools_AlgoTools::GetEdgeOnFace(theEdge, theFace1, aE1);
695 if (aE1.Orientation()==TopAbs_INTERNAL) {
696 aE2=aE1;
697 aE1.Orientation(TopAbs_FORWARD);
698 aE2.Orientation(TopAbs_REVERSED);
699 }
700 else if (theFace1==theFace2) {
701 aE2=aE1;
702 aE1.Orientation(TopAbs_FORWARD);
703 aE2.Orientation(TopAbs_REVERSED);
704 }
705 else {
706 BOPTools_AlgoTools::GetEdgeOnFace(theEdge, theFace2, aE2);
707 }
708 //
709 aCS1.SetShape1(theEdge);
710 aCS1.SetShape2(theFace);
711 theLCSOff.Append(aCS1);
712 //
713 aCS2.SetShape1(aE2);
714 aCS2.SetShape2(theFace2);
715 theLCSOff.Append(aCS2);
716 //
717 GetFaceOff(aE1, theFace1, theLCSOff, aFOff, theContext);
718 //
719 bRet = theFace.IsEqual(aFOff);
720 return bRet;
721}
722//=======================================================================
723//function : GetFaceOff
724//purpose :
725//=======================================================================
726 void BOPTools_AlgoTools::GetFaceOff(const TopoDS_Edge& theE1,
727 const TopoDS_Face& theF1,
728 BOPTools_ListOfCoupleOfShape& theLCSOff,
729 TopoDS_Face& theFOff,
730 Handle(BOPInt_Context)& theContext)
731{
732 Standard_Real aT, aT1, aT2, aAngle, aTwoPI, aAngleMin;
733 gp_Pnt aPn1, aPn2, aPx;
734 gp_Vec aVTgt;
735 gp_Dir aDN1, aDN2;
736 Handle(Geom_Curve)aC3D;
737 BOPTools_ListIteratorOfListOfCoupleOfShape aIt;
738 //
739 aAngleMin=100.;
740 aTwoPI=M_PI+M_PI;
741 aC3D =BRep_Tool::Curve(theE1, aT1, aT2);
742 //BRep_Tool::Range(theE1, aT1, aT2);
743 aT=BOPTools_AlgoTools2D::IntermediatePoint(aT1, aT2);
744 aC3D->D0(aT, aPx);
745 // Ref
746 BOPTools_AlgoTools2D::EdgeTangent(theE1, aT, aVTgt);
747 gp_Dir aDTtgt(aVTgt);
748 aDTtgt.Reverse();
749 Handle(Geom_Plane) aPL;
750 aPL = new Geom_Plane(aPx, aDTtgt);
751 // N1
752 BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge(theE1, theF1, aT, aPn1, aDN1, theContext);
753 //
754 gp_Pnt aPFx, aPF2x;
755 CorrectPoint(aPn1, aPL, aPFx);
756 gp_Vec aVBF (aPx, aPFx );
757 gp_Dir aDTF;
758 gp_Dir aDBF (aVBF);
759 aDTF=aDN1^aDBF;
760 //
761 aIt.Initialize(theLCSOff);
762 for (; aIt.More(); aIt.Next()) {
763 const BOPTools_CoupleOfShape& aCS=aIt.Value();
764 const TopoDS_Edge& aE2=(*(TopoDS_Edge*)(&aCS.Shape1()));
765 const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aCS.Shape2()));
766 //
767 /*if (aF2==theF1) {
768 aAngle=M_PI;
769 }
770 else if (aF2.IsSame(theF1)) {
771 aAngle=aTwoPI;
772 }
773 else {*/
774 if (!theE1.IsEqual(aE2) ||
775 !GetProjectPoint(theF1, aPn1, aF2, aPn2, aDN2, theContext)) {
776 BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge (aE2, aF2, aT, aPn2, aDN2, theContext);
777 }
778 CorrectPoint(aPn2, aPL, aPF2x);
779 gp_Vec aVBF2(aPx, aPF2x);
780 gp_Dir aDBF2(aVBF2);
781 //Angle
782 aAngle=AngleWithRef(aDBF, aDBF2, aDTF);
783 //
784 if(aAngle<0.) {
785 aAngle=aTwoPI+aAngle;
786 }
787 //}
788
789 if (aAngle<aAngleMin){
790 aAngleMin=aAngle;
791 theFOff=aF2;
792 }
793 }
794}
795//=======================================================================
796//function : GetEdgeOff
797//purpose :
798//=======================================================================
799 Standard_Boolean BOPTools_AlgoTools::GetEdgeOff(const TopoDS_Edge& theE1,
800 const TopoDS_Face& theF2,
801 TopoDS_Edge& theE2)
802{
803 Standard_Boolean bFound;
804 TopAbs_Orientation aOr1, aOr1C, aOr2;
805 TopExp_Explorer anExp;
806 //
807 bFound=Standard_False;
808 aOr1=theE1.Orientation();
809 aOr1C=TopAbs::Reverse(aOr1);
810 //
811 anExp.Init(theF2, TopAbs_EDGE);
812 for (; anExp.More(); anExp.Next()) {
813 const TopoDS_Edge& aEF2=(*(TopoDS_Edge*)(&anExp.Current()));
814 if (aEF2.IsSame(theE1)) {
815 aOr2=aEF2.Orientation();
816 if (aOr2==aOr1C) {
817 theE2=aEF2;
818 bFound=!bFound;
819 return bFound;
820 }
821 }
822 }
823 return bFound;
824}
825
826//=======================================================================
827//function : AreFacesSameDomain
828//purpose :
829//=======================================================================
830 Standard_Boolean BOPTools_AlgoTools::AreFacesSameDomain(const TopoDS_Face& theF1,
831 const TopoDS_Face& theF2,
832 Handle(BOPInt_Context)& theContext)
833{
834 Standard_Boolean bFlag;
835 Standard_Integer iP;
836 Standard_Real aTolF1, aTolF2, aTol;
837 gp_Pnt2d aP2D;
838 gp_Pnt aP;
839 TopoDS_Face aF1, aF2;
840 TopoDS_Edge aE1;
841 TopExp_Explorer aExp;
842 //
843 bFlag=Standard_False;
844 //
845 aF1=theF1;
846 aF1.Orientation(TopAbs_FORWARD);
847 aF2=theF2;
848 aF2.Orientation(TopAbs_FORWARD);
849 //
850 aTolF1=BRep_Tool::Tolerance(aF1);
851 // 1
852 iP=0;
853 aExp.Init(aF1, TopAbs_EDGE);
854 for (; aExp.More(); aExp.Next()) {
855 aE1=(*(TopoDS_Edge*)(&aExp.Current()));
856 if (!BRep_Tool::Degenerated(aE1)) {
857 iP=1;
858 //break;
859 Standard_Real aTolE = BRep_Tool::Tolerance(aE1);
860 aTolF1 = (aTolE > aTolF1) ? aTolE : aTolF1;
861 }
862 }
863 if (!iP) {
864 return bFlag;
865 }
866 //
867 // 2
868 aTolF2=BRep_Tool::Tolerance(aF2);
869 aTol=aTolF1+aTolF2;
870 //
871 BOPTools_AlgoTools3D::PointNearEdge(aE1, aF1, aP2D, aP, theContext);
872 bFlag=theContext->IsValidPointForFace(aP, aF2, aTol);
873 //
874 return bFlag;
875}
876
877//=======================================================================
878//function : CheckSameGeom
879//purpose :
880//=======================================================================
881 Standard_Boolean BOPTools_AlgoTools::CheckSameGeom(const TopoDS_Face& theF1,
882 const TopoDS_Face& theF2,
883 Handle(BOPInt_Context)& theContext)
884{
885 Standard_Boolean bRet;
886 Standard_Real aTolF1, aTolF2, aTol;
887 gp_Pnt2d aP2D;
888 gp_Pnt aP;
889 TopExp_Explorer aExp;
890 //
891 bRet=Standard_False;
892 aExp.Init(theF1, TopAbs_EDGE);
893 for (; aExp.More(); aExp.Next()) {
894 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
895 if (!BRep_Tool::Degenerated(aE)) {
896 aTolF1=BRep_Tool::Tolerance(theF1);
897 aTolF2=BRep_Tool::Tolerance(theF2);
898 aTol=aTolF1+aTolF2;
899 BOPTools_AlgoTools3D::PointNearEdge(aE, theF1, aP2D, aP, theContext);
900 bRet=theContext->IsValidPointForFace(aP, theF2, aTol);
901 break;
902 }
903 }
904 return bRet;
905}
906//=======================================================================
907// function: Sense
908// purpose:
909//=======================================================================
910 Standard_Integer BOPTools_AlgoTools::Sense (const TopoDS_Face& theF1,
911 const TopoDS_Face& theF2)
912{
913 Standard_Integer iSense=0;
914 gp_Dir aDNF1, aDNF2;
915 TopoDS_Edge aE1, aE2;
916 TopExp_Explorer aExp;
917 //
918 aExp.Init(theF1, TopAbs_EDGE);
919 for (; aExp.More(); aExp.Next()) {
920 aE1=(*(TopoDS_Edge*)(&aExp.Current()));
921 if (!BRep_Tool::Degenerated(aE1)) {
922 if (!BRep_Tool::IsClosed(aE1, theF1)) {
923 break;
924 }
925 }
926 }
927 //
928 aExp.Init(theF2, TopAbs_EDGE);
929 for (; aExp.More(); aExp.Next()) {
930 aE2=(*(TopoDS_Edge*)(&aExp.Current()));
931 if (!BRep_Tool::Degenerated(aE2)) {
932 if (!BRep_Tool::IsClosed(aE2, theF2)) {
933 if (aE2.IsSame(aE1)) {
934 iSense=1;
935 break;
936 }
937 }
938 }
939 }
940 //
941 if (!iSense) {
942 return iSense;
943 }
944 //
945 BOPTools_AlgoTools3D::GetNormalToFaceOnEdge(aE1, theF1, aDNF1);
946 BOPTools_AlgoTools3D::GetNormalToFaceOnEdge(aE2, theF2, aDNF2);
947 //
948 iSense=BOPTools_AlgoTools3D::SenseFlag(aDNF1, aDNF2);
949 //
950 return iSense;
951}
952//=======================================================================
953// function: IsSplitToReverse
954// purpose:
955//=======================================================================
956 Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse(const TopoDS_Shape& theSp,
957 const TopoDS_Shape& theSr,
958 Handle(BOPInt_Context)& theContext)
959{
960 Standard_Boolean bRet;
961 TopAbs_ShapeEnum aType;
962 //
963 bRet=Standard_False;
964 //
965 aType=theSp.ShapeType();
966 switch (aType) {
967 case TopAbs_EDGE: {
968 const TopoDS_Edge& aESp=(*(TopoDS_Edge*)(&theSp));
969 const TopoDS_Edge& aESr=(*(TopoDS_Edge*)(&theSr));
970 bRet=BOPTools_AlgoTools::IsSplitToReverse(aESp, aESr, theContext);
971 }
972 break;
973 //
974 case TopAbs_FACE: {
975 const TopoDS_Face& aFSp=(*(TopoDS_Face*)(&theSp));
976 const TopoDS_Face& aFSr=(*(TopoDS_Face*)(&theSr));
977 bRet=BOPTools_AlgoTools::IsSplitToReverse(aFSp, aFSr, theContext);
978 }
979 break;
980 //
981 default:
982 break;
983 }
984 return bRet;
985}
986//=======================================================================
987//function :IsSplitToReverse
988//purpose :
989//=======================================================================
990 Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse(const TopoDS_Face& theFSp,
991 const TopoDS_Face& theFSr,
992 Handle(BOPInt_Context)& theContext)
993{
994 Standard_Boolean bRet, bFound, bInFace;
995 Standard_Real aT1, aT2, aT, aU, aV, aScPr;
996 gp_Pnt aPFSp, aPFSr;
997 gp_Dir aDNFSp;
998 gp_Vec aD1U, aD1V;
999 Handle(Geom_Surface) aSr, aSp;
1000 TopAbs_Orientation aOrSr, aOrSp;
1001 TopExp_Explorer anExp;
1002 TopoDS_Edge aESp;
1003 //
1004 bRet=Standard_False;
1005 //
1006 aSr=BRep_Tool::Surface(theFSr);
1007 aSp=BRep_Tool::Surface(theFSp);
1008 if (aSr==aSp) {
1009 aOrSr=theFSr.Orientation();
1010 aOrSp=theFSp.Orientation();
1011 bRet=(aOrSr!=aOrSp);
1012 return bRet;
1013 }
1014 //
1015 bFound=Standard_False;
1016 anExp.Init(theFSp, TopAbs_EDGE);
1017 for (; anExp.More(); anExp.Next()) {
1018 aESp=(*(TopoDS_Edge*)(&anExp.Current()));
1019 if (!BRep_Tool::Degenerated(aESp)) {
1020 if (!BRep_Tool::IsClosed(aESp, theFSp)) {
1021 bFound=!bFound;
1022 break;
1023 }
1024 }
1025 }
1026 if (!bFound) {
1027 Standard_Boolean bFlag;
1028 Standard_Integer iErr;
1029 gp_Pnt2d aP2DFSp;
1030 //
1031 iErr=BOPTools_AlgoTools3D::PointInFace(theFSp, aPFSp, aP2DFSp, theContext);
1032 if (iErr) {
1033 return bRet;
1034 }
1035 //
1036 aP2DFSp.Coord(aU, aV);
1037 bFlag=BOPTools_AlgoTools3D::GetNormalToSurface(aSp, aU, aV, aDNFSp);
1038 if (!bFlag) {
1039 return bRet;
1040 }
1041 }
1042 else {
1043 BRep_Tool::Range(aESp, aT1, aT2);
1044 aT=BOPTools_AlgoTools2D::IntermediatePoint(aT1, aT2);
1045 BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge(aESp, theFSp, aT, aPFSp, aDNFSp, theContext);
1046 }
1047 //
1048 // Parts of theContext->ComputeVS(..)
1049 GeomAPI_ProjectPointOnSurf& aProjector=theContext->ProjPS(theFSr);
1050 aProjector.Perform(aPFSp);
1051 if (!aProjector.IsDone()) {
1052 return bRet;
1053 }
1054 //
1055 aProjector.LowerDistanceParameters(aU, aV);
1056 gp_Pnt2d aP2D(aU, aV);
1057 bInFace=theContext->IsPointInFace (theFSr, aP2D);
1058 if (!bInFace) {
1059 return bRet;
1060 }
1061 //
1062 aSr->D1(aU, aV, aPFSr, aD1U, aD1V);
1063 gp_Dir aDD1U(aD1U);
1064 gp_Dir aDD1V(aD1V);
1065 gp_Dir aDNFSr=aDD1U^aDD1V;
1066 if (theFSr.Orientation()==TopAbs_REVERSED){
1067 aDNFSr.Reverse();
1068 }
1069 //
1070 aScPr=aDNFSp*aDNFSr;
1071 bRet=(aScPr<0.);
1072 //
1073 return bRet;
1074}
1075//=======================================================================
1076//function :IsSplitToReverse
1077//purpose :
1078//=======================================================================
1079 Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse(const TopoDS_Edge& aEF1,
1080 const TopoDS_Edge& aEF2,
1081 Handle(BOPInt_Context)& theContext)
1082{
1083 Standard_Boolean bRet, bIsDegenerated;
1084 //
1085 bRet=Standard_False;
1086 bIsDegenerated=(BRep_Tool::Degenerated(aEF1) ||
1087 BRep_Tool::Degenerated(aEF2));
1088 if (bIsDegenerated) {
1089 return bRet;
1090 }
1091 //
1092 Standard_Real a, b;
1093 TopAbs_Orientation aOrE, aOrSp;
1094 Handle(Geom_Curve)aC1, aC2;
1095 //
1096 aC2=BRep_Tool::Curve(aEF2, a, b);
1097 aC1=BRep_Tool::Curve(aEF1, a, b);
1098 //
1099 if (aC1==aC2) {
1100 aOrE=aEF2.Orientation();
1101 aOrSp=aEF1.Orientation();
1102 bRet=(aOrE!=aOrSp);
1103 return bRet;
1104 }
1105 //
1106 Standard_Real aT1, aT2, aScPr;
1107 gp_Vec aV1, aV2;
1108 gp_Pnt aP;
1109 //
1110 aT1=BOPTools_AlgoTools2D::IntermediatePoint(a, b);
1111 aC1->D0(aT1, aP);
1112 BOPTools_AlgoTools2D::EdgeTangent(aEF1, aT1, aV1);
1113 gp_Dir aDT1(aV1);
1114 //
1115 theContext->ProjectPointOnEdge(aP, aEF2, aT2);
1116 //
1117 BOPTools_AlgoTools2D::EdgeTangent(aEF2, aT2, aV2);
1118 gp_Dir aDT2(aV2);
1119 //
1120 aScPr=aDT1*aDT2;
1121 bRet=(aScPr<0.);
1122 //
1123 return bRet;
1124}
1125
1126//=======================================================================
1127//function : IsHole
1128//purpose :
1129//=======================================================================
1130 Standard_Boolean BOPTools_AlgoTools::IsHole(const TopoDS_Shape& aW,
1131 const TopoDS_Shape& aFace)
1132{
1133 Standard_Boolean bIsHole;
1134 Standard_Integer i, aNbS;
1135 Standard_Real aT1, aT2, aS;
1136 Standard_Real aU1, aU2, aU, dU;
1137 Standard_Real aX1, aY1, aX0, aY0;
1138 TopAbs_Orientation aOr;
1139
1140 gp_Pnt2d aP2D0, aP2D1;
1141 Handle(Geom2d_Curve) aC2D;
1142 TopoDS_Face aF, aFF;
1143 TopoDS_Iterator aItW;
1144 //
1145 bIsHole=Standard_False;
1146 //
1147 aF=(*(TopoDS_Face *)(&aFace));
1148 aFF=aF;
1149 aFF.Orientation(TopAbs_FORWARD);
1150 //
1151 aS=0.;
1152 aItW.Initialize(aW);
1153 for (; aItW.More(); aItW.Next()) {
1154 const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&aItW.Value()));
1155 aOr=aE.Orientation();
1156 if (!(aOr==TopAbs_FORWARD ||
1157 aOr==TopAbs_REVERSED)) {
1158 continue;
1159 }
1160 //
1161 aC2D=BRep_Tool::CurveOnSurface(aE, aFF, aT1, aT2);
1162 if (aC2D.IsNull()) {
1163 break; //xx
1164 }
1165 //
1166 BRepAdaptor_Curve2d aBAC2D(aE, aFF);
1167 aNbS=Geom2dInt_Geom2dCurveTool::NbSamples(aBAC2D);
1168 if (aNbS>2) {
1169 aNbS*=4;
1170 }
1171 //
1172 dU=(aT2-aT1)/(Standard_Real)(aNbS-1);
1173 aU =aT1;
1174 aU1=aT1;
1175 aU2=aT2;
1176 if (aOr==TopAbs_REVERSED) {
1177 aU =aT2;
1178 aU1=aT2;
1179 aU2=aT1;
1180 dU=-dU;
1181 }
1182 //
1183 aC2D->D0(aU, aP2D0);
1184 for(i=2; i<=aNbS; i++) {
1185 aU=aU1+(i-1)*dU;
1186 aC2D->D0(aU, aP2D1);
1187 aP2D0.Coord(aX0, aY0);
1188 aP2D1.Coord(aX1, aY1);
1189 //
1190 aS=aS+(aY0+aY1)*(aX1-aX0);
1191 //
1192 aP2D0=aP2D1;
1193 }
1194 }//for (; aItW.More(); aItW.Next()) {
1195 bIsHole=(aS>0.);
1196 return bIsHole;
1197}
1198
1199//=======================================================================
1200// function: MakeContainer
1201// purpose:
1202//=======================================================================
1203 void BOPTools_AlgoTools::MakeContainer(const TopAbs_ShapeEnum theType,
1204 TopoDS_Shape& theC)
1205{
1206 BRep_Builder aBB;
1207 //
1208 switch(theType) {
1209 case TopAbs_COMPOUND:{
1210 TopoDS_Compound aC;
1211 aBB.MakeCompound(aC);
1212 theC=aC;
1213 }
1214 break;
1215 //
1216 case TopAbs_COMPSOLID:{
1217 TopoDS_CompSolid aCS;
1218 aBB.MakeCompSolid(aCS);
1219 theC=aCS;
1220 }
1221 break;
1222 //
1223 case TopAbs_SOLID:{
1224 TopoDS_Solid aSolid;
1225 aBB.MakeSolid(aSolid);
1226 theC=aSolid;
1227 }
1228 break;
1229 //
1230 //
1231 case TopAbs_SHELL:{
1232 TopoDS_Shell aShell;
1233 aBB.MakeShell(aShell);
1234 theC=aShell;
1235 }
1236 break;
1237 //
1238 case TopAbs_WIRE: {
1239 TopoDS_Wire aWire;
1240 aBB.MakeWire(aWire);
1241 theC=aWire;
1242 }
1243 break;
1244 //
1245 default:
1246 break;
1247 }
1248}
1249//=======================================================================
1250// function: MakePCurve
1251// purpose:
1252//=======================================================================
1253 void BOPTools_AlgoTools::MakePCurve(const TopoDS_Edge& aE,
1254 const TopoDS_Face& aF1,
1255 const TopoDS_Face& aF2,
1256 const IntTools_Curve& aIC,
1257 const Standard_Boolean bPC1,
1258 const Standard_Boolean bPC2)
1259
1260{
1261 Standard_Integer i;
1262 Standard_Real aTolE, aT1, aT2, aOutFirst, aOutLast, aOutTol;
1263 Handle(Geom2d_Curve) aC2D, aC2DA, aC2Dx1;
1264 TopoDS_Face aFFWD;
1265 BRep_Builder aBB;
1266 Standard_Boolean bPC;
1267 //
1268 aTolE=BRep_Tool::Tolerance(aE);
1269 //
1270 const Handle(Geom_Curve)& aC3DE=BRep_Tool::Curve(aE, aT1, aT2);
1271 Handle(Geom_TrimmedCurve)aC3DETrim=new Geom_TrimmedCurve(aC3DE, aT1, aT2);
1272 //
1273 for (i=0; i<2; ++i) {
1274 bPC = !i ? bPC1 : bPC2;
1275 if (!bPC) {
1276 continue;
1277 }
1278 //
1279 if (!i) {
1280 aFFWD=aF1;
1281 aC2Dx1=aIC.FirstCurve2d();
1282 }
1283 else {
1284 aFFWD=aF2;
1285 aC2Dx1=aIC.SecondCurve2d();
1286 }
1287 //
1288 aFFWD.Orientation(TopAbs_FORWARD);
1289 //
1290 aC2D=aC2Dx1;
1291 if (aC2D.IsNull()) {
1292 BOPTools_AlgoTools2D::BuildPCurveForEdgeOnFace(aE, aFFWD);
1293 BOPTools_AlgoTools2D::CurveOnSurface(aE, aFFWD, aC2D,
1294 aOutFirst, aOutLast,
1295 aOutTol);
1296 }
1297 //
1298 if (aC3DE->IsPeriodic()) {
1299 BOPTools_AlgoTools2D::AdjustPCurveOnFace(aFFWD, aT1, aT2, aC2D, aC2DA);
1300 }
1301 else {
1302 BOPTools_AlgoTools2D::AdjustPCurveOnFace(aFFWD, aC3DETrim, aC2D, aC2DA);
1303 }
1304 //
1305 aBB.UpdateEdge(aE, aC2DA, aFFWD, aTolE);
1306 //BRepLib::SameParameter(aE);
1307 }
1308 BRepLib::SameParameter(aE);
1309}
1310//=======================================================================
1311// function: MakeEdge
1312// purpose:
1313//=======================================================================
1314 void BOPTools_AlgoTools::MakeEdge(const IntTools_Curve& theIC,
1315 const TopoDS_Vertex& theV1,
1316 const Standard_Real theT1,
1317 const TopoDS_Vertex& theV2,
1318 const Standard_Real theT2,
1319 const Standard_Real theTolR3D,
1320 TopoDS_Edge& theE)
1321{
1322 Standard_Real aTolV;
1323 BRep_Builder aBB;
1324 //
1325 BOPTools_AlgoTools::MakeSectEdge (theIC, theV1, theT1, theV2, theT2, theE);
1326 //
1327 aBB.UpdateEdge(theE, theTolR3D);
1328 //
1329 aTolV=BRep_Tool::Tolerance(theV1);
1330 if (aTolV<theTolR3D) {
1331 aBB.UpdateVertex(theV1, theTolR3D);
1332 }
1333 //
1334 aTolV=BRep_Tool::Tolerance(theV2);
1335 if (aTolV<theTolR3D) {
1336 aBB.UpdateVertex(theV2, theTolR3D);
1337 }
1338}
1339//=======================================================================
1340// function: ComputeVV
1341// purpose:
1342//=======================================================================
1343 Standard_Integer BOPTools_AlgoTools::ComputeVV(const TopoDS_Vertex& aV1,
1344 const gp_Pnt& aP2,
1345 const Standard_Real aTolP2)
1346{
1347 Standard_Real aTolV1, aTolSum, aTolSum2, aD2;
1348 gp_Pnt aP1;
1349 //
1350 aTolV1=BRep_Tool::Tolerance(aV1);
1351
1352 aTolSum=aTolV1+aTolP2;
1353 aTolSum2=aTolSum*aTolSum;
1354 //
1355 aP1=BRep_Tool::Pnt(aV1);
1356 //
1357 aD2=aP1.SquareDistance(aP2);
1358 if (aD2>aTolSum2) {
1359 return 1;
1360 }
1361 return 0;
1362}
1363//=======================================================================
1364// function: ComputeVV
1365// purpose:
1366//=======================================================================
1367 Standard_Integer BOPTools_AlgoTools::ComputeVV(const TopoDS_Vertex& aV1,
1368 const TopoDS_Vertex& aV2)
1369{
1370 Standard_Real aTolV1, aTolV2, aTolSum, aTolSum2, aD2;
1371 gp_Pnt aP1, aP2;
1372 //
1373 aTolV1=BRep_Tool::Tolerance(aV1);
1374 aTolV2=BRep_Tool::Tolerance(aV2);
1375 aTolSum=aTolV1+aTolV2;
1376 aTolSum2=aTolSum*aTolSum;
1377 //
1378 aP1=BRep_Tool::Pnt(aV1);
1379 aP2=BRep_Tool::Pnt(aV2);
1380 //
1381 aD2=aP1.SquareDistance(aP2);
1382 if (aD2>aTolSum2) {
1383 return 1;
1384 }
1385 return 0;
1386}
1387//=======================================================================
1388// function: MakeVertex
1389// purpose :
1390//=======================================================================
1391 void BOPTools_AlgoTools::MakeVertex(BOPCol_ListOfShape& aLV,
1392 TopoDS_Vertex& aVnew)
1393{
1394 Standard_Integer aNb;
1395 Standard_Real aTi, aDi, aDmax;
1396 gp_Pnt aPi, aP;
1397 gp_XYZ aXYZ(0.,0.,0.), aXYZi;
1398 BOPCol_ListIteratorOfListOfShape aIt;
1399 //
1400 aNb=aLV.Extent();
1401 if (aNb) {
1402 aIt.Initialize(aLV);
1403 for (; aIt.More(); aIt.Next()) {
1404 TopoDS_Vertex& aVi=*((TopoDS_Vertex*)(&aIt.Value()));
1405 aPi=BRep_Tool::Pnt(aVi);
1406 aXYZi=aPi.XYZ();
1407 aXYZ=aXYZ+aXYZi;
1408 }
1409 //
1410 aXYZ.Divide((Standard_Real)aNb);
1411 aP.SetXYZ(aXYZ);
1412 //
1413 aDmax=-1.;
1414 aIt.Initialize(aLV);
1415 for (; aIt.More(); aIt.Next()) {
1416 TopoDS_Vertex& aVi=*((TopoDS_Vertex*)(&aIt.Value()));
1417 aPi=BRep_Tool::Pnt(aVi);
1418 aTi=BRep_Tool::Tolerance(aVi);
1419 aDi=aP.SquareDistance(aPi);
1420 aDi=fsqrt(aDi);
1421 aDi=aDi+aTi;
1422 if (aDi > aDmax) {
1423 aDmax=aDi;
1424 }
1425 }
1426 //
1427 BRep_Builder aBB;
1428 aBB.MakeVertex (aVnew, aP, aDmax);
1429 }
1430}
1431//=======================================================================
1432//function : GetEdgeOnFace
1433//purpose :
1434//=======================================================================
1435 Standard_Boolean BOPTools_AlgoTools::GetEdgeOnFace(const TopoDS_Edge& theE1,
1436 const TopoDS_Face& theF2,
1437 TopoDS_Edge& theE2)
1438{
1439 Standard_Boolean bFound;
1440 TopoDS_Iterator aItF, aItW;
1441 //
1442 bFound=Standard_False;
1443 //
1444 aItF.Initialize(theF2);
1445 for (; aItF.More(); aItF.Next()) {
1446 const TopoDS_Shape& aW=aItF.Value();
1447 aItW.Initialize(aW);
1448 for (; aItW.More(); aItW.Next()) {
1449 const TopoDS_Shape& aE=aItW.Value();
1450 if (aE.IsSame(theE1)) {
1451 theE2=(*(TopoDS_Edge*)(&aE));
1452 bFound=!bFound;
1453 return bFound;
1454 }
1455 }
1456 }
1457 return bFound;
1458}
1459//=======================================================================
1460//function : FindFacePairs
1461//purpose :
1462//=======================================================================
1463Standard_Boolean FindFacePairs (const TopoDS_Edge& theE,
1464 const BOPCol_ListOfShape& thLF,
1465 BOPTools_ListOfCoupleOfShape& theLCFF,
1466 Handle(BOPInt_Context)& theContext)
1467{
1468 Standard_Boolean bFound;
1469 Standard_Integer i, aNbCEF;
1470 TopAbs_Orientation aOr, aOrC;
1471 BOPCol_MapOfShape aMFP;
1472 TopoDS_Face aF1, aF2;
1473 TopoDS_Edge aEL, aE1;
1474 BOPCol_ListIteratorOfListOfShape aItLF;
1475 BOPTools_CoupleOfShape aCEF, aCFF;
1476 BOPTools_ListOfCoupleOfShape aLCEF, aLCEFx;
1477 BOPTools_ListIteratorOfListOfCoupleOfShape aIt;
1478 //
1479 bFound=Standard_True;
1480 //
1481 // Preface aLCEF
1482 aItLF.Initialize(thLF);
1483 for (; aItLF.More(); aItLF.Next()) {
1484 const TopoDS_Face& aFL=(*(TopoDS_Face*)(&aItLF.Value()));
1485 //
1486 bFound=BOPTools_AlgoTools::GetEdgeOnFace(theE, aFL, aEL);
1487 if (!bFound) {
1488 return bFound; // it can not be so
1489 }
1490 //
1491 aCEF.SetShape1(aEL);
1492 aCEF.SetShape2(aFL);
1493 aLCEF.Append(aCEF);
1494 }
1495 //
1496 aNbCEF=aLCEF.Extent();
1497 while(aNbCEF) {
1498 //
1499 // aLCEFx
1500 aLCEFx.Clear();
1501 aIt.Initialize(aLCEF);
1502 for (i=0; aIt.More(); aIt.Next(), ++i) {
1503 const BOPTools_CoupleOfShape& aCSx=aIt.Value();
1504 const TopoDS_Shape& aEx=aCSx.Shape1();
1505 const TopoDS_Shape& aFx=aCSx.Shape2();
1506 //
1507 aOr=aEx.Orientation();
1508 //
1509 if (!i) {
1510 aOrC=TopAbs::Reverse(aOr);
1511 aE1=(*(TopoDS_Edge*)(&aEx));
1512 aF1=(*(TopoDS_Face*)(&aFx));
1513 aMFP.Add(aFx);
1514 continue;
1515 }
1516 //
1517 if (aOr==aOrC) {
1518 aLCEFx.Append(aCSx);
1519 aMFP.Add(aFx);
1520 }
1521 }
1522 //
1523 // F2
1524 BOPTools_AlgoTools::GetFaceOff(aE1, aF1, aLCEFx, aF2, theContext);
1525 //
1526 aCFF.SetShape1(aF1);
1527 aCFF.SetShape2(aF2);
1528 theLCFF.Append(aCFF);
1529 //
1530 aMFP.Add(aF1);
1531 aMFP.Add(aF2);
1532 //
1533 // refine aLCEF
1534 aLCEFx.Clear();
1535 aLCEFx=aLCEF;
1536 aLCEF.Clear();
1537 aIt.Initialize(aLCEFx);
1538 for (; aIt.More(); aIt.Next()) {
1539 const BOPTools_CoupleOfShape& aCSx=aIt.Value();
1540 const TopoDS_Shape& aFx=aCSx.Shape2();
1541 if (!aMFP.Contains(aFx)) {
1542 aLCEF.Append(aCSx);
1543 }
1544 }
1545 //
1546 aNbCEF=aLCEF.Extent();
1547 }//while(aNbCEF) {
1548 //
1549 return bFound;
1550}
1551//=======================================================================
1552//function : AngleWithRef
1553//purpose :
1554//=======================================================================
1555Standard_Real AngleWithRef(const gp_Dir& theD1,
1556 const gp_Dir& theD2,
1557 const gp_Dir& theDRef)
1558{
1559 Standard_Real aCosinus, aSinus, aBeta, aHalfPI, aScPr;
1560 gp_XYZ aXYZ;
1561 //
1562 aHalfPI=0.5*M_PI;
1563 //
1564 const gp_XYZ& aXYZ1=theD1.XYZ();
1565 const gp_XYZ& aXYZ2=theD2.XYZ();
1566 aXYZ=aXYZ1.Crossed(aXYZ2);
1567 aSinus=aXYZ.Modulus();
1568 aCosinus=theD1*theD2;
1569 //
1570 aBeta=0.;
1571 if (aSinus>=0.) {
1572 aBeta=aHalfPI*(1.-aCosinus);
1573 }
1574 else {
1575 aBeta=2.*M_PI-aHalfPI*(3.+aCosinus);
1576 }
1577 //
1578 aScPr=aXYZ.Dot(theDRef.XYZ());
1579 if (aScPr<0.) {
1580 aBeta=-aBeta;
1581 }
1582 return aBeta;
1583}
1584//=======================================================================
1585//function : fsqrt
1586//purpose :
1587//=======================================================================
1588Standard_Real fsqrt(Standard_Real val)
1589{
1590 union {
1591 int tmp;
1592 float val;
1593 } u;
1594 //
1595 u.val = (float)val;
1596 u.tmp -= 1<<23; /* Remove last bit so 1.0 gives 1.0 */
1597 /* tmp is now an approximation to logbase2(val) */
1598 u.tmp >>= 1; /* divide by 2 */
1599 u.tmp += 1<<29; /* add 64 to exponent: (e+127)/2 =(e/2)+63, */
1600 /* that represents (e/2)-64 but we want e/2 */
1601 return (double)u.val;
1602}
1603
1604//=======================================================================
1605//function : CorrectPoint
1606//purpose :
1607//=======================================================================
1608 void BOPTools_AlgoTools::CorrectPoint(const gp_Pnt& thePnt,
1609 const Handle(Geom_Plane)& thePL,
1610 gp_Pnt& theNewPnt)
1611{
1612 theNewPnt = thePnt;
1613 GeomAPI_ProjectPointOnSurf aProjector;
1614 aProjector.Init(thePnt, thePL);
1615 if (aProjector.NbPoints()) {
1616 theNewPnt = aProjector.NearestPoint();
1617 }
1618}
1619
1620//=======================================================================
1621// function: IsBlockInOnFace
1622// purpose:
1623//=======================================================================
1624 Standard_Boolean BOPTools_AlgoTools::IsBlockInOnFace (const IntTools_Range& aShrR,
1625 const TopoDS_Face& aF,
1626 const TopoDS_Edge& aE1,
1627 Handle(BOPInt_Context)& aContext)
1628{
1629 Standard_Boolean bFlag;
1630 Standard_Real f1, l1, ULD, VLD;
1631 gp_Pnt2d aP2D;
1632 gp_Pnt aP11, aP12;
1633 //
1634 aShrR.Range(f1, l1);
1635 Standard_Real dt=0.0075, k;//dt=0.001, k;
1636 k=dt*(l1-f1);
1637 f1=f1+k;
1638 l1=l1-k;
1639 //
1640 // Treatment P11
1641 BOPTools_AlgoTools::PointOnEdge(aE1, f1, aP11);
1642 //
1643 GeomAPI_ProjectPointOnSurf& aProjector=aContext->ProjPS(aF);
1644 aProjector.Perform(aP11);
1645 //
1646 bFlag=aProjector.IsDone();
1647 if (!bFlag) {
1648 return bFlag;
1649 }
1650
1651 aProjector.LowerDistanceParameters(ULD, VLD);
1652 aP2D.SetCoord(ULD, VLD);
1653 //
1654 bFlag=aContext->IsPointInOnFace (aF, aP2D);
1655 //
1656 if (!bFlag) {
1657 return bFlag;
1658 }
1659 //
1660 // Treatment P12
1661 BOPTools_AlgoTools::PointOnEdge(aE1, l1, aP12);
1662 //
1663 aProjector.Perform(aP12);
1664 //
1665 bFlag=aProjector.IsDone();
1666 if (!bFlag) {
1667 return bFlag;
1668 }
1669
1670 aProjector.LowerDistanceParameters(ULD, VLD);
1671 aP2D.SetCoord(ULD, VLD);
1672 //
1673 bFlag=aContext->IsPointInOnFace (aF, aP2D);
1674 //
1675 if (!bFlag) {
1676 return bFlag;
1677 }
1678 //
1679 // Treatment intemediate
1680 Standard_Real m1, aTolF, aTolE, aTol, aDist;
1681 m1=IntTools_Tools::IntermediatePoint(f1, l1);
1682 BOPTools_AlgoTools::PointOnEdge(aE1, m1, aP12);
1683 //
1684 aProjector.Perform(aP12);
1685 //
1686 bFlag=aProjector.IsDone();
1687 if (!bFlag) {
1688 return bFlag;
1689 }
1690 //
1691 aTolE=BRep_Tool::Tolerance(aE1);
1692 aTolF=BRep_Tool::Tolerance(aF);
1693 aTol=aTolE+aTolF;
1694 aDist=aProjector.LowerDistance();
1695 if (aDist > aTol){
1696 return Standard_False;
1697 }
1698
1699 aProjector.LowerDistanceParameters(ULD, VLD);
1700 aP2D.SetCoord(ULD, VLD);
1701 //
1702 bFlag=aContext->IsPointInOnFace (aF, aP2D);
1703 //
1704 if (!bFlag) {
1705 return bFlag;
1706 }
1707 return bFlag;
1708}
1709
1710//=======================================================================
1711//function : GetProjectPoint
1712//purpose :
1713//=======================================================================
1714 Standard_Boolean BOPTools_AlgoTools::GetProjectPoint(const TopoDS_Face& aF,
1715 const gp_Pnt& aPF,
1716 const TopoDS_Face& aF1,
1717 gp_Pnt& aPF1,
1718 gp_Dir& aDNF1,
1719 Handle(BOPInt_Context)& aContext)
1720{
1721 Standard_Boolean bRet = Standard_False;
1722 Handle(Geom_Surface) aS, aS1;
1723 GeomAbs_SurfaceType aTS, aTS1;
1724 Handle(Geom_CylindricalSurface) aCS, aCS1;
1725 Standard_Real aR, aR1, dR, aU, aV, aDMin;
1726 //
1727 aS = BRep_Tool::Surface(aF);
1728 aS1 = BRep_Tool::Surface(aF1);
1729 GeomAdaptor_Surface aGAS(aS), aGAS1(aS1);
1730 //
1731 aTS = aGAS.GetType();
1732 aTS1 = aGAS1.GetType();
1733 //
1734 if (!(aTS == GeomAbs_Cylinder && aTS1 == GeomAbs_Cylinder)) {
1735 return bRet;
1736 }
1737 //
1738 aCS = Handle(Geom_CylindricalSurface)::DownCast(aS);
1739 aCS1 = Handle(Geom_CylindricalSurface)::DownCast(aS1);
1740 //
1741 if (aCS.IsNull() || aCS1.IsNull()) {
1742 return bRet;
1743 }
1744 //
1745 if (!aCS->Axis().IsParallel(aCS1->Axis(), Precision::Angular())) {
1746 return bRet;
1747 }
1748 //
1749 aR = aCS->Radius();
1750 aR1 = aCS1->Radius();
1751 dR = fabs(aR - aR1);
1752 //
1753 if (dR < Precision::Angular()) {
1754 return bRet;
1755 }
1756
1757 gp_Lin aL(aCS->Axis()), aL1(aCS1->Axis());
1758 if (Abs(aL.Distance(aL1) - dR) < Precision::Confusion()) {
1759 GeomAPI_ProjectPointOnSurf& aProjector=aContext->ProjPS(aF1);
1760 aProjector.Perform(aPF);
1761 if (!aProjector.IsDone()) {
1762 return bRet;
1763 }
1764 aDMin = aProjector.LowerDistance();
1765 if (aDMin > dR) {
1766 return bRet;
1767 }
1768 aProjector.LowerDistanceParameters(aU, aV);
1769 Handle(Geom_Surface) aS = BRep_Tool::Surface(aF1);
1770 BOPTools_AlgoTools3D::GetNormalToSurface (aS, aU, aV, aDNF1);
1771 aS->D0(aU, aV, aPF1);
1772 bRet = !bRet;
1773 }
1774 return bRet;
1775}
1776
1777//=======================================================================
1778//function : IsMicroEdge
1779//purpose :
1780//=======================================================================
1781 Standard_Boolean BOPTools_AlgoTools::IsMicroEdge(const TopoDS_Edge& aE,
1782 const Handle(BOPInt_Context)& aCtx)
1783{
1784 Standard_Boolean bRet;
1785 Standard_Integer iErr;
1786 Standard_Real aT1, aT2, aTmp;
1787 Handle(Geom_Curve) aC3D;
1788 TopoDS_Vertex aV1, aV2;
1789 //
1790 bRet=(BRep_Tool::Degenerated(aE) ||
1791 !BRep_Tool::IsGeometric(aE));
1792 if (bRet) {
1793 return bRet;
1794 }
1795 //
1796 aC3D=BRep_Tool::Curve(aE, aT1, aT2);
1797 TopExp::Vertices(aE, aV1, aV2);
1798 aT1=BRep_Tool::Parameter(aV1, aE);
1799 aT2=BRep_Tool::Parameter(aV2, aE);
1800 if (aT2<aT1) {
1801 aTmp=aT1;
1802 aT1=aT2;
1803 aT2=aTmp;
1804 }
1805 //
1806 BOPInt_ShrunkRange aSR;
1807 aSR.SetData(aE, aT1, aT2, aV1, aV2, aCtx);
1808 aSR.Perform();
1809 iErr=aSR.ErrorStatus();
1810 bRet = !(iErr==0);
1811 //
1812 return bRet;
1813}
1814
1815/*
1816//=======================================================================
1817//function : AreFacesSameDomain
1818//purpose :
1819//=======================================================================
1820 Standard_Boolean BOPTools_AlgoTools::AreFacesSameDomain(const TopoDS_Face& theF1,
1821 const TopoDS_Face& theF2,
1822 Handle(BOPInt_Context)& theContext)
1823 {
1824 Standard_Boolean bFlag;
1825
1826 Standard_Integer aNbE1, aNbE2;
1827 Standard_Real aTolF1, aTolF2, aTol;
1828 gp_Pnt2d aP2D;
1829 gp_Pnt aP;
1830 TopoDS_Face aF1, aF2;
1831 TopExp_Explorer aExp;
1832 BOPCol_MapOfShape aME1, aME2;
1833 BOPCol_MapIteratorOfMapOfShape aIt;
1834 //
1835 bFlag=Standard_False;
1836 //
1837 aF1=theF1;
1838 aF1.Orientation(TopAbs_FORWARD);
1839 aF2=theF2;
1840 aF2.Orientation(TopAbs_FORWARD);
1841 //
1842 // 1
1843 aExp.Init(aF1, TopAbs_EDGE);
1844 for (; aExp.More(); aExp.Next()) {
1845 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
1846 if (!BRep_Tool::Degenerated(aE)) {
1847 aME1.Add(aE);
1848 }
1849 }
1850 //
1851 aExp.Init(aF2, TopAbs_EDGE);
1852 for (; aExp.More(); aExp.Next()) {
1853 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
1854 if (!BRep_Tool::Degenerated(aE)) {
1855 if (!aME1.Contains(aE)) {
1856 return bFlag;
1857 }
1858 aME2.Add(aE);
1859 }
1860 }
1861 //
1862 aNbE1=aME1.Extent();
1863 aNbE2=aME2.Extent();
1864 //
1865 if(!aNbE1 || !aNbE2){
1866 return bFlag;
1867 }
1868 //
1869 if(aNbE1!=aNbE2) {
1870 return bFlag;
1871 }
1872 //
1873 // 2
1874 aTolF1=BRep_Tool::Tolerance(aF1);
1875 aTolF2=BRep_Tool::Tolerance(aF2);
1876 aTol=aTolF1+aTolF2;
1877 //
1878 aIt.Initialize(aME1);
1879 for (; aIt.More(); aIt.Next()) {
1880 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aIt.Key()));
1881 BOPTools_AlgoTools3D::PointNearEdge(aE, aF1, aP2D, aP);
1882 bFlag=theContext->IsValidPointForFace(aP, aF2, aTol);
1883 break;
1884 }
1885 //
1886 return bFlag;
1887}
1888*/