0024023: Revamp the OCCT Handle -- ambiguity
[occt.git] / src / BRepLib / BRepLib_MakeWire.cxx
CommitLineData
b311480e 1// Created on: 1993-07-23
2// Created by: Remi LEQUETTE
3// Copyright (c) 1993-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 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
973c2be1 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.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
7fd59977 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
38BRepLib_MakeWire::BRepLib_MakeWire() :
39 myError(BRepLib_EmptyWire)
40{
41}
42
43
44//=======================================================================
45//function : BRepLib_MakeWire
46//purpose :
47//=======================================================================
48
49BRepLib_MakeWire::BRepLib_MakeWire(const TopoDS_Edge& E)
50{
51 Add(E);
52}
53
54
55//=======================================================================
56//function : BRepLib_MakeWire
57//purpose :
58//=======================================================================
59
60BRepLib_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
73BRepLib_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
88BRepLib_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
105BRepLib_MakeWire::BRepLib_MakeWire(const TopoDS_Wire& W)
106{
107 Add(W);
108}
109
110
111//=======================================================================
112//function : BRepLib_MakeWire
113//purpose :
114//=======================================================================
115
116BRepLib_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
129void 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 :
0d969553
Y
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.
7fd59977 144//=======================================================================
145
146void BRepLib_MakeWire::Add(const TopoDS_Edge& E)
147{
148
149 Standard_Boolean forward = Standard_False;
0d969553 150 // to tell if it has been decided to add forward
7fd59977 151 Standard_Boolean reverse = Standard_False;
0d969553 152 // to tell if it has been decided to add reversed
7fd59977 153 Standard_Boolean init = Standard_False;
0d969553 154 // To know if it is necessary to calculate VL, VF
7fd59977 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 {
0d969553 172 init = myShape.Closed(); // If it is closed no control
7fd59977 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) {
0d969553 196 // is it always so ?
7fd59977 197 if (VF.IsSame(VL)) {
0d969553 198 // Orientation indetermined (in 3d) : Preserve the initial
7fd59977 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) {
0d969553 235 // is it always so ?
7fd59977 236 if (VF.IsSame(VL)) {
0d969553 237 // Orientation indetermined (in 3d) : Preserve the initial
7fd59977 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);
7fd59977 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 }
0d969553
Y
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
7fd59977 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 {
0797d9d3 353#ifdef OCCT_DEBUG
0d969553 354 cout << "MakeWire : There is a PROBLEM !!" << endl;
7fd59977 355#endif
356 myError = BRepLib_NonManifoldWire;
357 }
358
359 if (VF.IsSame(VL)) {
0d969553 360 // Particular case: it is required to control the orientation
0797d9d3 361#ifdef OCCT_DEBUG
7fd59977 362 if (!VF.IsSame(myVertex))
0d969553 363 cout << "MakeWire : There is a PROBLEM !!" << endl;
7fd59977 364#endif
365
366 }
0d969553 367 else { // General case
7fd59977 368 if (VF.IsSame(myVertex)) VF = VRef;
369 else if (VL.IsSame(myVertex)) VL = VRef;
370 else {
0797d9d3 371#ifdef OCCT_DEBUG
7fd59977 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
396const TopoDS_Wire& BRepLib_MakeWire::Wire()const
397{
398 return TopoDS::Wire(Shape());
399}
400
401
402//=======================================================================
403//function : Edge
404//purpose :
405//=======================================================================
406
407const TopoDS_Edge& BRepLib_MakeWire::Edge()const
408{
409 return myEdge;
410}
411
412
413//=======================================================================
414//function : Vertex
415//purpose :
416//=======================================================================
417
418const TopoDS_Vertex& BRepLib_MakeWire::Vertex()const
419{
420 return myVertex;
421}
422
423
424//=======================================================================
425//function : operator
426//purpose :
427//=======================================================================
428
429BRepLib_MakeWire::operator TopoDS_Wire() const
430{
431 return Wire();
432}
433
434
435
436//=======================================================================
437//function : Error
438//purpose :
439//=======================================================================
440
441BRepLib_WireError BRepLib_MakeWire::Error() const
442{
443 return myError;
444}