2 // File : Partition_Loop2d.cxx
3 // Created : Thu Aug 02 16:25:17 2001
4 // Author : Benedicte MARTIN
7 // Copyright : Open CASCADE
11 #include "Partition_Loop2d.ixx"
13 #include "utilities.h"
16 #include <BRepAdaptor_Curve2d.hxx>
17 #include <BRepAdaptor_Surface.hxx>
18 #include <BRepAlgo_AsDes.hxx>
19 #include <BRepOffset_DataMapOfShapeReal.hxx>
20 #include <BRepTopAdaptor_FClass2d.hxx>
21 #include <BRep_Builder.hxx>
22 #include <BRep_Tool.hxx>
23 #include <Geom2dInt_GInter.hxx>
24 #include <Geom2d_Curve.hxx>
25 #include <IntRes2d_IntersectionPoint.hxx>
26 #include <Precision.hxx>
27 #include <TColStd_MapOfInteger.hxx>
28 #include <TColStd_SequenceOfReal.hxx>
30 #include <TopExp_Explorer.hxx>
31 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
32 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
33 #include <TopTools_DataMapOfShapeInteger.hxx>
34 #include <TopTools_DataMapOfShapeShape.hxx>
35 #include <TopTools_IndexedMapOfShape.hxx>
36 #include <TopTools_ListIteratorOfListOfShape.hxx>
37 #include <TopTools_MapIteratorOfMapOfShape.hxx>
38 #include <TopTools_MapOfOrientedShape.hxx>
39 #include <TopTools_MapOfShape.hxx>
40 #include <TopTools_SequenceOfShape.hxx>
42 #include <TopoDS_Iterator.hxx>
43 #include <TopoDS_Vertex.hxx>
44 #include <TopoDS_Wire.hxx>
46 #include <gp_Pnt2d.hxx>
48 //=======================================================================
49 //function : Partition_Loop2d
51 //=======================================================================
53 Partition_Loop2d::Partition_Loop2d()
57 //=======================================================================
59 //purpose : Init with <F> the set of edges must have
61 //=======================================================================
63 void Partition_Loop2d::Init(const TopoDS_Face& F)
69 myFaceOri = myFace.Orientation();
70 myFace.Orientation( TopAbs_FORWARD );
73 //=======================================================================
74 //function : AddConstEdge
75 //purpose : Add <E> as unique edge in the result.
76 //=======================================================================
78 void Partition_Loop2d::AddConstEdge (const TopoDS_Edge& E)
82 Handle(Geom2d_Curve) pc = BRep_Tool::CurveOnSurface( E, myFace, f,l);
84 INFOS( "AddConstEdge(): EDGE W/O PCURVE on FACE");
88 myConstEdges.Append(E);
92 void Partition_Loop2d::AddSectionEdge (const TopoDS_Edge& E)
96 Handle(Geom2d_Curve) pc = BRep_Tool::CurveOnSurface( E, myFace, f,l);
98 pc = BRep_Tool::CurveOnSurface( E, myFace, f,l);
101 pc->D1(0.5*(f+l), PC, Tg1);
102 if (Tg1.Magnitude() <= gp::Resolution()) {
106 INFOS( "AddConstEdge(): EDGE W/O PCURVE on FACE");
110 myConstEdges.Append(E);
111 myConstEdges.Append(E.Reversed());
112 mySectionEdges.Add( E );
116 //=======================================================================
117 //function : SelectEdge
118 //purpose : Find the edge <NE> connected <CE> by the vertex <CV> in the list <LE>.
119 // <NE> Is erased of the list. If <CE> is too in the list <LE>
120 // with the same orientation, it's erased of the list
121 //=======================================================================
123 static Standard_Boolean SelectEdge(const BRepAdaptor_Surface& Surf,
124 const TopoDS_Edge& CE,
125 const TopoDS_Vertex& CV,
127 const TopTools_ListOfShape& LE)
131 if (LE.Extent() > 1) {
132 //--------------------------------------------------------------
133 // Several possible edges.
134 // - Test the edges differents of CE
135 //--------------------------------------------------------------
136 TopoDS_Face FForward = Surf.Face();
138 Standard_Real cf, cl, f, l;
139 Handle(Geom2d_Curve) Cc, C;
140 Cc = BRep_Tool::CurveOnSurface(CE,FForward,cf,cl);
142 // Standard_Real tolV, tol2d2;
143 Standard_Real tolV = BRep_Tool::Tolerance(CV);
144 // tol2d2 = Max ( Surf.UResolution(tolV) , Surf.VResolution(tolV) );
145 // tol2d2 = 2 * Max ( tol2d2, Precision::PConfusion() );
148 Standard_Real uc,u, du = Precision::PConfusion();
149 if (CE.Orientation () == TopAbs_FORWARD) uc = cl + du;
156 Cc->D1(uc, PC, CTg1);
157 if (CE.Orientation () == TopAbs_REVERSED) CTg1.Reverse();
159 Standard_Real anglemin = 3 * PI;
160 // Standard_Real sqdist, sqdistmin = 1.0e50;
162 TopTools_ListIteratorOfListOfShape itl;
163 for ( itl.Initialize(LE); itl.More(); itl.Next()) {
164 const TopoDS_Edge& E = TopoDS::Edge(itl.Value());
167 if (! CV.IsSame( TopExp::FirstVertex( E, Standard_True )))
170 C = BRep_Tool::CurveOnSurface(E,FForward,f,l);
171 if (E.Orientation () == TopAbs_FORWARD) u = f + du;
175 // if (P.SquareDistance(PC); > tol2d2)
178 if (E.Orientation () == TopAbs_REVERSED) Tg1.Reverse();
180 Standard_Real angle = Tg1.Angle(CTg1);
182 if (angle <= anglemin) {
186 // sqdist = P.SquareDistance(PC);
187 // if (sqdist < sqdistmin)
188 // sqdistmin = sqdist;
189 P3d = Surf.Value (PC.X(), PC.Y());
194 if (!NE.IsNull() && P3d.Distance( BRep_Tool::Pnt(CV)) > tolV) {
195 MESSAGE( "DISTANCE MORE THAN VERTEX TOL (" << tolV << ")" );
196 cout << "point p " << P3d.X() << " " << P3d.Y() << " " << P3d.Z() << endl;
200 else if (LE.Extent() == 1) {
201 NE = TopoDS::Edge(LE.First());
204 return Standard_False;
209 //=======================================================================
210 //function : SamePnt2d
212 //=======================================================================
214 static Standard_Boolean SamePnt2d(const TopoDS_Vertex& V1,
215 const TopoDS_Edge& E1,
216 const TopoDS_Vertex& V2,
217 const TopoDS_Edge& E2,
218 const TopoDS_Face& F)
220 Standard_Real f1,f2,l1,l2;
221 Handle(Geom2d_Curve) C1 = BRep_Tool::CurveOnSurface(E1,F,f1,l1);
222 Handle(Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(E2,F,f2,l2);
224 gp_Pnt2d P1 = C1->Value( BRep_Tool::Parameter(V1,E1));
225 gp_Pnt2d P2 = C2->Value( BRep_Tool::Parameter(V2,E2));
227 Standard_Real Tol = 100 * BRep_Tool::Tolerance(V1);
228 Standard_Real Dist = P1.Distance(P2);
233 //=======================================================================
234 //function : StoreInMVE
236 //=======================================================================
238 static void StoreInMVE (const TopoDS_Face& /*F*/,
240 TopTools_DataMapOfShapeListOfShape& MVE )
243 TopoDS_Vertex V1, V2;
244 TopTools_ListOfShape Empty;
246 TopExp::Vertices(E,V1,V2);
247 if (!MVE.IsBound(V1)) {
252 if (!MVE.IsBound(V2)) {
258 //=======================================================================
259 //function : RemoveFromMVE
261 //=======================================================================
263 static void RemoveFromMVE(const TopoDS_Edge& E,
264 TopTools_DataMapOfShapeListOfShape& MVE)
266 TopTools_ListIteratorOfListOfShape itl;
268 TopExp::Vertices (E,V1,V2);
270 for ( itl.Initialize(MVE(V1)); itl.More(); itl.Next()) {
271 if (itl.Value().IsEqual(E)) {
277 for ( itl.Initialize(MVE(V2)); itl.More(); itl.Next()) {
278 if (itl.Value().IsEqual(E)) {
284 //=======================================================================
285 //function : addConnected
286 //purpose : add to <EM> all edges reachable from <E>
287 //=======================================================================
289 static void addConnected(const TopoDS_Shape& E,
290 TopTools_MapOfShape& EM,
291 TopTools_MapOfShape& VM,
292 const TopTools_DataMapOfShapeListOfShape& MVE)
294 // Loop on vertices of E
295 TopoDS_Iterator itV ( E );
296 for ( ; itV.More(); itV.Next()) {
298 if ( ! VM.Add ( itV.Value() )) continue;
300 // Loop on edges sharing V
301 TopTools_ListIteratorOfListOfShape itE( MVE( itV.Value() ) );
302 for (; itE.More(); itE.Next()) {
303 if ( EM.Add( itE.Value() ))
304 addConnected ( itE.Value(), EM, VM, MVE );
308 //=======================================================================
309 //function : canPassToOld
311 //=======================================================================
313 static Standard_Boolean canPassToOld (const TopoDS_Shape& V,
314 TopTools_MapOfShape& UsedShapesMap,
315 const TopTools_DataMapOfShapeListOfShape& MVE,
316 const TopTools_MapOfShape& SectionEdgesMap)
318 TopTools_ListIteratorOfListOfShape itE( MVE(V) );
319 // Loop on edges sharing V
320 for (; itE.More(); itE.Next()) {
321 if ( !UsedShapesMap.Add( itE.Value() ))
322 continue; // already checked
324 if ( !SectionEdgesMap.Contains( itE.Value() ))
325 return Standard_True; // WE PASSED
327 TopoDS_Iterator itV( itE.Value() );
328 // Loop on vertices of an edge
329 for (; itV.More(); itV.Next()) {
330 if ( !UsedShapesMap.Add( itV.Value() ))
331 continue; // already checked
333 return canPassToOld( itV.Value(), UsedShapesMap, MVE, SectionEdgesMap);
336 return Standard_False;
339 //=======================================================================
340 //function : MakeDegenAndSelect
341 //purpose : Find parameter of intersection of <CE> with <DE> and
342 // select an edge with its parameter closest to found one.
343 // Return new degenerated edge trimming <DE> by found parameters
344 //=======================================================================
346 static TopoDS_Edge MakeDegenAndSelect(const TopoDS_Edge& CE,
347 const TopoDS_Vertex& CV,
349 TopTools_SequenceOfShape& EdgesSeq,
350 TColStd_SequenceOfReal& USeq,
351 const TopoDS_Edge& DE)
353 if (EdgesSeq.Length() < 3) {
354 if (CE == EdgesSeq.First())
355 NE = TopoDS::Edge( EdgesSeq.Last() );
357 NE = TopoDS::Edge( EdgesSeq.First() );
361 // find parameter on DE where it intersects CE
364 Standard_Integer i, nb = EdgesSeq.Length();
365 for (i=1; i<= nb; ++i) {
366 if (CE == EdgesSeq(i)) {
372 // select NE with param closest to U1 thus finding U2 for a new degen edge
374 Standard_Real U2, dU, dUmin = 1.e100;
375 Standard_Boolean isReversed = ( DE.Orientation() == TopAbs_REVERSED );
376 for (i=1; i<= nb; ++i) {
378 if (isReversed ? (dU > 0) : (dU < 0))
381 if ( dU > dUmin || IsEqual( dU, 0.))
383 const TopoDS_Edge& E = TopoDS::Edge ( EdgesSeq(i) );
384 if ( ! CV.IsSame( TopExp::FirstVertex( E , Standard_True )))
387 dUmin = dU + Epsilon(dU);
391 // make a new degenerated edge
392 TopoDS_Edge NewDegen = TopoDS::Edge ( DE.EmptyCopied() );
394 Standard_Real Tol = BRep_Tool::Tolerance( CV );
395 TopoDS_Vertex V = CV;
398 V.Orientation( NewDegen.Orientation() );
399 B.UpdateVertex( V, U1, NewDegen, Tol);
400 B.Add ( NewDegen , V );
403 B.UpdateVertex( V, U2, NewDegen, Tol);
404 B.Add ( NewDegen , V );
409 //=======================================================================
410 //function : prepareDegen
411 //purpose : Intersect <DegEdge> with edges bound to its vertex in <MVE>
412 // and store intersection parameter on <DegEdge> in
413 // <USeq> as well as the edges them-self in <EdgesSeq>.
414 // Bind <DegEdgeIndex> to vertex of <DegEdge> in <MVDEI>
415 //=======================================================================
417 static void prepareDegen (const TopoDS_Edge& DegEdge,
418 const TopoDS_Face& F,
419 const TopTools_DataMapOfShapeListOfShape& MVE,
420 TopTools_SequenceOfShape& EdgesSeq,
421 TColStd_SequenceOfReal& USeq,
422 TopTools_DataMapOfShapeInteger& MVDEI,
423 const Standard_Integer DegEdgeIndex)
425 const TopoDS_Vertex& V = TopExp::FirstVertex ( DegEdge );
426 MVDEI.Bind ( V, DegEdgeIndex );
428 const TopTools_ListOfShape& EdgesList = MVE ( V );
429 // if only 2 edges come to degenerated one, no pb in selection and
430 // no need to intersect them, just simulate asked data
431 Standard_Boolean doIntersect = ( EdgesList.Extent() > 2 );
433 BRepAdaptor_Curve2d DC, C;
434 Geom2dInt_GInter InterCC;
435 Standard_Real Tol = Precision::PConfusion();
437 DC.Initialize( DegEdge, F );
439 // avoid intersecting twice the same edge
440 BRepOffset_DataMapOfShapeReal EUMap ( EdgesList.Extent() );
442 Standard_Real U, f, l;
443 BRep_Tool::Range (DegEdge, f, l);
445 TopTools_ListIteratorOfListOfShape itE (EdgesList);
446 for (; itE.More(); itE.Next()) {
448 const TopoDS_Edge& E = TopoDS::Edge ( itE.Value() );
451 U = 0.; // it won't be used
453 else if ( BRep_Tool::IsClosed( E, F )) {
454 // seam edge: select U among f and l
455 Standard_Boolean first = Standard_True;
456 if ( V.IsSame ( TopExp::FirstVertex( E, Standard_True ) ))
457 first = Standard_False;
458 if ( DegEdge.Orientation() == TopAbs_REVERSED )
462 else if ( EUMap.IsBound( E ) ) {
463 // same edge already bound
467 // intersect 2d curves
468 C.Initialize( E, F );
469 InterCC.Perform ( DC, C , Tol, Tol );
470 if (! InterCC.IsDone() || InterCC.NbPoints() == 0) {
471 MESSAGE ( "NO 2d INTERSECTION ON DEGENERATED EDGE" );
474 // hope there is only one point of intersection
475 U = InterCC.Point( 1 ).ParamOnFirst();
478 EdgesSeq.Append ( E );
481 //=======================================================================
483 //purpose : Make loops.
484 //=======================================================================
486 void Partition_Loop2d::Perform()
489 Standard_Integer NbConstEdges = myConstEdges.Extent();
490 TopTools_DataMapOfShapeListOfShape MVE(NbConstEdges) , MVE2(NbConstEdges);
491 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape Mapit;
492 TopTools_ListIteratorOfListOfShape itl;
494 BRepAdaptor_Surface Surface ( myFace, Standard_False );
496 // degenerated edges and parameters of their 2d intersection with other edges
498 TopTools_SequenceOfShape SEID [2]; // seq of edges intersecting degenerated
499 TColStd_SequenceOfReal SeqU [2]; // n-th U corresponds to n-th edge in SEID
500 TopTools_DataMapOfShapeInteger MVDEI(2); // map vertex - degenerated edge index
501 Standard_Integer iDeg = 0; // index of degenerated edge [0,1]
503 //---------------------------------------------------------
504 // Construction map vertex => edges, find degenerated edges
505 //---------------------------------------------------------
506 for (itl.Initialize(myConstEdges); itl.More(); itl.Next()) {
507 TopoDS_Edge& E = TopoDS::Edge(itl.Value());
508 if ( BRep_Tool::Degenerated( E )) {
509 if (DE[0].IsNull()) DE[0] = E;
513 StoreInMVE(myFace,E,MVE);
516 // fill data for degenerated edges
517 if ( ! DE[0].IsNull() )
518 prepareDegen ( DE[0], myFace, MVE, SEID[0], SeqU[0], MVDEI, 0);
519 if ( ! DE[1].IsNull() )
520 prepareDegen ( DE[1], myFace, MVE, SEID[1], SeqU[1], MVDEI, 1);
523 // to detect internal wires
524 Standard_Boolean isInternCW = 0;
528 //------------------------------
529 // Construction of all the wires
530 //------------------------------
531 // first, we collect wire edges in WEL list looking for same edges that
532 // will be then removed possibly exploding a wire into parts;
533 // second, build wire(s)
535 while (!MVE.IsEmpty()) {
538 TopoDS_Edge CE,NE,EF;
541 Standard_Boolean End = Standard_False;
542 TopTools_ListOfShape WEL;
544 Mapit.Initialize(MVE);
545 if (Mapit.Value().IsEmpty()) {
546 MVE.UnBind(Mapit.Key());
551 EF = CE = TopoDS::Edge(Mapit.Value().First());
553 VF = TopExp::FirstVertex( CE, Standard_True);
555 isInternCW = Standard_True;
557 TopTools_MapOfShape addedEM (NbConstEdges); // map of edges added to WEL
558 TopTools_MapOfShape doubleEM (NbConstEdges); // edges encountered twice in WEL
560 //-------------------------------
561 // Construction of a wire.
562 //-------------------------------
565 // only a seam is allowed twice in a wire, the others should be removed
566 if (addedEM.Add ( CE ) || BRep_Tool::IsClosed( CE, myFace ) )
570 RemoveFromMVE (CE,MVE2);
571 TopoDS_Edge CERev = CE;
573 RemoveFromMVE (CERev,MVE2);
576 RemoveFromMVE (CE,MVE);
578 CV = TopExp::LastVertex( CE, Standard_True);
580 if (isInternCW && !mySectionEdges.Contains(CE))
581 // wire is internal if all edges are section ones
582 isInternCW = Standard_False;
584 if (MVDEI.IsBound( CV )) { // CE comes to the degeneration
586 TopoDS_Edge NewDegen;
587 NewDegen = MakeDegenAndSelect( CE, CV, NE, SEID[iDeg], SeqU[iDeg], DE[iDeg]);
588 WEL.Append( NewDegen );
590 End = CV.IsSame( VF );
597 if (MVE(CV).IsEmpty()) {
601 else if (CV.IsSame(VF) && SamePnt2d(CV,CE, VF,EF, myFace) ) {
605 //----------------------------
606 // select new current edge
607 //----------------------------
608 if (! SelectEdge (Surface,CE,CV,NE,MVE(CV))) {
609 MESSAGE ( " NOT CLOSED WIRE " );
618 // WEL is built, built wire(s)
621 itl.Initialize( WEL );
622 if ( doubleEM.IsEmpty()) { // no double edges
624 for (; itl.More(); itl.Next())
625 B.Add ( NW, itl.Value());
626 if (isInternCW) myInternalWL.Append(NW);
627 else myNewWires.Append (NW);
631 // remove double and degenerated edges from WEL
633 const TopoDS_Edge& E = TopoDS::Edge ( itl.Value() );
634 if ( doubleEM.Contains( E ) || BRep_Tool::Degenerated( E ))
641 // remove double edges from SEID and SeqU
642 Standard_Integer i,j;
643 for (j=0; j<2; ++j) {
644 for (i=1; i<=SEID[j].Length(); ++i) {
645 if (doubleEM.Contains( SEID[j].Value(i))) {
647 SeqU[j].Remove( i-- );
651 // removal of doulbe edges can explode a wire into parts,
652 // make new wires of them.
653 // A Loop like previous one but without 2d check
654 while ( !WEL.IsEmpty() ) {
655 CE = TopoDS::Edge( WEL.First() );
658 VF = TopExp::FirstVertex ( EF, Standard_True);
660 End = Standard_False;
663 CV = TopExp::LastVertex ( CE, Standard_True);
665 if (MVDEI.IsBound( CV )) { // CE comes to the degeneration
667 TopoDS_Edge NewDegen;
668 NewDegen = MakeDegenAndSelect( CE, CV, NE, SEID[iDeg], SeqU[iDeg], DE[iDeg]);
669 B.Add( NW, NewDegen );
670 End = CV.IsSame( VF );
672 if (!NE.IsNull()) { // remove NE from WEL
673 for (itl.Initialize( WEL ); itl.More(); itl.Next())
674 if ( NE == itl.Value()) {
679 } // end degeneration
682 if (CV.IsSame( VF )) {
686 // edges in WEL most often are well ordered
687 // so try to iterate until the End
688 Standard_Boolean add = Standard_False;
690 while ( itl.More() && !End) {
691 NE = TopoDS::Edge( itl.Value() );
692 if ( CV.IsSame( TopExp::FirstVertex( NE, Standard_True ))) {
698 CV = TopExp::LastVertex( CE, Standard_True);
699 if (MVDEI.IsBound( CV ) || CV.IsSame( VF ))
710 myInternalWL.Append( NW );
712 } // end building new wire(s) from WEL
716 // all wires are built
719 // ============================================================
720 // select really internal wires i.e. those from which we can`t
721 // pass to an old (not section) edge
722 // ============================================================
724 Standard_Integer nbIW = myInternalWL.Extent();
726 TopTools_MapOfShape UsedShapes( 2*NbConstEdges );
727 TopExp_Explorer expV (myInternalWL.First(), TopAbs_VERTEX);
728 if (canPassToOld (expV.Current(), UsedShapes, MVE2, mySectionEdges))
729 myNewWires.Append ( myInternalWL );
731 else if ( nbIW > 1 ) {
732 TopTools_MapOfShape outerEM (NbConstEdges); // edges connected to non-section ones
733 TopTools_MapOfShape visitedVM (NbConstEdges);
734 for ( itl.Initialize( myConstEdges ); itl.More(); itl.Next()) {
735 if ( ! mySectionEdges.Contains( itl.Value() ))
736 addConnected (itl.Value(), outerEM, visitedVM, MVE2);
738 // if an edge of a wire is in <outerEM>, the wire is not internal
739 TopExp_Explorer expIWE;
740 TopTools_ListIteratorOfListOfShape itIW ( myInternalWL );
741 while (itIW.More()) {
742 expIWE.Init ( itIW.Value() , TopAbs_EDGE );
743 if ( outerEM.Contains( expIWE.Current() )) {
744 myNewWires.Append ( itIW.Value() );
745 myInternalWL.Remove( itIW ); // == itIW.Next()
752 //=======================================================================
755 //=======================================================================
757 static Standard_Boolean isHole (const TopoDS_Wire& W,
758 const TopoDS_Face& F)
761 TopoDS_Shape newFace = F.EmptyCopied();
762 B.Add(newFace,W.Oriented(TopAbs_FORWARD));
763 BRepTopAdaptor_FClass2d classif (TopoDS::Face(newFace),
764 Precision::PConfusion());
765 return (classif.PerformInfinitePoint() == TopAbs_IN);
768 //=======================================================================
769 //function : IsInside
770 //purpose : check if W1 is inside W2. Suppose W2 is not a hole !!!!
771 //=======================================================================
773 static Standard_Boolean isInside(const TopoDS_Face& F,
774 const TopoDS_Wire& W1,
775 const TopoDS_Wire& W2)
777 // make a face with wire W2
779 TopoDS_Shape aLocalShape = F.EmptyCopied();
780 TopoDS_Face newFace = TopoDS::Face(aLocalShape);
783 // get any 2d point of W1
784 TopExp_Explorer exp(W1,TopAbs_EDGE);
785 const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
787 Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(edg,F,f,l);
788 gp_Pnt2d pt2d(C2d->Value(f));
790 BRepTopAdaptor_FClass2d classif(newFace,Precision::PConfusion());
791 return (classif.Perform(pt2d) == TopAbs_IN);
794 //=======================================================================
795 //function : NewWires
796 //purpose : Returns the list of wires performed.
797 // can be an empty list.
798 //=======================================================================
800 const TopTools_ListOfShape& Partition_Loop2d::NewWires() const
805 //=======================================================================
806 //function : NewFaces
807 //purpose : Returns the list of faces.
808 //Warning : The method <WiresToFaces> as to be called before.
809 // can be an empty list.
810 //=======================================================================
812 const TopTools_ListOfShape& Partition_Loop2d::NewFaces() const
817 //=======================================================================
818 //function : findEqual
819 //purpose : move wires form <WL> to <EqWL> pairs of wires build of the same edges
820 //=======================================================================
822 static void findEqual (TopTools_ListOfShape& WL,
823 TopTools_DataMapOfShapeShape& EqWM,
824 const TopoDS_Face& F)
826 TopTools_ListIteratorOfListOfShape it1, it2;
827 Standard_Integer i,j;
828 TColStd_MapOfInteger IndMap;
829 for (it1.Initialize(WL), i=1; it1.More(); it1.Next(), i++) {
831 if (IndMap.Contains(i)) continue;
832 const TopoDS_Wire& Wire1 = TopoDS::Wire( it1.Value());
834 for (it2.Initialize(WL), j=1; it2.More(); it2.Next(), j++) {
836 if (j <= i || IndMap.Contains(j)) continue;
838 TopTools_IndexedMapOfShape EdgesMap;
839 TopExp::MapShapes (Wire1, TopAbs_EDGE, EdgesMap);
841 const TopoDS_Shape& Wire2 = it2.Value();
842 TopoDS_Iterator itE ( Wire2);
843 for (; itE.More(); itE.Next()) {
844 if ( !EdgesMap.Contains( itE.Value()) )
847 if (!itE.More()) { // all edges are same
848 if (isHole( Wire1, F)) {
849 EqWM.Bind ( Wire1, Wire2 );
852 EqWM.Bind ( Wire2, Wire1 );
864 if (IndMap.Contains(i))
865 WL.Remove(it1); // next node becomes current and with Next() we would miss it
872 //=======================================================================
873 //function : classify
874 //purpose : bind to a wire a list of internal wires
875 //=======================================================================
877 static void classify(const TopTools_DataMapOfShapeShape& EqWM,
878 BRepAlgo_AsDes& OuterInner,
879 const TopoDS_Face& F)
881 TopTools_DataMapIteratorOfDataMapOfShapeShape it1, it2;
883 for (it1.Initialize(EqWM); it1.More(); it1.Next()) {
884 for (it2.Initialize(EqWM); it2.More(); it2.Next()) {
885 if (it1.Value().IsSame( it2.Value() )) continue;
886 const TopoDS_Wire& Wire1 = TopoDS::Wire( it1.Value() );
887 const TopoDS_Wire& Wire2 = TopoDS::Wire( it2.Value() );
888 if (isInside(F, Wire1, Wire2))
889 OuterInner.Add (Wire2, Wire1);
890 else if (isInside(F, Wire2, Wire1))
891 OuterInner.Add (Wire1, Wire2);
895 //=======================================================================
896 //function : WiresToFaces
897 //purpose : Build faces from the wires result.
898 // <EdgeImage> serves to find original edge by new
899 // one. <Section> contains edges resulting from face
901 //=======================================================================
903 //#define USE_BREPFEAT_SPLITSHAPE
905 #ifdef USE_BREPFEAT_SPLITSHAPE
907 # include <BRepFeat_SplitShape.hxx>
908 void Partition_Loop2d::WiresToFaces(const BRepAlgo_Image& EdgeImage)
911 # include <BRepAlgo_FaceRestrictor.hxx>
912 void Partition_Loop2d::WiresToFaces(const BRepAlgo_Image& )
915 Standard_Integer nbW = myNewWires.Extent() + myInternalWL.Extent();
919 #ifndef USE_BREPFEAT_SPLITSHAPE
921 // ============================================================
922 // use BRepAlgo_FaceRestrictor to make faces
923 // ============================================================
925 BRepAlgo_FaceRestrictor FR;
926 FR.Init (myFace,Standard_False);
928 // FaceRestrictor is instable in rather simple cases
929 // (ex. a single face of bellecoque.brep splited by 10 planes:
930 // sometimes 1-2 faces are missing ).
931 // So we use it as less as possible: no holes -> make faces by hands
934 // are there holes in myFace ?
935 Standard_Boolean hasOldHoles = Standard_False;
936 TopoDS_Iterator itOldW (myFace);
937 if ( itOldW.More()) {
938 const TopoDS_Wire& FirstOldWire = TopoDS::Wire( itOldW.Value() );
940 hasOldHoles = itOldW.More() || isHole( FirstOldWire, myFace);
942 if (myInternalWL.IsEmpty() && !hasOldHoles) {
943 // each wire bounds one face
945 TopTools_ListIteratorOfListOfShape itNW (myNewWires);
946 for (; itNW.More(); itNW.Next()) {
947 TopoDS_Face NF = TopoDS::Face ( myFace.EmptyCopied() );
948 B.Add ( NF, itNW.Value() );
949 NF.Orientation( myFaceOri);
950 myNewFaces.Append ( NF );
955 // FaceRestrictor can't classify wires build on all the same edges
956 // and gives incorrect result in such cases (ex. a plane cut into 2 parts by cylinder)
957 // We must make faces of equal wires separately. One of equal wires makes a
958 // hole in a face and should come together with outer wires of face.
959 // The other of a wires pair bounds a face that may have holes in turn.
961 // Find equal wires among internal wires
962 TopTools_DataMapOfShapeShape EqWM; // key is a hole part of a pair of equal wires
963 findEqual (myInternalWL, EqWM, myFace);
965 if (!EqWM.IsEmpty()) { // there are equal wires
968 myInternalWL.Append( myNewWires ); // an old wire can be inside an equal wire
970 // classify equal wire pairs
971 BRepAlgo_AsDes OuterInner;
972 classify (EqWM,OuterInner,myFace);
974 // make face of most internal of equal wires and its inner wires
975 while ( !EqWM.IsEmpty()) {
977 TopTools_ListOfShape prevHolesL; // list of hole-part of previous most internal equal wires
979 // find most internal wires among pairs (key - hole, value - outer part)
980 TopTools_DataMapIteratorOfDataMapOfShapeShape it(EqWM);
981 for ( ; it.More(); it.Next()) {
983 TopoDS_Wire outerW = TopoDS::Wire ( it.Value() );
984 if ( OuterInner.HasDescendant( outerW ) && // has internal
985 ! OuterInner.Descendant( outerW ).IsEmpty() )
990 // add internal wires that are inside of outerW
991 TopTools_ListIteratorOfListOfShape itIW (myInternalWL);
992 while ( itIW.More()) {
993 TopoDS_Wire IW = TopoDS::Wire ( itIW.Value() );
994 if ( isInside (myFace, IW, outerW)) {
996 myInternalWL.Remove( itIW ); // == itIW.Next() !!!
1002 // the hole-part of current pair of equal wires will be in the next new face
1003 prevHolesL.Append ( it.Key() );
1005 } // Loop on map of equal pairs searching for innermost wires
1010 for (; FR.More(); FR.Next())
1011 myNewFaces.Append(FR.Current());
1016 // add hole-parts to FaceRestrictor,
1017 // remove themfrom the EqWM,
1018 // remove found wires as internal of resting classified wires
1019 Standard_Boolean clearOuterInner = ( prevHolesL.Extent() < EqWM.Extent() );
1020 TopTools_ListIteratorOfListOfShape itPrev (prevHolesL);
1021 for (; itPrev.More(); itPrev.Next()) {
1022 TopoDS_Wire& Hole = TopoDS::Wire ( itPrev.Value() );
1024 if (clearOuterInner) {
1025 const TopoDS_Wire& outerW = TopoDS::Wire ( EqWM.Find( Hole ) );
1026 // Loop on wires including outerW
1027 TopTools_ListIteratorOfListOfShape itO( OuterInner.Ascendant( outerW ));
1028 for (; itO.More(); itO.Next()) {
1029 TopTools_ListOfShape& innerL = OuterInner.ChangeDescendant( itO.Value() );
1030 TopTools_ListIteratorOfListOfShape itI (innerL);
1031 // Loop on internal wires of current including wire
1032 for (; itI.More(); itI.Next())
1033 if ( outerW.IsSame( itI.Value() )) {
1034 innerL.Remove( itI ); break;
1038 EqWM.UnBind ( Hole );
1041 } // while (!EqWM.IsEmpty)
1043 } // !EqWM.IsEmpty()
1045 myNewWires.Append ( myInternalWL );
1047 TopTools_ListIteratorOfListOfShape itW (myNewWires);
1048 for (; itW.More(); itW.Next()) {
1049 TopoDS_Wire& W = TopoDS::Wire ( itW.Value() );
1053 for (; FR.IsDone() && FR.More(); FR.Next())
1054 myNewFaces.Append(FR.Current());
1058 #else // ifndef USE_BREPFEAT_SPLITSHAPE
1060 // ============================================================
1061 // use BRepFeat_SplitShape to make faces
1062 // ============================================================
1064 BRepFeat_SplitShape Split(myFace);
1065 TopTools_MapOfShape AddedSectionEdgesMap;
1067 myNewWires.Append(myInternalWL);
1069 TopTools_ListIteratorOfListOfShape it(myNewWires);
1070 for (; it.More(); it.Next()) {
1071 TopoDS_Iterator itE(it.Value());
1072 for (; itE.More(); itE.Next()) {
1073 const TopoDS_Edge& newE = TopoDS::Edge( itE.Value() );
1074 if (AddedSectionEdgesMap.Add(newE)) {
1075 if (mySectionEdges.Contains(newE))
1076 Split.Add(newE,F); // new edge on face
1078 const TopoDS_Edge& oldE = TopoDS::Edge( EdgeImage.ImageFrom(newE) );
1079 Split.Add(newE, oldE); // splited edge
1087 myNewFaces = Split.Modified(F);
1089 #endif // ifndef USE_BREPFEAT_SPLITSHAPE
1094 Standard_Integer nbF = myNewFaces.Extent();
1096 cout << "WiresToFaces(): " << nbW << " wires --> " << myNewFaces.Extent() << " faces "
1100 TopTools_ListIteratorOfListOfShape itNF (myNewFaces);
1101 for (; itNF.More(); itNF.Next())
1102 itNF.Value().Orientation( myFaceOri );