d2ff2f66e745a34101085910fa29b8bffc768d2c
[occt.git] / src / BRepOffset / BRepOffset_MakeOffset.cxx
1 // Created on: 1995-10-27
2 // Created by: Yves FRICAUD
3 // Copyright (c) 1995-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 //  Modified by skv - Tue Mar 15 16:20:43 2005
18 // Add methods for supporting history.
19
20 //  Modified by skv - Mon Jan 12 11:50:02 2004 OCC4455
21
22 #include <BRepOffset_MakeOffset.ixx>
23 #include <BRepOffset_Analyse.hxx>
24 #include <BRepOffset_DataMapOfShapeOffset.hxx> 
25 #include <BRepOffset_DataMapOfShapeMapOfShape.hxx>
26 #include <BRepOffset_DataMapIteratorOfDataMapOfShapeOffset.hxx>
27 #include <BRepOffset_Interval.hxx>
28 #include <BRepOffset_ListOfInterval.hxx>
29 #include <BRepOffset_Offset.hxx>
30 #include <BRepOffset_Tool.hxx>
31 #include <BRepOffset_Inter2d.hxx>
32 #include <BRepOffset_Inter3d.hxx>
33 #include <BRepOffset_MakeLoops.hxx>
34
35
36 #include <BRepAdaptor_Surface.hxx>
37 #include <BRepCheck_Edge.hxx>
38 #include <BRepCheck_Vertex.hxx>
39 #include <BRepLib.hxx>
40 #include <BRepLib_MakeVertex.hxx>
41 #include <BRep_Builder.hxx>
42 #include <BRep_Tool.hxx>
43 #include <BRep_TVertex.hxx>
44 #include <BRepTools_Quilt.hxx>
45 #include <BRepClass3d_SolidClassifier.hxx>
46 #include <gp_Pnt.hxx>
47
48 #include <TopExp.hxx>
49 #include <TopExp_Explorer.hxx>
50 #include <TopoDS.hxx>
51 #include <TopoDS_Solid.hxx>
52 #include <TopoDS_Shell.hxx>
53 #include <TopoDS_Compound.hxx>
54 #include <TopoDS_Face.hxx>
55 #include <TopoDS_Edge.hxx>
56 #include <TopoDS_Vertex.hxx>
57
58 #include <TopTools_MapOfShape.hxx>
59 #include <TopTools_MapIteratorOfMapOfShape.hxx>
60 #include <TopTools_ListOfShape.hxx>
61 #include <TopTools_ListIteratorOfListOfShape.hxx>
62 #include <TopTools_DataMapOfShapeShape.hxx>
63 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
64 #include <TopTools_DataMapIteratorOfDataMapOfShapeReal.hxx>
65 #include <TColStd_ListIteratorOfListOfInteger.hxx>
66
67 #include <Standard_NotImplemented.hxx>
68 #include <Standard_ConstructionError.hxx>
69 #include <Precision.hxx>
70
71 #include <TopTools_SequenceOfShape.hxx>
72 #include <Geom_OffsetSurface.hxx>
73 #include <Geom_ConicalSurface.hxx>
74 #include <TopTools_IndexedMapOfShape.hxx>
75 #include <BRep_TEdge.hxx>
76 #include <BRepTools.hxx>
77 #include <gp_Cone.hxx>
78 #include <ElSLib.hxx>
79 #include <ElCLib.hxx>
80 #include <gp_Lin2d.hxx>
81 #include <GCE2d_MakeLine.hxx>
82 #include <Geom2d_Line.hxx>
83 #include <TopoDS_Iterator.hxx>
84 #include <BRepLib_MakeFace.hxx>
85 #include <Geom_Circle.hxx>
86
87 #include <BRep_PointRepresentation.hxx>
88 #include <BRep_ListIteratorOfListOfPointRepresentation.hxx>
89 #include <GeomAPI_ProjectPointOnCurve.hxx>
90
91 #include <BRepAdaptor_Curve.hxx>
92 #include <BRepAdaptor_Curve2d.hxx>
93 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
94 #include <Geom_SphericalSurface.hxx>
95 #include <TopoDS_Wire.hxx>
96 #include <BRepTools_Substitution.hxx>
97 #include <Geom_TrimmedCurve.hxx>
98 #include <Geom2d_TrimmedCurve.hxx>
99
100 #include <BRepTools_WireExplorer.hxx>
101 #include <BRepLib_MakeEdge.hxx>
102 #include <gce_MakeDir.hxx>
103 #include <GC_MakeCylindricalSurface.hxx>
104 #include <gce_MakeCone.hxx>
105 #include <Geom_SurfaceOfLinearExtrusion.hxx>
106
107 #include <Geom2dAdaptor_HCurve.hxx>
108 #include <GeomAdaptor_HSurface.hxx>
109 #include <Adaptor3d_CurveOnSurface.hxx>
110 #include <GeomLib.hxx>
111 #include <GeomFill_Generator.hxx>
112 #include <Geom_Plane.hxx>
113 #include <IntTools_FClass2d.hxx>
114 #include <BRepLib_FindSurface.hxx>
115
116
117 // POP for NT
118 #include <stdio.h>
119
120 #ifdef DRAW
121
122 #include <DBRep.hxx>
123 #endif
124 #ifdef OCCT_DEBUG
125 #include <OSD_Chronometer.hxx>
126 //#define DEB_VERB
127   Standard_Boolean AffichInt2d = Standard_False;       
128   Standard_Boolean AffichOffC  = Standard_False;       
129   Standard_Boolean ChronBuild  = Standard_False;
130   Standard_Integer NbAE        = 0;
131   Standard_Integer NbAF        = 0;  
132   static OSD_Chronometer  Clock;
133   char name[100];
134
135
136
137
138 //=======================================================================
139 //function :  DEBVerticesControl
140 //purpose  : 
141 //=======================================================================
142
143 static void DEBVerticesControl (const TopTools_IndexedMapOfShape& NewEdges,
144                                       Handle(BRepAlgo_AsDes)      AsDes)
145 {
146   TopTools_ListOfShape               LVP;
147   TopTools_ListIteratorOfListOfShape it1LE ;    
148   TopTools_ListIteratorOfListOfShape it2LE ;
149   
150   Standard_Integer i;
151   for (i = 1; i <= NewEdges.Extent(); i++) {
152     const TopoDS_Edge& NE = TopoDS::Edge(NewEdges(i));
153     if (AsDes->HasDescendant(NE)) {
154       for (it1LE.Initialize(AsDes->Descendant(NE)); it1LE.More(); it1LE.Next()) {
155         if (AsDes->Ascendant(it1LE.Value()).Extent() < 3) {
156           LVP.Append(it1LE.Value());
157           cout <<"Vertex on at least 3 edges."<<endl;
158 #ifdef DRAW
159           if (AffichInt2d) {
160             sprintf (name,"VP_%d",NVP++);
161             DBRep::Set(name,it1LE.Value());
162           }
163 #endif
164         }
165         else if (AsDes->Ascendant(it1LE.Value()).Extent() > 3) {
166           cout <<"Vertex on more than 3 edges."<<endl;
167 #ifdef DRAW
168           if (AffichInt2d) {
169             sprintf (name,"VM_%d",NVM++);
170             DBRep::Set(name,it1LE.Value());
171           }
172 #endif
173           
174         }
175         else {
176 #ifdef DRAW
177           if (AffichInt2d) {
178             sprintf (name,"VN_%d",NVN++);
179             DBRep::Set(name,it1LE.Value());
180           }
181 #endif
182         }
183       }
184     }
185   }
186   //------------------------------------------------
187   // Try to mix spoiled vertices.
188   //------------------------------------------------
189   BRep_Builder B;
190   TopTools_ListIteratorOfListOfShape it1(LVP);
191   Standard_Real                      TolConf = 1.e-5;
192   Standard_Real                      Tol     = Precision::Confusion();
193   //Standard_Integer                   i = 1;
194   
195   i = 1;
196   for ( ; it1.More(); it1.Next()) {
197     TopoDS_Shape   V1 = it1.Value();
198     gp_Pnt         P1 = BRep_Tool::Pnt(TopoDS::Vertex(V1));
199     Standard_Real  distmin = Precision::Infinite();
200     TopTools_ListIteratorOfListOfShape it2(LVP);
201     Standard_Integer j = 1;
202
203     for ( ; it2.More(); it2.Next()) {
204       if (j > i) {
205         TopoDS_Shape V2 = it2.Value();
206         gp_Pnt       P2 = BRep_Tool::Pnt(TopoDS::Vertex(V2));
207         if (!V1.IsSame(V2)) {
208           Standard_Real       dist    = P1.Distance(P2);
209           if (dist < distmin) distmin = dist;
210           if (dist < TolConf) {
211             Standard_Real UV2;
212             TopoDS_Edge   EWE2;
213             const TopTools_ListOfShape& EdgeWithV2 = AsDes->Ascendant(V2);
214             TopTools_ListIteratorOfListOfShape itAsDes;
215             for (itAsDes.Initialize(EdgeWithV2); itAsDes.More(); itAsDes.Next()) {
216               EWE2  = TopoDS::Edge(itAsDes.Value());
217               TopoDS_Shape aLocalShape = V2.Oriented(TopAbs_INTERNAL);
218               UV2   = BRep_Tool::Parameter(TopoDS::Vertex(aLocalShape),EWE2);
219               aLocalShape = V1.Oriented(TopAbs_INTERNAL) ;
220               B.UpdateVertex(TopoDS::Vertex(aLocalShape),UV2,EWE2,Tol);
221 //            UV2   = 
222 //              BRep_Tool::Parameter(TopoDS::Vertex(),EWE2);
223 //            B.UpdateVertex(TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)),
224 //                           UV2,EWE2,Tol);
225             }
226             AsDes->Replace(V2,V1);
227           }
228         }
229       }
230       j++;
231     }
232     i++;
233     cout <<" distmin between VP : "<<distmin<<endl;
234   }
235 }  
236 #endif
237
238
239 static void UpdateTolerance (      TopoDS_Shape&               myShape,
240                              const TopTools_IndexedMapOfShape& myFaces);
241
242
243 static Standard_Boolean FindParameter(const TopoDS_Vertex& V, 
244                                       const TopoDS_Edge& E,
245                                       Standard_Real& U)
246 {
247   // Search the vertex in the edge
248
249   Standard_Boolean rev = Standard_False;
250   TopoDS_Shape VF;
251   TopAbs_Orientation orient = TopAbs_INTERNAL;
252
253   TopoDS_Iterator itv(E.Oriented(TopAbs_FORWARD));
254
255   // if the edge has no vertices
256   // and is degenerated use the vertex orientation
257   // RLE, june 94
258
259   if (!itv.More() && BRep_Tool::Degenerated(E)) {
260     orient = V.Orientation();
261   }
262
263   while (itv.More()) {
264     const TopoDS_Shape& Vcur = itv.Value();
265     if (V.IsSame(Vcur)) {
266       if (VF.IsNull()) {
267         VF = Vcur;
268       }
269       else {
270         rev = E.Orientation() == TopAbs_REVERSED;
271         if (Vcur.Orientation() == V.Orientation()) {
272           VF = Vcur;
273         }
274       }
275     }
276     itv.Next();
277   }
278   
279   if (!VF.IsNull()) orient = VF.Orientation();
280  
281   Standard_Real f,l;
282
283   if (orient ==  TopAbs_FORWARD) {
284     BRep_Tool::Range(E,f,l);
285     //return (rev) ? l : f;
286     U = (rev) ? l : f;
287     return Standard_True;
288   }
289  
290   else if (orient ==  TopAbs_REVERSED) {
291     BRep_Tool::Range(E,f,l);
292     //return (rev) ? f : l;
293     U = (rev) ? f : l;
294     return Standard_True;
295    }
296
297   else {
298     TopLoc_Location L;
299     const Handle(Geom_Curve)& C = BRep_Tool::Curve(E,L,f,l);
300     L = L.Predivided(V.Location());
301     if (!C.IsNull() || BRep_Tool::Degenerated(E)) {
302       BRep_ListIteratorOfListOfPointRepresentation itpr
303         ((*((Handle(BRep_TVertex)*) &V.TShape()))->Points());
304
305       while (itpr.More()) {
306         const Handle(BRep_PointRepresentation)& pr = itpr.Value();
307         if (pr->IsPointOnCurve(C,L)) {
308           Standard_Real p = pr->Parameter();
309           Standard_Real res = p;// SVV 4 nov 99 - to avoid warnings on Linux
310           if (!C.IsNull()) {
311             // Closed curves RLE 16 june 94
312             if (Precision::IsNegativeInfinite(f))
313               {
314                 //return pr->Parameter();//p;
315                 U = pr->Parameter();
316                 return Standard_True;
317               }
318             if (Precision::IsPositiveInfinite(l))
319               {
320                 //return pr->Parameter();//p;
321                 U = pr->Parameter();
322                 return Standard_True;
323               }
324             gp_Pnt Pf = C->Value(f).Transformed(L.Transformation());
325             gp_Pnt Pl = C->Value(l).Transformed(L.Transformation());
326             Standard_Real tol = BRep_Tool::Tolerance(V);
327             if (Pf.Distance(Pl) < tol) {
328               if (Pf.Distance(BRep_Tool::Pnt(V)) < tol) {
329                 if (V.Orientation() == TopAbs_FORWARD) res = f;//p = f;
330                 else                                   res = l;//p = l;
331               }
332             }
333           }
334           //return res;//p;
335           U = res;
336           return Standard_True;
337         }
338         itpr.Next();
339       }
340     }
341     else {
342       // no 3d curve !!
343       // let us try with the first pcurve
344       Handle(Geom2d_Curve) PC;
345       Handle(Geom_Surface) S;
346       BRep_Tool::CurveOnSurface(E,PC,S,L,f,l);
347       L = L.Predivided(V.Location()); 
348       BRep_ListIteratorOfListOfPointRepresentation itpr
349         ((*((Handle(BRep_TVertex)*) &V.TShape()))->Points());
350
351       while (itpr.More()) {
352         const Handle(BRep_PointRepresentation)& pr = itpr.Value();
353         if (pr->IsPointOnCurveOnSurface(PC,S,L)) {
354           Standard_Real p = pr->Parameter();
355           // Closed curves RLE 16 june 94
356           if (PC->IsClosed()) {
357             if ((p == PC->FirstParameter()) || 
358                 (p == PC->LastParameter())) {
359               if (V.Orientation() == TopAbs_FORWARD) p = PC->FirstParameter();
360               else                                   p = PC->LastParameter();
361             }
362           }
363           //return p;
364           U = p;
365           return Standard_True;
366         }
367         itpr.Next();
368       }
369     }
370   }
371   
372   //Standard_NoSuchObject::Raise("BRep_Tool:: no parameter on edge");
373   return Standard_False;
374 }
375
376 //=======================================================================
377 //function : GetEdgePoints
378 //purpose  : gets the first, last and middle points of the edge
379 //=======================================================================
380 static void GetEdgePoints(const TopoDS_Edge& anEdge,
381                                       const TopoDS_Face& aFace,
382                                       gp_Pnt& fPnt, gp_Pnt& mPnt,
383                                       gp_Pnt& lPnt)
384 {
385   Standard_Real f, l;
386   Handle(Geom2d_Curve) theCurve = BRep_Tool::CurveOnSurface( anEdge, aFace, f, l );
387   gp_Pnt2d fPnt2d = theCurve->Value(f);
388   gp_Pnt2d lPnt2d = theCurve->Value(l);
389   gp_Pnt2d mPnt2d = theCurve->Value(0.5*(f + l));
390   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
391   fPnt = aSurf->Value(fPnt2d.X(),fPnt2d.Y());
392   lPnt = aSurf->Value(lPnt2d.X(),lPnt2d.Y());
393   mPnt = aSurf->Value(mPnt2d.X(), mPnt2d.Y());
394 }
395
396 //=======================================================================
397 //function : FillContours
398 //purpose  : fills free boundary contours and faces connected (MapEF)
399 //=======================================================================
400 static void FillContours(const TopoDS_Shape& aShape,
401                          const BRepOffset_Analyse& Analyser,
402                          TopTools_DataMapOfShapeListOfShape& Contours,
403                          TopTools_DataMapOfShapeShape& MapEF)
404 {
405   TopTools_ListOfShape Edges;
406
407   TopExp_Explorer Explo(aShape, TopAbs_FACE);
408   BRepTools_WireExplorer Wexp;
409
410   for (; Explo.More(); Explo.Next())
411     {
412       TopoDS_Face aFace = TopoDS::Face(Explo.Current());
413       TopoDS_Iterator itf(aFace);
414       for (; itf.More(); itf.Next())
415         {
416           TopoDS_Wire aWire = TopoDS::Wire(itf.Value());
417           for (Wexp.Init(aWire, aFace); Wexp.More(); Wexp.Next())
418             {
419               TopoDS_Edge anEdge = Wexp.Current();
420               if (BRep_Tool::Degenerated(anEdge))
421                 continue;
422               const BRepOffset_ListOfInterval& Lint = Analyser.Type(anEdge);
423               if (!Lint.IsEmpty() && Lint.First().Type() == BRepOffset_FreeBoundary)
424                 {
425                   MapEF.Bind(anEdge, aFace);
426                   Edges.Append(anEdge);
427                 }
428             }
429         }
430     }
431
432   TopTools_ListIteratorOfListOfShape itl;
433   while (!Edges.IsEmpty())
434     {
435       TopoDS_Edge StartEdge = TopoDS::Edge(Edges.First());
436       Edges.RemoveFirst();
437       TopoDS_Vertex StartVertex, CurVertex;
438       TopExp::Vertices(StartEdge, StartVertex, CurVertex, Standard_True);
439       TopTools_ListOfShape aContour;
440       aContour.Append(StartEdge);
441       while (!CurVertex.IsSame(StartVertex))
442         for (itl.Initialize(Edges); itl.More(); itl.Next())
443           {
444             TopoDS_Edge anEdge = TopoDS::Edge(itl.Value());
445             TopoDS_Vertex V1, V2;
446             TopExp::Vertices(anEdge, V1, V2);
447             if (V1.IsSame(CurVertex) || V2.IsSame(CurVertex))
448               {
449                 aContour.Append(anEdge);
450                 CurVertex = (V1.IsSame(CurVertex))? V2 : V1;
451                 Edges.Remove(itl);
452                 break;
453               }
454           }
455       Contours.Bind(StartVertex, aContour);
456     }
457 }
458
459 //=======================================================================
460 //function : BRepOffset_MakeOffset
461 //purpose  : 
462 //=======================================================================
463
464 BRepOffset_MakeOffset::BRepOffset_MakeOffset()
465 {
466   myAsDes = new BRepAlgo_AsDes();
467 }
468
469
470 //=======================================================================
471 //function : BRepOffset_MakeOffset
472 //purpose  : 
473 //=======================================================================
474
475 BRepOffset_MakeOffset::BRepOffset_MakeOffset(const TopoDS_Shape&    S, 
476                                              const Standard_Real    Offset, 
477                                              const Standard_Real    Tol, 
478                                              const BRepOffset_Mode  Mode, 
479                                              const Standard_Boolean Inter, 
480                                              const Standard_Boolean SelfInter, 
481                                              const GeomAbs_JoinType Join,
482                                              const Standard_Boolean Thickening)
483
484 myOffset     (Offset),
485 myTol        (Tol),
486 myShape      (S),
487 myMode       (Mode),
488 myInter      (Inter),
489 mySelfInter  (SelfInter),
490 myJoin       (Join),
491 myThickening (Thickening),
492 myDone     (Standard_False)
493
494 {
495   myAsDes = new BRepAlgo_AsDes();
496   MakeOffsetShape();
497 }
498
499
500 //=======================================================================
501 //function : Initialize
502 //purpose  : 
503 //=======================================================================
504
505 void BRepOffset_MakeOffset::Initialize(const TopoDS_Shape&    S, 
506                                        const Standard_Real    Offset, 
507                                        const Standard_Real    Tol, 
508                                        const BRepOffset_Mode  Mode,
509                                        const Standard_Boolean Inter,
510                                        const Standard_Boolean SelfInter,
511                                        const GeomAbs_JoinType Join,
512                                        const Standard_Boolean Thickening)
513 {
514   myOffset     = Offset;
515   myShape      = S;
516   myTol        = Tol;
517   myMode       = Mode;
518   myInter      = Inter;
519   mySelfInter  = SelfInter;
520   myJoin       = Join;
521   myThickening = Thickening;
522   myDone     = Standard_False;
523   Clear();
524 }
525
526
527 //=======================================================================
528 //function : Clear
529 //purpose  : 
530 //=======================================================================
531
532 void BRepOffset_MakeOffset::Clear()
533 {
534   myOffsetShape.Nullify();
535   myInitOffsetFace .Clear();
536   myInitOffsetEdge .Clear();
537   myImageOffset    .Clear();
538   myFaces          .Clear();  
539   myFaceOffset     .Clear();
540   myAsDes          ->Clear();
541   myDone     = Standard_False;
542 }
543
544 //=======================================================================
545 //function : AddFace
546 //purpose  : 
547 //=======================================================================
548
549 void BRepOffset_MakeOffset::AddFace(const TopoDS_Face& F) {
550   myFaces.Add(F);    
551   //-------------
552   // MAJ SD.
553   //-------------
554   myInitOffsetFace.SetRoot (F)  ;    
555   myInitOffsetFace.Bind    (F,F);
556   myImageOffset.SetRoot    (F)  ;  
557 }
558
559 //=======================================================================
560 //function : SetOffsetOnFace
561 //purpose  : 
562 //=======================================================================
563
564 void BRepOffset_MakeOffset::SetOffsetOnFace(const TopoDS_Face&  F, 
565                                             const Standard_Real Off)
566 {
567   if ( myFaceOffset.IsBound(F)) myFaceOffset.UnBind(F);
568   myFaceOffset.Bind(F,Off);
569 }
570
571 //=======================================================================
572 //function : RemoveCorks
573 //purpose  : 
574 //=======================================================================
575
576 static void RemoveCorks (TopoDS_Shape&               S,
577                          TopTools_IndexedMapOfShape& Faces)
578 {  
579   TopoDS_Compound SS;
580   BRep_Builder    B;
581   B.MakeCompound (SS);
582   //-----------------------------------------------------
583   // Construction of a shape without caps.
584   // and Orientation of caps as in shape S.
585   //-----------------------------------------------------
586   TopExp_Explorer exp(S,TopAbs_FACE);
587   for (; exp.More(); exp.Next()) {
588     const TopoDS_Shape& Cork = exp.Current(); 
589     if (!Faces.Contains(Cork)) {
590       B.Add(SS,Cork);
591     }
592     else {
593       //Faces.Remove (Cork);
594       //begin instead of Remove//
595       TopoDS_Shape LastShape = Faces(Faces.Extent());
596       Faces.RemoveLast();
597       if (Faces.FindIndex(Cork) != 0)
598         Faces.Substitute(Faces.FindIndex(Cork), LastShape);
599       //end instead of Remove  //
600       Faces.Add(Cork); // to reset it with proper orientation.
601     }
602   }
603   S = SS;
604 #ifdef DRAW
605   if ( AffichOffC) 
606     DBRep::Set("myInit", SS);
607 #endif
608
609 }
610
611 static Standard_Boolean IsConnectedShell( const TopoDS_Shape& S )
612 {  
613   BRepTools_Quilt Glue;
614   Glue.Add( S );
615
616   TopoDS_Shape SS = Glue.Shells();
617   TopExp_Explorer Explo( SS, TopAbs_SHELL );
618   Explo.Next();
619   if (Explo.More())
620     return Standard_False;
621   
622   return Standard_True;
623 }
624
625
626 //=======================================================================
627 //function : MakeList
628 //purpose  : 
629 //=======================================================================
630
631 static void MakeList (TopTools_ListOfShape&             OffsetFaces,
632                       const BRepAlgo_Image&             myInitOffsetFace,
633                       const TopTools_IndexedMapOfShape& myFaces)
634 {
635   TopTools_ListIteratorOfListOfShape itLOF(myInitOffsetFace.Roots());
636   for ( ; itLOF.More(); itLOF.Next()) {
637     const TopoDS_Shape& Root = itLOF.Value();
638     if (!myFaces.Contains(Root))
639       OffsetFaces.Append(myInitOffsetFace.Image(Root).First());
640   }
641 }
642
643 //=======================================================================
644 //function : EvalMax
645 //purpose  : 
646 //=======================================================================
647
648 static void EvalMax(const TopoDS_Shape& S, Standard_Real& Tol)
649 {
650   TopExp_Explorer exp;
651   for (exp.Init(S,TopAbs_VERTEX); exp.More(); exp.Next()) {
652     const TopoDS_Vertex& V    = TopoDS::Vertex(exp.Current());
653     Standard_Real        TolV = BRep_Tool::Tolerance(V); 
654     if (TolV > Tol) Tol = TolV;
655   }
656   //Patch
657   Tol *= 5.;
658 }
659
660 //=======================================================================
661 //function : MakeOffsetShape
662 //purpose  : 
663 //=======================================================================
664
665 void BRepOffset_MakeOffset::MakeOffsetShape()
666 {  
667   myDone     = Standard_False;
668   //------------------------------------------
669   // Construction of myShape without caps.
670   //------------------------------------------
671   RemoveCorks (myShape,myFaces);
672   
673   if (! IsConnectedShell(myShape))
674     Standard_ConstructionError::Raise("BRepOffset_MakeOffset : Incorrect set of faces to remove, the remaining shell is not connected");
675
676   if (Abs(myOffset) < myTol) return;
677
678   TopAbs_State       Side = TopAbs_IN;
679   if (myOffset < 0.) Side = TopAbs_OUT;
680   // ------------
681   // Preanalyse.
682   // ------------
683   EvalMax(myShape,myTol);
684   if (myTol > Abs(myOffset*0.5)) {
685     Standard_ConstructionError::Raise("BRepOffset_MakeOffset : Tol > Offset");
686   }
687   Standard_Real TolAngle = 4*ASin(myTol/Abs(myOffset*0.5));
688   myAnalyse.Perform(myShape,TolAngle);
689   //---------------------------------------------------
690   // Construction of Offset from preanalysis.
691   //---------------------------------------------------  
692   //----------------------------
693   // MaJ of SD Face - Offset
694   //----------------------------
695   UpdateFaceOffset();
696
697   if (myJoin == GeomAbs_Arc)          
698     BuildOffsetByArc();
699   else if (myJoin == GeomAbs_Intersection) 
700     BuildOffsetByInter();
701   //-----------------
702   // Auto unwinding.
703   //-----------------
704   // if (mySelfInter)  SelfInter(Modif);
705   //-----------------
706   // Intersection 3d .
707   //-----------------
708   BRepOffset_Inter3d Inter(myAsDes,Side,myTol);
709   Intersection3D (Inter);
710   //-----------------
711   // Intersection2D
712   //-----------------
713   TopTools_IndexedMapOfShape& Modif    = Inter.TouchedFaces(); 
714   TopTools_IndexedMapOfShape& NewEdges = Inter.NewEdges();
715
716   if (!Modif.IsEmpty()) Intersection2D (Modif,NewEdges);
717   //-------------------------------------------------------
718   // Unwinding 2D and reconstruction of modified faces
719   //----------------------------------------------------
720   MakeLoops (Modif);
721   //-----------------------------------------------------
722   // Reconstruction of non modified faces sharing 
723   // reconstructed edges
724   //------------------------------------------------------
725   if (!Modif.IsEmpty()) MakeFaces (Modif);
726
727   if (myThickening)
728     MakeMissingWalls();
729
730   //-------------------------
731   // Construction of shells.
732   //-------------------------
733   MakeShells ();
734   //--------------
735   // Unwinding 3D.
736   //--------------
737   SelectShells ();
738   //----------------------------------
739   // Coding of regularities.
740   //----------------------------------
741   EncodeRegularity();
742   //----------------------
743   // Creation of solids.
744   //----------------------
745   MakeSolid ();
746
747   //-----------------------------
748   // MAJ Tolerance edge and Vertex
749   // ----------------------------
750   if (!myOffsetShape.IsNull()) {
751     UpdateTolerance (myOffsetShape,myFaces);
752     BRepLib::UpdateTolerances( myOffsetShape );
753   }
754
755   CorrectConicalFaces();
756
757   myDone = Standard_True;
758 }
759
760
761
762 //=======================================================================
763 //function : MakeThickSolid
764 //purpose  : 
765 //=======================================================================
766
767 void BRepOffset_MakeOffset::MakeThickSolid() 
768 {
769   //--------------------------------------------------------------
770   // Construction of shell parallel to shell (initial without cap).
771   //--------------------------------------------------------------
772   MakeOffsetShape ();
773
774   //--------------------------------------------------------------------
775   // Construction of a solid with the initial shell, parallel shell 
776   // limited by caps.
777   //--------------------------------------------------------------------
778   if (!myFaces.IsEmpty()) {
779     TopoDS_Solid    Res;
780     TopExp_Explorer exp;
781     BRep_Builder    B;
782     Standard_Integer NbF = myFaces.Extent();
783
784     B.MakeSolid(Res);
785
786     BRepTools_Quilt Glue;
787     for (exp.Init(myShape,TopAbs_FACE); exp.More(); exp.Next()) {
788       NbF++;
789       Glue.Add (exp.Current());
790     } 
791     Standard_Boolean YaResult = 0;
792     if (!myOffsetShape.IsNull())
793       {
794       for (exp.Init(myOffsetShape,TopAbs_FACE);exp.More(); exp.Next())
795         {
796         YaResult = 1;
797         Glue.Add (exp.Current().Reversed());
798         }
799 #ifdef OCCT_DEBUG
800       if(YaResult == 0)
801         {
802         cout << "OffsetShape does not contain a FACES." << endl;
803         }
804 #endif
805       }
806 #ifdef OCCT_DEBUG
807     else
808       {
809       cout << "OffsetShape is null!" << endl;
810       }
811 #endif
812
813     if (YaResult == 0)
814       {
815       myDone = Standard_False;
816       return;
817       }
818
819     myOffsetShape = Glue.Shells();
820     for (exp.Init(myOffsetShape,TopAbs_SHELL); exp.More(); exp.Next()) {
821       B.Add(Res,exp.Current());
822     }
823     Res.Closed(Standard_True);
824     myOffsetShape = Res;
825
826     // Test of Validity of the result of thick Solid 
827     // more face than the initial solid.
828         
829     Standard_Integer NbOF = 0;
830     for (exp.Init(myOffsetShape,TopAbs_FACE);exp.More(); exp.Next()) {
831       NbOF++;
832     }
833     if (NbOF <= NbF) {
834       myDone = Standard_False;
835       return;
836     }
837   }
838
839   if (myOffset > 0 ) myOffsetShape.Reverse();  
840
841   myDone = Standard_True;
842 }
843
844 //=======================================================================
845 //function : IsDone
846 //purpose  : 
847 //=======================================================================
848
849 Standard_Boolean BRepOffset_MakeOffset::IsDone() const
850 {
851   return myDone;
852 }
853
854 //=======================================================================
855 //function : Error
856 //purpose  : 
857 //=======================================================================
858
859 BRepOffset_Error BRepOffset_MakeOffset::Error() const
860 {
861   return myError;
862 }
863
864 //=======================================================================
865 //function : Shape
866 //purpose  : 
867 //=======================================================================
868
869 const TopoDS_Shape&  BRepOffset_MakeOffset::Shape() const 
870 {
871   return myOffsetShape;
872 }
873
874 //=======================================================================
875 //function : TrimEdge
876 //purpose  : Trim the edge of the largest of descendants in AsDes2d.
877 //           Order in AsDes two vertices that have trimmed the edge.
878 //=======================================================================
879
880 static void TrimEdge (TopoDS_Edge&                  NE,
881                       const Handle(BRepAlgo_AsDes)& AsDes2d,
882                             Handle(BRepAlgo_AsDes)& AsDes)
883 {
884   Standard_Real aSameParTol = Precision::Confusion();
885   
886   TopoDS_Vertex V1,V2;
887   Standard_Real U = 0.;
888   Standard_Real UMin =  Precision::Infinite();
889   Standard_Real UMax = -UMin;
890
891   const TopTools_ListOfShape& LE = AsDes2d->Descendant(NE);
892   
893   if (LE.Extent() > 1) {
894     TopTools_ListIteratorOfListOfShape it (LE);
895     for (; it.More(); it.Next()) {
896       TopoDS_Vertex V = TopoDS::Vertex(it.Value());
897       if (NE.Orientation() == TopAbs_REVERSED)
898         V.Reverse();
899       //V.Orientation(TopAbs_INTERNAL);
900       if (!FindParameter(V, NE, U))
901         {
902           Standard_Real f, l;
903           Handle(Geom_Curve) theCurve = BRep_Tool::Curve(NE, f, l);
904           gp_Pnt thePoint = BRep_Tool::Pnt(V);
905           GeomAPI_ProjectPointOnCurve Projector(thePoint, theCurve);
906           if (Projector.NbPoints() == 0)
907             Standard_ConstructionError::Raise("BRepOffset_MakeOffset::TrimEdge no projection");
908           U = Projector.LowerDistanceParameter();
909         }
910       if (U < UMin) {
911         UMin = U; V1   = V;
912       }
913       if (U > UMax) {
914         UMax = U; V2   = V;
915       }
916     }
917     if (V1.IsNull() || V2.IsNull()) {
918       Standard_ConstructionError::Raise("BRepOffset_MakeOffset::TrimEdge");
919     }
920     if (!V1.IsSame(V2)) {
921       NE.Free( Standard_True );
922       BRep_Builder B;
923       TopAbs_Orientation Or = NE.Orientation();
924       NE.Orientation(TopAbs_FORWARD);
925       TopoDS_Vertex VF,VL;
926       TopExp::Vertices (NE,VF,VL);
927       B.Remove(NE,VF);
928       B.Remove(NE,VL);
929       B.Add  (NE,V1.Oriented(TopAbs_FORWARD));
930       B.Add  (NE,V2.Oriented(TopAbs_REVERSED));
931       B.Range(NE,UMin,UMax);
932       NE.Orientation(Or);
933       AsDes->Add(NE,V1.Oriented(TopAbs_FORWARD));
934       AsDes->Add(NE,V2.Oriented(TopAbs_REVERSED));
935       BRepLib::SameParameter(NE, aSameParTol, Standard_True);
936     }
937   }
938 }
939
940 //=======================================================================
941 //function : BuildOffsetByInter
942 //purpose  : 
943 //=======================================================================
944 void BRepOffset_MakeOffset::BuildOffsetByInter()
945 {
946 #ifdef OCCT_DEBUG
947   if ( ChronBuild) {
948     cout << " CONSTRUCTION OF OFFSETS :" << endl;
949     Clock.Reset();
950     Clock.Start();
951   }
952 #endif
953
954   BRepOffset_DataMapOfShapeOffset MapSF;
955   TopTools_MapOfShape             Done;
956   Standard_Boolean OffsetOutside = (myOffset > 0.)? Standard_True : Standard_False;
957   //--------------------------------------------------------
958   // Construction of faces parallel to initial faces
959   //--------------------------------------------------------
960   TopExp_Explorer Exp;
961   TopTools_ListOfShape LF;
962   TopTools_ListIteratorOfListOfShape itLF;
963
964   BRepLib::SortFaces(myShape,LF);
965
966   TopTools_DataMapOfShapeShape ShapeTgt;
967   for (itLF.Initialize(LF); itLF.More(); itLF.Next()) {
968     const TopoDS_Face&   F = TopoDS::Face(itLF.Value());
969     Standard_Real CurOffset = myOffset;
970     if (myFaceOffset.IsBound(F)) CurOffset = myFaceOffset(F);
971     BRepOffset_Offset    OF(F,CurOffset,ShapeTgt,OffsetOutside,myJoin);
972     TopTools_ListOfShape Let;
973     myAnalyse.Edges(F,BRepOffset_Tangent,Let);
974     TopTools_ListIteratorOfListOfShape itl(Let);
975     
976     for ( ; itl.More(); itl.Next()) {
977       const TopoDS_Edge& Cur = TopoDS::Edge(itl.Value());
978       if ( !ShapeTgt.IsBound(Cur)) {
979         TopoDS_Shape aLocalShape = OF.Generated(Cur);
980         const TopoDS_Edge& OTE = TopoDS::Edge(aLocalShape);
981 //      const TopoDS_Edge& OTE = TopoDS::Edge(OF.Generated(Cur));
982         ShapeTgt.Bind(Cur,OF.Generated(Cur));
983         TopoDS_Vertex V1,V2,OV1,OV2;
984         TopExp::Vertices (Cur,V1,V2);
985         TopExp::Vertices (OTE,OV1,OV2);      
986         TopTools_ListOfShape LE;
987         if (!ShapeTgt.IsBound(V1)) {
988           myAnalyse.Edges(V1,BRepOffset_Tangent,LE);
989           const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V1);
990           if (LE.Extent() == LA.Extent())
991             ShapeTgt.Bind(V1,OV1);
992         }
993         if (!ShapeTgt.IsBound(V2)) {
994           LE.Clear();
995           myAnalyse.Edges(V2,BRepOffset_Tangent,LE);
996           const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V2);
997           if (LE.Extent() == LA.Extent())
998             ShapeTgt.Bind(V2,OV2);
999         }
1000       }
1001     }
1002     MapSF.Bind(F,OF);
1003   }
1004   //--------------------------------------------------------------------
1005   // MES   : Map of OffsetShape -> Extended Shapes.
1006   // Build : Map of Initial SS  -> OffsetShape build by Inter.
1007   //                               can be an edge or a compound of edges       
1008   //---------------------------------------------------------------------
1009   TopTools_DataMapOfShapeShape MES;  
1010   TopTools_DataMapOfShapeShape Build; 
1011   TopTools_ListOfShape         Failed;
1012   TopAbs_State                 Side = TopAbs_IN;  
1013   Handle(BRepAlgo_AsDes)       AsDes = new BRepAlgo_AsDes();
1014
1015   //-------------------------------------------------------------------
1016   // Extension of faces and calculation of new edges of intersection.
1017   //-------------------------------------------------------------------
1018   Standard_Boolean  ExtentContext = 0;
1019   if (myOffset > 0) ExtentContext = 1;
1020
1021   BRepOffset_Inter3d Inter3 (AsDes,Side,myTol);
1022   // Intersection between parallel faces
1023   Inter3.ConnexIntByInt(myShape,MapSF,myAnalyse,MES,Build,Failed );
1024   // Intersection with caps.
1025   Inter3.ContextIntByInt(myFaces,ExtentContext,MapSF,myAnalyse,MES,Build,Failed );
1026
1027
1028   //---------------------------------------------------------------------------------
1029   // Extension of neighbor edges of new edges and intersection between neighbors.
1030   //--------------------------------------------------------------------------------
1031   Handle(BRepAlgo_AsDes) AsDes2d = new BRepAlgo_AsDes();
1032   for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
1033     const TopoDS_Face& FI = TopoDS::Face(Exp.Current());
1034 //  Modified by skv - Mon Jan 12 11:50:02 2004 OCC4455 Begin
1035 //    BRepOffset_Inter2d::ConnexIntByInt (FI,MapSF(FI),MES,Build,AsDes2d,myTol);
1036     BRepOffset_Inter2d::ConnexIntByInt (FI,MapSF(FI),MES,Build,AsDes2d,myOffset, myTol);
1037 //  Modified by skv - Mon Jan 12 11:50:03 2004 OCC4455 End
1038   }
1039   //-----------------------------------------------------------
1040   // Great restriction of new edges and update of AsDes.
1041   //------------------------------------------ ----------------
1042   TopTools_IndexedMapOfShape NewEdges;
1043   TopExp_Explorer Exp2,ExpC;
1044   TopoDS_Shape    NE;
1045   TopoDS_Edge     TNE;
1046   TopoDS_Face     NF;
1047   
1048   for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
1049     const TopoDS_Face& FI = TopoDS::Face(Exp.Current());
1050     NF = MapSF(FI).Face();
1051     if (MES.IsBound(NF)) {NF = TopoDS::Face(MES(NF));}
1052     TopTools_MapOfShape View;
1053     for (Exp2.Init(FI.Oriented(TopAbs_FORWARD),TopAbs_EDGE); Exp2.More(); Exp2.Next()) {
1054       const TopoDS_Edge& EI = TopoDS::Edge(Exp2.Current());
1055       if (View.Add(EI)) {
1056         if (Build.IsBound(EI)) {
1057           NE = Build(EI);
1058           if (NE.ShapeType() == TopAbs_EDGE) {
1059             if (NewEdges.Add(NE)) {TrimEdge (TopoDS::Edge(NE),AsDes2d,AsDes);}
1060           }
1061           else {
1062             //------------------------------------------------------------
1063             // The Intersections are on several edges.
1064             // The pieces without intersections with neighbors  
1065             // are removed from AsDes.
1066             //------------------------------------------------------------
1067             for (ExpC.Init(NE,TopAbs_EDGE); ExpC.More(); ExpC.Next()) {
1068               if (NewEdges.Add(ExpC.Current())) {
1069                 TopoDS_Edge NEC = TopoDS::Edge(ExpC.Current());
1070                 NEC.Free(Standard_True);
1071                 if (!AsDes2d->Descendant(NEC).IsEmpty()) {
1072                   TrimEdge (NEC,AsDes2d,AsDes);
1073                 }
1074                 else {
1075                   AsDes->Remove(NEC);
1076                 }
1077               }
1078             }
1079           }
1080         }
1081         else {
1082           NE = MapSF(FI).Generated(EI);
1083           //// modified by jgv, 19.12.03 for OCC4455 ////
1084           NE.Orientation( EI.Orientation() );
1085           ///////////////////////////////////////////////
1086           if (MES.IsBound(NE)) {
1087             NE = MES(NE);
1088             NE.Orientation(EI.Orientation());
1089             if (NewEdges.Add(NE)) {TrimEdge (TopoDS::Edge(NE),AsDes2d,AsDes);} 
1090           }
1091           AsDes->Add(NF,NE);
1092         } 
1093       }
1094     }
1095   }
1096   
1097   //--------------------------------- 
1098   // Intersection 2D on //
1099   //---------------------------------  
1100   TopTools_ListOfShape LFE; 
1101   BRepAlgo_Image     IMOE;
1102   for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
1103     const TopoDS_Shape& FI  = Exp.Current();
1104     const TopoDS_Shape& OFI = MapSF(FI).Face();
1105     if (MES.IsBound(OFI)) {
1106       const TopoDS_Face& NF = TopoDS::Face(MES(OFI));
1107       LFE.Append(NF);
1108       IMOE.SetRoot(NF);
1109     }
1110   }
1111   
1112   TopTools_ListIteratorOfListOfShape itLFE(LFE);
1113   for (; itLFE.More(); itLFE.Next()) {
1114     const TopoDS_Face& NEF = TopoDS::Face(itLFE.Value());
1115     BRepOffset_Inter2d::Compute(AsDes,NEF,NewEdges,myTol);
1116   }
1117   //----------------------------------------------
1118   // Intersections 2d on caps.
1119   //----------------------------------------------
1120   Standard_Integer i;
1121   for (i = 1; i <= myFaces.Extent(); i++) {
1122     const TopoDS_Face& Cork = TopoDS::Face(myFaces(i));
1123     BRepOffset_Inter2d::Compute(AsDes,Cork,NewEdges,myTol);
1124   }
1125
1126   //-------------------------------
1127   // Unwinding of extended Faces.
1128   //-------------------------------
1129   myMakeLoops.Build(LFE  ,AsDes,IMOE);
1130
1131 #ifdef OCCT_DEBUG
1132   TopTools_IndexedMapOfShape COES;
1133 #endif
1134   //---------------------------
1135   // MAJ SD. for faces //
1136   //---------------------------
1137   for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
1138     const TopoDS_Shape& FI   = Exp.Current();
1139     myInitOffsetFace.SetRoot(FI);
1140     TopoDS_Face  OF  = MapSF(FI).Face();
1141     if (MES.IsBound(OF)) {
1142       OF = TopoDS::Face(MES(OF));
1143       if (IMOE.HasImage(OF)) {
1144         const TopTools_ListOfShape& LOFE = IMOE.Image(OF);
1145         myInitOffsetFace.Bind(FI,LOFE);
1146         for (itLF.Initialize(LOFE); itLF.More(); itLF.Next()) {
1147           const TopoDS_Shape& OFE =  itLF.Value();
1148           myImageOffset.SetRoot(OFE);
1149 #ifdef DRAW
1150           if (AffichInt2d) {
1151             sprintf(name,"AF_%d",NbAF++);
1152             DBRep::Set(name,OFE);
1153           }
1154 #endif
1155           TopTools_MapOfShape View;
1156           for (Exp2.Init(OFE.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
1157                Exp2.More(); Exp2.Next()) {
1158             const TopoDS_Edge& COE = TopoDS::Edge(Exp2.Current());
1159             
1160             myAsDes->Add (OFE,COE);
1161 #ifdef DRAW
1162             if (AffichInt2d) {
1163               sprintf(name,"AE_%d",NbAE++);
1164               DBRep::Set(name,COE);
1165               COES.Add(COE);
1166             }
1167 #endif
1168             if (View.Add(COE)){
1169               if (!myAsDes->HasDescendant(COE)) {
1170                 TopoDS_Vertex CV1,CV2;
1171                 TopExp::Vertices(COE,CV1,CV2);
1172                 if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
1173                 if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));     
1174               }
1175             }
1176           }
1177         }
1178       }
1179       else {
1180         myInitOffsetFace.Bind(FI,OF);
1181         myImageOffset.SetRoot(OF);
1182 #ifdef DRAW 
1183         if (AffichInt2d) {
1184           sprintf(name,"AF_%d",NbAF++);
1185           DBRep::Set(name,OF);
1186         }
1187 #endif
1188         const TopTools_ListOfShape& LE = AsDes->Descendant(OF);
1189         for (itLF.Initialize(LE) ; itLF.More(); itLF.Next()) {
1190           const TopoDS_Edge& OE = TopoDS::Edge(itLF.Value());
1191           if (IMOE.HasImage(OE)) {
1192             const TopTools_ListOfShape& LOE = IMOE.Image(OE);
1193             TopTools_ListIteratorOfListOfShape itLOE(LOE);
1194             for (; itLOE.More(); itLOE.Next()) {
1195               TopoDS_Shape aLocalShape = itLOE.Value().Oriented(OE.Orientation());
1196               const TopoDS_Edge& COE = TopoDS::Edge(aLocalShape);
1197 //            const TopoDS_Edge& COE = TopoDS::Edge(itLOE.Value().Oriented(OE.Orientation()));
1198               myAsDes->Add(OF,COE);
1199 #ifdef DRAW
1200               if (AffichInt2d) {
1201                 sprintf(name,"AE_%d",NbAE++);
1202                 DBRep::Set(name,COE);
1203                 COES.Add(COE);
1204               }
1205 #endif
1206               
1207               if (!myAsDes->HasDescendant(COE)) {
1208                 TopoDS_Vertex CV1,CV2;
1209                 TopExp::Vertices(COE,CV1,CV2);
1210                 if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
1211                 if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));     
1212               }
1213             }
1214           }
1215           else {
1216             myAsDes->Add(OF,OE);
1217 #ifdef DRAW
1218             if (AffichInt2d) {
1219               sprintf(name,"AE_%d",NbAE++);
1220               DBRep::Set(name,OE);
1221               COES.Add(OE);
1222             }
1223 #endif
1224
1225             const TopTools_ListOfShape& LV = AsDes->Descendant(OE);
1226             myAsDes->Add(OE,LV);
1227           }
1228         }
1229       }
1230     }
1231     else {
1232       myInitOffsetFace.Bind(FI,OF);
1233       myImageOffset.SetRoot(OF);
1234       TopTools_MapOfShape View;
1235       for (Exp2.Init(OF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
1236            Exp2.More(); Exp2.Next()) {
1237
1238         const TopoDS_Edge& COE = TopoDS::Edge(Exp2.Current());
1239         myAsDes->Add (OF,COE);
1240 #ifdef DRAW
1241         if (AffichInt2d) {
1242           sprintf(name,"AE_%d",NbAE++);
1243           DBRep::Set(name,COE);
1244           COES.Add(COE);
1245         }
1246 #endif
1247         
1248         if (View.Add(Exp2.Current())) {
1249           if (!myAsDes->HasDescendant(COE)) {
1250             TopoDS_Vertex CV1,CV2;
1251             TopExp::Vertices(COE,CV1,CV2);
1252             if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
1253             if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED)); 
1254           }
1255         }
1256       } 
1257     }
1258   }
1259   //  Modified by skv - Tue Mar 15 16:20:43 2005
1260   // Add methods for supporting history.
1261   TopTools_MapOfShape aMapEdges;
1262
1263   for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
1264     const TopoDS_Shape& aFaceRef = Exp.Current();
1265
1266     Exp2.Init(aFaceRef.Oriented(TopAbs_FORWARD), TopAbs_EDGE);
1267
1268     for (; Exp2.More(); Exp2.Next()) {
1269       const TopoDS_Shape& anEdgeRef = Exp2.Current();
1270
1271       if (aMapEdges.Add(anEdgeRef)) {
1272         myInitOffsetEdge.SetRoot(anEdgeRef);
1273         if (Build.IsBound(anEdgeRef)) {
1274           TopoDS_Shape aNewShape = Build(anEdgeRef);
1275           
1276           if (aNewShape.ShapeType() == TopAbs_EDGE) {
1277             if (IMOE.HasImage(aNewShape)) {
1278               const TopTools_ListOfShape& aListNewE = IMOE.Image(aNewShape);
1279               
1280               myInitOffsetEdge.Bind (anEdgeRef, aListNewE);
1281             } else
1282               myInitOffsetEdge.Bind (anEdgeRef, aNewShape);
1283           } else { // aNewShape != TopAbs_EDGE
1284             TopTools_ListOfShape aListNewEdge;
1285             
1286             for (ExpC.Init(aNewShape, TopAbs_EDGE); ExpC.More(); ExpC.Next()) {
1287               const TopoDS_Shape &aResEdge = ExpC.Current();
1288               
1289               if (IMOE.HasImage(aResEdge)) {
1290                 const TopTools_ListOfShape& aListNewE = IMOE.Image(aResEdge);
1291                 TopTools_ListIteratorOfListOfShape aNewEIter(aListNewE);
1292                 
1293                 for (; aNewEIter.More(); aNewEIter.Next())
1294                   aListNewEdge.Append(aNewEIter.Value());
1295               } else
1296                 aListNewEdge.Append(aResEdge);
1297             }
1298             
1299             myInitOffsetEdge.Bind (anEdgeRef, aListNewEdge);
1300           }
1301         } 
1302         else { // Free boundary.
1303           TopoDS_Shape aNewEdge = MapSF(aFaceRef).Generated(anEdgeRef);
1304
1305           if (MES.IsBound(aNewEdge))
1306             aNewEdge = MES(aNewEdge);
1307
1308           if (IMOE.HasImage(aNewEdge)) {
1309             const TopTools_ListOfShape& aListNewE = IMOE.Image(aNewEdge);
1310
1311             myInitOffsetEdge.Bind (anEdgeRef, aListNewE);
1312           } else
1313             myInitOffsetEdge.Bind (anEdgeRef, aNewEdge);
1314         }
1315       }
1316     }
1317   }
1318 //  Modified by skv - Tue Mar 15 16:20:43 2005
1319
1320   //---------------------------
1321   // MAJ SD. for caps 
1322   //---------------------------
1323   //TopTools_MapOfShape View; 
1324   for (i = 1; i <= myFaces.Extent(); i++) {
1325     const TopoDS_Shape& Cork = myFaces(i);
1326     const TopTools_ListOfShape& LE = AsDes->Descendant(Cork);
1327     for (itLF.Initialize(LE) ; itLF.More(); itLF.Next()) {
1328       const TopoDS_Edge& OE = TopoDS::Edge(itLF.Value());
1329       if (IMOE.HasImage(OE)) {
1330         const TopTools_ListOfShape& LOE = IMOE.Image(OE);
1331         TopTools_ListIteratorOfListOfShape itLOE(LOE);
1332         for (; itLOE.More(); itLOE.Next()) {
1333           const TopoDS_Edge& COE = TopoDS::Edge(itLOE.Value());
1334           myAsDes->Add(Cork,COE.Oriented(OE.Orientation())) ;
1335 #ifdef DRAW
1336           if (AffichInt2d) {
1337             sprintf(name,"AE_%d",NbAE++);
1338             DBRep::Set(name,COE);
1339             COES.Add(COE);
1340           }
1341 #endif
1342           
1343           if (!myAsDes->HasDescendant(COE)) {
1344             TopoDS_Vertex CV1,CV2;
1345             TopExp::Vertices(COE,CV1,CV2);
1346             if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
1347             if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));   
1348           }
1349         }
1350       }
1351       else {
1352         myAsDes->Add(Cork,OE);
1353         if (AsDes->HasDescendant(OE)) {
1354           myAsDes->Add(OE,AsDes->Descendant(OE));
1355         }
1356 #ifdef DRAW
1357         if (AffichInt2d) {
1358           sprintf(name,"AE_%d",NbAE++);
1359           DBRep::Set(name,OE);
1360           COES.Add(OE);
1361         }
1362 #endif
1363       }
1364     }
1365   }
1366   
1367 #ifdef OCCT_DEBUG
1368   DEBVerticesControl (COES,myAsDes);
1369   if ( ChronBuild) Clock.Show();
1370 #endif
1371 }
1372
1373
1374 //=======================================================================
1375 //function : BuildOffsetByArc
1376 //purpose  : 
1377 //=======================================================================
1378 void BRepOffset_MakeOffset::BuildOffsetByArc()
1379 {
1380 #ifdef OCCT_DEBUG
1381   if ( ChronBuild) {
1382     cout << " CONSTRUCTION OF OFFSETS :" << endl;
1383     Clock.Reset();
1384     Clock.Start();
1385   }
1386 #endif
1387
1388   BRepOffset_DataMapOfShapeOffset MapSF;
1389   TopTools_MapOfShape             Done;
1390   Standard_Boolean OffsetOutside = (myOffset > 0.)? Standard_True : Standard_False;
1391   //--------------------------------------------------------
1392   // Construction of faces parallel to initial faces
1393   //--------------------------------------------------------
1394   TopExp_Explorer Exp;
1395   TopTools_ListOfShape LF;
1396   TopTools_ListIteratorOfListOfShape itLF;
1397
1398   BRepLib::SortFaces(myShape,LF);
1399
1400   TopTools_DataMapOfShapeShape EdgeTgt;
1401   for (itLF.Initialize(LF); itLF.More(); itLF.Next()) {
1402     const TopoDS_Face&   F = TopoDS::Face(itLF.Value());
1403     Standard_Real CurOffset = myOffset;
1404     if (myFaceOffset.IsBound(F)) CurOffset = myFaceOffset(F);
1405     BRepOffset_Offset    OF(F,CurOffset,EdgeTgt,OffsetOutside,myJoin);
1406     TopTools_ListOfShape Let;
1407     myAnalyse.Edges(F,BRepOffset_Tangent,Let);
1408     TopTools_ListIteratorOfListOfShape itl(Let);
1409     
1410     for ( ; itl.More(); itl.Next()) {
1411       const TopoDS_Edge& Cur = TopoDS::Edge(itl.Value());
1412       if ( !EdgeTgt.IsBound(Cur)) {
1413         TopoDS_Shape aLocalShape = OF.Generated(Cur);
1414         const TopoDS_Edge& OTE = TopoDS::Edge(aLocalShape);
1415 //      const TopoDS_Edge& OTE = TopoDS::Edge(OF.Generated(Cur));
1416         EdgeTgt.Bind(Cur,OF.Generated(Cur));
1417         TopoDS_Vertex V1,V2,OV1,OV2;
1418         TopExp::Vertices (Cur,V1,V2);
1419         TopExp::Vertices (OTE,OV1,OV2);      
1420         TopTools_ListOfShape LE;
1421         if (!EdgeTgt.IsBound(V1)) {
1422           myAnalyse.Edges(V1,BRepOffset_Tangent,LE);
1423           const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V1);
1424           if (LE.Extent() == LA.Extent())
1425             EdgeTgt.Bind(V1,OV1);
1426         }
1427         if (!EdgeTgt.IsBound(V2)) {
1428           LE.Clear();
1429           myAnalyse.Edges(V2,BRepOffset_Tangent,LE);
1430           const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V2);
1431           if (LE.Extent() == LA.Extent())
1432               EdgeTgt.Bind(V2,OV2);
1433         }
1434       }
1435     }
1436     MapSF.Bind(F,OF);
1437   }
1438   //--------------------------------------------------------
1439   // Construction of tubes on edge.
1440   //--------------------------------------------------------
1441   BRepOffset_Type    OT = BRepOffset_Convex;
1442   if (myOffset < 0.) OT = BRepOffset_Concave; 
1443    
1444   for (Exp.Init(myShape,TopAbs_EDGE); Exp.More(); Exp.Next()) {
1445     const TopoDS_Edge& E = TopoDS::Edge(Exp.Current());
1446     if (Done.Add(E)) {
1447       const TopTools_ListOfShape& Anc = myAnalyse.Ancestors(E);
1448       if (Anc.Extent() == 2) {
1449         const BRepOffset_ListOfInterval& L = myAnalyse.Type(E);
1450         if (!L.IsEmpty() && L.First().Type() == OT) {
1451           Standard_Real CurOffset = myOffset;
1452           if ( myFaceOffset.IsBound(Anc.First()))
1453             CurOffset = myFaceOffset(Anc.First());
1454           TopoDS_Shape aLocalShape = MapSF(Anc.First()).Generated(E);
1455           TopoDS_Edge EOn1 = TopoDS::Edge(aLocalShape);
1456           aLocalShape = MapSF(Anc.Last()).Generated(E);
1457           TopoDS_Edge EOn2 = TopoDS::Edge(aLocalShape);
1458 //        TopoDS_Edge EOn1 = TopoDS::Edge(MapSF(Anc.First()).Generated(E));
1459 //        TopoDS_Edge EOn2 = TopoDS::Edge(MapSF(Anc.Last()) .Generated(E));
1460           // find if exits tangent edges in the original shape
1461           TopoDS_Edge E1f, E1l;
1462           TopoDS_Vertex V1f, V1l;
1463           TopExp::Vertices(E,V1f,V1l);
1464           TopTools_ListOfShape TangE;
1465           myAnalyse.TangentEdges(E,V1f,TangE);
1466           // find if the pipe on the tangent edges are soon created.
1467           TopTools_ListIteratorOfListOfShape itl(TangE);
1468           Standard_Boolean Find = Standard_False;
1469           for ( ; itl.More() && !Find; itl.Next()) {
1470             if ( MapSF.IsBound(itl.Value())) {
1471               TopoDS_Shape aLocalShape = MapSF(itl.Value()).Generated(V1f);
1472               E1f  = TopoDS::Edge(aLocalShape);
1473 //            E1f  = TopoDS::Edge(MapSF(itl.Value()).Generated(V1f));
1474               Find = Standard_True;
1475             }
1476           }
1477           TangE.Clear();
1478           myAnalyse.TangentEdges(E,V1l,TangE);
1479           // find if the pipe on the tangent edges are soon created.
1480           itl.Initialize(TangE);
1481           Find = Standard_False;
1482           for ( ; itl.More() && !Find; itl.Next()) {
1483             if ( MapSF.IsBound(itl.Value())) {
1484               TopoDS_Shape aLocalShape = MapSF(itl.Value()).Generated(V1l);
1485               E1l  = TopoDS::Edge(aLocalShape);
1486 //            E1l  = TopoDS::Edge(MapSF(itl.Value()).Generated(V1l));
1487               Find = Standard_True;
1488             }
1489           }
1490           BRepOffset_Offset OF (E,EOn1,EOn2,CurOffset,E1f, E1l);
1491           MapSF.Bind(E,OF);
1492         }
1493       }
1494       else {
1495         // ----------------------
1496         // free border.
1497         // ----------------------
1498         TopoDS_Shape aLocalShape = MapSF(Anc.First()).Generated(E);
1499         TopoDS_Edge EOn1 = TopoDS::Edge(aLocalShape);
1500 ///     TopoDS_Edge EOn1 = TopoDS::Edge(MapSF(Anc.First()).Generated(E));
1501         myInitOffsetEdge.SetRoot(E); // skv: supporting history.
1502         myInitOffsetEdge.Bind (E,EOn1);      
1503       }
1504     }
1505   }
1506
1507   //--------------------------------------------------------
1508   // Construction of spheres on vertex.
1509   //--------------------------------------------------------
1510   Done.Clear();
1511   TopTools_ListIteratorOfListOfShape it;
1512
1513   for (Exp.Init(myShape,TopAbs_VERTEX); Exp.More(); Exp.Next()) {
1514     const TopoDS_Vertex& V = TopoDS::Vertex (Exp.Current());
1515     if (Done.Add(V)) {
1516       const TopTools_ListOfShape& LA = myAnalyse.Ancestors(V);
1517       TopTools_ListOfShape LE;
1518       myAnalyse.Edges(V,OT,LE);
1519
1520       if (LE.Extent() >= 3 && LE.Extent() == LA.Extent()) {
1521         TopTools_ListOfShape LOE;
1522         //--------------------------------------------------------
1523         // Return connected edges on tubes.
1524         //--------------------------------------------------------
1525         for (it.Initialize(LE) ; it.More(); it.Next()) {
1526           LOE.Append(MapSF(it.Value()).Generated(V).Reversed());
1527         }
1528         //----------------------
1529         // construction sphere.
1530         //-----------------------
1531         const TopTools_ListOfShape& LLA = myAnalyse.Ancestors(LA.First());
1532         const TopoDS_Shape& FF = LLA.First();
1533         Standard_Real CurOffset = myOffset;
1534         if ( myFaceOffset.IsBound(FF))
1535           CurOffset = myFaceOffset(FF);
1536         
1537         BRepOffset_Offset OF(V,LOE,CurOffset);
1538         MapSF.Bind(V,OF);
1539       }
1540       //--------------------------------------------------------------
1541       // Particular processing if V is at least a free border.
1542       //-------------------------------------------------------------
1543       TopTools_ListOfShape LBF;
1544       myAnalyse.Edges(V,BRepOffset_FreeBoundary,LBF);
1545       if (!LBF.IsEmpty()) {     
1546         Standard_Boolean First = Standard_True;
1547         for (it.Initialize(LE) ; it.More(); it.Next()) {
1548           if (First) {
1549             myInitOffsetEdge.SetRoot(V); // skv: supporting history.
1550             myInitOffsetEdge.Bind(V,MapSF(it.Value()).Generated(V));
1551             First = Standard_False;
1552           }
1553           else {
1554             myInitOffsetEdge.Add(V,MapSF(it.Value()).Generated(V));
1555           }
1556         } 
1557       }
1558     }
1559   }
1560
1561   //------------------------------------------------------------
1562   // Extension of parallel faces to the context.
1563   // Extended faces are ordered in DS and removed from MapSF.
1564   //------------------------------------------------------------
1565   if (!myFaces.IsEmpty()) ToContext (MapSF);
1566
1567   //------------------------------------------------------
1568   // MAJ SD.
1569   //------------------------------------------------------
1570   BRepOffset_Type    RT = BRepOffset_Concave;
1571   if (myOffset < 0.) RT = BRepOffset_Convex;
1572   BRepOffset_DataMapIteratorOfDataMapOfShapeOffset It(MapSF);
1573   for ( ; It.More(); It.Next()) {
1574     const TopoDS_Shape& SI = It.Key(); 
1575     const BRepOffset_Offset& SF = It.Value();
1576     if (SF.Status() == BRepOffset_Reversed ||
1577         SF.Status() == BRepOffset_Degenerated ) {
1578       //------------------------------------------------
1579       // Degenerated or returned faces are not stored.
1580       //------------------------------------------------
1581       continue; 
1582     }   
1583
1584     const TopoDS_Face&  OF = It.Value().Face();
1585     myInitOffsetFace.Bind    (SI,OF);      
1586     myInitOffsetFace.SetRoot (SI);      // Initial<-> Offset
1587     myImageOffset.SetRoot    (OF);      // FaceOffset root of images
1588     
1589     if (SI.ShapeType() == TopAbs_FACE) {
1590       for (Exp.Init(SI.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
1591            Exp.More(); Exp.Next()) {
1592         //--------------------------------------------------------------------
1593         // To each face are associatedthe edges that restrict that 
1594         // The edges that do not generate tubes or are not tangent
1595         // to two faces are removed.
1596         //--------------------------------------------------------------------
1597         const TopoDS_Edge& E = TopoDS::Edge(Exp.Current());
1598         const BRepOffset_ListOfInterval& L  = myAnalyse.Type(E);
1599         if (!L.IsEmpty() && L.First().Type() != RT) {
1600           TopAbs_Orientation OO  = E.Orientation();
1601           TopoDS_Shape aLocalShape = It.Value().Generated(E);
1602           TopoDS_Edge        OE  = TopoDS::Edge(aLocalShape);
1603 //        TopoDS_Edge        OE  = TopoDS::Edge(It.Value().Generated(E));
1604           myAsDes->Add (OF,OE.Oriented(OO));
1605         }
1606       }
1607     }
1608     else {
1609       for (Exp.Init(OF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
1610            Exp.More(); Exp.Next()) {
1611         myAsDes->Add (OF,Exp.Current());
1612       }
1613     }
1614   }
1615
1616 #ifdef OCCT_DEBUG
1617   if ( ChronBuild) Clock.Show();
1618 #endif
1619 }
1620
1621
1622
1623 //=======================================================================
1624 //function : SelfInter
1625 //purpose  : 
1626 //=======================================================================
1627
1628 void BRepOffset_MakeOffset::SelfInter(TopTools_MapOfShape& /*Modif*/)
1629 {
1630 #ifdef OCCT_DEBUG
1631   if ( ChronBuild) {
1632     cout << " AUTODEBOUCLAGE:" << endl;
1633     Clock.Reset();
1634     Clock.Start();
1635   }    
1636 #endif  
1637
1638   Standard_NotImplemented::Raise();
1639
1640 #ifdef OCCT_DEBUG
1641   if ( ChronBuild) Clock.Show();
1642 #endif
1643 }
1644
1645
1646 //=======================================================================
1647 //function : ToContext
1648 //purpose  : 
1649 //=======================================================================
1650
1651 void BRepOffset_MakeOffset::ToContext (BRepOffset_DataMapOfShapeOffset& MapSF)
1652 {
1653   TopTools_DataMapOfShapeShape        Created;   
1654   TopTools_DataMapOfShapeShape        MEF;
1655   TopTools_IndexedMapOfShape          FacesToBuild;
1656   TopTools_ListIteratorOfListOfShape  itl;
1657   TopExp_Explorer                     exp;
1658
1659 //  TopAbs_State       Side = TopAbs_IN;  
1660 //  if (myOffset < 0.) Side = TopAbs_OUT;
1661
1662   TopAbs_State       Side = TopAbs_OUT; 
1663
1664   /*
1665   Standard_Integer i;
1666   for (i = 1; i <= myFaces.Extent(); i++) {
1667     const TopoDS_Face& CF = TopoDS::Face(myFaces(i));
1668     for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
1669          exp.More(); exp.Next()) {
1670       const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
1671       if (!myAnalyse.HasAncestor(E)) {
1672         //----------------------------------------------------------------
1673         // The edges of context faces that are not in the initial shape
1674         // can appear in the result.
1675         //----------------------------------------------------------------
1676         //myAsDes->Add(CF,E);
1677       }  
1678     }
1679   }
1680   */
1681   
1682   //--------------------------------------------------------
1683   // Determine the edges and faces reconstructed by  
1684   // intersection.
1685   //---------------------------------------------------------
1686   Standard_Integer j;
1687   for (j = 1; j <= myFaces.Extent(); j++) {
1688     const TopoDS_Face& CF = TopoDS::Face(myFaces(j));
1689     for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
1690          exp.More(); exp.Next()) {
1691       const TopoDS_Edge& E = TopoDS::Edge(exp.Current()); 
1692       if (myAnalyse.HasAncestor(E)) {
1693         const TopTools_ListOfShape& LEA = myAnalyse.Ancestors(E);
1694         for (itl.Initialize(LEA); itl.More(); itl.Next()) {
1695           const BRepOffset_Offset& OF = MapSF(itl.Value());
1696           FacesToBuild.Add(itl.Value());
1697           MEF.Bind(OF.Generated(E),CF);
1698         }
1699         TopoDS_Vertex V[2];
1700         TopExp::Vertices(E,V[0],V[1]);
1701         for (Standard_Integer i = 0; i < 2; i++) {
1702           const TopTools_ListOfShape& LVA =  myAnalyse.Ancestors(V[i]);
1703           for ( itl.Initialize(LVA); itl.More(); itl.Next()) {
1704             const TopoDS_Edge& EV = TopoDS::Edge(itl.Value());
1705             if (MapSF.IsBound(EV)) {
1706               const BRepOffset_Offset& OF = MapSF(EV);
1707               FacesToBuild.Add(EV);
1708               MEF.Bind(OF.Generated(V[i]),CF);
1709             }
1710           }
1711         }
1712       }
1713     }
1714   }
1715   //---------------------------
1716   // Reconstruction of faces.
1717   //---------------------------
1718   TopoDS_Face        F,NF;
1719   BRepOffset_Type    RT = BRepOffset_Concave;
1720   if (myOffset < 0.) RT = BRepOffset_Convex;
1721   TopoDS_Shape       OE,NE;
1722   TopAbs_Orientation Or;
1723
1724   for (j = 1; j <= FacesToBuild.Extent(); j++) {
1725     const TopoDS_Shape& S   = FacesToBuild(j);
1726     BRepOffset_Offset   BOF;
1727     BOF = MapSF(S);
1728     F = TopoDS::Face(BOF.Face());
1729     BRepOffset_Tool::ExtentFace(F,Created,MEF,Side,myTol,NF);
1730     MapSF.UnBind(S);
1731     //--------------
1732     // MAJ SD.
1733     //--------------
1734     myInitOffsetFace.Bind    (S,NF);      
1735     myInitOffsetFace.SetRoot (S);      // Initial<-> Offset
1736     myImageOffset.SetRoot    (NF);
1737
1738     if (S.ShapeType() == TopAbs_FACE) {
1739       for (exp.Init(S.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
1740            exp.More(); exp.Next()) {
1741         
1742         const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
1743         const BRepOffset_ListOfInterval& L  = myAnalyse.Type(E);
1744         OE = BOF.Generated(E);
1745         Or = E.Orientation();
1746         OE.Orientation(Or);
1747         if (!L.IsEmpty() && L.First().Type() != RT) {
1748           if (Created.IsBound(OE)) {
1749             NE = Created(OE); 
1750             if (NE.Orientation() == TopAbs_REVERSED) 
1751               NE.Orientation(TopAbs::Reverse(Or));
1752             else
1753               NE.Orientation(Or);
1754             myAsDes->Add(NF,NE);
1755           }
1756           else {
1757             myAsDes->Add(NF,OE);
1758           }
1759         }
1760       }
1761     }
1762     else {
1763       //------------------
1764       // Tube
1765       //---------------------
1766       for (exp.Init(NF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
1767            exp.More(); exp.Next()) {
1768         myAsDes->Add (NF,exp.Current());
1769       }
1770     }    
1771     MapSF.UnBind(S);
1772   }
1773
1774   //------------------
1775   // MAJ free borders
1776   //------------------
1777   TopTools_DataMapIteratorOfDataMapOfShapeShape itc;
1778   for (itc.Initialize(Created); itc.More(); itc.Next()) {
1779     OE = itc.Key();
1780     NE = itc.Value();
1781     if (myInitOffsetEdge.IsImage(OE)) {
1782       TopoDS_Shape E = myInitOffsetEdge.ImageFrom (OE);
1783       Or = myInitOffsetEdge.Image(E).First().Orientation();
1784       if (NE.Orientation() == TopAbs_REVERSED) 
1785         NE.Orientation(TopAbs::Reverse(Or));
1786       else
1787         NE.Orientation(Or);
1788       myInitOffsetEdge.Remove(OE);
1789       myInitOffsetEdge.Bind(E,NE);
1790     }
1791   }
1792 }
1793
1794
1795 //=======================================================================
1796 //function : UpdateFaceOffset
1797 //purpose  : 
1798 //=======================================================================
1799
1800 void BRepOffset_MakeOffset::UpdateFaceOffset()
1801 {
1802   TopTools_MapOfShape M;
1803   TopTools_DataMapOfShapeReal CopiedMap;
1804   CopiedMap.Assign(myFaceOffset);
1805   TopTools_DataMapIteratorOfDataMapOfShapeReal it(CopiedMap);
1806
1807   BRepOffset_Type    RT = BRepOffset_Convex;
1808   if (myOffset < 0.) RT = BRepOffset_Concave;
1809
1810   for ( ; it.More(); it.Next()) {
1811     const TopoDS_Face& F = TopoDS::Face(it.Key());
1812     Standard_Real CurOffset = CopiedMap(F);
1813     if ( !M.Add(F)) continue;
1814     TopoDS_Compound Co;
1815     BRep_Builder Build;
1816     Build.MakeCompound(Co);
1817     TopTools_MapOfShape Dummy;
1818     Build.Add(Co,F);
1819     if (myJoin == GeomAbs_Arc)
1820       myAnalyse.AddFaces(F,Co,Dummy,BRepOffset_Tangent,RT);
1821     else   
1822       myAnalyse.AddFaces(F,Co,Dummy,BRepOffset_Tangent);
1823
1824     TopExp_Explorer exp(Co,TopAbs_FACE);
1825     for (; exp.More(); exp.Next()) {
1826       const TopoDS_Face& FF = TopoDS::Face(exp.Current());
1827       if ( !M.Add(FF)) continue;
1828       if ( myFaceOffset.IsBound(FF))
1829         myFaceOffset.UnBind(FF);
1830       myFaceOffset.Bind(FF,CurOffset);
1831     }
1832   }
1833 }
1834
1835 //=======================================================================
1836 //function : CorrectConicalFaces
1837 //purpose  : 
1838 //=======================================================================
1839
1840 void BRepOffset_MakeOffset::CorrectConicalFaces()
1841 {
1842   TopTools_SequenceOfShape Cones;
1843   TopTools_SequenceOfShape Circs;
1844   TopTools_SequenceOfShape Seams;
1845   Standard_Real TolApex = 1.e-5;
1846
1847   Standard_Integer i;
1848
1849   TopTools_DataMapOfShapeListOfShape FacesOfCone;
1850   //TopTools_DataMapOfShapeShape DegEdges;
1851   TopExp_Explorer Explo( myOffsetShape, TopAbs_FACE );
1852   if (myJoin == GeomAbs_Arc)
1853   {
1854     for (; Explo.More(); Explo.Next())
1855     {
1856       TopoDS_Face aFace = TopoDS::Face( Explo.Current() );
1857       Handle(Geom_Surface) aSurf = BRep_Tool::Surface( aFace );
1858       //if (aSurf->DynamicType() == STANDARD_TYPE(Geom_OffsetSurface))
1859       //aSurf = (Handle(Geom_OffsetSurface)::DownCast(aSurf))->BasisSurface(); //???
1860       
1861       TopTools_IndexedMapOfShape Emap;
1862       TopExp::MapShapes( aFace, TopAbs_EDGE, Emap );
1863       for (i = 1; i <= Emap.Extent(); i++)
1864       {
1865         TopoDS_Edge anEdge = TopoDS::Edge( Emap(i) );
1866         //Standard_Real f, l;
1867         //Handle(Geom_Curve) theCurve = BRep_Tool::Curve( anEdge, f, l );
1868         //Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &anEdge.TShape());
1869         if (BRep_Tool::Degenerated(anEdge))
1870         {
1871           //Check if anEdge is a really degenerated edge or not
1872           BRepAdaptor_Curve BACurve(anEdge, aFace);
1873           gp_Pnt Pfirst, Plast, Pmid;
1874           Pfirst = BACurve.Value(BACurve.FirstParameter());
1875           Plast  = BACurve.Value(BACurve.LastParameter());
1876           Pmid   = BACurve.Value((BACurve.FirstParameter()+BACurve.LastParameter())/2.);
1877           if (Pfirst.Distance(Plast) <= TolApex &&
1878               Pfirst.Distance(Pmid)  <= TolApex)
1879             continue;
1880           //Cones.Append( aFace );
1881           //Circs.Append( anEdge );
1882           //TopoDS_Vertex Vdeg = TopExp::FirstVertex( anEdge );
1883           TopoDS_Edge OrEdge = 
1884             TopoDS::Edge( myInitOffsetEdge.Root( anEdge) );
1885           TopoDS_Vertex VF = TopExp::FirstVertex( OrEdge );
1886           if ( FacesOfCone.IsBound(VF) )
1887           {
1888             //add a face to the existing list
1889             TopTools_ListOfShape& aFaces = FacesOfCone.ChangeFind(VF);
1890             aFaces.Append (aFace);
1891             //DegEdges.Bind(aFace, anEdge);
1892           }
1893           else
1894           {
1895             //the vertex is not in the map => create a new key and items
1896             TopTools_ListOfShape aFaces;
1897             aFaces.Append (aFace);
1898             FacesOfCone.Bind(VF, aFaces);
1899             //DegEdges.Bind(aFace, anEdge);
1900           }
1901         }
1902       } //for (i = 1; i <= Emap.Extent(); i++)
1903     } //for (; fexp.More(); fexp.Next())
1904   } //if (myJoin == GeomAbs_Arc)
1905
1906   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape Cone(FacesOfCone);
1907   BRep_Builder BB;
1908   TopLoc_Location L;
1909   for (; Cone.More(); Cone.Next() ) {
1910     gp_Sphere theSphere;
1911     Handle(Geom_SphericalSurface) aSphSurf;
1912     TopoDS_Wire SphereWire;
1913     BB.MakeWire(SphereWire);
1914     TopoDS_Vertex anApex = TopoDS::Vertex(Cone.Key());
1915     const TopTools_ListOfShape& Faces = Cone.Value(); //FacesOfCone(anApex);
1916     TopTools_ListIteratorOfListOfShape itFaces(Faces);
1917     Standard_Boolean isFirstFace = Standard_True;
1918     gp_Pnt FirstPoint;
1919     TopoDS_Vertex theFirstVertex, CurFirstVertex;
1920     for (; itFaces.More(); itFaces.Next())
1921     {
1922       TopoDS_Face aFace = TopoDS::Face(itFaces.Value()); //TopoDS::Face(Faces.First());
1923       TopoDS_Edge DegEdge; // = TopoDS::Edge(DegEdges(aFace));
1924       for (Explo.Init(aFace, TopAbs_EDGE); Explo.More(); Explo.Next())
1925       {
1926         DegEdge = TopoDS::Edge(Explo.Current());
1927         if (BRep_Tool::Degenerated(DegEdge))
1928         {
1929           TopoDS_Edge OrEdge = TopoDS::Edge( myInitOffsetEdge.Root( DegEdge) );
1930           TopoDS_Vertex VF = TopExp::FirstVertex( OrEdge );
1931           if (VF.IsSame(anApex))
1932             break;
1933         }
1934       }
1935       TopoDS_Shape aLocalDegShape = DegEdge.Oriented(TopAbs_FORWARD);
1936       TopoDS_Edge CurEdge = TopoDS::Edge(aLocalDegShape);
1937       BB.Degenerated(CurEdge, Standard_False);
1938       BB.SameRange(CurEdge, Standard_False);
1939       BB.SameParameter(CurEdge, Standard_False);
1940       gp_Pnt fPnt, lPnt, mPnt;
1941       GetEdgePoints(CurEdge, aFace, fPnt, mPnt, lPnt);
1942       Standard_Real f, l;
1943       BRep_Tool::Range(CurEdge, f, l);
1944       if (isFirstFace)
1945       {
1946         gp_Vec aVec1(fPnt, mPnt);
1947         gp_Vec aVec2(fPnt, lPnt);
1948         gp_Vec aNorm = aVec1.Crossed(aVec2);
1949         gp_Pnt theApex = BRep_Tool::Pnt(anApex);
1950         gp_Vec ApexToFpnt(theApex, fPnt);
1951         gp_Vec Ydir = aNorm ^ ApexToFpnt;
1952         gp_Vec Xdir = Ydir ^ aNorm;
1953         //Xdir.Rotate(gp_Ax1(theApex, aNorm), -f);
1954         gp_Ax2 anAx2(theApex, gp_Dir(aNorm), gp_Dir(Xdir));
1955         theSphere.SetRadius(myOffset);
1956         theSphere.SetPosition(gp_Ax3(anAx2) /*gp_Ax3(theApex, gp_Dir(aNorm))*/);
1957         aSphSurf = new Geom_SphericalSurface(theSphere);
1958         FirstPoint = fPnt;
1959         theFirstVertex = BRepLib_MakeVertex(fPnt);
1960         CurFirstVertex = theFirstVertex;
1961       }
1962       
1963       TopoDS_Vertex v1, v2, FirstVert, EndVert;
1964       TopExp::Vertices(CurEdge, v1, v2);
1965       FirstVert = CurFirstVertex;
1966       if (lPnt.Distance(FirstPoint) <= Precision::Confusion())
1967         EndVert = theFirstVertex;
1968       else
1969         EndVert = BRepLib_MakeVertex(lPnt);
1970       CurEdge.Free( Standard_True );
1971       BB.Remove(CurEdge, v1);
1972       BB.Remove(CurEdge, v2);
1973       BB.Add(CurEdge, FirstVert.Oriented(TopAbs_FORWARD));
1974       BB.Add(CurEdge, EndVert.Oriented(TopAbs_REVERSED));
1975       //take the curve from sphere an put it to the edge
1976       Standard_Real Uf, Vf, Ul, Vl;
1977       ElSLib::Parameters( theSphere, fPnt, Uf, Vf );
1978       ElSLib::Parameters( theSphere, lPnt, Ul, Vl );
1979       if (Abs(Ul) <= Precision::Confusion())
1980         Ul = 2.*M_PI;
1981       Handle(Geom_Curve) aCurv = aSphSurf->VIso(Vf);
1982       /*
1983         if (!isFirstFace)
1984         {
1985         gp_Circ aCircle = (Handle(Geom_Circle)::DownCast(aCurv))->Circ();
1986         if (Abs(Uf - f) > Precision::Confusion())
1987         {
1988         aCircle.Rotate(aCircle.Axis(), f - Uf);
1989         aCurv = new Geom_Circle(aCircle);
1990         }
1991         }
1992       */
1993       Handle(Geom_TrimmedCurve) aTrimCurv = new Geom_TrimmedCurve(aCurv, Uf, Ul);
1994       BB.UpdateEdge(CurEdge, aTrimCurv, Precision::Confusion());
1995       BB.Range(CurEdge, Uf, Ul, Standard_True);
1996       Handle(Geom2d_Line) theLin2d = new Geom2d_Line( gp_Pnt2d( 0., Vf ), gp::DX2d() );
1997       Handle(Geom2d_TrimmedCurve) theTrimLin2d = new Geom2d_TrimmedCurve(theLin2d, Uf, Ul);
1998       BB.UpdateEdge(CurEdge, theTrimLin2d, aSphSurf, L, Precision::Confusion());
1999       BB.Range(CurEdge, aSphSurf, L, Uf, Ul);
2000       BRepLib::SameParameter(CurEdge);
2001       BB.Add(SphereWire, CurEdge);
2002       //Modifying correspondent edges in aFace: substitute vertices common with CurEdge
2003       BRepAdaptor_Curve2d BAc2d(CurEdge, aFace);
2004       gp_Pnt2d fPnt2d, lPnt2d;
2005       fPnt2d = BAc2d.Value(BAc2d.FirstParameter());
2006       lPnt2d = BAc2d.Value(BAc2d.LastParameter());
2007       TopTools_IndexedMapOfShape Emap;
2008       TopExp::MapShapes(aFace, TopAbs_EDGE, Emap);
2009       TopoDS_Edge EE [2];
2010       Standard_Integer j = 0, k;
2011       for (k = 1; k <= Emap.Extent(); k++)
2012       {
2013         const TopoDS_Edge& anEdge = TopoDS::Edge(Emap(k));
2014         if (!BRep_Tool::Degenerated(anEdge))
2015         {
2016           TopoDS_Vertex V1, V2;
2017           TopExp::Vertices(anEdge, V1, V2);
2018           if (V1.IsSame(v1) || V2.IsSame(v1))
2019             EE[j++] = anEdge;
2020         }
2021       }
2022       for (k = 0; k < j; k++)
2023       {
2024         TopoDS_Shape aLocalShape = EE[k].Oriented(TopAbs_FORWARD);
2025         TopoDS_Edge Eforward = TopoDS::Edge(aLocalShape);
2026         Eforward.Free(Standard_True);
2027         TopoDS_Vertex V1, V2;
2028         TopExp::Vertices( Eforward, V1, V2 );
2029         BRepAdaptor_Curve2d EEc( Eforward, aFace );
2030         gp_Pnt2d p2d1, p2d2;
2031         p2d1 = EEc.Value(EEc.FirstParameter());
2032         p2d2 = EEc.Value(EEc.LastParameter());
2033         if (V1.IsSame(v1))
2034         {
2035           TopoDS_Vertex NewV = (p2d1.Distance(fPnt2d) <= Precision::Confusion())?
2036             FirstVert : EndVert;
2037           BB.Remove( Eforward, V1 );
2038           BB.Add( Eforward, NewV.Oriented(TopAbs_FORWARD) );
2039         }
2040         else
2041         {
2042           TopoDS_Vertex NewV = (p2d2.Distance(fPnt2d) <= Precision::Confusion())?
2043             FirstVert : EndVert;
2044           BB.Remove( Eforward, V2 );
2045           BB.Add( Eforward, NewV.Oriented(TopAbs_REVERSED) );
2046         }
2047       }
2048       
2049       isFirstFace = Standard_False;
2050       CurFirstVertex = EndVert;
2051     }
2052     //Building new spherical face
2053     Standard_Real Ufirst = RealLast(), Ulast = RealFirst();
2054     gp_Pnt2d p2d1, p2d2;
2055     TopTools_ListOfShape EdgesOfWire;
2056     TopoDS_Iterator itw(SphereWire);
2057     for (; itw.More(); itw.Next())
2058     {
2059       const TopoDS_Edge& anEdge = TopoDS::Edge(itw.Value());
2060       EdgesOfWire.Append(anEdge);
2061       Standard_Real f, l;
2062       Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(anEdge, aSphSurf, L, f, l);
2063       p2d1 = aC2d->Value(f);
2064       p2d2 = aC2d->Value(l);
2065       if (p2d1.X() < Ufirst)
2066         Ufirst = p2d1.X();
2067       if (p2d1.X() > Ulast)
2068         Ulast = p2d1.X();
2069       if (p2d2.X() < Ufirst)
2070         Ufirst = p2d2.X();
2071       if (p2d2.X() > Ulast)
2072         Ulast = p2d2.X();
2073     }
2074     TopTools_ListOfShape NewEdges;
2075     TopoDS_Edge FirstEdge;
2076     TopTools_ListIteratorOfListOfShape itl(EdgesOfWire);
2077     for (; itl.More(); itl.Next())
2078     {
2079       FirstEdge = TopoDS::Edge(itl.Value());
2080       Standard_Real f, l;
2081       Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(FirstEdge, aSphSurf, L, f, l);
2082       p2d1 = aC2d->Value(f);
2083       p2d2 = aC2d->Value(l);
2084       if (Abs(p2d1.X() - Ufirst) <= Precision::Confusion())
2085       {
2086         EdgesOfWire.Remove(itl);
2087         break;
2088       }
2089     }
2090     NewEdges.Append(FirstEdge);
2091     TopoDS_Vertex Vf1, CurVertex;
2092     TopExp::Vertices(FirstEdge, Vf1, CurVertex);
2093     itl.Initialize(EdgesOfWire);
2094     while (itl.More())
2095     {
2096       const TopoDS_Edge& anEdge = TopoDS::Edge(itl.Value());
2097       TopoDS_Vertex V1, V2;
2098       TopExp::Vertices(anEdge, V1, V2);
2099       if (V1.IsSame(CurVertex) || V2.IsSame(CurVertex))
2100       {
2101         NewEdges.Append(anEdge);
2102         CurVertex = (V1.IsSame(CurVertex))? V2 : V1;
2103         EdgesOfWire.Remove(itl);
2104       }
2105       else
2106         itl.Next();
2107     }
2108     
2109     Standard_Real Vfirst, Vlast;
2110     if (p2d1.Y() > 0.)
2111     {
2112       Vfirst = p2d1.Y(); Vlast = M_PI/2.;
2113     }
2114     else
2115     {
2116       Vfirst = -M_PI/2.; Vlast = p2d1.Y();
2117     }
2118     TopoDS_Face NewSphericalFace = BRepLib_MakeFace(aSphSurf, Ufirst, Ulast, Vfirst, Vlast, Precision::Confusion());
2119     TopoDS_Edge OldEdge;
2120     for (Explo.Init(NewSphericalFace, TopAbs_EDGE); Explo.More(); Explo.Next())
2121     {
2122       OldEdge = TopoDS::Edge(Explo.Current());
2123       if (!BRep_Tool::Degenerated(OldEdge))
2124       {
2125         BRepAdaptor_Curve2d BAc2d(OldEdge, NewSphericalFace);
2126         p2d1 = BAc2d.Value(BAc2d.FirstParameter());
2127         p2d2 = BAc2d.Value(BAc2d.LastParameter());
2128         if (Abs(p2d1.X() - Ufirst) <= Precision::Confusion() &&
2129             Abs(p2d2.X() - Ulast)  <= Precision::Confusion())
2130           break;
2131       }
2132     }
2133     TopoDS_Vertex V1, V2;
2134     TopExp::Vertices(OldEdge, V1, V2);
2135     TopTools_ListOfShape LV1, LV2;
2136     LV1.Append(Vf1);
2137     LV2.Append(CurVertex);
2138     BRepTools_Substitution theSubstitutor;
2139     theSubstitutor.Substitute(V1, LV1);
2140     if (!V1.IsSame(V2))
2141       theSubstitutor.Substitute(V2, LV2);
2142     theSubstitutor.Substitute(OldEdge, NewEdges);
2143     theSubstitutor.Build(NewSphericalFace);
2144     if (theSubstitutor.IsCopied(NewSphericalFace))
2145     {
2146       const TopTools_ListOfShape& listSh = theSubstitutor.Copy(NewSphericalFace);
2147       NewSphericalFace = TopoDS::Face(listSh.First());
2148     }
2149     
2150     //Adding NewSphericalFace to the shell
2151     Explo.Init( myOffsetShape, TopAbs_SHELL );
2152     TopoDS_Shape theShell = Explo.Current();
2153     theShell.Free( Standard_True );
2154     BB.Add( theShell, NewSphericalFace );
2155   }
2156
2157   if (myShape.ShapeType() == TopAbs_SOLID || myThickening)
2158   {
2159     Explo.Init( myOffsetShape, TopAbs_SHELL );
2160     
2161     if (Explo.More()) {
2162       TopoDS_Shape theShell = Explo.Current();
2163       theShell.Closed( Standard_True );
2164     }
2165     
2166     Standard_Integer            NbShell = 0;
2167     TopoDS_Compound             NC;
2168     TopoDS_Shape                S1;
2169     BB.MakeCompound (NC);
2170     
2171     for (Explo.Init(myOffsetShape,TopAbs_SHELL); Explo.More(); Explo.Next()) {
2172       const TopoDS_Shell& Sh = TopoDS::Shell(Explo.Current());
2173       NbShell++;
2174       if (Sh.Closed()) {
2175         TopoDS_Solid  Sol;
2176         BB.MakeSolid  (Sol);
2177         BB.Add        (Sol,Sh);
2178         Sol.Closed(Standard_True);
2179         BB.Add (NC,Sol);
2180         if (NbShell == 1) S1 = Sol;
2181       }
2182       else {
2183         BB.Add (NC,Sh);
2184         if (NbShell == 1) S1 = Sh;
2185       }
2186     }
2187     if (NbShell == 1) myOffsetShape = S1;
2188     else              myOffsetShape = NC;
2189   }
2190 }
2191
2192
2193 //=======================================================================
2194 //function : Intersection3D
2195 //purpose  : 
2196 //=======================================================================
2197
2198 void BRepOffset_MakeOffset::Intersection3D(BRepOffset_Inter3d& Inter)
2199 {
2200 #ifdef OCCT_DEBUG
2201   if (ChronBuild) {
2202     cout << " INTERSECTION 3D:" << endl;
2203     Clock.Reset();
2204     Clock.Start();  
2205   }
2206 #endif
2207   TopTools_ListOfShape OffsetFaces;  // list of faces // created.
2208   MakeList (OffsetFaces,myInitOffsetFace,myFaces);
2209
2210   if (!myFaces.IsEmpty()) {     
2211     Standard_Boolean InSide = (myOffset < 0.); // Temporary
2212     // it is necessary to calculate Inside taking account of the concavity or convexity of edges
2213     // between the cap and the part.
2214
2215     if (myJoin == GeomAbs_Arc) 
2216       Inter.ContextIntByArc (myFaces,InSide,myAnalyse,myInitOffsetFace,myInitOffsetEdge);
2217   }
2218   if (myInter) {
2219     //-------------
2220     //Complete.
2221     //-------------
2222     Inter.CompletInt (OffsetFaces,myInitOffsetFace);
2223     TopTools_IndexedMapOfShape& NewEdges = Inter.NewEdges();
2224     if (myJoin == GeomAbs_Intersection) {
2225       BRepOffset_Tool::CorrectOrientation (myShape,NewEdges,myAsDes,myInitOffsetFace,myOffset);
2226     }
2227   }
2228   else {
2229     //--------------------------------
2230     // Only between neighbor faces.
2231     //--------------------------------
2232     Inter.ConnexIntByArc(OffsetFaces,myShape,myAnalyse,myInitOffsetFace);
2233   }
2234 #ifdef OCCT_DEBUG
2235   if ( ChronBuild) Clock.Show();
2236 #endif
2237 }
2238
2239 //=======================================================================
2240 //function : Intersection2D
2241 //purpose  : 
2242 //=======================================================================
2243
2244 void BRepOffset_MakeOffset::Intersection2D(const TopTools_IndexedMapOfShape& Modif,
2245                                            const TopTools_IndexedMapOfShape& NewEdges)
2246 {
2247 #ifdef OCCT_DEBUG
2248   if (ChronBuild) {
2249     cout << " INTERSECTION 2D:" << endl;
2250     Clock.Reset();
2251     Clock.Start();  
2252   }
2253 #endif
2254   //--------------------------------------------------------
2255   // calculate intersections2d on faces concerned by 
2256   // intersection3d
2257   //---------------------------------------------------------
2258   //TopTools_MapIteratorOfMapOfShape it(Modif);
2259   //-----------------------------------------------
2260   // Intersection of edges 2 by 2.
2261   //-----------------------------------------------
2262   Standard_Integer i;
2263   for (i = 1; i <= Modif.Extent(); i++) {
2264     const TopoDS_Face& F  = TopoDS::Face(Modif(i));
2265     BRepOffset_Inter2d::Compute(myAsDes,F,NewEdges,myTol);
2266   }
2267
2268 #ifdef OCCT_DEBUG
2269   if (AffichInt2d) {
2270     DEBVerticesControl (NewEdges,myAsDes);
2271   }
2272   if ( ChronBuild) Clock.Show();
2273 #endif
2274 }
2275
2276
2277 //=======================================================================
2278 //function : MakeLoops
2279 //purpose  : 
2280 //=======================================================================
2281
2282 void BRepOffset_MakeOffset::MakeLoops(TopTools_IndexedMapOfShape& Modif)
2283 {
2284 #ifdef OCCT_DEBUG
2285   if (ChronBuild) {
2286      cout << " DEBOUCLAGE 2D:" << endl;
2287      Clock.Reset();
2288      Clock.Start(); 
2289   }
2290 #endif
2291   //TopTools_MapIteratorOfMapOfShape    it(Modif);
2292   TopTools_ListOfShape                LF,LC;
2293   //-----------------------------------------
2294   // unwinding of faces // modified.
2295   //-----------------------------------------
2296   Standard_Integer i;
2297   for (i = 1; i <= Modif.Extent(); i++) { 
2298     if (!myFaces.Contains(Modif(i)))
2299       LF.Append(Modif(i));
2300   }
2301   myMakeLoops.Build(LF,myAsDes,myImageOffset);
2302
2303   //-----------------------------------------
2304   // unwinding of caps.
2305   //-----------------------------------------
2306   for (i = 1; i <= myFaces.Extent(); i++)
2307     LC.Append(myFaces(i));
2308
2309   Standard_Boolean   InSide = 1;
2310   if (myOffset > 0 ) InSide = 0;
2311   myMakeLoops.BuildOnContext(LC,myAnalyse,myAsDes,myImageOffset,InSide);
2312
2313 #ifdef OCCT_DEBUG
2314   if ( ChronBuild) Clock.Show();
2315 #endif
2316 }
2317
2318 //=======================================================================
2319 //function : MakeFaces
2320 //purpose  : Reconstruction of topologically unchanged faces that
2321 //           share edges that were reconstructed.
2322 //=======================================================================
2323
2324 void BRepOffset_MakeOffset::MakeFaces(TopTools_IndexedMapOfShape& /*Modif*/)
2325 {
2326 #ifdef OCCT_DEBUG
2327   if (ChronBuild) {  
2328     cout << " RECONSTRUCTION OF FACES:" << endl;
2329     Clock.Reset();
2330     Clock.Start();
2331   }
2332 #endif
2333   TopTools_ListIteratorOfListOfShape itr;
2334   const TopTools_ListOfShape& Roots = myInitOffsetFace.Roots();
2335   TopTools_ListOfShape        LOF;
2336   //----------------------------------
2337   // Loop on all faces //.
2338   //----------------------------------
2339   for (itr.Initialize(Roots); itr.More(); itr.Next()) {
2340     TopoDS_Face F = TopoDS::Face(myInitOffsetFace.Image(itr.Value()).First());
2341     LOF.Append(F);
2342   }
2343   myMakeLoops.BuildFaces(LOF,myAsDes,myImageOffset);
2344   
2345 #ifdef OCCT_DEBUG
2346   if ( ChronBuild) Clock.Show();
2347 #endif
2348 }
2349
2350 //=======================================================================
2351 //function : UpdateInitOffset
2352 //purpose  : Update and cleaning of myInitOffset 
2353 //=======================================================================
2354
2355 static void UpdateInitOffset (BRepAlgo_Image&         myInitOffset,
2356                               BRepAlgo_Image&         myImageOffset,
2357                               const TopoDS_Shape&     myOffsetShape,
2358                               const TopAbs_ShapeEnum &theShapeType) // skv
2359 {
2360   BRepAlgo_Image NIOF;
2361   const TopTools_ListOfShape& Roots = myInitOffset.Roots();
2362   TopTools_ListIteratorOfListOfShape it(Roots);
2363   for (; it.More(); it.Next()) {
2364     NIOF.SetRoot (it.Value());    
2365   }
2366   for (it.Initialize(Roots); it.More(); it.Next()) {
2367     const TopoDS_Shape& SI = it.Value();
2368     TopTools_ListOfShape LI;
2369     TopTools_ListOfShape L1;
2370     myInitOffset.LastImage(SI,L1);
2371     TopTools_ListIteratorOfListOfShape itL1(L1);
2372     for (; itL1.More(); itL1.Next()) {
2373       const TopoDS_Shape& O1 = itL1.Value();
2374       TopTools_ListOfShape L2;
2375       myImageOffset.LastImage(O1,L2);
2376       LI.Append(L2);
2377     }
2378     NIOF.Bind(SI,LI);
2379   }
2380 //  Modified by skv - Mon Apr  4 18:17:27 2005 Begin
2381 //  Supporting history.
2382 //   NIOF.Filter(myOffsetShape,TopAbs_FACE);
2383   NIOF.Filter(myOffsetShape, theShapeType);
2384 //  Modified by skv - Mon Apr  4 18:17:27 2005 End
2385   myInitOffset = NIOF;
2386 }
2387
2388 //=======================================================================
2389 //function : MakeMissingWalls
2390 //purpose  : 
2391 //=======================================================================
2392
2393 void BRepOffset_MakeOffset::MakeMissingWalls ()
2394 {
2395   TopTools_DataMapOfShapeListOfShape Contours; //Start vertex + list of connected edges (free boundary)
2396   TopTools_DataMapOfShapeShape MapEF; //Edges of contours: edge + face
2397   Standard_Real OffsetVal = Abs(myOffset);
2398
2399   FillContours(myShape, myAnalyse, Contours, MapEF);
2400
2401   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape iter(Contours);
2402   for (; iter.More(); iter.Next())
2403     {
2404       TopoDS_Vertex StartVertex = TopoDS::Vertex(iter.Key());
2405       TopoDS_Edge StartEdge;
2406       const TopTools_ListOfShape& aContour = iter.Value();
2407       TopTools_ListIteratorOfListOfShape itl(aContour);
2408       Standard_Boolean FirstStep = Standard_True;
2409       TopoDS_Edge PrevEdge;
2410       TopoDS_Vertex PrevVertex = StartVertex;
2411       for (; itl.More(); itl.Next())
2412         {
2413           TopoDS_Edge anEdge = TopoDS::Edge(itl.Value());
2414           if (!myInitOffsetEdge.HasImage(anEdge))
2415             continue;
2416           //if (BRep_Tool::Degenerated(anEdge))
2417             //continue;
2418           TopoDS_Face aFace = TopoDS::Face(MapEF(anEdge));
2419           //TopoDS_Edge OE = TopoDS::Edge(myInitOffsetEdge.Image(anEdge).First());
2420           TopTools_ListOfShape LOE, LOE2;
2421           myInitOffsetEdge.LastImage( anEdge, LOE );
2422           myImageOffset.LastImage( LOE.Last(), LOE2 );
2423           TopoDS_Edge OE = TopoDS::Edge( LOE2.Last() );
2424           ////////////////////////////////////////////////////////////////////////
2425           TopoDS_Vertex V1, V2, V3, V4;
2426           TopExp::Vertices(anEdge, V1, V2/*, Standard_True*/);
2427           TopExp::Vertices(OE,     V4, V3/*, Standard_True*/);
2428           Standard_Boolean ToReverse = Standard_False;
2429           if (!V1.IsSame(PrevVertex))
2430             {
2431               TopoDS_Vertex aVtx = V1; V1 = V2; V2 = aVtx;
2432               aVtx = V3; V3 = V4; V4 = aVtx;
2433               ToReverse = Standard_True;
2434             }
2435           //Temporary
2436           //anEdge.Reverse();
2437           OE.Orientation(TopAbs::Reverse(anEdge.Orientation()));
2438           TopoDS_Edge E3, E4;
2439           if (FirstStep)
2440             {
2441               E4 = BRepLib_MakeEdge( V1, V4 );
2442               StartEdge = E4;
2443             }
2444           else
2445             E4 = PrevEdge;
2446           Standard_Boolean ArcOnV2 = ((myJoin == GeomAbs_Arc) && (myInitOffsetEdge.HasImage(V2)));
2447           if (V2.IsSame(StartVertex) && !ArcOnV2)
2448             E3 = StartEdge;
2449           else
2450             E3 = BRepLib_MakeEdge( V2, V3 );
2451           E4.Reverse();
2452           TopoDS_Shape localAnEdge = anEdge.Oriented(TopAbs_FORWARD);
2453           const TopoDS_Edge& anEdgeFWD = TopoDS::Edge(localAnEdge);
2454           Standard_Real ParV1 = BRep_Tool::Parameter(V1, anEdgeFWD);
2455           Standard_Real ParV2 = BRep_Tool::Parameter(V2, anEdgeFWD);
2456           BRep_Builder BB;
2457           TopoDS_Wire theWire;
2458           BB.MakeWire(theWire);
2459           if (ToReverse)
2460             {
2461               BB.Add(theWire, anEdge.Reversed());
2462               BB.Add(theWire, E3.Reversed());
2463               BB.Add(theWire, OE.Reversed());
2464               BB.Add(theWire, E4.Reversed());
2465             }
2466           else
2467             {
2468               BB.Add(theWire, anEdge);
2469               BB.Add(theWire, E3);
2470               BB.Add(theWire, OE);
2471               BB.Add(theWire, E4);
2472             }
2473           BRepLib::BuildCurves3d( theWire, myTol );
2474           theWire.Closed(Standard_True);
2475           TopoDS_Face NewFace;
2476           Handle(Geom_Surface) theSurf;
2477           BRepAdaptor_Curve BAcurve(anEdge);
2478           BRepAdaptor_Curve BAcurveOE(OE);
2479           Standard_Real fpar = BAcurve.FirstParameter();
2480           Standard_Real lpar = BAcurve.LastParameter();
2481           gp_Pnt PonE  = BAcurve.Value(fpar);
2482           gp_Pnt PonOE = BAcurveOE.Value(fpar);
2483           gp_Dir OffsetDir = gce_MakeDir( PonE, PonOE );
2484           Handle(Geom2d_Line) EdgeLine2d, OELine2d, aLine2d, aLine2d2;
2485           Standard_Boolean IsPlanar = Standard_False;
2486           if (BAcurve.GetType() == GeomAbs_Circle &&
2487               BAcurveOE.GetType() == GeomAbs_Circle)
2488           {
2489             gp_Circ aCirc = BAcurve.Circle();
2490             gp_Circ aCircOE = BAcurveOE.Circle();
2491             gp_Lin anAxisLine(aCirc.Axis());
2492             gp_Dir CircAxisDir = aCirc.Axis().Direction();
2493             if (aCirc.Axis().IsParallel(aCircOE.Axis(), Precision::Confusion()) &&
2494                 anAxisLine.Contains(aCircOE.Location(), Precision::Confusion()))
2495             { //cylinder, plane or cone
2496               if (Abs(aCirc.Radius() - aCircOE.Radius()) <= Precision::Confusion()) //case of cylinder
2497                 theSurf = GC_MakeCylindricalSurface(aCirc).Value();
2498               else if (aCirc.Location().Distance(aCircOE.Location()) <= Precision::Confusion()) {//case of plane
2499                 IsPlanar = Standard_True;
2500                 //
2501                 gp_Pnt PonEL = BAcurve.Value(lpar);
2502                 if (PonEL.Distance(PonE) <= Precision::PConfusion()) {
2503                   Standard_Boolean bIsHole;
2504                   TopoDS_Edge aE1, aE2;
2505                   TopoDS_Wire aW1, aW2;
2506                   Handle(Geom_Plane) aPL;
2507                   IntTools_FClass2d aClsf;
2508                   //
2509                   if (aCirc.Radius()>aCircOE.Radius()) {
2510                     aE1 = anEdge;
2511                     aE2 = OE;
2512                   } else {
2513                     aE1 = OE;
2514                     aE2 = anEdge;
2515                   }
2516                   //
2517                   BB.MakeWire(aW1);
2518                   BB.Add(aW1, aE1);
2519                   BB.MakeWire(aW2);
2520                   BB.Add(aW2, aE2);
2521                   //
2522                   aPL = new Geom_Plane(aCirc.Location(), CircAxisDir);
2523                   for (Standard_Integer i = 0; i < 2; ++i) {
2524                     TopoDS_Wire& aW = (i==0) ? aW1 : aW2;
2525                     TopoDS_Edge& aE = (i==0) ? aE1 : aE2;
2526                     //
2527                     TopoDS_Face aFace;
2528                     BB.MakeFace(aFace, aPL, Precision::Confusion());
2529                     BB.Add (aFace, aW);
2530                     aClsf.Init(aFace, Precision::Confusion());
2531                     bIsHole=aClsf.IsHole();
2532                     if ((bIsHole && !i) || (!bIsHole && i)) {
2533                       aW.Nullify();
2534                       BB.MakeWire(aW);
2535                       BB.Add(aW, aE.Reversed());
2536                     }
2537                   }
2538                   //
2539                   BB.MakeFace(NewFace, aPL, Precision::Confusion());
2540                   BB.Add(NewFace, aW1);
2541                   BB.Add(NewFace, aW2);
2542                 }
2543               }
2544               else //case of cone
2545               {
2546                 gp_Cone theCone = gce_MakeCone(aCirc.Location(), aCircOE.Location(),
2547                                                aCirc.Radius(), aCircOE.Radius());
2548                 gp_Ax3 theAx3(aCirc.Position());
2549                 if (CircAxisDir * theCone.Axis().Direction() < 0.)
2550                 {
2551                   theAx3.ZReverse();
2552                   CircAxisDir.Reverse();
2553                 }
2554                 theCone.SetPosition(theAx3);
2555                 theSurf = new Geom_ConicalSurface(theCone);
2556               }
2557               if (!IsPlanar) {
2558                 TopLoc_Location Loc;
2559                 EdgeLine2d = new Geom2d_Line(gp_Pnt2d(0., 0.), gp_Dir2d(1., 0.));
2560                 BB.UpdateEdge(anEdge, EdgeLine2d, theSurf, Loc, Precision::Confusion());
2561                 Standard_Real Coeff = (OffsetDir * CircAxisDir > 0.)? 1. : -1.;
2562                 OELine2d = new Geom2d_Line(gp_Pnt2d(0., OffsetVal*Coeff), gp_Dir2d(1., 0.));
2563                 BB.UpdateEdge(OE, OELine2d, theSurf, Loc, Precision::Confusion());
2564                 aLine2d  = new Geom2d_Line(gp_Pnt2d(ParV2, 0.), gp_Dir2d(0., Coeff));
2565                 aLine2d2 = new Geom2d_Line(gp_Pnt2d(ParV1, 0.), gp_Dir2d(0., Coeff));
2566                 if (E3.IsSame(E4))
2567                 {
2568                   if (Coeff > 0.)
2569                     BB.UpdateEdge(E3, aLine2d, aLine2d2, theSurf, Loc, Precision::Confusion());
2570                   else
2571                   {
2572                     BB.UpdateEdge(E3, aLine2d2, aLine2d, theSurf, Loc, Precision::Confusion());
2573                     theWire.Nullify();
2574                     BB.MakeWire(theWire);
2575                     BB.Add(theWire, anEdge.Oriented(TopAbs_REVERSED));
2576                     BB.Add(theWire, E4);
2577                     BB.Add(theWire, OE.Oriented(TopAbs_FORWARD));
2578                     BB.Add(theWire, E3);
2579                     theWire.Closed(Standard_True);
2580                   }
2581                 }
2582                 else
2583                 {
2584                   BB.SameParameter(E3, Standard_False);
2585                   BB.SameRange(E3, Standard_False);
2586                   BB.SameParameter(E4, Standard_False);
2587                   BB.SameRange(E4, Standard_False);
2588                   BB.UpdateEdge(E3, aLine2d,  theSurf, Loc, Precision::Confusion());
2589                   BB.Range(E3, theSurf, Loc, 0., OffsetVal);
2590                   BB.UpdateEdge(E4, aLine2d2, theSurf, Loc, Precision::Confusion());
2591                   BB.Range(E4, theSurf, Loc, 0., OffsetVal);
2592                 }
2593                 NewFace = BRepLib_MakeFace(theSurf, theWire);
2594               }
2595             } //cylinder or cone
2596           } //if both edges are arcs of circles
2597           if (NewFace.IsNull())
2598             {
2599               BRepLib_MakeFace MF(theWire, Standard_True); //Only plane
2600               if (MF.Error() == BRepLib_FaceDone)
2601                 {
2602                   NewFace = MF.Face();
2603                   IsPlanar = Standard_True;
2604                 }
2605               else //Extrusion (by thrusections)
2606                 {
2607                   Handle(Geom_Curve) EdgeCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
2608                   Handle(Geom_TrimmedCurve) TrEdgeCurve =
2609                     new Geom_TrimmedCurve( EdgeCurve, fpar, lpar );
2610                   Standard_Real fparOE, lparOE;
2611                   Handle(Geom_Curve) OffsetCurve = BRep_Tool::Curve(OE, fparOE, lparOE);
2612                   Handle(Geom_TrimmedCurve) TrOffsetCurve =
2613                     new Geom_TrimmedCurve( OffsetCurve, fparOE, lparOE );
2614                   GeomFill_Generator ThrusecGenerator;
2615                   ThrusecGenerator.AddCurve( TrEdgeCurve );
2616                   ThrusecGenerator.AddCurve( TrOffsetCurve );
2617                   ThrusecGenerator.Perform( Precision::PConfusion() );
2618                   theSurf = ThrusecGenerator.Surface();
2619                   //theSurf = new Geom_SurfaceOfLinearExtrusion( TrOffsetCurve, OffsetDir );
2620                   Standard_Real Uf, Ul, Vf, Vl;
2621                   theSurf->Bounds(Uf, Ul, Vf, Vl);
2622                   TopLoc_Location Loc;
2623                   EdgeLine2d = new Geom2d_Line(gp_Pnt2d(0., Vf), gp_Dir2d(1., 0.));
2624                   BB.UpdateEdge(anEdge, EdgeLine2d, theSurf, Loc, Precision::Confusion());
2625                   OELine2d = new Geom2d_Line(gp_Pnt2d(0., Vl), gp_Dir2d(1., 0.));
2626                   BB.UpdateEdge(OE, OELine2d, theSurf, Loc, Precision::Confusion());
2627                   Standard_Real UonV1 = (ToReverse)? Ul : Uf;
2628                   Standard_Real UonV2 = (ToReverse)? Uf : Ul;
2629                   aLine2d  = new Geom2d_Line(gp_Pnt2d(UonV2, 0.), gp_Dir2d(0., 1.));
2630                   aLine2d2 = new Geom2d_Line(gp_Pnt2d(UonV1, 0.), gp_Dir2d(0., 1.));
2631                   if (E3.IsSame(E4))
2632                     {
2633                       BB.UpdateEdge(E3, aLine2d, aLine2d2, theSurf, Loc, Precision::Confusion());
2634                       Handle(Geom_Curve) BSplC34 = theSurf->UIso( Uf );
2635                       BB.UpdateEdge(E3, BSplC34, Precision::Confusion());
2636                       BB.Range(E3, Vf, Vl);
2637                     }
2638                   else
2639                     {
2640                       BB.SameParameter(E3, Standard_False);
2641                       BB.SameRange(E3, Standard_False);
2642                       BB.SameParameter(E4, Standard_False);
2643                       BB.SameRange(E4, Standard_False);
2644                       BB.UpdateEdge(E3, aLine2d,  theSurf, Loc, Precision::Confusion());
2645                       BB.Range(E3, theSurf, Loc, Vf, Vl);
2646                       BB.UpdateEdge(E4, aLine2d2, theSurf, Loc, Precision::Confusion());
2647                       BB.Range(E4, theSurf, Loc, Vf, Vl);
2648                       Handle(Geom_Curve) BSplC3 = theSurf->UIso( UonV2 );
2649                       BB.UpdateEdge(E3, BSplC3, Precision::Confusion());
2650                       BB.Range(E3, Vf, Vl, Standard_True); //only for 3d curve
2651                       Handle(Geom_Curve) BSplC4 = theSurf->UIso( UonV1 );
2652                       BB.UpdateEdge(E4, BSplC4, Precision::Confusion());
2653                       BB.Range(E4, Vf, Vl, Standard_True); //only for 3d curve
2654                     }
2655                   NewFace = BRepLib_MakeFace(theSurf, theWire);
2656                 }
2657             }
2658           if (!IsPlanar)
2659             {
2660               Standard_Real fparOE = BAcurveOE.FirstParameter();
2661               Standard_Real lparOE = BAcurveOE.LastParameter();
2662               TopLoc_Location Loc;
2663               if (Abs(fpar - fparOE) > Precision::Confusion())
2664                 {
2665                   const TopoDS_Edge& anE4 = (ToReverse)? E3 : E4;
2666                   gp_Pnt2d fp2d   = EdgeLine2d->Value(fpar);
2667                   gp_Pnt2d fp2dOE = OELine2d->Value(fparOE);
2668                   aLine2d2 = GCE2d_MakeLine( fp2d, fp2dOE ).Value();
2669                   Handle(Geom_Curve) aCurve;
2670                   Standard_Real FirstPar = 0., LastPar = fp2d.Distance(fp2dOE);
2671                   Geom2dAdaptor_Curve AC2d( aLine2d2, FirstPar, LastPar );
2672                   GeomAdaptor_Surface GAsurf( theSurf );
2673                   Handle(Geom2dAdaptor_HCurve) HC2d  = new Geom2dAdaptor_HCurve( AC2d );
2674                   Handle(GeomAdaptor_HSurface) HSurf = new GeomAdaptor_HSurface( GAsurf );
2675                   Adaptor3d_CurveOnSurface ConS( HC2d, HSurf );
2676                   Standard_Real max_deviation = 0., average_deviation;
2677                   GeomLib::BuildCurve3d(Precision::Confusion(),
2678                                         ConS, FirstPar, LastPar,
2679                                         aCurve, max_deviation, average_deviation);
2680                   BB.UpdateEdge( anE4, aCurve, max_deviation );
2681                   BB.UpdateEdge( anE4, aLine2d2, theSurf, Loc, max_deviation );
2682                   BB.Range( anE4, FirstPar, LastPar );
2683                 }
2684               if (Abs(lpar - lparOE) > Precision::Confusion())
2685                 {
2686                   const TopoDS_Edge& anE3 = (ToReverse)? E4 : E3;
2687                   gp_Pnt2d lp2d   = EdgeLine2d->Value(lpar);
2688                   gp_Pnt2d lp2dOE = OELine2d->Value(lparOE);
2689                   aLine2d = GCE2d_MakeLine( lp2d, lp2dOE ).Value();
2690                   Handle(Geom_Curve) aCurve;
2691                   Standard_Real FirstPar = 0., LastPar = lp2d.Distance(lp2dOE);
2692                   Geom2dAdaptor_Curve AC2d( aLine2d, FirstPar, LastPar );
2693                   GeomAdaptor_Surface GAsurf( theSurf );
2694                   Handle(Geom2dAdaptor_HCurve) HC2d  = new Geom2dAdaptor_HCurve( AC2d );
2695                   Handle(GeomAdaptor_HSurface) HSurf = new GeomAdaptor_HSurface( GAsurf );
2696                   Adaptor3d_CurveOnSurface ConS( HC2d, HSurf );
2697                   Standard_Real max_deviation = 0., average_deviation;
2698                   GeomLib::BuildCurve3d(Precision::Confusion(),
2699                                         ConS, FirstPar, LastPar,
2700                                         aCurve, max_deviation, average_deviation);
2701                   BB.UpdateEdge( anE3, aCurve, max_deviation );
2702                   BB.UpdateEdge( anE3, aLine2d, theSurf, Loc, max_deviation );
2703                   BB.Range( anE3, FirstPar, LastPar );
2704                 }
2705             }
2706           BRepLib::SameParameter(NewFace);
2707           BRepTools::Update(NewFace);
2708           myWalls.Append(NewFace);
2709           if (ArcOnV2)
2710             {
2711               TopoDS_Edge anArc = TopoDS::Edge(myInitOffsetEdge.Image(V2).First());
2712               TopoDS_Vertex arcV1, arcV2;
2713               TopExp::Vertices(anArc, arcV1, arcV2);
2714               Standard_Boolean ArcReverse = Standard_False;
2715               if (!arcV1.IsSame(V3))
2716                 {
2717                   TopoDS_Vertex aVtx = arcV1; arcV1 = arcV2; arcV2 = aVtx;
2718                   ArcReverse = Standard_True;
2719                 }
2720               TopoDS_Edge EA1, EA2;
2721               //EA1 = (ToReverse)? E3 : TopoDS::Edge(E3.Reversed());
2722               EA1 = E3;
2723               EA1.Reverse();
2724               if (ToReverse)
2725                 EA1.Reverse();
2726               //////////////////////////////////////////////////////
2727               if (V2.IsSame(StartVertex))
2728                 EA2 = StartEdge;
2729               else
2730                 EA2 = BRepLib_MakeEdge( V2, arcV2 );
2731               anArc.Orientation( ((ArcReverse)? TopAbs_REVERSED : TopAbs_FORWARD) );
2732               if (EA1.Orientation() == TopAbs_REVERSED)
2733                 anArc.Reverse();
2734               EA2.Orientation(TopAbs::Reverse(EA1.Orientation()));
2735               TopoDS_Wire arcWire;
2736               BB.MakeWire(arcWire);
2737               BB.Add(arcWire, EA1);
2738               BB.Add(arcWire, anArc);
2739               BB.Add(arcWire, EA2);
2740               BRepLib::BuildCurves3d( arcWire, myTol );
2741               arcWire.Closed(Standard_True);
2742               TopoDS_Face arcFace = BRepLib_MakeFace(arcWire, Standard_True);
2743               BRepTools::Update(arcFace);
2744               myWalls.Append(arcFace);
2745               TopoDS_Shape localEA2 = EA2.Oriented(TopAbs_FORWARD);
2746               const TopoDS_Edge& CEA2 = TopoDS::Edge(localEA2);
2747               PrevEdge = CEA2;
2748               PrevVertex = V2;
2749             }
2750           else
2751             {
2752               PrevEdge = E3;
2753               PrevVertex = V2;
2754             }
2755           FirstStep = Standard_False;
2756         }
2757     }
2758 }
2759
2760 //=======================================================================
2761 //function : MakeShells
2762 //purpose  : 
2763 //=======================================================================
2764
2765 void BRepOffset_MakeOffset::MakeShells ()
2766 {
2767 #ifdef OCCT_DEBUG
2768   if (ChronBuild) {  
2769     cout << " RECONSTRUCTION OF SHELLS:" << endl;
2770     Clock.Reset();
2771     Clock.Start();
2772   }
2773 #endif
2774   BRepTools_Quilt Glue;
2775   const TopTools_ListOfShape& R = myImageOffset.Roots();
2776   TopTools_ListIteratorOfListOfShape it(R);
2777
2778   for ( ; it.More(); it.Next()) {
2779     TopTools_ListOfShape Image;
2780     myImageOffset.LastImage(it.Value(),Image);
2781     TopTools_ListIteratorOfListOfShape it2(Image);
2782     for ( ; it2.More(); it2.Next()) {
2783       Glue.Add(it2.Value());
2784     }
2785   }
2786
2787   if (myThickening)
2788     {
2789       TopExp_Explorer Explo(myShape, TopAbs_FACE);
2790       for (; Explo.More(); Explo.Next())
2791         Glue.Add(Explo.Current());
2792       
2793       for (it.Initialize(myWalls); it.More(); it.Next())
2794         Glue.Add(it.Value());
2795     }
2796
2797   myOffsetShape = Glue.Shells();
2798 }
2799
2800 //=======================================================================
2801 //function : MakeSolid
2802 //purpose  : 
2803 //=======================================================================
2804
2805 void BRepOffset_MakeOffset::MakeSolid ()
2806 {
2807  if (myOffsetShape.IsNull()) return;
2808
2809 //  Modified by skv - Mon Apr  4 18:17:27 2005 Begin
2810 //  Supporting history.
2811   UpdateInitOffset (myInitOffsetFace,myImageOffset,myOffsetShape, TopAbs_FACE);
2812   UpdateInitOffset (myInitOffsetEdge,myImageOffset,myOffsetShape, TopAbs_EDGE);
2813 //  Modified by skv - Mon Apr  4 18:17:27 2005 End
2814   TopExp_Explorer             exp;
2815   BRep_Builder                B;
2816   Standard_Integer            NbShell = 0;
2817   TopoDS_Compound             NC;
2818   TopoDS_Shape                S1;
2819   B.MakeCompound (NC);
2820
2821   for (exp.Init(myOffsetShape,TopAbs_SHELL); exp.More(); exp.Next()) {
2822     TopoDS_Shell Sh = TopoDS::Shell(exp.Current());
2823     if (myThickening && myOffset > 0.)
2824       Sh.Reverse();
2825     NbShell++;
2826     if (Sh.Closed()) {
2827       TopoDS_Solid  Sol;
2828       B.MakeSolid  (Sol);
2829       B.Add        (Sol,Sh);
2830       Sol.Closed(Standard_True);
2831       B.Add (NC,Sol);
2832       if (NbShell == 1) S1 = Sol;
2833     }
2834     else {
2835       B.Add (NC,Sh);
2836       if (NbShell == 1) S1 = Sh;
2837     }
2838   }
2839   if (NbShell == 1) myOffsetShape = S1;
2840   else              myOffsetShape = NC;
2841 }
2842
2843 //=======================================================================
2844 //function : SelectShells
2845 //purpose  : 
2846 //=======================================================================
2847
2848 void BRepOffset_MakeOffset::SelectShells ()
2849 {  
2850   TopTools_MapOfShape FreeEdges;
2851   TopExp_Explorer exp(myShape,TopAbs_EDGE);
2852   //-------------------------------------------------------------
2853   // FreeEdges all edges that can have free border in the  
2854   // parallel shell
2855   // 1 - free borders of myShape .
2856   //-------------------------------------------------------------
2857   for ( ; exp.More(); exp.Next()) {
2858     const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
2859     const TopTools_ListOfShape& LA = myAnalyse.Ancestors(E);
2860     if (LA.Extent() < 2) {
2861       if (myAnalyse.Type(E).First().Type() == BRepOffset_FreeBoundary) {
2862         FreeEdges.Add(E);                       
2863       }
2864     }  
2865   }
2866   // myShape has free borders and there are no caps
2867   // no unwinding 3d.
2868   if (!FreeEdges.IsEmpty() && myFaces.IsEmpty()) return;
2869
2870   myOffsetShape = BRepOffset_Tool::Deboucle3D(myOffsetShape,FreeEdges);
2871 }
2872
2873 //=======================================================================
2874 //function : OffsetFacesFromShapes
2875 //purpose  : 
2876 //=======================================================================
2877
2878 const BRepAlgo_Image& BRepOffset_MakeOffset::OffsetFacesFromShapes() const
2879 {
2880   return myInitOffsetFace;
2881 }
2882
2883 //  Modified by skv - Tue Mar 15 16:20:43 2005 Begin
2884
2885 //=======================================================================
2886 //function : GetJoinType
2887 //purpose  : Query offset join type.
2888 //=======================================================================
2889
2890 GeomAbs_JoinType BRepOffset_MakeOffset::GetJoinType() const
2891 {
2892   return myJoin;
2893 }
2894
2895 //=======================================================================
2896 //function : OffsetEdgesFromShapes
2897 //purpose  : 
2898 //=======================================================================
2899
2900 const BRepAlgo_Image& BRepOffset_MakeOffset::OffsetEdgesFromShapes() const
2901 {
2902   return myInitOffsetEdge;
2903 }
2904
2905 //  Modified by skv - Tue Mar 15 16:20:43 2005 End
2906
2907 //=======================================================================
2908 //function : ClosingFaces
2909 //purpose  : 
2910 //=======================================================================
2911
2912 const TopTools_IndexedMapOfShape& BRepOffset_MakeOffset::ClosingFaces () const
2913 {
2914   return myFaces;
2915 }
2916
2917
2918
2919 //=======================================================================
2920 //function : EncodeRegularity
2921 //purpose  : 
2922 //=======================================================================
2923
2924 void BRepOffset_MakeOffset::EncodeRegularity ()
2925 {
2926 #ifdef OCCT_DEBUG
2927   if (ChronBuild) {  
2928     cout << " CODING OF REGULARITIES:" << endl;
2929     Clock.Reset();
2930     Clock.Start();
2931   }
2932 #endif
2933
2934   if (myOffsetShape.IsNull()) return;
2935   // find edges G1 in the result
2936   TopExp_Explorer exp(myOffsetShape,TopAbs_EDGE);
2937
2938   BRep_Builder B;
2939   TopTools_MapOfShape MS;
2940
2941   for ( ; exp.More(); exp.Next()) {
2942     TopoDS_Edge OE  = TopoDS::Edge(exp.Current());
2943     BRepLib::BuildCurve3d(OE,myTol);
2944     TopoDS_Edge ROE = OE;
2945     
2946     if ( !MS.Add(OE)) continue;
2947       
2948     if ( myImageOffset.IsImage(OE)) 
2949       ROE = TopoDS::Edge(myImageOffset.Root(OE));
2950
2951     const TopTools_ListOfShape& LofOF    = myAsDes->Ascendant(ROE);
2952     
2953     if (LofOF.Extent() != 2) {
2954 #ifdef OCCT_DEBUG_VERB
2955     cout << " Edge shared by " << LofOF.Extent() << " Faces" << endl;
2956 #endif
2957       continue;
2958     }
2959
2960     const TopoDS_Face& F1 = TopoDS::Face(LofOF.First());
2961     const TopoDS_Face& F2 = TopoDS::Face(LofOF.Last() );
2962     
2963     if ( F1.IsNull() || F2.IsNull()) 
2964       continue;
2965    
2966     const TopoDS_Shape& Root1 = myInitOffsetFace.Root(F1);
2967     const TopoDS_Shape& Root2 = myInitOffsetFace.Root(F2);
2968
2969     TopAbs_ShapeEnum Type1 = Root1.ShapeType();
2970     TopAbs_ShapeEnum Type2 = Root2.ShapeType();
2971  
2972     if (F1.IsSame(F2)) {      
2973       if (BRep_Tool::IsClosed(OE,F1)) {
2974         // Temporary Debug for the Bench.
2975         // Check with YFR.
2976         // In mode intersection, the edges are not coded in myInitOffsetEdge
2977         // so, manage case by case
2978         // Note DUB; for Hidden parts, it is NECESSARY to code CN 
2979         // Analytic Surfaces.
2980         if (myJoin == GeomAbs_Intersection) {
2981           BRepAdaptor_Surface BS(F1,Standard_False);
2982           GeomAbs_SurfaceType SType = BS.GetType();
2983           if (SType == GeomAbs_Cylinder ||
2984               SType == GeomAbs_Cone     ||
2985               SType == GeomAbs_Sphere   ||
2986               SType == GeomAbs_Torus      ) {
2987             B.Continuity(OE,F1,F1,GeomAbs_CN);
2988           }
2989           else {
2990             // See YFR : MaJ of myInitOffsetFace
2991           }
2992         }
2993         else if (myInitOffsetEdge.IsImage(ROE)) {
2994           if ( Type1 == TopAbs_FACE && Type2 == TopAbs_FACE) {
2995             const TopoDS_Face& FRoot = TopoDS::Face(Root1);
2996             const TopoDS_Edge& EI = TopoDS::Edge(myInitOffsetEdge.ImageFrom(ROE));
2997             GeomAbs_Shape Conti = BRep_Tool::Continuity(EI,FRoot,FRoot);
2998             if (Conti == GeomAbs_CN) {
2999               B.Continuity(OE,F1,F1,GeomAbs_CN);
3000             }
3001             else if ( Conti > GeomAbs_C0) {
3002               B.Continuity(OE,F1,F1,GeomAbs_G1);
3003             }
3004           }
3005         }
3006       }
3007       continue;
3008     }
3009
3010
3011     //  code regularities G1 between :
3012     //    - sphere and tube : one root is a vertex, the other is an edge 
3013     //                        and the vertex is included in the edge
3014     //    - face and tube   : one root is a face, the other an edge 
3015     //                        and the edge is included in the face
3016     //    - face and face    : if two root faces are tangent in 
3017     //                        the initial shape, they will be tangent in the offset shape
3018     //    - tube and tube  : if 2 edges generating tubes are
3019     //                        tangents, the 2 will be tangent either.
3020     if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_VERTEX) {
3021       TopoDS_Vertex V1,V2;
3022       TopExp::Vertices(TopoDS::Edge(Root1), V1, V2);
3023       if ( V1.IsSame(Root2) || V2.IsSame(Root2)) {
3024         B.Continuity(OE,F1,F2,GeomAbs_G1);
3025       }
3026     }
3027     else if ( Type1 == TopAbs_VERTEX && Type2 == TopAbs_EDGE) {
3028       TopoDS_Vertex V1,V2;
3029       TopExp::Vertices(TopoDS::Edge(Root2), V1, V2);
3030       if ( V1.IsSame(Root1) || V2.IsSame(Root1)) {
3031         B.Continuity(OE,F1,F2,GeomAbs_G1);
3032       }
3033     }
3034     else if ( Type1 == TopAbs_FACE && Type2 == TopAbs_EDGE) {
3035       TopExp_Explorer exp2(Root1,TopAbs_EDGE);
3036       for ( ; exp2.More(); exp2.Next()) {
3037         if ( exp2.Current().IsSame(Root2)) {
3038           B.Continuity(OE,F1,F2,GeomAbs_G1);
3039           break;
3040         }
3041       }
3042     }
3043     else if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_FACE) {
3044       TopExp_Explorer exp2(Root2,TopAbs_EDGE);
3045       for ( ; exp2.More(); exp2.Next()) {
3046         if ( exp2.Current().IsSame(Root1)) {
3047           B.Continuity(OE,F1,F2,GeomAbs_G1);
3048           break;
3049         }
3050       }
3051     }
3052     else if ( Type1 == TopAbs_FACE && Type2 == TopAbs_FACE) {
3053     //  if two root faces are tangent in 
3054     //  the initial shape, they will be tangent in the offset shape
3055       TopTools_ListOfShape LE,LV;
3056       BRepOffset_Tool::HasCommonShapes(TopoDS::Face(Root1),
3057                                        TopoDS::Face(Root2),
3058                                        LE,LV);
3059       if ( LE.Extent() == 1) { 
3060         const TopoDS_Edge& Ed = TopoDS::Edge(LE.First());
3061         if ( myAnalyse.HasAncestor(Ed)) {
3062           const BRepOffset_ListOfInterval& LI = myAnalyse.Type(Ed);
3063           if (LI.Extent()       == 1   && 
3064               LI.First().Type() == BRepOffset_Tangent) {
3065             B.Continuity(OE,F1,F2,GeomAbs_G1);
3066           }
3067         }
3068       }
3069     }
3070     else if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_EDGE) {
3071       TopTools_ListOfShape LV;
3072       TopExp_Explorer exp1,exp2;
3073       for (exp1.Init(Root1,TopAbs_VERTEX); exp1.More(); exp1.Next()) {
3074         TopExp_Explorer exp2(F2,TopAbs_EDGE);
3075         for (exp2.Init(Root2,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
3076           if (exp1.Current().IsSame(exp2.Current())) {
3077             LV.Append(exp1.Current());
3078           }
3079         }
3080       }
3081       if ( LV.Extent() == 1) {
3082         TopTools_ListOfShape LEdTg;
3083         myAnalyse.TangentEdges(TopoDS::Edge(Root1),
3084                                TopoDS::Vertex(LV.First()),
3085                                LEdTg);
3086         TopTools_ListIteratorOfListOfShape it(LEdTg);
3087         for (; it.More(); it.Next()) {
3088           if ( it.Value().IsSame(Root2)) {
3089             B.Continuity(OE,F1,F2,GeomAbs_G1);
3090             break;
3091           }
3092         }
3093       }
3094     }
3095   }
3096
3097 #ifdef OCCT_DEBUG
3098   if ( ChronBuild) Clock.Show();
3099 #endif
3100 }
3101
3102
3103
3104 //=======================================================================
3105 //function : UpDateTolerance
3106 //purpose  : 
3107 //=======================================================================
3108
3109 static void UpdateTolerance (TopoDS_Shape& S,
3110                              const TopTools_IndexedMapOfShape& Faces)
3111 {
3112   BRep_Builder B;
3113   TopTools_MapOfShape View;
3114   TopoDS_Vertex V[2];
3115
3116   // The edges of caps are not modified.
3117   Standard_Integer j;
3118   for (j = 1; j <= Faces.Extent(); j++) {
3119     const TopoDS_Shape& F = Faces(j);
3120     TopExp_Explorer Exp;
3121     for (Exp.Init(F,TopAbs_EDGE); Exp.More(); Exp.Next()) {
3122       View.Add(Exp.Current());
3123     }
3124   }
3125   
3126   TopExp_Explorer Exp;
3127   for (Exp.Init(S,TopAbs_EDGE); Exp.More(); Exp.Next()) {
3128     TopoDS_Edge E = TopoDS::Edge(Exp.Current());
3129     if (View.Add(E)) {
3130       Handle(BRepCheck_Edge) EdgeCorrector = new BRepCheck_Edge(E);
3131       Standard_Real    Tol = EdgeCorrector->Tolerance();
3132       B.UpdateEdge (E,Tol);
3133       
3134       // Update the vertices.
3135       TopExp::Vertices(E,V[0],V[1]);
3136      
3137       for (Standard_Integer i = 0 ; i <=1 ; i++) {
3138         if (View.Add(V[i])) {
3139           Handle(BRep_TVertex) TV = Handle(BRep_TVertex)::DownCast(V[i].TShape());
3140           TV->Tolerance(0.);
3141           Handle(BRepCheck_Vertex) VertexCorrector = new BRepCheck_Vertex(V[i]);
3142           B.UpdateVertex (V[i],VertexCorrector->Tolerance());
3143           // use the occasion to clean the vertices.
3144           (TV->ChangePoints()).Clear();
3145         }
3146         B.UpdateVertex(V[i],Tol);
3147       }
3148     }
3149   }
3150 }
3151