1 // Copyright (C) 2007-2010 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.ixx>
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& ,
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 (myContext==NULL) {
138 myErrorStatus=11;// Null Context
142 if (myFace.IsNull()) {
143 myErrorStatus=12;// Null face generix
147 PerformShapesToAvoid();
162 PerformInternalShapes();
167 //=======================================================================
168 //function :PerformShapesToAvoid
170 //=======================================================================
171 void GEOMAlgo_BuilderFace::PerformShapesToAvoid()
173 Standard_Boolean bFound;
174 Standard_Integer i, iCnt, aNbV, aNbE;
175 TopTools_IndexedDataMapOfShapeListOfShape aMVE;
176 TopTools_ListIteratorOfListOfShape aIt;
178 myShapesToAvoid.Clear();
183 bFound=Standard_False;
187 aIt.Initialize (myShapes);
188 for (; aIt.More(); aIt.Next()) {
189 const TopoDS_Shape& aE=aIt.Value();
190 if (!myShapesToAvoid.Contains(aE)) {
191 TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
200 for (i=1; i<=aNbV; ++i) {
201 const TopoDS_Vertex& aV=TopoDS::Vertex(aMVE.FindKey(i));
203 TopTools_ListOfShape& aLE=aMVE.ChangeFromKey(aV);
209 const TopoDS_Edge& aE1=TopoDS::Edge(aLE.First());
211 if (BRep_Tool::Degenerated(aE1)) {
214 if (aV.Orientation()==TopAbs_INTERNAL) {
217 bFound=Standard_True;
218 myShapesToAvoid.Add(aE1);
221 const TopoDS_Edge& aE2=TopoDS::Edge(aLE.Last());
222 if (aE2.IsSame(aE1)) {
223 TopoDS_Vertex aV1x, aV2x;
225 TopExp::Vertices(aE1, aV1x, aV2x);
226 if (aV1x.IsSame(aV2x)) {
229 bFound=Standard_True;
230 myShapesToAvoid.Add(aE1);
231 myShapesToAvoid.Add(aE2);
234 }// for (i=1; i<=aNbE; ++i) {
241 //printf(" EdgesToAvoid=%d, iCnt=%d\n", EdgesToAvoid.Extent(), iCnt);
243 //=======================================================================
244 //function : PerformLoops
246 //=======================================================================
247 void GEOMAlgo_BuilderFace::PerformLoops()
251 Standard_Boolean bFlag;
252 Standard_Integer aNbEA;
253 TopTools_ListIteratorOfListOfShape aIt;
254 TopTools_MapIteratorOfMapOfOrientedShape aItM;
255 TopTools_IndexedDataMapOfShapeListOfShape aVEMap;
256 TopTools_MapOfOrientedShape aMAdded;
257 TopoDS_Iterator aItW;
259 GEOMAlgo_WireEdgeSet aWES;
260 GEOMAlgo_WESCorrector aWESCor;
264 aWES.SetFace(myFace);
266 aIt.Initialize (myShapes);
267 for (; aIt.More(); aIt.Next()) {
268 const TopoDS_Shape& aE=aIt.Value();
269 if (!myShapesToAvoid.Contains(aE)) {
270 aWES.AddStartElement(aE);
274 aWESCor.SetWES(aWES);
277 GEOMAlgo_WireEdgeSet& aWESN=aWESCor.NewWES();
278 const TopTools_ListOfShape& aLW=aWESN.Shapes();
280 aIt.Initialize (aLW);
281 for (; aIt.More(); aIt.Next()) {
282 const TopoDS_Shape& aW=aIt.Value();
285 //modified by NIZNHY-PKV Tue Aug 5 15:09:29 2008f
287 TopTools_MapOfOrientedShape aMEP;
289 // a. collect all edges that are in loops
290 aIt.Initialize (myLoops);
291 for (; aIt.More(); aIt.Next()) {
292 const TopoDS_Shape& aW=aIt.Value();
294 for (; aItW.More(); aItW.Next()) {
295 const TopoDS_Shape& aE=aItW.Value();
300 // b. collect all edges that are to avoid
301 aItM.Initialize(myShapesToAvoid);
302 for (; aItM.More(); aItM.Next()) {
303 const TopoDS_Shape& aE=aItM.Key();
307 // c. add all edges that are not processed to myShapesToAvoid
308 aIt.Initialize (myShapes);
309 for (; aIt.More(); aIt.Next()) {
310 const TopoDS_Shape& aE=aIt.Value();
311 if (!aMEP.Contains(aE)) {
312 myShapesToAvoid.Add(aE);
315 //modified by NIZNHY-PKV Tue Aug 5 15:09:35 2008t
318 myLoopsInternal.Clear();
320 aNbEA=myShapesToAvoid.Extent();
321 aItM.Initialize(myShapesToAvoid);
322 for (; aItM.More(); aItM.Next()) {
323 const TopoDS_Shape& aEE=aItM.Key();
324 TopExp::MapShapesAndAncestors(aEE, TopAbs_VERTEX, TopAbs_EDGE, aVEMap);
328 aItM.Initialize(myShapesToAvoid);
329 for (; aItM.More()&&bFlag; aItM.Next()) {
330 const TopoDS_Shape& aEE=aItM.Key();
331 if (!aMAdded.Add(aEE)) {
341 for (; aItW.More()&&bFlag; aItW.Next()) {
342 const TopoDS_Edge& aE=TopoDS::Edge(aItW.Value());
344 TopoDS_Iterator aItE(aE);
345 for (; aItE.More()&&bFlag; aItE.Next()) {
346 const TopoDS_Vertex& aV = TopoDS::Vertex(aItE.Value());
347 const TopTools_ListOfShape& aLE=aVEMap.FindFromKey(aV);
349 for (; aIt.More()&&bFlag; aIt.Next()) {
350 const TopoDS_Shape& aEx=aIt.Value();
351 if (aMAdded.Add(aEx)) {
353 if(aMAdded.Extent()==aNbEA) {
357 }//for (; aIt.More(); aIt.Next()) {
358 }//for (; aItE.More(); aItE.Next()) {
359 }//for (; aItW.More(); aItW.Next()) {
360 myLoopsInternal.Append(aW);
361 }//for (; aItM.More(); aItM.Next()) {
363 //=======================================================================
364 //function : PerformAreas
366 //=======================================================================
367 void GEOMAlgo_BuilderFace::PerformAreas()
371 Standard_Boolean bIsGrowth, bIsHole;
373 TopTools_ListOfShape aNewFaces, aHoleWires;
374 TopoDS_Shape anInfinitePointShape;
375 TopTools_DataMapOfShapeShape aInOutMap;
376 TopTools_DataMapOfShapeListOfShape aMSH;
377 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItMSH;
378 TopTools_ListIteratorOfListOfShape aIt1, aIt2;
379 TopTools_IndexedMapOfShape aMHE;
381 Handle(Geom_Surface) aS;
382 TopLoc_Location aLoc;
384 aTol=BRep_Tool::Tolerance(myFace);
385 aS=BRep_Tool::Surface(myFace, aLoc);
389 // Draft faces [aNewFaces]
390 aIt1.Initialize(myLoops);
391 for ( ; aIt1.More(); aIt1.Next()) {
392 const TopoDS_Shape& aWire=aIt1.Value();
394 bIsGrowth=IsGrowthWire(aWire, aMHE);
396 // make a growth face from a wire
398 aBB.MakeFace(aFace, aS, aLoc, aTol);
399 aBB.Add (aFace, aWire);
401 aNewFaces.Append (aFace);
404 // check if a wire is a hole
406 //bIsHole=IsHole(aWire, myFace, myContext);
407 bIsHole=GEOMAlgo_BuilderTools::IsHole(aWire, myFace);
410 aHoleWires.Append(aWire);
411 TopExp::MapShapes(aWire, TopAbs_EDGE, aMHE);
414 // make a growth face from a wire
416 aBB.MakeFace(aFace, aS, aLoc, aTol);
417 aBB.Add (aFace, aWire);
419 aNewFaces.Append (aFace);
424 // 2. Find outer growth shell that is most close to each hole shell
425 aIt2.Initialize(aHoleWires);
426 for (; aIt2.More(); aIt2.Next()) {
427 const TopoDS_Shape& aHole = aIt2.Value();
429 aIt1.Initialize(aNewFaces);
430 for ( ; aIt1.More(); aIt1.Next()) {
431 const TopoDS_Shape& aF=aIt1.Value();
433 if (!IsInside(aHole, aF, myContext)){
437 if ( aInOutMap.IsBound (aHole)){
438 const TopoDS_Shape& aF2=aInOutMap(aHole);
439 if (IsInside(aF, aF2, myContext)) {
440 aInOutMap.UnBind(aHole);
441 aInOutMap.Bind (aHole, aF);
445 aInOutMap.Bind (aHole, aF);
449 // Add aHole to a map Face/ListOfHoles [aMSH]
450 if (aInOutMap.IsBound(aHole)){
451 const TopoDS_Shape& aF=aInOutMap(aHole);
452 if (aMSH.IsBound(aF)) {
453 TopTools_ListOfShape& aLH=aMSH.ChangeFind(aF);
457 TopTools_ListOfShape aLH;
462 }// for (; aIt2.More(); aIt2.Next())
464 // 3. Add aHoles to Faces
465 aItMSH.Initialize(aMSH);
466 for (; aItMSH.More(); aItMSH.Next()) {
467 TopoDS_Face aF=TopoDS::Face(aItMSH.Key());
469 const TopTools_ListOfShape& aLH=aItMSH.Value();
470 aIt2.Initialize(aLH);
471 for (; aIt2.More(); aIt2.Next()) {
472 const TopoDS_Shape& aHole = aIt2.Value();
477 aTol=BRep_Tool::Tolerance(aF);
478 IntTools_FClass2d& aClsf=myContext->FClass2d(aF);
479 aClsf.Init(aF, aTol);
482 // These aNewFaces are draft faces that
483 // do not contain any internal shapes
485 myAreas.Append(aNewFaces);
487 //=======================================================================
488 //function : PerformInternalShapes
490 //=======================================================================
491 void GEOMAlgo_BuilderFace::PerformInternalShapes()
495 Standard_Integer aNbWI=myLoopsInternal.Extent();
496 if (!aNbWI) {// nothing to do
500 //Standard_Real aTol;
502 TopTools_ListIteratorOfListOfShape aIt1, aIt2;
504 TopTools_MapOfShape aME, aMEP;
505 TopTools_MapIteratorOfMapOfShape aItME;
506 TopTools_IndexedDataMapOfShapeListOfShape aMVE;
507 TopTools_ListOfShape aLSI;
509 // 1. All internal edges
510 aIt1.Initialize(myLoopsInternal);
511 for (; aIt1.More(); aIt1.Next()) {
512 const TopoDS_Shape& aWire=aIt1.Value();
513 aIt.Initialize(aWire);
514 for (; aIt.More(); aIt.Next()) {
515 const TopoDS_Shape& aE=aIt.Value();
522 aIt2.Initialize(myAreas);
523 for ( ; aIt2.More(); aIt2.Next()) {
524 TopoDS_Face& aF=TopoDS::Face(aIt2.Value());
527 TopExp::MapShapesAndAncestors(aF, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
529 // 2.1 Separate faces to process aMEP
531 aItME.Initialize(aME);
532 for (; aItME.More(); aItME.Next()) {
533 const TopoDS_Edge& aE=TopoDS::Edge(aItME.Key());
534 if (IsInside(aE, aF, myContext)) {
539 // 2.2 Make Internal Wires
541 MakeInternalWires(aMEP, aLSI);
543 // 2.3 Add them to aF
544 aIt1.Initialize(aLSI);
545 for (; aIt1.More(); aIt1.Next()) {
546 const TopoDS_Shape& aSI=aIt1.Value();
550 // 2.4 Remove faces aMFP from aMF
551 aItME.Initialize(aMEP);
552 for (; aItME.More(); aItME.Next()) {
553 const TopoDS_Shape& aE=aItME.Key();
561 } //for ( ; aIt2.More(); aIt2.Next()) {
563 //=======================================================================
564 //function : MakeInternalWires
566 //=======================================================================
567 void MakeInternalWires(const TopTools_MapOfShape& theME,
568 TopTools_ListOfShape& theWires)
570 TopTools_MapIteratorOfMapOfShape aItM;
571 TopTools_MapOfShape aAddedMap;
572 TopTools_ListIteratorOfListOfShape aItE;
573 TopTools_IndexedDataMapOfShapeListOfShape aMVE;
576 aItM.Initialize(theME);
577 for (; aItM.More(); aItM.Next()) {
578 const TopoDS_Shape& aE=aItM.Key();
579 TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
582 aItM.Initialize(theME);
583 for (; aItM.More(); aItM.Next()) {
584 TopoDS_Shape aEE=aItM.Key();
585 if (!aAddedMap.Add(aEE)) {
592 aEE.Orientation(TopAbs_INTERNAL);
595 TopoDS_Iterator aItAdded (aW);
596 for (; aItAdded.More(); aItAdded.Next()) {
597 const TopoDS_Shape& aE =aItAdded.Value();
599 TopExp_Explorer aExp(aE, TopAbs_VERTEX);
600 for (; aExp.More(); aExp.Next()) {
601 const TopoDS_Shape& aV =aExp.Current();
602 const TopTools_ListOfShape& aLE=aMVE.FindFromKey(aV);
603 aItE.Initialize(aLE);
604 for (; aItE.More(); aItE.Next()) {
605 TopoDS_Shape aEL=aItE.Value();
606 if (aAddedMap.Add(aEL)){
607 aEL.Orientation(TopAbs_INTERNAL);
616 //=======================================================================
617 //function : IsInside
619 //=======================================================================
620 Standard_Boolean IsInside(const TopoDS_Shape& theHole,
621 const TopoDS_Shape& theF2,
622 IntTools_PContext& theContext)
624 Standard_Boolean bRet;
625 Standard_Real aT, aU, aV;
628 TopExp_Explorer aExp;
629 TopTools_IndexedMapOfShape aME2;
633 aState=TopAbs_UNKNOWN;
634 const TopoDS_Face& aF2=TopoDS::Face(theF2);
636 TopExp::MapShapes(aF2, TopAbs_EDGE, aME2);
638 aExp.Init(theHole, TopAbs_EDGE);
640 const TopoDS_Edge& aE = TopoDS::Edge(aExp.Current());
641 if (aME2.Contains(aE)) {
645 aT=BOPTools_Tools2D::IntermediatePoint(aE);
646 BOPTools_Tools2D::PointOnSurface(aE, aF2, aT, aU, aV);
647 aP2D.SetCoord(aU, aV);
649 IntTools_FClass2d& aClsf=theContext->FClass2d(aF2);
650 aState=aClsf.Perform(aP2D);
651 bRet=(aState==TopAbs_IN);
657 //=======================================================================
658 //function : IsGrowthWire
660 //=======================================================================
661 Standard_Boolean IsGrowthWire(const TopoDS_Shape& theWire,
662 const TopTools_IndexedMapOfShape& theMHE)
664 Standard_Boolean bRet;
668 if (theMHE.Extent()) {
669 aIt.Initialize(theWire);
670 for(; aIt.More(); aIt.Next()) {
671 const TopoDS_Shape& aE=aIt.Value();
672 if (theMHE.Contains(aE)) {
680 //BRepTools::Write(aFF, "ff");
684 // 12 - Null face generix
687 //=======================================================================
688 //function : IsInside
690 //=======================================================================
691 Standard_Boolean IsInside(const TopoDS_Shape& theHole,
692 const TopoDS_Shape& theF2,
693 IntTools_PContext& theContext)
695 Standard_Real aT, aU, aV;
696 TopExp_Explorer aExp;
697 TopAbs_State aState=TopAbs_UNKNOWN;
700 const TopoDS_Face& aF2=TopoDS::Face(theF2);
702 aExp.Init(theHole, TopAbs_EDGE);
704 const TopoDS_Edge& aE = TopoDS::Edge(aExp.Current());
705 aT=BOPTools_Tools2D::IntermediatePoint(aE);
706 BOPTools_Tools2D::PointOnSurface(aE, aF2, aT, aU, aV);
707 aP2D.SetCoord(aU, aV);
709 IntTools_FClass2d& aClsf=theContext->FClass2d(aF2);
710 aState=aClsf.Perform(aP2D);
712 return (aState==TopAbs_IN);