Salome HOME
b5a343347eff6c47a7094f3622e6b7a8e6a8a76a
[modules/geom.git] / src / PARTITION / Partition_Loop.cxx
1 using namespace std;
2 //  File      : Partition_Loop.cxx
3 //  Created   : Thu Aug 02 16:25:17 2001
4 //  Author    : Benedicte MARTIN
5 //  Project   : SALOME
6 //  Module    : PARTITION
7 //  Copyright : Open CASCADE
8 //  $Header$
9
10 #include <stdio.h>
11
12 #include "Partition_Loop.ixx"
13
14 #include "utilities.h"
15
16 #include <BRep_Builder.hxx>
17 #include <BRepAlgo_FaceRestrictor.hxx>
18 #include <BRep_Tool.hxx>
19
20 #include <Geom2d_Curve.hxx>
21 #include <Geom_Surface.hxx>
22
23 #include <TopTools_SequenceOfShape.hxx>
24 #include <TopTools_ListIteratorOfListOfShape.hxx>
25 #include <TopTools_MapOfShape.hxx>
26 #include <TopTools_MapIteratorOfMapOfShape.hxx>
27 #include <TopTools_MapOfOrientedShape.hxx>
28 #include <TopTools_DataMapOfShapeShape.hxx>
29 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
30
31 #include <gp_Pnt.hxx>
32 #include <gp_Pnt2d.hxx>
33
34 #include <TopoDS.hxx>
35 #include <TopoDS_Vertex.hxx>
36 #include <TopoDS_Wire.hxx>
37 #include <TopoDS_Iterator.hxx>
38
39 #include <Precision.hxx>
40 #include <BRep_TVertex.hxx>
41 #include <BRep_TEdge.hxx>
42
43 #include <TopExp.hxx>
44 #include <TopExp_Explorer.hxx>
45
46 static char* name = new char[100];
47 static int nbe = 0;
48
49 //=======================================================================
50 //function : Partition_Loop
51 //purpose  : 
52 //=======================================================================
53 Partition_Loop::Partition_Loop()
54 {
55 }
56
57 //=======================================================================
58 //function : Init
59 //purpose  : 
60 //=======================================================================
61 void Partition_Loop::Init(const TopoDS_Face& F)
62 {
63   myConstEdges.Clear(); 
64   myNewWires  .Clear();
65   myNewFaces  .Clear();
66   myFace = F;
67 }
68
69 //=======================================================================
70 //function : AddConstEdge
71 //purpose  : 
72 //=======================================================================
73 void Partition_Loop::AddConstEdge (const TopoDS_Edge& E)
74 {
75   myConstEdges.Append(E);
76 }
77
78
79 //=======================================================================
80 //function : FindDelta
81 //purpose  : 
82 //=======================================================================
83 static Standard_Real FindDelta(TopTools_ListOfShape& LE,
84                                const TopoDS_Face& F)
85 {
86   Standard_Real dist, f, l;
87   Standard_Real d = Precision::Infinite();
88   TopTools_ListIteratorOfListOfShape itl;
89
90   for ( itl.Initialize(LE); itl.More(); itl.Next()) {
91     const TopoDS_Edge& E = TopoDS::Edge(itl.Value());
92     Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(E,F,f,l);
93     gp_Pnt2d p = C->Value(f);
94     gp_Pnt2d pp = C->Value(l);
95     Standard_Real d1 = p.Distance(pp);
96     if (d1<d) { d=d1;}
97   }
98   dist = d ;
99   return dist;
100 }
101
102 //=======================================================================
103 //function : SelectEdge
104 //purpose  : Find the edge <NE> connected <CE> by the vertex <CV> in the list <LE>.
105 //           <NE> Is erased  of the list. If <CE> is too in the list <LE> 
106 //                       with the same orientation, it's erased of the list 
107 //=======================================================================
108 static Standard_Boolean  SelectEdge(const TopoDS_Face&    F,
109                                     const TopoDS_Edge&    CE,
110                                     const TopoDS_Vertex&  CV,
111                                     TopoDS_Edge&          NE,
112                                     TopTools_ListOfShape& LE)
113 {
114   TopTools_ListIteratorOfListOfShape itl;
115   NE.Nullify();
116   for ( itl.Initialize(LE); itl.More(); itl.Next()) {
117     if (itl.Value().IsEqual(CE)) {
118       LE.Remove(itl);
119       break;
120     }
121   }
122
123   if (LE.Extent() > 1) {
124     //--------------------------------------------------------------
125     // Several possible edges.   
126     // - Test the edges differents of CE 
127     //--------------------------------------------------------------
128     Standard_Real   cf, cl, f, l;
129     TopoDS_Face FForward = F;
130     Handle(Geom2d_Curve) Cc, C;
131     FForward.Orientation(TopAbs_FORWARD);
132                         
133     Cc = BRep_Tool::CurveOnSurface(CE,FForward,cf,cl);
134     Standard_Real dist,distmin  = 100*BRep_Tool::Tolerance(CV);
135     Standard_Real uc,u;
136     if (CE.Orientation () == TopAbs_FORWARD) uc = cl;
137     else                                     uc = cf;
138
139     gp_Pnt2d P2,PV = Cc->Value(uc); 
140
141     Standard_Real delta = FindDelta(LE,FForward);
142
143     for ( itl.Initialize(LE); itl.More(); itl.Next()) {
144       const TopoDS_Edge& E = TopoDS::Edge(itl.Value());
145       if (!E.IsSame(CE)) {
146         C = BRep_Tool::CurveOnSurface(E,FForward,f,l);
147         if (E.Orientation () == TopAbs_FORWARD) u = f;
148         else                                    u = l;
149         P2 = C->Value(u);
150         dist = PV.Distance(P2);
151         if (dist <= distmin){
152           distmin = dist;
153         }
154                                 
155       }
156     }
157
158     Standard_Real anglemax = - PI;
159     TopoDS_Edge   SelectedEdge; 
160     for ( itl.Initialize(LE); itl.More(); itl.Next()) {
161       const TopoDS_Edge& E = TopoDS::Edge(itl.Value());
162       if (!E.IsSame(CE)) {
163         C = BRep_Tool::CurveOnSurface(E,FForward,f,l);
164         if (E.Orientation () == TopAbs_FORWARD) u = f;
165         else                                    u = l;
166         P2 = C->Value(u);
167         dist = PV.Distance(P2);
168         if (dist <= distmin + (1./3)*delta){ 
169           gp_Pnt2d PC, P;
170           gp_Vec2d CTg1, CTg2, Tg1, Tg2;
171           Cc->D2(uc, PC, CTg1, CTg2);
172           C->D2(u, P, Tg1, Tg2);
173
174           Standard_Real angle;
175
176           if (CE.Orientation () == TopAbs_REVERSED && E.Orientation () == TopAbs_FORWARD) {
177             angle = CTg1.Angle(Tg1.Reversed());
178           }
179           else if (CE.Orientation () == TopAbs_FORWARD && E.Orientation () == TopAbs_REVERSED) {
180             angle = (CTg1.Reversed()).Angle(Tg1);
181           }
182           else if (CE.Orientation () == TopAbs_REVERSED && E.Orientation () == TopAbs_REVERSED) {
183             angle = CTg1.Angle(Tg1);
184           }
185           else if (CE.Orientation () == TopAbs_FORWARD && E.Orientation () == TopAbs_FORWARD) {
186             angle = (CTg1.Reversed()).Angle(Tg1.Reversed());
187           }
188           if (angle >= anglemax) {
189             anglemax = angle ;
190             SelectedEdge = E;   
191           }
192         }
193       }
194     }
195     for ( itl.Initialize(LE); itl.More(); itl.Next()) {
196       const TopoDS_Edge& E = TopoDS::Edge(itl.Value());
197       if (E.IsEqual(SelectedEdge)) {
198         NE = TopoDS::Edge(E);
199         LE.Remove(itl);
200         break;
201       }
202     }                                   
203   }
204   else if (LE.Extent() == 1) {
205     NE = TopoDS::Edge(LE.First());
206     LE.RemoveFirst();
207   }
208   else {
209     return Standard_False;
210   }
211   return Standard_True;
212 }
213
214 //=======================================================================
215 //function : SamePnt2d
216 //purpose  : 
217 //=======================================================================
218 static Standard_Boolean  SamePnt2d(TopoDS_Vertex  V,
219                                    TopoDS_Edge&   E1,
220                                    TopoDS_Edge&   E2,
221                                    TopoDS_Face&   F)
222 {
223   Standard_Real   f1,f2,l1,l2;
224   gp_Pnt2d        P1,P2;
225   TopoDS_Shape aLocalF = F.Oriented(TopAbs_FORWARD);
226   TopoDS_Face FF = TopoDS::Face(aLocalF);
227   Handle(Geom2d_Curve) C1 = BRep_Tool::CurveOnSurface(E1,FF,f1,l1);  
228   Handle(Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(E2,FF,f2,l2);  
229   if (E1.Orientation () == TopAbs_FORWARD) P1 = C1->Value(f1);
230   else                                     P1 = C1->Value(l1);
231   
232   if (E2.Orientation () == TopAbs_FORWARD) P2 = C2->Value(l2);
233   else                                     P2 = C2->Value(f2);
234   Standard_Real Tol  = 100*BRep_Tool::Tolerance(V);
235   Standard_Real Dist = P1.Distance(P2);
236   return Dist < Tol; 
237 }
238
239 //=======================================================================
240 //function : PurgeNewEdges
241 //purpose  : 
242 //=======================================================================
243 static void  PurgeNewEdges(TopTools_ListOfShape& ConstEdges,
244                            const TopTools_MapOfOrientedShape&          UsedEdges)
245 {
246   TopTools_ListIteratorOfListOfShape it(ConstEdges);
247   while ( it.More()) {
248     const TopoDS_Shape& NE = it.Value();
249     if (!UsedEdges.Contains(NE)) {
250       ConstEdges.Remove(it);
251     }
252     else {
253       it.Next();
254     }
255   }  
256 }
257
258 //=======================================================================
259 //function : StoreInMVE
260 //purpose  : 
261 //=======================================================================
262 static void StoreInMVE (const TopoDS_Face& F,
263                         TopoDS_Edge& E,
264                         TopTools_DataMapOfShapeListOfShape& MVE )
265
266
267   TopoDS_Vertex V1, V2;
268   TopTools_ListOfShape Empty;
269
270   TopExp::Vertices(E,V1,V2);
271   if (!MVE.IsBound(V1)) {
272     MVE.Bind(V1,Empty);
273   }
274   MVE(V1).Append(E);
275         
276   if (!MVE.IsBound(V2)) {
277     MVE.Bind(V2,Empty);
278   }
279   MVE(V2).Append(E);
280 }
281
282 //=======================================================================
283 //function : Perform
284 //purpose  : 
285 //=======================================================================
286 void Partition_Loop::Perform()
287 {
288
289   TopTools_DataMapOfShapeListOfShape MVE;
290   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape Mapit, Mapit1;  
291   TopTools_ListIteratorOfListOfShape                  itl;
292   TopoDS_Vertex                                       V1,V2;
293
294   //-----------------------------------
295   // Construction map vertex => edges
296   //-----------------------------------
297   for (itl.Initialize(myConstEdges); itl.More(); itl.Next()) {
298     TopoDS_Edge& E = TopoDS::Edge(itl.Value());
299     StoreInMVE(myFace,E,MVE);
300   }
301
302   //----------------------------------------------
303   // Construction of all the wires and of all the new faces. 
304   //----------------------------------------------
305   TopTools_MapOfOrientedShape UsedEdges;
306
307   while (!MVE.IsEmpty()) {
308     TopoDS_Vertex    VF,CV;
309     TopoDS_Edge      CE,NE,EF;
310     TopoDS_Wire      NW;
311     BRep_Builder     B;
312     Standard_Boolean End= Standard_False;
313
314     B.MakeWire(NW);
315     //--------------------------------
316     // EF first edge.
317     //--------------------------------
318     Mapit.Initialize(MVE);
319     EF = CE = TopoDS::Edge(Mapit.Value().First());
320
321     TopExp::Vertices(CE,V1,V2);
322     //--------------------------------
323     // VF first vertex 
324     //--------------------------------
325     if (CE.Orientation() == TopAbs_FORWARD) { 
326       CV = VF = V1;
327     }
328     else  { 
329       CV = VF = V2;
330     }
331     if (!MVE.IsBound(CV)) continue;
332     for ( itl.Initialize(MVE(CV)); itl.More(); itl.Next()) {
333       if (itl.Value().IsEqual(CE)) {
334         MVE(CV).Remove(itl);
335         break;
336       }
337     }
338
339     int i = 0;
340     while (!End) { 
341       //-------------------------------
342       // Construction of a wire.
343       //-------------------------------
344       TopExp::Vertices(CE,V1,V2);
345       if (!CV.IsSame(V1)) CV = V1; else CV = V2; 
346       B.Add (NW,CE);
347       UsedEdges.Add(CE);
348
349       //--------------
350       // stop test
351       //--------------                  
352       if (!MVE.IsBound(CV) || MVE(CV).IsEmpty() || CV.IsSame(VF) ) {
353         if (CV.IsSame(VF)) {
354           if (MVE(CV).Extent() == 1 ) MVE.UnBind(CV);
355           else {
356             for ( itl.Initialize(MVE(CV)); itl.More(); itl.Next()) {
357               if (itl.Value().IsEqual(CE)) {
358                 MVE(CV).Remove(itl);
359                 break;
360               }
361             }
362           }
363         }
364         End=Standard_True;
365       } 
366
367       //--------------
368       // select edge
369       //--------------
370       else {
371         Standard_Boolean find = SelectEdge(myFace,CE,CV,NE,MVE(CV));
372         if (find) {
373           CE=NE;
374           if (MVE(CV).IsEmpty()) MVE.UnBind(CV);
375           if (CE.IsNull() ) {
376             MESSAGE ( " CE is  NULL !!! " )
377             End=Standard_True;
378           }
379         }
380         else {
381           MESSAGE ( " edge doesn't exist " )
382           End=Standard_True;
383         }
384       }
385     }
386
387     //-----------------------------
388     // Test if the wire is closed  
389     //-----------------------------
390     if (VF.IsSame(CV) && SamePnt2d(VF,EF,CE,myFace)) {
391     }
392     else{
393       MESSAGE ( "wire not closed" )
394     }
395     myNewWires.Append (NW);                     
396   }
397
398   PurgeNewEdges(myConstEdges,UsedEdges);
399
400 }
401
402
403 //=======================================================================
404 //function : NewWires
405 //purpose  : 
406 //=======================================================================
407 const TopTools_ListOfShape&  Partition_Loop::NewWires() const 
408 {  
409   return myNewWires;
410 }
411
412 //=======================================================================
413 //function : NewFaces
414 //purpose  : 
415 //=======================================================================
416 const TopTools_ListOfShape&  Partition_Loop::NewFaces() const 
417 {  
418   return myNewFaces;
419 }
420  
421 //=======================================================================
422 //function : WiresToFaces
423 //purpose  : 
424 //=======================================================================
425 void  Partition_Loop::WiresToFaces() 
426 {  
427   if (!myNewWires.IsEmpty()) {
428     BRepAlgo_FaceRestrictor FR;
429
430     TopAbs_Orientation OriF = myFace.Orientation();
431     TopoDS_Shape aLocalS = myFace.Oriented(TopAbs_FORWARD);
432
433     FR.Init (TopoDS::Face(aLocalS),Standard_False);
434     TopTools_ListIteratorOfListOfShape it(myNewWires);
435     for (; it.More(); it.Next()) {
436       FR.Add(TopoDS::Wire(it.Value()));
437     }
438
439     FR.Perform();
440     
441     if (FR.IsDone()) {
442       for (; FR.More(); FR.Next()) {
443         myNewFaces.Append(FR.Current().Oriented(OriF));
444       }
445     }
446   }
447 }