1 // Created by: Peter KURNEV
2 // Copyright (c) 2010-2014 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
7 // This file is part of Open CASCADE Technology software library.
9 // This library is free software; you can redistribute it and/or modify it under
10 // the terms of the GNU Lesser General Public License version 2.1 as published
11 // by the Free Software Foundation, with special exception defined in the file
12 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
13 // distribution for complete text of the license and disclaimer of any warranty.
15 // Alternatively, this file may be used under the terms of Open CASCADE
16 // commercial license or contractual agreement.
19 #include <BOPTools_AlgoTools.hxx>
20 #include <BOPTools_AlgoTools2D.hxx>
21 #include <BOPTools_AlgoTools3D.hxx>
22 #include <BOPTools_CoupleOfShape.hxx>
23 #include <BOPTools_ListOfCoupleOfShape.hxx>
24 #include <BRep_Builder.hxx>
25 #include <BRep_Tool.hxx>
26 #include <BRepAdaptor_Curve2d.hxx>
27 #include <BRepAdaptor_Surface.hxx>
28 #include <BRepClass3d_SolidClassifier.hxx>
29 #include <BRepLib.hxx>
30 #include <Geom2d_Curve.hxx>
31 #include <Geom2dInt_Geom2dCurveTool.hxx>
32 #include <Geom_Curve.hxx>
33 #include <Geom_Plane.hxx>
34 #include <Geom_Surface.hxx>
35 #include <Geom_TrimmedCurve.hxx>
36 #include <GeomAPI_ProjectPointOnSurf.hxx>
37 #include <gp_Cone.hxx>
38 #include <gp_Cylinder.hxx>
41 #include <gp_Pnt2d.hxx>
42 #include <gp_Sphere.hxx>
43 #include <gp_Torus.hxx>
45 #include <IntTools_Context.hxx>
46 #include <IntTools_Curve.hxx>
47 #include <IntTools_Range.hxx>
48 #include <IntTools_ShrunkRange.hxx>
49 #include <IntTools_Tools.hxx>
50 #include <Precision.hxx>
51 #include <TopAbs_Orientation.hxx>
53 #include <TopExp_Explorer.hxx>
55 #include <TopoDS_Compound.hxx>
56 #include <TopoDS_CompSolid.hxx>
57 #include <TopoDS_Edge.hxx>
58 #include <TopoDS_Face.hxx>
59 #include <TopoDS_Shape.hxx>
60 #include <TopoDS_Shell.hxx>
61 #include <TopoDS_Solid.hxx>
62 #include <TopoDS_Vertex.hxx>
63 #include <TopoDS_Wire.hxx>
64 #include <TopTools_IndexedMapOfShape.hxx>
65 #include <TopTools_MapOfShape.hxx>
66 #include <TopTools_MapOfOrientedShape.hxx>
67 #include <NCollection_Array1.hxx>
72 Standard_Real AngleWithRef(const gp_Dir& theD1,
74 const gp_Dir& theDRef);
77 Standard_Boolean FindFacePairs (const TopoDS_Edge& theE,
78 const TopTools_ListOfShape& thLF,
79 BOPTools_ListOfCoupleOfShape& theLCFF,
80 Handle(IntTools_Context)& theContext);
82 TopAbs_Orientation Orientation(const TopoDS_Edge& anE,
83 const TopoDS_Face& aF);
86 Standard_Boolean GetFaceDir(const TopoDS_Edge& aE,
87 const TopoDS_Face& aF,
89 const Standard_Real aT,
91 const Standard_Boolean theSmallFaces,
94 Handle(IntTools_Context)& theContext,
95 GeomAPI_ProjectPointOnSurf& aProjPL,
96 const Standard_Real aDt);
98 Standard_Boolean FindPointInFace(const TopoDS_Face& aF,
102 Handle(IntTools_Context)& theContext,
103 GeomAPI_ProjectPointOnSurf& aProjPL,
104 const Standard_Real aDt,
105 const Standard_Real aTolE);
107 Standard_Real MinStep3D(const TopoDS_Edge& theE1,
108 const TopoDS_Face& theF1,
109 const BOPTools_ListOfCoupleOfShape& theLCS,
111 Handle(IntTools_Context)& theContext,
112 Standard_Boolean& theSmallFaces);
116 //=======================================================================
117 // function: MakeConnexityBlocks
119 //=======================================================================
120 void BOPTools_AlgoTools::MakeConnexityBlocks
121 (const TopoDS_Shape& theS,
122 const TopAbs_ShapeEnum theConnectionType,
123 const TopAbs_ShapeEnum theElementType,
124 TopTools_ListOfListOfShape& theLCB,
125 TopTools_IndexedDataMapOfShapeListOfShape& theConnectionMap)
127 // Map shapes to find connected elements
128 TopExp::MapShapesAndAncestors(theS, theConnectionType, theElementType, theConnectionMap);
130 TopTools_MapOfShape aMFence;
132 TopExp_Explorer aExp(theS, theElementType);
133 for (; aExp.More(); aExp.Next())
135 const TopoDS_Shape& aS = aExp.Current();
136 if (!aMFence.Add(aS)) {
140 TopTools_ListOfShape aLBlock;
143 // Look for connected parts
144 TopTools_ListIteratorOfListOfShape aItB(aLBlock);
145 for (; aItB.More(); aItB.Next())
147 const TopoDS_Shape& aS1 = aItB.Value();
148 TopExp_Explorer aExpSS(aS1, theConnectionType);
149 for (; aExpSS.More(); aExpSS.Next())
151 const TopoDS_Shape& aSubS = aExpSS.Current();
152 const TopTools_ListOfShape& aLS = theConnectionMap.FindFromKey(aSubS);
153 TopTools_ListIteratorOfListOfShape aItLS(aLS);
154 for (; aItLS.More(); aItLS.Next())
156 const TopoDS_Shape& aS2 = aItLS.Value();
157 if (aMFence.Add(aS2))
162 // Add the block into result
163 theLCB.Append(aLBlock);
167 //=======================================================================
168 // function: MakeConnexityBlocks
170 //=======================================================================
171 void BOPTools_AlgoTools::MakeConnexityBlocks
172 (const TopoDS_Shape& theS,
173 const TopAbs_ShapeEnum theConnectionType,
174 const TopAbs_ShapeEnum theElementType,
175 TopTools_ListOfShape& theLCB)
177 TopTools_ListOfListOfShape aLBlocks;
178 TopTools_IndexedDataMapOfShapeListOfShape aCMap;
179 BOPTools_AlgoTools::MakeConnexityBlocks(theS, theConnectionType, theElementType, aLBlocks, aCMap);
181 // Make compound from each block
182 TopTools_ListIteratorOfListOfListOfShape aItB(aLBlocks);
183 for (; aItB.More(); aItB.Next())
185 const TopTools_ListOfShape& aLB = aItB.Value();
187 TopoDS_Compound aBlock;
188 BRep_Builder().MakeCompound(aBlock);
189 for (TopTools_ListIteratorOfListOfShape it(aLB); it.More(); it.Next())
190 BRep_Builder().Add(aBlock, it.Value());
192 theLCB.Append(aBlock);
196 //=======================================================================
197 // function: MakeConnexityBlocks
199 //=======================================================================
200 void BOPTools_AlgoTools::MakeConnexityBlocks
201 (const TopTools_ListOfShape& theLS,
202 const TopAbs_ShapeEnum theConnectionType,
203 const TopAbs_ShapeEnum theElementType,
204 BOPTools_ListOfConnexityBlock& theLCB)
207 // Make connexity blocks from start elements
208 TopoDS_Compound aCStart;
209 aBB.MakeCompound(aCStart);
211 TopTools_MapOfShape aMFence, aMNRegular;
213 TopTools_ListIteratorOfListOfShape aItL(theLS);
214 for (; aItL.More(); aItL.Next())
216 const TopoDS_Shape& aS = aItL.Value();
218 aBB.Add(aCStart, aS);
223 TopTools_ListOfListOfShape aLCB;
224 TopTools_IndexedDataMapOfShapeListOfShape aCMap;
225 BOPTools_AlgoTools::MakeConnexityBlocks(aCStart, theConnectionType, theElementType, aLCB, aCMap);
227 // Save the blocks and check their regularity
228 TopTools_ListIteratorOfListOfListOfShape aItB(aLCB);
229 for (; aItB.More(); aItB.Next())
231 const TopTools_ListOfShape& aBlock = aItB.Value();
233 BOPTools_ConnexityBlock aCB;
234 TopTools_ListOfShape& aLCS = aCB.ChangeShapes();
236 Standard_Boolean bRegular = Standard_True;
237 for (TopTools_ListIteratorOfListOfShape it(aBlock); it.More(); it.Next())
239 TopoDS_Shape aS = it.Value();
240 if (aMNRegular.Contains(aS))
242 bRegular = Standard_False;
243 aS.Orientation(TopAbs_FORWARD);
245 aS.Orientation(TopAbs_REVERSED);
253 // Check if there are no multi-connected shapes
254 for (TopExp_Explorer ex(aS, theConnectionType); ex.More() && bRegular; ex.Next())
255 bRegular = (aCMap.FindFromKey(ex.Current()).Extent() == 2);
260 aCB.SetRegular(bRegular);
265 //=======================================================================
266 // function: OrientEdgesOnWire
267 // purpose: Reorient edges on wire for correct ordering
268 //=======================================================================
269 void BOPTools_AlgoTools::OrientEdgesOnWire(TopoDS_Shape& theWire)
271 // make vertex-edges connexity map
272 TopTools_IndexedDataMapOfShapeListOfShape aVEMap;
273 TopExp::MapShapesAndAncestors(theWire, TopAbs_VERTEX, TopAbs_EDGE, aVEMap);
275 if (aVEMap.IsEmpty()) {
284 TopTools_MapOfOrientedShape aMFence;
286 TopoDS_Iterator aIt(theWire);
287 for (; aIt.More(); aIt.Next()) {
288 const TopoDS_Edge& aEC = TopoDS::Edge(aIt.Value());
289 if (!aMFence.Add(aEC)) {
293 // add edge to a wire as it is
296 TopoDS_Vertex aV1, aV2;
297 TopExp::Vertices(aEC, aV1, aV2, Standard_True);
299 if (aV1.IsSame(aV2)) {
300 // closed edge, go to the next edge
304 // orient the adjacent edges
305 for (Standard_Integer i = 0; i < 2; ++i) {
306 TopoDS_Shape aVC = !i ? aV1 : aV2;
309 const TopTools_ListOfShape& aLE = aVEMap.FindFromKey(aVC);
310 if (aLE.Extent() != 2) {
311 // free vertex or multi-connexity, go to the next edge
315 Standard_Boolean bStop = Standard_True;
317 TopTools_ListIteratorOfListOfShape aItLE(aLE);
318 for (; aItLE.More(); aItLE.Next()) {
319 const TopoDS_Edge& aEN = TopoDS::Edge(aItLE.Value());
320 if (aMFence.Contains(aEN)) {
324 TopoDS_Vertex aVN1, aVN2;
325 TopExp::Vertices(aEN, aVN1, aVN2, Standard_True);
326 if (aVN1.IsSame(aVN2)) {
327 // closed edge, go to the next edge
331 // change orientation if necessary and go to the next edges
332 if ((!i && aVC.IsSame(aVN2)) || (i && aVC.IsSame(aVN1))) {
336 aBB.Add(aWire, aEN.Reversed());
339 aVC = aVC.IsSame(aVN1) ? aVN2 : aVN1;
340 bStop = Standard_False;
353 //=======================================================================
354 // function: OrientFacesOnShell
356 //=======================================================================
357 void BOPTools_AlgoTools::OrientFacesOnShell (TopoDS_Shape& aShell)
359 Standard_Boolean bIsProcessed1, bIsProcessed2;
360 Standard_Integer i, aNbE, aNbF, j;
361 TopAbs_Orientation anOrE1, anOrE2;
362 TopoDS_Face aF1x, aF2x;
363 TopoDS_Shape aShellNew;
364 TopTools_IndexedDataMapOfShapeListOfShape aEFMap;
365 TopTools_IndexedMapOfShape aProcessedFaces;
368 BOPTools_AlgoTools::MakeContainer(TopAbs_SHELL, aShellNew);
370 TopExp::MapShapesAndAncestors(aShell,
371 TopAbs_EDGE, TopAbs_FACE,
373 aNbE=aEFMap.Extent();
375 // One seam edge in aEFMap contains 2 equivalent faces.
376 for (i=1; i<=aNbE; ++i) {
377 TopTools_ListOfShape& aLF=aEFMap.ChangeFromIndex(i);
380 TopTools_ListOfShape aLFTmp;
381 TopTools_IndexedMapOfShape aFM;
383 TopTools_ListIteratorOfListOfShape anIt(aLF);
384 for (; anIt.More(); anIt.Next()) {
385 const TopoDS_Shape& aF=anIt.Value();
386 if (!aFM.Contains(aF)) {
397 for (i=1; i<=aNbE; ++i) {
398 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aEFMap.FindKey(i)));
399 if (BRep_Tool::Degenerated(aE)) {
403 const TopTools_ListOfShape& aLF=aEFMap.FindFromIndex(i);
409 TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First()));
410 TopoDS_Face& aF2=(*(TopoDS_Face*)(&aLF.Last()));
412 bIsProcessed1=aProcessedFaces.Contains(aF1);
413 bIsProcessed2=aProcessedFaces.Contains(aF2);
414 if (bIsProcessed1 && bIsProcessed2) {
418 if (!bIsProcessed1 && !bIsProcessed2) {
419 aProcessedFaces.Add(aF1);
420 aBB.Add(aShellNew, aF1);
421 bIsProcessed1=!bIsProcessed1;
426 j=aProcessedFaces.FindIndex(aF1);
427 aF1x=(*(TopoDS_Face*)(&aProcessedFaces.FindKey(j)));
432 j=aProcessedFaces.FindIndex(aF2);
433 aF2x=(*(TopoDS_Face*)(&aProcessedFaces.FindKey(j)));
436 anOrE1=Orientation(aE, aF1x);
437 anOrE2=Orientation(aE, aF2x);
439 if (bIsProcessed1 && !bIsProcessed2) {
440 if (anOrE1==anOrE2) {
441 if (!BRep_Tool::IsClosed(aE, aF1) &&
442 !BRep_Tool::IsClosed(aE, aF2)) {
446 aProcessedFaces.Add(aF2);
447 aBB.Add(aShellNew, aF2);
449 else if (!bIsProcessed1 && bIsProcessed2) {
450 if (anOrE1==anOrE2) {
451 if (!BRep_Tool::IsClosed(aE, aF1) &&
452 !BRep_Tool::IsClosed(aE, aF2)) {
456 aProcessedFaces.Add(aF1);
457 aBB.Add(aShellNew, aF1);
462 for (i=1; i<=aNbE; ++i) {
463 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aEFMap.FindKey(i)));
464 if (BRep_Tool::Degenerated(aE)) {
468 const TopTools_ListOfShape& aLF=aEFMap.FindFromIndex(i);
471 TopTools_ListIteratorOfListOfShape anIt(aLF);
472 for(; anIt.More(); anIt.Next()) {
473 const TopoDS_Face& aF=(*(TopoDS_Face*)(&anIt.Value()));
474 if (!aProcessedFaces.Contains(aF)) {
475 aProcessedFaces.Add(aF);
476 aBB.Add(aShellNew, aF);
483 //=======================================================================
484 //function : Orientation
486 //=======================================================================
487 TopAbs_Orientation Orientation(const TopoDS_Edge& anE,
488 const TopoDS_Face& aF)
490 TopAbs_Orientation anOr=TopAbs_INTERNAL;
492 TopExp_Explorer anExp;
493 anExp.Init(aF, TopAbs_EDGE);
494 for (; anExp.More(); anExp.Next()) {
495 const TopoDS_Edge& anEF1=(*(TopoDS_Edge*)(&anExp.Current()));
496 if (anEF1.IsSame(anE)) {
497 anOr=anEF1.Orientation();
503 //=======================================================================
504 // function: MakeConnexityBlock.
506 //=======================================================================
507 void BOPTools_AlgoTools::MakeConnexityBlock
508 (TopTools_ListOfShape& theLFIn,
509 TopTools_IndexedMapOfShape& theMEAvoid,
510 TopTools_ListOfShape& theLCB,
511 const Handle(NCollection_BaseAllocator)& theAllocator)
513 Standard_Integer aNbF, aNbAdd1, aNbAdd, i;
514 TopExp_Explorer aExp;
515 TopTools_ListIteratorOfListOfShape aIt;
517 TopTools_IndexedMapOfShape aMCB(100, theAllocator);
518 TopTools_IndexedMapOfShape aMAdd(100, theAllocator);
519 TopTools_IndexedMapOfShape aMAdd1(100, theAllocator);
520 TopTools_IndexedDataMapOfShapeListOfShape aMEF(100, theAllocator);
523 aNbF=theLFIn.Extent();
524 aIt.Initialize(theLFIn);
525 for (; aIt.More(); aIt.Next()) {
526 const TopoDS_Shape& aF=aIt.Value();
527 TopExp::MapShapesAndAncestors(aF, TopAbs_EDGE, TopAbs_FACE, aMEF);
531 const TopoDS_Shape& aF1=theLFIn.First();
536 aNbAdd = aMAdd.Extent();
537 for (i=1; i<=aNbAdd; ++i) {
538 const TopoDS_Shape& aF=aMAdd(i);
541 aExp.Init(aF, TopAbs_EDGE);
542 for (; aExp.More(); aExp.Next()) {
543 const TopoDS_Shape& aE=aExp.Current();
544 if (theMEAvoid.Contains(aE)){
548 const TopTools_ListOfShape& aLF=aMEF.FindFromKey(aE);
550 for (; aIt.More(); aIt.Next()) {
551 const TopoDS_Shape& aFx=aIt.Value();
552 if (aFx.IsSame(aF)) {
555 if (aMCB.Contains(aFx)) {
560 }//for (; aExp.More(); aExp.Next()){
562 }// for (i=1; i<=aNbAdd; ++i) {
564 aNbAdd1=aMAdd1.Extent();
570 for (i=1; i<=aNbAdd1; ++i) {
571 const TopoDS_Shape& aFAdd=aMAdd1(i);
579 for (i=1; i<=aNbF; ++i) {
580 const TopoDS_Shape& aF=aMCB(i);
584 //=======================================================================
585 // function: ComputeStateByOnePoint
587 //=======================================================================
588 TopAbs_State BOPTools_AlgoTools::ComputeStateByOnePoint
589 (const TopoDS_Shape& theS,
590 const TopoDS_Solid& theRef,
591 const Standard_Real theTol,
592 Handle(IntTools_Context)& theContext)
595 TopAbs_ShapeEnum aType;
597 aState=TopAbs_UNKNOWN;
598 aType=theS.ShapeType();
599 if (aType==TopAbs_VERTEX) {
600 const TopoDS_Vertex& aV=(*(TopoDS_Vertex*)(&theS));
601 aState=BOPTools_AlgoTools::ComputeState(aV, theRef, theTol, theContext);
603 else if (aType==TopAbs_EDGE) {
604 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&theS));
605 aState=BOPTools_AlgoTools::ComputeState(aE, theRef, theTol, theContext);
610 //=======================================================================
611 // function: ComputeState
613 //=======================================================================
614 TopAbs_State BOPTools_AlgoTools::ComputeState
615 (const TopoDS_Face& theF,
616 const TopoDS_Solid& theRef,
617 const Standard_Real theTol,
618 TopTools_IndexedMapOfShape& theBounds,
619 Handle(IntTools_Context)& theContext)
622 TopExp_Explorer aExp;
627 aState=TopAbs_UNKNOWN;
629 aExp.Init(theF, TopAbs_EDGE);
630 for (; aExp.More(); aExp.Next()) {
631 const TopoDS_Edge& aSE=(*(TopoDS_Edge*)(&aExp.Current()));
632 if (BRep_Tool::Degenerated(aSE)) {
636 if (!theBounds.Contains(aSE)) {
637 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aSE));
638 aState=BOPTools_AlgoTools::ComputeState(aE, theRef, theTol,
643 aE1=(*(TopoDS_Edge*)(&aSE));
646 // !!<- process edges that are all on theRef
648 BOPTools_AlgoTools3D::PointNearEdge(aE1, theF,
649 aP2D, aP3D, theContext);
650 aState=BOPTools_AlgoTools::ComputeState(aP3D, theRef, theTol,
656 //=======================================================================
657 // function: ComputeState
659 //=======================================================================
660 TopAbs_State BOPTools_AlgoTools::ComputeState
661 (const TopoDS_Vertex& theV,
662 const TopoDS_Solid& theRef,
663 const Standard_Real theTol,
664 Handle(IntTools_Context)& theContext)
669 aP3D=BRep_Tool::Pnt(theV);
670 aState=BOPTools_AlgoTools::ComputeState(aP3D, theRef, theTol,
674 //=======================================================================
675 // function: ComputeState
677 //=======================================================================
678 TopAbs_State BOPTools_AlgoTools::ComputeState
679 (const TopoDS_Edge& theE,
680 const TopoDS_Solid& theRef,
681 const Standard_Real theTol,
682 Handle(IntTools_Context)& theContext)
684 Standard_Real aT1, aT2, aT = 0.;
686 Handle(Geom_Curve) aC3D;
689 aC3D = BRep_Tool::Curve(theE, aT1, aT2);
692 //it means that we are in degenerated edge
693 const TopoDS_Vertex& aV = TopExp::FirstVertex(theE);
695 return TopAbs_UNKNOWN;
697 aP3D=BRep_Tool::Pnt(aV);
700 Standard_Boolean bF2Inf, bL2Inf;
701 Standard_Real dT=10.;
703 bF2Inf = Precision::IsNegativeInfinite(aT1);
704 bL2Inf = Precision::IsPositiveInfinite(aT2);
706 if (bF2Inf && !bL2Inf) {
709 else if (!bF2Inf && bL2Inf) {
712 else if (bF2Inf && bL2Inf) {
716 aT=IntTools_Tools::IntermediatePoint(aT1, aT2);
721 aState=BOPTools_AlgoTools::ComputeState(aP3D, theRef, theTol,
726 //=======================================================================
727 // function: ComputeState
729 //=======================================================================
730 TopAbs_State BOPTools_AlgoTools::ComputeState
732 const TopoDS_Solid& theRef,
733 const Standard_Real theTol,
734 Handle(IntTools_Context)& theContext)
738 BRepClass3d_SolidClassifier& aSC=theContext->SolidClassifier(theRef);
739 aSC.Perform(theP, theTol);
745 //=======================================================================
746 //function : IsInternalFace
748 //=======================================================================
749 Standard_Boolean BOPTools_AlgoTools::IsInternalFace
750 (const TopoDS_Face& theFace,
751 const TopoDS_Solid& theSolid,
752 TopTools_IndexedDataMapOfShapeListOfShape& theMEF,
753 const Standard_Real theTol,
754 Handle(IntTools_Context)& theContext)
756 Standard_Boolean bDegenerated;
757 Standard_Integer aNbF, iRet, iFound;
758 TopAbs_Orientation aOr;
760 TopExp_Explorer aExp;
761 TopTools_ListIteratorOfListOfShape aItF;
763 // For all invoked functions: [::IsInternalFace(...)]
764 // the returned value iRet means:
765 // iRet=0; - state is not IN
766 // iRet=1; - state is IN
767 // iRet=2; - state can not be found by the method of angles
769 // For this function the returned value iRet means:
770 // iRet=0; - state is not IN
771 // iRet=1; - state is IN
774 // 1 Try to find an edge from theFace in theMEF
776 aExp.Init(theFace, TopAbs_EDGE);
777 for(; aExp.More(); aExp.Next()) {
778 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
779 if (!theMEF.Contains(aE)) {
785 aOr=aE.Orientation();
786 if (aOr==TopAbs_INTERNAL) {
789 bDegenerated=BRep_Tool::Degenerated(aE);
794 TopTools_ListOfShape& aLF=theMEF.ChangeFromKey(aE);
797 return iRet != 0; // it can not be so
801 // aE is internal edge on aLF.First()
802 const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First()));
803 BOPTools_AlgoTools::GetEdgeOnFace(aE, aF1, aE1);
804 if (aE1.Orientation()!=TopAbs_INTERNAL) {
809 iRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aF1, aF1,
815 const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First()));
816 const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aLF.Last()));
818 if (aF2.IsSame(aF1) && BRep_Tool::IsClosed(aE, aF1)) {
819 // treat as it was for 1 face
820 iRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aF1, aF2,
827 return Standard_False; // it can not be so
829 else { // aNbF=2,4,6,8,...
830 iRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aLF,
834 }//for(; aExp.More(); aExp.Next()) {
837 // the face has no shared edges with the solid
845 //========================================
846 // 2. Classify face using classifier
849 TopTools_IndexedMapOfShape aBounds;
851 TopExp::MapShapes(theSolid, TopAbs_EDGE, aBounds);
853 aState=BOPTools_AlgoTools::ComputeState(theFace, theSolid,
854 theTol, aBounds, theContext);
855 return aState == TopAbs_IN;
857 //=======================================================================
858 //function : IsInternalFace
860 //=======================================================================
861 Standard_Integer BOPTools_AlgoTools::IsInternalFace
862 (const TopoDS_Face& theFace,
863 const TopoDS_Edge& theEdge,
864 TopTools_ListOfShape& theLF,
865 Handle(IntTools_Context)& theContext)
867 Standard_Integer aNbF, iRet;
873 const TopoDS_Face& aF1=(*(TopoDS_Face*)(&theLF.First()));
874 const TopoDS_Face& aF2=(*(TopoDS_Face*)(&theLF.Last()));
875 iRet=BOPTools_AlgoTools::IsInternalFace(theFace, theEdge, aF1, aF2,
881 BOPTools_ListOfCoupleOfShape aLCFF;
882 BOPTools_ListIteratorOfListOfCoupleOfShape aIt;
884 FindFacePairs(theEdge, theLF, aLCFF, theContext);
886 aIt.Initialize(aLCFF);
887 for (; aIt.More(); aIt.Next()) {
888 BOPTools_CoupleOfShape& aCSFF=aIt.ChangeValue();
890 const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aCSFF.Shape1()));
891 const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aCSFF.Shape2()));
892 iRet=BOPTools_AlgoTools::IsInternalFace(theFace, theEdge, aF1, aF2,
901 //=======================================================================
902 //function : IsInternalFace
904 //=======================================================================
905 Standard_Integer BOPTools_AlgoTools::IsInternalFace
906 (const TopoDS_Face& theFace,
907 const TopoDS_Edge& theEdge,
908 const TopoDS_Face& theFace1,
909 const TopoDS_Face& theFace2,
910 Handle(IntTools_Context)& theContext)
912 Standard_Boolean bRet;
913 Standard_Integer iRet;
914 TopoDS_Edge aE1, aE2;
916 BOPTools_ListOfCoupleOfShape theLCSOff;
917 BOPTools_CoupleOfShape aCS1, aCS2;
919 BOPTools_AlgoTools::GetEdgeOnFace(theEdge, theFace1, aE1);
920 if (aE1.Orientation()==TopAbs_INTERNAL) {
922 aE1.Orientation(TopAbs_FORWARD);
923 aE2.Orientation(TopAbs_REVERSED);
925 else if (theFace1==theFace2) {
927 aE1.Orientation(TopAbs_FORWARD);
928 aE2.Orientation(TopAbs_REVERSED);
931 BOPTools_AlgoTools::GetEdgeOnFace(theEdge, theFace2, aE2);
934 aCS1.SetShape1(theEdge);
935 aCS1.SetShape2(theFace);
936 theLCSOff.Append(aCS1);
939 aCS2.SetShape2(theFace2);
940 theLCSOff.Append(aCS2);
942 bRet=GetFaceOff(aE1, theFace1, theLCSOff, aFOff, theContext);
944 iRet=0; // theFace is not internal
945 if (theFace.IsEqual(aFOff)) {
946 // theFace is internal
949 // theFace seems to be internal
955 //=======================================================================
956 //function : GetFaceOff
958 //=======================================================================
959 Standard_Boolean BOPTools_AlgoTools::GetFaceOff
960 (const TopoDS_Edge& theE1,
961 const TopoDS_Face& theF1,
962 BOPTools_ListOfCoupleOfShape& theLCSOff,
963 TopoDS_Face& theFOff,
964 Handle(IntTools_Context)& theContext)
966 Standard_Boolean bRet, bIsComputed;
967 Standard_Real aT, aT1, aT2, aAngle, aTwoPI, aAngleMin, aDt3D;
968 Standard_Real aUmin, aUsup, aVmin, aVsup, aPA;
969 gp_Pnt aPn1, aPn2, aPx;
970 gp_Dir aDN1, aDN2, aDBF, aDBF2, aDTF;
972 TopAbs_Orientation aOr;
973 Handle(Geom_Curve)aC3D;
974 Handle(Geom_Plane) aPL;
975 BOPTools_ListIteratorOfListOfCoupleOfShape aIt;
976 GeomAPI_ProjectPointOnSurf aProjPL;
978 aPA=Precision::Angular();
981 aC3D =BRep_Tool::Curve(theE1, aT1, aT2);
982 aT=BOPTools_AlgoTools2D::IntermediatePoint(aT1, aT2);
985 BOPTools_AlgoTools2D::EdgeTangent(theE1, aT, aVTgt);
986 gp_Dir aDTgt(aVTgt), aDTgt2;
987 aOr = theE1.Orientation();
989 aPL = new Geom_Plane(aPx, aDTgt);
990 aPL->Bounds(aUmin, aUsup, aVmin, aVsup);
991 aProjPL.Init(aPL, aUmin, aUsup, aVmin, aVsup);
993 Standard_Boolean bSmallFaces = Standard_False;
994 aDt3D = MinStep3D(theE1, theF1, theLCSOff, aPx, theContext, bSmallFaces);
995 bIsComputed = GetFaceDir(theE1, theF1, aPx, aT, aDTgt, bSmallFaces,
996 aDN1, aDBF, theContext, aProjPL, aDt3D);
999 cout << "BOPTools_AlgoTools::GetFaceOff(): incorrect computation of bi-normal direction." << endl;
1006 aIt.Initialize(theLCSOff);
1007 for (; aIt.More(); aIt.Next()) {
1008 const BOPTools_CoupleOfShape& aCS=aIt.Value();
1009 const TopoDS_Edge& aE2=(*(TopoDS_Edge*)(&aCS.Shape1()));
1010 const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aCS.Shape2()));
1012 aDTgt2 = (aE2.Orientation()==aOr) ? aDTgt : aDTgt.Reversed();
1013 bIsComputed = GetFaceDir(aE2, aF2, aPx, aT, aDTgt2, bSmallFaces, aDN2,
1014 aDBF2, theContext, aProjPL, aDt3D);
1017 cout << "BOPTools_AlgoTools::GetFaceOff(): incorrect computation of bi-normal direction." << endl;
1021 aAngle=AngleWithRef(aDBF, aDBF2, aDTF);
1024 aAngle=aTwoPI+aAngle;
1031 else if (aF2.IsSame(theF1)) {
1036 if (fabs(aAngle-aAngleMin)<aPA) {
1037 // the minimal angle can not be found
1038 bRet=Standard_False;
1041 if (aAngle<aAngleMin){
1045 else if (aAngle==aAngleMin) {
1046 // the minimal angle can not be found
1047 bRet=Standard_False;
1052 //=======================================================================
1053 //function : GetEdgeOff
1055 //=======================================================================
1056 Standard_Boolean BOPTools_AlgoTools::GetEdgeOff(const TopoDS_Edge& theE1,
1057 const TopoDS_Face& theF2,
1060 Standard_Boolean bFound;
1061 TopAbs_Orientation aOr1, aOr1C, aOr2;
1062 TopExp_Explorer anExp;
1064 bFound=Standard_False;
1065 aOr1=theE1.Orientation();
1066 aOr1C=TopAbs::Reverse(aOr1);
1068 anExp.Init(theF2, TopAbs_EDGE);
1069 for (; anExp.More(); anExp.Next()) {
1070 const TopoDS_Edge& aEF2=(*(TopoDS_Edge*)(&anExp.Current()));
1071 if (aEF2.IsSame(theE1)) {
1072 aOr2=aEF2.Orientation();
1083 //=======================================================================
1084 //function : AreFacesSameDomain
1086 //=======================================================================
1087 Standard_Boolean BOPTools_AlgoTools::AreFacesSameDomain
1088 (const TopoDS_Face& theF1,
1089 const TopoDS_Face& theF2,
1090 Handle(IntTools_Context)& theContext,
1091 const Standard_Real theFuzz)
1093 Standard_Boolean bFlag;
1094 Standard_Integer iErr;
1095 Standard_Real aTolF1, aTolF2, aTol;
1098 TopoDS_Face aF1, aF2;
1100 TopExp_Explorer aExp;
1101 Standard_Real aFuzz1 = (theFuzz > Precision::Confusion() ? theFuzz : Precision::Confusion());
1103 bFlag=Standard_False;
1106 aF1.Orientation(TopAbs_FORWARD);
1108 aF2.Orientation(TopAbs_FORWARD);
1110 aTolF1=BRep_Tool::Tolerance(aF1);
1112 aExp.Init(aF1, TopAbs_EDGE);
1113 for (; aExp.More(); aExp.Next()) {
1114 aE1=(*(TopoDS_Edge*)(&aExp.Current()));
1115 if (!BRep_Tool::Degenerated(aE1)) {
1116 Standard_Real aTolE = BRep_Tool::Tolerance(aE1);
1117 if (aTolE > aTolF1) {
1123 aTolF2=BRep_Tool::Tolerance(aF2);
1124 aTol = aTolF1 + aTolF2 + aFuzz1;
1126 iErr = BOPTools_AlgoTools3D::PointInFace(aF1, aP, aP2D,
1129 bFlag=theContext->IsValidPointForFace(aP, aF2, aTol);
1135 //=======================================================================
1136 //function : CheckSameGeom
1138 //=======================================================================
1139 Standard_Boolean BOPTools_AlgoTools::CheckSameGeom
1140 (const TopoDS_Face& theF1,
1141 const TopoDS_Face& theF2,
1142 Handle(IntTools_Context)& theContext)
1144 Standard_Boolean bRet;
1145 Standard_Real aTolF1, aTolF2, aTol;
1148 TopExp_Explorer aExp;
1150 bRet=Standard_False;
1151 aExp.Init(theF1, TopAbs_EDGE);
1152 for (; aExp.More(); aExp.Next()) {
1153 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
1154 if (!BRep_Tool::Degenerated(aE)) {
1155 aTolF1=BRep_Tool::Tolerance(theF1);
1156 aTolF2=BRep_Tool::Tolerance(theF2);
1158 BOPTools_AlgoTools3D::PointNearEdge(aE, theF1, aP2D, aP, theContext);
1159 bRet=theContext->IsValidPointForFace(aP, theF2, aTol);
1165 //=======================================================================
1168 //=======================================================================
1169 Standard_Integer BOPTools_AlgoTools::Sense (const TopoDS_Face& theF1,
1170 const TopoDS_Face& theF2,
1171 const Handle(IntTools_Context)& theContext)
1173 Standard_Integer iSense=0;
1174 gp_Dir aDNF1, aDNF2;
1175 TopoDS_Edge aE1, aE2;
1176 TopExp_Explorer aExp;
1178 aExp.Init(theF1, TopAbs_EDGE);
1179 for (; aExp.More(); aExp.Next()) {
1180 aE1=(*(TopoDS_Edge*)(&aExp.Current()));
1181 if (!BRep_Tool::Degenerated(aE1)) {
1182 if (!BRep_Tool::IsClosed(aE1, theF1)) {
1188 aExp.Init(theF2, TopAbs_EDGE);
1189 for (; aExp.More(); aExp.Next()) {
1190 aE2=(*(TopoDS_Edge*)(&aExp.Current()));
1191 if (!BRep_Tool::Degenerated(aE2)) {
1192 if (!BRep_Tool::IsClosed(aE2, theF2)) {
1193 if (aE2.IsSame(aE1)) {
1205 BOPTools_AlgoTools3D::GetNormalToFaceOnEdge(aE1, theF1, aDNF1, theContext);
1206 BOPTools_AlgoTools3D::GetNormalToFaceOnEdge(aE2, theF2, aDNF2, theContext);
1208 iSense=BOPTools_AlgoTools3D::SenseFlag(aDNF1, aDNF2);
1212 //=======================================================================
1213 // function: IsSplitToReverse
1215 //=======================================================================
1216 Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse
1217 (const TopoDS_Shape& theSp,
1218 const TopoDS_Shape& theSr,
1219 Handle(IntTools_Context)& theContext)
1221 Standard_Boolean bRet;
1222 TopAbs_ShapeEnum aType;
1224 bRet=Standard_False;
1226 aType=theSp.ShapeType();
1229 const TopoDS_Edge& aESp=(*(TopoDS_Edge*)(&theSp));
1230 const TopoDS_Edge& aESr=(*(TopoDS_Edge*)(&theSr));
1231 bRet=BOPTools_AlgoTools::IsSplitToReverse(aESp, aESr, theContext);
1236 const TopoDS_Face& aFSp=(*(TopoDS_Face*)(&theSp));
1237 const TopoDS_Face& aFSr=(*(TopoDS_Face*)(&theSr));
1238 bRet=BOPTools_AlgoTools::IsSplitToReverse(aFSp, aFSr, theContext);
1247 //=======================================================================
1248 //function :IsSplitToReverse
1250 //=======================================================================
1251 Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse
1252 (const TopoDS_Face& theFSp,
1253 const TopoDS_Face& theFSr,
1254 Handle(IntTools_Context)& theContext)
1257 Handle(Geom_Surface) aSFSp = BRep_Tool::Surface(theFSp);
1258 Handle(Geom_Surface) aSFOr = BRep_Tool::Surface(theFSr);
1259 if (aSFSp == aSFOr) {
1260 return theFSp.Orientation() != theFSr.Orientation();
1263 Standard_Boolean bDone = Standard_False;
1264 // Find the point inside the split face
1269 Standard_Integer iErr;
1270 // Use the hatcher to find the point in the middle of the face
1271 iErr = BOPTools_AlgoTools3D::PointInFace(theFSp, aPFSp, aP2DFSp, theContext);
1273 // Hatcher has failed to find a point.
1274 // Try to get the point near some not closed and
1275 // not degenerated edge on the split face.
1276 TopExp_Explorer anExp(theFSp, TopAbs_EDGE);
1277 for (; anExp.More(); anExp.Next()) {
1278 const TopoDS_Edge& aESp = (*(TopoDS_Edge*)(&anExp.Current()));
1279 if (!BRep_Tool::Degenerated(aESp) && !BRep_Tool::IsClosed(aESp, theFSp)) {
1280 iErr = BOPTools_AlgoTools3D::PointNearEdge
1281 (aESp, theFSp, aP2DFSp, aPFSp, theContext);
1288 if (!anExp.More()) {
1289 // The point has not been found.
1294 // Compute normal direction of the split face
1296 bDone = BOPTools_AlgoTools3D::GetNormalToSurface
1297 (aSFSp, aP2DFSp.X(), aP2DFSp.Y(), aDNFSp);
1302 if (theFSp.Orientation() == TopAbs_REVERSED){
1306 // Project the point from the split face on the original face
1307 // to find its UV coordinates
1308 GeomAPI_ProjectPointOnSurf& aProjector = theContext->ProjPS(theFSr);
1309 aProjector.Perform(aPFSp);
1310 bDone = (aProjector.NbPoints() > 0);
1314 // UV coordinates of the point on the original face
1315 Standard_Real aU, aV;
1316 aProjector.LowerDistanceParameters(aU, aV);
1318 // Compute normal direction for the original face in this point
1320 bDone = BOPTools_AlgoTools3D::GetNormalToSurface(aSFOr, aU, aV, aDNFOr);
1325 if (theFSr.Orientation() == TopAbs_REVERSED) {
1329 // compare the normals
1330 Standard_Real aCos = aDNFSp*aDNFOr;
1333 //=======================================================================
1334 //function :IsSplitToReverse
1336 //=======================================================================
1337 Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse
1338 (const TopoDS_Edge& aEF1,
1339 const TopoDS_Edge& aEF2,
1340 Handle(IntTools_Context)& theContext)
1342 Standard_Boolean bRet, bIsDegenerated;
1344 bRet=Standard_False;
1345 bIsDegenerated=(BRep_Tool::Degenerated(aEF1) ||
1346 BRep_Tool::Degenerated(aEF2));
1347 if (bIsDegenerated) {
1352 TopAbs_Orientation aOrE, aOrSp;
1353 Handle(Geom_Curve)aC1, aC2;
1355 aC2=BRep_Tool::Curve(aEF2, a, b);
1356 aC1=BRep_Tool::Curve(aEF1, a, b);
1359 aOrE=aEF2.Orientation();
1360 aOrSp=aEF1.Orientation();
1365 Standard_Real aT1, aT2, aScPr;
1369 aT1=BOPTools_AlgoTools2D::IntermediatePoint(a, b);
1371 BOPTools_AlgoTools2D::EdgeTangent(aEF1, aT1, aV1);
1374 theContext->ProjectPointOnEdge(aP, aEF2, aT2);
1376 BOPTools_AlgoTools2D::EdgeTangent(aEF2, aT2, aV2);
1385 //=======================================================================
1388 //=======================================================================
1389 Standard_Boolean BOPTools_AlgoTools::IsHole(const TopoDS_Shape& aW,
1390 const TopoDS_Shape& aFace)
1392 Standard_Boolean bIsHole;
1393 Standard_Integer i, aNbS;
1394 Standard_Real aT1, aT2, aS;
1395 Standard_Real aU1, aU, dU;
1396 Standard_Real aX1, aY1, aX0, aY0;
1397 TopAbs_Orientation aOr;
1399 gp_Pnt2d aP2D0, aP2D1;
1400 Handle(Geom2d_Curve) aC2D;
1401 TopoDS_Face aF, aFF;
1402 TopoDS_Iterator aItW;
1404 bIsHole=Standard_False;
1406 aF=(*(TopoDS_Face *)(&aFace));
1408 aFF.Orientation(TopAbs_FORWARD);
1411 aItW.Initialize(aW);
1412 for (; aItW.More(); aItW.Next()) {
1413 const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&aItW.Value()));
1414 aOr=aE.Orientation();
1415 if (!(aOr==TopAbs_FORWARD ||
1416 aOr==TopAbs_REVERSED)) {
1420 aC2D=BRep_Tool::CurveOnSurface(aE, aFF, aT1, aT2);
1421 if (aC2D.IsNull()) {
1425 BRepAdaptor_Curve2d aBAC2D(aE, aFF);
1426 aNbS=Geom2dInt_Geom2dCurveTool::NbSamples(aBAC2D);
1431 dU=(aT2-aT1)/(Standard_Real)(aNbS-1);
1434 if (aOr==TopAbs_REVERSED) {
1440 aBAC2D.D0(aU, aP2D0);
1441 for(i=2; i<=aNbS; i++) {
1443 aBAC2D.D0(aU, aP2D1);
1444 aP2D0.Coord(aX0, aY0);
1445 aP2D1.Coord(aX1, aY1);
1447 aS=aS+(aY0+aY1)*(aX1-aX0);
1451 }//for (; aItW.More(); aItW.Next()) {
1456 //=======================================================================
1457 // function: MakeContainer
1459 //=======================================================================
1460 void BOPTools_AlgoTools::MakeContainer(const TopAbs_ShapeEnum theType,
1466 case TopAbs_COMPOUND:{
1468 aBB.MakeCompound(aC);
1473 case TopAbs_COMPSOLID:{
1474 TopoDS_CompSolid aCS;
1475 aBB.MakeCompSolid(aCS);
1481 TopoDS_Solid aSolid;
1482 aBB.MakeSolid(aSolid);
1489 TopoDS_Shell aShell;
1490 aBB.MakeShell(aShell);
1497 aBB.MakeWire(aWire);
1506 //=======================================================================
1507 // function: MakePCurve
1509 //=======================================================================
1510 void BOPTools_AlgoTools::MakePCurve(const TopoDS_Edge& aE,
1511 const TopoDS_Face& aF1,
1512 const TopoDS_Face& aF2,
1513 const IntTools_Curve& aIC,
1514 const Standard_Boolean bPC1,
1515 const Standard_Boolean bPC2,
1516 const Handle(IntTools_Context)& theContext)
1520 Standard_Real aTolE, aT1, aT2, aOutFirst, aOutLast, aOutTol;
1521 Handle(Geom2d_Curve) aC2D, aC2DA, aC2Dx1;
1524 Standard_Boolean bPC;
1526 aTolE=BRep_Tool::Tolerance(aE);
1528 const Handle(Geom_Curve)& aC3DE=BRep_Tool::Curve(aE, aT1, aT2);
1529 Handle(Geom_TrimmedCurve)aC3DETrim=
1530 new Geom_TrimmedCurve(aC3DE, aT1, aT2);
1532 for (i=0; i<2; ++i) {
1533 bPC = !i ? bPC1 : bPC2;
1540 aC2Dx1=aIC.FirstCurve2d();
1544 aC2Dx1=aIC.SecondCurve2d();
1547 aFFWD.Orientation(TopAbs_FORWARD);
1550 if (aC2D.IsNull()) {
1551 BOPTools_AlgoTools2D::BuildPCurveForEdgeOnFace(aE, aFFWD, theContext);
1552 BOPTools_AlgoTools2D::CurveOnSurface(aE, aFFWD, aC2D,
1553 aOutFirst, aOutLast,
1554 aOutTol, theContext);
1557 if (aC3DE->IsPeriodic()) {
1558 BOPTools_AlgoTools2D::AdjustPCurveOnFace(aFFWD, aT1, aT2, aC2D,
1562 BOPTools_AlgoTools2D::AdjustPCurveOnFace(aFFWD, aC3DETrim, aC2D,
1566 aBB.UpdateEdge(aE, aC2DA, aFFWD, aTolE);
1567 //BRepLib::SameParameter(aE);
1569 BRepLib::SameParameter(aE);
1571 //=======================================================================
1572 // function: MakeEdge
1574 //=======================================================================
1575 void BOPTools_AlgoTools::MakeEdge(const IntTools_Curve& theIC,
1576 const TopoDS_Vertex& theV1,
1577 const Standard_Real theT1,
1578 const TopoDS_Vertex& theV2,
1579 const Standard_Real theT2,
1580 const Standard_Real theTolR3D,
1584 Standard_Real aNeedTol = theTolR3D + 1e-12;
1586 aBB.UpdateVertex(theV1, aNeedTol);
1587 aBB.UpdateVertex(theV2, aNeedTol);
1589 BOPTools_AlgoTools::MakeSectEdge (theIC, theV1, theT1, theV2, theT2,
1592 aBB.UpdateEdge(theE, theTolR3D);
1594 //=======================================================================
1595 // function: ComputeVV
1597 //=======================================================================
1598 Standard_Integer BOPTools_AlgoTools::ComputeVV(const TopoDS_Vertex& aV1,
1600 const Standard_Real aTolP2)
1602 Standard_Real aTolV1, aTolSum, aTolSum2, aD2;
1605 aTolV1=BRep_Tool::Tolerance(aV1);
1607 aTolSum = aTolV1 + aTolP2 + Precision::Confusion();
1608 aTolSum2=aTolSum*aTolSum;
1610 aP1=BRep_Tool::Pnt(aV1);
1612 aD2=aP1.SquareDistance(aP2);
1618 //=======================================================================
1619 // function: ComputeVV
1621 //=======================================================================
1622 Standard_Integer BOPTools_AlgoTools::ComputeVV(const TopoDS_Vertex& aV1,
1623 const TopoDS_Vertex& aV2,
1624 const Standard_Real aFuzz)
1626 Standard_Real aTolV1, aTolV2, aTolSum, aTolSum2, aD2;
1628 Standard_Real aFuzz1 = (aFuzz > Precision::Confusion() ? aFuzz : Precision::Confusion());
1630 aTolV1=BRep_Tool::Tolerance(aV1);
1631 aTolV2=BRep_Tool::Tolerance(aV2);
1632 aTolSum=aTolV1+aTolV2+aFuzz1;
1633 aTolSum2=aTolSum*aTolSum;
1635 aP1=BRep_Tool::Pnt(aV1);
1636 aP2=BRep_Tool::Pnt(aV2);
1638 aD2=aP1.SquareDistance(aP2);
1644 //=======================================================================
1645 // function: MakeVertex
1647 //=======================================================================
1648 void BOPTools_AlgoTools::MakeVertex(const TopTools_ListOfShape& aLV,
1649 TopoDS_Vertex& aVnew)
1651 Standard_Integer aNb = aLV.Extent();
1653 aVnew=*((TopoDS_Vertex*)(&aLV.First()));
1656 Standard_Real aNTol;
1658 BRepLib::BoundingVertex(aLV, aNC, aNTol);
1660 aBB.MakeVertex(aVnew, aNC, aNTol);
1663 //=======================================================================
1664 //function : GetEdgeOnFace
1666 //=======================================================================
1667 Standard_Boolean BOPTools_AlgoTools::GetEdgeOnFace
1668 (const TopoDS_Edge& theE1,
1669 const TopoDS_Face& theF2,
1672 Standard_Boolean bFound;
1673 TopoDS_Iterator aItF, aItW;
1675 bFound=Standard_False;
1677 aItF.Initialize(theF2);
1678 for (; aItF.More(); aItF.Next()) {
1679 const TopoDS_Shape& aW=aItF.Value();
1680 aItW.Initialize(aW);
1681 for (; aItW.More(); aItW.Next()) {
1682 const TopoDS_Shape& aE=aItW.Value();
1683 if (aE.IsSame(theE1)) {
1684 theE2=(*(TopoDS_Edge*)(&aE));
1692 //=======================================================================
1693 //function : FindFacePairs
1695 //=======================================================================
1696 Standard_Boolean FindFacePairs (const TopoDS_Edge& theE,
1697 const TopTools_ListOfShape& thLF,
1698 BOPTools_ListOfCoupleOfShape& theLCFF,
1699 Handle(IntTools_Context)& theContext)
1701 Standard_Boolean bFound;
1702 Standard_Integer i, aNbCEF;
1703 TopAbs_Orientation aOr, aOrC = TopAbs_FORWARD;
1704 TopTools_MapOfShape aMFP;
1705 TopoDS_Face aF1, aF2;
1706 TopoDS_Edge aEL, aE1;
1707 TopTools_ListIteratorOfListOfShape aItLF;
1708 BOPTools_CoupleOfShape aCEF, aCFF;
1709 BOPTools_ListOfCoupleOfShape aLCEF, aLCEFx;
1710 BOPTools_ListIteratorOfListOfCoupleOfShape aIt;
1712 bFound=Standard_True;
1715 aItLF.Initialize(thLF);
1716 for (; aItLF.More(); aItLF.Next()) {
1717 const TopoDS_Face& aFL=(*(TopoDS_Face*)(&aItLF.Value()));
1719 bFound=BOPTools_AlgoTools::GetEdgeOnFace(theE, aFL, aEL);
1721 return bFound; // it can not be so
1724 aCEF.SetShape1(aEL);
1725 aCEF.SetShape2(aFL);
1729 aNbCEF=aLCEF.Extent();
1734 aIt.Initialize(aLCEF);
1735 for (i=0; aIt.More(); aIt.Next(), ++i) {
1736 const BOPTools_CoupleOfShape& aCSx=aIt.Value();
1737 const TopoDS_Shape& aEx=aCSx.Shape1();
1738 const TopoDS_Shape& aFx=aCSx.Shape2();
1740 aOr=aEx.Orientation();
1743 aOrC=TopAbs::Reverse(aOr);
1744 aE1=(*(TopoDS_Edge*)(&aEx));
1745 aF1=(*(TopoDS_Face*)(&aFx));
1751 aLCEFx.Append(aCSx);
1757 BOPTools_AlgoTools::GetFaceOff(aE1, aF1, aLCEFx, aF2, theContext);
1759 aCFF.SetShape1(aF1);
1760 aCFF.SetShape2(aF2);
1761 theLCFF.Append(aCFF);
1770 aIt.Initialize(aLCEFx);
1771 for (; aIt.More(); aIt.Next()) {
1772 const BOPTools_CoupleOfShape& aCSx=aIt.Value();
1773 const TopoDS_Shape& aFx=aCSx.Shape2();
1774 if (!aMFP.Contains(aFx)) {
1779 aNbCEF=aLCEF.Extent();
1784 //=======================================================================
1785 //function : AngleWithRef
1787 //=======================================================================
1788 Standard_Real AngleWithRef(const gp_Dir& theD1,
1789 const gp_Dir& theD2,
1790 const gp_Dir& theDRef)
1792 Standard_Real aCosinus, aSinus, aBeta, aHalfPI, aScPr;
1797 const gp_XYZ& aXYZ1=theD1.XYZ();
1798 const gp_XYZ& aXYZ2=theD2.XYZ();
1799 aXYZ=aXYZ1.Crossed(aXYZ2);
1800 aSinus=aXYZ.Modulus();
1801 aCosinus=theD1*theD2;
1805 aBeta=aHalfPI*(1.-aCosinus);
1808 aBeta=2.*M_PI-aHalfPI*(3.+aCosinus);
1811 aScPr=aXYZ.Dot(theDRef.XYZ());
1817 //=======================================================================
1818 // function: IsBlockInOnFace
1820 //=======================================================================
1821 Standard_Boolean BOPTools_AlgoTools::IsBlockInOnFace
1822 (const IntTools_Range& aShrR,
1823 const TopoDS_Face& aF,
1824 const TopoDS_Edge& aE1,
1825 Handle(IntTools_Context)& aContext)
1827 Standard_Boolean bFlag;
1828 Standard_Real f1, l1, ULD, VLD;
1832 aShrR.Range(f1, l1);
1833 Standard_Real dt=0.0075, k;//dt=0.001, k;
1839 BOPTools_AlgoTools::PointOnEdge(aE1, f1, aP11);
1841 GeomAPI_ProjectPointOnSurf& aProjector=aContext->ProjPS(aF);
1842 aProjector.Perform(aP11);
1844 bFlag=aProjector.IsDone();
1849 aProjector.LowerDistanceParameters(ULD, VLD);
1850 aP2D.SetCoord(ULD, VLD);
1852 bFlag=aContext->IsPointInOnFace (aF, aP2D);
1859 BOPTools_AlgoTools::PointOnEdge(aE1, l1, aP12);
1861 aProjector.Perform(aP12);
1863 bFlag=aProjector.IsDone();
1868 aProjector.LowerDistanceParameters(ULD, VLD);
1869 aP2D.SetCoord(ULD, VLD);
1871 bFlag=aContext->IsPointInOnFace (aF, aP2D);
1877 // Treatment intemediate
1878 Standard_Real m1, aTolF, aTolE, aTol, aDist;
1879 m1=IntTools_Tools::IntermediatePoint(f1, l1);
1880 BOPTools_AlgoTools::PointOnEdge(aE1, m1, aP12);
1882 aProjector.Perform(aP12);
1884 bFlag=aProjector.IsDone();
1889 aTolE=BRep_Tool::Tolerance(aE1);
1890 aTolF=BRep_Tool::Tolerance(aF);
1892 aDist=aProjector.LowerDistance();
1894 return Standard_False;
1897 aProjector.LowerDistanceParameters(ULD, VLD);
1898 aP2D.SetCoord(ULD, VLD);
1900 bFlag=aContext->IsPointInOnFace (aF, aP2D);
1908 //=======================================================================
1909 //function : IsMicroEdge
1911 //=======================================================================
1912 Standard_Boolean BOPTools_AlgoTools::IsMicroEdge
1913 (const TopoDS_Edge& aE,
1914 const Handle(IntTools_Context)& aCtx,
1915 const Standard_Boolean bCheckSplittable)
1917 Standard_Boolean bRet;
1918 Standard_Real aT1, aT2, aTmp;
1919 Handle(Geom_Curve) aC3D;
1920 TopoDS_Vertex aV1, aV2;
1922 bRet=(BRep_Tool::Degenerated(aE) ||
1923 !BRep_Tool::IsGeometric(aE));
1928 aC3D=BRep_Tool::Curve(aE, aT1, aT2);
1929 TopExp::Vertices(aE, aV1, aV2);
1930 aT1=BRep_Tool::Parameter(aV1, aE);
1931 aT2=BRep_Tool::Parameter(aV2, aE);
1938 IntTools_ShrunkRange aSR;
1939 aSR.SetContext(aCtx);
1940 aSR.SetData(aE, aT1, aT2, aV1, aV2);
1942 bRet = !aSR.IsDone();
1943 if (!bRet && bCheckSplittable) {
1944 bRet = !aSR.IsSplittable();
1950 //=======================================================================
1951 //function : GetFaceDir
1952 //purpose : Get binormal direction for the face in the point aP
1953 //=======================================================================
1954 Standard_Boolean GetFaceDir(const TopoDS_Edge& aE,
1955 const TopoDS_Face& aF,
1957 const Standard_Real aT,
1958 const gp_Dir& aDTgt,
1959 const Standard_Boolean theSmallFaces,
1962 Handle(IntTools_Context)& theContext,
1963 GeomAPI_ProjectPointOnSurf& aProjPL,
1964 const Standard_Real aDt)
1966 Standard_Real aTolE;
1969 BOPTools_AlgoTools3D::GetNormalToFaceOnEdge(aE, aF, aT, aDN, theContext);
1970 if (aF.Orientation()==TopAbs_REVERSED){
1974 aTolE=BRep_Tool::Tolerance(aE);
1977 // do not try to look for the point in the small face by intersecting
1978 // it with the circle because, most likely, the intersection point will
1979 // be out of the face
1980 Standard_Boolean bFound = !theSmallFaces &&
1981 FindPointInFace(aF, aP, aDB, aPx, theContext, aProjPL, aDt, aTolE);
1983 // if the first method did not succeed, try to use hatcher to find the point
1984 bFound = BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge
1985 (aE, aF, aT, aDt, aPx, aDN, theContext);
1986 aProjPL.Perform(aPx);
1987 Standard_ASSERT_RETURN(aProjPL.IsDone(),
1988 "GetFaceDir: Project point on plane is failed", Standard_False);
1989 aPx = aProjPL.NearestPoint();
1990 gp_Vec aVec(aP, aPx);
1991 aDB.SetXYZ(aVec.XYZ());
1996 //=======================================================================
1997 //function : FindPointInFace
1998 //purpose : Find a point in the face in direction of <aDB>.
1999 // To get this point the method intersects the circle with radius
2000 // <aDt> built in point <aP> with normal perpendicular to <aDB>.
2001 //=======================================================================
2002 Standard_Boolean FindPointInFace(const TopoDS_Face& aF,
2006 Handle(IntTools_Context)& theContext,
2007 GeomAPI_ProjectPointOnSurf& aProjPL,
2008 const Standard_Real aDt,
2009 const Standard_Real aTolE)
2011 Standard_Integer aNbItMax;
2012 Standard_Real aDist, aDTol, aPM, anEps;
2013 Standard_Boolean bRet;
2016 aDTol = Precision::Angular();
2017 aPM = aP.XYZ().Modulus();
2019 aDTol = 5.e-16 * aPM;
2021 bRet = Standard_False;
2023 anEps = Precision::SquareConfusion();
2025 GeomAPI_ProjectPointOnSurf& aProj=theContext->ProjPS(aF);
2029 if (!aProj.IsDone()) {
2032 aPS=aProj.NearestPoint();
2033 aProjPL.Perform(aPS);
2034 aPS=aProjPL.NearestPoint();
2036 aPS.SetXYZ(aPS.XYZ()+2.*aTolE*aDB.XYZ());
2038 if (!aProj.IsDone()) {
2041 aPS=aProj.NearestPoint();
2042 aProjPL.Perform(aPS);
2043 aPS=aProjPL.NearestPoint();
2046 aP1.SetXYZ(aPS.XYZ()+aDt*aDB.XYZ());
2049 if (!aProj.IsDone()) {
2052 aPOut = aProj.NearestPoint();
2053 aDist = aProj.LowerDistance();
2055 aProjPL.Perform(aPOut);
2056 aPOut = aProjPL.NearestPoint();
2058 gp_Vec aV(aPS, aPOut);
2059 if (aV.SquareMagnitude() < anEps) {
2062 aDB.SetXYZ(aV.XYZ());
2063 } while (aDist > aDTol && --aNbItMax);
2065 bRet = aDist < aDTol;
2068 //=======================================================================
2069 //function : MinStep3D
2071 //=======================================================================
2072 Standard_Real MinStep3D(const TopoDS_Edge& theE1,
2073 const TopoDS_Face& theF1,
2074 const BOPTools_ListOfCoupleOfShape& theLCS,
2076 Handle(IntTools_Context)& theContext,
2077 Standard_Boolean& theSmallFaces)
2079 Standard_Real aDt, aTolE, aTolF, aDtMax, aDtMin;
2081 // add the current pair of edge/face for checking as well
2082 BOPTools_CoupleOfShape aCS1;
2083 aCS1.SetShape1(theE1);
2084 aCS1.SetShape2(theF1);
2086 BOPTools_ListOfCoupleOfShape aLCS = theLCS;
2089 aTolE = BRep_Tool::Tolerance(theE1);
2093 BOPTools_ListIteratorOfListOfCoupleOfShape aIt(aLCS);
2094 for (; aIt.More(); aIt.Next()) {
2095 const BOPTools_CoupleOfShape& aCS = aIt.Value();
2096 const TopoDS_Face& aF = (*(TopoDS_Face*)(&aCS.Shape2()));
2098 aTolF = BRep_Tool::Tolerance(aF);
2099 aDt = 2*(aTolE + aTolF);
2104 // try to compute the minimal 3D step
2105 const BRepAdaptor_Surface& aBAS = theContext->SurfaceAdaptor(aF);
2106 Standard_Real aR = 0.;
2107 GeomAbs_SurfaceType aSType = aBAS.GetType();
2109 case GeomAbs_Cylinder: {
2110 aR = aBAS.Cylinder().Radius();
2113 case GeomAbs_Cone: {
2114 gp_Lin aL(aBAS.Cone().Axis());
2115 aR = aL.Distance(aP);
2118 case GeomAbs_Sphere: {
2119 aDtMin = Max(aDtMin, 5.e-4);
2120 aR = aBAS.Sphere().Radius();
2123 case GeomAbs_Torus: {
2124 aR = aBAS.Torus().MajorRadius();
2128 aDtMin = Max(aDtMin, 5.e-4);
2133 Standard_Real d = 10*Precision::PConfusion();
2134 aDtMin = Max(aDtMin, sqrt(d*d + 2*d*aR));
2138 if (aDtMax < aDtMin) {
2142 // check if the computed 3D step is too big for any of the faces in the list
2143 aIt.Initialize(aLCS);
2144 for (; aIt.More(); aIt.Next()) {
2145 const BOPTools_CoupleOfShape& aCS = aIt.Value();
2146 const TopoDS_Face& aF = (*(TopoDS_Face*)(&aCS.Shape2()));
2148 const BRepAdaptor_Surface& aBAS = theContext->SurfaceAdaptor(aF);
2150 Standard_Real aUMin, aUMax, aVMin, aVMax;
2151 theContext->UVBounds(aF, aUMin, aUMax, aVMin, aVMax);
2153 Standard_Real aDU = aUMax - aUMin;
2155 Standard_Real aURes = aBAS.UResolution(aDtMax);
2156 if (2*aURes > aDU) {
2161 Standard_Real aDV = aVMax - aVMin;
2163 Standard_Real aVRes = aBAS.VResolution(aDtMax);
2164 if (2*aVRes > aDV) {
2170 theSmallFaces = aIt.More();
2174 //=======================================================================
2175 //function : IsOpenShell
2177 //=======================================================================
2178 Standard_Boolean BOPTools_AlgoTools::IsOpenShell(const TopoDS_Shell& aSh)
2180 Standard_Boolean bRet;
2181 Standard_Integer i, aNbE, aNbF;
2182 TopAbs_Orientation aOrF;
2183 TopTools_IndexedDataMapOfShapeListOfShape aMEF;
2184 TopTools_ListIteratorOfListOfShape aItLS;
2186 bRet=Standard_False;
2188 TopExp::MapShapesAndAncestors(aSh, TopAbs_EDGE, TopAbs_FACE, aMEF);
2191 for (i=1; i<=aNbE; ++i) {
2192 const TopoDS_Edge& aE=*((TopoDS_Edge*)&aMEF.FindKey(i));
2193 if (BRep_Tool::Degenerated(aE)) {
2198 const TopTools_ListOfShape& aLF=aMEF(i);
2199 aItLS.Initialize(aLF);
2200 for (; aItLS.More(); aItLS.Next()) {
2201 const TopoDS_Shape& aF=aItLS.Value();
2202 aOrF=aF.Orientation();
2203 if (aOrF==TopAbs_INTERNAL || aOrF==TopAbs_EXTERNAL) {
2217 //=======================================================================
2218 //function : IsInvertedSolid
2220 //=======================================================================
2221 Standard_Boolean BOPTools_AlgoTools::IsInvertedSolid
2222 (const TopoDS_Solid& aSolid)
2224 Standard_Real aTolS;
2225 TopAbs_State aState;
2226 BRepClass3d_SolidClassifier aSC(aSolid);
2229 aSC.PerformInfinitePoint(aTolS);
2231 return (aState==TopAbs_IN);