1 // Copyright (C) 2007-2012 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
23 // File: GEOMAlgo_BuilderFace.cxx
25 // Author: Peter KURNEV
27 #include <GEOMAlgo_BuilderFace.hxx>
29 #include <gp_Pnt2d.hxx>
35 #include <Geom_Surface.hxx>
38 #include <TopLoc_Location.hxx>
40 #include <TopoDS_Iterator.hxx>
41 #include <TopoDS_Face.hxx>
43 #include <TopoDS_Shape.hxx>
44 #include <TopoDS_Wire.hxx>
45 #include <TopoDS_Edge.hxx>
46 #include <TopoDS_Vertex.hxx>
48 #include <BRep_Builder.hxx>
49 #include <BRep_Tool.hxx>
50 #include <BRepTools.hxx>
53 #include <TopExp_Explorer.hxx>
55 #include <TopTools_MapOfShape.hxx>
56 #include <TopTools_MapIteratorOfMapOfShape.hxx>
57 #include <TopTools_MapOfOrientedShape.hxx>
58 #include <TopTools_MapIteratorOfMapOfOrientedShape.hxx>
59 #include <TopTools_ListOfShape.hxx>
60 #include <TopTools_ListIteratorOfListOfShape.hxx>
61 #include <TopTools_DataMapOfShapeShape.hxx>
62 #include <TopTools_IndexedMapOfShape.hxx>
63 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
64 #include <TopTools_DataMapOfShapeListOfShape.hxx>
65 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
67 #include <IntTools_FClass2d.hxx>
68 #include <IntTools_Context.hxx>
70 #include <BOPTools_Tools2D.hxx>
71 #include <BOP_WireEdgeSet.hxx>
72 #include <BOP_WESCorrector.hxx>
74 #include <NMTTools_ListOfCoupleOfShape.hxx>
75 #include <NMTTools_CoupleOfShape.hxx>
76 #include <NMTTools_ListIteratorOfListOfCoupleOfShape.hxx>
78 #include <GEOMAlgo_Tools3D.hxx>
79 #include <GEOMAlgo_BuilderTools.hxx>
80 #include <GEOMAlgo_WireEdgeSet.hxx>
81 #include <GEOMAlgo_WESCorrector.hxx>
85 Standard_Boolean IsGrowthWire(const TopoDS_Shape& ,
87 const TopTools_IndexedMapOfShape& );
90 Standard_Boolean IsInside(const TopoDS_Shape& ,
92 const Handle(IntTools_Context)& );
94 void MakeInternalWires(const TopTools_MapOfShape& ,
95 TopTools_ListOfShape& );
97 //=======================================================================
100 //=======================================================================
101 GEOMAlgo_BuilderFace::GEOMAlgo_BuilderFace()
103 GEOMAlgo_BuilderArea()
106 //=======================================================================
109 //=======================================================================
110 GEOMAlgo_BuilderFace::~GEOMAlgo_BuilderFace()
113 //=======================================================================
116 //=======================================================================
117 void GEOMAlgo_BuilderFace::SetFace(const TopoDS_Face& theFace)
121 //=======================================================================
124 //=======================================================================
125 const TopoDS_Face& GEOMAlgo_BuilderFace::Face()const
129 //=======================================================================
132 //=======================================================================
133 void GEOMAlgo_BuilderFace::Perform()
137 if (myFace.IsNull()) {
138 myErrorStatus=12;// Null face generix
141 // Initialize the context
142 GEOMAlgo_BuilderArea::Perform();
144 PerformShapesToAvoid();
159 PerformInternalShapes();
164 //=======================================================================
165 //function :PerformShapesToAvoid
167 //=======================================================================
168 void GEOMAlgo_BuilderFace::PerformShapesToAvoid()
170 Standard_Boolean bFound;
171 Standard_Integer i, iCnt, aNbV, aNbE;
172 TopTools_IndexedDataMapOfShapeListOfShape aMVE;
173 TopTools_ListIteratorOfListOfShape aIt;
175 myShapesToAvoid.Clear();
180 bFound=Standard_False;
184 aIt.Initialize (myShapes);
185 for (; aIt.More(); aIt.Next()) {
186 const TopoDS_Shape& aE=aIt.Value();
187 if (!myShapesToAvoid.Contains(aE)) {
188 TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
197 for (i=1; i<=aNbV; ++i) {
198 const TopoDS_Vertex& aV=TopoDS::Vertex(aMVE.FindKey(i));
200 TopTools_ListOfShape& aLE=aMVE.ChangeFromKey(aV);
206 const TopoDS_Edge& aE1=TopoDS::Edge(aLE.First());
208 if (BRep_Tool::Degenerated(aE1)) {
211 if (aV.Orientation()==TopAbs_INTERNAL) {
214 bFound=Standard_True;
215 myShapesToAvoid.Add(aE1);
218 const TopoDS_Edge& aE2=TopoDS::Edge(aLE.Last());
219 if (aE2.IsSame(aE1)) {
220 TopoDS_Vertex aV1x, aV2x;
222 TopExp::Vertices(aE1, aV1x, aV2x);
223 if (aV1x.IsSame(aV2x)) {
226 bFound=Standard_True;
227 myShapesToAvoid.Add(aE1);
228 myShapesToAvoid.Add(aE2);
231 }// for (i=1; i<=aNbE; ++i) {
238 //printf(" EdgesToAvoid=%d, iCnt=%d\n", EdgesToAvoid.Extent(), iCnt);
240 //=======================================================================
241 //function : PerformLoops
243 //=======================================================================
244 void GEOMAlgo_BuilderFace::PerformLoops()
248 Standard_Boolean bFlag;
249 Standard_Integer aNbEA;
250 TopTools_ListIteratorOfListOfShape aIt;
251 TopTools_MapIteratorOfMapOfOrientedShape aItM;
252 TopTools_IndexedDataMapOfShapeListOfShape aVEMap;
253 TopTools_MapOfOrientedShape aMAdded;
254 TopoDS_Iterator aItW;
256 GEOMAlgo_WireEdgeSet aWES;
257 GEOMAlgo_WESCorrector aWESCor;
261 aWES.SetFace(myFace);
263 aIt.Initialize (myShapes);
264 for (; aIt.More(); aIt.Next()) {
265 const TopoDS_Shape& aE=aIt.Value();
266 if (!myShapesToAvoid.Contains(aE)) {
267 aWES.AddStartElement(aE);
271 aWESCor.SetWES(aWES);
274 GEOMAlgo_WireEdgeSet& aWESN=aWESCor.NewWES();
275 const TopTools_ListOfShape& aLW=aWESN.Shapes();
277 aIt.Initialize (aLW);
278 for (; aIt.More(); aIt.Next()) {
279 const TopoDS_Shape& aW=aIt.Value();
282 //modified by NIZNHY-PKV Tue Aug 5 15:09:29 2008f
284 TopTools_MapOfOrientedShape aMEP;
286 // a. collect all edges that are in loops
287 aIt.Initialize (myLoops);
288 for (; aIt.More(); aIt.Next()) {
289 const TopoDS_Shape& aW=aIt.Value();
291 for (; aItW.More(); aItW.Next()) {
292 const TopoDS_Shape& aE=aItW.Value();
297 // b. collect all edges that are to avoid
298 aItM.Initialize(myShapesToAvoid);
299 for (; aItM.More(); aItM.Next()) {
300 const TopoDS_Shape& aE=aItM.Key();
304 // c. add all edges that are not processed to myShapesToAvoid
305 aIt.Initialize (myShapes);
306 for (; aIt.More(); aIt.Next()) {
307 const TopoDS_Shape& aE=aIt.Value();
308 if (!aMEP.Contains(aE)) {
309 myShapesToAvoid.Add(aE);
312 //modified by NIZNHY-PKV Tue Aug 5 15:09:35 2008t
315 myLoopsInternal.Clear();
317 aNbEA=myShapesToAvoid.Extent();
318 aItM.Initialize(myShapesToAvoid);
319 for (; aItM.More(); aItM.Next()) {
320 const TopoDS_Shape& aEE=aItM.Key();
321 TopExp::MapShapesAndAncestors(aEE, TopAbs_VERTEX, TopAbs_EDGE, aVEMap);
325 aItM.Initialize(myShapesToAvoid);
326 for (; aItM.More()&&bFlag; aItM.Next()) {
327 const TopoDS_Shape& aEE=aItM.Key();
328 if (!aMAdded.Add(aEE)) {
338 for (; aItW.More()&&bFlag; aItW.Next()) {
339 const TopoDS_Edge& aE=TopoDS::Edge(aItW.Value());
341 TopoDS_Iterator aItE(aE);
342 for (; aItE.More()&&bFlag; aItE.Next()) {
343 const TopoDS_Vertex& aV = TopoDS::Vertex(aItE.Value());
344 const TopTools_ListOfShape& aLE=aVEMap.FindFromKey(aV);
346 for (; aIt.More()&&bFlag; aIt.Next()) {
347 const TopoDS_Shape& aEx=aIt.Value();
348 if (aMAdded.Add(aEx)) {
350 if(aMAdded.Extent()==aNbEA) {
354 }//for (; aIt.More(); aIt.Next()) {
355 }//for (; aItE.More(); aItE.Next()) {
356 }//for (; aItW.More(); aItW.Next()) {
357 myLoopsInternal.Append(aW);
358 }//for (; aItM.More(); aItM.Next()) {
360 //=======================================================================
361 //function : PerformAreas
363 //=======================================================================
364 void GEOMAlgo_BuilderFace::PerformAreas()
368 Standard_Boolean bIsGrowth, bIsHole;
370 TopTools_ListOfShape aNewFaces, aHoleWires;
371 TopoDS_Shape anInfinitePointShape;
372 TopTools_DataMapOfShapeShape aInOutMap;
373 TopTools_DataMapOfShapeListOfShape aMSH;
374 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItMSH;
375 TopTools_ListIteratorOfListOfShape aIt1, aIt2;
376 TopTools_IndexedMapOfShape aMHE;
378 Handle(Geom_Surface) aS;
379 TopLoc_Location aLoc;
381 aTol=BRep_Tool::Tolerance(myFace);
382 aS=BRep_Tool::Surface(myFace, aLoc);
386 // Draft faces [aNewFaces]
387 aIt1.Initialize(myLoops);
388 for ( ; aIt1.More(); aIt1.Next()) {
389 const TopoDS_Shape& aWire=aIt1.Value();
391 bIsGrowth=IsGrowthWire(aWire, aMHE);
393 // make a growth face from a wire
395 aBB.MakeFace(aFace, aS, aLoc, aTol);
396 aBB.Add (aFace, aWire);
398 aNewFaces.Append (aFace);
401 // check if a wire is a hole
403 //bIsHole=IsHole(aWire, myFace, myContext);
404 bIsHole=GEOMAlgo_BuilderTools::IsHole(aWire, myFace);
407 aHoleWires.Append(aWire);
408 TopExp::MapShapes(aWire, TopAbs_EDGE, aMHE);
411 // make a growth face from a wire
413 aBB.MakeFace(aFace, aS, aLoc, aTol);
414 aBB.Add (aFace, aWire);
416 aNewFaces.Append (aFace);
421 // 2. Find outer growth shell that is most close to each hole shell
422 aIt2.Initialize(aHoleWires);
423 for (; aIt2.More(); aIt2.Next()) {
424 const TopoDS_Shape& aHole = aIt2.Value();
426 aIt1.Initialize(aNewFaces);
427 for ( ; aIt1.More(); aIt1.Next()) {
428 const TopoDS_Shape& aF=aIt1.Value();
430 if (!IsInside(aHole, aF, myContext)){
434 if ( aInOutMap.IsBound (aHole)){
435 const TopoDS_Shape& aF2=aInOutMap(aHole);
436 if (IsInside(aF, aF2, myContext)) {
437 aInOutMap.UnBind(aHole);
438 aInOutMap.Bind (aHole, aF);
442 aInOutMap.Bind (aHole, aF);
446 // Add aHole to a map Face/ListOfHoles [aMSH]
447 if (aInOutMap.IsBound(aHole)){
448 const TopoDS_Shape& aF=aInOutMap(aHole);
449 if (aMSH.IsBound(aF)) {
450 TopTools_ListOfShape& aLH=aMSH.ChangeFind(aF);
454 TopTools_ListOfShape aLH;
459 }// for (; aIt2.More(); aIt2.Next())
461 // 3. Add aHoles to Faces
462 aItMSH.Initialize(aMSH);
463 for (; aItMSH.More(); aItMSH.Next()) {
464 TopoDS_Face aF=TopoDS::Face(aItMSH.Key());
466 const TopTools_ListOfShape& aLH=aItMSH.Value();
467 aIt2.Initialize(aLH);
468 for (; aIt2.More(); aIt2.Next()) {
469 const TopoDS_Shape& aHole = aIt2.Value();
474 aTol=BRep_Tool::Tolerance(aF);
475 IntTools_FClass2d& aClsf=myContext->FClass2d(aF);
476 aClsf.Init(aF, aTol);
479 // These aNewFaces are draft faces that
480 // do not contain any internal shapes
482 myAreas.Append(aNewFaces);
484 //=======================================================================
485 //function : PerformInternalShapes
487 //=======================================================================
488 void GEOMAlgo_BuilderFace::PerformInternalShapes()
492 Standard_Integer aNbWI=myLoopsInternal.Extent();
493 if (!aNbWI) {// nothing to do
497 //Standard_Real aTol;
499 TopTools_ListIteratorOfListOfShape aIt1, aIt2;
501 TopTools_MapOfShape aME, aMEP;
502 TopTools_MapIteratorOfMapOfShape aItME;
503 TopTools_IndexedDataMapOfShapeListOfShape aMVE;
504 TopTools_ListOfShape aLSI;
506 // 1. All internal edges
507 aIt1.Initialize(myLoopsInternal);
508 for (; aIt1.More(); aIt1.Next()) {
509 const TopoDS_Shape& aWire=aIt1.Value();
510 aIt.Initialize(aWire);
511 for (; aIt.More(); aIt.Next()) {
512 const TopoDS_Shape& aE=aIt.Value();
519 aIt2.Initialize(myAreas);
520 for ( ; aIt2.More(); aIt2.Next()) {
521 TopoDS_Face& aF=TopoDS::Face(aIt2.Value());
524 TopExp::MapShapesAndAncestors(aF, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
526 // 2.1 Separate faces to process aMEP
528 aItME.Initialize(aME);
529 for (; aItME.More(); aItME.Next()) {
530 const TopoDS_Edge& aE=TopoDS::Edge(aItME.Key());
531 if (IsInside(aE, aF, myContext)) {
536 // 2.2 Make Internal Wires
538 MakeInternalWires(aMEP, aLSI);
540 // 2.3 Add them to aF
541 aIt1.Initialize(aLSI);
542 for (; aIt1.More(); aIt1.Next()) {
543 const TopoDS_Shape& aSI=aIt1.Value();
547 // 2.4 Remove faces aMFP from aMF
548 aItME.Initialize(aMEP);
549 for (; aItME.More(); aItME.Next()) {
550 const TopoDS_Shape& aE=aItME.Key();
558 } //for ( ; aIt2.More(); aIt2.Next()) {
560 //=======================================================================
561 //function : MakeInternalWires
563 //=======================================================================
564 void MakeInternalWires(const TopTools_MapOfShape& theME,
565 TopTools_ListOfShape& theWires)
567 TopTools_MapIteratorOfMapOfShape aItM;
568 TopTools_MapOfShape aAddedMap;
569 TopTools_ListIteratorOfListOfShape aItE;
570 TopTools_IndexedDataMapOfShapeListOfShape aMVE;
573 aItM.Initialize(theME);
574 for (; aItM.More(); aItM.Next()) {
575 const TopoDS_Shape& aE=aItM.Key();
576 TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
579 aItM.Initialize(theME);
580 for (; aItM.More(); aItM.Next()) {
581 TopoDS_Shape aEE=aItM.Key();
582 if (!aAddedMap.Add(aEE)) {
589 aEE.Orientation(TopAbs_INTERNAL);
592 TopoDS_Iterator aItAdded (aW);
593 for (; aItAdded.More(); aItAdded.Next()) {
594 const TopoDS_Shape& aE =aItAdded.Value();
596 TopExp_Explorer aExp(aE, TopAbs_VERTEX);
597 for (; aExp.More(); aExp.Next()) {
598 const TopoDS_Shape& aV =aExp.Current();
599 const TopTools_ListOfShape& aLE=aMVE.FindFromKey(aV);
600 aItE.Initialize(aLE);
601 for (; aItE.More(); aItE.Next()) {
602 TopoDS_Shape aEL=aItE.Value();
603 if (aAddedMap.Add(aEL)){
604 aEL.Orientation(TopAbs_INTERNAL);
613 //=======================================================================
614 //function : IsInside
616 //=======================================================================
617 Standard_Boolean IsInside(const TopoDS_Shape& theHole,
618 const TopoDS_Shape& theF2,
619 const Handle(IntTools_Context)& theContext)
621 Standard_Boolean bRet;
622 Standard_Real aT, aU, aV;
625 TopExp_Explorer aExp;
626 TopTools_IndexedMapOfShape aME2;
630 aState=TopAbs_UNKNOWN;
631 const TopoDS_Face& aF2=TopoDS::Face(theF2);
633 TopExp::MapShapes(aF2, TopAbs_EDGE, aME2);
635 aExp.Init(theHole, TopAbs_EDGE);
637 const TopoDS_Edge& aE = TopoDS::Edge(aExp.Current());
638 if (aME2.Contains(aE)) {
642 aT=BOPTools_Tools2D::IntermediatePoint(aE);
643 BOPTools_Tools2D::PointOnSurface(aE, aF2, aT, aU, aV);
644 aP2D.SetCoord(aU, aV);
646 IntTools_FClass2d& aClsf=theContext->FClass2d(aF2);
647 aState=aClsf.Perform(aP2D);
648 bRet=(aState==TopAbs_IN);
654 //=======================================================================
655 //function : IsGrowthWire
657 //=======================================================================
658 Standard_Boolean IsGrowthWire(const TopoDS_Shape& theWire,
659 const TopTools_IndexedMapOfShape& theMHE)
661 Standard_Boolean bRet;
665 if (theMHE.Extent()) {
666 aIt.Initialize(theWire);
667 for(; aIt.More(); aIt.Next()) {
668 const TopoDS_Shape& aE=aIt.Value();
669 if (theMHE.Contains(aE)) {
677 //BRepTools::Write(aFF, "ff");
681 // 12 - Null face generix
684 //=======================================================================
685 //function : IsInside
687 //=======================================================================
688 Standard_Boolean IsInside(const TopoDS_Shape& theHole,
689 const TopoDS_Shape& theF2,
690 IntTools_PContext& theContext)
692 Standard_Real aT, aU, aV;
693 TopExp_Explorer aExp;
694 TopAbs_State aState=TopAbs_UNKNOWN;
697 const TopoDS_Face& aF2=TopoDS::Face(theF2);
699 aExp.Init(theHole, TopAbs_EDGE);
701 const TopoDS_Edge& aE = TopoDS::Edge(aExp.Current());
702 aT=BOPTools_Tools2D::IntermediatePoint(aE);
703 BOPTools_Tools2D::PointOnSurface(aE, aF2, aT, aU, aV);
704 aP2D.SetCoord(aU, aV);
706 IntTools_FClass2d& aClsf=theContext->FClass2d(aF2);
707 aState=aClsf.Perform(aP2D);
709 return (aState==TopAbs_IN);