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 <BOPAlgo_Alerts.hxx>
21 #include <BOPTools_AlgoTools2D.hxx>
22 #include <BOPTools_AlgoTools3D.hxx>
23 #include <BOPTools_CoupleOfShape.hxx>
24 #include <BOPTools_ListOfCoupleOfShape.hxx>
25 #include <BRep_Builder.hxx>
26 #include <BRep_Tool.hxx>
27 #include <BRepAdaptor_Curve2d.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_Range.hxx>
47 #include <IntTools_ShrunkRange.hxx>
48 #include <IntTools_Tools.hxx>
49 #include <Precision.hxx>
50 #include <TopAbs_Orientation.hxx>
52 #include <TopExp_Explorer.hxx>
54 #include <TopoDS_Compound.hxx>
55 #include <TopoDS_CompSolid.hxx>
56 #include <TopoDS_Edge.hxx>
57 #include <TopoDS_Face.hxx>
58 #include <TopoDS_Shape.hxx>
59 #include <TopoDS_Shell.hxx>
60 #include <TopoDS_Solid.hxx>
61 #include <TopoDS_Vertex.hxx>
62 #include <TopoDS_Wire.hxx>
63 #include <TopTools_IndexedMapOfShape.hxx>
64 #include <TopTools_MapOfShape.hxx>
65 #include <TopTools_MapOfOrientedShape.hxx>
66 #include <Message_Report.hxx>
71 Standard_Real AngleWithRef(const gp_Dir& theD1,
73 const gp_Dir& theDRef);
76 Standard_Boolean FindFacePairs (const TopoDS_Edge& theE,
77 const TopTools_ListOfShape& thLF,
78 BOPTools_ListOfCoupleOfShape& theLCFF,
79 const Handle(IntTools_Context)& theContext);
81 TopAbs_Orientation Orientation(const TopoDS_Edge& anE,
82 const TopoDS_Face& aF);
85 Standard_Boolean GetFaceDir(const TopoDS_Edge& aE,
86 const TopoDS_Face& aF,
88 const Standard_Real aT,
90 const Standard_Boolean theSmallFaces,
93 const Handle(IntTools_Context)& theContext,
94 GeomAPI_ProjectPointOnSurf& aProjPL,
95 const Standard_Real aDt);
97 Standard_Boolean FindPointInFace(const TopoDS_Face& aF,
101 const Handle(IntTools_Context)& theContext,
102 GeomAPI_ProjectPointOnSurf& aProjPL,
103 const Standard_Real aDt,
104 const Standard_Real aTolE);
106 Standard_Real MinStep3D(const TopoDS_Edge& theE1,
107 const TopoDS_Face& theF1,
108 const BOPTools_ListOfCoupleOfShape& theLCS,
110 const Handle(IntTools_Context)& theContext,
111 Standard_Boolean& theSmallFaces);
115 //=======================================================================
116 // function: MakeConnexityBlocks
118 //=======================================================================
119 void BOPTools_AlgoTools::MakeConnexityBlocks
120 (const TopoDS_Shape& theS,
121 const TopAbs_ShapeEnum theConnectionType,
122 const TopAbs_ShapeEnum theElementType,
123 TopTools_ListOfListOfShape& theLCB,
124 TopTools_IndexedDataMapOfShapeListOfShape& theConnectionMap)
126 // Map shapes to find connected elements
127 TopExp::MapShapesAndAncestors(theS, theConnectionType, theElementType, theConnectionMap);
129 TopTools_MapOfShape aMFence;
131 TopExp_Explorer aExp(theS, theElementType);
132 for (; aExp.More(); aExp.Next())
134 const TopoDS_Shape& aS = aExp.Current();
135 if (!aMFence.Add(aS)) {
139 TopTools_ListOfShape aLBlock;
142 // Look for connected parts
143 TopTools_ListIteratorOfListOfShape aItB(aLBlock);
144 for (; aItB.More(); aItB.Next())
146 const TopoDS_Shape& aS1 = aItB.Value();
147 TopExp_Explorer aExpSS(aS1, theConnectionType);
148 for (; aExpSS.More(); aExpSS.Next())
150 const TopoDS_Shape& aSubS = aExpSS.Current();
151 const TopTools_ListOfShape& aLS = theConnectionMap.FindFromKey(aSubS);
152 TopTools_ListIteratorOfListOfShape aItLS(aLS);
153 for (; aItLS.More(); aItLS.Next())
155 const TopoDS_Shape& aS2 = aItLS.Value();
156 if (aMFence.Add(aS2))
161 // Add the block into result
162 theLCB.Append(aLBlock);
166 //=======================================================================
167 // function: MakeConnexityBlocks
169 //=======================================================================
170 void BOPTools_AlgoTools::MakeConnexityBlocks
171 (const TopoDS_Shape& theS,
172 const TopAbs_ShapeEnum theConnectionType,
173 const TopAbs_ShapeEnum theElementType,
174 TopTools_ListOfShape& theLCB)
176 TopTools_ListOfListOfShape aLBlocks;
177 TopTools_IndexedDataMapOfShapeListOfShape aCMap;
178 BOPTools_AlgoTools::MakeConnexityBlocks(theS, theConnectionType, theElementType, aLBlocks, aCMap);
180 // Make compound from each block
181 TopTools_ListIteratorOfListOfListOfShape aItB(aLBlocks);
182 for (; aItB.More(); aItB.Next())
184 const TopTools_ListOfShape& aLB = aItB.Value();
186 TopoDS_Compound aBlock;
187 BRep_Builder().MakeCompound(aBlock);
188 for (TopTools_ListIteratorOfListOfShape it(aLB); it.More(); it.Next())
189 BRep_Builder().Add(aBlock, it.Value());
191 theLCB.Append(aBlock);
195 //=======================================================================
196 // function: MakeConnexityBlocks
198 //=======================================================================
199 void BOPTools_AlgoTools::MakeConnexityBlocks
200 (const TopTools_ListOfShape& theLS,
201 const TopAbs_ShapeEnum theConnectionType,
202 const TopAbs_ShapeEnum theElementType,
203 BOPTools_ListOfConnexityBlock& theLCB)
206 // Make connexity blocks from start elements
207 TopoDS_Compound aCStart;
208 aBB.MakeCompound(aCStart);
210 TopTools_MapOfShape aMFence, aMNRegular;
212 TopTools_ListIteratorOfListOfShape aItL(theLS);
213 for (; aItL.More(); aItL.Next())
215 const TopoDS_Shape& aS = aItL.Value();
217 aBB.Add(aCStart, aS);
222 TopTools_ListOfListOfShape aLCB;
223 TopTools_IndexedDataMapOfShapeListOfShape aCMap;
224 BOPTools_AlgoTools::MakeConnexityBlocks(aCStart, theConnectionType, theElementType, aLCB, aCMap);
226 // Save the blocks and check their regularity
227 TopTools_ListIteratorOfListOfListOfShape aItB(aLCB);
228 for (; aItB.More(); aItB.Next())
230 const TopTools_ListOfShape& aBlock = aItB.Value();
232 BOPTools_ConnexityBlock aCB;
233 TopTools_ListOfShape& aLCS = aCB.ChangeShapes();
235 Standard_Boolean bRegular = Standard_True;
236 for (TopTools_ListIteratorOfListOfShape it(aBlock); it.More(); it.Next())
238 TopoDS_Shape aS = it.Value();
239 if (aMNRegular.Contains(aS))
241 bRegular = Standard_False;
242 aS.Orientation(TopAbs_FORWARD);
244 aS.Orientation(TopAbs_REVERSED);
252 // Check if there are no multi-connected shapes
253 for (TopExp_Explorer ex(aS, theConnectionType); ex.More() && bRegular; ex.Next())
254 bRegular = (aCMap.FindFromKey(ex.Current()).Extent() == 2);
259 aCB.SetRegular(bRegular);
264 //=======================================================================
265 // function: OrientEdgesOnWire
266 // purpose: Reorient edges on wire for correct ordering
267 //=======================================================================
268 void BOPTools_AlgoTools::OrientEdgesOnWire(TopoDS_Shape& theWire)
270 // make vertex-edges connexity map
271 TopTools_IndexedDataMapOfShapeListOfShape aVEMap;
272 TopExp::MapShapesAndAncestors(theWire, TopAbs_VERTEX, TopAbs_EDGE, aVEMap);
274 if (aVEMap.IsEmpty()) {
283 TopTools_MapOfOrientedShape aMFence;
285 TopoDS_Iterator aIt(theWire);
286 for (; aIt.More(); aIt.Next()) {
287 const TopoDS_Edge& aEC = TopoDS::Edge(aIt.Value());
288 if (!aMFence.Add(aEC)) {
292 // add edge to a wire as it is
295 TopoDS_Vertex aV1, aV2;
296 TopExp::Vertices(aEC, aV1, aV2, Standard_True);
298 if (aV1.IsSame(aV2)) {
299 // closed edge, go to the next edge
303 // orient the adjacent edges
304 for (Standard_Integer i = 0; i < 2; ++i) {
305 TopoDS_Shape aVC = !i ? aV1 : aV2;
308 const TopTools_ListOfShape& aLE = aVEMap.FindFromKey(aVC);
309 if (aLE.Extent() != 2) {
310 // free vertex or multi-connexity, go to the next edge
314 Standard_Boolean bStop = Standard_True;
316 TopTools_ListIteratorOfListOfShape aItLE(aLE);
317 for (; aItLE.More(); aItLE.Next()) {
318 const TopoDS_Edge& aEN = TopoDS::Edge(aItLE.Value());
319 if (aMFence.Contains(aEN)) {
323 TopoDS_Vertex aVN1, aVN2;
324 TopExp::Vertices(aEN, aVN1, aVN2, Standard_True);
325 if (aVN1.IsSame(aVN2)) {
326 // closed edge, go to the next edge
330 // change orientation if necessary and go to the next edges
331 if ((!i && aVC.IsSame(aVN2)) || (i && aVC.IsSame(aVN1))) {
335 aBB.Add(aWire, aEN.Reversed());
338 aVC = aVC.IsSame(aVN1) ? aVN2 : aVN1;
339 bStop = Standard_False;
352 //=======================================================================
353 // function: OrientFacesOnShell
355 //=======================================================================
356 void BOPTools_AlgoTools::OrientFacesOnShell (TopoDS_Shape& aShell)
358 Standard_Boolean bIsProcessed1, bIsProcessed2;
359 Standard_Integer i, aNbE, aNbF, j;
360 TopAbs_Orientation anOrE1, anOrE2;
361 TopoDS_Face aF1x, aF2x;
362 TopoDS_Shape aShellNew;
363 TopTools_IndexedDataMapOfShapeListOfShape aEFMap;
364 TopTools_IndexedMapOfShape aProcessedFaces;
367 BOPTools_AlgoTools::MakeContainer(TopAbs_SHELL, aShellNew);
369 TopExp::MapShapesAndAncestors(aShell,
370 TopAbs_EDGE, TopAbs_FACE,
372 aNbE=aEFMap.Extent();
374 // One seam edge in aEFMap contains 2 equivalent faces.
375 for (i=1; i<=aNbE; ++i) {
376 TopTools_ListOfShape& aLF=aEFMap.ChangeFromIndex(i);
379 TopTools_ListOfShape aLFTmp;
380 TopTools_IndexedMapOfShape aFM;
382 TopTools_ListIteratorOfListOfShape anIt(aLF);
383 for (; anIt.More(); anIt.Next()) {
384 const TopoDS_Shape& aF=anIt.Value();
385 if (!aFM.Contains(aF)) {
396 for (i=1; i<=aNbE; ++i) {
397 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aEFMap.FindKey(i)));
398 if (BRep_Tool::Degenerated(aE)) {
402 const TopTools_ListOfShape& aLF=aEFMap.FindFromIndex(i);
408 TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First()));
409 TopoDS_Face& aF2=(*(TopoDS_Face*)(&aLF.Last()));
411 bIsProcessed1=aProcessedFaces.Contains(aF1);
412 bIsProcessed2=aProcessedFaces.Contains(aF2);
413 if (bIsProcessed1 && bIsProcessed2) {
417 if (!bIsProcessed1 && !bIsProcessed2) {
418 aProcessedFaces.Add(aF1);
419 aBB.Add(aShellNew, aF1);
420 bIsProcessed1=!bIsProcessed1;
425 j=aProcessedFaces.FindIndex(aF1);
426 aF1x=(*(TopoDS_Face*)(&aProcessedFaces.FindKey(j)));
431 j=aProcessedFaces.FindIndex(aF2);
432 aF2x=(*(TopoDS_Face*)(&aProcessedFaces.FindKey(j)));
435 anOrE1=Orientation(aE, aF1x);
436 anOrE2=Orientation(aE, aF2x);
438 if (bIsProcessed1 && !bIsProcessed2) {
439 if (anOrE1==anOrE2) {
440 if (!BRep_Tool::IsClosed(aE, aF1) &&
441 !BRep_Tool::IsClosed(aE, aF2)) {
445 aProcessedFaces.Add(aF2);
446 aBB.Add(aShellNew, aF2);
448 else if (!bIsProcessed1 && bIsProcessed2) {
449 if (anOrE1==anOrE2) {
450 if (!BRep_Tool::IsClosed(aE, aF1) &&
451 !BRep_Tool::IsClosed(aE, aF2)) {
455 aProcessedFaces.Add(aF1);
456 aBB.Add(aShellNew, aF1);
461 for (i=1; i<=aNbE; ++i) {
462 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aEFMap.FindKey(i)));
463 if (BRep_Tool::Degenerated(aE)) {
467 const TopTools_ListOfShape& aLF=aEFMap.FindFromIndex(i);
470 TopTools_ListIteratorOfListOfShape anIt(aLF);
471 for(; anIt.More(); anIt.Next()) {
472 const TopoDS_Face& aF=(*(TopoDS_Face*)(&anIt.Value()));
473 if (!aProcessedFaces.Contains(aF)) {
474 aProcessedFaces.Add(aF);
475 aBB.Add(aShellNew, aF);
482 //=======================================================================
483 //function : Orientation
485 //=======================================================================
486 TopAbs_Orientation Orientation(const TopoDS_Edge& anE,
487 const TopoDS_Face& aF)
489 TopAbs_Orientation anOr=TopAbs_INTERNAL;
491 TopExp_Explorer anExp;
492 anExp.Init(aF, TopAbs_EDGE);
493 for (; anExp.More(); anExp.Next()) {
494 const TopoDS_Edge& anEF1=(*(TopoDS_Edge*)(&anExp.Current()));
495 if (anEF1.IsSame(anE)) {
496 anOr=anEF1.Orientation();
502 //=======================================================================
503 // function: MakeConnexityBlock.
505 //=======================================================================
506 void BOPTools_AlgoTools::MakeConnexityBlock
507 (TopTools_ListOfShape& theLFIn,
508 TopTools_IndexedMapOfShape& theMEAvoid,
509 TopTools_ListOfShape& theLCB,
510 const Handle(NCollection_BaseAllocator)& theAllocator)
512 Standard_Integer aNbF, aNbAdd1, aNbAdd, i;
513 TopExp_Explorer aExp;
514 TopTools_ListIteratorOfListOfShape aIt;
516 TopTools_IndexedMapOfShape aMCB(100, theAllocator);
517 TopTools_IndexedMapOfShape aMAdd(100, theAllocator);
518 TopTools_IndexedMapOfShape aMAdd1(100, theAllocator);
519 TopTools_IndexedDataMapOfShapeListOfShape aMEF(100, theAllocator);
522 aNbF=theLFIn.Extent();
523 aIt.Initialize(theLFIn);
524 for (; aIt.More(); aIt.Next()) {
525 const TopoDS_Shape& aF=aIt.Value();
526 TopExp::MapShapesAndAncestors(aF, TopAbs_EDGE, TopAbs_FACE, aMEF);
530 const TopoDS_Shape& aF1=theLFIn.First();
535 aNbAdd = aMAdd.Extent();
536 for (i=1; i<=aNbAdd; ++i) {
537 const TopoDS_Shape& aF=aMAdd(i);
540 aExp.Init(aF, TopAbs_EDGE);
541 for (; aExp.More(); aExp.Next()) {
542 const TopoDS_Shape& aE=aExp.Current();
543 if (theMEAvoid.Contains(aE)){
547 const TopTools_ListOfShape& aLF=aMEF.FindFromKey(aE);
549 for (; aIt.More(); aIt.Next()) {
550 const TopoDS_Shape& aFx=aIt.Value();
551 if (aFx.IsSame(aF)) {
554 if (aMCB.Contains(aFx)) {
559 }//for (; aExp.More(); aExp.Next()){
561 }// for (i=1; i<=aNbAdd; ++i) {
563 aNbAdd1=aMAdd1.Extent();
569 for (i=1; i<=aNbAdd1; ++i) {
570 const TopoDS_Shape& aFAdd=aMAdd1(i);
578 for (i=1; i<=aNbF; ++i) {
579 const TopoDS_Shape& aF=aMCB(i);
583 //=======================================================================
584 // function: ComputeStateByOnePoint
586 //=======================================================================
587 TopAbs_State BOPTools_AlgoTools::ComputeStateByOnePoint
588 (const TopoDS_Shape& theS,
589 const TopoDS_Solid& theRef,
590 const Standard_Real theTol,
591 const Handle(IntTools_Context)& theContext)
593 TopAbs_State aState = TopAbs_UNKNOWN;
594 TopAbs_ShapeEnum aType = theS.ShapeType();
599 aState = ComputeState(TopoDS::Vertex(theS), theRef, theTol, theContext);
602 aState = ComputeState(TopoDS::Edge(theS), theRef, theTol, theContext);
606 TopTools_IndexedMapOfShape aBounds;
607 TopExp::MapShapes(theRef, TopAbs_EDGE, aBounds);
608 aState = ComputeState(TopoDS::Face(theS), theRef, theTol, aBounds, theContext);
613 TopoDS_Iterator it(theS);
615 ComputeStateByOnePoint(it.Value(), theRef, theTol, theContext);
622 //=======================================================================
623 // function: ComputeState
625 //=======================================================================
626 TopAbs_State BOPTools_AlgoTools::ComputeState
627 (const TopoDS_Face& theF,
628 const TopoDS_Solid& theRef,
629 const Standard_Real theTol,
630 const TopTools_IndexedMapOfShape& theBounds,
631 const Handle(IntTools_Context)& theContext)
633 TopAbs_State aState = TopAbs_UNKNOWN;
635 // Try to find the edge on the face which does not
636 // belong to the solid and classify the middle point of that
637 // edge relatively solid.
638 TopExp_Explorer aExp(theF, TopAbs_EDGE);
639 for (; aExp.More(); aExp.Next())
641 const TopoDS_Edge& aSE = (*(TopoDS_Edge*)(&aExp.Current()));
642 if (BRep_Tool::Degenerated(aSE))
645 if (!theBounds.Contains(aSE))
647 aState = BOPTools_AlgoTools::ComputeState(aSE, theRef, theTol, theContext);
652 // All edges of the face are on the solid.
653 // Get point inside the face and classify it relatively solid.
656 Standard_Integer iErr = BOPTools_AlgoTools3D::PointInFace(theF, aP3D, aP2D, theContext);
659 // Hatcher fails to find the point -> get point near some edge
660 aExp.Init(theF, TopAbs_EDGE);
661 for (; aExp.More() && iErr != 0; aExp.Next())
663 const TopoDS_Edge& aSE = TopoDS::Edge(aExp.Current());
664 if (BRep_Tool::Degenerated(aSE))
667 iErr = BOPTools_AlgoTools3D::PointNearEdge(aSE, theF, aP2D, aP3D, theContext);
672 aState = BOPTools_AlgoTools::ComputeState(aP3D, theRef, theTol, theContext);
676 //=======================================================================
677 // function: ComputeState
679 //=======================================================================
680 TopAbs_State BOPTools_AlgoTools::ComputeState
681 (const TopoDS_Vertex& theV,
682 const TopoDS_Solid& theRef,
683 const Standard_Real theTol,
684 const Handle(IntTools_Context)& theContext)
689 aP3D=BRep_Tool::Pnt(theV);
690 aState=BOPTools_AlgoTools::ComputeState(aP3D, theRef, theTol,
694 //=======================================================================
695 // function: ComputeState
697 //=======================================================================
698 TopAbs_State BOPTools_AlgoTools::ComputeState
699 (const TopoDS_Edge& theE,
700 const TopoDS_Solid& theRef,
701 const Standard_Real theTol,
702 const Handle(IntTools_Context)& theContext)
704 Standard_Real aT1, aT2, aT = 0.;
706 Handle(Geom_Curve) aC3D;
709 aC3D = BRep_Tool::Curve(theE, aT1, aT2);
712 //it means that we are in degenerated edge
713 const TopoDS_Vertex& aV = TopExp::FirstVertex(theE);
715 return TopAbs_UNKNOWN;
717 aP3D=BRep_Tool::Pnt(aV);
720 Standard_Boolean bF2Inf, bL2Inf;
721 Standard_Real dT=10.;
723 bF2Inf = Precision::IsNegativeInfinite(aT1);
724 bL2Inf = Precision::IsPositiveInfinite(aT2);
726 if (bF2Inf && !bL2Inf) {
729 else if (!bF2Inf && bL2Inf) {
732 else if (bF2Inf && bL2Inf) {
736 aT=IntTools_Tools::IntermediatePoint(aT1, aT2);
741 aState=BOPTools_AlgoTools::ComputeState(aP3D, theRef, theTol,
746 //=======================================================================
747 // function: ComputeState
749 //=======================================================================
750 TopAbs_State BOPTools_AlgoTools::ComputeState
752 const TopoDS_Solid& theRef,
753 const Standard_Real theTol,
754 const Handle(IntTools_Context)& theContext)
758 BRepClass3d_SolidClassifier& aSC=theContext->SolidClassifier(theRef);
759 aSC.Perform(theP, theTol);
765 //=======================================================================
766 //function : IsInternalFace
768 //=======================================================================
769 Standard_Boolean BOPTools_AlgoTools::IsInternalFace
770 (const TopoDS_Face& theFace,
771 const TopoDS_Solid& theSolid,
772 TopTools_IndexedDataMapOfShapeListOfShape& theMEF,
773 const Standard_Real theTol,
774 const Handle(IntTools_Context)& theContext)
776 Standard_Boolean bDegenerated;
777 TopAbs_Orientation aOr;
779 TopExp_Explorer aExp;
780 TopTools_ListIteratorOfListOfShape aItF;
782 // For all invoked functions: [::IsInternalFace(...)]
783 // the returned value iRet means:
784 // iRet=0; - state is not IN
785 // iRet=1; - state is IN
786 // iRet=2; - state can not be found by the method of angles
787 Standard_Integer iRet = 0;
788 // 1 Try to find an edge from theFace in theMEF
789 aExp.Init(theFace, TopAbs_EDGE);
790 for(; aExp.More(); aExp.Next()) {
791 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
792 if (!theMEF.Contains(aE)) {
796 aOr=aE.Orientation();
797 if (aOr==TopAbs_INTERNAL) {
800 bDegenerated=BRep_Tool::Degenerated(aE);
805 TopTools_ListOfShape& aLF=theMEF.ChangeFromKey(aE);
806 Standard_Integer aNbF = aLF.Extent();
808 // aE is internal edge on aLF.First()
809 const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First()));
810 BOPTools_AlgoTools::GetEdgeOnFace(aE, aF1, aE1);
811 if (aE1.Orientation() != TopAbs_INTERNAL) {
815 iRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aF1, aF1,
821 const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First()));
822 const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aLF.Last()));
823 iRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aF1, aF2,
828 }//for(; aExp.More(); aExp.Next()) {
830 if (aExp.More() && iRet != 2)
835 //========================================
836 // 2. Classify face using classifier
839 TopTools_IndexedMapOfShape aBounds;
841 TopExp::MapShapes(theSolid, TopAbs_EDGE, aBounds);
843 aState=BOPTools_AlgoTools::ComputeState(theFace, theSolid,
844 theTol, aBounds, theContext);
845 return aState == TopAbs_IN;
847 //=======================================================================
848 //function : IsInternalFace
850 //=======================================================================
851 Standard_Integer BOPTools_AlgoTools::IsInternalFace
852 (const TopoDS_Face& theFace,
853 const TopoDS_Edge& theEdge,
854 TopTools_ListOfShape& theLF,
855 const Handle(IntTools_Context)& theContext)
857 Standard_Integer aNbF, iRet;
863 const TopoDS_Face& aF1=(*(TopoDS_Face*)(&theLF.First()));
864 const TopoDS_Face& aF2=(*(TopoDS_Face*)(&theLF.Last()));
865 iRet=BOPTools_AlgoTools::IsInternalFace(theFace, theEdge, aF1, aF2,
871 BOPTools_ListOfCoupleOfShape aLCFF;
872 BOPTools_ListIteratorOfListOfCoupleOfShape aIt;
874 FindFacePairs(theEdge, theLF, aLCFF, theContext);
876 aIt.Initialize(aLCFF);
877 for (; aIt.More(); aIt.Next()) {
878 BOPTools_CoupleOfShape& aCSFF=aIt.ChangeValue();
880 const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aCSFF.Shape1()));
881 const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aCSFF.Shape2()));
882 iRet=BOPTools_AlgoTools::IsInternalFace(theFace, theEdge, aF1, aF2,
891 //=======================================================================
892 //function : IsInternalFace
894 //=======================================================================
895 Standard_Integer BOPTools_AlgoTools::IsInternalFace
896 (const TopoDS_Face& theFace,
897 const TopoDS_Edge& theEdge,
898 const TopoDS_Face& theFace1,
899 const TopoDS_Face& theFace2,
900 const Handle(IntTools_Context)& theContext)
902 TopoDS_Edge aE1, aE2;
904 BOPTools_ListOfCoupleOfShape theLCSOff;
905 BOPTools_CoupleOfShape aCS1, aCS2;
907 BOPTools_AlgoTools::GetEdgeOnFace(theEdge, theFace1, aE1);
908 if (aE1.Orientation()==TopAbs_INTERNAL) {
910 aE1.Orientation(TopAbs_FORWARD);
911 aE2.Orientation(TopAbs_REVERSED);
913 else if (theFace1==theFace2) {
915 aE1.Orientation(TopAbs_FORWARD);
916 aE2.Orientation(TopAbs_REVERSED);
919 BOPTools_AlgoTools::GetEdgeOnFace(theEdge, theFace2, aE2);
922 aCS1.SetShape1(theEdge);
923 aCS1.SetShape2(theFace);
924 theLCSOff.Append(aCS1);
927 aCS2.SetShape2(theFace2);
928 theLCSOff.Append(aCS2);
930 Standard_Integer iRet = 0; // theFace is not internal
931 Standard_Boolean isDone = GetFaceOff (aE1, theFace1, theLCSOff, aFOff, theContext);
933 // error, unable to classify face by this edge
935 else if (theFace.IsEqual (aFOff))
936 // theFace is internal
941 //=======================================================================
942 //function : GetFaceOff
944 //=======================================================================
945 Standard_Boolean BOPTools_AlgoTools::GetFaceOff
946 (const TopoDS_Edge& theE1,
947 const TopoDS_Face& theF1,
948 BOPTools_ListOfCoupleOfShape& theLCSOff,
949 TopoDS_Face& theFOff,
950 const Handle(IntTools_Context)& theContext)
952 Standard_Boolean bRet, bIsComputed;
953 Standard_Real aT, aT1, aT2, aAngle, aTwoPI, aAngleMin, aDt3D;
954 Standard_Real aUmin, aUsup, aVmin, aVsup;
955 gp_Pnt aPn1, aPn2, aPx;
956 gp_Dir aDN1, aDN2, aDBF, aDBF2, aDTF;
958 TopAbs_Orientation aOr;
959 Handle(Geom_Curve)aC3D;
960 Handle(Geom_Plane) aPL;
961 BOPTools_ListIteratorOfListOfCoupleOfShape aIt;
962 GeomAPI_ProjectPointOnSurf aProjPL;
966 aC3D =BRep_Tool::Curve(theE1, aT1, aT2);
967 aT=BOPTools_AlgoTools2D::IntermediatePoint(aT1, aT2);
970 BOPTools_AlgoTools2D::EdgeTangent(theE1, aT, aVTgt);
971 gp_Dir aDTgt(aVTgt), aDTgt2;
972 aOr = theE1.Orientation();
974 aPL = new Geom_Plane(aPx, aDTgt);
975 aPL->Bounds(aUmin, aUsup, aVmin, aVsup);
976 aProjPL.Init(aPL, aUmin, aUsup, aVmin, aVsup);
978 Standard_Boolean bSmallFaces = Standard_False;
979 aDt3D = MinStep3D(theE1, theF1, theLCSOff, aPx, theContext, bSmallFaces);
980 bIsComputed = GetFaceDir(theE1, theF1, aPx, aT, aDTgt, bSmallFaces,
981 aDN1, aDBF, theContext, aProjPL, aDt3D);
984 std::cout << "BOPTools_AlgoTools::GetFaceOff(): incorrect computation of bi-normal direction." << std::endl;
990 // The difference between faces should be obvious enough
991 // to guarantee the correctness of the classification
992 Standard_Real anAngleCriteria = Precision::Confusion();
995 aIt.Initialize(theLCSOff);
996 for (; aIt.More(); aIt.Next()) {
997 const BOPTools_CoupleOfShape& aCS=aIt.Value();
998 const TopoDS_Edge& aE2=(*(TopoDS_Edge*)(&aCS.Shape1()));
999 const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aCS.Shape2()));
1001 aDTgt2 = (aE2.Orientation()==aOr) ? aDTgt : aDTgt.Reversed();
1002 bIsComputed = GetFaceDir(aE2, aF2, aPx, aT, aDTgt2, bSmallFaces, aDN2,
1003 aDBF2, theContext, aProjPL, aDt3D);
1006 std::cout << "BOPTools_AlgoTools::GetFaceOff(): incorrect computation of bi-normal direction." << std::endl;
1010 aAngle=AngleWithRef(aDBF, aDBF2, aDTF);
1012 if (Abs(aAngle) < Precision::Angular()) {
1016 else if (aF2.IsSame(theF1)) {
1021 if (Abs(aAngle) < anAngleCriteria ||
1022 Abs (aAngle-aAngleMin) < anAngleCriteria) {
1023 // the minimal angle can not be found
1024 bRet=Standard_False;
1029 aAngle = aTwoPI + aAngle;
1032 if (aAngle<aAngleMin){
1039 //=======================================================================
1040 //function : GetEdgeOff
1042 //=======================================================================
1043 Standard_Boolean BOPTools_AlgoTools::GetEdgeOff(const TopoDS_Edge& theE1,
1044 const TopoDS_Face& theF2,
1047 Standard_Boolean bFound;
1048 TopAbs_Orientation aOr1, aOr1C, aOr2;
1049 TopExp_Explorer anExp;
1051 bFound=Standard_False;
1052 aOr1=theE1.Orientation();
1053 aOr1C=TopAbs::Reverse(aOr1);
1055 anExp.Init(theF2, TopAbs_EDGE);
1056 for (; anExp.More(); anExp.Next()) {
1057 const TopoDS_Edge& aEF2=(*(TopoDS_Edge*)(&anExp.Current()));
1058 if (aEF2.IsSame(theE1)) {
1059 aOr2=aEF2.Orientation();
1070 //=======================================================================
1071 //function : AreFacesSameDomain
1073 //=======================================================================
1074 Standard_Boolean BOPTools_AlgoTools::AreFacesSameDomain
1075 (const TopoDS_Face& theF1,
1076 const TopoDS_Face& theF2,
1077 const Handle(IntTools_Context)& theContext,
1078 const Standard_Real theFuzz)
1080 Standard_Boolean bFacesSD = Standard_False;
1082 // The idea is to find a point inside the first face
1083 // and check its validity for the second face.
1084 // If valid - the faces are same domain.
1088 // Find point inside the first face
1089 Standard_Integer iErr =
1090 BOPTools_AlgoTools3D::PointInFace(theF1, aP1, aP2D1, theContext);
1094 // unable to find the point
1098 // Check validity of the point for second face
1100 // Compute the tolerance to check the validity -
1101 // sum of tolerance of faces and fuzzy tolerance
1103 // Compute the tolerance of the faces, taking into account the deviation
1104 // of the edges from the surfaces
1105 Standard_Real aTolF1 = BRep_Tool::Tolerance(theF1),
1106 aTolF2 = BRep_Tool::Tolerance(theF2);
1108 // Find maximal tolerance of edges.
1109 // The faces should have the same boundaries, thus
1110 // it does not matter which face to explore.
1112 Standard_Real aTolEMax = -1.;
1113 TopExp_Explorer anExpE(theF1, TopAbs_EDGE);
1114 for (; anExpE.More(); anExpE.Next())
1116 const TopoDS_Edge& aE = TopoDS::Edge(anExpE.Current());
1117 if (!BRep_Tool::Degenerated(aE))
1119 Standard_Real aTolE = BRep_Tool::Tolerance(aE);
1120 if (aTolE > aTolEMax)
1124 if (aTolEMax > aTolF1) aTolF1 = aTolEMax;
1125 if (aTolEMax > aTolF2) aTolF2 = aTolEMax;
1128 // Checking criteria
1129 Standard_Real aTol = aTolF1 + aTolF2 + Max(theFuzz, Precision::Confusion());
1131 // Project and classify the point on second face
1132 bFacesSD = theContext->IsValidPointForFace(aP1, theF2, aTol);
1137 //=======================================================================
1140 //=======================================================================
1141 Standard_Integer BOPTools_AlgoTools::Sense(const TopoDS_Face& theF1,
1142 const TopoDS_Face& theF2,
1143 const Handle(IntTools_Context)& theContext)
1145 Standard_Integer iSense=0;
1146 gp_Dir aDNF1, aDNF2;
1147 TopoDS_Edge aE1, aE2;
1148 TopExp_Explorer aExp;
1150 aExp.Init(theF1, TopAbs_EDGE);
1151 for (; aExp.More(); aExp.Next()) {
1152 aE1=(*(TopoDS_Edge*)(&aExp.Current()));
1153 if (!BRep_Tool::Degenerated(aE1)) {
1154 if (!BRep_Tool::IsClosed(aE1, theF1)) {
1160 aExp.Init(theF2, TopAbs_EDGE);
1161 for (; aExp.More(); aExp.Next()) {
1162 aE2=(*(TopoDS_Edge*)(&aExp.Current()));
1163 if (!BRep_Tool::Degenerated(aE2)) {
1164 if (!BRep_Tool::IsClosed(aE2, theF2)) {
1165 if (aE2.IsSame(aE1)) {
1177 BOPTools_AlgoTools3D::GetNormalToFaceOnEdge(aE1, theF1, aDNF1, theContext);
1178 BOPTools_AlgoTools3D::GetNormalToFaceOnEdge(aE2, theF2, aDNF2, theContext);
1180 iSense=BOPTools_AlgoTools3D::SenseFlag(aDNF1, aDNF2);
1184 //=======================================================================
1185 // function: IsSplitToReverse
1187 //=======================================================================
1188 Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse
1189 (const TopoDS_Shape& theSp,
1190 const TopoDS_Shape& theSr,
1191 const Handle(IntTools_Context)& theContext,
1192 Standard_Integer *theError)
1194 Standard_Boolean bRet;
1195 TopAbs_ShapeEnum aType;
1197 bRet=Standard_False;
1199 aType=theSp.ShapeType();
1202 const TopoDS_Edge& aESp=(*(TopoDS_Edge*)(&theSp));
1203 const TopoDS_Edge& aESr=(*(TopoDS_Edge*)(&theSr));
1204 bRet=BOPTools_AlgoTools::IsSplitToReverse(aESp, aESr, theContext, theError);
1209 const TopoDS_Face& aFSp=(*(TopoDS_Face*)(&theSp));
1210 const TopoDS_Face& aFSr=(*(TopoDS_Face*)(&theSr));
1211 bRet=BOPTools_AlgoTools::IsSplitToReverse(aFSp, aFSr, theContext, theError);
1223 //=======================================================================
1224 //function : IsSplitToReverseWithWarn
1226 //=======================================================================
1227 Standard_Boolean BOPTools_AlgoTools::IsSplitToReverseWithWarn(const TopoDS_Shape& theSplit,
1228 const TopoDS_Shape& theShape,
1229 const Handle(IntTools_Context)& theContext,
1230 const Handle(Message_Report)& theReport)
1232 Standard_Integer anErr;
1233 Standard_Boolean isToReverse = BOPTools_AlgoTools::IsSplitToReverse(theSplit, theShape, theContext, &anErr);
1234 if (anErr != 0 && !theReport.IsNull())
1236 // The error occurred during the check.
1237 // Add warning to the report, storing the shapes into the warning.
1238 TopoDS_Compound aWC;
1239 BRep_Builder().MakeCompound(aWC);
1240 BRep_Builder().Add(aWC, theSplit);
1241 BRep_Builder().Add(aWC, theShape);
1242 theReport->AddAlert(Message_Warning, new BOPAlgo_AlertUnableToOrientTheShape(aWC));
1247 //=======================================================================
1248 //function :IsSplitToReverse
1250 //=======================================================================
1251 Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse
1252 (const TopoDS_Face& theFSp,
1253 const TopoDS_Face& theFSr,
1254 const Handle(IntTools_Context)& theContext,
1255 Standard_Integer *theError)
1257 // Set OK error status
1262 Handle(Geom_Surface) aSFSp = BRep_Tool::Surface(theFSp);
1263 Handle(Geom_Surface) aSFOr = BRep_Tool::Surface(theFSr);
1264 if (aSFSp == aSFOr) {
1265 return theFSp.Orientation() != theFSr.Orientation();
1268 Standard_Boolean bDone = Standard_False;
1269 // Find the point inside the split face
1274 Standard_Integer iErr;
1275 // Use the hatcher to find the point in the middle of the face
1276 iErr = BOPTools_AlgoTools3D::PointInFace(theFSp, aPFSp, aP2DFSp, theContext);
1278 // Hatcher has failed to find a point.
1279 // Try to get the point near some not closed and
1280 // not degenerated edge on the split face.
1281 TopExp_Explorer anExp(theFSp, TopAbs_EDGE);
1282 for (; anExp.More(); anExp.Next()) {
1283 const TopoDS_Edge& aESp = (*(TopoDS_Edge*)(&anExp.Current()));
1284 if (!BRep_Tool::Degenerated(aESp) && !BRep_Tool::IsClosed(aESp, theFSp)) {
1285 iErr = BOPTools_AlgoTools3D::PointNearEdge
1286 (aESp, theFSp, aP2DFSp, aPFSp, theContext);
1293 if (!anExp.More()) {
1296 // The point has not been found.
1301 // Compute normal direction of the split face
1303 bDone = BOPTools_AlgoTools3D::GetNormalToSurface
1304 (aSFSp, aP2DFSp.X(), aP2DFSp.Y(), aDNFSp);
1311 if (theFSp.Orientation() == TopAbs_REVERSED){
1315 // Project the point from the split face on the original face
1316 // to find its UV coordinates
1317 GeomAPI_ProjectPointOnSurf& aProjector = theContext->ProjPS(theFSr);
1318 aProjector.Perform(aPFSp);
1319 bDone = (aProjector.NbPoints() > 0);
1325 // UV coordinates of the point on the original face
1326 Standard_Real aU, aV;
1327 aProjector.LowerDistanceParameters(aU, aV);
1329 // Compute normal direction for the original face in this point
1331 bDone = BOPTools_AlgoTools3D::GetNormalToSurface(aSFOr, aU, aV, aDNFOr);
1338 if (theFSr.Orientation() == TopAbs_REVERSED) {
1342 // compare the normals
1343 Standard_Real aCos = aDNFSp*aDNFOr;
1346 //=======================================================================
1347 //function :IsSplitToReverse
1349 //=======================================================================
1350 Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse
1351 (const TopoDS_Edge& theESp,
1352 const TopoDS_Edge& theEOr,
1353 const Handle(IntTools_Context)& theContext,
1354 Standard_Integer *theError)
1356 // The idea is to compare the tangent vectors of two edges computed in
1357 // the same point. Thus, we need to take the point on split edge (since it is
1358 // shorter) and project it onto original edge to find corresponding parameter.
1360 if (BRep_Tool::Degenerated(theESp) ||
1361 BRep_Tool::Degenerated(theEOr))
1365 return Standard_False;
1368 // Set OK error status
1372 // Get the curves from the edges
1374 Handle(Geom_Curve) aCSp = BRep_Tool::Curve(theESp, f, l);
1375 Handle(Geom_Curve) aCOr = BRep_Tool::Curve(theEOr, f, l);
1377 // If the curves are the same, compare orientations only
1379 return theESp.Orientation() != theEOr.Orientation();
1381 // Find valid range of the split edge, to ensure that the point for computing
1382 // tangent vectors will be inside both edges.
1383 if (!BRepLib::FindValidRange(theESp, f, l))
1384 BRep_Tool::Range(theESp, f, l);
1387 Standard_Integer anErr = 0;
1388 // Try a few sample points on the split edge until first valid found
1389 const Standard_Integer aNbP = 11;
1390 const Standard_Real aDT = (l - f) / aNbP;
1391 for (Standard_Integer i = 1; i < aNbP; ++i)
1393 const Standard_Real aTm = f + i*aDT;
1394 // Compute tangent vector on split edge
1396 if (!BOPTools_AlgoTools2D::EdgeTangent(theESp, aTm, aVSpTgt))
1398 // Unable to compute the tangent vector on the split edge
1399 // in this point -> take the next point
1404 // Find corresponding parameter on the original edge
1405 Standard_Real aTmOr;
1406 if (!theContext->ProjectPointOnEdge(aCSp->Value(aTm), theEOr, aTmOr))
1408 // Unable to project the point inside the split edge
1409 // onto the original edge -> take the next point
1414 // Compute tangent vector on original edge
1416 if (!BOPTools_AlgoTools2D::EdgeTangent(theEOr, aTmOr, aVOrTgt))
1418 // Unable to compute the tangent vector on the original edge
1419 // in this point -> take the next point
1424 // Compute the Dot product
1425 Standard_Real aCos = aVSpTgt.Dot(aVOrTgt);
1432 return Standard_False;
1435 //=======================================================================
1438 //=======================================================================
1439 Standard_Boolean BOPTools_AlgoTools::IsHole(const TopoDS_Shape& aW,
1440 const TopoDS_Shape& aFace)
1442 Standard_Boolean bIsHole;
1443 Standard_Integer i, aNbS;
1444 Standard_Real aT1, aT2, aS;
1445 Standard_Real aU1, aU, dU;
1446 Standard_Real aX1, aY1, aX0, aY0;
1447 TopAbs_Orientation aOr;
1449 gp_Pnt2d aP2D0, aP2D1;
1450 Handle(Geom2d_Curve) aC2D;
1451 TopoDS_Face aF, aFF;
1452 TopoDS_Iterator aItW;
1454 bIsHole=Standard_False;
1456 aF=(*(TopoDS_Face *)(&aFace));
1458 aFF.Orientation(TopAbs_FORWARD);
1461 aItW.Initialize(aW);
1462 for (; aItW.More(); aItW.Next()) {
1463 const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&aItW.Value()));
1464 aOr=aE.Orientation();
1465 if (!(aOr==TopAbs_FORWARD ||
1466 aOr==TopAbs_REVERSED)) {
1470 aC2D=BRep_Tool::CurveOnSurface(aE, aFF, aT1, aT2);
1471 if (aC2D.IsNull()) {
1475 BRepAdaptor_Curve2d aBAC2D(aE, aFF);
1476 aNbS=Geom2dInt_Geom2dCurveTool::NbSamples(aBAC2D);
1481 dU=(aT2-aT1)/(Standard_Real)(aNbS-1);
1484 if (aOr==TopAbs_REVERSED) {
1490 aBAC2D.D0(aU, aP2D0);
1491 for(i=2; i<=aNbS; i++) {
1493 aBAC2D.D0(aU, aP2D1);
1494 aP2D0.Coord(aX0, aY0);
1495 aP2D1.Coord(aX1, aY1);
1497 aS=aS+(aY0+aY1)*(aX1-aX0);
1501 }//for (; aItW.More(); aItW.Next()) {
1506 //=======================================================================
1507 // function: MakeContainer
1509 //=======================================================================
1510 void BOPTools_AlgoTools::MakeContainer(const TopAbs_ShapeEnum theType,
1516 case TopAbs_COMPOUND:{
1518 aBB.MakeCompound(aC);
1523 case TopAbs_COMPSOLID:{
1524 TopoDS_CompSolid aCS;
1525 aBB.MakeCompSolid(aCS);
1531 TopoDS_Solid aSolid;
1532 aBB.MakeSolid(aSolid);
1539 TopoDS_Shell aShell;
1540 aBB.MakeShell(aShell);
1547 aBB.MakeWire(aWire);
1556 //=======================================================================
1557 // function: MakePCurve
1559 //=======================================================================
1560 void BOPTools_AlgoTools::MakePCurve(const TopoDS_Edge& aE,
1561 const TopoDS_Face& aF1,
1562 const TopoDS_Face& aF2,
1563 const IntTools_Curve& aIC,
1564 const Standard_Boolean bPC1,
1565 const Standard_Boolean bPC2,
1566 const Handle(IntTools_Context)& theContext)
1570 Standard_Real aTolE, aT1, aT2, aOutFirst, aOutLast, aOutTol;
1571 Handle(Geom2d_Curve) aC2D, aC2DA, aC2Dx1;
1574 Standard_Boolean bPC;
1576 aTolE=BRep_Tool::Tolerance(aE);
1578 const Handle(Geom_Curve)& aC3DE=BRep_Tool::Curve(aE, aT1, aT2);
1579 Handle(Geom_TrimmedCurve)aC3DETrim=
1580 new Geom_TrimmedCurve(aC3DE, aT1, aT2);
1582 for (i=0; i<2; ++i) {
1583 bPC = !i ? bPC1 : bPC2;
1590 aC2Dx1=aIC.FirstCurve2d();
1594 aC2Dx1=aIC.SecondCurve2d();
1597 aFFWD.Orientation(TopAbs_FORWARD);
1600 if (aC2D.IsNull()) {
1601 BOPTools_AlgoTools2D::BuildPCurveForEdgeOnFace(aE, aFFWD, theContext);
1602 BOPTools_AlgoTools2D::CurveOnSurface(aE, aFFWD, aC2D,
1603 aOutFirst, aOutLast,
1604 aOutTol, theContext);
1607 if (aC3DE->IsPeriodic()) {
1608 BOPTools_AlgoTools2D::AdjustPCurveOnFace(aFFWD, aT1, aT2, aC2D,
1612 BOPTools_AlgoTools2D::AdjustPCurveOnFace(aFFWD, aC3DETrim, aC2D,
1616 aBB.UpdateEdge(aE, aC2DA, aFFWD, aTolE);
1617 //BRepLib::SameParameter(aE);
1619 BRepLib::SameParameter(aE);
1621 //=======================================================================
1622 // function: MakeEdge
1624 //=======================================================================
1625 void BOPTools_AlgoTools::MakeEdge(const IntTools_Curve& theIC,
1626 const TopoDS_Vertex& theV1,
1627 const Standard_Real theT1,
1628 const TopoDS_Vertex& theV2,
1629 const Standard_Real theT2,
1630 const Standard_Real theTolR3D,
1634 Standard_Real aNeedTol = theTolR3D + BOPTools_AlgoTools::DTolerance();
1636 aBB.UpdateVertex(theV1, aNeedTol);
1637 aBB.UpdateVertex(theV2, aNeedTol);
1639 BOPTools_AlgoTools::MakeSectEdge (theIC, theV1, theT1, theV2, theT2,
1642 aBB.UpdateEdge(theE, theTolR3D);
1644 //=======================================================================
1645 // function: ComputeVV
1647 //=======================================================================
1648 Standard_Integer BOPTools_AlgoTools::ComputeVV(const TopoDS_Vertex& aV1,
1650 const Standard_Real aTolP2)
1652 Standard_Real aTolV1, aTolSum, aTolSum2, aD2;
1655 aTolV1=BRep_Tool::Tolerance(aV1);
1657 aTolSum = aTolV1 + aTolP2 + Precision::Confusion();
1658 aTolSum2=aTolSum*aTolSum;
1660 aP1=BRep_Tool::Pnt(aV1);
1662 aD2=aP1.SquareDistance(aP2);
1668 //=======================================================================
1669 // function: ComputeVV
1671 //=======================================================================
1672 Standard_Integer BOPTools_AlgoTools::ComputeVV(const TopoDS_Vertex& aV1,
1673 const TopoDS_Vertex& aV2,
1674 const Standard_Real aFuzz)
1676 Standard_Real aTolV1, aTolV2, aTolSum, aTolSum2, aD2;
1678 Standard_Real aFuzz1 = (aFuzz > Precision::Confusion() ? aFuzz : Precision::Confusion());
1680 aTolV1=BRep_Tool::Tolerance(aV1);
1681 aTolV2=BRep_Tool::Tolerance(aV2);
1682 aTolSum=aTolV1+aTolV2+aFuzz1;
1683 aTolSum2=aTolSum*aTolSum;
1685 aP1=BRep_Tool::Pnt(aV1);
1686 aP2=BRep_Tool::Pnt(aV2);
1688 aD2=aP1.SquareDistance(aP2);
1694 //=======================================================================
1695 // function: MakeVertex
1697 //=======================================================================
1698 void BOPTools_AlgoTools::MakeVertex(const TopTools_ListOfShape& aLV,
1699 TopoDS_Vertex& aVnew)
1701 Standard_Integer aNb = aLV.Extent();
1703 aVnew=*((TopoDS_Vertex*)(&aLV.First()));
1706 Standard_Real aNTol;
1708 BRepLib::BoundingVertex(aLV, aNC, aNTol);
1710 aBB.MakeVertex(aVnew, aNC, aNTol);
1713 //=======================================================================
1714 //function : GetEdgeOnFace
1716 //=======================================================================
1717 Standard_Boolean BOPTools_AlgoTools::GetEdgeOnFace
1718 (const TopoDS_Edge& theE1,
1719 const TopoDS_Face& theF2,
1722 Standard_Boolean bFound;
1723 TopoDS_Iterator aItF, aItW;
1725 bFound=Standard_False;
1727 aItF.Initialize(theF2);
1728 for (; aItF.More(); aItF.Next()) {
1729 const TopoDS_Shape& aW=aItF.Value();
1730 aItW.Initialize(aW);
1731 for (; aItW.More(); aItW.Next()) {
1732 const TopoDS_Shape& aE=aItW.Value();
1733 if (aE.IsSame(theE1)) {
1734 theE2=(*(TopoDS_Edge*)(&aE));
1742 //=======================================================================
1743 //function : FindFacePairs
1745 //=======================================================================
1746 Standard_Boolean FindFacePairs (const TopoDS_Edge& theE,
1747 const TopTools_ListOfShape& thLF,
1748 BOPTools_ListOfCoupleOfShape& theLCFF,
1749 const Handle(IntTools_Context)& theContext)
1751 Standard_Boolean bFound;
1752 Standard_Integer i, aNbCEF;
1753 TopAbs_Orientation aOr, aOrC = TopAbs_FORWARD;
1754 TopTools_MapOfShape aMFP;
1755 TopoDS_Face aF1, aF2;
1756 TopoDS_Edge aEL, aE1;
1757 TopTools_ListIteratorOfListOfShape aItLF;
1758 BOPTools_CoupleOfShape aCEF, aCFF;
1759 BOPTools_ListOfCoupleOfShape aLCEF, aLCEFx;
1760 BOPTools_ListIteratorOfListOfCoupleOfShape aIt;
1762 bFound=Standard_True;
1765 aItLF.Initialize(thLF);
1766 for (; aItLF.More(); aItLF.Next()) {
1767 const TopoDS_Face& aFL=(*(TopoDS_Face*)(&aItLF.Value()));
1769 bFound=BOPTools_AlgoTools::GetEdgeOnFace(theE, aFL, aEL);
1771 return bFound; // it can not be so
1774 aCEF.SetShape1(aEL);
1775 aCEF.SetShape2(aFL);
1779 aNbCEF=aLCEF.Extent();
1784 aIt.Initialize(aLCEF);
1785 for (i=0; aIt.More(); aIt.Next(), ++i) {
1786 const BOPTools_CoupleOfShape& aCSx=aIt.Value();
1787 const TopoDS_Shape& aEx=aCSx.Shape1();
1788 const TopoDS_Shape& aFx=aCSx.Shape2();
1790 aOr=aEx.Orientation();
1793 aOrC=TopAbs::Reverse(aOr);
1794 aE1=(*(TopoDS_Edge*)(&aEx));
1795 aF1=(*(TopoDS_Face*)(&aFx));
1801 aLCEFx.Append(aCSx);
1807 BOPTools_AlgoTools::GetFaceOff(aE1, aF1, aLCEFx, aF2, theContext);
1809 aCFF.SetShape1(aF1);
1810 aCFF.SetShape2(aF2);
1811 theLCFF.Append(aCFF);
1820 aIt.Initialize(aLCEFx);
1821 for (; aIt.More(); aIt.Next()) {
1822 const BOPTools_CoupleOfShape& aCSx=aIt.Value();
1823 const TopoDS_Shape& aFx=aCSx.Shape2();
1824 if (!aMFP.Contains(aFx)) {
1829 aNbCEF=aLCEF.Extent();
1834 //=======================================================================
1835 //function : AngleWithRef
1837 //=======================================================================
1838 Standard_Real AngleWithRef(const gp_Dir& theD1,
1839 const gp_Dir& theD2,
1840 const gp_Dir& theDRef)
1842 Standard_Real aCosinus, aSinus, aBeta, aHalfPI, aScPr;
1847 const gp_XYZ& aXYZ1=theD1.XYZ();
1848 const gp_XYZ& aXYZ2=theD2.XYZ();
1849 aXYZ=aXYZ1.Crossed(aXYZ2);
1850 aSinus=aXYZ.Modulus();
1851 aCosinus=theD1*theD2;
1855 aBeta=aHalfPI*(1.-aCosinus);
1858 aBeta=2.*M_PI-aHalfPI*(3.+aCosinus);
1861 aScPr=aXYZ.Dot(theDRef.XYZ());
1867 //=======================================================================
1868 // function: IsBlockInOnFace
1870 //=======================================================================
1871 Standard_Boolean BOPTools_AlgoTools::IsBlockInOnFace
1872 (const IntTools_Range& aShrR,
1873 const TopoDS_Face& aF,
1874 const TopoDS_Edge& aE1,
1875 const Handle(IntTools_Context)& aContext)
1877 Standard_Boolean bFlag;
1878 Standard_Real f1, l1, ULD, VLD;
1882 aShrR.Range(f1, l1);
1883 Standard_Real dt=0.0075, k;//dt=0.001, k;
1889 BOPTools_AlgoTools::PointOnEdge(aE1, f1, aP11);
1891 GeomAPI_ProjectPointOnSurf& aProjector=aContext->ProjPS(aF);
1892 aProjector.Perform(aP11);
1894 bFlag=aProjector.IsDone();
1899 aProjector.LowerDistanceParameters(ULD, VLD);
1900 aP2D.SetCoord(ULD, VLD);
1902 bFlag=aContext->IsPointInOnFace (aF, aP2D);
1909 BOPTools_AlgoTools::PointOnEdge(aE1, l1, aP12);
1911 aProjector.Perform(aP12);
1913 bFlag=aProjector.IsDone();
1918 aProjector.LowerDistanceParameters(ULD, VLD);
1919 aP2D.SetCoord(ULD, VLD);
1921 bFlag=aContext->IsPointInOnFace (aF, aP2D);
1927 // Treatment intemediate
1928 Standard_Real m1, aTolF, aTolE, aTol, aDist;
1929 m1=IntTools_Tools::IntermediatePoint(f1, l1);
1930 BOPTools_AlgoTools::PointOnEdge(aE1, m1, aP12);
1932 aProjector.Perform(aP12);
1934 bFlag=aProjector.IsDone();
1939 aTolE=BRep_Tool::Tolerance(aE1);
1940 aTolF=BRep_Tool::Tolerance(aF);
1942 aDist=aProjector.LowerDistance();
1944 return Standard_False;
1947 aProjector.LowerDistanceParameters(ULD, VLD);
1948 aP2D.SetCoord(ULD, VLD);
1950 bFlag=aContext->IsPointInOnFace (aF, aP2D);
1958 //=======================================================================
1959 //function : IsMicroEdge
1961 //=======================================================================
1962 Standard_Boolean BOPTools_AlgoTools::IsMicroEdge
1963 (const TopoDS_Edge& aE,
1964 const Handle(IntTools_Context)& aCtx,
1965 const Standard_Boolean bCheckSplittable)
1967 Standard_Boolean bRet;
1968 Standard_Real aT1, aT2, aTmp;
1969 Handle(Geom_Curve) aC3D;
1970 TopoDS_Vertex aV1, aV2;
1972 bRet=(BRep_Tool::Degenerated(aE) ||
1973 !BRep_Tool::IsGeometric(aE));
1978 aC3D=BRep_Tool::Curve(aE, aT1, aT2);
1979 TopExp::Vertices(aE, aV1, aV2);
1980 aT1=BRep_Tool::Parameter(aV1, aE);
1981 aT2=BRep_Tool::Parameter(aV2, aE);
1988 IntTools_ShrunkRange aSR;
1989 aSR.SetContext(aCtx);
1990 aSR.SetData(aE, aT1, aT2, aV1, aV2);
1992 bRet = !aSR.IsDone();
1993 if (!bRet && bCheckSplittable) {
1994 bRet = !aSR.IsSplittable();
2000 //=======================================================================
2001 //function : GetFaceDir
2002 //purpose : Get binormal direction for the face in the point aP
2003 //=======================================================================
2004 Standard_Boolean GetFaceDir(const TopoDS_Edge& aE,
2005 const TopoDS_Face& aF,
2007 const Standard_Real aT,
2008 const gp_Dir& aDTgt,
2009 const Standard_Boolean theSmallFaces,
2012 const Handle(IntTools_Context)& theContext,
2013 GeomAPI_ProjectPointOnSurf& aProjPL,
2014 const Standard_Real aDt)
2016 Standard_Real aTolE;
2019 BOPTools_AlgoTools3D::GetNormalToFaceOnEdge(aE, aF, aT, aDN, theContext);
2020 if (aF.Orientation()==TopAbs_REVERSED){
2024 aTolE=BRep_Tool::Tolerance(aE);
2027 // do not try to look for the point in the small face by intersecting
2028 // it with the circle because, most likely, the intersection point will
2029 // be out of the face
2030 Standard_Boolean bFound = !theSmallFaces &&
2031 FindPointInFace(aF, aP, aDB, aPx, theContext, aProjPL, aDt, aTolE);
2033 // if the first method did not succeed, try to use hatcher to find the point
2034 bFound = BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge
2035 (aE, aF, aT, aDt, aPx, aDN, theContext);
2036 aProjPL.Perform(aPx);
2037 Standard_ASSERT_RETURN(aProjPL.IsDone(),
2038 "GetFaceDir: Project point on plane is failed", Standard_False);
2039 aPx = aProjPL.NearestPoint();
2040 gp_Vec aVec(aP, aPx);
2041 aDB.SetXYZ(aVec.XYZ());
2046 //=======================================================================
2047 //function : FindPointInFace
2048 //purpose : Find a point in the face in direction of <aDB>.
2049 // To get this point the method intersects the circle with radius
2050 // <aDt> built in point <aP> with normal perpendicular to <aDB>.
2051 //=======================================================================
2052 Standard_Boolean FindPointInFace(const TopoDS_Face& aF,
2056 const Handle(IntTools_Context)& theContext,
2057 GeomAPI_ProjectPointOnSurf& aProjPL,
2058 const Standard_Real aDt,
2059 const Standard_Real aTolE)
2061 Standard_Integer aNbItMax;
2062 Standard_Real aDist, aDTol, aPM, anEps;
2063 Standard_Boolean bRet;
2066 aDTol = Precision::Angular();
2067 aPM = aP.XYZ().Modulus();
2069 aDTol = 5.e-16 * aPM;
2071 bRet = Standard_False;
2073 anEps = Precision::SquareConfusion();
2075 GeomAPI_ProjectPointOnSurf& aProj=theContext->ProjPS(aF);
2079 if (!aProj.IsDone()) {
2082 aPS=aProj.NearestPoint();
2083 aProjPL.Perform(aPS);
2084 aPS=aProjPL.NearestPoint();
2086 aPS.SetXYZ(aPS.XYZ()+2.*aTolE*aDB.XYZ());
2088 if (!aProj.IsDone()) {
2091 aPS=aProj.NearestPoint();
2092 aProjPL.Perform(aPS);
2093 aPS=aProjPL.NearestPoint();
2096 aP1.SetXYZ(aPS.XYZ()+aDt*aDB.XYZ());
2099 if (!aProj.IsDone()) {
2102 aPOut = aProj.NearestPoint();
2103 aDist = aProj.LowerDistance();
2105 aProjPL.Perform(aPOut);
2106 aPOut = aProjPL.NearestPoint();
2108 gp_Vec aV(aPS, aPOut);
2109 if (aV.SquareMagnitude() < anEps) {
2112 aDB.SetXYZ(aV.XYZ());
2113 } while (aDist > aDTol && --aNbItMax);
2115 bRet = aDist < aDTol;
2118 //=======================================================================
2119 //function : MinStep3D
2121 //=======================================================================
2122 Standard_Real MinStep3D(const TopoDS_Edge& theE1,
2123 const TopoDS_Face& theF1,
2124 const BOPTools_ListOfCoupleOfShape& theLCS,
2126 const Handle(IntTools_Context)& theContext,
2127 Standard_Boolean& theSmallFaces)
2129 Standard_Real aDt, aTolE, aTolF, aDtMax, aDtMin;
2131 // add the current pair of edge/face for checking as well
2132 BOPTools_CoupleOfShape aCS1;
2133 aCS1.SetShape1(theE1);
2134 aCS1.SetShape2(theF1);
2136 BOPTools_ListOfCoupleOfShape aLCS = theLCS;
2139 aTolE = BRep_Tool::Tolerance(theE1);
2143 BOPTools_ListIteratorOfListOfCoupleOfShape aIt(aLCS);
2144 for (; aIt.More(); aIt.Next()) {
2145 const BOPTools_CoupleOfShape& aCS = aIt.Value();
2146 const TopoDS_Face& aF = (*(TopoDS_Face*)(&aCS.Shape2()));
2148 aTolF = BRep_Tool::Tolerance(aF);
2149 aDt = 2*(aTolE + aTolF);
2154 // try to compute the minimal 3D step
2155 const BRepAdaptor_Surface& aBAS = theContext->SurfaceAdaptor(aF);
2156 Standard_Real aR = 0.;
2157 GeomAbs_SurfaceType aSType = aBAS.GetType();
2159 case GeomAbs_Cylinder: {
2160 aR = aBAS.Cylinder().Radius();
2163 case GeomAbs_Cone: {
2164 gp_Lin aL(aBAS.Cone().Axis());
2165 aR = aL.Distance(aP);
2168 case GeomAbs_Sphere: {
2169 aDtMin = Max(aDtMin, 5.e-4);
2170 aR = aBAS.Sphere().Radius();
2173 case GeomAbs_Torus: {
2174 aR = aBAS.Torus().MajorRadius();
2178 aDtMin = Max(aDtMin, 5.e-4);
2183 Standard_Real d = 10*Precision::PConfusion();
2184 aDtMin = Max(aDtMin, sqrt(d*d + 2*d*aR));
2188 if (aDtMax < aDtMin) {
2192 // check if the computed 3D step is too big for any of the faces in the list
2193 aIt.Initialize(aLCS);
2194 for (; aIt.More(); aIt.Next()) {
2195 const BOPTools_CoupleOfShape& aCS = aIt.Value();
2196 const TopoDS_Face& aF = (*(TopoDS_Face*)(&aCS.Shape2()));
2198 const BRepAdaptor_Surface& aBAS = theContext->SurfaceAdaptor(aF);
2200 Standard_Real aUMin, aUMax, aVMin, aVMax;
2201 theContext->UVBounds(aF, aUMin, aUMax, aVMin, aVMax);
2203 Standard_Real aDU = aUMax - aUMin;
2205 Standard_Real aURes = aBAS.UResolution(aDtMax);
2206 if (2*aURes > aDU) {
2211 Standard_Real aDV = aVMax - aVMin;
2213 Standard_Real aVRes = aBAS.VResolution(aDtMax);
2214 if (2*aVRes > aDV) {
2220 theSmallFaces = aIt.More();
2224 //=======================================================================
2225 //function : IsOpenShell
2227 //=======================================================================
2228 Standard_Boolean BOPTools_AlgoTools::IsOpenShell(const TopoDS_Shell& aSh)
2230 Standard_Boolean bRet;
2231 Standard_Integer i, aNbE, aNbF;
2232 TopAbs_Orientation aOrF;
2233 TopTools_IndexedDataMapOfShapeListOfShape aMEF;
2234 TopTools_ListIteratorOfListOfShape aItLS;
2236 bRet=Standard_False;
2238 TopExp::MapShapesAndAncestors(aSh, TopAbs_EDGE, TopAbs_FACE, aMEF);
2241 for (i=1; i<=aNbE; ++i) {
2242 const TopoDS_Edge& aE=*((TopoDS_Edge*)&aMEF.FindKey(i));
2243 if (BRep_Tool::Degenerated(aE)) {
2248 const TopTools_ListOfShape& aLF=aMEF(i);
2249 aItLS.Initialize(aLF);
2250 for (; aItLS.More(); aItLS.Next()) {
2251 const TopoDS_Shape& aF=aItLS.Value();
2252 aOrF=aF.Orientation();
2253 if (aOrF==TopAbs_INTERNAL || aOrF==TopAbs_EXTERNAL) {
2267 //=======================================================================
2268 //function : IsInvertedSolid
2270 //=======================================================================
2271 Standard_Boolean BOPTools_AlgoTools::IsInvertedSolid
2272 (const TopoDS_Solid& aSolid)
2274 Standard_Real aTolS;
2275 TopAbs_State aState;
2276 BRepClass3d_SolidClassifier aSC(aSolid);
2279 aSC.PerformInfinitePoint(aTolS);
2281 return (aState==TopAbs_IN);