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