0024624: Lost word in license statement in source files
[occt.git] / src / ShapeExtend / ShapeExtend_WireData.cxx
CommitLineData
973c2be1 1// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 2//
973c2be1 3// This file is part of Open CASCADE Technology software library.
b311480e 4//
d5f74e42 5// This library is free software; you can redistribute it and/or modify it under
6// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 7// by the Free Software Foundation, with special exception defined in the file
8// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9// distribution for complete text of the license and disclaimer of any warranty.
b311480e 10//
973c2be1 11// Alternatively, this file may be used under the terms of Open CASCADE
12// commercial license or contractual agreement.
b311480e 13
7fd59977 14//:q0 abv 12.03.99: mat-a.stp: protection against no pcurves in SwapSeam()
15// abv 28.04.99 S4137: added method Add(WireData), method SetLast fixed
16// abv 05.05.99 S4174: protection against INTERNAL/EXTERNAL edges
17
18#include <ShapeExtend_WireData.ixx>
19#include <Geom2d_Curve.hxx>
20#include <TopoDS.hxx>
21#include <TopoDS_Vertex.hxx>
22#include <TopoDS_Iterator.hxx>
23#include <TopExp.hxx>
24#include <TopTools_IndexedMapOfShape.hxx>
25#include <BRep_Tool.hxx>
26#include <BRep_Builder.hxx>
27#include <BRepBuilderAPI_MakeWire.hxx>
28#include <BRepTools_WireExplorer.hxx>
29
30//=======================================================================
31//function : ShapeExtend_WireData
32//purpose :
33//=======================================================================
34
35ShapeExtend_WireData::ShapeExtend_WireData()
36{
37 Clear();
38}
39
40//=======================================================================
41//function : ShapeExtend_WireData
42//purpose :
43//=======================================================================
44
45ShapeExtend_WireData::ShapeExtend_WireData (const TopoDS_Wire& wire,
46 const Standard_Boolean chained,
47 const Standard_Boolean theManifold)
48{
49 Init ( wire, chained ,theManifold);
50}
51
52//=======================================================================
53//function : Init
54//purpose :
55//=======================================================================
56
57void ShapeExtend_WireData::Init (const Handle(ShapeExtend_WireData)& other)
58{
59 Clear();
60 Standard_Integer i, nb = other->NbEdges();
61 for (i = 1; i <= nb; i++) Add ( other->Edge(i) );
62 nb = other->NbNonManifoldEdges();
63 for (i = 1; i <= nb; i++) Add ( other->NonmanifoldEdge(i) );
64 myManifoldMode = other->ManifoldMode();
65}
66
67//=======================================================================
68//function : Init
69//purpose :
70//=======================================================================
71
72Standard_Boolean ShapeExtend_WireData::Init (const TopoDS_Wire& wire,
73 const Standard_Boolean chained,
74 const Standard_Boolean theManifold)
75{
76 Clear();
77 myManifoldMode = theManifold;
78 Standard_Boolean OK = Standard_True;
79 TopoDS_Vertex Vlast;
80 for ( TopoDS_Iterator it(wire); it.More(); it.Next() ) {
81 TopoDS_Edge E = TopoDS::Edge ( it.Value() );
82
83 // protect against INTERNAL/EXTERNAL edges
84 if ( (E.Orientation() != TopAbs_REVERSED &&
85 E.Orientation() != TopAbs_FORWARD)) {
86 myNonmanifoldEdges->Append(E);
87 continue;
88 }
89
90 TopoDS_Vertex V1, V2;
91 for ( TopoDS_Iterator itv(E); itv.More(); itv.Next() ) {
92 TopoDS_Vertex V = TopoDS::Vertex ( itv.Value() );
93 if ( V.Orientation() == TopAbs_FORWARD ) V1 = V;
94 else if ( V.Orientation() == TopAbs_REVERSED ) V2 = V;
95 }
96
97 // chainage? Si pas bon et chained False on repart sur WireExplorer
98 if ( ! Vlast.IsNull() && ! Vlast.IsSame ( V1 ) && theManifold) {
99 OK = Standard_False;
100 if ( ! chained ) break;
101 }
102 Vlast = V2;
103 if(wire.Orientation() == TopAbs_REVERSED)
104 myEdges->Prepend( E );
105 else
106 myEdges->Append ( E );
107 }
108
109 if(!myManifoldMode) {
110 Standard_Integer nb = myNonmanifoldEdges->Length();
111 Standard_Integer i =1;
112 for( ; i <= nb; i++)
113 myEdges->Append(myNonmanifoldEdges->Value(i));
114 myNonmanifoldEdges->Clear();
115 }
116// refaire chainage ? Par WireExplorer
117 if ( OK || chained ) return OK;
118
119 Clear();
120 for ( BRepTools_WireExplorer we(wire); we.More(); we.Next() )
121 myEdges->Append ( TopoDS::Edge ( we.Current() ) );
122
123 return OK;
124}
125
126//=======================================================================
127//function : Clear
128//purpose :
129//=======================================================================
130
131void ShapeExtend_WireData::Clear()
132{
133 myEdges = new TopTools_HSequenceOfShape();
134 myNonmanifoldEdges = new TopTools_HSequenceOfShape;
135 mySeamF = mySeamR = -1;
136 mySeams.Nullify();
137 myManifoldMode = Standard_True;
138}
139
140//=======================================================================
141//function : ComputeSeams
142//purpose :
143//=======================================================================
144
145void ShapeExtend_WireData::ComputeSeams (const Standard_Boolean enforce)
146{
147 if (mySeamF >= 0 && !enforce) return;
148
149 mySeams = new TColStd_HSequenceOfInteger();
150 mySeamF = mySeamR = 0;
151 TopoDS_Shape S;
152 Standard_Integer i, nb = NbEdges();
153 TopTools_IndexedMapOfShape ME;
154 Standard_Integer* SE = new Standard_Integer [nb+1];
155
156 // deux passes : d abord on mappe les Edges REVERSED
157 // Pour chacune, on note aussi son RANG dans la liste
158 for (i = 1; i <= nb; i ++) {
159 S = Edge(i);
160 if (S.Orientation() == TopAbs_REVERSED) {
161 Standard_Integer num = ME.Add (S);
162 SE[num] = i;
163 }
164 }
165
166 // ensuite on voit les Edges FORWARD qui y seraient deja -> on note leur n0
167 // c-a-d le n0 de la directe ET de la reverse
168 for (i = 1; i <= nb; i ++) {
169 S = Edge(i);
170 if (S.Orientation() == TopAbs_REVERSED) continue;
171 Standard_Integer num = ME.FindIndex (S);
172 if (num <= 0) continue;
173 if (mySeamF == 0) { mySeamF = i; mySeamR = SE[num]; }
174 else { mySeams->Append(i); mySeams->Append( SE[num] ); }
175 }
176
177 delete [] SE; // ne pas oublier !!
178}
179
180//=======================================================================
181//function : SetLast
182//purpose :
183//=======================================================================
184
185void ShapeExtend_WireData::SetLast (const Standard_Integer num)
186{
187 if (num == 0) return;
188 Standard_Integer i, nb = NbEdges();
189 for (i = nb; i > num; i--) {
190 TopoDS_Edge edge = TopoDS::Edge ( myEdges->Value(nb) );
191 myEdges->Remove (nb);
192 myEdges->InsertBefore (1, edge);
193 }
194 mySeamF = -1;
195}
196
197//=======================================================================
198//function : SetDegeneratedLast
199//purpose :
200//=======================================================================
201
202void ShapeExtend_WireData::SetDegeneratedLast()
203{
204 Standard_Integer i, nb = NbEdges();
205 for (i = 1; i <= nb; i ++) {
206 if ( BRep_Tool::Degenerated ( Edge(i) ) ) {
207 SetLast ( i );
208 return;
209 }
210 }
211}
212
213//=======================================================================
214//function : Add
215//purpose :
216//=======================================================================
217
218void ShapeExtend_WireData::Add (const TopoDS_Edge& edge,
219 const Standard_Integer atnum)
220{
221 if(edge.Orientation()!= TopAbs_REVERSED &&
222 edge.Orientation() != TopAbs_FORWARD && myManifoldMode) {
223 myNonmanifoldEdges->Append(edge);
224 return;
225 }
226
227 if (edge.IsNull()) return;
228 if (atnum == 0) {
229 myEdges->Append (edge);
230 }
231 else {
232 myEdges->InsertBefore (atnum,edge);
233 }
234 mySeamF = -1;
235}
236
237//=======================================================================
238//function : Add
239//purpose :
240//=======================================================================
241
242void ShapeExtend_WireData::Add (const TopoDS_Wire& wire,
243 const Standard_Integer atnum)
244{
245 if (wire.IsNull()) return;
246 Standard_Integer n = atnum;
247 TopTools_SequenceOfShape aNMEdges;
248 for (TopoDS_Iterator it(wire); it.More(); it.Next()) {
249 TopoDS_Edge edge = TopoDS::Edge (it.Value());
250 if(edge.Orientation()!= TopAbs_REVERSED &&
251 edge.Orientation() != TopAbs_FORWARD) {
252 if(myManifoldMode)
253 myNonmanifoldEdges->Append(edge);
254 else
255 aNMEdges.Append(edge);
256 continue;
257 }
258 if (n == 0) {
259 myEdges->Append (edge);
260 } else {
261 myEdges->InsertBefore (n,edge);
262 n++;
263 }
264 }
265 Standard_Integer i =1, nb = aNMEdges.Length();
266 for( ; i <= nb ; i++)
267 myEdges->Append(aNMEdges.Value(i));
268 mySeamF = -1;
269}
270
271//=======================================================================
272//function : Add
273//purpose :
274//=======================================================================
275
276void ShapeExtend_WireData::Add (const Handle(ShapeExtend_WireData) &wire,
277 const Standard_Integer atnum)
278{
279 if ( wire.IsNull() ) return;
280 TopTools_SequenceOfShape aNMEdges;
281 Standard_Integer n = atnum;
282 Standard_Integer i=1;
283 for (; i <= wire->NbEdges(); i++ ) {
284 TopoDS_Edge aE = wire->Edge(i);
285 if(aE.Orientation() == TopAbs_INTERNAL ||
286 aE.Orientation() == TopAbs_EXTERNAL) {
287 aNMEdges.Append(aE);
288 continue;
289 }
290
291 if (n == 0 ) {
292 myEdges->Append ( wire->Edge(i) );
293 }
294 else {
295 myEdges->InsertBefore ( n, wire->Edge(i) );
296 n++;
297 }
298 }
299
300 //non-manifold edges for non-manifold wire shoud be added at end
301 for (i=1; i <=aNMEdges.Length(); i++)
302 myEdges->Append(aNMEdges.Value(i));
303
304 for (i=1; i <= wire->NbNonManifoldEdges(); i++) {
305 if( myManifoldMode)
306 myNonmanifoldEdges->Append(wire->NonmanifoldEdge(i));
307 else {
308 if (n == 0)
309 myEdges->Append ( wire->Edge(i) );
310
311 else {
312 myEdges->InsertBefore ( n, wire->Edge(i) );
313 n++;
314 }
315 }
316 }
317
318 mySeamF = -1;
319}
320
321//=======================================================================
322//function : Add
323//purpose :
324//=======================================================================
325
326void ShapeExtend_WireData::Add (const TopoDS_Shape& shape,
327 const Standard_Integer atnum)
328{
329 if (shape.ShapeType() == TopAbs_EDGE) Add (TopoDS::Edge (shape), atnum);
330 else if (shape.ShapeType() == TopAbs_WIRE) Add (TopoDS::Wire (shape), atnum);
331}
332
333//=======================================================================
334//function : AddOriented
335//purpose :
336//=======================================================================
337
338void ShapeExtend_WireData::AddOriented (const TopoDS_Edge& edge,
339 const Standard_Integer mode)
340{
341 if (edge.IsNull() || mode < 0) return;
342 TopoDS_Edge E = edge;
343 if (mode == 1 || mode == 3) E.Reverse();
344 Add (E, mode/2); // mode = 0,1 -> 0 mode = 2,3 -> 1
345}
346
347//=======================================================================
348//function : AddOriented
349//purpose :
350//=======================================================================
351
352void ShapeExtend_WireData::AddOriented (const TopoDS_Wire& wire,
353 const Standard_Integer mode)
354{
355 if (wire.IsNull() || mode < 0) return;
356 TopoDS_Wire W = wire;
357 if (mode == 1 || mode == 3) W.Reverse();
358 Add (W, mode/2); // mode = 0,1 -> 0 mode = 2,3 -> 1
359}
360
361void ShapeExtend_WireData::AddOriented (const TopoDS_Shape& shape,
362 const Standard_Integer mode)
363{
364 if (shape.ShapeType() == TopAbs_EDGE) AddOriented (TopoDS::Edge (shape), mode);
365 else if (shape.ShapeType() == TopAbs_WIRE) AddOriented (TopoDS::Wire (shape), mode);
366}
367
368//=======================================================================
369//function : Remove
370//purpose :
371//=======================================================================
372
373void ShapeExtend_WireData::Remove (const Standard_Integer num)
374{
375
376 myEdges->Remove ( num > 0 ? num : NbEdges() );
377
378 mySeamF = -1;
379}
380
381//=======================================================================
382//function : Set
383//purpose :
384//=======================================================================
385
386void ShapeExtend_WireData::Set (const TopoDS_Edge& edge,
387 const Standard_Integer num)
388{
389 if(edge.Orientation()!= TopAbs_REVERSED &&
390 edge.Orientation() != TopAbs_FORWARD && myManifoldMode) {
391 if(num <= myNonmanifoldEdges->Length())
392 myNonmanifoldEdges->SetValue(num,edge);
393 else
394 myNonmanifoldEdges->Append(edge);
395 }
396
397 else
398 myEdges->SetValue ( ( num > 0 ? num : NbEdges() ), edge);
399 mySeamF = -1;
400}
401
402//=======================================================================
403//function : Reverse
404//purpose : reverse order of edges in the wire
405//=======================================================================
406
407void ShapeExtend_WireData::Reverse ()
408{
409 Standard_Integer i, nb = NbEdges();
410
411 // inverser les edges + les permuter pour inverser le wire
412 for (i = 1; i <= nb/2; i ++) {
413 TopoDS_Shape S1 = myEdges->Value(i); S1.Reverse();
414 TopoDS_Shape S2 = myEdges->Value(nb+1-i); S2.Reverse();
415 myEdges->SetValue (i, S2);
416 myEdges->SetValue (nb+1-i, S1);
417 }
418 // nb d edges impair : inverser aussi l edge du milieu (rang inchange)
419 if ( nb % 2 ) { // test impair
420 i = (nb+1)/2;
421 TopoDS_Shape SI = myEdges->Value(i); SI.Reverse();
422 myEdges->SetValue (i, SI);
423 }
424 mySeamF = -1;
425}
426
427//=======================================================================
428//function : Reverse
429//purpose :
430//=======================================================================
431
432// Fonction auxiliaire SwapSeam pour inverser
433static void SwapSeam (const TopoDS_Shape& S, const TopoDS_Face& F)
434{
435 TopoDS_Edge E = TopoDS::Edge (S);
436 if ( E.IsNull() || F.IsNull() ) return;
437 if ( E.Orientation() == TopAbs_REVERSED ) return; // ne le faire qu une fois !
438
439 TopoDS_Face theface = F;
440 theface.Orientation(TopAbs_FORWARD);
441
442//:S4136 Standard_Real Tol = BRep_Tool::Tolerance(theface);
443 Handle(Geom2d_Curve) c2df,c2dr;
444 Standard_Real uff,ulf,ufr,ulr;
445
446 // d abord FWD puis REV
447 c2df = BRep_Tool::CurveOnSurface (E,theface,uff,ulf);
448 E.Orientation (TopAbs_REVERSED);
449 c2dr = BRep_Tool::CurveOnSurface (E,theface,ufr,ulr);
450 if ( c2df.IsNull() || c2dr.IsNull() ) return; //:q0
451 // On permute
452 E.Orientation (TopAbs_FORWARD);
453 BRep_Builder B;
454 B.UpdateEdge (E,c2dr,c2df,theface,0.); //:S4136: Tol
455 B.Range (E,theface,uff,ulf);
456}
457
458void ShapeExtend_WireData::Reverse (const TopoDS_Face &face)
459{
460 Reverse();
461 if ( face.IsNull() ) return;
462
463 // ATTENTION aux coutures
464 // Une edge de couture est presente deux fois, FWD et REV
465 // Les inverser revient a permuter leur role ... donc ne rien faire
466 // Il faut donc aussi permuter leurs pcurves
467 ComputeSeams(Standard_True);
468 if (mySeamF > 0) SwapSeam (myEdges->Value(mySeamF),face);
469 if (mySeamR > 0) SwapSeam (myEdges->Value(mySeamR),face);
470 Standard_Integer nb = (mySeams.IsNull() ? 0 : mySeams->Length());
471 for ( Standard_Integer i = 1; i <= nb; i ++) {
472 SwapSeam (myEdges->Value(mySeams->Value(i)),face);
473 }
474 mySeamF = -1;
475}
476
477//=======================================================================
478//function : NbEdges
479//purpose :
480//=======================================================================
481
482Standard_Integer ShapeExtend_WireData::NbEdges() const
483{
484 return myEdges->Length();
485}
486
487//=======================================================================
488//function : Edge
489//purpose :
490//=======================================================================
491
492TopoDS_Edge ShapeExtend_WireData::Edge (const Standard_Integer num) const
493{
494 if (num < 0) {
495 TopoDS_Edge E = Edge (-num);
496 E.Reverse();
497 return E;
498 }
499 return TopoDS::Edge ( myEdges->Value ( num ) );
500}
501//=======================================================================
502//function : NbNonManifoldEdges
503//purpose :
504//=======================================================================
505
506Standard_Integer ShapeExtend_WireData::NbNonManifoldEdges() const
507{
508 return myNonmanifoldEdges->Length();
509}
510
511//=======================================================================
512//function : Edge
513//purpose :
514//=======================================================================
515
516TopoDS_Edge ShapeExtend_WireData::NonmanifoldEdge (const Standard_Integer num) const
517{
518 TopoDS_Edge E;
519 if (num < 0)
520 return E;
521
522 return TopoDS::Edge ( myNonmanifoldEdges->Value ( num ) );
523}
524//=======================================================================
525//function : Index
526//purpose :
527//=======================================================================
528
529Standard_Integer ShapeExtend_WireData::Index (const TopoDS_Edge& edge)
530{
531 for (Standard_Integer i = 1; i <= NbEdges(); i++)
532 if (Edge (i).IsSame (edge) && (Edge(i).Orientation() == edge.Orientation() || !IsSeam(i)))
533 return i;
534 return 0;
535}
536
537//=======================================================================
538//function : IsSeam
539//purpose :
540//=======================================================================
541
542Standard_Boolean ShapeExtend_WireData::IsSeam (const Standard_Integer num)
543{
544 if (mySeamF < 0) ComputeSeams();
545 if (mySeamF == 0) return Standard_False;
546
547 if (num == mySeamF || num == mySeamR) return Standard_True;
548// Pas suffisant : on regarde dans la liste
549 Standard_Integer i, nb = mySeams->Length();
550 for (i = 1; i <= nb; i ++) {
551 if (num == mySeams->Value(i)) return Standard_True;
552 }
553 return Standard_False;
554}
555
556//=======================================================================
557//function : Make
558//purpose :
559//=======================================================================
560
561TopoDS_Wire ShapeExtend_WireData::Wire() const
562{
563 TopoDS_Wire W;
564 BRep_Builder B;
565 B.MakeWire (W);
566 Standard_Integer i, nb = NbEdges();
567 Standard_Boolean ismanifold = Standard_True;
568 for (i = 1; i <= nb; i ++) {
569 TopoDS_Edge aE = Edge(i);
570 if (aE.Orientation() != TopAbs_FORWARD &&
571 aE.Orientation() != TopAbs_REVERSED)
572 ismanifold = Standard_False;
573 B.Add (W, aE);
574 }
575 if(ismanifold) {
576 TopoDS_Vertex vf, vl;
577 TopExp::Vertices (W, vf, vl);
578 if (!vf.IsNull() && !vl.IsNull() && vf.IsSame (vl)) W.Closed (Standard_True);
579 }
580 if(myManifoldMode) {
581 nb = NbNonManifoldEdges();
582 for (i = 1; i <= nb; i ++) B.Add (W, NonmanifoldEdge(i));
583 }
584 return W;
585}
586
587//=======================================================================
588//function : APIMake
589//purpose :
590//=======================================================================
591
592TopoDS_Wire ShapeExtend_WireData::WireAPIMake() const
593{
594 TopoDS_Wire W;
595 BRepBuilderAPI_MakeWire MW;
596 Standard_Integer i, nb = NbEdges();
597 for (i = 1; i <= nb; i ++) MW.Add (Edge(i));
598 if(myManifoldMode) {
599 nb = NbNonManifoldEdges();
600 for (i = 1; i <= nb; i ++) MW.Add (NonmanifoldEdge(i));
601 }
602 if ( MW.IsDone() ) W = MW.Wire();
603 return W;
604}
605
606//=======================================================================
607//function : NonmanifoldEdges
608//purpose :
609//=======================================================================
610Handle(TopTools_HSequenceOfShape) ShapeExtend_WireData::NonmanifoldEdges() const
611{
612 return myNonmanifoldEdges;
613}
614
615//=======================================================================
616//function : ManifoldMode
617//purpose :
618//=======================================================================
619Standard_Boolean& ShapeExtend_WireData::ManifoldMode()
620{
621 return myManifoldMode;
622}