0030895: Coding Rules - specify std namespace explicitly for std::cout and streams
[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   for (TopoDS_Iterator it(W); it.More(); it.Next()) {
135     Add(TopoDS::Edge(it.Value()));
136     if (myError != BRepLib_WireDone)
137       break;
138   }
139 }
140
141 //=======================================================================
142 //function : Add
143 //purpose  : 
144 //=======================================================================
145 void  BRepLib_MakeWire::Add(const TopoDS_Edge& E)
146 {
147   Add(E, Standard_True);
148 }
149
150 //=======================================================================
151 //function : Add
152 //purpose  : 
153 // PMN  19/03/1998  For the Problem of performance TopExp::Vertices are not used on wire
154 // PMN  10/09/1998  In case if the wire is previously closed (or degenerated) 
155 //                  TopExp::Vertices is used to reduce the ambiguity.
156 // IsCheckGeometryProximity flag : If true => check for the geometry proximity of vertices
157 //=======================================================================
158 void  BRepLib_MakeWire::Add(const TopoDS_Edge& E, Standard_Boolean IsCheckGeometryProximity)
159 {
160
161   Standard_Boolean forward = Standard_False; 
162      // to tell if it has been decided to add forward
163   Standard_Boolean reverse = Standard_False; 
164      // to tell if it has been decided to add reversed
165   Standard_Boolean init = Standard_False;
166      // To know if it is necessary to calculate VL, VF
167   BRep_Builder B;
168   TopoDS_Iterator it;
169
170   if (myEdge.IsNull()) {
171     init = Standard_True;
172     // first edge, create the wire
173     B.MakeWire(TopoDS::Wire(myShape));
174
175     // set the edge
176     myEdge = E;
177
178     // add the vertices
179     for (it.Initialize(myEdge); it.More(); it.Next()) 
180       myVertices.Add(it.Value());
181   }
182   
183   else {
184     init = myShape.Closed(); // If it is closed no control
185     TopoDS_Shape aLocalShape = E.Oriented(TopAbs_FORWARD);
186     TopoDS_Edge EE = TopoDS::Edge(aLocalShape);
187 //    TopoDS_Edge EE = TopoDS::Edge(E.Oriented(TopAbs_FORWARD));
188
189     // test the vertices of the edge
190     
191     Standard_Boolean connected = Standard_False;
192     Standard_Boolean copyedge  = Standard_False;
193     
194     if (myError != BRepLib_NonManifoldWire) {
195       if (VF.IsNull() || VL.IsNull()) 
196         myError = BRepLib_NonManifoldWire;
197     }
198
199     for (it.Initialize(EE); it.More(); it.Next()) {
200
201       const TopoDS_Vertex& VE = TopoDS::Vertex(it.Value());
202
203       // if the vertex is in the wire, ok for the connection
204       if (myVertices.Contains(VE)) {
205         connected = Standard_True;
206         myVertex = VE;
207         if (myError != BRepLib_NonManifoldWire) {
208           // is it always so ?
209           if (VF.IsSame(VL)) {
210             // Orientation indetermined (in 3d) : Preserve the initial
211             if (!VF.IsSame(VE)) myError = BRepLib_NonManifoldWire;
212           }
213           else {
214             if (VF.IsSame(VE)) {
215               if  (VE.Orientation() == TopAbs_FORWARD) 
216                 reverse = Standard_True;
217               else 
218                 forward = Standard_True;
219             }
220             else if (VL.IsSame(VE)) {
221               if (VE.Orientation() == TopAbs_REVERSED)
222                 reverse = Standard_True;
223               else 
224                 forward = Standard_True;
225             }
226             else 
227               myError = BRepLib_NonManifoldWire;
228           }
229         }
230       }
231       else if (IsCheckGeometryProximity)
232       {
233           // search if there is a similar vertex in the edge    
234         gp_Pnt PE = BRep_Tool::Pnt(VE);
235         
236         for (Standard_Integer i = 1; i <= myVertices.Extent(); i++) {
237           const TopoDS_Vertex& VW = TopoDS::Vertex(myVertices.FindKey(i));
238           gp_Pnt PW = BRep_Tool::Pnt(VW);
239           Standard_Real l = PE.Distance(PW);
240           
241           if ((l < BRep_Tool::Tolerance(VE)) ||
242               (l < BRep_Tool::Tolerance(VW))) {
243             copyedge = Standard_True;
244             if (myError != BRepLib_NonManifoldWire) {
245               // is it always so ?
246               if (VF.IsSame(VL)) {
247                 // Orientation indetermined (in 3d) : Preserve the initial
248                 if (!VF.IsSame(VW)) myError = BRepLib_NonManifoldWire;
249               }
250               else {
251                 if (VF.IsSame(VW)) {
252                  if  (VE.Orientation() == TopAbs_FORWARD) 
253                    reverse = Standard_True;
254                  else 
255                    forward = Standard_True; 
256                 }
257                 else if (VL.IsSame(VW)) { 
258                   if (VE.Orientation() == TopAbs_REVERSED)
259                     reverse = Standard_True;
260                   else 
261                     forward = Standard_True;
262                 }
263                 else 
264                   myError = BRepLib_NonManifoldWire;
265               }
266             }      
267             break;
268           }
269         }
270         if (copyedge) {
271           connected = Standard_True;
272         }
273       }
274     }
275     
276     if (!connected) {
277       myError = BRepLib_DisconnectedWire;
278       NotDone();
279       return;
280     }
281     else {
282       if (!copyedge) {
283         myEdge = EE;
284         for (it.Initialize(EE); it.More(); it.Next())
285           myVertices.Add(it.Value());
286       }
287       else {
288         // copy the edge
289         TopoDS_Shape Dummy = EE.EmptyCopied();
290         myEdge = TopoDS::Edge(Dummy);
291         
292         for (it.Initialize(EE); it.More(); it.Next()) {
293
294           const TopoDS_Vertex& VE = TopoDS::Vertex(it.Value());
295           gp_Pnt PE = BRep_Tool::Pnt(VE);
296           
297           Standard_Boolean newvertex = Standard_False;
298           for (Standard_Integer i = 1; i <= myVertices.Extent(); i++) {
299             const TopoDS_Vertex& VW = TopoDS::Vertex(myVertices.FindKey(i));
300             gp_Pnt PW = BRep_Tool::Pnt(VW);
301             Standard_Real l = PE.Distance(PW), tolE, tolW;
302             tolW = BRep_Tool::Tolerance(VW);
303             tolE = BRep_Tool::Tolerance(VE);
304             
305             if ((l < tolE) || (l < tolW)) {
306
307               Standard_Real maxtol = .5*(tolW + tolE + l), cW, cE;
308               if(maxtol > tolW && maxtol > tolE) {
309                 cW = (maxtol - tolE)/l; 
310                 cE = 1. - cW;
311               }
312               else if (maxtol > tolW) {maxtol = tolE; cW = 0.; cE = 1.;}
313               else {maxtol = tolW; cW = 1.; cE = 0.;}
314
315               gp_Pnt PC(cW*PW.X() + cE*PE.X(),cW*PW.Y() + cE*PE.Y(),cW*PW.Z() + cE*PE.Z());
316
317               B.UpdateVertex(VW, PC, maxtol);
318               
319               newvertex = Standard_True;
320               myVertex = VW;
321               myVertex.Orientation(VE.Orientation());
322               B.Add(myEdge,myVertex);
323               B.Transfert(EE,myEdge,VE,myVertex);
324               break;
325             }
326             
327           }
328           if (!newvertex) {
329             myVertices.Add(VE);
330             B.Add(myEdge,VE);
331             B.Transfert(EE,myEdge,VE,VE);
332           }
333         }
334       }
335     }
336     // Make a decision about the orientation of the edge
337     // If there is an ambiguity (in 3d) preserve the orientation given at input
338     // Case of ambiguity :
339     // reverse and forward are false as nothing has been decided : 
340     //       closed wire, internal vertex ... 
341     // reverse and forward are true : closed or degenerated edge
342     if ( ((forward == reverse) && (E.Orientation() == TopAbs_REVERSED)) ||
343        ( reverse && !forward) )  myEdge.Reverse();
344   }
345  
346   // add myEdge to myShape
347   B.Add(myShape,myEdge);
348   myShape.Closed(Standard_False);
349
350   // Initialize VF, VL
351   if (init) TopExp::Vertices(TopoDS::Wire(myShape), VF,VL);
352   else {
353     if (myError == BRepLib_WireDone){ // Update only
354       TopoDS_Vertex V1,V2,VRef; 
355       TopExp::Vertices(myEdge, V1, V2);
356       if (V1.IsSame(myVertex)) VRef = V2;
357       else if (V2.IsSame(myVertex)) VRef = V1;
358       else {
359 #ifdef OCCT_DEBUG
360         std::cout << "MakeWire : There is a PROBLEM !!" << std::endl;
361 #endif
362         myError = BRepLib_NonManifoldWire;
363       }
364       
365       if (VF.IsSame(VL)) {
366         // Particular case: it is required to control the orientation
367 #ifdef OCCT_DEBUG
368         if (!VF.IsSame(myVertex))
369           std::cout << "MakeWire : There is a PROBLEM !!" << std::endl;
370 #endif
371         
372       }
373       else { // General case
374         if (VF.IsSame(myVertex)) VF = VRef;
375         else if (VL.IsSame(myVertex)) VL = VRef;
376         else {
377 #ifdef OCCT_DEBUG
378           std::cout << "MakeWire : Y A UN PROBLEME !!" << std::endl;
379 #endif
380           myError = BRepLib_NonManifoldWire;
381         }
382       }
383     }
384     if (myError == BRepLib_NonManifoldWire) {
385       VF = VL = TopoDS_Vertex(); // nullify
386     }
387   }
388   // Test myShape is closed
389   if (!VF.IsNull() && !VL.IsNull() && VF.IsSame(VL))
390     myShape.Closed(Standard_True);
391   
392   myError = BRepLib_WireDone;
393   Done();
394 }
395
396
397 //=======================================================================
398 //function : Wire
399 //purpose  : 
400 //=======================================================================
401
402 const TopoDS_Wire&  BRepLib_MakeWire::Wire()
403 {
404   return TopoDS::Wire(Shape());
405 }
406
407
408 //=======================================================================
409 //function : Edge
410 //purpose  : 
411 //=======================================================================
412
413 const TopoDS_Edge&  BRepLib_MakeWire::Edge()const 
414 {
415   return myEdge;
416 }
417
418
419 //=======================================================================
420 //function : Vertex
421 //purpose  : 
422 //=======================================================================
423
424 const TopoDS_Vertex&  BRepLib_MakeWire::Vertex()const 
425 {
426   return myVertex;
427 }
428
429
430 //=======================================================================
431 //function : operator
432 //purpose  : 
433 //=======================================================================
434
435 BRepLib_MakeWire::operator TopoDS_Wire()
436 {
437   return Wire();
438 }
439
440
441
442 //=======================================================================
443 //function : Error
444 //purpose  : 
445 //=======================================================================
446
447 BRepLib_WireError BRepLib_MakeWire::Error() const
448 {
449   return myError;
450 }