1 // Created by: Peter KURNEV
2 // Copyright (c) 2010-2012 OPEN CASCADE SAS
3 // Copyright (c) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE
4 // Copyright (c) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT,
5 // EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
8 // This file is part of Open CASCADE Technology software library.
10 // This library is free software; you can redistribute it and/or modify it under
11 // the terms of the GNU Lesser General Public License version 2.1 as published
12 // by the Free Software Foundation, with special exception defined in the file
13 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
14 // distribution for complete text of the license and disclaimer of any warranty.
16 // Alternatively, this file may be used under the terms of Open CASCADE
17 // commercial license or contractual agreement.
19 #include <BOPAlgo_BuilderFace.ixx>
21 #include <gp_Pnt2d.hxx>
27 #include <Geom_Surface.hxx>
30 #include <TopLoc_Location.hxx>
32 #include <TopoDS_Iterator.hxx>
33 #include <TopoDS_Face.hxx>
34 #include <TopoDS_Shape.hxx>
35 #include <TopoDS_Wire.hxx>
36 #include <TopoDS_Edge.hxx>
37 #include <TopoDS_Vertex.hxx>
39 #include <BRep_Builder.hxx>
40 #include <BRep_Tool.hxx>
41 #include <BRepTools.hxx>
44 #include <TopExp_Explorer.hxx>
46 #include <IntTools_FClass2d.hxx>
47 #include <IntTools_Context.hxx>
50 #include <BOPTools_AlgoTools.hxx>
51 #include <BOPTools_AlgoTools2D.hxx>
52 #include <BOPAlgo_WireEdgeSet.hxx>
54 #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
55 #include <BOPTools.hxx>
56 #include <BOPCol_ListOfShape.hxx>
57 #include <BOPAlgo_WireSplitter.hxx>
58 #include <BOPCol_DataMapOfShapeShape.hxx>
59 #include <BOPCol_DataMapOfShapeListOfShape.hxx>
60 #include <BOPCol_MapOfShape.hxx>
64 Standard_Boolean IsGrowthWire(const TopoDS_Shape& ,
65 const BOPCol_IndexedMapOfShape& );
68 Standard_Boolean IsInside(const TopoDS_Shape& ,
70 Handle(IntTools_Context)& );
72 void MakeInternalWires(const BOPCol_MapOfShape& ,
73 BOPCol_ListOfShape& );
75 void GetWire(const TopoDS_Shape& ,
78 #include <NCollection_UBTreeFiller.hxx>
79 #include <BOPCol_Box2DBndTree.hxx>
80 #include <BRepTools.hxx>
81 #include <TColStd_MapIntegerHasher.hxx>
82 #include <NCollection_DataMap.hxx>
84 //=======================================================================
85 //class : BOPAlgo_ShapeBox2D
86 //purpose : Auxiliary class
87 //=======================================================================
88 class BOPAlgo_ShapeBox2D {
90 BOPAlgo_ShapeBox2D() {
91 myIsHole=Standard_False;
94 ~BOPAlgo_ShapeBox2D() {
97 void SetShape(const TopoDS_Shape& aS) {
101 const TopoDS_Shape& Shape()const {
105 void SetBox2D(const Bnd_Box2d& aBox2D) {
109 const Bnd_Box2d& Box2D()const {
113 void SetIsHole(const Standard_Boolean bFlag) {
117 Standard_Boolean IsHole()const {
122 Standard_Boolean myIsHole;
123 TopoDS_Shape myShape;
127 typedef NCollection_DataMap\
128 <Standard_Integer, BOPAlgo_ShapeBox2D, TColStd_MapIntegerHasher> \
129 BOPAlgo_DataMapOfIntegerShapeBox2D;
131 typedef BOPAlgo_DataMapOfIntegerShapeBox2D::Iterator \
132 BOPAlgo_DataMapIteratorOfDataMapOfIntegerShapeBox2D;
135 //=======================================================================
138 //=======================================================================
139 BOPAlgo_BuilderFace::BOPAlgo_BuilderFace()
141 BOPAlgo_BuilderArea()
143 myOrientation=TopAbs_EXTERNAL;
145 //=======================================================================
148 //=======================================================================
149 BOPAlgo_BuilderFace::BOPAlgo_BuilderFace
150 (const Handle(NCollection_BaseAllocator)& theAllocator)
152 BOPAlgo_BuilderArea(theAllocator)
154 myOrientation=TopAbs_EXTERNAL;
156 //=======================================================================
159 //=======================================================================
160 BOPAlgo_BuilderFace::~BOPAlgo_BuilderFace()
163 //=======================================================================
166 //=======================================================================
167 void BOPAlgo_BuilderFace::SetFace(const TopoDS_Face& theFace)
169 myOrientation=theFace.Orientation();
171 myFace.Orientation(TopAbs_FORWARD);
173 //=======================================================================
174 //function : Orientation
176 //=======================================================================
177 TopAbs_Orientation BOPAlgo_BuilderFace::Orientation()const
179 return myOrientation;
181 //=======================================================================
184 //=======================================================================
185 const TopoDS_Face& BOPAlgo_BuilderFace::Face()const
189 //=======================================================================
190 //function : CheckData
192 //=======================================================================
193 void BOPAlgo_BuilderFace::CheckData()
197 if (myFace.IsNull()) {
198 myErrorStatus=12;// Null face generix
201 if (myContext.IsNull()) {
202 myContext = new IntTools_Context;
205 //=======================================================================
208 //=======================================================================
209 void BOPAlgo_BuilderFace::Perform()
218 PerformShapesToAvoid();
233 PerformInternalShapes();
238 //=======================================================================
239 //function :PerformShapesToAvoid
241 //=======================================================================
242 void BOPAlgo_BuilderFace::PerformShapesToAvoid()
244 Standard_Boolean bFound;
245 Standard_Integer i, iCnt, aNbV, aNbE;
246 BOPCol_IndexedDataMapOfShapeListOfShape aMVE;
247 BOPCol_ListIteratorOfListOfShape aIt;
249 myShapesToAvoid.Clear();
254 bFound=Standard_False;
258 aIt.Initialize (myShapes);
259 for (; aIt.More(); aIt.Next()) {
260 const TopoDS_Shape& aE=aIt.Value();
261 if (!myShapesToAvoid.Contains(aE)) {
262 BOPTools::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
268 for (i=1; i<=aNbV; ++i) {
269 const TopoDS_Vertex& aV=(*(TopoDS_Vertex *)(&aMVE.FindKey(i)));
271 BOPCol_ListOfShape& aLE=aMVE.ChangeFromKey(aV);
277 const TopoDS_Edge& aE1=(*(TopoDS_Edge *)(&aLE.First()));
279 if (BRep_Tool::Degenerated(aE1)) {
282 if (aV.Orientation()==TopAbs_INTERNAL) {
285 bFound=Standard_True;
286 myShapesToAvoid.Add(aE1);
289 const TopoDS_Edge& aE2=(*(TopoDS_Edge *)(&aLE.Last()));
290 if (aE2.IsSame(aE1)) {
291 TopoDS_Vertex aV1x, aV2x;
293 TopExp::Vertices(aE1, aV1x, aV2x);
294 if (aV1x.IsSame(aV2x)) {
297 bFound=Standard_True;
298 myShapesToAvoid.Add(aE1);
299 myShapesToAvoid.Add(aE2);
302 }// for (i=1; i<=aNbE; ++i) {
309 //printf(" EdgesToAvoid=%d, iCnt=%d\n", EdgesToAvoid.Extent(), iCnt);
311 //=======================================================================
312 //function : PerformLoops
314 //=======================================================================
315 void BOPAlgo_BuilderFace::PerformLoops()
319 Standard_Boolean bFlag;
320 Standard_Integer iErr, aNbEA;
321 BOPCol_ListIteratorOfListOfShape aIt;
322 BOPCol_MapIteratorOfMapOfOrientedShape aItM;
323 BOPCol_IndexedDataMapOfShapeListOfShape aVEMap;
324 BOPCol_MapOfOrientedShape aMAdded;
325 TopoDS_Iterator aItW;
327 BOPAlgo_WireEdgeSet aWES(myAllocator);
328 BOPAlgo_WireSplitter aWSp(myAllocator);
332 aWES.SetFace(myFace);
334 aIt.Initialize(myShapes);
335 for (; aIt.More(); aIt.Next()) {
336 const TopoDS_Shape& aE=aIt.Value();
337 if (!myShapesToAvoid.Contains(aE)) {
338 aWES.AddStartElement(aE);
343 aWSp.SetRunParallel(myRunParallel);
345 iErr=aWSp.ErrorStatus();
350 const BOPCol_ListOfShape& aLW=aWES.Shapes();
351 aIt.Initialize (aLW);
352 for (; aIt.More(); aIt.Next()) {
353 const TopoDS_Shape& aW=aIt.Value();
357 BOPCol_MapOfOrientedShape aMEP;
359 // a. collect all edges that are in loops
360 aIt.Initialize (myLoops);
361 for (; aIt.More(); aIt.Next()) {
362 const TopoDS_Shape& aW=aIt.Value();
364 for (; aItW.More(); aItW.Next()) {
365 const TopoDS_Shape& aE=aItW.Value();
370 // b. collect all edges that are to avoid
371 aItM.Initialize(myShapesToAvoid);
372 for (; aItM.More(); aItM.Next()) {
373 const TopoDS_Shape& aE=aItM.Key();
377 // c. add all edges that are not processed to myShapesToAvoid
378 aIt.Initialize (myShapes);
379 for (; aIt.More(); aIt.Next()) {
380 const TopoDS_Shape& aE=aIt.Value();
381 if (!aMEP.Contains(aE)) {
382 myShapesToAvoid.Add(aE);
387 myLoopsInternal.Clear();
389 aNbEA=myShapesToAvoid.Extent();
390 aItM.Initialize(myShapesToAvoid);
391 for (; aItM.More(); aItM.Next()) {
392 const TopoDS_Shape& aEE=aItM.Key();
393 BOPTools::MapShapesAndAncestors(aEE,
400 aItM.Initialize(myShapesToAvoid);
401 for (; aItM.More()&&bFlag; aItM.Next()) {
402 const TopoDS_Shape& aEE=aItM.Key();
403 if (!aMAdded.Add(aEE)) {
413 for (; aItW.More()&&bFlag; aItW.Next()) {
414 const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&aItW.Value()));
416 TopoDS_Iterator aItE(aE);
417 for (; aItE.More()&&bFlag; aItE.Next()) {
418 const TopoDS_Vertex& aV = (*(TopoDS_Vertex *)(&aItE.Value()));
419 const BOPCol_ListOfShape& aLE=aVEMap.FindFromKey(aV);
421 for (; aIt.More()&&bFlag; aIt.Next()) {
422 const TopoDS_Shape& aEx=aIt.Value();
423 if (aMAdded.Add(aEx)) {
425 if(aMAdded.Extent()==aNbEA) {
429 }//for (; aIt.More(); aIt.Next()) {
430 }//for (; aItE.More(); aItE.Next()) {
431 }//for (; aItW.More(); aItW.Next()) {
432 myLoopsInternal.Append(aW);
433 }//for (; aItM.More(); aItM.Next()) {
437 //=======================================================================
438 //function : PerformAreas
440 //=======================================================================
441 void BOPAlgo_BuilderFace::PerformAreas()
443 Standard_Boolean bIsGrowth, bIsHole;
444 Standard_Integer k,aNbHoles;
446 TopLoc_Location aLoc;
447 Handle(Geom_Surface) aS;
451 BOPCol_ListIteratorOfListOfInteger aItLI;
452 BOPCol_IndexedMapOfShape aMHE;
453 BOPCol_DataMapOfShapeShape aInOutMap;
454 BOPCol_DataMapIteratorOfDataMapOfShapeShape aItDMSS;
455 BOPCol_DataMapOfShapeListOfShape aMSH;
456 BOPCol_DataMapIteratorOfDataMapOfShapeListOfShape aItMSH;
457 BOPCol_ListIteratorOfListOfShape aIt1;
458 BOPAlgo_DataMapOfIntegerShapeBox2D aDMISB(100);
459 BOPAlgo_DataMapIteratorOfDataMapOfIntegerShapeBox2D aItDMISB;
461 BOPCol_Box2DBndTreeSelector aSelector;
462 BOPCol_Box2DBndTree aBBTree;
463 NCollection_UBTreeFiller <Standard_Integer, Bnd_Box2d> aTreeFiller(aBBTree);
467 aTol=BRep_Tool::Tolerance(myFace);
468 aS=BRep_Tool::Surface(myFace, aLoc);
472 // 1. Growthes and Holes -> aDMISB: [Index/ShapeBox2D]
473 aIt1.Initialize(myLoops);
474 for (k=0 ; aIt1.More(); aIt1.Next(), ++k) {
477 const TopoDS_Shape& aWire=aIt1.Value();
479 aBB.MakeFace(aFace, aS, aLoc, aTol);
480 aBB.Add (aFace, aWire);
481 BRepTools::AddUVBounds(aFace, aBox2D);
483 bIsGrowth=IsGrowthWire(aWire, aMHE);
485 bIsHole=Standard_False;
488 // check if a wire is a hole
489 IntTools_FClass2d& aClsf=myContext->FClass2d(aFace);
490 aClsf.Init(aFace, aTol);
492 bIsHole=aClsf.IsHole();
494 BOPTools::MapShapes(aWire, TopAbs_EDGE, aMHE);
496 bIsHole=Standard_True;
499 bIsHole=Standard_False;
503 BOPAlgo_ShapeBox2D aSB2D;
505 aSB2D.SetShape(aFace);
506 aSB2D.SetBox2D(aBox2D);
507 aSB2D.SetIsHole(bIsHole);
509 aDMISB.Bind(k, aSB2D);
512 // 2. Prepare TreeFiller
513 aItDMISB.Initialize(aDMISB);
514 for (; aItDMISB.More(); aItDMISB.Next()) {
516 const BOPAlgo_ShapeBox2D& aSB2D=aItDMISB.Value();
518 bIsHole=aSB2D.IsHole();
520 const Bnd_Box2d& aBox2D=aSB2D.Box2D();
521 aTreeFiller.Add(k, aBox2D);
525 // 3. Shake TreeFiller
528 // 4. Find outer growth shell that is most close
529 // to each hole shell
530 aItDMISB.Initialize(aDMISB);
531 for (; aItDMISB.More(); aItDMISB.Next()) {
533 const BOPAlgo_ShapeBox2D& aSB2D=aItDMISB.Value();
534 bIsHole=aSB2D.IsHole();
539 const Bnd_Box2d& aBox2DF=aSB2D.Box2D();
540 const TopoDS_Shape aF=aSB2D.Shape();
543 aSelector.SetBox(aBox2DF);
545 aNbHoles=aBBTree.Select(aSelector);
547 const BOPCol_ListOfInteger& aLI=aSelector.Indices();
549 aItLI.Initialize(aLI);
550 for (; aItLI.More(); aItLI.Next()) {
552 const BOPAlgo_ShapeBox2D& aSB2Dk=aDMISB.Find(k);
553 const TopoDS_Shape& aHole=aSB2Dk.Shape();
555 if (!IsInside(aHole, aF, myContext)){
559 if (aInOutMap.IsBound (aHole)){
560 const TopoDS_Shape& aF2=aInOutMap(aHole);
561 if (IsInside(aF, aF2, myContext)) {
562 aInOutMap.UnBind(aHole);
563 aInOutMap.Bind (aHole, aF);
567 aInOutMap.Bind(aHole, aF);
572 // 5. Map [Face/Holes] -> aMSH
573 aItDMSS.Initialize(aInOutMap);
574 for (; aItDMSS.More(); aItDMSS.Next()) {
575 const TopoDS_Shape& aHole=aItDMSS.Key();
576 const TopoDS_Shape& aF=aItDMSS.Value();
578 if (aMSH.IsBound(aF)) {
579 BOPCol_ListOfShape& aLH=aMSH.ChangeFind(aF);
583 BOPCol_ListOfShape aLH;
589 // 6. Add aHoles to Faces,
590 aItMSH.Initialize(aMSH);
591 for (; aItMSH.More(); aItMSH.Next()) {
592 TopoDS_Face aF=(*(TopoDS_Face *)(&aItMSH.Key()));
594 const BOPCol_ListOfShape& aLH=aItMSH.Value();
595 aIt1.Initialize(aLH);
596 for (; aIt1.More(); aIt1.Next()) {
599 const TopoDS_Shape& aFHole=aIt1.Value();
600 GetWire(aFHole, aWHole);
601 aBB.Add (aF, aWHole);
605 aTol=BRep_Tool::Tolerance(aF);
606 IntTools_FClass2d& aClsf=myContext->FClass2d(aF);
607 aClsf.Init(aF, aTol);
611 // NB:These aNewFaces are draft faces that
612 // do not contain any internal shapes
613 aItDMISB.Initialize(aDMISB);
614 for (; aItDMISB.More(); aItDMISB.Next()) {
615 const BOPAlgo_ShapeBox2D& aSB2D=aItDMISB.Value();
616 bIsHole=aSB2D.IsHole();
618 const TopoDS_Shape aF=aSB2D.Shape();
623 //=======================================================================
626 //=======================================================================
627 void GetWire(const TopoDS_Shape& aF, TopoDS_Shape& aW)
633 for (; aIt.More(); aIt.Next()) {
637 //=======================================================================
638 //function : PerformInternalShapes
640 //=======================================================================
641 void BOPAlgo_BuilderFace::PerformInternalShapes()
645 Standard_Integer aNbWI=myLoopsInternal.Extent();
646 if (!aNbWI) {// nothing to do
650 //Standard_Real aTol;
652 BOPCol_ListIteratorOfListOfShape aIt1, aIt2;
654 BOPCol_MapOfShape aME, aMEP;
655 BOPCol_MapIteratorOfMapOfShape aItME;
656 BOPCol_IndexedDataMapOfShapeListOfShape aMVE;
657 BOPCol_ListOfShape aLSI;
659 // 1. All internal edges
660 aIt1.Initialize(myLoopsInternal);
661 for (; aIt1.More(); aIt1.Next()) {
662 const TopoDS_Shape& aWire=aIt1.Value();
663 aIt.Initialize(aWire);
664 for (; aIt.More(); aIt.Next()) {
665 const TopoDS_Shape& aE=aIt.Value();
672 aIt2.Initialize(myAreas);
673 for ( ; aIt2.More(); aIt2.Next()) {
674 TopoDS_Face& aF=(*(TopoDS_Face *)(&aIt2.Value()));
677 BOPTools::MapShapesAndAncestors(aF, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
679 // 2.1 Separate faces to process aMEP
681 aItME.Initialize(aME);
682 for (; aItME.More(); aItME.Next()) {
683 const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&aItME.Key()));
684 if (IsInside(aE, aF, myContext)) {
689 // 2.2 Make Internal Wires
691 MakeInternalWires(aMEP, aLSI);
693 // 2.3 Add them to aF
694 aIt1.Initialize(aLSI);
695 for (; aIt1.More(); aIt1.Next()) {
696 const TopoDS_Shape& aSI=aIt1.Value();
700 // 2.4 Remove faces aMFP from aMF
701 aItME.Initialize(aMEP);
702 for (; aItME.More(); aItME.Next()) {
703 const TopoDS_Shape& aE=aItME.Key();
711 } //for ( ; aIt2.More(); aIt2.Next()) {
713 //=======================================================================
714 //function : MakeInternalWires
716 //=======================================================================
717 void MakeInternalWires(const BOPCol_MapOfShape& theME,
718 BOPCol_ListOfShape& theWires)
720 BOPCol_MapIteratorOfMapOfShape aItM;
721 BOPCol_MapOfShape aAddedMap;
722 BOPCol_ListIteratorOfListOfShape aItE;
723 BOPCol_IndexedDataMapOfShapeListOfShape aMVE;
726 aItM.Initialize(theME);
727 for (; aItM.More(); aItM.Next()) {
728 const TopoDS_Shape& aE=aItM.Key();
729 BOPTools::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
732 aItM.Initialize(theME);
733 for (; aItM.More(); aItM.Next()) {
734 TopoDS_Shape aEE=aItM.Key();
735 if (!aAddedMap.Add(aEE)) {
742 aEE.Orientation(TopAbs_INTERNAL);
745 TopoDS_Iterator aItAdded (aW);
746 for (; aItAdded.More(); aItAdded.Next()) {
747 const TopoDS_Shape& aE =aItAdded.Value();
749 TopExp_Explorer aExp(aE, TopAbs_VERTEX);
750 for (; aExp.More(); aExp.Next()) {
751 const TopoDS_Shape& aV =aExp.Current();
752 const BOPCol_ListOfShape& aLE=aMVE.FindFromKey(aV);
753 aItE.Initialize(aLE);
754 for (; aItE.More(); aItE.Next()) {
755 TopoDS_Shape aEL=aItE.Value();
756 if (aAddedMap.Add(aEL)){
757 aEL.Orientation(TopAbs_INTERNAL);
766 //=======================================================================
767 //function : IsInside
769 //=======================================================================
770 Standard_Boolean IsInside(const TopoDS_Shape& theHole,
771 const TopoDS_Shape& theF2,
772 Handle(IntTools_Context)& theContext)
774 Standard_Boolean bRet;
775 Standard_Real aT, aU, aV;
778 TopExp_Explorer aExp;
779 BOPCol_IndexedMapOfShape aME2;
783 aState=TopAbs_UNKNOWN;
784 const TopoDS_Face& aF2=(*(TopoDS_Face *)(&theF2));
786 BOPTools::MapShapes(aF2, TopAbs_EDGE, aME2);//AA
788 aExp.Init(theHole, TopAbs_EDGE);
790 const TopoDS_Edge& aE =(*(TopoDS_Edge *)(&aExp.Current()));
791 if (aME2.Contains(aE)) {
794 if (!BRep_Tool::Degenerated(aE)) {
796 aT=BOPTools_AlgoTools2D::IntermediatePoint(aE);
797 BOPTools_AlgoTools2D::PointOnSurface(aE, aF2, aT, aU, aV);
798 aP2D.SetCoord(aU, aV);
800 IntTools_FClass2d& aClsf=theContext->FClass2d(aF2);
801 aState=aClsf.Perform(aP2D);
802 bRet=(aState==TopAbs_IN);
809 //=======================================================================
810 //function : IsGrowthWire
812 //=======================================================================
813 Standard_Boolean IsGrowthWire(const TopoDS_Shape& theWire,
814 const BOPCol_IndexedMapOfShape& theMHE)
816 Standard_Boolean bRet;
820 if (theMHE.Extent()) {
821 aIt.Initialize(theWire);
822 for(; aIt.More(); aIt.Next()) {
823 const TopoDS_Shape& aE=aIt.Value();
824 if (theMHE.Contains(aE)) {
832 //BRepTools::Write(aFF, "ff");
836 // 12 - Null face generix