0027552: Wire creation fails depending on the order of edges
[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
42cf5bc1 17
18#include <BRep_Builder.hxx>
19#include <BRep_Tool.hxx>
7fd59977 20#include <BRepLib.hxx>
21#include <BRepLib_MakeEdge.hxx>
42cf5bc1 22#include <BRepLib_MakeWire.hxx>
23#include <Geom_Curve.hxx>
24#include <gp.hxx>
25#include <gp_Pnt.hxx>
26#include <StdFail_NotDone.hxx>
7fd59977 27#include <TopExp.hxx>
28#include <TopExp_Explorer.hxx>
7fd59977 29#include <TopoDS.hxx>
42cf5bc1 30#include <TopoDS_Edge.hxx>
7fd59977 31#include <TopoDS_Iterator.hxx>
42cf5bc1 32#include <TopoDS_Vertex.hxx>
33#include <TopoDS_Wire.hxx>
34#include <TopTools_MapIteratorOfMapOfShape.hxx>
35#include <TopTools_MapOfShape.hxx>
7fd59977 36
37//=======================================================================
38//function : BRepLib_MakeWire
39//purpose :
40//=======================================================================
7fd59977 41BRepLib_MakeWire::BRepLib_MakeWire() :
42 myError(BRepLib_EmptyWire)
43{
44}
45
46
47//=======================================================================
48//function : BRepLib_MakeWire
49//purpose :
50//=======================================================================
51
52BRepLib_MakeWire::BRepLib_MakeWire(const TopoDS_Edge& E)
53{
54 Add(E);
55}
56
57
58//=======================================================================
59//function : BRepLib_MakeWire
60//purpose :
61//=======================================================================
62
63BRepLib_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
76BRepLib_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
91BRepLib_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
108BRepLib_MakeWire::BRepLib_MakeWire(const TopoDS_Wire& W)
109{
110 Add(W);
111}
112
113
114//=======================================================================
115//function : BRepLib_MakeWire
116//purpose :
117//=======================================================================
118
119BRepLib_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
132void BRepLib_MakeWire::Add(const TopoDS_Wire& W)
133{
134 TopExp_Explorer ex(W,TopAbs_EDGE);
135 while (ex.More()) {
136 Add(TopoDS::Edge(ex.Current()));
137 ex.Next();
138 }
139}
140
07ef8bdf 141//=======================================================================
142//function : Add
143//purpose :
144//=======================================================================
145void BRepLib_MakeWire::Add(const TopoDS_Edge& E)
146{
147 Add(E, Standard_True);
148}
149
7fd59977 150//=======================================================================
151//function : Add
152//purpose :
0d969553
Y
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.
07ef8bdf 156// IsCheckGeometryProximity flag : If true => check for the geometry proximity of vertices
7fd59977 157//=======================================================================
07ef8bdf 158void BRepLib_MakeWire::Add(const TopoDS_Edge& E, Standard_Boolean IsCheckGeometryProximity)
7fd59977 159{
160
161 Standard_Boolean forward = Standard_False;
0d969553 162 // to tell if it has been decided to add forward
7fd59977 163 Standard_Boolean reverse = Standard_False;
0d969553 164 // to tell if it has been decided to add reversed
7fd59977 165 Standard_Boolean init = Standard_False;
0d969553 166 // To know if it is necessary to calculate VL, VF
7fd59977 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 {
0d969553 184 init = myShape.Closed(); // If it is closed no control
7fd59977 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) {
0d969553 208 // is it always so ?
7fd59977 209 if (VF.IsSame(VL)) {
0d969553 210 // Orientation indetermined (in 3d) : Preserve the initial
7fd59977 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 }
07ef8bdf 231 else if (IsCheckGeometryProximity)
232 {
7fd59977 233 // search if there is a similar vertex in the edge
234 gp_Pnt PE = BRep_Tool::Pnt(VE);
235
07ef8bdf 236 for (Standard_Integer i = 1; i <= myVertices.Extent(); i++) {
237 const TopoDS_Vertex& VW = TopoDS::Vertex(myVertices.FindKey(i));
7fd59977 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) {
0d969553 245 // is it always so ?
7fd59977 246 if (VF.IsSame(VL)) {
0d969553 247 // Orientation indetermined (in 3d) : Preserve the initial
7fd59977 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 }
7fd59977 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);
7fd59977 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;
07ef8bdf 298 for (Standard_Integer i = 1; i <= myVertices.Extent(); i++) {
299 const TopoDS_Vertex& VW = TopoDS::Vertex(myVertices.FindKey(i));
7fd59977 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
7fd59977 327 }
328 if (!newvertex) {
329 myVertices.Add(VE);
330 B.Add(myEdge,VE);
331 B.Transfert(EE,myEdge,VE,VE);
332 }
333 }
334 }
335 }
0d969553
Y
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
7fd59977 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 {
0797d9d3 359#ifdef OCCT_DEBUG
0d969553 360 cout << "MakeWire : There is a PROBLEM !!" << endl;
7fd59977 361#endif
362 myError = BRepLib_NonManifoldWire;
363 }
364
365 if (VF.IsSame(VL)) {
0d969553 366 // Particular case: it is required to control the orientation
0797d9d3 367#ifdef OCCT_DEBUG
7fd59977 368 if (!VF.IsSame(myVertex))
0d969553 369 cout << "MakeWire : There is a PROBLEM !!" << endl;
7fd59977 370#endif
371
372 }
0d969553 373 else { // General case
7fd59977 374 if (VF.IsSame(myVertex)) VF = VRef;
375 else if (VL.IsSame(myVertex)) VL = VRef;
376 else {
0797d9d3 377#ifdef OCCT_DEBUG
7fd59977 378 cout << "MakeWire : Y A UN PROBLEME !!" << 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
ecac41a9 402const TopoDS_Wire& BRepLib_MakeWire::Wire()
7fd59977 403{
404 return TopoDS::Wire(Shape());
405}
406
407
408//=======================================================================
409//function : Edge
410//purpose :
411//=======================================================================
412
413const TopoDS_Edge& BRepLib_MakeWire::Edge()const
414{
415 return myEdge;
416}
417
418
419//=======================================================================
420//function : Vertex
421//purpose :
422//=======================================================================
423
424const TopoDS_Vertex& BRepLib_MakeWire::Vertex()const
425{
426 return myVertex;
427}
428
429
430//=======================================================================
431//function : operator
432//purpose :
433//=======================================================================
434
ecac41a9 435BRepLib_MakeWire::operator TopoDS_Wire()
7fd59977 436{
437 return Wire();
438}
439
440
441
442//=======================================================================
443//function : Error
444//purpose :
445//=======================================================================
446
447BRepLib_WireError BRepLib_MakeWire::Error() const
448{
449 return myError;
450}