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