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