0024002: Overall code and build procedure refactoring -- automatic
[occt.git] / src / BRepOffset / BRepOffset_MakeLoops.cxx
1 // Created on: 1996-09-05
2 // Created by: Yves FRICAUD
3 // Copyright (c) 1996-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <BRep_Builder.hxx>
19 #include <BRep_Tool.hxx>
20 #include <BRep_TVertex.hxx>
21 #include <BRepAlgo_AsDes.hxx>
22 #include <BRepAlgo_Image.hxx>
23 #include <BRepAlgo_Loop.hxx>
24 #include <BRepOffset_Analyse.hxx>
25 #include <BRepOffset_MakeLoops.hxx>
26 #include <TopExp.hxx>
27 #include <TopExp_Explorer.hxx>
28 #include <TopoDS.hxx>
29 #include <TopoDS_Edge.hxx>
30 #include <TopoDS_Face.hxx>
31 #include <TopoDS_Iterator.hxx>
32 #include <TopoDS_Vertex.hxx>
33 #include <TopTools_ListIteratorOfListOfShape.hxx>
34 #include <TopTools_MapOfShape.hxx>
35
36 #include <stdio.h>
37 #ifdef DRAW
38 #include <DBRep.hxx>
39 Standard_Integer NbF = 1;
40 static Standard_Boolean Affich = Standard_False;
41 #endif
42
43 BRepOffset_MakeLoops::BRepOffset_MakeLoops()
44 {
45 }
46
47 //=======================================================================
48 //function : Build
49 //purpose  : 
50 //=======================================================================
51
52 void BRepOffset_MakeLoops::Build(const TopTools_ListOfShape&   LF, 
53                                  const Handle(BRepAlgo_AsDes)& AsDes, 
54                                  BRepAlgo_Image&               Image)
55 {
56   TopTools_ListIteratorOfListOfShape    it(LF);
57   TopTools_ListIteratorOfListOfShape    itl,itLCE;
58   BRepAlgo_Loop                       Loops;
59   Loops.VerticesForSubstitute( myVerVerMap );
60
61   for (; it.More(); it.Next()) {
62     const TopoDS_Face& F = TopoDS::Face(it.Value());
63     //---------------------------
64     // Initialization of Loops.
65     //---------------------------
66     Loops.Init(F);
67     //-----------------------------
68     // return edges of F.
69     //-----------------------------
70     const TopTools_ListOfShape& LE = AsDes->Descendant(F);
71     TopTools_ListOfShape        AddedEdges;
72
73     for (itl.Initialize(LE); itl.More(); itl.Next()) {
74       TopoDS_Edge E = TopoDS::Edge(itl.Value());
75       if (Image.HasImage(E)) {
76         //-------------------------------------------
77         // E was already cut in another face.
78         // Return the cut edges reorientate them as E.
79         // See pb for the edges that have disappeared?
80         //-------------------------------------------
81         const TopTools_ListOfShape& LCE = Image.Image(E);
82         for (itLCE.Initialize(LCE); itLCE.More(); itLCE.Next()) {
83           TopoDS_Shape CE = itLCE.Value().Oriented(E.Orientation()); 
84           Loops.AddConstEdge(TopoDS::Edge(CE));
85         }
86       }
87       else {
88         Loops     .AddEdge(E, AsDes->Descendant(E));
89         AddedEdges.Append (E);
90       }
91     }
92     //------------------------
93     // Unwind.
94     //------------------------
95     Loops.Perform();
96     Loops.WiresToFaces();      
97     //------------------------
98     // MAJ SD.
99     //------------------------
100     const TopTools_ListOfShape&  NF = Loops.NewFaces();
101     //-----------------------
102     // F => New faces;
103     //-----------------------
104     Image.Bind(F,NF);
105
106     TopTools_ListIteratorOfListOfShape itAdded;
107     for (itAdded.Initialize(AddedEdges); itAdded.More(); itAdded.Next()) {
108       const TopoDS_Edge& E = TopoDS::Edge(itAdded.Value());
109       //-----------------------
110       //  E => New edges;
111       //-----------------------
112       const TopTools_ListOfShape& LoopNE = Loops.NewEdges(E);
113       if (Image.HasImage(E)) {
114         Image.Add(E,LoopNE);
115       }
116       else {
117         Image.Bind(E,LoopNE);
118       }
119     }
120   }
121   Loops.GetVerticesForSubstitute( myVerVerMap );
122   if (myVerVerMap.IsEmpty())
123     return;
124   BRep_Builder BB;
125   for (it.Initialize( LF ); it.More(); it.Next())
126     {
127       TopoDS_Shape F = it.Value();
128       TopTools_ListOfShape LIF;
129       Image.LastImage( F, LIF );
130       for (itl.Initialize(LIF); itl.More(); itl.Next())
131         {
132           const TopoDS_Shape& IF = itl.Value();
133           TopExp_Explorer EdExp( IF, TopAbs_EDGE );
134           for (; EdExp.More(); EdExp.Next())
135             {
136               TopoDS_Shape E = EdExp.Current();
137               TopTools_ListOfShape VList;
138               TopoDS_Iterator VerExp( E );
139               for (; VerExp.More(); VerExp.Next())
140                 VList.Append( VerExp.Value() );
141               TopTools_ListIteratorOfListOfShape itlv( VList );
142               for (; itlv.More(); itlv.Next())
143                 {
144                   const TopoDS_Shape& V = itlv.Value();
145                   if (myVerVerMap.IsBound( V ))
146                     {
147                       TopoDS_Shape NewV = myVerVerMap( V );
148                       E.Free( Standard_True );
149                       NewV.Orientation( V.Orientation() );
150                       Handle(BRep_TVertex)& TV = *((Handle(BRep_TVertex)*) &V.TShape());
151                       Handle(BRep_TVertex)& NewTV = *((Handle(BRep_TVertex)*) &NewV.TShape());
152                       if (TV->Tolerance() > NewTV->Tolerance())
153                         NewTV->Tolerance( TV->Tolerance() );
154                       NewTV->ChangePoints().Append( TV->ChangePoints() );
155                       AsDes->Replace( V, NewV );
156                       BB.Remove( E, V );
157                       BB.Add( E, NewV );
158                     }
159                 }
160             }
161         }
162     }
163 }
164
165 //=======================================================================
166 //function : IsBetweenCorks
167 //purpose  : 
168 //=======================================================================
169
170 static Standard_Boolean IsBetweenCorks(const TopoDS_Shape& E,
171                                        const Handle(BRepAlgo_AsDes)& AsDes,
172                                        const TopTools_ListOfShape&   LContext) 
173 {
174   if (!AsDes->HasAscendant(E)) return 1;
175   const TopTools_ListOfShape& LF = AsDes->Ascendant(E);
176   TopTools_ListIteratorOfListOfShape it;
177   for (it.Initialize(LF); it.More(); it.Next()) {
178     const TopoDS_Shape& S = it.Value();
179     Standard_Boolean found = 0;
180     TopTools_ListIteratorOfListOfShape it2;
181     for (it2.Initialize(LContext); it2.More(); it2.Next()) {
182       if(S.IsSame(it2.Value())) {
183         found = 1;
184         break;
185       }
186     }
187     if (!found) return 0;
188   }
189   return 1;
190 }
191 //=======================================================================
192 //function : BuildOnContext
193 //purpose  : 
194 //=======================================================================
195
196 void BRepOffset_MakeLoops::BuildOnContext(const TopTools_ListOfShape&   LContext,  
197                                           const BRepOffset_Analyse&     Analyse, 
198                                           const Handle(BRepAlgo_AsDes)& AsDes, 
199                                           BRepAlgo_Image&               Image,
200                                           const Standard_Boolean        InSide)
201 {
202   //-----------------------------------------
203   // unwinding of caps.
204   //-----------------------------------------
205   TopTools_ListIteratorOfListOfShape  it(LContext);
206   TopTools_ListIteratorOfListOfShape  itl,itLCE;
207   BRepAlgo_Loop                     Loops;
208   Loops.VerticesForSubstitute( myVerVerMap );
209   TopExp_Explorer                     exp; 
210   TopTools_MapOfShape                 MapExtent;
211
212   for (; it.More(); it.Next()) {
213     const TopoDS_Face& F = TopoDS::Face(it.Value());
214     TopTools_MapOfShape                 MBound;
215     //-----------------------------------------------
216     // Initialisation of Loops.
217     // F is reversed it will be added in myOffC.
218     // and myOffC will be reversed in the final result.
219     //-----------------------------------------------
220     TopoDS_Shape aLocalShape = F.Reversed();
221     if (InSide) Loops.Init(TopoDS::Face(aLocalShape));
222 //    if (InSide) Loops.Init(TopoDS::Face(F.Reversed()));
223     else        Loops.Init(F);
224     //--------------------------------------------------------
225     // return edges of F not modified by definition.
226     //--------------------------------------------------------
227     for (exp.Init(F.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
228          exp.More();
229          exp.Next()) {
230       TopoDS_Edge CE = TopoDS::Edge(exp.Current());
231       MBound.Add(CE);   
232       if (Analyse.HasAncestor(CE)) {
233         // the stop of cups except for the connectivity stops between caps.
234         //      if (!AsDes->HasAscendant(CE)) {
235         aLocalShape = CE.Reversed();
236         if (InSide) Loops.AddConstEdge(CE);
237         else        Loops.AddConstEdge(TopoDS::Edge(aLocalShape));
238 //      else        Loops.AddConstEdge(TopoDS::Edge(CE.Reversed()));
239       }
240     }
241     //------------------------------------------------------
242     // Trace of offsets + connectivity edge between caps.
243     //------------------------------------------------------    
244     const TopTools_ListOfShape& LE = AsDes->Descendant(F);
245     TopTools_ListOfShape        AddedEdges;
246     
247     for (itl.Initialize(LE); itl.More(); itl.Next()) {
248       TopoDS_Edge E = TopoDS::Edge(itl.Value());
249       if (Image.HasImage(E)) {
250         //-------------------------------------------
251         // E was already cut in another face.
252         // Return cut edges and orientate them as E.
253         // See pb for the edges that have disappeared?
254         //-------------------------------------------
255         const TopTools_ListOfShape& LCE = Image.Image(E);
256         for (itLCE.Initialize(LCE); itLCE.More(); itLCE.Next()) {
257           TopoDS_Shape CE = itLCE.Value().Oriented(E.Orientation());      
258           if (MapExtent.Contains(E)) {
259             Loops.AddConstEdge(TopoDS::Edge(CE));
260             continue;
261           }
262           if (!MBound.Contains(E)) CE.Reverse();
263           if (InSide) Loops.AddConstEdge(TopoDS::Edge(CE));
264           else
265             {
266               TopoDS_Shape aLocalShape = CE.Reversed();
267               Loops.AddConstEdge(TopoDS::Edge(aLocalShape));
268             }
269 //        else        Loops.AddConstEdge(TopoDS::Edge(CE.Reversed()));
270         }
271       }
272       else {
273         if (IsBetweenCorks(E,AsDes,LContext) && AsDes->HasDescendant(E)) {
274           //connection between 2 caps
275           MapExtent.Add(E);
276           TopTools_ListOfShape LV;
277           if (InSide) {
278             for (itLCE.Initialize(AsDes->Descendant(E)); itLCE.More(); itLCE.Next()) {
279               LV.Append(itLCE.Value().Reversed());
280             }
281             Loops.AddEdge(E,LV);
282           }
283           else {
284             Loops.AddEdge(E,AsDes->Descendant(E));
285           }
286           AddedEdges.Append (E);
287         }
288         else if (IsBetweenCorks(E,AsDes,LContext)) {
289         TopoDS_Shape aLocalShape = E.Reversed();
290           if (InSide) Loops.AddConstEdge(E);
291           else        Loops.AddConstEdge(TopoDS::Edge(aLocalShape));
292 //        if (InSide) Loops.AddConstEdge(TopoDS::Edge(E));
293 //        else        Loops.AddConstEdge(TopoDS::Edge(E.Reversed()));
294         }
295         else { 
296           TopoDS_Shape aLocalShape = E.Reversed();
297           if (InSide) Loops.AddConstEdge(TopoDS::Edge(aLocalShape));
298           else        Loops.AddConstEdge(E);
299 //        if (InSide) Loops.AddConstEdge(TopoDS::Edge(E.Reversed()));
300 //        else        Loops.AddConstEdge(TopoDS::Edge(E));
301         }
302       }
303     }
304     //------------------------
305     // Unwind.
306     //------------------------
307     Loops.Perform();
308     Loops.WiresToFaces();      
309     //------------------------
310     // MAJ SD.
311     //------------------------
312     const TopTools_ListOfShape&  NF = Loops.NewFaces();
313     //-----------------------
314     // F => New faces;
315     //-----------------------
316     Image.Bind(F,NF);   
317
318     TopTools_ListIteratorOfListOfShape itAdded;
319     for (itAdded.Initialize(AddedEdges); itAdded.More(); itAdded.Next()) {
320       const TopoDS_Edge& E = TopoDS::Edge(itAdded.Value());
321       //-----------------------
322       //  E => New edges;
323       //-----------------------
324       if (Image.HasImage(E)) {
325         Image.Add(E,Loops.NewEdges(E));
326       }
327       else {
328         Image.Bind(E,Loops.NewEdges(E));
329       }
330     }
331   }
332   Loops.GetVerticesForSubstitute( myVerVerMap );
333   if (myVerVerMap.IsEmpty())
334     return;
335   BRep_Builder BB;
336   for (it.Initialize( LContext ); it.More(); it.Next())
337     {
338       TopoDS_Shape F = it.Value();
339       TopTools_ListOfShape LIF;
340       Image.LastImage( F, LIF );
341       for (itl.Initialize(LIF); itl.More(); itl.Next())
342         {
343           const TopoDS_Shape& IF = itl.Value();
344           TopExp_Explorer EdExp( IF, TopAbs_EDGE );
345           for (; EdExp.More(); EdExp.Next())
346             {
347               TopoDS_Shape E = EdExp.Current();
348               TopTools_ListOfShape VList;
349               TopoDS_Iterator VerExp( E );
350               for (; VerExp.More(); VerExp.Next())
351                 VList.Append( VerExp.Value() );
352               TopTools_ListIteratorOfListOfShape itlv( VList );
353               for (; itlv.More(); itlv.Next())
354                 {
355                   const TopoDS_Shape& V = itlv.Value();
356                   if (myVerVerMap.IsBound( V ))
357                     {
358                       TopoDS_Shape NewV = myVerVerMap( V );
359                       E.Free( Standard_True );
360                       NewV.Orientation( V.Orientation() );
361                       Handle(BRep_TVertex)& TV = *((Handle(BRep_TVertex)*) &V.TShape());
362                       Handle(BRep_TVertex)& NewTV = *((Handle(BRep_TVertex)*) &NewV.TShape());
363                       if (TV->Tolerance() > NewTV->Tolerance())
364                         NewTV->Tolerance( TV->Tolerance() );
365                       NewTV->ChangePoints().Append( TV->ChangePoints() );
366                       AsDes->Replace( V, NewV );
367                       BB.Remove( E, V );
368                       BB.Add( E, NewV );
369                     }
370                 }
371             }
372         }
373     }
374 }
375
376
377 //=======================================================================
378 //function : BuildFaces
379 //purpose  : 
380 //=======================================================================
381   
382 void BRepOffset_MakeLoops::BuildFaces(const TopTools_ListOfShape&   LF, 
383                                       const Handle(BRepAlgo_AsDes)& AsDes, 
384                                       BRepAlgo_Image&               Image)
385 {
386   TopTools_ListIteratorOfListOfShape itr,itl,itLCE;
387   Standard_Boolean                   ToRebuild;
388   BRepAlgo_Loop                    Loops;
389   Loops.VerticesForSubstitute( myVerVerMap );
390   BRep_Builder                       B;
391
392   //----------------------------------
393   // Loop on all faces //.
394   //----------------------------------
395   for (itr.Initialize(LF); itr.More(); itr.Next()) {
396     TopoDS_Face F = TopoDS::Face(itr.Value());
397     Loops.Init(F);
398     ToRebuild = Standard_False;
399     TopTools_ListOfShape        AddedEdges;
400     
401     if (!Image.HasImage(F)) {
402       //----------------------------------
403       // Face F not yet reconstructed.
404       //----------------------------------
405       const TopTools_ListOfShape& LE = AsDes->Descendant(F);
406       //----------------------------------------------------------------
407       // first loop to find if the edges of the face were reconstructed.
408       // - maj on map MONV. Some vertices on reconstructed edges
409       // coincide geometrically with old but are not IsSame.
410       //----------------------------------------------------------------
411       TopTools_DataMapOfShapeShape MONV;
412       TopoDS_Vertex OV1,OV2,NV1,NV2;
413       
414       for (itl.Initialize(LE); itl.More(); itl.Next()) {
415         TopoDS_Edge E = TopoDS::Edge(itl.Value());
416         if (Image.HasImage(E)) {
417           const TopTools_ListOfShape& LCE = Image.Image(E);
418           if (LCE.Extent() == 1 && LCE.First().IsSame(E)) {
419             TopoDS_Shape aLocalShape = LCE.First().Oriented(E.Orientation());
420             TopoDS_Edge CE = TopoDS::Edge(aLocalShape);
421 //          TopoDS_Edge CE = TopoDS::Edge(LCE.First().Oriented(E.Orientation()));
422             Loops.AddConstEdge(CE);
423             continue;
424           }
425           //----------------------------------
426           // F should be reconstructed.
427           //----------------------------------
428           ToRebuild = Standard_True;
429           for (itLCE.Initialize(LCE); itLCE.More(); itLCE.Next()) {
430             TopoDS_Shape aLocalShape = itLCE.Value().Oriented(E.Orientation());
431             TopoDS_Edge CE = TopoDS::Edge(aLocalShape); 
432 //          TopoDS_Edge CE = TopoDS::Edge(itLCE.Value().Oriented(E.Orientation())); 
433             TopExp::Vertices (E ,OV1,OV2);
434             TopExp::Vertices (CE,NV1,NV2);
435             if (!OV1.IsSame(NV1)) MONV.Bind(OV1,NV1);
436             if (!OV2.IsSame(NV2)) MONV.Bind(OV2,NV2);
437             Loops.AddConstEdge(CE);
438           }
439         }
440       }
441       if (ToRebuild) {
442 #ifdef DRAW
443         if ( Affich) {
444           char name[256];
445           sprintf(name,"CF_%d",NbF++);
446           DBRep::Set(name,F);
447         }
448 #endif
449
450         //-----------------------------------------------------------
451         // Non-reconstructed edges on other faces are added.  
452         // If their vertices were reconstructed they are reconstructed.
453         //-----------------------------------------------------------
454         for (itl.Initialize(LE); itl.More(); itl.Next()) {
455           Standard_Real f,l;
456           TopoDS_Edge E = TopoDS::Edge(itl.Value());
457           BRep_Tool::Range(E,f,l);
458           if (!Image.HasImage(E)) {
459             TopExp::Vertices (E,OV1,OV2);
460             TopTools_ListOfShape LV;
461             if (MONV.IsBound(OV1)) {
462               TopoDS_Vertex VV = TopoDS::Vertex(MONV(OV1));
463               VV.Orientation(TopAbs_FORWARD);
464               LV.Append(VV);
465               TopoDS_Shape aLocalShape = VV.Oriented(TopAbs_INTERNAL);
466               B.UpdateVertex(TopoDS::Vertex(aLocalShape),
467                              f,E,BRep_Tool::Tolerance(VV));
468             }
469             if (MONV.IsBound(OV2)) {
470               TopoDS_Vertex VV = TopoDS::Vertex(MONV(OV2));
471               VV.Orientation(TopAbs_REVERSED);
472               LV.Append(VV);
473               TopoDS_Shape aLocalShape = VV.Oriented(TopAbs_INTERNAL);
474               B.UpdateVertex(TopoDS::Vertex(aLocalShape),
475                              l,E,BRep_Tool::Tolerance(VV));
476 //            B.UpdateVertex(TopoDS::Vertex(VV.Oriented(TopAbs_INTERNAL)),
477 //                           l,E,BRep_Tool::Tolerance(VV));
478             }
479             if (LV.IsEmpty()) Loops.AddConstEdge(E);
480             else  {
481               Loops.AddEdge    (E,LV);
482               AddedEdges.Append(E);
483             }
484           }
485         }
486       }  
487     }
488     if (ToRebuild) {
489       //------------------------
490       // Reconstruction.
491       //------------------------
492       Loops.Perform();
493       Loops.WiresToFaces();
494       //------------------------
495       // MAJ SD.
496       //------------------------
497       const TopTools_ListOfShape&  NF = Loops.NewFaces();
498       //-----------------------
499       // F => New faces;
500       //-----------------------
501       Image.Bind(F,NF); 
502
503       TopTools_ListIteratorOfListOfShape itAdded;
504       for (itAdded.Initialize(AddedEdges); itAdded.More(); itAdded.Next()) {
505         const TopoDS_Edge& E = TopoDS::Edge(itAdded.Value());
506         //-----------------------
507         //  E => New edges;
508         //-----------------------
509         if (Image.HasImage(E)) {
510           Image.Add(E,Loops.NewEdges(E));
511         }
512         else {
513           Image.Bind(E,Loops.NewEdges(E));
514         }
515       }
516     }
517   }
518   Loops.GetVerticesForSubstitute( myVerVerMap );
519   if (myVerVerMap.IsEmpty())
520     return;
521   BRep_Builder BB;
522   for (itr.Initialize( LF ); itr.More(); itr.Next())
523     {
524       TopoDS_Shape F = itr.Value();
525       TopTools_ListOfShape LIF;
526       Image.LastImage( F, LIF );
527       for (itl.Initialize(LIF); itl.More(); itl.Next())
528         {
529           const TopoDS_Shape& IF = itl.Value();
530           TopExp_Explorer EdExp( IF, TopAbs_EDGE );
531           for (; EdExp.More(); EdExp.Next())
532             {
533               TopoDS_Shape E = EdExp.Current();
534               TopTools_ListOfShape VList;
535               TopoDS_Iterator VerExp( E );
536               for (; VerExp.More(); VerExp.Next())
537                 VList.Append( VerExp.Value() );
538               TopTools_ListIteratorOfListOfShape itlv( VList );
539               for (; itlv.More(); itlv.Next())
540                 {
541                   const TopoDS_Shape& V = itlv.Value();
542                   if (myVerVerMap.IsBound( V ))
543                     {
544                       TopoDS_Shape NewV = myVerVerMap( V );
545                       E.Free( Standard_True );
546                       NewV.Orientation( V.Orientation() );
547                       Handle(BRep_TVertex)& TV = *((Handle(BRep_TVertex)*) &V.TShape());
548                       Handle(BRep_TVertex)& NewTV = *((Handle(BRep_TVertex)*) &NewV.TShape());
549                       if (TV->Tolerance() > NewTV->Tolerance())
550                         NewTV->Tolerance( TV->Tolerance() );
551                       NewTV->ChangePoints().Append( TV->ChangePoints() );
552                       AsDes->Replace( V, NewV );
553                       BB.Remove( E, V );
554                       BB.Add( E, NewV );
555                     }
556                 }
557             }
558         }
559     }
560 }