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