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
10 // under the terms of the GNU Lesser General Public 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.
18 #include <BOPAlgo_BuilderFace.ixx>
20 #include <gp_Pnt2d.hxx>
26 #include <Geom_Surface.hxx>
29 #include <TopLoc_Location.hxx>
31 #include <TopoDS_Iterator.hxx>
32 #include <TopoDS_Face.hxx>
33 #include <TopoDS_Shape.hxx>
34 #include <TopoDS_Wire.hxx>
35 #include <TopoDS_Edge.hxx>
36 #include <TopoDS_Vertex.hxx>
38 #include <BRep_Builder.hxx>
39 #include <BRep_Tool.hxx>
40 #include <BRepTools.hxx>
43 #include <TopExp_Explorer.hxx>
45 #include <IntTools_FClass2d.hxx>
46 #include <BOPInt_Context.hxx>
49 #include <BOPTools_AlgoTools.hxx>
50 #include <BOPTools_AlgoTools2D.hxx>
51 #include <BOPAlgo_WireEdgeSet.hxx>
53 #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
54 #include <BOPTools.hxx>
55 #include <BOPCol_ListOfShape.hxx>
56 #include <BOPAlgo_WireSplitter.hxx>
57 #include <BOPCol_DataMapOfShapeShape.hxx>
58 #include <BOPCol_DataMapOfShapeListOfShape.hxx>
59 #include <BOPCol_MapOfShape.hxx>
63 Standard_Boolean IsGrowthWire(const TopoDS_Shape& ,
64 const BOPCol_IndexedMapOfShape& );
67 Standard_Boolean IsInside(const TopoDS_Shape& ,
69 Handle(BOPInt_Context)& );
71 void MakeInternalWires(const BOPCol_MapOfShape& ,
72 BOPCol_ListOfShape& );
74 //=======================================================================
77 //=======================================================================
78 BOPAlgo_BuilderFace::BOPAlgo_BuilderFace()
82 myOrientation=TopAbs_EXTERNAL;
84 //=======================================================================
87 //=======================================================================
88 BOPAlgo_BuilderFace::BOPAlgo_BuilderFace(const Handle(NCollection_BaseAllocator)& theAllocator)
90 BOPAlgo_BuilderArea(theAllocator)
92 myOrientation=TopAbs_EXTERNAL;
94 //=======================================================================
97 //=======================================================================
98 BOPAlgo_BuilderFace::~BOPAlgo_BuilderFace()
101 //=======================================================================
104 //=======================================================================
105 void BOPAlgo_BuilderFace::SetFace(const TopoDS_Face& theFace)
107 myOrientation=theFace.Orientation();
109 myFace.Orientation(TopAbs_FORWARD);
111 //=======================================================================
112 //function : Orientation
114 //=======================================================================
115 TopAbs_Orientation BOPAlgo_BuilderFace::Orientation()const
117 return myOrientation;
119 //=======================================================================
122 //=======================================================================
123 const TopoDS_Face& BOPAlgo_BuilderFace::Face()const
127 //=======================================================================
128 //function : CheckData
130 //=======================================================================
131 void BOPAlgo_BuilderFace::CheckData()
135 if (myContext.IsNull()) {
136 //myErrorStatus=11;// Null Context
138 myContext = new BOPInt_Context;
141 if (myFace.IsNull()) {
142 myErrorStatus=12;// Null face generix
146 //=======================================================================
149 //=======================================================================
150 void BOPAlgo_BuilderFace::Perform()
159 PerformShapesToAvoid();
174 PerformInternalShapes();
179 //=======================================================================
180 //function :PerformShapesToAvoid
182 //=======================================================================
183 void BOPAlgo_BuilderFace::PerformShapesToAvoid()
185 Standard_Boolean bFound;
186 Standard_Integer i, iCnt, aNbV, aNbE;
187 BOPCol_IndexedDataMapOfShapeListOfShape aMVE;
188 BOPCol_ListIteratorOfListOfShape aIt;
190 myShapesToAvoid.Clear();
195 bFound=Standard_False;
199 aIt.Initialize (myShapes);
200 for (; aIt.More(); aIt.Next()) {
201 const TopoDS_Shape& aE=aIt.Value();
202 if (!myShapesToAvoid.Contains(aE)) {
203 BOPTools::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
212 for (i=1; i<=aNbV; ++i) {
213 const TopoDS_Vertex& aV=(*(TopoDS_Vertex *)(&aMVE.FindKey(i)));
215 BOPCol_ListOfShape& aLE=aMVE.ChangeFromKey(aV);
221 const TopoDS_Edge& aE1=(*(TopoDS_Edge *)(&aLE.First()));
223 if (BRep_Tool::Degenerated(aE1)) {
226 if (aV.Orientation()==TopAbs_INTERNAL) {
229 bFound=Standard_True;
230 myShapesToAvoid.Add(aE1);
233 const TopoDS_Edge& aE2=(*(TopoDS_Edge *)(&aLE.Last()));
234 if (aE2.IsSame(aE1)) {
235 TopoDS_Vertex aV1x, aV2x;
237 TopExp::Vertices(aE1, aV1x, aV2x);
238 if (aV1x.IsSame(aV2x)) {
241 bFound=Standard_True;
242 myShapesToAvoid.Add(aE1);
243 myShapesToAvoid.Add(aE2);
246 }// for (i=1; i<=aNbE; ++i) {
253 //printf(" EdgesToAvoid=%d, iCnt=%d\n", EdgesToAvoid.Extent(), iCnt);
255 //=======================================================================
256 //function : PerformLoops
258 //=======================================================================
259 void BOPAlgo_BuilderFace::PerformLoops()
263 Standard_Boolean bFlag;
264 Standard_Integer iErr, aNbEA;
265 BOPCol_ListIteratorOfListOfShape aIt;
266 BOPCol_MapIteratorOfMapOfOrientedShape aItM;
267 BOPCol_IndexedDataMapOfShapeListOfShape aVEMap;
268 BOPCol_MapOfOrientedShape aMAdded;
269 TopoDS_Iterator aItW;
271 BOPAlgo_WireEdgeSet aWES(myAllocator);
272 BOPAlgo_WireSplitter aWSp(myAllocator);
276 aWES.SetFace(myFace);
278 aIt.Initialize(myShapes);
279 for (; aIt.More(); aIt.Next()) {
280 const TopoDS_Shape& aE=aIt.Value();
281 if (!myShapesToAvoid.Contains(aE)) {
282 aWES.AddStartElement(aE);
288 iErr=aWSp.ErrorStatus();
293 const BOPCol_ListOfShape& aLW=aWES.Shapes();
294 aIt.Initialize (aLW);
295 for (; aIt.More(); aIt.Next()) {
296 const TopoDS_Shape& aW=aIt.Value();
300 BOPCol_MapOfOrientedShape aMEP;
302 // a. collect all edges that are in loops
303 aIt.Initialize (myLoops);
304 for (; aIt.More(); aIt.Next()) {
305 const TopoDS_Shape& aW=aIt.Value();
307 for (; aItW.More(); aItW.Next()) {
308 const TopoDS_Shape& aE=aItW.Value();
313 // b. collect all edges that are to avoid
314 aItM.Initialize(myShapesToAvoid);
315 for (; aItM.More(); aItM.Next()) {
316 const TopoDS_Shape& aE=aItM.Key();
320 // c. add all edges that are not processed to myShapesToAvoid
321 aIt.Initialize (myShapes);
322 for (; aIt.More(); aIt.Next()) {
323 const TopoDS_Shape& aE=aIt.Value();
324 if (!aMEP.Contains(aE)) {
325 myShapesToAvoid.Add(aE);
330 myLoopsInternal.Clear();
332 aNbEA=myShapesToAvoid.Extent();
333 aItM.Initialize(myShapesToAvoid);
334 for (; aItM.More(); aItM.Next()) {
335 const TopoDS_Shape& aEE=aItM.Key();
336 BOPTools::MapShapesAndAncestors(aEE, TopAbs_VERTEX, TopAbs_EDGE, aVEMap);
340 aItM.Initialize(myShapesToAvoid);
341 for (; aItM.More()&&bFlag; aItM.Next()) {
342 const TopoDS_Shape& aEE=aItM.Key();
343 if (!aMAdded.Add(aEE)) {
353 for (; aItW.More()&&bFlag; aItW.Next()) {
354 const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&aItW.Value()));
356 TopoDS_Iterator aItE(aE);
357 for (; aItE.More()&&bFlag; aItE.Next()) {
358 const TopoDS_Vertex& aV = (*(TopoDS_Vertex *)(&aItE.Value()));
359 const BOPCol_ListOfShape& aLE=aVEMap.FindFromKey(aV);
361 for (; aIt.More()&&bFlag; aIt.Next()) {
362 const TopoDS_Shape& aEx=aIt.Value();
363 if (aMAdded.Add(aEx)) {
365 if(aMAdded.Extent()==aNbEA) {
369 }//for (; aIt.More(); aIt.Next()) {
370 }//for (; aItE.More(); aItE.Next()) {
371 }//for (; aItW.More(); aItW.Next()) {
372 myLoopsInternal.Append(aW);
373 }//for (; aItM.More(); aItM.Next()) {
375 //=======================================================================
376 //function : PerformAreas
378 //=======================================================================
379 void BOPAlgo_BuilderFace::PerformAreas()
383 Standard_Boolean bIsGrowth, bIsHole;
385 TopoDS_Shape anInfinitePointShape;
387 BOPCol_ListOfShape aNewFaces, aHoleWires;
388 BOPCol_DataMapOfShapeShape aInOutMap;
389 BOPCol_DataMapOfShapeListOfShape aMSH;
390 BOPCol_IndexedMapOfShape aMHE;
392 BOPCol_DataMapIteratorOfDataMapOfShapeListOfShape aItMSH;
393 BOPCol_ListIteratorOfListOfShape aIt1, aIt2;
395 Handle(Geom_Surface) aS;
396 TopLoc_Location aLoc;
398 aTol=BRep_Tool::Tolerance(myFace);
399 aS=BRep_Tool::Surface(myFace, aLoc);
403 // Draft faces [aNewFaces]
404 aIt1.Initialize(myLoops);
405 for ( ; aIt1.More(); aIt1.Next()) {
406 const TopoDS_Shape& aWire=aIt1.Value();
408 bIsGrowth=IsGrowthWire(aWire, aMHE);
410 // make a growth face from a wire
412 aBB.MakeFace(aFace, aS, aLoc, aTol);
413 aBB.Add (aFace, aWire);
415 aNewFaces.Append (aFace);
418 // check if a wire is a hole
421 aBB.MakeFace(aFace, aS, aLoc, aTol);
422 aBB.Add (aFace, aWire);
424 IntTools_FClass2d& aClsf=myContext->FClass2d(aFace);
425 aClsf.Init(aFace, aTol);
427 bIsHole=aClsf.IsHole();
429 //bIsHole=BOPTools_AlgoTools::IsHole(aWire, myFace);
432 aHoleWires.Append(aWire);
433 BOPTools::MapShapes(aWire, TopAbs_EDGE, aMHE);
436 // make a growth face from a wire
438 aBB.MakeFace(aFace, aS, aLoc, aTol);
439 aBB.Add (aFace, aWire);
441 aNewFaces.Append (aFace);
446 // 2. Find outer growth shell that is most close to each hole shell
447 aIt2.Initialize(aHoleWires);
448 for (; aIt2.More(); aIt2.Next()) {
449 const TopoDS_Shape& aHole = aIt2.Value();
451 aIt1.Initialize(aNewFaces);
452 for ( ; aIt1.More(); aIt1.Next()) {
453 const TopoDS_Shape& aF=aIt1.Value();
455 if (!IsInside(aHole, aF, myContext)){
459 if ( aInOutMap.IsBound (aHole)){
460 const TopoDS_Shape& aF2=aInOutMap(aHole);
461 if (IsInside(aF, aF2, myContext)) {
462 aInOutMap.UnBind(aHole);
463 aInOutMap.Bind (aHole, aF);
467 aInOutMap.Bind (aHole, aF);
471 // Add aHole to a map Face/ListOfHoles [aMSH]
472 if (aInOutMap.IsBound(aHole)){
473 const TopoDS_Shape& aF=aInOutMap(aHole);
474 if (aMSH.IsBound(aF)) {
475 BOPCol_ListOfShape& aLH=aMSH.ChangeFind(aF);
479 BOPCol_ListOfShape aLH;
484 }// for (; aIt2.More(); aIt2.Next())
486 // 3. Add aHoles to Faces
487 aItMSH.Initialize(aMSH);
488 for (; aItMSH.More(); aItMSH.Next()) {
489 TopoDS_Face aF=(*(TopoDS_Face *)(&aItMSH.Key()));
491 const BOPCol_ListOfShape& aLH=aItMSH.Value();
492 aIt2.Initialize(aLH);
493 for (; aIt2.More(); aIt2.Next()) {
494 const TopoDS_Shape& aHole = aIt2.Value();
499 aTol=BRep_Tool::Tolerance(aF);
500 IntTools_FClass2d& aClsf=myContext->FClass2d(aF);
501 aClsf.Init(aF, aTol);
504 // These aNewFaces are draft faces that
505 // do not contain any internal shapes
507 aIt1.Initialize(aNewFaces);
508 for ( ; aIt1.More(); aIt1.Next()) {
509 const TopoDS_Shape& aF=aIt1.Value();
513 //=======================================================================
514 //function : PerformInternalShapes
516 //=======================================================================
517 void BOPAlgo_BuilderFace::PerformInternalShapes()
521 Standard_Integer aNbWI=myLoopsInternal.Extent();
522 if (!aNbWI) {// nothing to do
526 //Standard_Real aTol;
528 BOPCol_ListIteratorOfListOfShape aIt1, aIt2;
530 BOPCol_MapOfShape aME, aMEP;
531 BOPCol_MapIteratorOfMapOfShape aItME;
532 BOPCol_IndexedDataMapOfShapeListOfShape aMVE;
533 BOPCol_ListOfShape aLSI;
535 // 1. All internal edges
536 aIt1.Initialize(myLoopsInternal);
537 for (; aIt1.More(); aIt1.Next()) {
538 const TopoDS_Shape& aWire=aIt1.Value();
539 aIt.Initialize(aWire);
540 for (; aIt.More(); aIt.Next()) {
541 const TopoDS_Shape& aE=aIt.Value();
548 aIt2.Initialize(myAreas);
549 for ( ; aIt2.More(); aIt2.Next()) {
550 TopoDS_Face& aF=(*(TopoDS_Face *)(&aIt2.Value()));
553 BOPTools::MapShapesAndAncestors(aF, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
555 // 2.1 Separate faces to process aMEP
557 aItME.Initialize(aME);
558 for (; aItME.More(); aItME.Next()) {
559 const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&aItME.Key()));
560 if (IsInside(aE, aF, myContext)) {
565 // 2.2 Make Internal Wires
567 MakeInternalWires(aMEP, aLSI);
569 // 2.3 Add them to aF
570 aIt1.Initialize(aLSI);
571 for (; aIt1.More(); aIt1.Next()) {
572 const TopoDS_Shape& aSI=aIt1.Value();
576 // 2.4 Remove faces aMFP from aMF
577 aItME.Initialize(aMEP);
578 for (; aItME.More(); aItME.Next()) {
579 const TopoDS_Shape& aE=aItME.Key();
587 } //for ( ; aIt2.More(); aIt2.Next()) {
589 //=======================================================================
590 //function : MakeInternalWires
592 //=======================================================================
593 void MakeInternalWires(const BOPCol_MapOfShape& theME,
594 BOPCol_ListOfShape& theWires)
596 BOPCol_MapIteratorOfMapOfShape aItM;
597 BOPCol_MapOfShape aAddedMap;
598 BOPCol_ListIteratorOfListOfShape aItE;
599 BOPCol_IndexedDataMapOfShapeListOfShape aMVE;
602 aItM.Initialize(theME);
603 for (; aItM.More(); aItM.Next()) {
604 const TopoDS_Shape& aE=aItM.Key();
605 BOPTools::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
608 aItM.Initialize(theME);
609 for (; aItM.More(); aItM.Next()) {
610 TopoDS_Shape aEE=aItM.Key();
611 if (!aAddedMap.Add(aEE)) {
618 aEE.Orientation(TopAbs_INTERNAL);
621 TopoDS_Iterator aItAdded (aW);
622 for (; aItAdded.More(); aItAdded.Next()) {
623 const TopoDS_Shape& aE =aItAdded.Value();
625 TopExp_Explorer aExp(aE, TopAbs_VERTEX);
626 for (; aExp.More(); aExp.Next()) {
627 const TopoDS_Shape& aV =aExp.Current();
628 const BOPCol_ListOfShape& aLE=aMVE.FindFromKey(aV);
629 aItE.Initialize(aLE);
630 for (; aItE.More(); aItE.Next()) {
631 TopoDS_Shape aEL=aItE.Value();
632 if (aAddedMap.Add(aEL)){
633 aEL.Orientation(TopAbs_INTERNAL);
642 //=======================================================================
643 //function : IsInside
645 //=======================================================================
646 Standard_Boolean IsInside(const TopoDS_Shape& theHole,
647 const TopoDS_Shape& theF2,
648 Handle(BOPInt_Context)& theContext)
650 Standard_Boolean bRet;
651 Standard_Real aT, aU, aV;
654 TopExp_Explorer aExp;
655 BOPCol_IndexedMapOfShape aME2;
659 aState=TopAbs_UNKNOWN;
660 const TopoDS_Face& aF2=(*(TopoDS_Face *)(&theF2));
662 BOPTools::MapShapes(aF2, TopAbs_EDGE, aME2);//AA
664 aExp.Init(theHole, TopAbs_EDGE);
666 const TopoDS_Edge& aE =(*(TopoDS_Edge *)(&aExp.Current()));
667 if (aME2.Contains(aE)) {
670 if (!BRep_Tool::Degenerated(aE)) {
672 aT=BOPTools_AlgoTools2D::IntermediatePoint(aE);
673 BOPTools_AlgoTools2D::PointOnSurface(aE, aF2, aT, aU, aV);
674 aP2D.SetCoord(aU, aV);
676 IntTools_FClass2d& aClsf=theContext->FClass2d(aF2);
677 aState=aClsf.Perform(aP2D);
678 bRet=(aState==TopAbs_IN);
685 //=======================================================================
686 //function : IsGrowthWire
688 //=======================================================================
689 Standard_Boolean IsGrowthWire(const TopoDS_Shape& theWire,
690 const BOPCol_IndexedMapOfShape& theMHE)
692 Standard_Boolean bRet;
696 if (theMHE.Extent()) {
697 aIt.Initialize(theWire);
698 for(; aIt.More(); aIt.Next()) {
699 const TopoDS_Shape& aE=aIt.Value();
700 if (theMHE.Contains(aE)) {
708 //BRepTools::Write(aFF, "ff");
712 // 12 - Null face generix