0023024: Update headers of OCCT files
[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-2012 OPEN CASCADE SAS
5 //
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
10 //
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 //
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
20
21
22
23 #include <BRepLib_MakeWire.ixx>
24 #include <BRepLib.hxx>
25 #include <BRepLib_MakeEdge.hxx>
26 #include <BRep_Tool.hxx>
27 #include <BRep_Builder.hxx>
28 #include <TopExp.hxx>
29 #include <TopExp_Explorer.hxx>
30 #include <TopTools_MapOfShape.hxx>
31 #include <TopTools_MapIteratorOfMapOfShape.hxx>
32 #include <TopoDS.hxx>
33 #include <TopoDS_Iterator.hxx>
34 #include <gp_Pnt.hxx>
35 #include <Geom_Curve.hxx>
36 #include <gp.hxx>
37
38
39 //=======================================================================
40 //function : BRepLib_MakeWire
41 //purpose  : 
42 //=======================================================================
43
44 BRepLib_MakeWire::BRepLib_MakeWire() :
45      myError(BRepLib_EmptyWire)
46 {
47 }
48
49
50 //=======================================================================
51 //function : BRepLib_MakeWire
52 //purpose  : 
53 //=======================================================================
54
55 BRepLib_MakeWire::BRepLib_MakeWire(const TopoDS_Edge& E)
56 {
57   Add(E);
58 }
59
60
61 //=======================================================================
62 //function : BRepLib_MakeWire
63 //purpose  : 
64 //=======================================================================
65
66 BRepLib_MakeWire::BRepLib_MakeWire(const TopoDS_Edge& E1, 
67                                    const TopoDS_Edge& E2)
68 {
69   Add(E1);
70   Add(E2);
71 }
72
73
74 //=======================================================================
75 //function : BRepLib_MakeWire
76 //purpose  : 
77 //=======================================================================
78
79 BRepLib_MakeWire::BRepLib_MakeWire(const TopoDS_Edge& E1,
80                                    const TopoDS_Edge& E2, 
81                                    const TopoDS_Edge& E3)
82 {
83   Add(E1);
84   Add(E2);
85   Add(E3);
86 }
87
88
89 //=======================================================================
90 //function : BRepLib_MakeWire
91 //purpose  : 
92 //=======================================================================
93
94 BRepLib_MakeWire::BRepLib_MakeWire(const TopoDS_Edge& E1, 
95                                    const TopoDS_Edge& E2,
96                                    const TopoDS_Edge& E3, 
97                                    const TopoDS_Edge& E4)
98 {
99   Add(E1);
100   Add(E2);
101   Add(E3);
102   Add(E4);
103 }
104
105
106 //=======================================================================
107 //function : BRepLib_MakeWire
108 //purpose  : 
109 //=======================================================================
110
111 BRepLib_MakeWire::BRepLib_MakeWire(const TopoDS_Wire& W)
112 {
113   Add(W);
114 }
115
116
117 //=======================================================================
118 //function : BRepLib_MakeWire
119 //purpose  : 
120 //=======================================================================
121
122 BRepLib_MakeWire::BRepLib_MakeWire(const TopoDS_Wire& W, 
123                                    const TopoDS_Edge& E)
124 {
125   Add(W);
126   Add(E);
127 }
128
129
130 //=======================================================================
131 //function : Add
132 //purpose  : 
133 //=======================================================================
134
135 void  BRepLib_MakeWire::Add(const TopoDS_Wire& W)
136 {
137   TopExp_Explorer ex(W,TopAbs_EDGE);
138   while (ex.More()) {
139     Add(TopoDS::Edge(ex.Current()));
140     ex.Next();
141   }
142 }
143
144 //=======================================================================
145 //function : Add
146 //purpose  : 
147 // PMN  19/03/1998  For the Problem of performance TopExp::Vertices are not used on wire
148 // PMN  10/09/1998  In case if the wire is previously closed (or degenerated) 
149 //                  TopExp::Vertices is used to reduce the ambiguity.
150 //=======================================================================
151
152 void  BRepLib_MakeWire::Add(const TopoDS_Edge& E)
153 {
154
155   Standard_Boolean forward = Standard_False; 
156      // to tell if it has been decided to add forward
157   Standard_Boolean reverse = Standard_False; 
158      // to tell if it has been decided to add reversed
159   Standard_Boolean init = Standard_False;
160      // To know if it is necessary to calculate VL, VF
161   BRep_Builder B;
162   TopoDS_Iterator it;
163
164   if (myEdge.IsNull()) {
165     init = Standard_True;
166     // first edge, create the wire
167     B.MakeWire(TopoDS::Wire(myShape));
168
169     // set the edge
170     myEdge = E;
171
172     // add the vertices
173     for (it.Initialize(myEdge); it.More(); it.Next()) 
174       myVertices.Add(it.Value());
175   }
176   
177   else {
178     init = myShape.Closed(); // If it is closed no control
179     TopoDS_Shape aLocalShape = E.Oriented(TopAbs_FORWARD);
180     TopoDS_Edge EE = TopoDS::Edge(aLocalShape);
181 //    TopoDS_Edge EE = TopoDS::Edge(E.Oriented(TopAbs_FORWARD));
182
183     // test the vertices of the edge
184     
185     Standard_Boolean connected = Standard_False;
186     Standard_Boolean copyedge  = Standard_False;
187     
188     if (myError != BRepLib_NonManifoldWire) {
189       if (VF.IsNull() || VL.IsNull()) 
190         myError = BRepLib_NonManifoldWire;
191     }
192
193     for (it.Initialize(EE); it.More(); it.Next()) {
194
195       const TopoDS_Vertex& VE = TopoDS::Vertex(it.Value());
196
197       // if the vertex is in the wire, ok for the connection
198       if (myVertices.Contains(VE)) {
199         connected = Standard_True;
200         myVertex = VE;
201         if (myError != BRepLib_NonManifoldWire) {
202           // is it always so ?
203           if (VF.IsSame(VL)) {
204             // Orientation indetermined (in 3d) : Preserve the initial
205             if (!VF.IsSame(VE)) myError = BRepLib_NonManifoldWire;
206           }
207           else {
208             if (VF.IsSame(VE)) {
209               if  (VE.Orientation() == TopAbs_FORWARD) 
210                 reverse = Standard_True;
211               else 
212                 forward = Standard_True;
213             }
214             else if (VL.IsSame(VE)) {
215               if (VE.Orientation() == TopAbs_REVERSED)
216                 reverse = Standard_True;
217               else 
218                 forward = Standard_True;
219             }
220             else 
221               myError = BRepLib_NonManifoldWire;
222           }
223         }
224       }
225       else {
226           // search if there is a similar vertex in the edge    
227         gp_Pnt PE = BRep_Tool::Pnt(VE);
228         
229 //      Standard_Boolean newvertex = Standard_False;
230         TopTools_MapIteratorOfMapOfShape itm(myVertices);
231         while (itm.More()) {
232           
233           const TopoDS_Vertex& VW = TopoDS::Vertex(itm.Key());
234           gp_Pnt PW = BRep_Tool::Pnt(VW);
235           Standard_Real l = PE.Distance(PW);
236           
237           if ((l < BRep_Tool::Tolerance(VE)) ||
238               (l < BRep_Tool::Tolerance(VW))) {
239             copyedge = Standard_True;
240             if (myError != BRepLib_NonManifoldWire) {
241               // is it always so ?
242               if (VF.IsSame(VL)) {
243                 // Orientation indetermined (in 3d) : Preserve the initial
244                 if (!VF.IsSame(VW)) myError = BRepLib_NonManifoldWire;
245               }
246               else {
247                 if (VF.IsSame(VW)) {
248                  if  (VE.Orientation() == TopAbs_FORWARD) 
249                    reverse = Standard_True;
250                  else 
251                    forward = Standard_True; 
252                 }
253                 else if (VL.IsSame(VW)) { 
254                   if (VE.Orientation() == TopAbs_REVERSED)
255                     reverse = Standard_True;
256                   else 
257                     forward = Standard_True;
258                 }
259                 else 
260                   myError = BRepLib_NonManifoldWire;
261               }
262             }      
263             break;
264           }
265           itm.Next();
266         }
267         if (copyedge) {
268           connected = Standard_True;
269         }
270       }
271     }
272     
273     if (!connected) {
274       myError = BRepLib_DisconnectedWire;
275       NotDone();
276       return;
277     }
278     else {
279       if (!copyedge) {
280         myEdge = EE;
281         for (it.Initialize(EE); it.More(); it.Next())
282           myVertices.Add(it.Value());
283       }
284       else {
285         // copy the edge
286         TopoDS_Shape Dummy = EE.EmptyCopied();
287         myEdge = TopoDS::Edge(Dummy);
288         myEdge.Closed(EE.Closed());
289         
290         for (it.Initialize(EE); it.More(); it.Next()) {
291
292           const TopoDS_Vertex& VE = TopoDS::Vertex(it.Value());
293           gp_Pnt PE = BRep_Tool::Pnt(VE);
294           
295           Standard_Boolean newvertex = Standard_False;
296           TopTools_MapIteratorOfMapOfShape itm(myVertices);
297           while (itm.More()) {
298           
299             const TopoDS_Vertex& VW = TopoDS::Vertex(itm.Key());
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             itm.Next();
328           }
329           if (!newvertex) {
330             myVertices.Add(VE);
331             B.Add(myEdge,VE);
332             B.Transfert(EE,myEdge,VE,VE);
333           }
334         }
335       }
336     }
337     // Make a decision about the orientation of the edge
338     // If there is an ambiguity (in 3d) preserve the orientation given at input
339     // Case of ambiguity :
340     // reverse and forward are false as nothing has been decided : 
341     //       closed wire, internal vertex ... 
342     // reverse and forward are true : closed or degenerated edge
343     if ( ((forward == reverse) && (E.Orientation() == TopAbs_REVERSED)) ||
344        ( reverse && !forward) )  myEdge.Reverse();
345   }
346  
347   // add myEdge to myShape
348   B.Add(myShape,myEdge);
349   myShape.Closed(Standard_False);
350
351   // Initialize VF, VL
352   if (init) TopExp::Vertices(TopoDS::Wire(myShape), VF,VL);
353   else {
354     if (myError == BRepLib_WireDone){ // Update only
355       TopoDS_Vertex V1,V2,VRef; 
356       TopExp::Vertices(myEdge, V1, V2);
357       if (V1.IsSame(myVertex)) VRef = V2;
358       else if (V2.IsSame(myVertex)) VRef = V1;
359       else {
360 #if DEB
361         cout << "MakeWire : There is a PROBLEM !!" << endl;
362 #endif
363         myError = BRepLib_NonManifoldWire;
364       }
365       
366       if (VF.IsSame(VL)) {
367         // Particular case: it is required to control the orientation
368 #if DEB
369         if (!VF.IsSame(myVertex))
370           cout << "MakeWire : There is a PROBLEM !!" << endl;
371 #endif
372         
373       }
374       else { // General case
375         if (VF.IsSame(myVertex)) VF = VRef;
376         else if (VL.IsSame(myVertex)) VL = VRef;
377         else {
378 #if DEB
379           cout << "MakeWire : Y A UN PROBLEME !!" << endl;
380 #endif
381           myError = BRepLib_NonManifoldWire;
382         }
383       }
384     }
385     if (myError == BRepLib_NonManifoldWire) {
386       VF = VL = TopoDS_Vertex(); // nullify
387     }
388   }
389   // Test myShape is closed
390   if (!VF.IsNull() && !VL.IsNull() && VF.IsSame(VL))
391     myShape.Closed(Standard_True);
392   
393   myError = BRepLib_WireDone;
394   Done();
395 }
396
397
398 //=======================================================================
399 //function : Wire
400 //purpose  : 
401 //=======================================================================
402
403 const TopoDS_Wire&  BRepLib_MakeWire::Wire()const 
404 {
405   return TopoDS::Wire(Shape());
406 }
407
408
409 //=======================================================================
410 //function : Edge
411 //purpose  : 
412 //=======================================================================
413
414 const TopoDS_Edge&  BRepLib_MakeWire::Edge()const 
415 {
416   return myEdge;
417 }
418
419
420 //=======================================================================
421 //function : Vertex
422 //purpose  : 
423 //=======================================================================
424
425 const TopoDS_Vertex&  BRepLib_MakeWire::Vertex()const 
426 {
427   return myVertex;
428 }
429
430
431 //=======================================================================
432 //function : operator
433 //purpose  : 
434 //=======================================================================
435
436 BRepLib_MakeWire::operator TopoDS_Wire() const
437 {
438   return Wire();
439 }
440
441
442
443 //=======================================================================
444 //function : Error
445 //purpose  : 
446 //=======================================================================
447
448 BRepLib_WireError BRepLib_MakeWire::Error() const
449 {
450   return myError;
451 }