Integration of OCCT 6.5.0 from SVN
[occt.git] / src / BRepLib / BRepLib_MakeWire.cxx
1 // File:        BRepLib_MakeWire.cxx
2 // Created:     Fri Jul 23 15:51:57 1993
3 // Author:      Remi LEQUETTE
4 //              <rle@nonox>
5
6
7 #include <BRepLib_MakeWire.ixx>
8 #include <BRepLib.hxx>
9 #include <BRepLib_MakeEdge.hxx>
10 #include <BRep_Tool.hxx>
11 #include <BRep_Builder.hxx>
12 #include <TopExp.hxx>
13 #include <TopExp_Explorer.hxx>
14 #include <TopTools_MapOfShape.hxx>
15 #include <TopTools_MapIteratorOfMapOfShape.hxx>
16 #include <TopoDS.hxx>
17 #include <TopoDS_Iterator.hxx>
18 #include <gp_Pnt.hxx>
19 #include <Geom_Curve.hxx>
20 #include <gp.hxx>
21
22
23 //=======================================================================
24 //function : BRepLib_MakeWire
25 //purpose  : 
26 //=======================================================================
27
28 BRepLib_MakeWire::BRepLib_MakeWire() :
29      myError(BRepLib_EmptyWire)
30 {
31 }
32
33
34 //=======================================================================
35 //function : BRepLib_MakeWire
36 //purpose  : 
37 //=======================================================================
38
39 BRepLib_MakeWire::BRepLib_MakeWire(const TopoDS_Edge& E)
40 {
41   Add(E);
42 }
43
44
45 //=======================================================================
46 //function : BRepLib_MakeWire
47 //purpose  : 
48 //=======================================================================
49
50 BRepLib_MakeWire::BRepLib_MakeWire(const TopoDS_Edge& E1, 
51                                    const TopoDS_Edge& E2)
52 {
53   Add(E1);
54   Add(E2);
55 }
56
57
58 //=======================================================================
59 //function : BRepLib_MakeWire
60 //purpose  : 
61 //=======================================================================
62
63 BRepLib_MakeWire::BRepLib_MakeWire(const TopoDS_Edge& E1,
64                                    const TopoDS_Edge& E2, 
65                                    const TopoDS_Edge& E3)
66 {
67   Add(E1);
68   Add(E2);
69   Add(E3);
70 }
71
72
73 //=======================================================================
74 //function : BRepLib_MakeWire
75 //purpose  : 
76 //=======================================================================
77
78 BRepLib_MakeWire::BRepLib_MakeWire(const TopoDS_Edge& E1, 
79                                    const TopoDS_Edge& E2,
80                                    const TopoDS_Edge& E3, 
81                                    const TopoDS_Edge& E4)
82 {
83   Add(E1);
84   Add(E2);
85   Add(E3);
86   Add(E4);
87 }
88
89
90 //=======================================================================
91 //function : BRepLib_MakeWire
92 //purpose  : 
93 //=======================================================================
94
95 BRepLib_MakeWire::BRepLib_MakeWire(const TopoDS_Wire& W)
96 {
97   Add(W);
98 }
99
100
101 //=======================================================================
102 //function : BRepLib_MakeWire
103 //purpose  : 
104 //=======================================================================
105
106 BRepLib_MakeWire::BRepLib_MakeWire(const TopoDS_Wire& W, 
107                                    const TopoDS_Edge& E)
108 {
109   Add(W);
110   Add(E);
111 }
112
113
114 //=======================================================================
115 //function : Add
116 //purpose  : 
117 //=======================================================================
118
119 void  BRepLib_MakeWire::Add(const TopoDS_Wire& W)
120 {
121   TopExp_Explorer ex(W,TopAbs_EDGE);
122   while (ex.More()) {
123     Add(TopoDS::Edge(ex.Current()));
124     ex.Next();
125   }
126 }
127
128 //=======================================================================
129 //function : Add
130 //purpose  : 
131 // PMN  19/03/1998  Pour des Probleme de performances on n'utilise pas
132 //                  TopExp::Vertices sur des wire
133 // PMN  10/09/1998  Dans le cas ou le wire est precedament ferme (ou degenere) 
134 //                  on emploie quand meme TopExp::Vertices ... Afin de lever
135 //                  les ambiguites.
136 //=======================================================================
137
138 void  BRepLib_MakeWire::Add(const TopoDS_Edge& E)
139 {
140
141   Standard_Boolean forward = Standard_False; 
142      // pour dire si on decider d'ajouter forward
143   Standard_Boolean reverse = Standard_False; 
144      // pour dire si on decide d'ajouter reversed
145   Standard_Boolean init = Standard_False;
146      // Pour savoir s'il on doit calculer VL, VF
147   BRep_Builder B;
148   TopoDS_Iterator it;
149
150   if (myEdge.IsNull()) {
151     init = Standard_True;
152     // first edge, create the wire
153     B.MakeWire(TopoDS::Wire(myShape));
154
155     // set the edge
156     myEdge = E;
157
158     // add the vertices
159     for (it.Initialize(myEdge); it.More(); it.Next()) 
160       myVertices.Add(it.Value());
161   }
162   
163   else {
164     init = myShape.Closed(); // Si c'est ferme, on ne controle
165     TopoDS_Shape aLocalShape = E.Oriented(TopAbs_FORWARD);
166     TopoDS_Edge EE = TopoDS::Edge(aLocalShape);
167 //    TopoDS_Edge EE = TopoDS::Edge(E.Oriented(TopAbs_FORWARD));
168
169     // test the vertices of the edge
170     
171     Standard_Boolean connected = Standard_False;
172     Standard_Boolean copyedge  = Standard_False;
173     
174     if (myError != BRepLib_NonManifoldWire) {
175       if (VF.IsNull() || VL.IsNull()) 
176         myError = BRepLib_NonManifoldWire;
177     }
178
179     for (it.Initialize(EE); it.More(); it.Next()) {
180
181       const TopoDS_Vertex& VE = TopoDS::Vertex(it.Value());
182
183       // if the vertex is in the wire, ok for the connection
184       if (myVertices.Contains(VE)) {
185         connected = Standard_True;
186         myVertex = VE;
187         if (myError != BRepLib_NonManifoldWire) {
188           // l est on toujours ?
189           if (VF.IsSame(VL)) {
190             // Orientation indetermine (en 3d) : On garde l'init
191             if (!VF.IsSame(VE)) myError = BRepLib_NonManifoldWire;
192           }
193           else {
194             if (VF.IsSame(VE)) {
195               if  (VE.Orientation() == TopAbs_FORWARD) 
196                 reverse = Standard_True;
197               else 
198                 forward = Standard_True;
199             }
200             else if (VL.IsSame(VE)) {
201               if (VE.Orientation() == TopAbs_REVERSED)
202                 reverse = Standard_True;
203               else 
204                 forward = Standard_True;
205             }
206             else 
207               myError = BRepLib_NonManifoldWire;
208           }
209         }
210       }
211       else {
212           // search if there is a similar vertex in the edge    
213         gp_Pnt PE = BRep_Tool::Pnt(VE);
214         
215 //      Standard_Boolean newvertex = Standard_False;
216         TopTools_MapIteratorOfMapOfShape itm(myVertices);
217         while (itm.More()) {
218           
219           const TopoDS_Vertex& VW = TopoDS::Vertex(itm.Key());
220           gp_Pnt PW = BRep_Tool::Pnt(VW);
221           Standard_Real l = PE.Distance(PW);
222           
223           if ((l < BRep_Tool::Tolerance(VE)) ||
224               (l < BRep_Tool::Tolerance(VW))) {
225             copyedge = Standard_True;
226             if (myError != BRepLib_NonManifoldWire) {
227               // l est on toujours ?
228               if (VF.IsSame(VL)) {
229                 // Orientation indetermine (en 3d) : On garde l'init
230                 if (!VF.IsSame(VW)) myError = BRepLib_NonManifoldWire;
231               }
232               else {
233                 if (VF.IsSame(VW)) {
234                  if  (VE.Orientation() == TopAbs_FORWARD) 
235                    reverse = Standard_True;
236                  else 
237                    forward = Standard_True; 
238                 }
239                 else if (VL.IsSame(VW)) { 
240                   if (VE.Orientation() == TopAbs_REVERSED)
241                     reverse = Standard_True;
242                   else 
243                     forward = Standard_True;
244                 }
245                 else 
246                   myError = BRepLib_NonManifoldWire;
247               }
248             }      
249             break;
250           }
251           itm.Next();
252         }
253         if (copyedge) {
254           connected = Standard_True;
255         }
256       }
257     }
258     
259     if (!connected) {
260       myError = BRepLib_DisconnectedWire;
261       NotDone();
262       return;
263     }
264     else {
265       if (!copyedge) {
266         myEdge = EE;
267         for (it.Initialize(EE); it.More(); it.Next())
268           myVertices.Add(it.Value());
269       }
270       else {
271         // copy the edge
272         TopoDS_Shape Dummy = EE.EmptyCopied();
273         myEdge = TopoDS::Edge(Dummy);
274         myEdge.Closed(EE.Closed());
275         
276         for (it.Initialize(EE); it.More(); it.Next()) {
277
278           const TopoDS_Vertex& VE = TopoDS::Vertex(it.Value());
279           gp_Pnt PE = BRep_Tool::Pnt(VE);
280           
281           Standard_Boolean newvertex = Standard_False;
282           TopTools_MapIteratorOfMapOfShape itm(myVertices);
283           while (itm.More()) {
284           
285             const TopoDS_Vertex& VW = TopoDS::Vertex(itm.Key());
286             gp_Pnt PW = BRep_Tool::Pnt(VW);
287             Standard_Real l = PE.Distance(PW), tolE, tolW;
288             tolW = BRep_Tool::Tolerance(VW);
289             tolE = BRep_Tool::Tolerance(VE);
290             
291             if ((l < tolE) || (l < tolW)) {
292
293               Standard_Real maxtol = .5*(tolW + tolE + l), cW, cE;
294               if(maxtol > tolW && maxtol > tolE) {
295                 cW = (maxtol - tolE)/l; 
296                 cE = 1. - cW;
297               }
298               else if (maxtol > tolW) {maxtol = tolE; cW = 0.; cE = 1.;}
299               else {maxtol = tolW; cW = 1.; cE = 0.;}
300
301               gp_Pnt PC(cW*PW.X() + cE*PE.X(),cW*PW.Y() + cE*PE.Y(),cW*PW.Z() + cE*PE.Z());
302
303               B.UpdateVertex(VW, PC, maxtol);
304               
305               newvertex = Standard_True;
306               myVertex = VW;
307               myVertex.Orientation(VE.Orientation());
308               B.Add(myEdge,myVertex);
309               B.Transfert(EE,myEdge,VE,myVertex);
310               break;
311             }
312             
313             itm.Next();
314           }
315           if (!newvertex) {
316             myVertices.Add(VE);
317             B.Add(myEdge,VE);
318             B.Transfert(EE,myEdge,VE,VE);
319           }
320         }
321       }
322     }
323     // On decide ici de l'orientation de l'arete
324     // S'il y a ambiguite (en 3d) on garde l'orientation donnee en entree
325     // Cas d'ambiguite :
326     // reverse et forward sont faux car on n'a rien decider : 
327     //       wire ferme, vertex interne ... 
328     // reverse et forward sont vrai : Edge ferme ou degenere
329     if ( ((forward == reverse) && (E.Orientation() == TopAbs_REVERSED)) ||
330        ( reverse && !forward) )  myEdge.Reverse();
331   }
332  
333   // add myEdge to myShape
334   B.Add(myShape,myEdge);
335   myShape.Closed(Standard_False);
336
337   // Initialize VF, VL
338   if (init) TopExp::Vertices(TopoDS::Wire(myShape), VF,VL);
339   else {
340     if (myError == BRepLib_WireDone){ // Update only
341       TopoDS_Vertex V1,V2,VRef; 
342       TopExp::Vertices(myEdge, V1, V2);
343       if (V1.IsSame(myVertex)) VRef = V2;
344       else if (V2.IsSame(myVertex)) VRef = V1;
345       else {
346 #if DEB
347         cout << "MakeWire : Y A UN PROBLEME !!" << endl;
348 #endif
349         myError = BRepLib_NonManifoldWire;
350       }
351       
352       if (VF.IsSame(VL)) {
353         // Cas particulier: il faut controler les orientations
354 #if DEB
355         if (!VF.IsSame(myVertex))
356           cout << "MakeWire : Y A UN PROBLEME !!" << endl;
357 #endif
358         
359       }
360       else { // Cas general
361         if (VF.IsSame(myVertex)) VF = VRef;
362         else if (VL.IsSame(myVertex)) VL = VRef;
363         else {
364 #if DEB
365           cout << "MakeWire : Y A UN PROBLEME !!" << endl;
366 #endif
367           myError = BRepLib_NonManifoldWire;
368         }
369       }
370     }
371     if (myError == BRepLib_NonManifoldWire) {
372       VF = VL = TopoDS_Vertex(); // nullify
373     }
374   }
375   // Test myShape is closed
376   if (!VF.IsNull() && !VL.IsNull() && VF.IsSame(VL))
377     myShape.Closed(Standard_True);
378   
379   myError = BRepLib_WireDone;
380   Done();
381 }
382
383
384 //=======================================================================
385 //function : Wire
386 //purpose  : 
387 //=======================================================================
388
389 const TopoDS_Wire&  BRepLib_MakeWire::Wire()const 
390 {
391   return TopoDS::Wire(Shape());
392 }
393
394
395 //=======================================================================
396 //function : Edge
397 //purpose  : 
398 //=======================================================================
399
400 const TopoDS_Edge&  BRepLib_MakeWire::Edge()const 
401 {
402   return myEdge;
403 }
404
405
406 //=======================================================================
407 //function : Vertex
408 //purpose  : 
409 //=======================================================================
410
411 const TopoDS_Vertex&  BRepLib_MakeWire::Vertex()const 
412 {
413   return myVertex;
414 }
415
416
417 //=======================================================================
418 //function : operator
419 //purpose  : 
420 //=======================================================================
421
422 BRepLib_MakeWire::operator TopoDS_Wire() const
423 {
424   return Wire();
425 }
426
427
428
429 //=======================================================================
430 //function : Error
431 //purpose  : 
432 //=======================================================================
433
434 BRepLib_WireError BRepLib_MakeWire::Error() const
435 {
436   return myError;
437 }