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