0024023: Revamp the OCCT Handle -- general
[occt.git] / src / BRepTools / BRepTools_Quilt.cxx
CommitLineData
b311480e 1// Created on: 1994-12-23
2// Created by: Remi LEQUETTE
3// Copyright (c) 1994-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 <BRepTools_Quilt.ixx>
18
19#include <TopoDS.hxx>
20#include <TopoDS_Face.hxx>
21#include <TopoDS_Wire.hxx>
22#include <TopoDS_Shape.hxx>
23#include <TopoDS_Shell.hxx>
24#include <TopoDS_Compound.hxx>
25#include <TopoDS_Iterator.hxx>
26
27#include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
28#include <TopTools_DataMapOfShapeShape.hxx>
29#include <TopExp_Explorer.hxx>
30
31#include <Geom2d_Curve.hxx>
32
33#include <BRep_Builder.hxx>
34#include <BRep_Tool.hxx>
35#include <TopTools_MapOfShape.hxx>
36#include <TopoDS_Shape.hxx>
37#include <TopTools_MapIteratorOfMapOfShape.hxx>
38#include <TopTools_ListOfShape.hxx>
39#include <TopTools_IndexedDataMapOfShapeShape.hxx>
40
41//=======================================================================
42//function : BRepTools_Quilt
43//purpose :
44//=======================================================================
45
46BRepTools_Quilt::BRepTools_Quilt() : hasCopy(Standard_False)
47{
48}
49
50//=======================================================================
51//function : Add
52//purpose :
53//=======================================================================
54static Standard_Boolean NeedCopied(const TopoDS_Shape& theShape,const TopTools_IndexedDataMapOfShapeShape& myBounds)
55{
56 // test if the shape must be copied
57 // i.e. it contains a bound subshape
58 Standard_Boolean IsCopied = Standard_False;
59 TopoDS_Iterator itv(theShape) ;
60 for ( ; itv.More(); itv.Next()) {
61 if (myBounds.Contains(itv.Value())) {
62 IsCopied = Standard_True;
63 break;
64 }
65 }
66 return IsCopied;
67}
68static void CopyShape(const TopoDS_Edge& E,TopTools_IndexedDataMapOfShapeShape& myBounds)
69{
70 TopoDS_Edge NE = E;
71 NE.EmptyCopy();
72 NE.Orientation(TopAbs_FORWARD);
73 BRep_Builder B;
74 // add the edges
75 TopoDS_Iterator itv;
76 itv.Initialize(E,Standard_False) ; //TCollection_DataMap
77 for ( ; itv.More(); itv.Next()) {
78 const TopoDS_Shape& V = itv.Value();
79 if (myBounds.Contains(V)) {
80 B.Add(NE,myBounds.FindFromKey(V).Oriented(V.Orientation()));
81 }
82 else {
83 B.Add(NE,V);
84 }
85 }
86 // set the 3d range
87 Standard_Real f,l;
88 BRep_Tool::Range(E,f,l);
89 B.Range(NE,f,l);
90 myBounds.Add(E,NE.Oriented(TopAbs_FORWARD));
91}
92/*static void CopyShape(const TopoDS_Wire& W,TopTools_DataMapOfShapeShape& myBounds)
93{
94 TopoDS_Wire NW;
95 B.MakeWire(NW);
96 TopoDS_Iterator ite(W,Standard_False);
97 for ( ; ite.More(); ite.Next()){
98 const TopoDS_Edge& E = TopoDS::Edge(ite.Value());
99 TopAbs_Orientation OE = E.Orientation();
100 if (myBounds.IsBound(E)) {
101 TopoDS_Edge& NE = TopoDS::Edge(myBounds(E));
102 B.Add(NW,NE.Oriented(OE));
103 }
104 else
105 B.Add(NW,E);
106 }
107 NW.Orientation(W.Orientation());
108 myBounds.Bind(W,NW);
109}*/
110void BRepTools_Quilt::Add(const TopoDS_Shape& S)
111{
112 //cout <<" Version of sewing with free edges"<<endl;
113 // Binds all the faces of S
114 // - to the face itself if it is not copied
115 // - to the copy if it is copied
116 if(myBounds.Contains(S)) return;
117 BRep_Builder B;
118 for (TopExp_Explorer wex(S,TopAbs_WIRE,TopAbs_FACE); wex.More(); wex.Next())
119 myBounds.Add(wex.Current(),wex.Current());
120
121 for (TopExp_Explorer eex(S,TopAbs_EDGE,TopAbs_WIRE); eex.More(); eex.Next())
122 myBounds.Add(eex.Current(),eex.Current());
123
124 for (TopExp_Explorer vex(S,TopAbs_VERTEX,TopAbs_EDGE); vex.More(); vex.Next())
125 myBounds.Add(vex.Current(),vex.Current());
126
127 // explore the faces
128 for (TopExp_Explorer fex(S,TopAbs_FACE); fex.More(); fex.Next()) {
129
130 // explore the edges of the face and try to copy them
131 // if one edge is bound the face must be copied
132
133 Standard_Boolean copyFace = Standard_False;
134 const TopoDS_Face& F = TopoDS::Face(fex.Current());
135
136 if (hasCopy) { // if their is no binding, do not test for copy
137
138 for (TopExp_Explorer fed(F,TopAbs_EDGE); fed.More(); fed.Next()) {
139
140 if (myBounds.Contains(fed.Current())) {
141 copyFace = Standard_True;
142 }
143 else {
144 // test if the edge must be copied
145 // i.e. it contains a bound vertex
146
147 Standard_Boolean copyEdge = NeedCopied(fed.Current(),myBounds);
148 //Standard_Boolean copyEdge = Standard_False;
149 const TopoDS_Edge& E = TopoDS::Edge(fed.Current());
150
151 // TopoDS_Iterator itv(E) ;
152 // for ( ; itv.More(); itv.Next()) {
153 // if (myBounds.IsBound(itv.Value())) {
154 // copyEdge = Standard_True;
155 // break;
156 // }
157 // }
158
159 if (copyEdge) {
160
161 // copy of an edge
162
163 copyFace = Standard_True;
164 CopyShape(E,myBounds);
165 //TopoDS_Edge NE = E; //gka version for free edges
166 //NE.EmptyCopy();
167
168 //NE.Orientation(TopAbs_FORWARD);
169 // add the edges
170 //itv.Initialize(E,Standard_False) ;
171 //for ( ; itv.More(); itv.Next()) {
172 //const TopoDS_Shape& V = itv.Value();
173 //if (myBounds.IsBound(V)) {
174 // B.Add(NE,myBounds(V).Oriented(V.Orientation()));
175 //}
176 //else {
177 // B.Add(NE,V);
178 //}
179 //}
180 // set the 3d range
181 //Standard_Real f,l;
182 //BRep_Tool::Range(E,f,l);
183 //B.Range(NE,f,l);
184
185 //myBounds.Bind(E,NE.Oriented(TopAbs_FORWARD));
186 }
187 }
188 }
189 }
190
191 // NF will be the copy of F or F itself
192 TopoDS_Face NF = F;
193
194 if (copyFace) {
195
196 // copy of a face
197
198 NF.EmptyCopy();
199 NF.Orientation(TopAbs_FORWARD);
200
201 for (TopoDS_Iterator itw(F,Standard_False); itw.More(); itw.Next()) {
202 const TopoDS_Wire& W = TopoDS::Wire(itw.Value());
203
204 TopoDS_Wire NW;
205 B.MakeWire(NW);
206 TopoDS_Iterator ite(W,Standard_False);
7fd59977 207 Standard_Real UFirst,ULast;
208
209 // Reconstruction des wires.
210
211 for ( ; ite.More(); ite.Next()){
212 const TopoDS_Edge& E = TopoDS::Edge(ite.Value());
213 TopAbs_Orientation OE = E.Orientation();
214 if (myBounds.Contains(E)) {
215 const TopoDS_Edge& NE = TopoDS::Edge(myBounds.FindFromKey(E));
216 // pcurve.
217 if (NE.Orientation() == TopAbs_FORWARD) {
218 B.UpdateEdge(NE,
219 BRep_Tool::CurveOnSurface(E,F,UFirst,ULast),
220 F,BRep_Tool::Tolerance(E));
221 }
222 else {
223 // Si NE est REVERSED
224 // => les curve3d n ont pas la meme orientation.
225 // ( C est une convention cf BRepTools_Quilt.cdl. et la methode
226 // Bind.)
227 // => la PCurve de E sur F doit etre inversee.
228
229 OE = TopAbs::Reverse(OE);
230 Handle(Geom2d_Curve) CE =
231 BRep_Tool::CurveOnSurface(E,F,UFirst,ULast);
232 Handle(Geom2d_Curve) NCE = CE->Reversed();
233 B.UpdateEdge(NE,NCE,F,BRep_Tool::Tolerance(E));
234 Standard_Real tmp = UFirst;
235 UFirst = CE->ReversedParameter(ULast);
236 ULast = CE->ReversedParameter(tmp);
237 }
238 // pcurve range
239 B.Range(NE,F,UFirst,ULast);
240
241 B.Add(NW,NE.Oriented(OE));
242 }
243 else {
244 B.Add(NW,E);
245 }
246 }
247 NW.Orientation(W.Orientation());
248 B.Add(NF,NW);
249 }
250 NF.Orientation(F.Orientation());
251 }
252
253 // binds the face to itself or its copy
254 myBounds.Add(F,NF);
255 }
256
257}
258
259//=======================================================================
260//function : Bind
261//purpose :
262//=======================================================================
263
264void BRepTools_Quilt::Bind(const TopoDS_Vertex& Vold,
265 const TopoDS_Vertex& Vnew)
266{
267 if (!myBounds.Contains(Vold)) {
268 myBounds.Add(Vold,Vnew);
269 }
270}
271
272//=======================================================================
273//function : Bind
274//purpose :
275//=======================================================================
276
277void BRepTools_Quilt::Bind(const TopoDS_Edge& Eold, const TopoDS_Edge& Enew)
278{
279 if (!myBounds.Contains(Eold)) {
280 TopoDS_Edge ENew = Enew;
281 if (IsCopied(Enew)) {
282 ENew = TopoDS::Edge(Copy(Enew));
283 ENew.Orientation(Enew.Orientation());
284 }
285
286 if (Eold.Orientation() != ENew.Orientation()) {
287 myBounds.Add(Eold.Oriented(TopAbs_FORWARD),
288 ENew.Oriented(TopAbs_REVERSED));
289 }
290 else {
291 myBounds.Add(Eold.Oriented(TopAbs_FORWARD),
292 ENew.Oriented(TopAbs_FORWARD));
293 }
294 // if new binding bind also the vertices
295 TopoDS_Iterator itold(Eold);
296 while (itold.More()) {
297 if (!myBounds.Contains(itold.Value())) {
298 // find the vertex of Enew with same orientation
299 TopAbs_Orientation anOrien = itold.Value().Orientation();
300 TopoDS_Iterator itnew(ENew);
301 while (itnew.More()) {
302 if (itnew.Value().Orientation() == anOrien) {
303 TopoDS_Vertex VNew = TopoDS::Vertex(itnew.Value());
304 if (IsCopied(VNew)) {
305 // if VNew has been copied take the copy
306 VNew = TopoDS::Vertex(Copy(VNew));
307 }
308 myBounds.Add(itold.Value(),VNew);
309 break;
310 }
311 itnew.Next();
312 }
313 }
314 itold.Next();
315 }
316 hasCopy = Standard_True;
317 }
318}
319
320//=======================================================================
321//function : IsBound
322//purpose :
323//=======================================================================
324
325Standard_Boolean BRepTools_Quilt::IsCopied(const TopoDS_Shape& S) const
326{
327 if (myBounds.Contains(S)) {
328 return !S.IsSame(myBounds.FindFromKey(S));
329 }
330 else
331 return Standard_False;
332}
333
334//=======================================================================
335//function : Copy
336//purpose :
337//=======================================================================
338
339const TopoDS_Shape& BRepTools_Quilt::Copy(const TopoDS_Shape& S) const
340{
341 Standard_NoSuchObject_Raise_if(!IsCopied(S),"BRepTools_Quilt::Copy");
342 return myBounds.FindFromKey(S);
343}
344
345//=======================================================================
346//function : Shells
347//purpose :
348//=======================================================================
349
350TopoDS_Shape BRepTools_Quilt::Shells() const
351{
352 // Outline of the algorithm
353 //
354 // In the map M we bind the free edges to their shells
355 // We explore all the faces in myBounds
356 // For each one we search the edges in the map and either :
357 //
358 // - Start a new shell if no edge is a free edge.
359 // - Add the face to an existing shell
360 // - Connect other shells if the face touch more than one shell
361
362 // In the Map M the Shell is bound withe the relative orientation of E
363 // in the shell
364 // In the map MF we binb the face to its shell.
365 // In the Map MF the Shell is bound with the relative orientation of F
366 // in the shell
367
368 TopTools_DataMapOfShapeShape M, MF;
369 BRep_Builder B;
370 TopoDS_Compound result;
371
372 B.MakeCompound(result);
373
374 TopTools_MapOfShape MapOtherShape; //gka
375 TopTools_MapOfShape EdgesFaces;
376
377 // loop on the face in myBounds
378 //TopTools_DataMapIteratorOfDataMapOfShapeShape it(myBounds);
379
380 //while (it.More())
381 for(Standard_Integer ii =1; ii <= myBounds.Extent(); ii++) {
382 const TopoDS_Shape& Shape = myBounds.FindFromIndex(ii); //it.Value();
383 if (Shape.ShapeType() == TopAbs_FACE) {
384 for(TopExp_Explorer aExpEdg(Shape,TopAbs_EDGE); aExpEdg.More(); aExpEdg.Next()) //gka
385 EdgesFaces.Add(aExpEdg.Current());
386
387 TopoDS_Shell SH;
388 TopAbs_Orientation NewO;
389
390 TopExp_Explorer itf1( Shape,TopAbs_EDGE);
391 for ( ; itf1.More(); itf1.Next()) {
392 const TopoDS_Shape& E = itf1.Current();
393 if (M.IsBound(E)) {
394 SH = TopoDS::Shell(M(E));
395 if (SH.Orientation() == E.Orientation())
396 NewO = TopAbs::Reverse(Shape.Orientation());
397 else
398 NewO = Shape.Orientation();
399
400 MF.Bind (Shape,SH.Oriented(NewO));
401 break;
402 }
403 }
404
405 if (SH.IsNull()) {
406 // Create a new shell, closed. Add it to the result.
407 B.MakeShell(SH);
408 SH.Closed(Standard_True);
409 B.Add(result,SH);
410 MF.Bind (Shape,SH.Oriented(Shape.Orientation()));
411 }
412
413
414 // Add the face to the shell
415 SH.Free(Standard_True);
416// B.Add(SH.Oriented(TopAbs_FORWARD), F .Oriented(MF(F).Orientation()));
417 TopoDS_Shape arefShape = SH.Oriented(TopAbs_FORWARD) ;
418 B.Add( arefShape , Shape.Oriented(MF(Shape).Orientation()));
419
420 TopExp_Explorer itf(Shape.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
421
422 for ( ;itf.More(); itf.Next()) {
423 const TopoDS_Edge& E = TopoDS::Edge(itf.Current());
424
425 if (M.IsBound(E)) {
426 const TopoDS_Shape oldShell = M(E);
427 if (!oldShell.IsSame(SH)) {
428 // Fuse the old shell with the new one
429 // Compare the orientation of E in SH and in oldshell.
430 TopAbs_Orientation anOrien = E.Orientation();
431 if (MF(Shape).Orientation() == TopAbs_REVERSED)
432 anOrien = TopAbs::Reverse(anOrien);
433
434 Standard_Boolean Rev = (anOrien == oldShell.Orientation());
435 //if rev = True oldShell has to be reversed.
436
437 // Add the faces of oldShell in SH.
438 for (TopoDS_Iterator its(oldShell); its.More(); its.Next()) {
439 const TopoDS_Face Fo = TopoDS::Face(its.Value());
440 TopAbs_Orientation NewO;
441 // update the orientation of Fo in SH.
442 if (Rev)
443 NewO = TopAbs::Reverse(MF(Fo).Orientation());
444 else
445 NewO = MF(Fo).Orientation();
446
447 MF.Bind(Fo,SH.Oriented(NewO));
448// B.Add (SH.Oriented(TopAbs_FORWARD),Fo.Oriented(NewO));
449 TopoDS_Shape arefShape = SH.Oriented(TopAbs_FORWARD) ;
450 B.Add ( arefShape ,Fo.Oriented(NewO));
451 }
7fd59977 452 // Rebind the free edges of the old shell to the new shell
453 //gka BUG 6491
454 TopExp_Explorer aexp(SH,TopAbs_EDGE);
455 for( ; aexp.More(); aexp.Next()) {
456 //for (TopTools_DataMapIteratorOfDataMapOfShapeShape itm(M);
457// itm.More(); ) {
458 if(!M.IsBound(aexp.Current()))
459 continue;
460 TopoDS_Shape ae = aexp.Current();
461 TopoDS_Shape as = M.Find(ae);
462 if (as.IsSame(oldShell)) {
463 // update the orientation of free edges in SH.
464 if (Rev)
465 NewO = TopAbs::Reverse(as.Orientation());
466 else
467 NewO = as.Orientation();
468
469 M.Bind(ae,SH.Oriented(NewO));
470 }
471 }
472 // remove the old shell from the result
473 B.Remove(result,oldShell.Oriented(TopAbs_FORWARD));
474 }
475 // Test if SH is always orientable.
476 TopAbs_Orientation anOrien = E.Orientation();
477 if (MF(Shape).Orientation() == TopAbs_REVERSED)
478 anOrien = TopAbs::Reverse(anOrien);
479
480 if (M(E).Orientation() == anOrien)
481 SH.Orientable(Standard_False);
482
483 // remove the edge from M (no more a free edge)
484 M.UnBind(E);
485 }
486 else {
487 NewO = E.Orientation();
488 if (MF(Shape).Orientation() == TopAbs_REVERSED)
489 NewO = TopAbs::Reverse(NewO);
490 if(!E.IsNull())
491 M.Bind(E,SH.Oriented(NewO));
492 else
493 continue;
494 }
495 }
496
497 // freeze the shell
498 SH.Free(Standard_False);
499 }
500 else
501 MapOtherShape.Add(Shape);
502
503 //it.Next();
504 }
505
506 // Unclose all shells having free edges
507 for (TopTools_DataMapIteratorOfDataMapOfShapeShape it(M); it.More(); it.Next()) {
508 TopoDS_Shape S = it.Value();
509 S.Closed(Standard_Boolean(Standard_False));
510 }
511
512 TopTools_MapIteratorOfMapOfShape itother(MapOtherShape); //gka version for free edges
513 for( ; itother.More() ; itother.Next()) {
514 if(!EdgesFaces.Contains(itother.Key()) && myBounds.Contains(itother.Key())) {
515 TopoDS_Shape aSh = myBounds.FindFromKey(itother.Key());
516 B.Add(result,aSh);
517 }
518 }
519 return result;
520}
521