1 // Copyright (C) 2005 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License.
9 // This library is distributed in the hope that it will be useful
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 // File: GEOMAlgo_BuilderFace.cxx
22 // Author: Peter KURNEV
24 #include <GEOMAlgo_BuilderFace.ixx>
26 #include <gp_Pnt2d.hxx>
32 #include <Geom_Surface.hxx>
35 #include <TopLoc_Location.hxx>
37 #include <TopoDS_Iterator.hxx>
38 #include <TopoDS_Face.hxx>
40 #include <TopoDS_Shape.hxx>
41 #include <TopoDS_Wire.hxx>
42 #include <TopoDS_Edge.hxx>
43 #include <TopoDS_Vertex.hxx>
45 #include <BRep_Builder.hxx>
46 #include <BRep_Tool.hxx>
47 #include <BRepTools.hxx>
50 #include <TopExp_Explorer.hxx>
52 #include <TopTools_MapOfShape.hxx>
53 #include <TopTools_MapIteratorOfMapOfShape.hxx>
54 #include <TopTools_MapOfOrientedShape.hxx>
55 #include <TopTools_MapIteratorOfMapOfOrientedShape.hxx>
56 #include <TopTools_ListOfShape.hxx>
57 #include <TopTools_ListIteratorOfListOfShape.hxx>
58 #include <TopTools_DataMapOfShapeShape.hxx>
59 #include <TopTools_IndexedMapOfShape.hxx>
60 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
61 #include <TopTools_DataMapOfShapeListOfShape.hxx>
62 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
64 #include <IntTools_FClass2d.hxx>
65 #include <IntTools_Context.hxx>
67 #include <BOPTools_Tools2D.hxx>
68 #include <BOP_WireEdgeSet.hxx>
69 #include <BOP_WESCorrector.hxx>
71 #include <NMTTools_ListOfCoupleOfShape.hxx>
72 #include <NMTTools_CoupleOfShape.hxx>
73 #include <NMTTools_ListIteratorOfListOfCoupleOfShape.hxx>
75 #include <GEOMAlgo_Tools3D.hxx>
76 #include <GEOMAlgo_BuilderTools.hxx>
77 #include <GEOMAlgo_WireEdgeSet.hxx>
78 #include <GEOMAlgo_WESCorrector.hxx>
82 Standard_Boolean IsGrowthWire(const TopoDS_Shape& ,
84 const TopTools_IndexedMapOfShape& );
87 Standard_Boolean IsInside(const TopoDS_Shape& ,
91 void MakeInternalWires(const TopTools_MapOfShape& ,
92 TopTools_ListOfShape& );
94 //=======================================================================
97 //=======================================================================
98 GEOMAlgo_BuilderFace::GEOMAlgo_BuilderFace()
100 GEOMAlgo_BuilderArea()
103 //=======================================================================
106 //=======================================================================
107 GEOMAlgo_BuilderFace::~GEOMAlgo_BuilderFace()
110 //=======================================================================
113 //=======================================================================
114 void GEOMAlgo_BuilderFace::SetFace(const TopoDS_Face& theFace)
118 //=======================================================================
121 //=======================================================================
122 const TopoDS_Face& GEOMAlgo_BuilderFace::Face()const
126 //=======================================================================
129 //=======================================================================
130 void GEOMAlgo_BuilderFace::Perform()
134 if (myContext==NULL) {
135 myErrorStatus=11;// Null Context
139 if (myFace.IsNull()) {
140 myErrorStatus=12;// Null face generix
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;
255 GEOMAlgo_WireEdgeSet aWES;
256 GEOMAlgo_WESCorrector aWESCor;
260 aWES.SetFace(myFace);
262 aIt.Initialize (myShapes);
263 for (; aIt.More(); aIt.Next()) {
264 const TopoDS_Shape& aE=aIt.Value();
265 if (!myShapesToAvoid.Contains(aE)) {
266 aWES.AddStartElement(aE);
270 aWESCor.SetWES(aWES);
273 GEOMAlgo_WireEdgeSet& aWESN=aWESCor.NewWES();
274 const TopTools_ListOfShape& aLW=aWESN.Shapes();
276 aIt.Initialize (aLW);
277 for (; aIt.More(); aIt.Next()) {
278 const TopoDS_Shape& aW=aIt.Value();
283 myLoopsInternal.Clear();
285 aNbEA=myShapesToAvoid.Extent();
286 aItM.Initialize(myShapesToAvoid);
287 for (; aItM.More(); aItM.Next()) {
288 const TopoDS_Shape& aEE=aItM.Key();
289 TopExp::MapShapesAndAncestors(aEE, TopAbs_VERTEX, TopAbs_EDGE, aVEMap);
293 aItM.Initialize(myShapesToAvoid);
294 for (; aItM.More()&&bFlag; aItM.Next()) {
295 const TopoDS_Shape& aEE=aItM.Key();
296 if (!aMAdded.Add(aEE)) {
305 TopoDS_Iterator aItW (aW);
306 for (; aItW.More()&&bFlag; aItW.Next()) {
307 const TopoDS_Edge& aE=TopoDS::Edge(aItW.Value());
309 TopoDS_Iterator aItE(aE);
310 for (; aItE.More()&&bFlag; aItE.Next()) {
311 const TopoDS_Vertex& aV = TopoDS::Vertex(aItE.Value());
312 const TopTools_ListOfShape& aLE=aVEMap.FindFromKey(aV);
314 for (; aIt.More()&&bFlag; aIt.Next()) {
315 const TopoDS_Shape& aEx=aIt.Value();
316 if (aMAdded.Add(aEx)) {
318 if(aMAdded.Extent()==aNbEA) {
322 }//for (; aIt.More(); aIt.Next()) {
323 }//for (; aItE.More(); aItE.Next()) {
324 }//for (; aItW.More(); aItW.Next()) {
325 myLoopsInternal.Append(aW);
326 }//for (; aItM.More(); aItM.Next()) {
328 //=======================================================================
329 //function : PerformAreas
331 //=======================================================================
332 void GEOMAlgo_BuilderFace::PerformAreas()
336 Standard_Boolean bIsGrowth, bIsHole;
338 TopTools_ListOfShape aNewFaces, aHoleWires;
339 TopoDS_Shape anInfinitePointShape;
340 TopTools_DataMapOfShapeShape aInOutMap;
341 TopTools_DataMapOfShapeListOfShape aMSH;
342 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItMSH;
343 TopTools_ListIteratorOfListOfShape aIt1, aIt2;
344 TopTools_IndexedMapOfShape aMHE;
346 Handle(Geom_Surface) aS;
347 TopLoc_Location aLoc;
349 aTol=BRep_Tool::Tolerance(myFace);
350 aS=BRep_Tool::Surface(myFace, aLoc);
354 // Draft faces [aNewFaces]
355 aIt1.Initialize(myLoops);
356 for ( ; aIt1.More(); aIt1.Next()) {
357 const TopoDS_Shape& aWire=aIt1.Value();
359 bIsGrowth=IsGrowthWire(aWire, aMHE);
361 // make a growth face from a wire
363 aBB.MakeFace(aFace, aS, aLoc, aTol);
364 aBB.Add (aFace, aWire);
366 aNewFaces.Append (aFace);
369 // check if a wire is a hole
371 //bIsHole=IsHole(aWire, myFace, myContext);
372 bIsHole=GEOMAlgo_BuilderTools::IsHole(aWire, myFace);
375 aHoleWires.Append(aWire);
376 TopExp::MapShapes(aWire, TopAbs_EDGE, aMHE);
379 // make a growth face from a wire
381 aBB.MakeFace(aFace, aS, aLoc, aTol);
382 aBB.Add (aFace, aWire);
384 aNewFaces.Append (aFace);
389 // 2. Find outer growth shell that is most close to each hole shell
390 aIt2.Initialize(aHoleWires);
391 for (; aIt2.More(); aIt2.Next()) {
392 const TopoDS_Shape& aHole = aIt2.Value();
394 aIt1.Initialize(aNewFaces);
395 for ( ; aIt1.More(); aIt1.Next()) {
396 const TopoDS_Shape& aF=aIt1.Value();
398 if (!IsInside(aHole, aF, myContext)){
402 if ( aInOutMap.IsBound (aHole)){
403 const TopoDS_Shape& aF2=aInOutMap(aHole);
404 if (IsInside(aF, aF2, myContext)) {
405 aInOutMap.UnBind(aHole);
406 aInOutMap.Bind (aHole, aF);
410 aInOutMap.Bind (aHole, aF);
414 // Add aHole to a map Face/ListOfHoles [aMSH]
415 if (aInOutMap.IsBound(aHole)){
416 const TopoDS_Shape& aF=aInOutMap(aHole);
417 if (aMSH.IsBound(aF)) {
418 TopTools_ListOfShape& aLH=aMSH.ChangeFind(aF);
422 TopTools_ListOfShape aLH;
427 }// for (; aIt2.More(); aIt2.Next())
429 // 3. Add aHoles to Faces
430 aItMSH.Initialize(aMSH);
431 for (; aItMSH.More(); aItMSH.Next()) {
432 TopoDS_Face aF=TopoDS::Face(aItMSH.Key());
434 const TopTools_ListOfShape& aLH=aItMSH.Value();
435 aIt2.Initialize(aLH);
436 for (; aIt2.More(); aIt2.Next()) {
437 const TopoDS_Shape& aHole = aIt2.Value();
442 aTol=BRep_Tool::Tolerance(aF);
443 IntTools_FClass2d& aClsf=myContext->FClass2d(aF);
444 aClsf.Init(aF, aTol);
447 // These aNewFaces are draft faces that
448 // do not contain any internal shapes
450 myAreas.Append(aNewFaces);
452 //=======================================================================
453 //function : PerformInternalShapes
455 //=======================================================================
456 void GEOMAlgo_BuilderFace::PerformInternalShapes()
460 Standard_Integer aNbWI=myLoopsInternal.Extent();
461 if (!aNbWI) {// nothing to do
465 //Standard_Real aTol;
467 TopTools_ListIteratorOfListOfShape aIt1, aIt2;
469 TopTools_MapOfShape aME, aMEP;
470 TopTools_MapIteratorOfMapOfShape aItME;
471 TopTools_IndexedDataMapOfShapeListOfShape aMVE;
472 TopTools_ListOfShape aLSI;
474 // 1. All internal edges
475 aIt1.Initialize(myLoopsInternal);
476 for (; aIt1.More(); aIt1.Next()) {
477 const TopoDS_Shape& aWire=aIt1.Value();
478 aIt.Initialize(aWire);
479 for (; aIt.More(); aIt.Next()) {
480 const TopoDS_Shape& aE=aIt.Value();
487 aIt2.Initialize(myAreas);
488 for ( ; aIt2.More(); aIt2.Next()) {
489 TopoDS_Face& aF=TopoDS::Face(aIt2.Value());
492 TopExp::MapShapesAndAncestors(aF, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
494 // 2.1 Separate faces to process aMEP
496 aItME.Initialize(aME);
497 for (; aItME.More(); aItME.Next()) {
498 const TopoDS_Edge& aE=TopoDS::Edge(aItME.Key());
499 if (IsInside(aE, aF, myContext)) {
504 // 2.2 Make Internal Wires
506 MakeInternalWires(aMEP, aLSI);
508 // 2.3 Add them to aF
509 aIt1.Initialize(aLSI);
510 for (; aIt1.More(); aIt1.Next()) {
511 const TopoDS_Shape& aSI=aIt1.Value();
515 // 2.4 Remove faces aMFP from aMF
516 aItME.Initialize(aMEP);
517 for (; aItME.More(); aItME.Next()) {
518 const TopoDS_Shape& aE=aItME.Key();
526 } //for ( ; aIt2.More(); aIt2.Next()) {
528 //=======================================================================
529 //function : MakeInternalWires
531 //=======================================================================
532 void MakeInternalWires(const TopTools_MapOfShape& theME,
533 TopTools_ListOfShape& theWires)
535 TopTools_MapIteratorOfMapOfShape aItM;
536 TopTools_MapOfShape aAddedMap;
537 TopTools_ListIteratorOfListOfShape aItE;
538 TopTools_IndexedDataMapOfShapeListOfShape aMVE;
541 aItM.Initialize(theME);
542 for (; aItM.More(); aItM.Next()) {
543 const TopoDS_Shape& aE=aItM.Key();
544 TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
547 aItM.Initialize(theME);
548 for (; aItM.More(); aItM.Next()) {
549 TopoDS_Shape aEE=aItM.Key();
550 if (!aAddedMap.Add(aEE)) {
557 aEE.Orientation(TopAbs_INTERNAL);
560 TopoDS_Iterator aItAdded (aW);
561 for (; aItAdded.More(); aItAdded.Next()) {
562 const TopoDS_Shape& aE =aItAdded.Value();
564 TopExp_Explorer aExp(aE, TopAbs_VERTEX);
565 for (; aExp.More(); aExp.Next()) {
566 const TopoDS_Shape& aV =aExp.Current();
567 const TopTools_ListOfShape& aLE=aMVE.FindFromKey(aV);
568 aItE.Initialize(aLE);
569 for (; aItE.More(); aItE.Next()) {
570 TopoDS_Shape aEL=aItE.Value();
571 if (aAddedMap.Add(aEL)){
572 aEL.Orientation(TopAbs_INTERNAL);
581 //=======================================================================
582 //function : IsInside
584 //=======================================================================
585 Standard_Boolean IsInside(const TopoDS_Shape& theHole,
586 const TopoDS_Shape& theF2,
587 IntTools_PContext& theContext)
589 Standard_Boolean bRet;
590 Standard_Real aT, aU, aV;
593 TopExp_Explorer aExp;
594 TopTools_IndexedMapOfShape aME2;
598 aState=TopAbs_UNKNOWN;
599 const TopoDS_Face& aF2=TopoDS::Face(theF2);
601 TopExp::MapShapes(aF2, TopAbs_EDGE, aME2);
603 aExp.Init(theHole, TopAbs_EDGE);
605 const TopoDS_Edge& aE = TopoDS::Edge(aExp.Current());
606 if (aME2.Contains(aE)) {
610 aT=BOPTools_Tools2D::IntermediatePoint(aE);
611 BOPTools_Tools2D::PointOnSurface(aE, aF2, aT, aU, aV);
612 aP2D.SetCoord(aU, aV);
614 IntTools_FClass2d& aClsf=theContext->FClass2d(aF2);
615 aState=aClsf.Perform(aP2D);
616 bRet=(aState==TopAbs_IN);
622 //=======================================================================
623 //function : IsGrowthWire
625 //=======================================================================
626 Standard_Boolean IsGrowthWire(const TopoDS_Shape& theWire,
627 const TopTools_IndexedMapOfShape& theMHE)
629 Standard_Boolean bRet;
633 if (theMHE.Extent()) {
634 aIt.Initialize(theWire);
635 for(; aIt.More(); aIt.Next()) {
636 const TopoDS_Shape& aE=aIt.Value();
637 if (theMHE.Contains(aE)) {
645 //BRepTools::Write(aFF, "ff");
649 // 12 - Null face generix
652 //=======================================================================
653 //function : IsInside
655 //=======================================================================
656 Standard_Boolean IsInside(const TopoDS_Shape& theHole,
657 const TopoDS_Shape& theF2,
658 IntTools_PContext& theContext)
660 Standard_Real aT, aU, aV;
661 TopExp_Explorer aExp;
662 TopAbs_State aState=TopAbs_UNKNOWN;
665 const TopoDS_Face& aF2=TopoDS::Face(theF2);
667 aExp.Init(theHole, TopAbs_EDGE);
669 const TopoDS_Edge& aE = TopoDS::Edge(aExp.Current());
670 aT=BOPTools_Tools2D::IntermediatePoint(aE);
671 BOPTools_Tools2D::PointOnSurface(aE, aF2, aT, aU, aV);
672 aP2D.SetCoord(aU, aV);
674 IntTools_FClass2d& aClsf=theContext->FClass2d(aF2);
675 aState=aClsf.Perform(aP2D);
677 return (aState==TopAbs_IN);