1 // File: BRepTools_Quilt.cxx
2 // Created: Fri Dec 23 10:37:05 1994
3 // Author: Remi LEQUETTE
7 #include <BRepTools_Quilt.ixx>
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>
17 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
18 #include <TopTools_DataMapOfShapeShape.hxx>
19 #include <TopExp_Explorer.hxx>
21 #include <Geom2d_Curve.hxx>
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>
31 //=======================================================================
32 //function : BRepTools_Quilt
34 //=======================================================================
36 BRepTools_Quilt::BRepTools_Quilt() : hasCopy(Standard_False)
40 //=======================================================================
43 //=======================================================================
44 static Standard_Boolean NeedCopied(const TopoDS_Shape& theShape,const TopTools_IndexedDataMapOfShapeShape& myBounds)
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;
58 static void CopyShape(const TopoDS_Edge& E,TopTools_IndexedDataMapOfShapeShape& myBounds)
62 NE.Orientation(TopAbs_FORWARD);
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()));
78 BRep_Tool::Range(E,f,l);
80 myBounds.Add(E,NE.Oriented(TopAbs_FORWARD));
82 /*static void CopyShape(const TopoDS_Wire& W,TopTools_DataMapOfShapeShape& myBounds)
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));
97 NW.Orientation(W.Orientation());
100 void BRepTools_Quilt::Add(const TopoDS_Shape& S)
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;
108 for (TopExp_Explorer wex(S,TopAbs_WIRE,TopAbs_FACE); wex.More(); wex.Next())
109 myBounds.Add(wex.Current(),wex.Current());
111 for (TopExp_Explorer eex(S,TopAbs_EDGE,TopAbs_WIRE); eex.More(); eex.Next())
112 myBounds.Add(eex.Current(),eex.Current());
114 for (TopExp_Explorer vex(S,TopAbs_VERTEX,TopAbs_EDGE); vex.More(); vex.Next())
115 myBounds.Add(vex.Current(),vex.Current());
118 for (TopExp_Explorer fex(S,TopAbs_FACE); fex.More(); fex.Next()) {
120 // explore the edges of the face and try to copy them
121 // if one edge is bound the face must be copied
123 Standard_Boolean copyFace = Standard_False;
124 const TopoDS_Face& F = TopoDS::Face(fex.Current());
126 if (hasCopy) { // if their is no binding, do not test for copy
128 for (TopExp_Explorer fed(F,TopAbs_EDGE); fed.More(); fed.Next()) {
130 if (myBounds.Contains(fed.Current())) {
131 copyFace = Standard_True;
134 // test if the edge must be copied
135 // i.e. it contains a bound vertex
137 Standard_Boolean copyEdge = NeedCopied(fed.Current(),myBounds);
138 //Standard_Boolean copyEdge = Standard_False;
139 const TopoDS_Edge& E = TopoDS::Edge(fed.Current());
141 // TopoDS_Iterator itv(E) ;
142 // for ( ; itv.More(); itv.Next()) {
143 // if (myBounds.IsBound(itv.Value())) {
144 // copyEdge = Standard_True;
153 copyFace = Standard_True;
154 CopyShape(E,myBounds);
155 //TopoDS_Edge NE = E; //gka version for free edges
158 //NE.Orientation(TopAbs_FORWARD);
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()));
172 //BRep_Tool::Range(E,f,l);
175 //myBounds.Bind(E,NE.Oriented(TopAbs_FORWARD));
181 // NF will be the copy of F or F itself
189 NF.Orientation(TopAbs_FORWARD);
191 for (TopoDS_Iterator itw(F,Standard_False); itw.More(); itw.Next()) {
192 const TopoDS_Wire& W = TopoDS::Wire(itw.Value());
196 TopoDS_Iterator ite(W,Standard_False);
198 Standard_Real Tol = BRep_Tool::Tolerance(F);
200 BRep_Tool::Tolerance(F);
202 Standard_Real UFirst,ULast;
204 // Reconstruction des wires.
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));
212 if (NE.Orientation() == TopAbs_FORWARD) {
214 BRep_Tool::CurveOnSurface(E,F,UFirst,ULast),
215 F,BRep_Tool::Tolerance(E));
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
222 // => la PCurve de E sur F doit etre inversee.
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);
234 B.Range(NE,F,UFirst,ULast);
236 B.Add(NW,NE.Oriented(OE));
242 NW.Orientation(W.Orientation());
245 NF.Orientation(F.Orientation());
248 // binds the face to itself or its copy
254 //=======================================================================
257 //=======================================================================
259 void BRepTools_Quilt::Bind(const TopoDS_Vertex& Vold,
260 const TopoDS_Vertex& Vnew)
262 if (!myBounds.Contains(Vold)) {
263 myBounds.Add(Vold,Vnew);
267 //=======================================================================
270 //=======================================================================
272 void BRepTools_Quilt::Bind(const TopoDS_Edge& Eold, const TopoDS_Edge& Enew)
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());
281 if (Eold.Orientation() != ENew.Orientation()) {
282 myBounds.Add(Eold.Oriented(TopAbs_FORWARD),
283 ENew.Oriented(TopAbs_REVERSED));
286 myBounds.Add(Eold.Oriented(TopAbs_FORWARD),
287 ENew.Oriented(TopAbs_FORWARD));
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));
303 myBounds.Add(itold.Value(),VNew);
311 hasCopy = Standard_True;
315 //=======================================================================
318 //=======================================================================
320 Standard_Boolean BRepTools_Quilt::IsCopied(const TopoDS_Shape& S) const
322 if (myBounds.Contains(S)) {
323 return !S.IsSame(myBounds.FindFromKey(S));
326 return Standard_False;
329 //=======================================================================
332 //=======================================================================
334 const TopoDS_Shape& BRepTools_Quilt::Copy(const TopoDS_Shape& S) const
336 Standard_NoSuchObject_Raise_if(!IsCopied(S),"BRepTools_Quilt::Copy");
337 return myBounds.FindFromKey(S);
340 //=======================================================================
343 //=======================================================================
345 TopoDS_Shape BRepTools_Quilt::Shells() const
347 // Outline of the algorithm
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 :
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
357 // In the Map M the Shell is bound withe the relative orientation of E
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
363 TopTools_DataMapOfShapeShape M, MF;
365 TopoDS_Compound result;
367 B.MakeCompound(result);
369 TopTools_MapOfShape MapOtherShape; //gka
370 TopTools_MapOfShape EdgesFaces;
372 // loop on the face in myBounds
373 //TopTools_DataMapIteratorOfDataMapOfShapeShape it(myBounds);
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());
383 TopAbs_Orientation NewO;
385 TopExp_Explorer itf1( Shape,TopAbs_EDGE);
386 for ( ; itf1.More(); itf1.Next()) {
387 const TopoDS_Shape& E = itf1.Current();
389 SH = TopoDS::Shell(M(E));
390 if (SH.Orientation() == E.Orientation())
391 NewO = TopAbs::Reverse(Shape.Orientation());
393 NewO = Shape.Orientation();
395 MF.Bind (Shape,SH.Oriented(NewO));
401 // Create a new shell, closed. Add it to the result.
403 SH.Closed(Standard_True);
405 MF.Bind (Shape,SH.Oriented(Shape.Orientation()));
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()));
415 TopExp_Explorer itf(Shape.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
417 for ( ;itf.More(); itf.Next()) {
418 const TopoDS_Edge& E = TopoDS::Edge(itf.Current());
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);
429 Standard_Boolean Rev = (anOrien == oldShell.Orientation());
430 //if rev = True oldShell has to be reversed.
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.
438 NewO = TopAbs::Reverse(MF(Fo).Orientation());
440 NewO = MF(Fo).Orientation();
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));
447 Standard_Integer kk =1;
448 Standard_Integer p =0;
449 // Rebind the free edges of the old shell to the new shell
451 TopExp_Explorer aexp(SH,TopAbs_EDGE);
452 for( ; aexp.More(); aexp.Next()) {
453 //for (TopTools_DataMapIteratorOfDataMapOfShapeShape itm(M);
455 if(!M.IsBound(aexp.Current()))
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.
462 NewO = TopAbs::Reverse(as.Orientation());
464 NewO = as.Orientation();
466 M.Bind(ae,SH.Oriented(NewO));
469 // remove the old shell from the result
470 B.Remove(result,oldShell.Oriented(TopAbs_FORWARD));
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);
477 if (M(E).Orientation() == anOrien)
478 SH.Orientable(Standard_False);
480 // remove the edge from M (no more a free edge)
484 NewO = E.Orientation();
485 if (MF(Shape).Orientation() == TopAbs_REVERSED)
486 NewO = TopAbs::Reverse(NewO);
488 M.Bind(E,SH.Oriented(NewO));
495 SH.Free(Standard_False);
498 MapOtherShape.Add(Shape);
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));
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());