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