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