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
7 // The content of this file is subject to the Open CASCADE Technology Public
8 // License Version 6.5 (the "License"). You may not use the content of this file
9 // except in compliance with the License. Please obtain a copy of the License
10 // at http://www.opencascade.org and read it completely before using this file.
12 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
13 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
15 // The Original Code and all software distributed under the License is
16 // distributed on an "AS IS" basis, without warranty of any kind, and the
17 // Initial Developer hereby disclaims all such warranties, including without
18 // limitation, any warranties of merchantability, fitness for a particular
19 // purpose or non-infringement. Please see the License for the specific terms
20 // and conditions governing the rights and limitations under the License.
22 #include <BOPAlgo_BuilderFace.ixx>
24 #include <gp_Pnt2d.hxx>
30 #include <Geom_Surface.hxx>
33 #include <TopLoc_Location.hxx>
35 #include <TopoDS_Iterator.hxx>
36 #include <TopoDS_Face.hxx>
37 #include <TopoDS_Shape.hxx>
38 #include <TopoDS_Wire.hxx>
39 #include <TopoDS_Edge.hxx>
40 #include <TopoDS_Vertex.hxx>
42 #include <BRep_Builder.hxx>
43 #include <BRep_Tool.hxx>
44 #include <BRepTools.hxx>
47 #include <TopExp_Explorer.hxx>
49 #include <IntTools_FClass2d.hxx>
50 #include <BOPInt_Context.hxx>
53 #include <BOPTools_AlgoTools.hxx>
54 #include <BOPTools_AlgoTools2D.hxx>
55 #include <BOPAlgo_WireEdgeSet.hxx>
57 #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
58 #include <BOPTools.hxx>
59 #include <BOPCol_ListOfShape.hxx>
60 #include <BOPAlgo_WireSplitter.hxx>
61 #include <BOPCol_DataMapOfShapeShape.hxx>
62 #include <BOPCol_DataMapOfShapeListOfShape.hxx>
63 #include <BOPCol_MapOfShape.hxx>
67 Standard_Boolean IsGrowthWire(const TopoDS_Shape& ,
68 const BOPCol_IndexedMapOfShape& );
71 Standard_Boolean IsInside(const TopoDS_Shape& ,
73 Handle(BOPInt_Context)& );
75 void MakeInternalWires(const BOPCol_MapOfShape& ,
76 BOPCol_ListOfShape& );
78 //=======================================================================
81 //=======================================================================
82 BOPAlgo_BuilderFace::BOPAlgo_BuilderFace()
87 //=======================================================================
90 //=======================================================================
91 BOPAlgo_BuilderFace::BOPAlgo_BuilderFace(const Handle(NCollection_BaseAllocator)& theAllocator)
93 BOPAlgo_BuilderArea(theAllocator)
96 //=======================================================================
99 //=======================================================================
100 BOPAlgo_BuilderFace::~BOPAlgo_BuilderFace()
103 //=======================================================================
106 //=======================================================================
107 void BOPAlgo_BuilderFace::SetFace(const TopoDS_Face& theFace)
111 //=======================================================================
114 //=======================================================================
115 const TopoDS_Face& BOPAlgo_BuilderFace::Face()const
119 //=======================================================================
120 //function : CheckData
122 //=======================================================================
123 void BOPAlgo_BuilderFace::CheckData()
127 if (myContext.IsNull()) {
128 //myErrorStatus=11;// Null Context
130 myContext = new BOPInt_Context;
133 if (myFace.IsNull()) {
134 myErrorStatus=12;// Null face generix
138 //=======================================================================
141 //=======================================================================
142 void BOPAlgo_BuilderFace::Perform()
151 PerformShapesToAvoid();
166 PerformInternalShapes();
171 //=======================================================================
172 //function :PerformShapesToAvoid
174 //=======================================================================
175 void BOPAlgo_BuilderFace::PerformShapesToAvoid()
177 Standard_Boolean bFound;
178 Standard_Integer i, iCnt, aNbV, aNbE;
179 BOPCol_IndexedDataMapOfShapeListOfShape aMVE;
180 BOPCol_ListIteratorOfListOfShape aIt;
182 myShapesToAvoid.Clear();
187 bFound=Standard_False;
191 aIt.Initialize (myShapes);
192 for (; aIt.More(); aIt.Next()) {
193 const TopoDS_Shape& aE=aIt.Value();
194 if (!myShapesToAvoid.Contains(aE)) {
195 BOPTools::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
204 for (i=1; i<=aNbV; ++i) {
205 const TopoDS_Vertex& aV=(*(TopoDS_Vertex *)(&aMVE.FindKey(i)));
207 BOPCol_ListOfShape& aLE=aMVE.ChangeFromKey(aV);
213 const TopoDS_Edge& aE1=(*(TopoDS_Edge *)(&aLE.First()));
215 if (BRep_Tool::Degenerated(aE1)) {
218 if (aV.Orientation()==TopAbs_INTERNAL) {
221 bFound=Standard_True;
222 myShapesToAvoid.Add(aE1);
225 const TopoDS_Edge& aE2=(*(TopoDS_Edge *)(&aLE.Last()));
226 if (aE2.IsSame(aE1)) {
227 TopoDS_Vertex aV1x, aV2x;
229 TopExp::Vertices(aE1, aV1x, aV2x);
230 if (aV1x.IsSame(aV2x)) {
233 bFound=Standard_True;
234 myShapesToAvoid.Add(aE1);
235 myShapesToAvoid.Add(aE2);
238 }// for (i=1; i<=aNbE; ++i) {
245 //printf(" EdgesToAvoid=%d, iCnt=%d\n", EdgesToAvoid.Extent(), iCnt);
247 //=======================================================================
248 //function : PerformLoops
250 //=======================================================================
251 void BOPAlgo_BuilderFace::PerformLoops()
255 Standard_Boolean bFlag;
256 Standard_Integer iErr, aNbEA;
257 BOPCol_ListIteratorOfListOfShape aIt;
258 BOPCol_MapIteratorOfMapOfOrientedShape aItM;
259 BOPCol_IndexedDataMapOfShapeListOfShape aVEMap;
260 BOPCol_MapOfOrientedShape aMAdded;
261 TopoDS_Iterator aItW;
263 BOPAlgo_WireEdgeSet aWES(myAllocator);
264 BOPAlgo_WireSplitter aWSp(myAllocator);
268 aWES.SetFace(myFace);
270 aIt.Initialize(myShapes);
271 for (; aIt.More(); aIt.Next()) {
272 const TopoDS_Shape& aE=aIt.Value();
273 if (!myShapesToAvoid.Contains(aE)) {
274 aWES.AddStartElement(aE);
280 iErr=aWSp.ErrorStatus();
285 const BOPCol_ListOfShape& aLW=aWES.Shapes();
286 aIt.Initialize (aLW);
287 for (; aIt.More(); aIt.Next()) {
288 const TopoDS_Shape& aW=aIt.Value();
292 BOPCol_MapOfOrientedShape aMEP;
294 // a. collect all edges that are in loops
295 aIt.Initialize (myLoops);
296 for (; aIt.More(); aIt.Next()) {
297 const TopoDS_Shape& aW=aIt.Value();
299 for (; aItW.More(); aItW.Next()) {
300 const TopoDS_Shape& aE=aItW.Value();
305 // b. collect all edges that are to avoid
306 aItM.Initialize(myShapesToAvoid);
307 for (; aItM.More(); aItM.Next()) {
308 const TopoDS_Shape& aE=aItM.Key();
312 // c. add all edges that are not processed to myShapesToAvoid
313 aIt.Initialize (myShapes);
314 for (; aIt.More(); aIt.Next()) {
315 const TopoDS_Shape& aE=aIt.Value();
316 if (!aMEP.Contains(aE)) {
317 myShapesToAvoid.Add(aE);
322 myLoopsInternal.Clear();
324 aNbEA=myShapesToAvoid.Extent();
325 aItM.Initialize(myShapesToAvoid);
326 for (; aItM.More(); aItM.Next()) {
327 const TopoDS_Shape& aEE=aItM.Key();
328 BOPTools::MapShapesAndAncestors(aEE, TopAbs_VERTEX, TopAbs_EDGE, aVEMap);
332 aItM.Initialize(myShapesToAvoid);
333 for (; aItM.More()&&bFlag; aItM.Next()) {
334 const TopoDS_Shape& aEE=aItM.Key();
335 if (!aMAdded.Add(aEE)) {
345 for (; aItW.More()&&bFlag; aItW.Next()) {
346 const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&aItW.Value()));
348 TopoDS_Iterator aItE(aE);
349 for (; aItE.More()&&bFlag; aItE.Next()) {
350 const TopoDS_Vertex& aV = (*(TopoDS_Vertex *)(&aItE.Value()));
351 const BOPCol_ListOfShape& aLE=aVEMap.FindFromKey(aV);
353 for (; aIt.More()&&bFlag; aIt.Next()) {
354 const TopoDS_Shape& aEx=aIt.Value();
355 if (aMAdded.Add(aEx)) {
357 if(aMAdded.Extent()==aNbEA) {
361 }//for (; aIt.More(); aIt.Next()) {
362 }//for (; aItE.More(); aItE.Next()) {
363 }//for (; aItW.More(); aItW.Next()) {
364 myLoopsInternal.Append(aW);
365 }//for (; aItM.More(); aItM.Next()) {
367 //=======================================================================
368 //function : PerformAreas
370 //=======================================================================
371 void BOPAlgo_BuilderFace::PerformAreas()
375 Standard_Boolean bIsGrowth, bIsHole;
377 TopoDS_Shape anInfinitePointShape;
379 BOPCol_ListOfShape aNewFaces, aHoleWires;
380 BOPCol_DataMapOfShapeShape aInOutMap;
381 BOPCol_DataMapOfShapeListOfShape aMSH;
382 BOPCol_IndexedMapOfShape aMHE;
384 BOPCol_DataMapIteratorOfDataMapOfShapeListOfShape aItMSH;
385 BOPCol_ListIteratorOfListOfShape aIt1, aIt2;
387 Handle(Geom_Surface) aS;
388 TopLoc_Location aLoc;
390 aTol=BRep_Tool::Tolerance(myFace);
391 aS=BRep_Tool::Surface(myFace, aLoc);
395 // Draft faces [aNewFaces]
396 aIt1.Initialize(myLoops);
397 for ( ; aIt1.More(); aIt1.Next()) {
398 const TopoDS_Shape& aWire=aIt1.Value();
400 bIsGrowth=IsGrowthWire(aWire, aMHE);
402 // make a growth face from a wire
404 aBB.MakeFace(aFace, aS, aLoc, aTol);
405 aBB.Add (aFace, aWire);
407 aNewFaces.Append (aFace);
410 // check if a wire is a hole
413 aBB.MakeFace(aFace, aS, aLoc, aTol);
414 aBB.Add (aFace, aWire);
416 IntTools_FClass2d& aClsf=myContext->FClass2d(aFace);
417 aClsf.Init(aFace, aTol);
419 bIsHole=aClsf.IsHole();
421 //bIsHole=BOPTools_AlgoTools::IsHole(aWire, myFace);
424 aHoleWires.Append(aWire);
425 BOPTools::MapShapes(aWire, TopAbs_EDGE, aMHE);
428 // make a growth face from a wire
430 aBB.MakeFace(aFace, aS, aLoc, aTol);
431 aBB.Add (aFace, aWire);
433 aNewFaces.Append (aFace);
438 // 2. Find outer growth shell that is most close to each hole shell
439 aIt2.Initialize(aHoleWires);
440 for (; aIt2.More(); aIt2.Next()) {
441 const TopoDS_Shape& aHole = aIt2.Value();
443 aIt1.Initialize(aNewFaces);
444 for ( ; aIt1.More(); aIt1.Next()) {
445 const TopoDS_Shape& aF=aIt1.Value();
447 if (!IsInside(aHole, aF, myContext)){
451 if ( aInOutMap.IsBound (aHole)){
452 const TopoDS_Shape& aF2=aInOutMap(aHole);
453 if (IsInside(aF, aF2, myContext)) {
454 aInOutMap.UnBind(aHole);
455 aInOutMap.Bind (aHole, aF);
459 aInOutMap.Bind (aHole, aF);
463 // Add aHole to a map Face/ListOfHoles [aMSH]
464 if (aInOutMap.IsBound(aHole)){
465 const TopoDS_Shape& aF=aInOutMap(aHole);
466 if (aMSH.IsBound(aF)) {
467 BOPCol_ListOfShape& aLH=aMSH.ChangeFind(aF);
471 BOPCol_ListOfShape aLH;
476 }// for (; aIt2.More(); aIt2.Next())
478 // 3. Add aHoles to Faces
479 aItMSH.Initialize(aMSH);
480 for (; aItMSH.More(); aItMSH.Next()) {
481 TopoDS_Face aF=(*(TopoDS_Face *)(&aItMSH.Key()));
483 const BOPCol_ListOfShape& aLH=aItMSH.Value();
484 aIt2.Initialize(aLH);
485 for (; aIt2.More(); aIt2.Next()) {
486 const TopoDS_Shape& aHole = aIt2.Value();
491 aTol=BRep_Tool::Tolerance(aF);
492 IntTools_FClass2d& aClsf=myContext->FClass2d(aF);
493 aClsf.Init(aF, aTol);
496 // These aNewFaces are draft faces that
497 // do not contain any internal shapes
499 aIt1.Initialize(aNewFaces);
500 for ( ; aIt1.More(); aIt1.Next()) {
501 const TopoDS_Shape& aF=aIt1.Value();
505 //=======================================================================
506 //function : PerformInternalShapes
508 //=======================================================================
509 void BOPAlgo_BuilderFace::PerformInternalShapes()
513 Standard_Integer aNbWI=myLoopsInternal.Extent();
514 if (!aNbWI) {// nothing to do
518 //Standard_Real aTol;
520 BOPCol_ListIteratorOfListOfShape aIt1, aIt2;
522 BOPCol_MapOfShape aME, aMEP;
523 BOPCol_MapIteratorOfMapOfShape aItME;
524 BOPCol_IndexedDataMapOfShapeListOfShape aMVE;
525 BOPCol_ListOfShape aLSI;
527 // 1. All internal edges
528 aIt1.Initialize(myLoopsInternal);
529 for (; aIt1.More(); aIt1.Next()) {
530 const TopoDS_Shape& aWire=aIt1.Value();
531 aIt.Initialize(aWire);
532 for (; aIt.More(); aIt.Next()) {
533 const TopoDS_Shape& aE=aIt.Value();
540 aIt2.Initialize(myAreas);
541 for ( ; aIt2.More(); aIt2.Next()) {
542 TopoDS_Face& aF=(*(TopoDS_Face *)(&aIt2.Value()));
545 BOPTools::MapShapesAndAncestors(aF, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
547 // 2.1 Separate faces to process aMEP
549 aItME.Initialize(aME);
550 for (; aItME.More(); aItME.Next()) {
551 const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&aItME.Key()));
552 if (IsInside(aE, aF, myContext)) {
557 // 2.2 Make Internal Wires
559 MakeInternalWires(aMEP, aLSI);
561 // 2.3 Add them to aF
562 aIt1.Initialize(aLSI);
563 for (; aIt1.More(); aIt1.Next()) {
564 const TopoDS_Shape& aSI=aIt1.Value();
568 // 2.4 Remove faces aMFP from aMF
569 aItME.Initialize(aMEP);
570 for (; aItME.More(); aItME.Next()) {
571 const TopoDS_Shape& aE=aItME.Key();
579 } //for ( ; aIt2.More(); aIt2.Next()) {
581 //=======================================================================
582 //function : MakeInternalWires
584 //=======================================================================
585 void MakeInternalWires(const BOPCol_MapOfShape& theME,
586 BOPCol_ListOfShape& theWires)
588 BOPCol_MapIteratorOfMapOfShape aItM;
589 BOPCol_MapOfShape aAddedMap;
590 BOPCol_ListIteratorOfListOfShape aItE;
591 BOPCol_IndexedDataMapOfShapeListOfShape aMVE;
594 aItM.Initialize(theME);
595 for (; aItM.More(); aItM.Next()) {
596 const TopoDS_Shape& aE=aItM.Key();
597 BOPTools::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
600 aItM.Initialize(theME);
601 for (; aItM.More(); aItM.Next()) {
602 TopoDS_Shape aEE=aItM.Key();
603 if (!aAddedMap.Add(aEE)) {
610 aEE.Orientation(TopAbs_INTERNAL);
613 TopoDS_Iterator aItAdded (aW);
614 for (; aItAdded.More(); aItAdded.Next()) {
615 const TopoDS_Shape& aE =aItAdded.Value();
617 TopExp_Explorer aExp(aE, TopAbs_VERTEX);
618 for (; aExp.More(); aExp.Next()) {
619 const TopoDS_Shape& aV =aExp.Current();
620 const BOPCol_ListOfShape& aLE=aMVE.FindFromKey(aV);
621 aItE.Initialize(aLE);
622 for (; aItE.More(); aItE.Next()) {
623 TopoDS_Shape aEL=aItE.Value();
624 if (aAddedMap.Add(aEL)){
625 aEL.Orientation(TopAbs_INTERNAL);
634 //=======================================================================
635 //function : IsInside
637 //=======================================================================
638 Standard_Boolean IsInside(const TopoDS_Shape& theHole,
639 const TopoDS_Shape& theF2,
640 Handle(BOPInt_Context)& theContext)
642 Standard_Boolean bRet;
643 Standard_Real aT, aU, aV;
646 TopExp_Explorer aExp;
647 BOPCol_IndexedMapOfShape aME2;
651 aState=TopAbs_UNKNOWN;
652 const TopoDS_Face& aF2=(*(TopoDS_Face *)(&theF2));
654 BOPTools::MapShapes(aF2, TopAbs_EDGE, aME2);//AA
656 aExp.Init(theHole, TopAbs_EDGE);
658 const TopoDS_Edge& aE =(*(TopoDS_Edge *)(&aExp.Current()));
659 if (aME2.Contains(aE)) {
662 if (!BRep_Tool::Degenerated(aE)) {
664 aT=BOPTools_AlgoTools2D::IntermediatePoint(aE);
665 BOPTools_AlgoTools2D::PointOnSurface(aE, aF2, aT, aU, aV);
666 aP2D.SetCoord(aU, aV);
668 IntTools_FClass2d& aClsf=theContext->FClass2d(aF2);
669 aState=aClsf.Perform(aP2D);
670 bRet=(aState==TopAbs_IN);
677 //=======================================================================
678 //function : IsGrowthWire
680 //=======================================================================
681 Standard_Boolean IsGrowthWire(const TopoDS_Shape& theWire,
682 const BOPCol_IndexedMapOfShape& theMHE)
684 Standard_Boolean bRet;
688 if (theMHE.Extent()) {
689 aIt.Initialize(theWire);
690 for(; aIt.More(); aIt.Next()) {
691 const TopoDS_Shape& aE=aIt.Value();
692 if (theMHE.Contains(aE)) {
700 //BRepTools::Write(aFF, "ff");
704 // 12 - Null face generix