1 // Copyright (C) 2007-2008 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
24 // Author: Peter KURNEV
26 #include <GEOMAlgo_BuilderFace.ixx>
28 #include <gp_Pnt2d.hxx>
34 #include <Geom_Surface.hxx>
37 #include <TopLoc_Location.hxx>
39 #include <TopoDS_Iterator.hxx>
40 #include <TopoDS_Face.hxx>
42 #include <TopoDS_Shape.hxx>
43 #include <TopoDS_Wire.hxx>
44 #include <TopoDS_Edge.hxx>
45 #include <TopoDS_Vertex.hxx>
47 #include <BRep_Builder.hxx>
48 #include <BRep_Tool.hxx>
49 #include <BRepTools.hxx>
52 #include <TopExp_Explorer.hxx>
54 #include <TopTools_MapOfShape.hxx>
55 #include <TopTools_MapIteratorOfMapOfShape.hxx>
56 #include <TopTools_MapOfOrientedShape.hxx>
57 #include <TopTools_MapIteratorOfMapOfOrientedShape.hxx>
58 #include <TopTools_ListOfShape.hxx>
59 #include <TopTools_ListIteratorOfListOfShape.hxx>
60 #include <TopTools_DataMapOfShapeShape.hxx>
61 #include <TopTools_IndexedMapOfShape.hxx>
62 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
63 #include <TopTools_DataMapOfShapeListOfShape.hxx>
64 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
66 #include <IntTools_FClass2d.hxx>
67 #include <IntTools_Context.hxx>
69 #include <BOPTools_Tools2D.hxx>
70 #include <BOP_WireEdgeSet.hxx>
71 #include <BOP_WESCorrector.hxx>
73 #include <NMTTools_ListOfCoupleOfShape.hxx>
74 #include <NMTTools_CoupleOfShape.hxx>
75 #include <NMTTools_ListIteratorOfListOfCoupleOfShape.hxx>
77 #include <GEOMAlgo_Tools3D.hxx>
78 #include <GEOMAlgo_BuilderTools.hxx>
79 #include <GEOMAlgo_WireEdgeSet.hxx>
80 #include <GEOMAlgo_WESCorrector.hxx>
84 Standard_Boolean IsGrowthWire(const TopoDS_Shape& ,
86 const TopTools_IndexedMapOfShape& );
89 Standard_Boolean IsInside(const TopoDS_Shape& ,
93 void MakeInternalWires(const TopTools_MapOfShape& ,
94 TopTools_ListOfShape& );
96 //=======================================================================
99 //=======================================================================
100 GEOMAlgo_BuilderFace::GEOMAlgo_BuilderFace()
102 GEOMAlgo_BuilderArea()
105 //=======================================================================
108 //=======================================================================
109 GEOMAlgo_BuilderFace::~GEOMAlgo_BuilderFace()
112 //=======================================================================
115 //=======================================================================
116 void GEOMAlgo_BuilderFace::SetFace(const TopoDS_Face& theFace)
120 //=======================================================================
123 //=======================================================================
124 const TopoDS_Face& GEOMAlgo_BuilderFace::Face()const
128 //=======================================================================
131 //=======================================================================
132 void GEOMAlgo_BuilderFace::Perform()
136 if (myContext==NULL) {
137 myErrorStatus=11;// Null Context
141 if (myFace.IsNull()) {
142 myErrorStatus=12;// Null face generix
146 PerformShapesToAvoid();
161 PerformInternalShapes();
166 //=======================================================================
167 //function :PerformShapesToAvoid
169 //=======================================================================
170 void GEOMAlgo_BuilderFace::PerformShapesToAvoid()
172 Standard_Boolean bFound;
173 Standard_Integer i, iCnt, aNbV, aNbE;
174 TopTools_IndexedDataMapOfShapeListOfShape aMVE;
175 TopTools_ListIteratorOfListOfShape aIt;
177 myShapesToAvoid.Clear();
182 bFound=Standard_False;
186 aIt.Initialize (myShapes);
187 for (; aIt.More(); aIt.Next()) {
188 const TopoDS_Shape& aE=aIt.Value();
189 if (!myShapesToAvoid.Contains(aE)) {
190 TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
199 for (i=1; i<=aNbV; ++i) {
200 const TopoDS_Vertex& aV=TopoDS::Vertex(aMVE.FindKey(i));
202 TopTools_ListOfShape& aLE=aMVE.ChangeFromKey(aV);
208 const TopoDS_Edge& aE1=TopoDS::Edge(aLE.First());
210 if (BRep_Tool::Degenerated(aE1)) {
213 if (aV.Orientation()==TopAbs_INTERNAL) {
216 bFound=Standard_True;
217 myShapesToAvoid.Add(aE1);
220 const TopoDS_Edge& aE2=TopoDS::Edge(aLE.Last());
221 if (aE2.IsSame(aE1)) {
222 TopoDS_Vertex aV1x, aV2x;
224 TopExp::Vertices(aE1, aV1x, aV2x);
225 if (aV1x.IsSame(aV2x)) {
228 bFound=Standard_True;
229 myShapesToAvoid.Add(aE1);
230 myShapesToAvoid.Add(aE2);
233 }// for (i=1; i<=aNbE; ++i) {
240 //printf(" EdgesToAvoid=%d, iCnt=%d\n", EdgesToAvoid.Extent(), iCnt);
242 //=======================================================================
243 //function : PerformLoops
245 //=======================================================================
246 void GEOMAlgo_BuilderFace::PerformLoops()
250 Standard_Boolean bFlag;
251 Standard_Integer aNbEA;
252 TopTools_ListIteratorOfListOfShape aIt;
253 TopTools_MapIteratorOfMapOfOrientedShape aItM;
254 TopTools_IndexedDataMapOfShapeListOfShape aVEMap;
255 TopTools_MapOfOrientedShape aMAdded;
256 TopoDS_Iterator aItW;
258 GEOMAlgo_WireEdgeSet aWES;
259 GEOMAlgo_WESCorrector aWESCor;
263 aWES.SetFace(myFace);
265 aIt.Initialize (myShapes);
266 for (; aIt.More(); aIt.Next()) {
267 const TopoDS_Shape& aE=aIt.Value();
268 if (!myShapesToAvoid.Contains(aE)) {
269 aWES.AddStartElement(aE);
273 aWESCor.SetWES(aWES);
276 GEOMAlgo_WireEdgeSet& aWESN=aWESCor.NewWES();
277 const TopTools_ListOfShape& aLW=aWESN.Shapes();
279 aIt.Initialize (aLW);
280 for (; aIt.More(); aIt.Next()) {
281 const TopoDS_Shape& aW=aIt.Value();
284 //modified by NIZNHY-PKV Tue Aug 5 15:09:29 2008f
286 TopTools_MapOfOrientedShape aMEP;
288 // a. collect all edges that are in loops
289 aIt.Initialize (myLoops);
290 for (; aIt.More(); aIt.Next()) {
291 const TopoDS_Shape& aW=aIt.Value();
293 for (; aItW.More(); aItW.Next()) {
294 const TopoDS_Shape& aE=aItW.Value();
299 // b. collect all edges that are to avoid
300 aItM.Initialize(myShapesToAvoid);
301 for (; aItM.More(); aItM.Next()) {
302 const TopoDS_Shape& aE=aItM.Key();
306 // c. add all edges that are not processed to myShapesToAvoid
307 aIt.Initialize (myShapes);
308 for (; aIt.More(); aIt.Next()) {
309 const TopoDS_Shape& aE=aIt.Value();
310 if (!aMEP.Contains(aE)) {
311 myShapesToAvoid.Add(aE);
314 //modified by NIZNHY-PKV Tue Aug 5 15:09:35 2008t
317 myLoopsInternal.Clear();
319 aNbEA=myShapesToAvoid.Extent();
320 aItM.Initialize(myShapesToAvoid);
321 for (; aItM.More(); aItM.Next()) {
322 const TopoDS_Shape& aEE=aItM.Key();
323 TopExp::MapShapesAndAncestors(aEE, TopAbs_VERTEX, TopAbs_EDGE, aVEMap);
327 aItM.Initialize(myShapesToAvoid);
328 for (; aItM.More()&&bFlag; aItM.Next()) {
329 const TopoDS_Shape& aEE=aItM.Key();
330 if (!aMAdded.Add(aEE)) {
340 for (; aItW.More()&&bFlag; aItW.Next()) {
341 const TopoDS_Edge& aE=TopoDS::Edge(aItW.Value());
343 TopoDS_Iterator aItE(aE);
344 for (; aItE.More()&&bFlag; aItE.Next()) {
345 const TopoDS_Vertex& aV = TopoDS::Vertex(aItE.Value());
346 const TopTools_ListOfShape& aLE=aVEMap.FindFromKey(aV);
348 for (; aIt.More()&&bFlag; aIt.Next()) {
349 const TopoDS_Shape& aEx=aIt.Value();
350 if (aMAdded.Add(aEx)) {
352 if(aMAdded.Extent()==aNbEA) {
356 }//for (; aIt.More(); aIt.Next()) {
357 }//for (; aItE.More(); aItE.Next()) {
358 }//for (; aItW.More(); aItW.Next()) {
359 myLoopsInternal.Append(aW);
360 }//for (; aItM.More(); aItM.Next()) {
362 //=======================================================================
363 //function : PerformAreas
365 //=======================================================================
366 void GEOMAlgo_BuilderFace::PerformAreas()
370 Standard_Boolean bIsGrowth, bIsHole;
372 TopTools_ListOfShape aNewFaces, aHoleWires;
373 TopoDS_Shape anInfinitePointShape;
374 TopTools_DataMapOfShapeShape aInOutMap;
375 TopTools_DataMapOfShapeListOfShape aMSH;
376 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItMSH;
377 TopTools_ListIteratorOfListOfShape aIt1, aIt2;
378 TopTools_IndexedMapOfShape aMHE;
380 Handle(Geom_Surface) aS;
381 TopLoc_Location aLoc;
383 aTol=BRep_Tool::Tolerance(myFace);
384 aS=BRep_Tool::Surface(myFace, aLoc);
388 // Draft faces [aNewFaces]
389 aIt1.Initialize(myLoops);
390 for ( ; aIt1.More(); aIt1.Next()) {
391 const TopoDS_Shape& aWire=aIt1.Value();
393 bIsGrowth=IsGrowthWire(aWire, aMHE);
395 // make a growth face from a wire
397 aBB.MakeFace(aFace, aS, aLoc, aTol);
398 aBB.Add (aFace, aWire);
400 aNewFaces.Append (aFace);
403 // check if a wire is a hole
405 //bIsHole=IsHole(aWire, myFace, myContext);
406 bIsHole=GEOMAlgo_BuilderTools::IsHole(aWire, myFace);
409 aHoleWires.Append(aWire);
410 TopExp::MapShapes(aWire, TopAbs_EDGE, aMHE);
413 // make a growth face from a wire
415 aBB.MakeFace(aFace, aS, aLoc, aTol);
416 aBB.Add (aFace, aWire);
418 aNewFaces.Append (aFace);
423 // 2. Find outer growth shell that is most close to each hole shell
424 aIt2.Initialize(aHoleWires);
425 for (; aIt2.More(); aIt2.Next()) {
426 const TopoDS_Shape& aHole = aIt2.Value();
428 aIt1.Initialize(aNewFaces);
429 for ( ; aIt1.More(); aIt1.Next()) {
430 const TopoDS_Shape& aF=aIt1.Value();
432 if (!IsInside(aHole, aF, myContext)){
436 if ( aInOutMap.IsBound (aHole)){
437 const TopoDS_Shape& aF2=aInOutMap(aHole);
438 if (IsInside(aF, aF2, myContext)) {
439 aInOutMap.UnBind(aHole);
440 aInOutMap.Bind (aHole, aF);
444 aInOutMap.Bind (aHole, aF);
448 // Add aHole to a map Face/ListOfHoles [aMSH]
449 if (aInOutMap.IsBound(aHole)){
450 const TopoDS_Shape& aF=aInOutMap(aHole);
451 if (aMSH.IsBound(aF)) {
452 TopTools_ListOfShape& aLH=aMSH.ChangeFind(aF);
456 TopTools_ListOfShape aLH;
461 }// for (; aIt2.More(); aIt2.Next())
463 // 3. Add aHoles to Faces
464 aItMSH.Initialize(aMSH);
465 for (; aItMSH.More(); aItMSH.Next()) {
466 TopoDS_Face aF=TopoDS::Face(aItMSH.Key());
468 const TopTools_ListOfShape& aLH=aItMSH.Value();
469 aIt2.Initialize(aLH);
470 for (; aIt2.More(); aIt2.Next()) {
471 const TopoDS_Shape& aHole = aIt2.Value();
476 aTol=BRep_Tool::Tolerance(aF);
477 IntTools_FClass2d& aClsf=myContext->FClass2d(aF);
478 aClsf.Init(aF, aTol);
481 // These aNewFaces are draft faces that
482 // do not contain any internal shapes
484 myAreas.Append(aNewFaces);
486 //=======================================================================
487 //function : PerformInternalShapes
489 //=======================================================================
490 void GEOMAlgo_BuilderFace::PerformInternalShapes()
494 Standard_Integer aNbWI=myLoopsInternal.Extent();
495 if (!aNbWI) {// nothing to do
499 //Standard_Real aTol;
501 TopTools_ListIteratorOfListOfShape aIt1, aIt2;
503 TopTools_MapOfShape aME, aMEP;
504 TopTools_MapIteratorOfMapOfShape aItME;
505 TopTools_IndexedDataMapOfShapeListOfShape aMVE;
506 TopTools_ListOfShape aLSI;
508 // 1. All internal edges
509 aIt1.Initialize(myLoopsInternal);
510 for (; aIt1.More(); aIt1.Next()) {
511 const TopoDS_Shape& aWire=aIt1.Value();
512 aIt.Initialize(aWire);
513 for (; aIt.More(); aIt.Next()) {
514 const TopoDS_Shape& aE=aIt.Value();
521 aIt2.Initialize(myAreas);
522 for ( ; aIt2.More(); aIt2.Next()) {
523 TopoDS_Face& aF=TopoDS::Face(aIt2.Value());
526 TopExp::MapShapesAndAncestors(aF, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
528 // 2.1 Separate faces to process aMEP
530 aItME.Initialize(aME);
531 for (; aItME.More(); aItME.Next()) {
532 const TopoDS_Edge& aE=TopoDS::Edge(aItME.Key());
533 if (IsInside(aE, aF, myContext)) {
538 // 2.2 Make Internal Wires
540 MakeInternalWires(aMEP, aLSI);
542 // 2.3 Add them to aF
543 aIt1.Initialize(aLSI);
544 for (; aIt1.More(); aIt1.Next()) {
545 const TopoDS_Shape& aSI=aIt1.Value();
549 // 2.4 Remove faces aMFP from aMF
550 aItME.Initialize(aMEP);
551 for (; aItME.More(); aItME.Next()) {
552 const TopoDS_Shape& aE=aItME.Key();
560 } //for ( ; aIt2.More(); aIt2.Next()) {
562 //=======================================================================
563 //function : MakeInternalWires
565 //=======================================================================
566 void MakeInternalWires(const TopTools_MapOfShape& theME,
567 TopTools_ListOfShape& theWires)
569 TopTools_MapIteratorOfMapOfShape aItM;
570 TopTools_MapOfShape aAddedMap;
571 TopTools_ListIteratorOfListOfShape aItE;
572 TopTools_IndexedDataMapOfShapeListOfShape aMVE;
575 aItM.Initialize(theME);
576 for (; aItM.More(); aItM.Next()) {
577 const TopoDS_Shape& aE=aItM.Key();
578 TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
581 aItM.Initialize(theME);
582 for (; aItM.More(); aItM.Next()) {
583 TopoDS_Shape aEE=aItM.Key();
584 if (!aAddedMap.Add(aEE)) {
591 aEE.Orientation(TopAbs_INTERNAL);
594 TopoDS_Iterator aItAdded (aW);
595 for (; aItAdded.More(); aItAdded.Next()) {
596 const TopoDS_Shape& aE =aItAdded.Value();
598 TopExp_Explorer aExp(aE, TopAbs_VERTEX);
599 for (; aExp.More(); aExp.Next()) {
600 const TopoDS_Shape& aV =aExp.Current();
601 const TopTools_ListOfShape& aLE=aMVE.FindFromKey(aV);
602 aItE.Initialize(aLE);
603 for (; aItE.More(); aItE.Next()) {
604 TopoDS_Shape aEL=aItE.Value();
605 if (aAddedMap.Add(aEL)){
606 aEL.Orientation(TopAbs_INTERNAL);
615 //=======================================================================
616 //function : IsInside
618 //=======================================================================
619 Standard_Boolean IsInside(const TopoDS_Shape& theHole,
620 const TopoDS_Shape& theF2,
621 IntTools_PContext& theContext)
623 Standard_Boolean bRet;
624 Standard_Real aT, aU, aV;
627 TopExp_Explorer aExp;
628 TopTools_IndexedMapOfShape aME2;
632 aState=TopAbs_UNKNOWN;
633 const TopoDS_Face& aF2=TopoDS::Face(theF2);
635 TopExp::MapShapes(aF2, TopAbs_EDGE, aME2);
637 aExp.Init(theHole, TopAbs_EDGE);
639 const TopoDS_Edge& aE = TopoDS::Edge(aExp.Current());
640 if (aME2.Contains(aE)) {
644 aT=BOPTools_Tools2D::IntermediatePoint(aE);
645 BOPTools_Tools2D::PointOnSurface(aE, aF2, aT, aU, aV);
646 aP2D.SetCoord(aU, aV);
648 IntTools_FClass2d& aClsf=theContext->FClass2d(aF2);
649 aState=aClsf.Perform(aP2D);
650 bRet=(aState==TopAbs_IN);
656 //=======================================================================
657 //function : IsGrowthWire
659 //=======================================================================
660 Standard_Boolean IsGrowthWire(const TopoDS_Shape& theWire,
661 const TopTools_IndexedMapOfShape& theMHE)
663 Standard_Boolean bRet;
667 if (theMHE.Extent()) {
668 aIt.Initialize(theWire);
669 for(; aIt.More(); aIt.Next()) {
670 const TopoDS_Shape& aE=aIt.Value();
671 if (theMHE.Contains(aE)) {
679 //BRepTools::Write(aFF, "ff");
683 // 12 - Null face generix
686 //=======================================================================
687 //function : IsInside
689 //=======================================================================
690 Standard_Boolean IsInside(const TopoDS_Shape& theHole,
691 const TopoDS_Shape& theF2,
692 IntTools_PContext& theContext)
694 Standard_Real aT, aU, aV;
695 TopExp_Explorer aExp;
696 TopAbs_State aState=TopAbs_UNKNOWN;
699 const TopoDS_Face& aF2=TopoDS::Face(theF2);
701 aExp.Init(theHole, TopAbs_EDGE);
703 const TopoDS_Edge& aE = TopoDS::Edge(aExp.Current());
704 aT=BOPTools_Tools2D::IntermediatePoint(aE);
705 BOPTools_Tools2D::PointOnSurface(aE, aF2, aT, aU, aV);
706 aP2D.SetCoord(aU, aV);
708 IntTools_FClass2d& aClsf=theContext->FClass2d(aF2);
709 aState=aClsf.Perform(aP2D);
711 return (aState==TopAbs_IN);