6c82af20dcb9701955aef3a3609655c0ff2e429c
[occt.git] / src / BRepLib / BRepLib_MakeWire.cxx
1 // Created on: 1993-07-23
2 // Created by: Remi LEQUETTE
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <BRep_Builder.hxx>
19 #include <BRep_Tool.hxx>
20 #include <BRepLib.hxx>
21 #include <BRepLib_MakeEdge.hxx>
22 #include <BRepLib_MakeWire.hxx>
23 #include <Geom_Curve.hxx>
24 #include <gp.hxx>
25 #include <gp_Pnt.hxx>
26 #include <StdFail_NotDone.hxx>
27 #include <TopExp.hxx>
28 #include <TopExp_Explorer.hxx>
29 #include <TopoDS.hxx>
30 #include <TopoDS_Edge.hxx>
31 #include <TopoDS_Iterator.hxx>
32 #include <TopoDS_Vertex.hxx>
33 #include <TopoDS_Wire.hxx>
34 #include <TopTools_MapIteratorOfMapOfShape.hxx>
35 #include <TopTools_MapOfShape.hxx>
36
37 //=======================================================================
38 //function : BRepLib_MakeWire
39 //purpose  : 
40 //=======================================================================
41 BRepLib_MakeWire::BRepLib_MakeWire() :
42      myError(BRepLib_EmptyWire)
43 {
44 }
45
46
47 //=======================================================================
48 //function : BRepLib_MakeWire
49 //purpose  : 
50 //=======================================================================
51
52 BRepLib_MakeWire::BRepLib_MakeWire(const TopoDS_Edge& E)
53 {
54   Add(E);
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 {
66   Add(E1);
67   Add(E2);
68 }
69
70
71 //=======================================================================
72 //function : BRepLib_MakeWire
73 //purpose  : 
74 //=======================================================================
75
76 BRepLib_MakeWire::BRepLib_MakeWire(const TopoDS_Edge& E1,
77                                    const TopoDS_Edge& E2, 
78                                    const TopoDS_Edge& E3)
79 {
80   Add(E1);
81   Add(E2);
82   Add(E3);
83 }
84
85
86 //=======================================================================
87 //function : BRepLib_MakeWire
88 //purpose  : 
89 //=======================================================================
90
91 BRepLib_MakeWire::BRepLib_MakeWire(const TopoDS_Edge& E1, 
92                                    const TopoDS_Edge& E2,
93                                    const TopoDS_Edge& E3, 
94                                    const TopoDS_Edge& E4)
95 {
96   Add(E1);
97   Add(E2);
98   Add(E3);
99   Add(E4);
100 }
101
102
103 //=======================================================================
104 //function : BRepLib_MakeWire
105 //purpose  : 
106 //=======================================================================
107
108 BRepLib_MakeWire::BRepLib_MakeWire(const TopoDS_Wire& W)
109 {
110   Add(W);
111 }
112
113
114 //=======================================================================
115 //function : BRepLib_MakeWire
116 //purpose  : 
117 //=======================================================================
118
119 BRepLib_MakeWire::BRepLib_MakeWire(const TopoDS_Wire& W, 
120                                    const TopoDS_Edge& E)
121 {
122   Add(W);
123   Add(E);
124 }
125
126
127 //=======================================================================
128 //function : Add
129 //purpose  : 
130 //=======================================================================
131
132 void  BRepLib_MakeWire::Add(const TopoDS_Wire& W)
133 {
134   TopExp_Explorer ex(W,TopAbs_EDGE);
135   while (ex.More()) {
136     Add(TopoDS::Edge(ex.Current()));
137     ex.Next();
138   }
139 }
140
141 //=======================================================================
142 //function : Add
143 //purpose  : 
144 // PMN  19/03/1998  For the Problem of performance TopExp::Vertices are not used on wire
145 // PMN  10/09/1998  In case if the wire is previously closed (or degenerated) 
146 //                  TopExp::Vertices is used to reduce the ambiguity.
147 //=======================================================================
148
149 void  BRepLib_MakeWire::Add(const TopoDS_Edge& E)
150 {
151
152   Standard_Boolean forward = Standard_False; 
153      // to tell if it has been decided to add forward
154   Standard_Boolean reverse = Standard_False; 
155      // to tell if it has been decided to add reversed
156   Standard_Boolean init = Standard_False;
157      // To know if it is necessary to calculate VL, VF
158   BRep_Builder B;
159   TopoDS_Iterator it;
160
161   if (myEdge.IsNull()) {
162     init = Standard_True;
163     // first edge, create the wire
164     B.MakeWire(TopoDS::Wire(myShape));
165
166     // set the edge
167     myEdge = E;
168
169     // add the vertices
170     for (it.Initialize(myEdge); it.More(); it.Next()) 
171       myVertices.Add(it.Value());
172   }
173   
174   else {
175     init = myShape.Closed(); // If it is closed no control
176     TopoDS_Shape aLocalShape = E.Oriented(TopAbs_FORWARD);
177     TopoDS_Edge EE = TopoDS::Edge(aLocalShape);
178 //    TopoDS_Edge EE = TopoDS::Edge(E.Oriented(TopAbs_FORWARD));
179
180     // test the vertices of the edge
181     
182     Standard_Boolean connected = Standard_False;
183     Standard_Boolean copyedge  = Standard_False;
184     
185     if (myError != BRepLib_NonManifoldWire) {
186       if (VF.IsNull() || VL.IsNull()) 
187         myError = BRepLib_NonManifoldWire;
188     }
189
190     for (it.Initialize(EE); it.More(); it.Next()) {
191
192       const TopoDS_Vertex& VE = TopoDS::Vertex(it.Value());
193
194       // if the vertex is in the wire, ok for the connection
195       if (myVertices.Contains(VE)) {
196         connected = Standard_True;
197         myVertex = VE;
198         if (myError != BRepLib_NonManifoldWire) {
199           // is it always so ?
200           if (VF.IsSame(VL)) {
201             // Orientation indetermined (in 3d) : Preserve the initial
202             if (!VF.IsSame(VE)) myError = BRepLib_NonManifoldWire;
203           }
204           else {
205             if (VF.IsSame(VE)) {
206               if  (VE.Orientation() == TopAbs_FORWARD) 
207                 reverse = Standard_True;
208               else 
209                 forward = Standard_True;
210             }
211             else if (VL.IsSame(VE)) {
212               if (VE.Orientation() == TopAbs_REVERSED)
213                 reverse = Standard_True;
214               else 
215                 forward = Standard_True;
216             }
217             else 
218               myError = BRepLib_NonManifoldWire;
219           }
220         }
221       }
222       else {
223           // search if there is a similar vertex in the edge    
224         gp_Pnt PE = BRep_Tool::Pnt(VE);
225         
226 //      Standard_Boolean newvertex = Standard_False;
227         TopTools_MapIteratorOfMapOfShape itm(myVertices);
228         while (itm.More()) {
229           
230           const TopoDS_Vertex& VW = TopoDS::Vertex(itm.Key());
231           gp_Pnt PW = BRep_Tool::Pnt(VW);
232           Standard_Real l = PE.Distance(PW);
233           
234           if ((l < BRep_Tool::Tolerance(VE)) ||
235               (l < BRep_Tool::Tolerance(VW))) {
236             copyedge = Standard_True;
237             if (myError != BRepLib_NonManifoldWire) {
238               // is it always so ?
239               if (VF.IsSame(VL)) {
240                 // Orientation indetermined (in 3d) : Preserve the initial
241                 if (!VF.IsSame(VW)) myError = BRepLib_NonManifoldWire;
242               }
243               else {
244                 if (VF.IsSame(VW)) {
245                  if  (VE.Orientation() == TopAbs_FORWARD) 
246                    reverse = Standard_True;
247                  else 
248                    forward = Standard_True; 
249                 }
250                 else if (VL.IsSame(VW)) { 
251                   if (VE.Orientation() == TopAbs_REVERSED)
252                     reverse = Standard_True;
253                   else 
254                     forward = Standard_True;
255                 }
256                 else 
257                   myError = BRepLib_NonManifoldWire;
258               }
259             }      
260             break;
261           }
262           itm.Next();
263         }
264         if (copyedge) {
265           connected = Standard_True;
266         }
267       }
268     }
269     
270     if (!connected) {
271       myError = BRepLib_DisconnectedWire;
272       NotDone();
273       return;
274     }
275     else {
276       if (!copyedge) {
277         myEdge = EE;
278         for (it.Initialize(EE); it.More(); it.Next())
279           myVertices.Add(it.Value());
280       }
281       else {
282         // copy the edge
283         TopoDS_Shape Dummy = EE.EmptyCopied();
284         myEdge = TopoDS::Edge(Dummy);
285         
286         for (it.Initialize(EE); it.More(); it.Next()) {
287
288           const TopoDS_Vertex& VE = TopoDS::Vertex(it.Value());
289           gp_Pnt PE = BRep_Tool::Pnt(VE);
290           
291           Standard_Boolean newvertex = Standard_False;
292           TopTools_MapIteratorOfMapOfShape itm(myVertices);
293           while (itm.More()) {
294           
295             const TopoDS_Vertex& VW = TopoDS::Vertex(itm.Key());
296             gp_Pnt PW = BRep_Tool::Pnt(VW);
297             Standard_Real l = PE.Distance(PW), tolE, tolW;
298             tolW = BRep_Tool::Tolerance(VW);
299             tolE = BRep_Tool::Tolerance(VE);
300             
301             if ((l < tolE) || (l < tolW)) {
302
303               Standard_Real maxtol = .5*(tolW + tolE + l), cW, cE;
304               if(maxtol > tolW && maxtol > tolE) {
305                 cW = (maxtol - tolE)/l; 
306                 cE = 1. - cW;
307               }
308               else if (maxtol > tolW) {maxtol = tolE; cW = 0.; cE = 1.;}
309               else {maxtol = tolW; cW = 1.; cE = 0.;}
310
311               gp_Pnt PC(cW*PW.X() + cE*PE.X(),cW*PW.Y() + cE*PE.Y(),cW*PW.Z() + cE*PE.Z());
312
313               B.UpdateVertex(VW, PC, maxtol);
314               
315               newvertex = Standard_True;
316               myVertex = VW;
317               myVertex.Orientation(VE.Orientation());
318               B.Add(myEdge,myVertex);
319               B.Transfert(EE,myEdge,VE,myVertex);
320               break;
321             }
322             
323             itm.Next();
324           }
325           if (!newvertex) {
326             myVertices.Add(VE);
327             B.Add(myEdge,VE);
328             B.Transfert(EE,myEdge,VE,VE);
329           }
330         }
331       }
332     }
333     // Make a decision about the orientation of the edge
334     // If there is an ambiguity (in 3d) preserve the orientation given at input
335     // Case of ambiguity :
336     // reverse and forward are false as nothing has been decided : 
337     //       closed wire, internal vertex ... 
338     // reverse and forward are true : closed or degenerated edge
339     if ( ((forward == reverse) && (E.Orientation() == TopAbs_REVERSED)) ||
340        ( reverse && !forward) )  myEdge.Reverse();
341   }
342  
343   // add myEdge to myShape
344   B.Add(myShape,myEdge);
345   myShape.Closed(Standard_False);
346
347   // Initialize VF, VL
348   if (init) TopExp::Vertices(TopoDS::Wire(myShape), VF,VL);
349   else {
350     if (myError == BRepLib_WireDone){ // Update only
351       TopoDS_Vertex V1,V2,VRef; 
352       TopExp::Vertices(myEdge, V1, V2);
353       if (V1.IsSame(myVertex)) VRef = V2;
354       else if (V2.IsSame(myVertex)) VRef = V1;
355       else {
356 #ifdef OCCT_DEBUG
357         cout << "MakeWire : There is a PROBLEM !!" << endl;
358 #endif
359         myError = BRepLib_NonManifoldWire;
360       }
361       
362       if (VF.IsSame(VL)) {
363         // Particular case: it is required to control the orientation
364 #ifdef OCCT_DEBUG
365         if (!VF.IsSame(myVertex))
366           cout << "MakeWire : There is a PROBLEM !!" << endl;
367 #endif
368         
369       }
370       else { // General case
371         if (VF.IsSame(myVertex)) VF = VRef;
372         else if (VL.IsSame(myVertex)) VL = VRef;
373         else {
374 #ifdef OCCT_DEBUG
375           cout << "MakeWire : Y A UN PROBLEME !!" << endl;
376 #endif
377           myError = BRepLib_NonManifoldWire;
378         }
379       }
380     }
381     if (myError == BRepLib_NonManifoldWire) {
382       VF = VL = TopoDS_Vertex(); // nullify
383     }
384   }
385   // Test myShape is closed
386   if (!VF.IsNull() && !VL.IsNull() && VF.IsSame(VL))
387     myShape.Closed(Standard_True);
388   
389   myError = BRepLib_WireDone;
390   Done();
391 }
392
393
394 //=======================================================================
395 //function : Wire
396 //purpose  : 
397 //=======================================================================
398
399 const TopoDS_Wire&  BRepLib_MakeWire::Wire()const 
400 {
401   return TopoDS::Wire(Shape());
402 }
403
404
405 //=======================================================================
406 //function : Edge
407 //purpose  : 
408 //=======================================================================
409
410 const TopoDS_Edge&  BRepLib_MakeWire::Edge()const 
411 {
412   return myEdge;
413 }
414
415
416 //=======================================================================
417 //function : Vertex
418 //purpose  : 
419 //=======================================================================
420
421 const TopoDS_Vertex&  BRepLib_MakeWire::Vertex()const 
422 {
423   return myVertex;
424 }
425
426
427 //=======================================================================
428 //function : operator
429 //purpose  : 
430 //=======================================================================
431
432 BRepLib_MakeWire::operator TopoDS_Wire() const
433 {
434   return Wire();
435 }
436
437
438
439 //=======================================================================
440 //function : Error
441 //purpose  : 
442 //=======================================================================
443
444 BRepLib_WireError BRepLib_MakeWire::Error() const
445 {
446   return myError;
447 }