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