1 // Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // File: GEOMAlgo_BuilderFace.cxx
23 // Author: Peter KURNEV
25 #include <GEOMAlgo_BuilderFace.ixx>
27 #include <GEOMAlgo_Tools3D.hxx>
28 #include <GEOMAlgo_BuilderTools.hxx>
29 #include <GEOMAlgo_WireEdgeSet.hxx>
30 #include <GEOMAlgo_WESCorrector.hxx>
32 #include <NMTTools_ListOfCoupleOfShape.hxx>
33 #include <NMTTools_CoupleOfShape.hxx>
34 #include <NMTTools_ListIteratorOfListOfCoupleOfShape.hxx>
36 #include <Basics_OCCTVersion.hxx>
38 #include <gp_Pnt2d.hxx>
44 #include <Geom_Surface.hxx>
47 #include <TopLoc_Location.hxx>
49 #include <TopoDS_Iterator.hxx>
50 #include <TopoDS_Face.hxx>
52 #include <TopoDS_Shape.hxx>
53 #include <TopoDS_Wire.hxx>
54 #include <TopoDS_Edge.hxx>
55 #include <TopoDS_Vertex.hxx>
57 #include <BRep_Builder.hxx>
58 #include <BRep_Tool.hxx>
59 #include <BRepTools.hxx>
62 #include <TopExp_Explorer.hxx>
64 #include <TopTools_MapOfShape.hxx>
65 #include <TopTools_MapIteratorOfMapOfShape.hxx>
66 #include <TopTools_MapOfOrientedShape.hxx>
67 #include <TopTools_MapIteratorOfMapOfOrientedShape.hxx>
68 #include <TopTools_ListOfShape.hxx>
69 #include <TopTools_ListIteratorOfListOfShape.hxx>
70 #include <TopTools_DataMapOfShapeShape.hxx>
71 #include <TopTools_IndexedMapOfShape.hxx>
72 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
73 #include <TopTools_DataMapOfShapeListOfShape.hxx>
74 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
76 #include <IntTools_FClass2d.hxx>
77 #include <IntTools_Context.hxx>
79 #include <BOPTools_Tools2D.hxx>
80 #include <BOP_WireEdgeSet.hxx>
81 #include <BOP_WESCorrector.hxx>
85 Standard_Boolean IsGrowthWire(const TopoDS_Shape& ,
87 const TopTools_IndexedMapOfShape& );
90 Standard_Boolean IsInside(const TopoDS_Shape& ,
92 #if OCC_VERSION_LARGE > 0x06050200
93 const Handle(IntTools_Context)& );
99 void MakeInternalWires(const TopTools_MapOfShape& ,
100 TopTools_ListOfShape& );
102 //=======================================================================
105 //=======================================================================
106 GEOMAlgo_BuilderFace::GEOMAlgo_BuilderFace()
108 GEOMAlgo_BuilderArea()
111 //=======================================================================
114 //=======================================================================
115 GEOMAlgo_BuilderFace::~GEOMAlgo_BuilderFace()
118 //=======================================================================
121 //=======================================================================
122 void GEOMAlgo_BuilderFace::SetFace(const TopoDS_Face& theFace)
126 //=======================================================================
129 //=======================================================================
130 const TopoDS_Face& GEOMAlgo_BuilderFace::Face()const
134 //=======================================================================
137 //=======================================================================
138 void GEOMAlgo_BuilderFace::Perform()
142 #if OCC_VERSION_LARGE <= 0x06050200
143 if (myContext==NULL) {
144 myErrorStatus=11;// Null Context
149 if (myFace.IsNull()) {
150 myErrorStatus=12;// Null face generix
154 #if OCC_VERSION_LARGE > 0x06050200
155 // Initialize the context
156 GEOMAlgo_BuilderArea::Perform();
159 PerformShapesToAvoid();
174 PerformInternalShapes();
179 //=======================================================================
180 //function :PerformShapesToAvoid
182 //=======================================================================
183 void GEOMAlgo_BuilderFace::PerformShapesToAvoid()
185 Standard_Boolean bFound;
186 Standard_Integer i, iCnt, aNbV, aNbE;
187 TopTools_IndexedDataMapOfShapeListOfShape aMVE;
188 TopTools_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 TopExp::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 TopTools_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 GEOMAlgo_BuilderFace::PerformLoops()
263 Standard_Boolean bFlag;
264 Standard_Integer aNbEA;
265 TopTools_ListIteratorOfListOfShape aIt;
266 TopTools_MapIteratorOfMapOfOrientedShape aItM;
267 TopTools_IndexedDataMapOfShapeListOfShape aVEMap;
268 TopTools_MapOfOrientedShape aMAdded;
269 TopoDS_Iterator aItW;
271 GEOMAlgo_WireEdgeSet aWES;
272 GEOMAlgo_WESCorrector aWESCor;
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);
286 aWESCor.SetWES(aWES);
289 GEOMAlgo_WireEdgeSet& aWESN=aWESCor.NewWES();
290 const TopTools_ListOfShape& aLW=aWESN.Shapes();
292 aIt.Initialize (aLW);
293 for (; aIt.More(); aIt.Next()) {
294 const TopoDS_Shape& aW=aIt.Value();
297 //modified by NIZNHY-PKV Tue Aug 5 15:09:29 2008f
299 TopTools_MapOfOrientedShape aMEP;
301 // a. collect all edges that are in loops
302 aIt.Initialize (myLoops);
303 for (; aIt.More(); aIt.Next()) {
304 const TopoDS_Shape& aW=aIt.Value();
306 for (; aItW.More(); aItW.Next()) {
307 const TopoDS_Shape& aE=aItW.Value();
312 // b. collect all edges that are to avoid
313 aItM.Initialize(myShapesToAvoid);
314 for (; aItM.More(); aItM.Next()) {
315 const TopoDS_Shape& aE=aItM.Key();
319 // c. add all edges that are not processed to myShapesToAvoid
320 aIt.Initialize (myShapes);
321 for (; aIt.More(); aIt.Next()) {
322 const TopoDS_Shape& aE=aIt.Value();
323 if (!aMEP.Contains(aE)) {
324 myShapesToAvoid.Add(aE);
327 //modified by NIZNHY-PKV Tue Aug 5 15:09:35 2008t
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 TopExp::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 TopTools_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 GEOMAlgo_BuilderFace::PerformAreas()
383 Standard_Boolean bIsGrowth, bIsHole;
385 TopTools_ListOfShape aNewFaces, aHoleWires;
386 TopoDS_Shape anInfinitePointShape;
387 TopTools_DataMapOfShapeShape aInOutMap;
388 TopTools_DataMapOfShapeListOfShape aMSH;
389 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItMSH;
390 TopTools_ListIteratorOfListOfShape aIt1, aIt2;
391 TopTools_IndexedMapOfShape aMHE;
393 Handle(Geom_Surface) aS;
394 TopLoc_Location aLoc;
396 aTol=BRep_Tool::Tolerance(myFace);
397 aS=BRep_Tool::Surface(myFace, aLoc);
401 // Draft faces [aNewFaces]
402 aIt1.Initialize(myLoops);
403 for ( ; aIt1.More(); aIt1.Next()) {
404 const TopoDS_Shape& aWire=aIt1.Value();
406 bIsGrowth=IsGrowthWire(aWire, aMHE);
408 // make a growth face from a wire
410 aBB.MakeFace(aFace, aS, aLoc, aTol);
411 aBB.Add (aFace, aWire);
413 aNewFaces.Append (aFace);
416 // check if a wire is a hole
418 //bIsHole=IsHole(aWire, myFace, myContext);
419 bIsHole=GEOMAlgo_BuilderTools::IsHole(aWire, myFace);
422 aHoleWires.Append(aWire);
423 TopExp::MapShapes(aWire, TopAbs_EDGE, aMHE);
426 // make a growth face from a wire
428 aBB.MakeFace(aFace, aS, aLoc, aTol);
429 aBB.Add (aFace, aWire);
431 aNewFaces.Append (aFace);
436 // 2. Find outer growth shell that is most close to each hole shell
437 aIt2.Initialize(aHoleWires);
438 for (; aIt2.More(); aIt2.Next()) {
439 const TopoDS_Shape& aHole = aIt2.Value();
441 aIt1.Initialize(aNewFaces);
442 for ( ; aIt1.More(); aIt1.Next()) {
443 const TopoDS_Shape& aF=aIt1.Value();
445 if (!IsInside(aHole, aF, myContext)){
449 if ( aInOutMap.IsBound (aHole)){
450 const TopoDS_Shape& aF2=aInOutMap(aHole);
451 if (IsInside(aF, aF2, myContext)) {
452 aInOutMap.UnBind(aHole);
453 aInOutMap.Bind (aHole, aF);
457 aInOutMap.Bind (aHole, aF);
461 // Add aHole to a map Face/ListOfHoles [aMSH]
462 if (aInOutMap.IsBound(aHole)){
463 const TopoDS_Shape& aF=aInOutMap(aHole);
464 if (aMSH.IsBound(aF)) {
465 TopTools_ListOfShape& aLH=aMSH.ChangeFind(aF);
469 TopTools_ListOfShape aLH;
474 }// for (; aIt2.More(); aIt2.Next())
476 // 3. Add aHoles to Faces
477 aItMSH.Initialize(aMSH);
478 for (; aItMSH.More(); aItMSH.Next()) {
479 TopoDS_Face aF=TopoDS::Face(aItMSH.Key());
481 const TopTools_ListOfShape& aLH=aItMSH.Value();
482 aIt2.Initialize(aLH);
483 for (; aIt2.More(); aIt2.Next()) {
484 const TopoDS_Shape& aHole = aIt2.Value();
489 aTol=BRep_Tool::Tolerance(aF);
490 IntTools_FClass2d& aClsf=myContext->FClass2d(aF);
491 aClsf.Init(aF, aTol);
494 // These aNewFaces are draft faces that
495 // do not contain any internal shapes
497 myAreas.Append(aNewFaces);
499 //=======================================================================
500 //function : PerformInternalShapes
502 //=======================================================================
503 void GEOMAlgo_BuilderFace::PerformInternalShapes()
507 Standard_Integer aNbWI=myLoopsInternal.Extent();
508 if (!aNbWI) {// nothing to do
512 //Standard_Real aTol;
514 TopTools_ListIteratorOfListOfShape aIt1, aIt2;
516 TopTools_MapOfShape aME, aMEP;
517 TopTools_MapIteratorOfMapOfShape aItME;
518 TopTools_IndexedDataMapOfShapeListOfShape aMVE;
519 TopTools_ListOfShape aLSI;
521 // 1. All internal edges
522 aIt1.Initialize(myLoopsInternal);
523 for (; aIt1.More(); aIt1.Next()) {
524 const TopoDS_Shape& aWire=aIt1.Value();
525 aIt.Initialize(aWire);
526 for (; aIt.More(); aIt.Next()) {
527 const TopoDS_Shape& aE=aIt.Value();
534 aIt2.Initialize(myAreas);
535 for ( ; aIt2.More(); aIt2.Next()) {
536 TopoDS_Face& aF=TopoDS::Face(aIt2.Value());
539 TopExp::MapShapesAndAncestors(aF, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
541 // 2.1 Separate faces to process aMEP
543 aItME.Initialize(aME);
544 for (; aItME.More(); aItME.Next()) {
545 const TopoDS_Edge& aE=TopoDS::Edge(aItME.Key());
546 if (IsInside(aE, aF, myContext)) {
551 // 2.2 Make Internal Wires
553 MakeInternalWires(aMEP, aLSI);
555 // 2.3 Add them to aF
556 aIt1.Initialize(aLSI);
557 for (; aIt1.More(); aIt1.Next()) {
558 const TopoDS_Shape& aSI=aIt1.Value();
562 // 2.4 Remove faces aMFP from aMF
563 aItME.Initialize(aMEP);
564 for (; aItME.More(); aItME.Next()) {
565 const TopoDS_Shape& aE=aItME.Key();
573 } //for ( ; aIt2.More(); aIt2.Next()) {
575 //=======================================================================
576 //function : MakeInternalWires
578 //=======================================================================
579 void MakeInternalWires(const TopTools_MapOfShape& theME,
580 TopTools_ListOfShape& theWires)
582 TopTools_MapIteratorOfMapOfShape aItM;
583 TopTools_MapOfShape aAddedMap;
584 TopTools_ListIteratorOfListOfShape aItE;
585 TopTools_IndexedDataMapOfShapeListOfShape aMVE;
588 aItM.Initialize(theME);
589 for (; aItM.More(); aItM.Next()) {
590 const TopoDS_Shape& aE=aItM.Key();
591 TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
594 aItM.Initialize(theME);
595 for (; aItM.More(); aItM.Next()) {
596 TopoDS_Shape aEE=aItM.Key();
597 if (!aAddedMap.Add(aEE)) {
604 aEE.Orientation(TopAbs_INTERNAL);
607 TopoDS_Iterator aItAdded (aW);
608 for (; aItAdded.More(); aItAdded.Next()) {
609 const TopoDS_Shape& aE =aItAdded.Value();
611 TopExp_Explorer aExp(aE, TopAbs_VERTEX);
612 for (; aExp.More(); aExp.Next()) {
613 const TopoDS_Shape& aV =aExp.Current();
614 const TopTools_ListOfShape& aLE=aMVE.FindFromKey(aV);
615 aItE.Initialize(aLE);
616 for (; aItE.More(); aItE.Next()) {
617 TopoDS_Shape aEL=aItE.Value();
618 if (aAddedMap.Add(aEL)){
619 aEL.Orientation(TopAbs_INTERNAL);
628 //=======================================================================
629 //function : IsInside
631 //=======================================================================
632 Standard_Boolean IsInside(const TopoDS_Shape& theHole,
633 const TopoDS_Shape& theF2,
634 #if OCC_VERSION_LARGE > 0x06050200
635 const Handle(IntTools_Context)& theContext)
637 IntTools_PContext& theContext)
640 Standard_Boolean bRet;
641 Standard_Real aT, aU, aV;
644 TopExp_Explorer aExp;
645 TopTools_IndexedMapOfShape aME2;
649 aState=TopAbs_UNKNOWN;
650 const TopoDS_Face& aF2=TopoDS::Face(theF2);
652 TopExp::MapShapes(aF2, TopAbs_EDGE, aME2);
654 aExp.Init(theHole, TopAbs_EDGE);
656 const TopoDS_Edge& aE = TopoDS::Edge(aExp.Current());
657 if (aME2.Contains(aE)) {
661 aT=BOPTools_Tools2D::IntermediatePoint(aE);
662 BOPTools_Tools2D::PointOnSurface(aE, aF2, aT, aU, aV);
663 aP2D.SetCoord(aU, aV);
665 IntTools_FClass2d& aClsf=theContext->FClass2d(aF2);
666 aState=aClsf.Perform(aP2D);
667 bRet=(aState==TopAbs_IN);
673 //=======================================================================
674 //function : IsGrowthWire
676 //=======================================================================
677 Standard_Boolean IsGrowthWire(const TopoDS_Shape& theWire,
678 const TopTools_IndexedMapOfShape& theMHE)
680 Standard_Boolean bRet;
684 if (theMHE.Extent()) {
685 aIt.Initialize(theWire);
686 for(; aIt.More(); aIt.Next()) {
687 const TopoDS_Shape& aE=aIt.Value();
688 if (theMHE.Contains(aE)) {
696 //BRepTools::Write(aFF, "ff");
700 // 12 - Null face generix
703 //=======================================================================
704 //function : IsInside
706 //=======================================================================
707 Standard_Boolean IsInside(const TopoDS_Shape& theHole,
708 const TopoDS_Shape& theF2,
709 IntTools_PContext& theContext)
711 Standard_Real aT, aU, aV;
712 TopExp_Explorer aExp;
713 TopAbs_State aState=TopAbs_UNKNOWN;
716 const TopoDS_Face& aF2=TopoDS::Face(theF2);
718 aExp.Init(theHole, TopAbs_EDGE);
720 const TopoDS_Edge& aE = TopoDS::Edge(aExp.Current());
721 aT=BOPTools_Tools2D::IntermediatePoint(aE);
722 BOPTools_Tools2D::PointOnSurface(aE, aF2, aT, aU, aV);
723 aP2D.SetCoord(aU, aV);
725 IntTools_FClass2d& aClsf=theContext->FClass2d(aF2);
726 aState=aClsf.Perform(aP2D);
728 return (aState==TopAbs_IN);