]> OCCT Git - occt-copy.git/commitdiff
Corrections in splitting faces and making shells functions.
authoremv <emv@opencascade.com>
Fri, 10 Jul 2015 09:52:58 +0000 (12:52 +0300)
committeremv <emv@opencascade.com>
Fri, 10 Jul 2015 09:52:58 +0000 (12:52 +0300)
src/BRepOffset/BRepOffset_MakeOffset.cxx

index 6bb83429923a3c19238a1da870fd453e07a5bd68..f7f99de611975e37f1dc8b5d8699a76eec79ae69 100644 (file)
@@ -62,6 +62,8 @@
 #include <TopTools_DataMapOfShapeShape.hxx>
 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
 #include <TopTools_DataMapIteratorOfDataMapOfShapeReal.hxx>
+#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
+#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
 #include <TColStd_ListIteratorOfListOfInteger.hxx>
 
 #include <Standard_NotImplemented.hxx>
@@ -90,7 +92,6 @@
 
 #include <BRepAdaptor_Curve.hxx>
 #include <BRepAdaptor_Curve2d.hxx>
-#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
 #include <Geom_SphericalSurface.hxx>
 #include <TopoDS_Wire.hxx>
 #include <BRepTools_Substitution.hxx>
 #include <IntTools_FClass2d.hxx>
 #include <BRepLib_FindSurface.hxx>
 
+#include <BOPAlgo_PaveFiller.hxx>
+#include <BOPAlgo_Builder.hxx>
+#include <BOPAlgo_MakerVolume.hxx>
+
+#include <BOPCol_ListOfShape.hxx>
+#include <BOPCol_DataMapOfShapeShape.hxx>
+#include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
+
+#include <BOPTools.hxx>
+#include <BOPTools_AlgoTools3D.hxx>
+#include <BOPTools_AlgoTools.hxx>
+
+#include <IntTools_Context.hxx>
+#include <IntTools_ShrunkRange.hxx>
+
+#include <CPnts_AbscissaPoint.hxx>
+
 
 // POP for NT
 #include <stdio.h>
@@ -239,242 +257,114 @@ static void DEBVerticesControl (const TopTools_IndexedMapOfShape& NewEdges,
 #endif
 
 
-static void UpdateTolerance (      TopoDS_Shape&               myShape,
-                             const TopTools_IndexedMapOfShape& myFaces);
-
-
-static Standard_Boolean FindParameter(const TopoDS_Vertex& V, 
-                                      const TopoDS_Edge& E,
-                                      Standard_Real& U)
-{
-  // Search the vertex in the edge
-
-  Standard_Boolean rev = Standard_False;
-  TopoDS_Shape VF;
-  TopAbs_Orientation orient = TopAbs_INTERNAL;
-
-  TopoDS_Iterator itv(E.Oriented(TopAbs_FORWARD));
-
-  // if the edge has no vertices
-  // and is degenerated use the vertex orientation
-  // RLE, june 94
-
-  if (!itv.More() && BRep_Tool::Degenerated(E)) {
-    orient = V.Orientation();
-  }
-
-  while (itv.More()) {
-    const TopoDS_Shape& Vcur = itv.Value();
-    if (V.IsSame(Vcur)) {
-      if (VF.IsNull()) {
-        VF = Vcur;
-      }
-      else {
-        rev = E.Orientation() == TopAbs_REVERSED;
-        if (Vcur.Orientation() == V.Orientation()) {
-          VF = Vcur;
-        }
-      }
-    }
-    itv.Next();
-  }
-  
-  if (!VF.IsNull()) orient = VF.Orientation();
-  Standard_Real f,l;
-
-  if (orient ==  TopAbs_FORWARD) {
-    BRep_Tool::Range(E,f,l);
-    //return (rev) ? l : f;
-    U = (rev) ? l : f;
-    return Standard_True;
-  }
-  else if (orient ==  TopAbs_REVERSED) {
-    BRep_Tool::Range(E,f,l);
-    //return (rev) ? f : l;
-    U = (rev) ? f : l;
-    return Standard_True;
-   }
-
-  else {
-    TopLoc_Location L;
-    const Handle(Geom_Curve)& C = BRep_Tool::Curve(E,L,f,l);
-    L = L.Predivided(V.Location());
-    if (!C.IsNull() || BRep_Tool::Degenerated(E)) {
-      BRep_ListIteratorOfListOfPointRepresentation itpr
-        ((*((Handle(BRep_TVertex)*) &V.TShape()))->Points());
-
-      while (itpr.More()) {
-        const Handle(BRep_PointRepresentation)& pr = itpr.Value();
-        if (pr->IsPointOnCurve(C,L)) {
-          Standard_Real p = pr->Parameter();
-          Standard_Real res = p;// SVV 4 nov 99 - to avoid warnings on Linux
-          if (!C.IsNull()) {
-            // Closed curves RLE 16 june 94
-            if (Precision::IsNegativeInfinite(f))
-              {
-                //return pr->Parameter();//p;
-                U = pr->Parameter();
-                return Standard_True;
-              }
-            if (Precision::IsPositiveInfinite(l))
-              {
-                //return pr->Parameter();//p;
-                U = pr->Parameter();
-                return Standard_True;
-              }
-            gp_Pnt Pf = C->Value(f).Transformed(L.Transformation());
-            gp_Pnt Pl = C->Value(l).Transformed(L.Transformation());
-            Standard_Real tol = BRep_Tool::Tolerance(V);
-            if (Pf.Distance(Pl) < tol) {
-              if (Pf.Distance(BRep_Tool::Pnt(V)) < tol) {
-                if (V.Orientation() == TopAbs_FORWARD) res = f;//p = f;
-                else                                   res = l;//p = l;
-              }
-            }
-          }
-          //return res;//p;
-          U = res;
-          return Standard_True;
-        }
-        itpr.Next();
-      }
-    }
-    else {
-      // no 3d curve !!
-      // let us try with the first pcurve
-      Handle(Geom2d_Curve) PC;
-      Handle(Geom_Surface) S;
-      BRep_Tool::CurveOnSurface(E,PC,S,L,f,l);
-      L = L.Predivided(V.Location()); 
-      BRep_ListIteratorOfListOfPointRepresentation itpr
-        ((*((Handle(BRep_TVertex)*) &V.TShape()))->Points());
-
-      while (itpr.More()) {
-        const Handle(BRep_PointRepresentation)& pr = itpr.Value();
-        if (pr->IsPointOnCurveOnSurface(PC,S,L)) {
-          Standard_Real p = pr->Parameter();
-          // Closed curves RLE 16 june 94
-          if (PC->IsClosed()) {
-            if ((p == PC->FirstParameter()) || 
-                (p == PC->LastParameter())) {
-              if (V.Orientation() == TopAbs_FORWARD) p = PC->FirstParameter();
-              else                                   p = PC->LastParameter();
-            }
-          }
-          //return p;
-          U = p;
-          return Standard_True;
-        }
-        itpr.Next();
-      }
-    }
-  }
-  
-  //Standard_NoSuchObject::Raise("BRep_Tool:: no parameter on edge");
-  return Standard_False;
-}
-
 //=======================================================================
-//function : GetEdgePoints
-//purpose  : gets the first, last and middle points of the edge
+// static methods
 //=======================================================================
-static void GetEdgePoints(const TopoDS_Edge& anEdge,
-                                      const TopoDS_Face& aFace,
-                                      gp_Pnt& fPnt, gp_Pnt& mPnt,
-                                      gp_Pnt& lPnt)
-{
-  Standard_Real f, l;
-  Handle(Geom2d_Curve) theCurve = BRep_Tool::CurveOnSurface( anEdge, aFace, f, l );
-  gp_Pnt2d fPnt2d = theCurve->Value(f);
-  gp_Pnt2d lPnt2d = theCurve->Value(l);
-  gp_Pnt2d mPnt2d = theCurve->Value(0.5*(f + l));
-  Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
-  fPnt = aSurf->Value(fPnt2d.X(),fPnt2d.Y());
-  lPnt = aSurf->Value(lPnt2d.X(),lPnt2d.Y());
-  mPnt = aSurf->Value(mPnt2d.X(), mPnt2d.Y());
-}
+static 
+  void UpdateTolerance(TopoDS_Shape& myShape,
+                       const TopTools_IndexedMapOfShape& myFaces);
+
+static 
+  Standard_Boolean FindParameter(const TopoDS_Vertex& V, 
+                                 const TopoDS_Edge& E,
+                                 Standard_Real& U);
+
+static 
+  void GetEdgePoints(const TopoDS_Edge& anEdge,
+                     const TopoDS_Face& aFace,
+                     gp_Pnt& fPnt, gp_Pnt& mPnt,
+                     gp_Pnt& lPnt);
+
+static 
+  void FillContours(const TopoDS_Shape& aShape,
+                    const BRepOffset_Analyse& Analyser,
+                    TopTools_DataMapOfShapeListOfShape& Contours,
+                    TopTools_DataMapOfShapeShape& MapEF);
+
+static 
+  void RemoveCorks(TopoDS_Shape&               S,
+                   TopTools_IndexedMapOfShape& Faces);
+
+static 
+  Standard_Boolean IsConnectedShell(const TopoDS_Shape& S);
+
+static 
+  void MakeList(TopTools_ListOfShape&             OffsetFaces,
+                const BRepAlgo_Image&             myInitOffsetFace,
+                const TopTools_IndexedMapOfShape& myFaces);
+
+static 
+  void EvalMax(const TopoDS_Shape& S, 
+               Standard_Real& Tol);
+
+static 
+  void TrimEdge(TopoDS_Edge&                  NE,
+                const Handle(BRepAlgo_AsDes)& AsDes2d,
+                Handle(BRepAlgo_AsDes)& AsDes);
+
+static 
+  void SortFaces(const TopTools_ListOfShape& theLIm, 
+                 TopTools_ListOfShape& theLFImages,
+                 const Standard_Boolean bKeepFirst);
+
+static 
+  Standard_Boolean FindShape(const TopoDS_Shape& theSWhat,
+                             const TopoDS_Shape& theSWhere,
+                             TopoDS_Shape& theRes);
+
+static 
+  void UpdateOrigins(TopTools_IndexedDataMapOfShapeListOfShape& theOrigins,
+                     BOPAlgo_Builder& theGF);
+
+static 
+  Standard_Boolean IsMicroEdge(const TopoDS_Edge& theEdge,
+                               const Handle(IntTools_Context)& theCtx,
+                               Standard_Real& theFuzz);
+
+static 
+  Standard_Boolean ComputeBiNormal(const TopoDS_Face& theF,
+                                   const TopoDS_Edge& theE,
+                                   gp_Dir& theDB);
+static 
+  Standard_Boolean CheckBiNormals(const TopoDS_Face& aFIm,
+                                  const TopoDS_Face& aFOr,
+                                  const TopTools_IndexedDataMapOfShapeListOfShape& theOrigins,
+                                  const TopTools_MapOfShape& theMFence,
+                                  Standard_Boolean& bKeep,
+                                  Standard_Boolean& bRem);
+
+static 
+  void CheckBiNormals(TopTools_ListOfShape&  theLFImages,
+                      const TopoDS_Face& theF,
+                      const TopTools_IndexedDataMapOfShapeListOfShape& theOrigins,
+                      TopTools_ListOfShape& theLFKeep);
+
+static 
+  Standard_Boolean CheckNormals(const TopoDS_Face& theFIm,
+                                const TopoDS_Face& theFOr);
+
+static 
+  void UpdateInitOffset(BRepAlgo_Image&         myInitOffset,
+                        BRepAlgo_Image&         myImageOffset,
+                        const TopoDS_Shape&     myOffsetShape,
+                        const TopAbs_ShapeEnum &theShapeType);
 
 //=======================================================================
-//function : FillContours
-//purpose  : fills free boundary contours and faces connected (MapEF)
-//=======================================================================
-static void FillContours(const TopoDS_Shape& aShape,
-                         const BRepOffset_Analyse& Analyser,
-                         TopTools_DataMapOfShapeListOfShape& Contours,
-                         TopTools_DataMapOfShapeShape& MapEF)
-{
-  TopTools_ListOfShape Edges;
-
-  TopExp_Explorer Explo(aShape, TopAbs_FACE);
-  BRepTools_WireExplorer Wexp;
-
-  for (; Explo.More(); Explo.Next())
-    {
-      TopoDS_Face aFace = TopoDS::Face(Explo.Current());
-      TopoDS_Iterator itf(aFace);
-      for (; itf.More(); itf.Next())
-        {
-          TopoDS_Wire aWire = TopoDS::Wire(itf.Value());
-          for (Wexp.Init(aWire, aFace); Wexp.More(); Wexp.Next())
-            {
-              TopoDS_Edge anEdge = Wexp.Current();
-              if (BRep_Tool::Degenerated(anEdge))
-                continue;
-              const BRepOffset_ListOfInterval& Lint = Analyser.Type(anEdge);
-              if (!Lint.IsEmpty() && Lint.First().Type() == BRepOffset_FreeBoundary)
-                {
-                  MapEF.Bind(anEdge, aFace);
-                  Edges.Append(anEdge);
-                }
-            }
-        }
-    }
 
-  TopTools_ListIteratorOfListOfShape itl;
-  while (!Edges.IsEmpty())
-    {
-      TopoDS_Edge StartEdge = TopoDS::Edge(Edges.First());
-      Edges.RemoveFirst();
-      TopoDS_Vertex StartVertex, CurVertex;
-      TopExp::Vertices(StartEdge, StartVertex, CurVertex, Standard_True);
-      TopTools_ListOfShape aContour;
-      aContour.Append(StartEdge);
-      while (!CurVertex.IsSame(StartVertex))
-        for (itl.Initialize(Edges); itl.More(); itl.Next())
-          {
-            TopoDS_Edge anEdge = TopoDS::Edge(itl.Value());
-            TopoDS_Vertex V1, V2;
-            TopExp::Vertices(anEdge, V1, V2);
-            if (V1.IsSame(CurVertex) || V2.IsSame(CurVertex))
-              {
-                aContour.Append(anEdge);
-                CurVertex = (V1.IsSame(CurVertex))? V2 : V1;
-                Edges.Remove(itl);
-                break;
-              }
-          }
-      Contours.Bind(StartVertex, aContour);
-    }
-}
 
 //=======================================================================
 //function : BRepOffset_MakeOffset
 //purpose  : 
 //=======================================================================
-
 BRepOffset_MakeOffset::BRepOffset_MakeOffset()
 {
   myAsDes = new BRepAlgo_AsDes();
 }
 
-
 //=======================================================================
 //function : BRepOffset_MakeOffset
 //purpose  : 
 //=======================================================================
-
 BRepOffset_MakeOffset::BRepOffset_MakeOffset(const TopoDS_Shape&    S, 
                                              const Standard_Real    Offset, 
                                              const Standard_Real    Tol, 
@@ -499,12 +389,10 @@ myDone     (Standard_False)
   MakeOffsetShape();
 }
 
-
 //=======================================================================
 //function : Initialize
 //purpose  : 
 //=======================================================================
-
 void BRepOffset_MakeOffset::Initialize(const TopoDS_Shape&    S, 
                                        const Standard_Real    Offset, 
                                        const Standard_Real    Tol, 
@@ -526,12 +414,10 @@ void BRepOffset_MakeOffset::Initialize(const TopoDS_Shape&    S,
   Clear();
 }
 
-
 //=======================================================================
 //function : Clear
 //purpose  : 
 //=======================================================================
-
 void BRepOffset_MakeOffset::Clear()
 {
   myOffsetShape.Nullify();
@@ -548,7 +434,6 @@ void BRepOffset_MakeOffset::Clear()
 //function : AddFace
 //purpose  : 
 //=======================================================================
-
 void BRepOffset_MakeOffset::AddFace(const TopoDS_Face& F) {
   myFaces.Add(F);    
   //-------------
@@ -563,7 +448,6 @@ void BRepOffset_MakeOffset::AddFace(const TopoDS_Face& F) {
 //function : SetOffsetOnFace
 //purpose  : 
 //=======================================================================
-
 void BRepOffset_MakeOffset::SetOffsetOnFace(const TopoDS_Face&  F, 
                                             const Standard_Real Off)
 {
@@ -572,103 +456,10 @@ void BRepOffset_MakeOffset::SetOffsetOnFace(const TopoDS_Face&  F,
 }
 
 //=======================================================================
-//function : RemoveCorks
+//function : MakeOffsetShape
 //purpose  : 
 //=======================================================================
-
-static void RemoveCorks (TopoDS_Shape&               S,
-                         TopTools_IndexedMapOfShape& Faces)
-{  
-  TopoDS_Compound SS;
-  BRep_Builder    B;
-  B.MakeCompound (SS);
-  //-----------------------------------------------------
-  // Construction of a shape without caps.
-  // and Orientation of caps as in shape S.
-  //-----------------------------------------------------
-  TopExp_Explorer exp(S,TopAbs_FACE);
-  for (; exp.More(); exp.Next()) {
-    const TopoDS_Shape& Cork = exp.Current(); 
-    if (!Faces.Contains(Cork)) {
-      B.Add(SS,Cork);
-    }
-    else {
-      //Faces.Remove (Cork);
-      //begin instead of Remove//
-      TopoDS_Shape LastShape = Faces(Faces.Extent());
-      Faces.RemoveLast();
-      if (Faces.FindIndex(Cork) != 0)
-        Faces.Substitute(Faces.FindIndex(Cork), LastShape);
-      //end instead of Remove  //
-      Faces.Add(Cork); // to reset it with proper orientation.
-    }
-  }
-  S = SS;
-#ifdef DRAW
-  if ( AffichOffC) 
-    DBRep::Set("myInit", SS);
-#endif
-
-}
-
-static Standard_Boolean IsConnectedShell( const TopoDS_Shape& S )
-{  
-  BRepTools_Quilt Glue;
-  Glue.Add( S );
-
-  TopoDS_Shape SS = Glue.Shells();
-  TopExp_Explorer Explo( SS, TopAbs_SHELL );
-  Explo.Next();
-  if (Explo.More())
-    return Standard_False;
-  
-  return Standard_True;
-}
-
-
-//=======================================================================
-//function : MakeList
-//purpose  : 
-//=======================================================================
-
-static void MakeList (TopTools_ListOfShape&             OffsetFaces,
-                      const BRepAlgo_Image&             myInitOffsetFace,
-                      const TopTools_IndexedMapOfShape& myFaces)
-{
-  TopTools_ListIteratorOfListOfShape itLOF(myInitOffsetFace.Roots());
-  for ( ; itLOF.More(); itLOF.Next()) {
-    const TopoDS_Shape& Root = itLOF.Value();
-    if (myInitOffsetFace.HasImage(Root)) {
-      if (!myFaces.Contains(Root)) {
-        OffsetFaces.Append(myInitOffsetFace.Image(Root).First());
-      }
-    }
-  }
-}
-
-//=======================================================================
-//function : EvalMax
-//purpose  : 
-//=======================================================================
-
-static void EvalMax(const TopoDS_Shape& S, Standard_Real& Tol)
-{
-  TopExp_Explorer exp;
-  for (exp.Init(S,TopAbs_VERTEX); exp.More(); exp.Next()) {
-    const TopoDS_Vertex& V    = TopoDS::Vertex(exp.Current());
-    Standard_Real        TolV = BRep_Tool::Tolerance(V); 
-    if (TolV > Tol) Tol = TolV;
-  }
-  //Patch
-  Tol *= 5.;
-}
-
-//=======================================================================
-//function : MakeOffsetShape
-//purpose  : 
-//=======================================================================
-
-void BRepOffset_MakeOffset::MakeOffsetShape()
+void BRepOffset_MakeOffset::MakeOffsetShape()
 {  
   myDone     = Standard_False;
   //------------------------------------------
@@ -769,13 +560,10 @@ void BRepOffset_MakeOffset::MakeOffsetShape()
   myDone = Standard_True;
 }
 
-
-
 //=======================================================================
 //function : MakeThickSolid
 //purpose  : 
 //=======================================================================
-
 void BRepOffset_MakeOffset::MakeThickSolid() 
 {
   //--------------------------------------------------------------
@@ -857,7 +645,6 @@ void BRepOffset_MakeOffset::MakeThickSolid()
 //function : IsDone
 //purpose  : 
 //=======================================================================
-
 Standard_Boolean BRepOffset_MakeOffset::IsDone() const
 {
   return myDone;
@@ -867,7 +654,6 @@ Standard_Boolean BRepOffset_MakeOffset::IsDone() const
 //function : Error
 //purpose  : 
 //=======================================================================
-
 BRepOffset_Error BRepOffset_MakeOffset::Error() const
 {
   return myError;
@@ -877,416 +663,529 @@ BRepOffset_Error BRepOffset_MakeOffset::Error() const
 //function : Shape
 //purpose  : 
 //=======================================================================
-
 const TopoDS_Shape&  BRepOffset_MakeOffset::Shape() const 
 {
   return myOffsetShape;
 }
 
 //=======================================================================
-//function : TrimEdge
-//purpose  : Trim the edge of the largest of descendants in AsDes2d.
-//           Order in AsDes two vertices that have trimmed the edge.
+//function : BuildOffsetByInter
+//purpose  : 
 //=======================================================================
-
-static void TrimEdge (TopoDS_Edge&                  NE,
-                      const Handle(BRepAlgo_AsDes)& AsDes2d,
-                            Handle(BRepAlgo_AsDes)& AsDes)
+void BRepOffset_MakeOffset::BuildOffsetByInter()
 {
-  Standard_Real aSameParTol = Precision::Confusion();
-  
-  TopoDS_Vertex V1,V2;
-  Standard_Real U = 0.;
-  Standard_Real UMin =  Precision::Infinite();
-  Standard_Real UMax = -UMin;
-
-  const TopTools_ListOfShape& LE = AsDes2d->Descendant(NE);
-  //
-  Standard_Boolean bTrim = Standard_False;
-  //
-  if (LE.Extent() > 1) {
-    TopTools_ListIteratorOfListOfShape it (LE);
-    for (; it.More(); it.Next()) {
-      TopoDS_Vertex V = TopoDS::Vertex(it.Value());
-      if (NE.Orientation() == TopAbs_REVERSED)
-        V.Reverse();
-      //V.Orientation(TopAbs_INTERNAL);
-      if (!FindParameter(V, NE, U)) {
-        Standard_Real f, l;
-        Handle(Geom_Curve) theCurve = BRep_Tool::Curve(NE, f, l);
-        gp_Pnt thePoint = BRep_Tool::Pnt(V);
-        GeomAPI_ProjectPointOnCurve Projector(thePoint, theCurve);
-        if (Projector.NbPoints() == 0)
-          Standard_ConstructionError::Raise("BRepOffset_MakeOffset::TrimEdge no projection");
-        U = Projector.LowerDistanceParameter();
-      }
-      if (U < UMin) {
-        UMin = U; V1   = V;
-      }
-      if (U > UMax) {
-        UMax = U; V2   = V;
-      }
-    }
-    //
-    if (V1.IsNull() || V2.IsNull()) {
-      Standard_ConstructionError::Raise("BRepOffset_MakeOffset::TrimEdge");
-    }
-    if (!V1.IsSame(V2)) {
-      NE.Free( Standard_True );
-      BRep_Builder B;
-      TopAbs_Orientation Or = NE.Orientation();
-      NE.Orientation(TopAbs_FORWARD);
-      TopoDS_Vertex VF,VL;
-      TopExp::Vertices (NE,VF,VL);
-      B.Remove(NE,VF);
-      B.Remove(NE,VL);
-      B.Add  (NE,V1.Oriented(TopAbs_FORWARD));
-      B.Add  (NE,V2.Oriented(TopAbs_REVERSED));
-      B.Range(NE,UMin,UMax);
-      NE.Orientation(Or);
-      AsDes->Add(NE,V1.Oriented(TopAbs_FORWARD));
-      AsDes->Add(NE,V2.Oriented(TopAbs_REVERSED));
-      BRepLib::SameParameter(NE, aSameParTol, Standard_True);
-      //
-      bTrim = Standard_True;
-    }
+#ifdef OCCT_DEBUG
+  if ( ChronBuild) {
+    cout << " CONSTRUCTION OF OFFSETS :" << endl;
+    Clock.Reset();
+    Clock.Start();
   }
-  //
-  if (!bTrim) {
-    if (!BRep_Tool::Degenerated(NE)) {
-      BRepAdaptor_Curve aBAC(NE);
-      if (!aBAC.IsClosed()) {
-        if (AsDes->HasAscendant(NE)) {
-          AsDes->Remove(NE);
+#endif
+
+  BRepOffset_DataMapOfShapeOffset MapSF;
+  TopTools_MapOfShape             Done;
+  Standard_Boolean OffsetOutside = (myOffset > 0.)? Standard_True : Standard_False;
+  //--------------------------------------------------------
+  // Construction of faces parallel to initial faces
+  //--------------------------------------------------------
+  TopExp_Explorer Exp;
+  TopTools_ListOfShape LF;
+  TopTools_ListIteratorOfListOfShape itLF;
+
+  BRepLib::SortFaces(myShape,LF);
+
+  TopTools_DataMapOfShapeShape ShapeTgt;
+  for (itLF.Initialize(LF); itLF.More(); itLF.Next()) {
+    const TopoDS_Face&   F = TopoDS::Face(itLF.Value());
+    Standard_Real CurOffset = myOffset;
+    if (myFaceOffset.IsBound(F)) CurOffset = myFaceOffset(F);
+    BRepOffset_Offset    OF(F,CurOffset,ShapeTgt,OffsetOutside,myJoin);
+    TopTools_ListOfShape Let;
+    myAnalyse.Edges(F,BRepOffset_Tangent,Let);
+    TopTools_ListIteratorOfListOfShape itl(Let);
+    
+    for ( ; itl.More(); itl.Next()) {
+      const TopoDS_Edge& Cur = TopoDS::Edge(itl.Value());
+      if ( !ShapeTgt.IsBound(Cur)) {
+        TopoDS_Shape aLocalShape = OF.Generated(Cur);
+        const TopoDS_Edge& OTE = TopoDS::Edge(aLocalShape);
+//        const TopoDS_Edge& OTE = TopoDS::Edge(OF.Generated(Cur));
+        ShapeTgt.Bind(Cur,OF.Generated(Cur));
+        TopoDS_Vertex V1,V2,OV1,OV2;
+        TopExp::Vertices (Cur,V1,V2);
+        TopExp::Vertices (OTE,OV1,OV2);      
+        TopTools_ListOfShape LE;
+        if (!ShapeTgt.IsBound(V1)) {
+          myAnalyse.Edges(V1,BRepOffset_Tangent,LE);
+          const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V1);
+          if (LE.Extent() == LA.Extent())
+            ShapeTgt.Bind(V1,OV1);
+        }
+        if (!ShapeTgt.IsBound(V2)) {
+          LE.Clear();
+          myAnalyse.Edges(V2,BRepOffset_Tangent,LE);
+          const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V2);
+          if (LE.Extent() == LA.Extent())
+            ShapeTgt.Bind(V2,OV2);
         }
       }
     }
+    MapSF.Bind(F,OF);
   }
-}
+  //--------------------------------------------------------------------
+  // MES   : Map of OffsetShape -> Extended Shapes.
+  // Build : Map of Initial SS  -> OffsetShape build by Inter.
+  //                               can be an edge or a compound of edges       
+  //---------------------------------------------------------------------
+  TopTools_DataMapOfShapeShape MES;  
+  TopTools_DataMapOfShapeShape Build; 
+  TopTools_ListOfShape         Failed;
+  TopAbs_State                 Side = TopAbs_IN;  
+  Handle(BRepAlgo_AsDes)       AsDes = new BRepAlgo_AsDes();
 
+  //-------------------------------------------------------------------
+  // Extension of faces and calculation of new edges of intersection.
+  //-------------------------------------------------------------------
+  Standard_Boolean  ExtentContext = 0;
+  if (myOffset > 0) ExtentContext = 1;
 
-#include <BOPCol_ListOfShape.hxx>
-#include <BOPAlgo_Builder.hxx>
-#include <BOPAlgo_MakerVolume.hxx>
-#include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
-#include <BOPTools.hxx>
-#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
-#include <BOPAlgo_PaveFiller.hxx>
-#include <BOPDS_DS.hxx>
-#include <BOPDS_VectorOfInterfVE.hxx>
-#include <BOPCol_DataMapOfShapeShape.hxx>
-#include <BOPTools_AlgoTools3D.hxx>
-#include <IntTools_Context.hxx>
-#include <BOPTools_AlgoTools.hxx>
-#include <CPnts_AbscissaPoint.hxx>
-#include <IntTools_ShrunkRange.hxx>
+  BRepOffset_Inter3d Inter3 (AsDes,Side,myTol);
+  // Intersection between parallel faces
+  Inter3.ConnexIntByInt(myShape,MapSF,myAnalyse,MES,Build,Failed );
+  // Intersection with caps.
+  Inter3.ContextIntByInt(myFaces,ExtentContext,MapSF,myAnalyse,MES,Build,Failed );
 
-//=======================================================================
-//function : SortFaces
-//purpose  : 
-//=======================================================================
-static void SortFaces(const TopTools_ListOfShape& theLIm, 
-                      TopTools_ListOfShape& theLFImages,
-                      const Standard_Boolean bKeepFirst)
-{
-  Standard_Integer bKeep; // 1 - keep; -1 - remove
-  Standard_Boolean bFlag;
-  TopTools_IndexedDataMapOfShapeListOfShape aDMELF;
-  TopTools_ListOfShape aLFKeep, aLFLeft, aLFTmp;
-  TopTools_MapOfShape aMV;
-  TopTools_ListIteratorOfListOfShape aItLF;
-  TopExp_Explorer aExp;
-  //
-  aLFLeft = theLIm;
-  //
-  bKeep = bKeepFirst ? 1 : -1;
-  for (;;) {
-    aLFTmp = aLFLeft;
-    //
-    aLFLeft.Clear();
-    aLFKeep.Clear();
-    aDMELF.Clear();
-    //
-    // map list of images  edge - faces
-    aItLF.Initialize(aLFTmp);
-    for (; aItLF.More(); aItLF.Next()) {
-      const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
-      TopExp::MapShapesAndAncestors(aFIm, TopAbs_EDGE, TopAbs_FACE, aDMELF);
-    }
-    //
-    // find images that have edge attached to only one face
-    aItLF.Initialize(aLFTmp);
-    for (; aItLF.More(); aItLF.Next()) {
-      const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
-      aExp.Init(aFIm, TopAbs_EDGE);
-      for (bFlag = Standard_False; aExp.More(); aExp.Next()) {
-        const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExp.Current();
-        const TopTools_ListOfShape& aLEF = aDMELF.FindFromKey(aE);
-        if (aLEF.Extent() == 1) {
-          TopoDS_Vertex aV1, aV2;
-          TopExp::Vertices(aE, aV1, aV2);
-          aMV.Add(aV1);
-          aMV.Add(aV2);
-          //
-          bFlag = Standard_True;
-        }
-      }
-      //
-      if (bFlag) {
-        aLFKeep.Append(aFIm);
-      }
-      else {
-        aLFLeft.Append(aFIm);
-      }
+
+  //---------------------------------------------------------------------------------
+  // Extension of neighbor edges of new edges and intersection between neighbors.
+  //--------------------------------------------------------------------------------
+  Handle(BRepAlgo_AsDes) AsDes2d = new BRepAlgo_AsDes();
+  for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
+    const TopoDS_Face& FI = TopoDS::Face(Exp.Current());
+//  Modified by skv - Mon Jan 12 11:50:02 2004 OCC4455 Begin
+//    BRepOffset_Inter2d::ConnexIntByInt (FI,MapSF(FI),MES,Build,AsDes2d,myTol);
+    BRepOffset_Inter2d::ConnexIntByInt (FI,MapSF(FI),MES,Build,AsDes,AsDes2d,myOffset, myTol);
+//  Modified by skv - Mon Jan 12 11:50:03 2004 OCC4455 End
+  }
+  //-----------------------------------------------------------
+  // Great restriction of new edges and update of AsDes.
+  //------------------------------------------ ----------------
+  TopTools_IndexedMapOfShape NewEdges;
+  TopExp_Explorer Exp2,ExpC;
+  TopoDS_Shape    NE;
+  TopoDS_Edge     TNE;
+  TopoDS_Face     NF;
+  TopTools_IndexedDataMapOfShapeListOfShape anOrigins;
+  
+  for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
+    const TopoDS_Face& FI = TopoDS::Face(Exp.Current());
+    NF = MapSF(FI).Face();
+    if (MES.IsBound(NF)) {
+      NF = TopoDS::Face(MES(NF));
     }
     //
-    // map shapes left for processing
-    aDMELF.Clear();
-    aLFTmp = aLFLeft;
-    aLFLeft.Clear();
+    TopTools_MapOfShape View;
+    TopTools_IndexedMapOfShape VEmap;
+    Standard_Integer i, aNb;
     //
-    aItLF.Initialize(aLFTmp);
-    for (; aItLF.More(); aItLF.Next()) {
-      const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
-      TopExp::MapShapesAndAncestors(aFIm, TopAbs_EDGE, TopAbs_FACE, aDMELF);
-    }
+    TopExp::MapShapes(FI.Oriented(TopAbs_FORWARD), TopAbs_EDGE  , VEmap);
+    TopExp::MapShapes(FI.Oriented(TopAbs_FORWARD), TopAbs_VERTEX, VEmap);
     //
-    // find outer edges and check if they touch the first part of edges
-    aItLF.Initialize(aLFTmp);
-    for (; aItLF.More(); aItLF.Next()) {
-      const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
-      aExp.Init(aFIm, TopAbs_EDGE);
-      for (bFlag = Standard_False; aExp.More() && !bFlag; aExp.Next()) {
-        const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExp.Current();
-        const TopTools_ListOfShape& aLEF = aDMELF.FindFromKey(aE);
-        if (aLEF.Extent() == 1) {
-          TopoDS_Vertex aV1, aV2;
-          TopExp::Vertices(aE, aV1, aV2);
+    aNb = VEmap.Extent();
+    for (i = 1; i <= aNb; ++i) {
+      const TopoDS_Shape& aS = VEmap(i);
+      if (!View.Add(aS)) {
+        continue;
+      }
+      //
+      if (Build.IsBound(aS)) {
+        NE = Build(aS);
+        if (NE.ShapeType() == TopAbs_EDGE) {
+          if (anOrigins.Contains(NE)) {
+            anOrigins.ChangeFromKey(NE).Append(aS);
+          }
+          else {
+            TopTools_ListOfShape aLSx;
+            aLSx.Append(aS);
+            anOrigins.Add(NE, aLSx);
+          }
           //
-          bFlag = aMV.Contains(aV1) || aMV.Contains(aV2);
+          if (NewEdges.Add(NE)) {
+            TrimEdge (TopoDS::Edge(NE),AsDes2d,AsDes);
+          }
+        }
+        else {
+          //------------------------------------------------------------
+          // The Intersections are on several edges.
+          // The pieces without intersections with neighbors  
+          // are removed from AsDes.
+          //------------------------------------------------------------
+          for (ExpC.Init(NE,TopAbs_EDGE); ExpC.More(); ExpC.Next()) {
+            TopoDS_Edge NEC = TopoDS::Edge(ExpC.Current());
+            if (NewEdges.Add(NEC)) {
+              NEC.Free(Standard_True);
+              if (anOrigins.Contains(NEC)) {
+                anOrigins.ChangeFromKey(NEC).Append(aS);
+              }
+              else {
+                TopTools_ListOfShape aLSx;
+                aLSx.Append(aS);
+                anOrigins.Add(NEC, aLSx);
+              }
+              //
+              if (!AsDes2d->Descendant(NEC).IsEmpty()) {
+                TrimEdge (NEC,AsDes2d,AsDes);
+              }
+              else {
+                if (AsDes->HasAscendant(NEC)) {
+                  AsDes->Remove(NEC);
+                }
+              }
+            }
+          }
         }
       }
+      else {
+        if (aS.ShapeType() != TopAbs_EDGE) {
+          continue;
+        }
+        //
+        NE = MapSF(FI).Generated(aS);
+        //// modified by jgv, 19.12.03 for OCC4455 ////
+        NE.Orientation(aS.Orientation());
+        if (anOrigins.Contains(NE)) {
+          anOrigins.ChangeFromKey(NE).Append(aS);
+        }
+        else {
+          TopTools_ListOfShape aLSx;
+          aLSx.Append(aS);
+          anOrigins.Add(NE, aLSx);
+        }
+        //
+        if (MES.IsBound(NE)) {
+          NE = MES(NE);
+          NE.Orientation(aS.Orientation());
+          if (NewEdges.Add(NE)) {TrimEdge (TopoDS::Edge(NE),AsDes2d,AsDes);} 
+        }
+        AsDes->Add(NF,NE);
+      } 
+    }
+  }
+  
+  //--------------------------------- 
+  // Intersection 2D on //
+  //---------------------------------  
+  TopTools_ListOfShape LFE; 
+  BRepAlgo_Image     IMOE;
+  for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
+    const TopoDS_Shape& FI  = Exp.Current();
+    const TopoDS_Shape& OFI = MapSF(FI).Face();
+    if (MES.IsBound(OFI)) {
+      const TopoDS_Face& NF = TopoDS::Face(MES(OFI));
+      LFE.Append(NF);
+      IMOE.SetRoot(NF);
       //
-      if (bFlag) {
-        aLFKeep.Append(aFIm);
+      if (anOrigins.Contains(NF)) {
+        anOrigins.ChangeFromKey(NF).Append(FI);
       }
       else {
-        aLFLeft.Append(aFIm);
-      }
-    }
-    //
-    if (bKeep == 1) {
-      // aLFKeep should be kept
-      // aLFLeft left for further processing
-      aItLF.Initialize(aLFKeep);
-      for (; aItLF.More(); aItLF.Next()) {
-        const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
-        theLFImages.Append(aFIm);
+        TopTools_ListOfShape aLSx;
+        aLSx.Append(FI);
+        anOrigins.Add(NF, aLSx);
       }
     }
-    //
-    if (aLFLeft.IsEmpty()) {
-      break;
-    }
-    //
-    bKeep *= -1;
   }
-}
-
-//=======================================================================
-//function : FindShape
-//purpose  : 
-//=======================================================================
-static Standard_Boolean FindShape(const TopoDS_Shape& theSWhat,
-                                  const TopoDS_Shape& theSWhere,
-                                  TopoDS_Shape& theRes)
-{
-  Standard_Boolean bFound = Standard_False;
-  TopAbs_ShapeEnum aType = theSWhat.ShapeType();
-  TopExp_Explorer aExp(theSWhere, aType);
-  for (; aExp.More(); aExp.Next()) {
-    const TopoDS_Shape& aS = aExp.Current();
-    if (aS.IsSame(theSWhat)) {
-      theRes = aS;
-      bFound = Standard_True;
-      break;
-    }
+  
+  TopTools_ListIteratorOfListOfShape itLFE(LFE);
+  for (; itLFE.More(); itLFE.Next()) {
+    const TopoDS_Face& NEF = TopoDS::Face(itLFE.Value());
+    BRepOffset_Inter2d::Compute(AsDes,NEF,NewEdges,myTol);
+  }
+  //----------------------------------------------
+  // Intersections 2d on caps.
+  //----------------------------------------------
+  Standard_Integer i;
+  for (i = 1; i <= myFaces.Extent(); i++) {
+    const TopoDS_Face& Cork = TopoDS::Face(myFaces(i));
+    BRepOffset_Inter2d::Compute(AsDes,Cork,NewEdges,myTol);
   }
-  return bFound;
-}
 
-//=======================================================================
-//function : ComputeBiNormal
-//purpose  : 
-//=======================================================================
-static Standard_Boolean ComputeBiNormal(const TopoDS_Face& theF,
-                                        const TopoDS_Edge& theE,
-                                        gp_Dir& theDB)
-{
-  Standard_Boolean bDone = Standard_False;
-  Standard_Real aT1, aT2, aTm;
+  //-------------------------------
+  // Unwinding of extended Faces.
+  //-------------------------------
   //
-  const Handle(Geom2d_Curve)& aC2d = 
-    BRep_Tool::CurveOnSurface(theE, theF, aT1, aT2);
-  if (aC2d.IsNull()) {
-    return bDone;
+  if ((myJoin == GeomAbs_Intersection) && myInter) {
+    TopTools_ListOfShape aLFailed;
+    BuildSplitsOfFaces(LFE, AsDes, anOrigins, IMOE, aLFailed, Standard_False);
+    if (aLFailed.Extent()) {
+      myMakeLoops.Build(aLFailed, AsDes, IMOE);
+    }
+  }
+  else {
+    myMakeLoops.Build(LFE, AsDes, IMOE);
   }
   //
-  gp_Pnt2d aP2dNear;
-  gp_Pnt aP, aPNear;
-  //
-  const Handle(Geom_Curve)& aC3d = 
-    BRep_Tool::Curve(theE, aT1, aT2);
-  //
-  aTm = (aT1 + aT2) * 0.5;
-  aP = aC3d->Value(aTm);
-  //
-  BOPTools_AlgoTools3D::PointNearEdge(theE, theF, aTm, 1.e-5, aP2dNear, aPNear);
-  //
-  gp_Vec aVB(aP, aPNear);
-  theDB = gp_Dir(aVB);
-  return !bDone;
-}
-
-//=======================================================================
-//function : UpdateOrigins
-//purpose  : 
-//=======================================================================
-static void UpdateOrigins(TopTools_IndexedDataMapOfShapeListOfShape& theOrigins,
-                          BOPAlgo_Builder& theGF)
-{
-  TopTools_ListOfShape aLSTmp;
-  TopTools_MapOfShape aMFence;
-  BOPCol_ListIteratorOfListOfShape aItA;
-  TopTools_ListIteratorOfListOfShape aIt, aIt1;
-  //
-  const BOPCol_ListOfShape& aLSU = theGF.Arguments();
-  aItA.Initialize(aLSU);
-  for (; aItA.More(); aItA.Next()) {
-    const TopoDS_Shape& aS = aItA.Value();
-    //
-    if (!theOrigins.Contains(aS)) {
-      continue;
-    }
-    //
-    const TopTools_ListOfShape& aLSIm = theGF.Modified(aS);
-    if (aLSIm.IsEmpty()) {
-      continue;
-    }
-    //
-    const TopTools_ListOfShape& aLS = theOrigins.FindFromKey(aS);
-    //      
-    aIt.Initialize(aLSIm);
-    for (; aIt.More(); aIt.Next()) {
-      const TopoDS_Shape& aSIm = aIt.Value();
-      //
-      if (!theOrigins.Contains(aSIm)) {
-        theOrigins.Add(aSIm, aLS);
-        continue;
-      }
-      //
-      aMFence.Clear();
-      //
-      TopTools_ListOfShape& aLS1 = theOrigins.ChangeFromKey(aSIm);
-      aLSTmp.Assign(aLS1);
-      //
-      aLS1.Clear();
-      aIt1.Initialize(aLSTmp);
-      for (; aIt1.More(); aIt1.Next()) {
-        const TopoDS_Shape& aS1 = aIt1.Value();
-        if (aMFence.Add(aS1)) {
-          aLS1.Append(aS1);
+#ifdef OCCT_DEBUG
+  TopTools_IndexedMapOfShape COES;
+#endif
+  //---------------------------
+  // MAJ SD. for faces //
+  //---------------------------
+  for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
+    const TopoDS_Shape& FI   = Exp.Current();
+    myInitOffsetFace.SetRoot(FI);
+    TopoDS_Face  OF  = MapSF(FI).Face();
+    if (MES.IsBound(OF)) {
+      OF = TopoDS::Face(MES(OF));
+      if (IMOE.HasImage(OF)) {
+        const TopTools_ListOfShape& LOFE = IMOE.Image(OF);
+        myInitOffsetFace.Bind(FI,LOFE);
+        for (itLF.Initialize(LOFE); itLF.More(); itLF.Next()) {
+          const TopoDS_Shape& OFE =  itLF.Value();
+          myImageOffset.SetRoot(OFE);
+#ifdef DRAW
+          if (AffichInt2d) {
+            sprintf(name,"AF_%d",NbAF++);
+            DBRep::Set(name,OFE);
+          }
+#endif
+          TopTools_MapOfShape View;
+          for (Exp2.Init(OFE.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
+               Exp2.More(); Exp2.Next()) {
+            const TopoDS_Edge& COE = TopoDS::Edge(Exp2.Current());
+            
+            myAsDes->Add (OFE,COE);
+#ifdef DRAW
+            if (AffichInt2d) {
+              sprintf(name,"AE_%d",NbAE++);
+              DBRep::Set(name,COE);
+              COES.Add(COE);
+            }
+#endif
+            if (View.Add(COE)){
+              if (!myAsDes->HasDescendant(COE)) {
+                TopoDS_Vertex CV1,CV2;
+                TopExp::Vertices(COE,CV1,CV2);
+                if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
+                if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));        
+              }
+            }
+          }
         }
       }
-      //
-      aIt1.Initialize(aLS);
-      for (; aIt1.More(); aIt1.Next()) {
-        const TopoDS_Shape& aS1 = aIt1.Value();
-        if (aMFence.Add(aS1)) {
-          aLS1.Append(aS1);
+      else {
+        /*myInitOffsetFace.Bind(FI,OF);
+        myImageOffset.SetRoot(OF);
+#ifdef DRAW 
+        if (AffichInt2d) {
+          sprintf(name,"AF_%d",NbAF++);
+          DBRep::Set(name,OF);
         }
+#endif
+        const TopTools_ListOfShape& LE = AsDes->Descendant(OF);
+        for (itLF.Initialize(LE) ; itLF.More(); itLF.Next()) {
+          const TopoDS_Edge& OE = TopoDS::Edge(itLF.Value());
+          if (IMOE.HasImage(OE)) {
+            const TopTools_ListOfShape& LOE = IMOE.Image(OE);
+            TopTools_ListIteratorOfListOfShape itLOE(LOE);
+            for (; itLOE.More(); itLOE.Next()) {
+              TopoDS_Shape aLocalShape = itLOE.Value().Oriented(OE.Orientation());
+              const TopoDS_Edge& COE = TopoDS::Edge(aLocalShape);
+//              const TopoDS_Edge& COE = TopoDS::Edge(itLOE.Value().Oriented(OE.Orientation()));
+              myAsDes->Add(OF,COE);
+#ifdef DRAW
+              if (AffichInt2d) {
+                sprintf(name,"AE_%d",NbAE++);
+                DBRep::Set(name,COE);
+                COES.Add(COE);
+              }
+#endif
+              
+              if (!myAsDes->HasDescendant(COE)) {
+                TopoDS_Vertex CV1,CV2;
+                TopExp::Vertices(COE,CV1,CV2);
+                 if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
+                if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));        
+              }
+            }
+          }
+          else {
+            myAsDes->Add(OF,OE);
+#ifdef DRAW
+            if (AffichInt2d) {
+              sprintf(name,"AE_%d",NbAE++);
+              DBRep::Set(name,OE);
+              COES.Add(OE);
+            }
+#endif
+
+            const TopTools_ListOfShape& LV = AsDes->Descendant(OE);
+            myAsDes->Add(OE,LV);
+          }
+        }*/
       }
     }
-  }
-}
+    else {
+      myInitOffsetFace.Bind(FI,OF);
+      myImageOffset.SetRoot(OF);
+      TopTools_MapOfShape View;
+      for (Exp2.Init(OF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
+           Exp2.More(); Exp2.Next()) {
 
-//=======================================================================
-//function : IsMicroEdge
-//purpose  : 
-//=======================================================================
-static Standard_Boolean IsMicroEdge (const TopoDS_Edge& theEdge,
-                                     const Handle(IntTools_Context)& theCtx,
-                                     Standard_Real& theFuzz)
-{
-  TopoDS_Vertex aV1, aV2;
-  TopExp::Vertices(theEdge, aV1, aV2);
-  Standard_Boolean bNull = aV1.IsNull() || aV2.IsNull();
-  if (bNull) {
-    return Standard_False;
-  }
-  //
-  Standard_Boolean bMicro;
-  Standard_Real aT1, aT2;
-  IntTools_ShrunkRange aSR;
-  //
-  BRepAdaptor_Curve aBAC(theEdge);
-  //
-  aT1 = BRep_Tool::Parameter(aV1, theEdge);
-  aT2 = BRep_Tool::Parameter(aV2, theEdge);
-  if (aT2 < aT1) {
-    Standard_Real aTmp = aT1;
-    aT1 = aT2;
-    aT2 = aTmp;
-  }
-  //
-  aSR.SetContext(theCtx);
-  aSR.SetData(theEdge, aT1, aT2, aV1, aV2);
-  aSR.Perform();
-  bMicro = (aSR.ErrorStatus() != 0);
-  if (!bMicro) {
-    Standard_Real anEps, aTS1, aTS2, aTolV1, aTolV2;
-    //
-    aTolV1 = BRep_Tool::Tolerance(aV1);
-    aTolV2 = BRep_Tool::Tolerance(aV2);
-    //
-    anEps = aBAC.Resolution(aTolV1 + aTolV2);
-    if (anEps < 1.e-8) {
-      anEps = 1.e-8;
-    }
-    //
-    aSR.ShrunkRange(aTS1, aTS2);
-    bMicro = (aTS2 - aTS1) <= anEps;
-  }
-  //
-  if (bMicro) {
-    Standard_Real aLen = CPnts_AbscissaPoint::Length(aBAC);
-    if (aLen > theFuzz) {
-      theFuzz = aLen;
+        const TopoDS_Edge& COE = TopoDS::Edge(Exp2.Current());
+        myAsDes->Add (OF,COE);
+#ifdef DRAW
+        if (AffichInt2d) {
+          sprintf(name,"AE_%d",NbAE++);
+          DBRep::Set(name,COE);
+          COES.Add(COE);
+        }
+#endif
+        
+        if (View.Add(Exp2.Current())) {
+          if (!myAsDes->HasDescendant(COE)) {
+            TopoDS_Vertex CV1,CV2;
+            TopExp::Vertices(COE,CV1,CV2);
+            if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
+            if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));        
+          }
+        }
+      } 
     }
   }
-  //
-  return bMicro;
-}
+  //  Modified by skv - Tue Mar 15 16:20:43 2005
+  // Add methods for supporting history.
+  TopTools_MapOfShape aMapEdges;
 
-//=======================================================================
-//function : BuildSplitsOfFaces
-//purpose  : 
-//=======================================================================
-void BRepOffset_MakeOffset::BuildSplitsOfFaces
-  (const TopTools_ListOfShape& theLF,
-   const Handle(BRepAlgo_AsDes)& theAsDes,
-   TopTools_IndexedDataMapOfShapeListOfShape& theOrigins,
-   BRepAlgo_Image& theImage,
-   TopTools_ListOfShape& theLFailed,
-   const Standard_Boolean bLimited)
-{
-  BOPCol_ListOfShape aLS;
-  BOPCol_ListIteratorOfListOfShape aIt;
-  TopTools_ListIteratorOfListOfShape aItLF, aItLE, aItLE1;
-  TopTools_DataMapOfShapeListOfShape anEImages;
-  BRep_Builder aBB;
-  TopoDS_Compound aFaces;
-  //
+  for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
+    const TopoDS_Shape& aFaceRef = Exp.Current();
+
+    Exp2.Init(aFaceRef.Oriented(TopAbs_FORWARD), TopAbs_EDGE);
+
+    for (; Exp2.More(); Exp2.Next()) {
+      const TopoDS_Shape& anEdgeRef = Exp2.Current();
+
+      if (aMapEdges.Add(anEdgeRef)) {
+        myInitOffsetEdge.SetRoot(anEdgeRef);
+        if (Build.IsBound(anEdgeRef)) {
+          TopoDS_Shape aNewShape = Build(anEdgeRef);
+          
+          if (aNewShape.ShapeType() == TopAbs_EDGE) {
+            if (IMOE.HasImage(aNewShape)) {
+              const TopTools_ListOfShape& aListNewE = IMOE.Image(aNewShape);
+              
+              myInitOffsetEdge.Bind (anEdgeRef, aListNewE);
+            } else
+              myInitOffsetEdge.Bind (anEdgeRef, aNewShape);
+          } else { // aNewShape != TopAbs_EDGE
+            TopTools_ListOfShape aListNewEdge;
+            
+            for (ExpC.Init(aNewShape, TopAbs_EDGE); ExpC.More(); ExpC.Next()) {
+              const TopoDS_Shape &aResEdge = ExpC.Current();
+              
+              if (IMOE.HasImage(aResEdge)) {
+                const TopTools_ListOfShape& aListNewE = IMOE.Image(aResEdge);
+                TopTools_ListIteratorOfListOfShape aNewEIter(aListNewE);
+                
+                for (; aNewEIter.More(); aNewEIter.Next())
+                  aListNewEdge.Append(aNewEIter.Value());
+              } else
+                aListNewEdge.Append(aResEdge);
+            }
+            
+            myInitOffsetEdge.Bind (anEdgeRef, aListNewEdge);
+          }
+        } 
+        else { // Free boundary.
+          TopoDS_Shape aNewEdge = MapSF(aFaceRef).Generated(anEdgeRef);
+
+          if (MES.IsBound(aNewEdge))
+            aNewEdge = MES(aNewEdge);
+
+          if (IMOE.HasImage(aNewEdge)) {
+            const TopTools_ListOfShape& aListNewE = IMOE.Image(aNewEdge);
+
+            myInitOffsetEdge.Bind (anEdgeRef, aListNewE);
+          } else
+            myInitOffsetEdge.Bind (anEdgeRef, aNewEdge);
+        }
+      }
+    }
+  }
+//  Modified by skv - Tue Mar 15 16:20:43 2005
+
+  //---------------------------
+  // MAJ SD. for caps 
+  //---------------------------
+  //TopTools_MapOfShape View; 
+  for (i = 1; i <= myFaces.Extent(); i++) {
+    const TopoDS_Shape& Cork = myFaces(i);
+    const TopTools_ListOfShape& LE = AsDes->Descendant(Cork);
+    for (itLF.Initialize(LE) ; itLF.More(); itLF.Next()) {
+      const TopoDS_Edge& OE = TopoDS::Edge(itLF.Value());
+      if (IMOE.HasImage(OE)) {
+        const TopTools_ListOfShape& LOE = IMOE.Image(OE);
+          TopTools_ListIteratorOfListOfShape itLOE(LOE);
+        for (; itLOE.More(); itLOE.Next()) {
+          const TopoDS_Edge& COE = TopoDS::Edge(itLOE.Value());
+          myAsDes->Add(Cork,COE.Oriented(OE.Orientation())) ;
+#ifdef DRAW
+          if (AffichInt2d) {
+            sprintf(name,"AE_%d",NbAE++);
+            DBRep::Set(name,COE);
+            COES.Add(COE);
+          }
+#endif
+          
+          if (!myAsDes->HasDescendant(COE)) {
+            TopoDS_Vertex CV1,CV2;
+            TopExp::Vertices(COE,CV1,CV2);
+            if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
+            if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));          
+          }
+        }
+      }
+      else {
+        myAsDes->Add(Cork,OE);
+        if (AsDes->HasDescendant(OE)) {
+          myAsDes->Add(OE,AsDes->Descendant(OE));
+        }
+#ifdef DRAW
+        if (AffichInt2d) {
+          sprintf(name,"AE_%d",NbAE++);
+          DBRep::Set(name,OE);
+          COES.Add(OE);
+        }
+#endif
+      }
+    }
+  }
+  
+#ifdef OCCT_DEBUG
+  DEBVerticesControl (COES,myAsDes);
+  if ( ChronBuild) Clock.Show();
+#endif
+}
+
+//=======================================================================
+//function : BuildSplitsOfFaces
+//purpose  : 
+//=======================================================================
+void BRepOffset_MakeOffset::BuildSplitsOfFaces
+  (const TopTools_ListOfShape& theLF,
+   const Handle(BRepAlgo_AsDes)& theAsDes,
+   TopTools_IndexedDataMapOfShapeListOfShape& theOrigins,
+   BRepAlgo_Image& theImage,
+   TopTools_ListOfShape& theLFailed,
+   const Standard_Boolean bLimited)
+{
+  BOPCol_ListOfShape aLS;
+  BOPCol_ListIteratorOfListOfShape aIt;
+  TopTools_ListIteratorOfListOfShape aItLF, aItLE, aItLE1;
+  TopTools_DataMapOfShapeListOfShape anEImages;
+  BRep_Builder aBB;
+  TopoDS_Compound aFaces;
+  //
   aBB.MakeCompound(aFaces);
   //
   // firstly it is necessary to fuse all the edges
@@ -1507,129 +1406,38 @@ void BRepOffset_MakeOffset::BuildSplitsOfFaces
         }
       }
       //
-      // check offset faces on the coincidence of the 
-      // bi-normal directions with the original faces
-      //
       UpdateOrigins(theOrigins, aGF);
       //
-      Standard_Real anAngle;
-      Standard_Boolean bRem;
-      TopTools_ListOfShape aLFKeep;
-      //
-      const TopoDS_Face& aFOr = *(TopoDS_Face*)&theOrigins.FindFromKey(aF).First();
-      //
-      aItLE.Initialize(aLFImages);
-      for (; aItLE.More(); ) {
-        const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLE.Value();
-        const TopoDS_Wire& aWIm = BRepTools::OuterWire(aFIm);
+      if (aLFImages.Extent() > 1) {
+        TopTools_ListOfShape aLFKeep;
         //
-        bKeep = Standard_True;
-        bRem = Standard_True;
+        // check offset faces on the coincidence of the 
+        // bi-normal directions with the original faces
+        CheckBiNormals(aLFImages, aF, theOrigins, aLFKeep);
         //
-        TopExp_Explorer aExp(aWIm, TopAbs_EDGE);
-        for (; aExp.More(); aExp.Next()) {
-          const TopoDS_Edge& aEIm = *(TopoDS_Edge*)&aExp.Current();
-          //
-          if (BRep_Tool::Degenerated(aEIm)) {
-            continue;
-          }
-          //
-          if (!theOrigins.Contains(aEIm)) {
-            continue;
-          }
+        // limit the face
+        if (aLFImages.Extent() > 1) {
+          TopTools_ListOfShape aLFTmp = aLFImages;
+          aLFImages.Clear();
           //
-          const TopTools_ListOfShape& aLEOr = theOrigins.FindFromKey(aEIm);
-          const TopoDS_Shape& aSOr = aLEOr.First();
-          if (aSOr.ShapeType() != TopAbs_EDGE) {
-            bRem = Standard_False;
-            break;
+          SortFaces(aLFTmp, aLFImages, Standard_True);
+        }
+        //
+        if (aLFKeep.Extent()) {
+          TopTools_MapOfShape aMFence;
+          aItLE.Initialize(aLFImages);
+          for (; aItLE.More(); aItLE.Next()) {
+            const TopoDS_Shape& aFIm = aItLE.Value();
+            aMFence.Add(aFIm);
           }
           //
-          if (aLEOr.Extent() > 1) {
-            TopTools_MapOfShape aME, aMV;
-            Standard_Integer aNbE, aNbV;
-            //
-            TopTools_ListIteratorOfListOfShape aItLS1(aLEOr);
-            for (; aItLS1.More(); aItLS1.Next()) {
-              const TopoDS_Edge& aEOr = *(TopoDS_Edge*)&aItLS1.Value();
-              aME.Add(aEOr);
-              //
-              TopExp_Explorer aExpE(aEOr, TopAbs_VERTEX);
-              for (; aExpE.More(); aExpE.Next()) {
-                const TopoDS_Shape& aV = aExpE.Current();
-                aMV.Add(aV);
-              }
-            }
-            //
-            aNbV = aMV.Extent();
-            aNbE = aME.Extent();
-            //
-            if ((aNbE > 1) && (aNbV == 2*aNbE)) {
-              continue;
+          aItLE.Initialize(aLFKeep);
+          for (; aItLE.More(); aItLE.Next()) {
+            const TopoDS_Shape& aFIm = aItLE.Value();
+            if (aMFence.Add(aFIm)) {
+              aLFImages.Append(aFIm);
             }
           }
-          //
-          const TopoDS_Shape& aEOr = *(TopoDS_Edge*)&aLEOr.First();
-          TopoDS_Edge aEOrF;
-          if (!FindShape(aEOr, aFOr, aEOrF)) {
-            continue;
-          }
-          //
-          // compute bi-normal for face aFIm on the edge aEIm
-          gp_Dir aDB1;
-          if (!ComputeBiNormal(aFIm, aEIm, aDB1)) {
-            continue;
-          }
-          //
-          // compute bi-normal for face aFOr on the edge aEOrF
-          gp_Dir aDB2;
-          if (!ComputeBiNormal(aFOr, aEOrF, aDB2)) {
-            continue;
-          }
-          //
-          // check coincidence of bi-normals
-          anAngle = aDB1.Angle(aDB2);
-          if (Abs(anAngle - M_PI) < Precision::Confusion()) {
-            bKeep = Standard_False;
-            bRem = bRem && Standard_True;
-          }
-          else {
-            bRem = Standard_False;
-          }
-          //
-          if (!bKeep && !bRem) {
-            break;
-          }
-        }
-        //
-        if (bRem && !bKeep) {
-          aLFImages.Remove(aItLE);
-        }
-        else {
-          if (!bRem && bKeep) {
-            aLFKeep.Append(aFIm);
-          }
-          aItLE.Next();
-        }
-      }
-      //
-      TopTools_ListOfShape aLFTmp = aLFImages;
-      aLFImages.Clear();
-      // limit the face
-      SortFaces(aLFTmp, aLFImages, Standard_True);
-      //
-      TopTools_MapOfShape aMFence;
-      aItLE.Initialize(aLFImages);
-      for (; aItLE.More(); aItLE.Next()) {
-        const TopoDS_Shape& aFIm = aItLE.Value();
-        aMFence.Add(aFIm);
-      }
-      //
-      aItLE.Initialize(aLFKeep);
-      for (; aItLE.More(); aItLE.Next()) {
-        const TopoDS_Shape& aFIm = aItLE.Value();
-        if (aMFence.Add(aFIm)) {
-          aLFImages.Append(aFIm);
         }
       }
     }
@@ -1679,10 +1487,10 @@ void BRepOffset_MakeOffset::BuildSplitsOfFaces
 }
 
 //=======================================================================
-//function : BuildOffsetByInter
+//function : BuildOffsetByArc
 //purpose  : 
 //=======================================================================
-void BRepOffset_MakeOffset::BuildOffsetByInter()
+void BRepOffset_MakeOffset::BuildOffsetByArc()
 {
 #ifdef OCCT_DEBUG
   if ( ChronBuild) {
@@ -1704,734 +1512,231 @@ void BRepOffset_MakeOffset::BuildOffsetByInter()
 
   BRepLib::SortFaces(myShape,LF);
 
-  TopTools_DataMapOfShapeShape ShapeTgt;
+  TopTools_DataMapOfShapeShape EdgeTgt;
   for (itLF.Initialize(LF); itLF.More(); itLF.Next()) {
     const TopoDS_Face&   F = TopoDS::Face(itLF.Value());
     Standard_Real CurOffset = myOffset;
     if (myFaceOffset.IsBound(F)) CurOffset = myFaceOffset(F);
-    BRepOffset_Offset    OF(F,CurOffset,ShapeTgt,OffsetOutside,myJoin);
+    BRepOffset_Offset    OF(F,CurOffset,EdgeTgt,OffsetOutside,myJoin);
     TopTools_ListOfShape Let;
     myAnalyse.Edges(F,BRepOffset_Tangent,Let);
     TopTools_ListIteratorOfListOfShape itl(Let);
     
     for ( ; itl.More(); itl.Next()) {
       const TopoDS_Edge& Cur = TopoDS::Edge(itl.Value());
-      if ( !ShapeTgt.IsBound(Cur)) {
+      if ( !EdgeTgt.IsBound(Cur)) {
         TopoDS_Shape aLocalShape = OF.Generated(Cur);
         const TopoDS_Edge& OTE = TopoDS::Edge(aLocalShape);
 //        const TopoDS_Edge& OTE = TopoDS::Edge(OF.Generated(Cur));
-        ShapeTgt.Bind(Cur,OF.Generated(Cur));
+        EdgeTgt.Bind(Cur,OF.Generated(Cur));
         TopoDS_Vertex V1,V2,OV1,OV2;
         TopExp::Vertices (Cur,V1,V2);
         TopExp::Vertices (OTE,OV1,OV2);      
         TopTools_ListOfShape LE;
-        if (!ShapeTgt.IsBound(V1)) {
+        if (!EdgeTgt.IsBound(V1)) {
           myAnalyse.Edges(V1,BRepOffset_Tangent,LE);
           const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V1);
           if (LE.Extent() == LA.Extent())
-            ShapeTgt.Bind(V1,OV1);
+            EdgeTgt.Bind(V1,OV1);
         }
-        if (!ShapeTgt.IsBound(V2)) {
+        if (!EdgeTgt.IsBound(V2)) {
           LE.Clear();
           myAnalyse.Edges(V2,BRepOffset_Tangent,LE);
           const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V2);
           if (LE.Extent() == LA.Extent())
-            ShapeTgt.Bind(V2,OV2);
+              EdgeTgt.Bind(V2,OV2);
         }
       }
     }
     MapSF.Bind(F,OF);
   }
-  //--------------------------------------------------------------------
-  // MES   : Map of OffsetShape -> Extended Shapes.
-  // Build : Map of Initial SS  -> OffsetShape build by Inter.
-  //                               can be an edge or a compound of edges       
-  //---------------------------------------------------------------------
-  TopTools_DataMapOfShapeShape MES;  
-  TopTools_DataMapOfShapeShape Build; 
-  TopTools_ListOfShape         Failed;
-  TopAbs_State                 Side = TopAbs_IN;  
-  Handle(BRepAlgo_AsDes)       AsDes = new BRepAlgo_AsDes();
-
-  //-------------------------------------------------------------------
-  // Extension of faces and calculation of new edges of intersection.
-  //-------------------------------------------------------------------
-  Standard_Boolean  ExtentContext = 0;
-  if (myOffset > 0) ExtentContext = 1;
-
-  BRepOffset_Inter3d Inter3 (AsDes,Side,myTol);
-  // Intersection between parallel faces
-  Inter3.ConnexIntByInt(myShape,MapSF,myAnalyse,MES,Build,Failed );
-  // Intersection with caps.
-  Inter3.ContextIntByInt(myFaces,ExtentContext,MapSF,myAnalyse,MES,Build,Failed );
-
-
-  //---------------------------------------------------------------------------------
-  // Extension of neighbor edges of new edges and intersection between neighbors.
-  //--------------------------------------------------------------------------------
-  Handle(BRepAlgo_AsDes) AsDes2d = new BRepAlgo_AsDes();
-  for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
-    const TopoDS_Face& FI = TopoDS::Face(Exp.Current());
-//  Modified by skv - Mon Jan 12 11:50:02 2004 OCC4455 Begin
-//    BRepOffset_Inter2d::ConnexIntByInt (FI,MapSF(FI),MES,Build,AsDes2d,myTol);
-    BRepOffset_Inter2d::ConnexIntByInt (FI,MapSF(FI),MES,Build,AsDes,AsDes2d,myOffset, myTol);
-//  Modified by skv - Mon Jan 12 11:50:03 2004 OCC4455 End
-  }
-  //-----------------------------------------------------------
-  // Great restriction of new edges and update of AsDes.
-  //------------------------------------------ ----------------
-  TopTools_IndexedMapOfShape NewEdges;
-  TopExp_Explorer Exp2,ExpC;
-  TopoDS_Shape    NE;
-  TopoDS_Edge     TNE;
-  TopoDS_Face     NF;
-  TopTools_IndexedDataMapOfShapeListOfShape anOrigins;
-  
-  for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
-    const TopoDS_Face& FI = TopoDS::Face(Exp.Current());
-    NF = MapSF(FI).Face();
-    if (MES.IsBound(NF)) {
-      NF = TopoDS::Face(MES(NF));
-    }
-    //
-    TopTools_MapOfShape View;
-    TopTools_IndexedMapOfShape VEmap;
-    Standard_Integer i, aNb;
-    //
-    TopExp::MapShapes(FI.Oriented(TopAbs_FORWARD), TopAbs_EDGE  , VEmap);
-    TopExp::MapShapes(FI.Oriented(TopAbs_FORWARD), TopAbs_VERTEX, VEmap);
-    //
-    aNb = VEmap.Extent();
-    for (i = 1; i <= aNb; ++i) {
-      const TopoDS_Shape& aS = VEmap(i);
-      if (!View.Add(aS)) {
-        continue;
-      }
-      //
-      if (Build.IsBound(aS)) {
-        NE = Build(aS);
-        if (NE.ShapeType() == TopAbs_EDGE) {
-          if (anOrigins.Contains(NE)) {
-            anOrigins.ChangeFromKey(NE).Append(aS);
-          }
-          else {
-            TopTools_ListOfShape aLSx;
-            aLSx.Append(aS);
-            anOrigins.Add(NE, aLSx);
-          }
-          //
-          if (NewEdges.Add(NE)) {
-            TrimEdge (TopoDS::Edge(NE),AsDes2d,AsDes);
+  //--------------------------------------------------------
+  // Construction of tubes on edge.
+  //--------------------------------------------------------
+  BRepOffset_Type    OT = BRepOffset_Convex;
+  if (myOffset < 0.) OT = BRepOffset_Concave; 
+   
+  for (Exp.Init(myShape,TopAbs_EDGE); Exp.More(); Exp.Next()) {
+    const TopoDS_Edge& E = TopoDS::Edge(Exp.Current());
+    if (Done.Add(E)) {
+      const TopTools_ListOfShape& Anc = myAnalyse.Ancestors(E);
+      if (Anc.Extent() == 2) {
+        const BRepOffset_ListOfInterval& L = myAnalyse.Type(E);
+        if (!L.IsEmpty() && L.First().Type() == OT) {
+          Standard_Real CurOffset = myOffset;
+          if ( myFaceOffset.IsBound(Anc.First()))
+            CurOffset = myFaceOffset(Anc.First());
+          TopoDS_Shape aLocalShape = MapSF(Anc.First()).Generated(E);
+          TopoDS_Edge EOn1 = TopoDS::Edge(aLocalShape);
+          aLocalShape = MapSF(Anc.Last()).Generated(E);
+          TopoDS_Edge EOn2 = TopoDS::Edge(aLocalShape);
+//          TopoDS_Edge EOn1 = TopoDS::Edge(MapSF(Anc.First()).Generated(E));
+//          TopoDS_Edge EOn2 = TopoDS::Edge(MapSF(Anc.Last()) .Generated(E));
+          // find if exits tangent edges in the original shape
+          TopoDS_Edge E1f, E1l;
+          TopoDS_Vertex V1f, V1l;
+          TopExp::Vertices(E,V1f,V1l);
+          TopTools_ListOfShape TangE;
+          myAnalyse.TangentEdges(E,V1f,TangE);
+          // find if the pipe on the tangent edges are soon created.
+          TopTools_ListIteratorOfListOfShape itl(TangE);
+          Standard_Boolean Find = Standard_False;
+          for ( ; itl.More() && !Find; itl.Next()) {
+            if ( MapSF.IsBound(itl.Value())) {
+              TopoDS_Shape aLocalShape = MapSF(itl.Value()).Generated(V1f);
+              E1f  = TopoDS::Edge(aLocalShape);
+//              E1f  = TopoDS::Edge(MapSF(itl.Value()).Generated(V1f));
+              Find = Standard_True;
+            }
           }
-        }
-        else {
-          //------------------------------------------------------------
-          // The Intersections are on several edges.
-          // The pieces without intersections with neighbors  
-          // are removed from AsDes.
-          //------------------------------------------------------------
-          for (ExpC.Init(NE,TopAbs_EDGE); ExpC.More(); ExpC.Next()) {
-            TopoDS_Edge NEC = TopoDS::Edge(ExpC.Current());
-            if (NewEdges.Add(NEC)) {
-              NEC.Free(Standard_True);
-              if (anOrigins.Contains(NEC)) {
-                anOrigins.ChangeFromKey(NEC).Append(aS);
-              }
-              else {
-                TopTools_ListOfShape aLSx;
-                aLSx.Append(aS);
-                anOrigins.Add(NEC, aLSx);
-              }
-              //
-              if (!AsDes2d->Descendant(NEC).IsEmpty()) {
-                TrimEdge (NEC,AsDes2d,AsDes);
-              }
-              else {
-                if (AsDes->HasAscendant(NEC)) {
-                  AsDes->Remove(NEC);
-                }
-              }
+          TangE.Clear();
+          myAnalyse.TangentEdges(E,V1l,TangE);
+          // find if the pipe on the tangent edges are soon created.
+          itl.Initialize(TangE);
+          Find = Standard_False;
+          for ( ; itl.More() && !Find; itl.Next()) {
+            if ( MapSF.IsBound(itl.Value())) {
+              TopoDS_Shape aLocalShape = MapSF(itl.Value()).Generated(V1l);
+              E1l  = TopoDS::Edge(aLocalShape);
+//              E1l  = TopoDS::Edge(MapSF(itl.Value()).Generated(V1l));
+              Find = Standard_True;
             }
           }
+          BRepOffset_Offset OF (E,EOn1,EOn2,CurOffset,E1f, E1l);
+          MapSF.Bind(E,OF);
         }
       }
       else {
-        if (aS.ShapeType() != TopAbs_EDGE) {
-          continue;
-        }
-        //
-        NE = MapSF(FI).Generated(aS);
-        //// modified by jgv, 19.12.03 for OCC4455 ////
-        NE.Orientation(aS.Orientation());
-        if (anOrigins.Contains(NE)) {
-          anOrigins.ChangeFromKey(NE).Append(aS);
-        }
-        else {
-          TopTools_ListOfShape aLSx;
-          aLSx.Append(aS);
-          anOrigins.Add(NE, aLSx);
-        }
-        //
-        if (MES.IsBound(NE)) {
-          NE = MES(NE);
-          NE.Orientation(aS.Orientation());
-          if (NewEdges.Add(NE)) {TrimEdge (TopoDS::Edge(NE),AsDes2d,AsDes);} 
-        }
-        AsDes->Add(NF,NE);
-      } 
+        // ----------------------
+        // free border.
+        // ----------------------
+        TopoDS_Shape aLocalShape = MapSF(Anc.First()).Generated(E);
+        TopoDS_Edge EOn1 = TopoDS::Edge(aLocalShape);
+///        TopoDS_Edge EOn1 = TopoDS::Edge(MapSF(Anc.First()).Generated(E));
+        myInitOffsetEdge.SetRoot(E); // skv: supporting history.
+        myInitOffsetEdge.Bind (E,EOn1);      
+      }
     }
   }
-  
-  //--------------------------------- 
-  // Intersection 2D on //
-  //---------------------------------  
-  TopTools_ListOfShape LFE; 
-  BRepAlgo_Image     IMOE;
-  for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
-    const TopoDS_Shape& FI  = Exp.Current();
-    const TopoDS_Shape& OFI = MapSF(FI).Face();
-    if (MES.IsBound(OFI)) {
-      const TopoDS_Face& NF = TopoDS::Face(MES(OFI));
-      LFE.Append(NF);
-      IMOE.SetRoot(NF);
-      //
-      if (anOrigins.Contains(NF)) {
-        anOrigins.ChangeFromKey(NF).Append(FI);
+
+  //--------------------------------------------------------
+  // Construction of spheres on vertex.
+  //--------------------------------------------------------
+  Done.Clear();
+  TopTools_ListIteratorOfListOfShape it;
+
+  for (Exp.Init(myShape,TopAbs_VERTEX); Exp.More(); Exp.Next()) {
+    const TopoDS_Vertex& V = TopoDS::Vertex (Exp.Current());
+    if (Done.Add(V)) {
+      const TopTools_ListOfShape& LA = myAnalyse.Ancestors(V);
+      TopTools_ListOfShape LE;
+      myAnalyse.Edges(V,OT,LE);
+
+      if (LE.Extent() >= 3 && LE.Extent() == LA.Extent()) {
+        TopTools_ListOfShape LOE;
+        //--------------------------------------------------------
+        // Return connected edges on tubes.
+        //--------------------------------------------------------
+        for (it.Initialize(LE) ; it.More(); it.Next()) {
+          LOE.Append(MapSF(it.Value()).Generated(V).Reversed());
+        }
+        //----------------------
+        // construction sphere.
+        //-----------------------
+        const TopTools_ListOfShape& LLA = myAnalyse.Ancestors(LA.First());
+        const TopoDS_Shape& FF = LLA.First();
+        Standard_Real CurOffset = myOffset;
+        if ( myFaceOffset.IsBound(FF))
+          CurOffset = myFaceOffset(FF);
+        
+        BRepOffset_Offset OF(V,LOE,CurOffset);
+        MapSF.Bind(V,OF);
       }
-      else {
-        TopTools_ListOfShape aLSx;
-        aLSx.Append(FI);
-        anOrigins.Add(NF, aLSx);
+      //--------------------------------------------------------------
+      // Particular processing if V is at least a free border.
+      //-------------------------------------------------------------
+      TopTools_ListOfShape LBF;
+      myAnalyse.Edges(V,BRepOffset_FreeBoundary,LBF);
+      if (!LBF.IsEmpty()) {        
+        Standard_Boolean First = Standard_True;
+        for (it.Initialize(LE) ; it.More(); it.Next()) {
+          if (First) {
+            myInitOffsetEdge.SetRoot(V); // skv: supporting history.
+            myInitOffsetEdge.Bind(V,MapSF(it.Value()).Generated(V));
+            First = Standard_False;
+          }
+          else {
+            myInitOffsetEdge.Add(V,MapSF(it.Value()).Generated(V));
+          }
+        } 
       }
     }
   }
-  
-  TopTools_ListIteratorOfListOfShape itLFE(LFE);
-  for (; itLFE.More(); itLFE.Next()) {
-    const TopoDS_Face& NEF = TopoDS::Face(itLFE.Value());
-    BRepOffset_Inter2d::Compute(AsDes,NEF,NewEdges,myTol);
-  }
-  //----------------------------------------------
-  // Intersections 2d on caps.
-  //----------------------------------------------
-  Standard_Integer i;
-  for (i = 1; i <= myFaces.Extent(); i++) {
-    const TopoDS_Face& Cork = TopoDS::Face(myFaces(i));
-    BRepOffset_Inter2d::Compute(AsDes,Cork,NewEdges,myTol);
-  }
 
-  //-------------------------------
-  // Unwinding of extended Faces.
-  //-------------------------------
-  //
-  if ((myJoin == GeomAbs_Intersection) && myInter) {
-    TopTools_ListOfShape aLFailed;
-    BuildSplitsOfFaces(LFE, AsDes, anOrigins, IMOE, aLFailed, Standard_False);
-    if (aLFailed.Extent()) {
-      myMakeLoops.Build(aLFailed, AsDes, IMOE);
-    }
-  }
-  else {
-    myMakeLoops.Build(LFE, AsDes, IMOE);
-  }
-  //
-#ifdef OCCT_DEBUG
-  TopTools_IndexedMapOfShape COES;
-#endif
-  //---------------------------
-  // MAJ SD. for faces //
-  //---------------------------
-  for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
-    const TopoDS_Shape& FI   = Exp.Current();
-    myInitOffsetFace.SetRoot(FI);
-    TopoDS_Face  OF  = MapSF(FI).Face();
-    if (MES.IsBound(OF)) {
-      OF = TopoDS::Face(MES(OF));
-      if (IMOE.HasImage(OF)) {
-        const TopTools_ListOfShape& LOFE = IMOE.Image(OF);
-        myInitOffsetFace.Bind(FI,LOFE);
-        for (itLF.Initialize(LOFE); itLF.More(); itLF.Next()) {
-          const TopoDS_Shape& OFE =  itLF.Value();
-          myImageOffset.SetRoot(OFE);
-#ifdef DRAW
-          if (AffichInt2d) {
-            sprintf(name,"AF_%d",NbAF++);
-            DBRep::Set(name,OFE);
-          }
-#endif
-          TopTools_MapOfShape View;
-          for (Exp2.Init(OFE.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
-               Exp2.More(); Exp2.Next()) {
-            const TopoDS_Edge& COE = TopoDS::Edge(Exp2.Current());
-            
-            myAsDes->Add (OFE,COE);
-#ifdef DRAW
-            if (AffichInt2d) {
-              sprintf(name,"AE_%d",NbAE++);
-              DBRep::Set(name,COE);
-              COES.Add(COE);
-            }
-#endif
-            if (View.Add(COE)){
-              if (!myAsDes->HasDescendant(COE)) {
-                TopoDS_Vertex CV1,CV2;
-                TopExp::Vertices(COE,CV1,CV2);
-                if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
-                if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));        
-              }
-            }
-          }
-        }
-      }
-      else {
-        /*myInitOffsetFace.Bind(FI,OF);
-        myImageOffset.SetRoot(OF);
-#ifdef DRAW 
-        if (AffichInt2d) {
-          sprintf(name,"AF_%d",NbAF++);
-          DBRep::Set(name,OF);
-        }
-#endif
-        const TopTools_ListOfShape& LE = AsDes->Descendant(OF);
-        for (itLF.Initialize(LE) ; itLF.More(); itLF.Next()) {
-          const TopoDS_Edge& OE = TopoDS::Edge(itLF.Value());
-          if (IMOE.HasImage(OE)) {
-            const TopTools_ListOfShape& LOE = IMOE.Image(OE);
-            TopTools_ListIteratorOfListOfShape itLOE(LOE);
-            for (; itLOE.More(); itLOE.Next()) {
-              TopoDS_Shape aLocalShape = itLOE.Value().Oriented(OE.Orientation());
-              const TopoDS_Edge& COE = TopoDS::Edge(aLocalShape);
-//              const TopoDS_Edge& COE = TopoDS::Edge(itLOE.Value().Oriented(OE.Orientation()));
-              myAsDes->Add(OF,COE);
-#ifdef DRAW
-              if (AffichInt2d) {
-                sprintf(name,"AE_%d",NbAE++);
-                DBRep::Set(name,COE);
-                COES.Add(COE);
-              }
-#endif
-              
-              if (!myAsDes->HasDescendant(COE)) {
-                TopoDS_Vertex CV1,CV2;
-                TopExp::Vertices(COE,CV1,CV2);
-                 if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
-                if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));        
-              }
-            }
-          }
-          else {
-            myAsDes->Add(OF,OE);
-#ifdef DRAW
-            if (AffichInt2d) {
-              sprintf(name,"AE_%d",NbAE++);
-              DBRep::Set(name,OE);
-              COES.Add(OE);
-            }
-#endif
-
-            const TopTools_ListOfShape& LV = AsDes->Descendant(OE);
-            myAsDes->Add(OE,LV);
-          }
-        }*/
-      }
-    }
-    else {
-      myInitOffsetFace.Bind(FI,OF);
-      myImageOffset.SetRoot(OF);
-      TopTools_MapOfShape View;
-      for (Exp2.Init(OF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
-           Exp2.More(); Exp2.Next()) {
-
-        const TopoDS_Edge& COE = TopoDS::Edge(Exp2.Current());
-        myAsDes->Add (OF,COE);
-#ifdef DRAW
-        if (AffichInt2d) {
-          sprintf(name,"AE_%d",NbAE++);
-          DBRep::Set(name,COE);
-          COES.Add(COE);
-        }
-#endif
-        
-        if (View.Add(Exp2.Current())) {
-          if (!myAsDes->HasDescendant(COE)) {
-            TopoDS_Vertex CV1,CV2;
-            TopExp::Vertices(COE,CV1,CV2);
-            if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
-            if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));        
-          }
-        }
-      } 
-    }
-  }
-  //  Modified by skv - Tue Mar 15 16:20:43 2005
-  // Add methods for supporting history.
-  TopTools_MapOfShape aMapEdges;
-
-  for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
-    const TopoDS_Shape& aFaceRef = Exp.Current();
-
-    Exp2.Init(aFaceRef.Oriented(TopAbs_FORWARD), TopAbs_EDGE);
-
-    for (; Exp2.More(); Exp2.Next()) {
-      const TopoDS_Shape& anEdgeRef = Exp2.Current();
-
-      if (aMapEdges.Add(anEdgeRef)) {
-        myInitOffsetEdge.SetRoot(anEdgeRef);
-        if (Build.IsBound(anEdgeRef)) {
-          TopoDS_Shape aNewShape = Build(anEdgeRef);
-          
-          if (aNewShape.ShapeType() == TopAbs_EDGE) {
-            if (IMOE.HasImage(aNewShape)) {
-              const TopTools_ListOfShape& aListNewE = IMOE.Image(aNewShape);
-              
-              myInitOffsetEdge.Bind (anEdgeRef, aListNewE);
-            } else
-              myInitOffsetEdge.Bind (anEdgeRef, aNewShape);
-          } else { // aNewShape != TopAbs_EDGE
-            TopTools_ListOfShape aListNewEdge;
-            
-            for (ExpC.Init(aNewShape, TopAbs_EDGE); ExpC.More(); ExpC.Next()) {
-              const TopoDS_Shape &aResEdge = ExpC.Current();
-              
-              if (IMOE.HasImage(aResEdge)) {
-                const TopTools_ListOfShape& aListNewE = IMOE.Image(aResEdge);
-                TopTools_ListIteratorOfListOfShape aNewEIter(aListNewE);
-                
-                for (; aNewEIter.More(); aNewEIter.Next())
-                  aListNewEdge.Append(aNewEIter.Value());
-              } else
-                aListNewEdge.Append(aResEdge);
-            }
-            
-            myInitOffsetEdge.Bind (anEdgeRef, aListNewEdge);
-          }
-        } 
-        else { // Free boundary.
-          TopoDS_Shape aNewEdge = MapSF(aFaceRef).Generated(anEdgeRef);
-
-          if (MES.IsBound(aNewEdge))
-            aNewEdge = MES(aNewEdge);
+  //------------------------------------------------------------
+  // Extension of parallel faces to the context.
+  // Extended faces are ordered in DS and removed from MapSF.
+  //------------------------------------------------------------
+  if (!myFaces.IsEmpty()) ToContext (MapSF);
 
-          if (IMOE.HasImage(aNewEdge)) {
-            const TopTools_ListOfShape& aListNewE = IMOE.Image(aNewEdge);
+  //------------------------------------------------------
+  // MAJ SD.
+  //------------------------------------------------------
+  BRepOffset_Type    RT = BRepOffset_Concave;
+  if (myOffset < 0.) RT = BRepOffset_Convex;
+  BRepOffset_DataMapIteratorOfDataMapOfShapeOffset It(MapSF);
+  for ( ; It.More(); It.Next()) {
+    const TopoDS_Shape& SI = It.Key(); 
+    const BRepOffset_Offset& SF = It.Value();
+    if (SF.Status() == BRepOffset_Reversed ||
+        SF.Status() == BRepOffset_Degenerated ) {
+      //------------------------------------------------
+      // Degenerated or returned faces are not stored.
+      //------------------------------------------------
+      continue; 
+    }        
 
-            myInitOffsetEdge.Bind (anEdgeRef, aListNewE);
-          } else
-            myInitOffsetEdge.Bind (anEdgeRef, aNewEdge);
+    const TopoDS_Face&  OF = It.Value().Face();
+    myInitOffsetFace.Bind    (SI,OF);      
+    myInitOffsetFace.SetRoot (SI);      // Initial<-> Offset
+    myImageOffset.SetRoot    (OF);      // FaceOffset root of images
+    
+    if (SI.ShapeType() == TopAbs_FACE) {
+      for (Exp.Init(SI.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
+           Exp.More(); Exp.Next()) {
+        //--------------------------------------------------------------------
+        // To each face are associatedthe edges that restrict that 
+        // The edges that do not generate tubes or are not tangent
+        // to two faces are removed.
+        //--------------------------------------------------------------------
+        const TopoDS_Edge& E = TopoDS::Edge(Exp.Current());
+        const BRepOffset_ListOfInterval& L  = myAnalyse.Type(E);
+        if (!L.IsEmpty() && L.First().Type() != RT) {
+          TopAbs_Orientation OO  = E.Orientation();
+          TopoDS_Shape aLocalShape = It.Value().Generated(E);
+          TopoDS_Edge        OE  = TopoDS::Edge(aLocalShape);
+//          TopoDS_Edge        OE  = TopoDS::Edge(It.Value().Generated(E));
+          myAsDes->Add (OF,OE.Oriented(OO));
         }
       }
     }
-  }
-//  Modified by skv - Tue Mar 15 16:20:43 2005
-
-  //---------------------------
-  // MAJ SD. for caps 
-  //---------------------------
-  //TopTools_MapOfShape View; 
-  for (i = 1; i <= myFaces.Extent(); i++) {
-    const TopoDS_Shape& Cork = myFaces(i);
-    const TopTools_ListOfShape& LE = AsDes->Descendant(Cork);
-    for (itLF.Initialize(LE) ; itLF.More(); itLF.Next()) {
-      const TopoDS_Edge& OE = TopoDS::Edge(itLF.Value());
-      if (IMOE.HasImage(OE)) {
-        const TopTools_ListOfShape& LOE = IMOE.Image(OE);
-          TopTools_ListIteratorOfListOfShape itLOE(LOE);
-        for (; itLOE.More(); itLOE.Next()) {
-          const TopoDS_Edge& COE = TopoDS::Edge(itLOE.Value());
-          myAsDes->Add(Cork,COE.Oriented(OE.Orientation())) ;
-#ifdef DRAW
-          if (AffichInt2d) {
-            sprintf(name,"AE_%d",NbAE++);
-            DBRep::Set(name,COE);
-            COES.Add(COE);
-          }
-#endif
-          
-          if (!myAsDes->HasDescendant(COE)) {
-            TopoDS_Vertex CV1,CV2;
-            TopExp::Vertices(COE,CV1,CV2);
-            if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
-            if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));          
-          }
-        }
-      }
-      else {
-        myAsDes->Add(Cork,OE);
-        if (AsDes->HasDescendant(OE)) {
-          myAsDes->Add(OE,AsDes->Descendant(OE));
-        }
-#ifdef DRAW
-        if (AffichInt2d) {
-          sprintf(name,"AE_%d",NbAE++);
-          DBRep::Set(name,OE);
-          COES.Add(OE);
-        }
-#endif
+    else {
+      for (Exp.Init(OF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
+           Exp.More(); Exp.Next()) {
+        myAsDes->Add (OF,Exp.Current());
       }
     }
   }
-  
+
 #ifdef OCCT_DEBUG
-  DEBVerticesControl (COES,myAsDes);
   if ( ChronBuild) Clock.Show();
 #endif
 }
 
-
 //=======================================================================
-//function : BuildOffsetByArc
+//function : SelfInter
 //purpose  : 
 //=======================================================================
-void BRepOffset_MakeOffset::BuildOffsetByArc()
-{
-#ifdef OCCT_DEBUG
-  if ( ChronBuild) {
-    cout << " CONSTRUCTION OF OFFSETS :" << endl;
-    Clock.Reset();
-    Clock.Start();
-  }
-#endif
-
-  BRepOffset_DataMapOfShapeOffset MapSF;
-  TopTools_MapOfShape             Done;
-  Standard_Boolean OffsetOutside = (myOffset > 0.)? Standard_True : Standard_False;
-  //--------------------------------------------------------
-  // Construction of faces parallel to initial faces
-  //--------------------------------------------------------
-  TopExp_Explorer Exp;
-  TopTools_ListOfShape LF;
-  TopTools_ListIteratorOfListOfShape itLF;
-
-  BRepLib::SortFaces(myShape,LF);
-
-  TopTools_DataMapOfShapeShape EdgeTgt;
-  for (itLF.Initialize(LF); itLF.More(); itLF.Next()) {
-    const TopoDS_Face&   F = TopoDS::Face(itLF.Value());
-    Standard_Real CurOffset = myOffset;
-    if (myFaceOffset.IsBound(F)) CurOffset = myFaceOffset(F);
-    BRepOffset_Offset    OF(F,CurOffset,EdgeTgt,OffsetOutside,myJoin);
-    TopTools_ListOfShape Let;
-    myAnalyse.Edges(F,BRepOffset_Tangent,Let);
-    TopTools_ListIteratorOfListOfShape itl(Let);
-    
-    for ( ; itl.More(); itl.Next()) {
-      const TopoDS_Edge& Cur = TopoDS::Edge(itl.Value());
-      if ( !EdgeTgt.IsBound(Cur)) {
-        TopoDS_Shape aLocalShape = OF.Generated(Cur);
-        const TopoDS_Edge& OTE = TopoDS::Edge(aLocalShape);
-//        const TopoDS_Edge& OTE = TopoDS::Edge(OF.Generated(Cur));
-        EdgeTgt.Bind(Cur,OF.Generated(Cur));
-        TopoDS_Vertex V1,V2,OV1,OV2;
-        TopExp::Vertices (Cur,V1,V2);
-        TopExp::Vertices (OTE,OV1,OV2);      
-        TopTools_ListOfShape LE;
-        if (!EdgeTgt.IsBound(V1)) {
-          myAnalyse.Edges(V1,BRepOffset_Tangent,LE);
-          const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V1);
-          if (LE.Extent() == LA.Extent())
-            EdgeTgt.Bind(V1,OV1);
-        }
-        if (!EdgeTgt.IsBound(V2)) {
-          LE.Clear();
-          myAnalyse.Edges(V2,BRepOffset_Tangent,LE);
-          const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V2);
-          if (LE.Extent() == LA.Extent())
-              EdgeTgt.Bind(V2,OV2);
-        }
-      }
-    }
-    MapSF.Bind(F,OF);
-  }
-  //--------------------------------------------------------
-  // Construction of tubes on edge.
-  //--------------------------------------------------------
-  BRepOffset_Type    OT = BRepOffset_Convex;
-  if (myOffset < 0.) OT = BRepOffset_Concave; 
-   
-  for (Exp.Init(myShape,TopAbs_EDGE); Exp.More(); Exp.Next()) {
-    const TopoDS_Edge& E = TopoDS::Edge(Exp.Current());
-    if (Done.Add(E)) {
-      const TopTools_ListOfShape& Anc = myAnalyse.Ancestors(E);
-      if (Anc.Extent() == 2) {
-        const BRepOffset_ListOfInterval& L = myAnalyse.Type(E);
-        if (!L.IsEmpty() && L.First().Type() == OT) {
-          Standard_Real CurOffset = myOffset;
-          if ( myFaceOffset.IsBound(Anc.First()))
-            CurOffset = myFaceOffset(Anc.First());
-          TopoDS_Shape aLocalShape = MapSF(Anc.First()).Generated(E);
-          TopoDS_Edge EOn1 = TopoDS::Edge(aLocalShape);
-          aLocalShape = MapSF(Anc.Last()).Generated(E);
-          TopoDS_Edge EOn2 = TopoDS::Edge(aLocalShape);
-//          TopoDS_Edge EOn1 = TopoDS::Edge(MapSF(Anc.First()).Generated(E));
-//          TopoDS_Edge EOn2 = TopoDS::Edge(MapSF(Anc.Last()) .Generated(E));
-          // find if exits tangent edges in the original shape
-          TopoDS_Edge E1f, E1l;
-          TopoDS_Vertex V1f, V1l;
-          TopExp::Vertices(E,V1f,V1l);
-          TopTools_ListOfShape TangE;
-          myAnalyse.TangentEdges(E,V1f,TangE);
-          // find if the pipe on the tangent edges are soon created.
-          TopTools_ListIteratorOfListOfShape itl(TangE);
-          Standard_Boolean Find = Standard_False;
-          for ( ; itl.More() && !Find; itl.Next()) {
-            if ( MapSF.IsBound(itl.Value())) {
-              TopoDS_Shape aLocalShape = MapSF(itl.Value()).Generated(V1f);
-              E1f  = TopoDS::Edge(aLocalShape);
-//              E1f  = TopoDS::Edge(MapSF(itl.Value()).Generated(V1f));
-              Find = Standard_True;
-            }
-          }
-          TangE.Clear();
-          myAnalyse.TangentEdges(E,V1l,TangE);
-          // find if the pipe on the tangent edges are soon created.
-          itl.Initialize(TangE);
-          Find = Standard_False;
-          for ( ; itl.More() && !Find; itl.Next()) {
-            if ( MapSF.IsBound(itl.Value())) {
-              TopoDS_Shape aLocalShape = MapSF(itl.Value()).Generated(V1l);
-              E1l  = TopoDS::Edge(aLocalShape);
-//              E1l  = TopoDS::Edge(MapSF(itl.Value()).Generated(V1l));
-              Find = Standard_True;
-            }
-          }
-          BRepOffset_Offset OF (E,EOn1,EOn2,CurOffset,E1f, E1l);
-          MapSF.Bind(E,OF);
-        }
-      }
-      else {
-        // ----------------------
-        // free border.
-        // ----------------------
-        TopoDS_Shape aLocalShape = MapSF(Anc.First()).Generated(E);
-        TopoDS_Edge EOn1 = TopoDS::Edge(aLocalShape);
-///        TopoDS_Edge EOn1 = TopoDS::Edge(MapSF(Anc.First()).Generated(E));
-        myInitOffsetEdge.SetRoot(E); // skv: supporting history.
-        myInitOffsetEdge.Bind (E,EOn1);      
-      }
-    }
-  }
-
-  //--------------------------------------------------------
-  // Construction of spheres on vertex.
-  //--------------------------------------------------------
-  Done.Clear();
-  TopTools_ListIteratorOfListOfShape it;
-
-  for (Exp.Init(myShape,TopAbs_VERTEX); Exp.More(); Exp.Next()) {
-    const TopoDS_Vertex& V = TopoDS::Vertex (Exp.Current());
-    if (Done.Add(V)) {
-      const TopTools_ListOfShape& LA = myAnalyse.Ancestors(V);
-      TopTools_ListOfShape LE;
-      myAnalyse.Edges(V,OT,LE);
-
-      if (LE.Extent() >= 3 && LE.Extent() == LA.Extent()) {
-        TopTools_ListOfShape LOE;
-        //--------------------------------------------------------
-        // Return connected edges on tubes.
-        //--------------------------------------------------------
-        for (it.Initialize(LE) ; it.More(); it.Next()) {
-          LOE.Append(MapSF(it.Value()).Generated(V).Reversed());
-        }
-        //----------------------
-        // construction sphere.
-        //-----------------------
-        const TopTools_ListOfShape& LLA = myAnalyse.Ancestors(LA.First());
-        const TopoDS_Shape& FF = LLA.First();
-        Standard_Real CurOffset = myOffset;
-        if ( myFaceOffset.IsBound(FF))
-          CurOffset = myFaceOffset(FF);
-        
-        BRepOffset_Offset OF(V,LOE,CurOffset);
-        MapSF.Bind(V,OF);
-      }
-      //--------------------------------------------------------------
-      // Particular processing if V is at least a free border.
-      //-------------------------------------------------------------
-      TopTools_ListOfShape LBF;
-      myAnalyse.Edges(V,BRepOffset_FreeBoundary,LBF);
-      if (!LBF.IsEmpty()) {        
-        Standard_Boolean First = Standard_True;
-        for (it.Initialize(LE) ; it.More(); it.Next()) {
-          if (First) {
-            myInitOffsetEdge.SetRoot(V); // skv: supporting history.
-            myInitOffsetEdge.Bind(V,MapSF(it.Value()).Generated(V));
-            First = Standard_False;
-          }
-          else {
-            myInitOffsetEdge.Add(V,MapSF(it.Value()).Generated(V));
-          }
-        } 
-      }
-    }
-  }
-
-  //------------------------------------------------------------
-  // Extension of parallel faces to the context.
-  // Extended faces are ordered in DS and removed from MapSF.
-  //------------------------------------------------------------
-  if (!myFaces.IsEmpty()) ToContext (MapSF);
-
-  //------------------------------------------------------
-  // MAJ SD.
-  //------------------------------------------------------
-  BRepOffset_Type    RT = BRepOffset_Concave;
-  if (myOffset < 0.) RT = BRepOffset_Convex;
-  BRepOffset_DataMapIteratorOfDataMapOfShapeOffset It(MapSF);
-  for ( ; It.More(); It.Next()) {
-    const TopoDS_Shape& SI = It.Key(); 
-    const BRepOffset_Offset& SF = It.Value();
-    if (SF.Status() == BRepOffset_Reversed ||
-        SF.Status() == BRepOffset_Degenerated ) {
-      //------------------------------------------------
-      // Degenerated or returned faces are not stored.
-      //------------------------------------------------
-      continue; 
-    }        
-
-    const TopoDS_Face&  OF = It.Value().Face();
-    myInitOffsetFace.Bind    (SI,OF);      
-    myInitOffsetFace.SetRoot (SI);      // Initial<-> Offset
-    myImageOffset.SetRoot    (OF);      // FaceOffset root of images
-    
-    if (SI.ShapeType() == TopAbs_FACE) {
-      for (Exp.Init(SI.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
-           Exp.More(); Exp.Next()) {
-        //--------------------------------------------------------------------
-        // To each face are associatedthe edges that restrict that 
-        // The edges that do not generate tubes or are not tangent
-        // to two faces are removed.
-        //--------------------------------------------------------------------
-        const TopoDS_Edge& E = TopoDS::Edge(Exp.Current());
-        const BRepOffset_ListOfInterval& L  = myAnalyse.Type(E);
-        if (!L.IsEmpty() && L.First().Type() != RT) {
-          TopAbs_Orientation OO  = E.Orientation();
-          TopoDS_Shape aLocalShape = It.Value().Generated(E);
-          TopoDS_Edge        OE  = TopoDS::Edge(aLocalShape);
-//          TopoDS_Edge        OE  = TopoDS::Edge(It.Value().Generated(E));
-          myAsDes->Add (OF,OE.Oriented(OO));
-        }
-      }
-    }
-    else {
-      for (Exp.Init(OF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
-           Exp.More(); Exp.Next()) {
-        myAsDes->Add (OF,Exp.Current());
-      }
-    }
-  }
-
-#ifdef OCCT_DEBUG
-  if ( ChronBuild) Clock.Show();
-#endif
-}
-
-
-
-//=======================================================================
-//function : SelfInter
-//purpose  : 
-//=======================================================================
-
 void BRepOffset_MakeOffset::SelfInter(TopTools_MapOfShape& /*Modif*/)
 {
 #ifdef OCCT_DEBUG
@@ -2449,12 +1754,10 @@ void BRepOffset_MakeOffset::SelfInter(TopTools_MapOfShape& /*Modif*/)
 #endif
 }
 
-
 //=======================================================================
 //function : ToContext
 //purpose  : 
 //=======================================================================
-
 void BRepOffset_MakeOffset::ToContext (BRepOffset_DataMapOfShapeOffset& MapSF)
 {
   TopTools_DataMapOfShapeShape        Created;   
@@ -2598,12 +1901,10 @@ void BRepOffset_MakeOffset::ToContext (BRepOffset_DataMapOfShapeOffset& MapSF)
   }
 }
 
-
 //=======================================================================
 //function : UpdateFaceOffset
 //purpose  : 
 //=======================================================================
-
 void BRepOffset_MakeOffset::UpdateFaceOffset()
 {
   TopTools_MapOfShape M;
@@ -2643,7 +1944,6 @@ void BRepOffset_MakeOffset::UpdateFaceOffset()
 //function : CorrectConicalFaces
 //purpose  : 
 //=======================================================================
-
 void BRepOffset_MakeOffset::CorrectConicalFaces()
 {
   TopTools_SequenceOfShape Cones;
@@ -3078,12 +2378,10 @@ void BRepOffset_MakeOffset::Intersection2D(const TopTools_IndexedMapOfShape& Mod
 #endif
 }
 
-
 //=======================================================================
 //function : MakeLoops
 //purpose  : 
 //=======================================================================
-
 void BRepOffset_MakeOffset::MakeLoops(TopTools_IndexedMapOfShape& Modif)
 {
 #ifdef OCCT_DEBUG
@@ -3135,7 +2433,6 @@ void BRepOffset_MakeOffset::MakeLoops(TopTools_IndexedMapOfShape& Modif)
 //purpose  : Reconstruction of topologically unchanged faces that
 //           share edges that were reconstructed.
 //=======================================================================
-
 void BRepOffset_MakeOffset::MakeFaces(TopTools_IndexedMapOfShape& /*Modif*/)
 {
 #ifdef OCCT_DEBUG
@@ -3162,49 +2459,10 @@ void BRepOffset_MakeOffset::MakeFaces(TopTools_IndexedMapOfShape& /*Modif*/)
 #endif
 }
 
-//=======================================================================
-//function : UpdateInitOffset
-//purpose  : Update and cleaning of myInitOffset 
-//=======================================================================
-
-static void UpdateInitOffset (BRepAlgo_Image&         myInitOffset,
-                              BRepAlgo_Image&         myImageOffset,
-                              const TopoDS_Shape&     myOffsetShape,
-                              const TopAbs_ShapeEnum &theShapeType) // skv
-{
-  BRepAlgo_Image NIOF;
-  const TopTools_ListOfShape& Roots = myInitOffset.Roots();
-  TopTools_ListIteratorOfListOfShape it(Roots);
-  for (; it.More(); it.Next()) {
-    NIOF.SetRoot (it.Value());    
-  }
-  for (it.Initialize(Roots); it.More(); it.Next()) {
-    const TopoDS_Shape& SI = it.Value();
-    TopTools_ListOfShape LI;
-    TopTools_ListOfShape L1;
-    myInitOffset.LastImage(SI,L1);
-    TopTools_ListIteratorOfListOfShape itL1(L1);
-    for (; itL1.More(); itL1.Next()) {
-      const TopoDS_Shape& O1 = itL1.Value();
-      TopTools_ListOfShape L2;
-      myImageOffset.LastImage(O1,L2);
-      LI.Append(L2);
-    }
-    NIOF.Bind(SI,LI);
-  }
-//  Modified by skv - Mon Apr  4 18:17:27 2005 Begin
-//  Supporting history.
-//   NIOF.Filter(myOffsetShape,TopAbs_FACE);
-  NIOF.Filter(myOffsetShape, theShapeType);
-//  Modified by skv - Mon Apr  4 18:17:27 2005 End
-  myInitOffset = NIOF;
-}
-
 //=======================================================================
 //function : MakeMissingWalls
 //purpose  : 
 //=======================================================================
-
 void BRepOffset_MakeOffset::MakeMissingWalls ()
 {
   TopTools_DataMapOfShapeListOfShape Contours; //Start vertex + list of connected edges (free boundary)
@@ -3572,71 +2830,6 @@ void BRepOffset_MakeOffset::MakeMissingWalls ()
     }
 }
 
-//=======================================================================
-//function : CheckNormals
-//purpose  : 
-//=======================================================================
-static Standard_Boolean CheckNormals(const TopoDS_Face& theFIm,
-                                     const TopoDS_Face& theFOr)
-{
-  
-  Standard_Real aUMin, aUMax, aVMin, aVMax, aU, aV, anAngle;
-  gp_Pnt aP;
-  gp_Vec aVecU, aVecV, aVNIm, aVNOr;
-  Standard_Boolean bIsCollinear;
-  //
-  BRepAdaptor_Surface aSFIm(theFIm), aSFOr(theFOr);
-  //
-  aUMin = aSFIm.FirstUParameter();
-  aUMax = aSFIm.LastUParameter();
-  aVMin = aSFIm.FirstVParameter();
-  aVMax = aSFIm.LastVParameter();
-  //
-  aU = (aUMin + aUMax) * 0.5;
-  if (Precision::IsInfinite(aUMin) && 
-      Precision::IsInfinite(aUMax)) {
-    aU = 0.;
-  }
-  else if (Precision::IsInfinite(aUMin) && 
-           !Precision::IsInfinite(aUMax)) {
-    aU = aUMax;
-  }
-  else if (!Precision::IsInfinite(aUMin) && 
-           Precision::IsInfinite(aUMax)) {
-    aU = aUMin;
-  }
-  //
-  aV = (aVMin + aVMax) * 0.5;
-  if (Precision::IsInfinite(aVMin) && 
-      Precision::IsInfinite(aVMax)) {
-    aV = 0.;
-  }
-  else if (Precision::IsInfinite(aVMin) && 
-           !Precision::IsInfinite(aVMax)) {
-    aV = aVMax;
-  }
-  else if (!Precision::IsInfinite(aVMin) && 
-           Precision::IsInfinite(aVMax)) {
-    aV = aVMin;
-  }
-  //
-  aSFIm.D1(aU, aV, aP, aVecU, aVecV);
-  aVNIm = aVecU.Crossed(aVecV);
-  if (theFIm.Orientation() == TopAbs_REVERSED) {
-    aVNIm.Reverse();
-  }
-  //
-  aSFOr.D1(aU, aV, aP, aVecU, aVecV);
-  aVNOr = aVecU.Crossed(aVecV);
-  if (theFOr.Orientation() == TopAbs_REVERSED) {
-    aVNOr.Reverse();
-  }
-  //
-  anAngle = aVNIm.Angle(aVNOr);
-  bIsCollinear = (anAngle < Precision::Confusion());
-  return bIsCollinear;
-}
-
 //=======================================================================
 //function : MakeShells
 //purpose  : 
@@ -3729,7 +2922,7 @@ void BRepOffset_MakeOffset::MakeShells()
         aBB.Add(aCSF, aF);
       }
       //
-      bDone = (myOffset > 0);
+      bDone = ((myOffset > 0) || !bFaces);
       if (bDone) {
         UpdateOrigins(anOrigins, aGF);
         //
@@ -3785,30 +2978,14 @@ void BRepOffset_MakeOffset::MakeShells()
             //
             if (bDone) {
               for (i = 1; i <= aNb; ++i) {
-                const TopoDS_Shape& aFx = aMFS.FindKey(i);
                 const BOPCol_ListOfShape& aLSx = aMFS(i);
                 if (aLSx.Extent() == 1) {
-                  // check orientation
-                  const TopoDS_Face& aF = *(TopoDS_Face*)&aFx;
-                  if (!anOrigins.Contains(aF)) {
-                    aLSF2.Append(aFx);
-                    continue;
-                  }
-                  //
-                  const TopTools_ListOfShape& aLFOr = anOrigins.FindFromKey(aFx);
-                  aItLS.Initialize(aLFOr);
-                  for (; aItLS.More(); aItLS.Next()) {
-                    const TopoDS_Face& aFOr = *(TopoDS_Face*)&aItLS.Value();
-                    //
-                    if (CheckNormals(aF, aFOr)) {
-                      aLSF2.Append(aFx);
-                      break;
-                    }
-                  }
+                  const TopoDS_Shape& aFx = aMFS.FindKey(i);
+                  aLSF2.Append(aFx);
                 }
               }
               //
-              // make solid containing most outer faces
+              // make solids from the new list
               BOPAlgo_MakerVolume aMV2;
               //
               aMV2.SetArguments(aLSF2);
@@ -3818,6 +2995,43 @@ void BRepOffset_MakeOffset::MakeShells()
               bDone = (aMV2.ErrorStatus() == 0);
               if (bDone) {
                 aResult = aMV2.Shape();
+                if (aResult.ShapeType() == TopAbs_COMPOUND) {
+                  BOPCol_ListOfShape aLSF3;
+                  //
+                  aExp.Init(aResult, TopAbs_FACE);
+                  for (; aExp.More(); aExp.Next()) {
+                    const TopoDS_Face& aF = *(TopoDS_Face*)&aExp.Current();
+                    //
+                    // check orientation
+                    if (!anOrigins.Contains(aF)) {
+                      aLSF3.Append(aF);
+                      continue;
+                    }
+                    //
+                    const TopTools_ListOfShape& aLFOr = anOrigins.FindFromKey(aF);
+                    aItLS.Initialize(aLFOr);
+                    for (; aItLS.More(); aItLS.Next()) {
+                      const TopoDS_Face& aFOr = *(TopoDS_Face*)&aItLS.Value();
+                      //
+                      if (CheckNormals(aF, aFOr)) {
+                        aLSF3.Append(aF);
+                        break;
+                      }
+                    }
+                  }
+                  //
+                  // make solid containing most outer faces
+                  BOPAlgo_MakerVolume aMV3;
+                  //
+                  aMV3.SetArguments(aLSF3);
+                  aMV3.SetIntersect(Standard_False);
+                  //
+                  aMV3.Perform();
+                  bDone = (aMV3.ErrorStatus() == 0);
+                  if (bDone) {
+                    aResult = aMV3.Shape();
+                  }
+                }
               }
             }
           }
@@ -3850,369 +3064,1307 @@ void BRepOffset_MakeOffset::MakeShells()
       }
     }
   }
-  //
-  if (!bDone) {
-    BRepTools_Quilt Glue;
-    BOPCol_ListIteratorOfListOfShape aItLS;
-    //
-    aItLS.Initialize(aLSF);
-    for (; aItLS.More(); aItLS.Next()) {
-      const TopoDS_Shape& aF = aItLS.Value();
-      Glue.Add(aF);
-    }
-    myOffsetShape = Glue.Shells();
-  }
+  //
+  if (!bDone) {
+    BRepTools_Quilt Glue;
+    BOPCol_ListIteratorOfListOfShape aItLS;
+    //
+    aItLS.Initialize(aLSF);
+    for (; aItLS.More(); aItLS.Next()) {
+      const TopoDS_Shape& aF = aItLS.Value();
+      Glue.Add(aF);
+    }
+    myOffsetShape = Glue.Shells();
+  }
+}
+
+//=======================================================================
+//function : MakeSolid
+//purpose  : 
+//=======================================================================
+void BRepOffset_MakeOffset::MakeSolid ()
+{
+ if (myOffsetShape.IsNull()) return;
+
+//  Modified by skv - Mon Apr  4 18:17:27 2005 Begin
+//  Supporting history.
+  UpdateInitOffset (myInitOffsetFace,myImageOffset,myOffsetShape, TopAbs_FACE);
+  UpdateInitOffset (myInitOffsetEdge,myImageOffset,myOffsetShape, TopAbs_EDGE);
+//  Modified by skv - Mon Apr  4 18:17:27 2005 End
+  TopExp_Explorer             exp;
+  BRep_Builder                B;
+  Standard_Integer            NbShell = 0;
+  TopoDS_Compound             NC;
+  TopoDS_Shape                S1;
+  B.MakeCompound (NC);
+
+  for (exp.Init(myOffsetShape,TopAbs_SHELL); exp.More(); exp.Next()) {
+    TopoDS_Shell Sh = TopoDS::Shell(exp.Current());
+    if (myThickening && myOffset > 0.)
+      Sh.Reverse();
+    NbShell++;
+    if (Sh.Closed()) {
+      TopoDS_Solid  Sol;
+      B.MakeSolid  (Sol);
+      B.Add        (Sol,Sh);
+      Sol.Closed(Standard_True);
+      B.Add (NC,Sol);
+      if (NbShell == 1) S1 = Sol;
+    }
+    else {
+      B.Add (NC,Sh);
+      if (NbShell == 1) S1 = Sh;
+    }
+  }
+  if (NbShell == 1) myOffsetShape = S1;
+  else              myOffsetShape = NC;
+}
+
+//=======================================================================
+//function : SelectShells
+//purpose  : 
+//=======================================================================
+void BRepOffset_MakeOffset::SelectShells ()
+{  
+  TopTools_MapOfShape FreeEdges;
+  TopExp_Explorer exp(myShape,TopAbs_EDGE);
+  //-------------------------------------------------------------
+  // FreeEdges all edges that can have free border in the  
+  // parallel shell
+  // 1 - free borders of myShape .
+  //-------------------------------------------------------------
+  for ( ; exp.More(); exp.Next()) {
+    const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
+    const TopTools_ListOfShape& LA = myAnalyse.Ancestors(E);
+    if (LA.Extent() < 2) {
+      if (myAnalyse.Type(E).First().Type() == BRepOffset_FreeBoundary) {
+        FreeEdges.Add(E);                       
+      }
+    }  
+  }
+  // myShape has free borders and there are no caps
+  // no unwinding 3d.
+  if (!FreeEdges.IsEmpty() && myFaces.IsEmpty()) return;
+
+  myOffsetShape = BRepOffset_Tool::Deboucle3D(myOffsetShape,FreeEdges);
+}
+
+//=======================================================================
+//function : OffsetFacesFromShapes
+//purpose  : 
+//=======================================================================
+const BRepAlgo_Image& BRepOffset_MakeOffset::OffsetFacesFromShapes() const
+{
+  return myInitOffsetFace;
+}
+
+//  Modified by skv - Tue Mar 15 16:20:43 2005 Begin
+
+//=======================================================================
+//function : GetJoinType
+//purpose  : Query offset join type.
+//=======================================================================
+GeomAbs_JoinType BRepOffset_MakeOffset::GetJoinType() const
+{
+  return myJoin;
+}
+
+//=======================================================================
+//function : OffsetEdgesFromShapes
+//purpose  : 
+//=======================================================================
+const BRepAlgo_Image& BRepOffset_MakeOffset::OffsetEdgesFromShapes() const
+{
+  return myInitOffsetEdge;
+}
+
+//  Modified by skv - Tue Mar 15 16:20:43 2005 End
+
+//=======================================================================
+//function : ClosingFaces
+//purpose  : 
+//=======================================================================
+const TopTools_IndexedMapOfShape& BRepOffset_MakeOffset::ClosingFaces () const
+{
+  return myFaces;
+}
+
+//=======================================================================
+//function : EncodeRegularity
+//purpose  : 
+//=======================================================================
+void BRepOffset_MakeOffset::EncodeRegularity ()
+{
+#ifdef OCCT_DEBUG
+  if (ChronBuild) {  
+    cout << " CODING OF REGULARITIES:" << endl;
+    Clock.Reset();
+    Clock.Start();
+  }
+#endif
+
+  if (myOffsetShape.IsNull()) return;
+  // find edges G1 in the result
+  TopExp_Explorer exp(myOffsetShape,TopAbs_EDGE);
+
+  BRep_Builder B;
+  TopTools_MapOfShape MS;
+
+  for ( ; exp.More(); exp.Next()) {
+    TopoDS_Edge OE  = TopoDS::Edge(exp.Current());
+    BRepLib::BuildCurve3d(OE,myTol);
+    TopoDS_Edge ROE = OE;
+    
+    if ( !MS.Add(OE)) continue;
+      
+    if ( myImageOffset.IsImage(OE)) 
+      ROE = TopoDS::Edge(myImageOffset.Root(OE));
+
+    const TopTools_ListOfShape& LofOF    = myAsDes->Ascendant(ROE);
+    
+    if (LofOF.Extent() != 2) {
+#ifdef OCCT_DEBUG_VERB
+    cout << " Edge shared by " << LofOF.Extent() << " Faces" << endl;
+#endif
+      continue;
+    }
+
+    const TopoDS_Face& F1 = TopoDS::Face(LofOF.First());
+    const TopoDS_Face& F2 = TopoDS::Face(LofOF.Last() );
+    
+    if ( F1.IsNull() || F2.IsNull()) 
+      continue;
+   
+    const TopoDS_Shape& Root1 = myInitOffsetFace.Root(F1);
+    const TopoDS_Shape& Root2 = myInitOffsetFace.Root(F2);
+
+    TopAbs_ShapeEnum Type1 = Root1.ShapeType();
+    TopAbs_ShapeEnum Type2 = Root2.ShapeType();
+    if (F1.IsSame(F2)) {      
+      if (BRep_Tool::IsClosed(OE,F1)) {
+        // Temporary Debug for the Bench.
+        // Check with YFR.
+        // In mode intersection, the edges are not coded in myInitOffsetEdge
+        // so, manage case by case
+        // Note DUB; for Hidden parts, it is NECESSARY to code CN 
+        // Analytic Surfaces.
+        if (myJoin == GeomAbs_Intersection) {
+          BRepAdaptor_Surface BS(F1,Standard_False);
+          GeomAbs_SurfaceType SType = BS.GetType();
+          if (SType == GeomAbs_Cylinder ||
+              SType == GeomAbs_Cone     ||
+              SType == GeomAbs_Sphere   ||
+              SType == GeomAbs_Torus      ) {
+            B.Continuity(OE,F1,F1,GeomAbs_CN);
+          }
+          else {
+            // See YFR : MaJ of myInitOffsetFace
+          }
+        }
+        else if (myInitOffsetEdge.IsImage(ROE)) {
+          if ( Type1 == TopAbs_FACE && Type2 == TopAbs_FACE) {
+            const TopoDS_Face& FRoot = TopoDS::Face(Root1);
+            const TopoDS_Edge& EI = TopoDS::Edge(myInitOffsetEdge.ImageFrom(ROE));
+            GeomAbs_Shape Conti = BRep_Tool::Continuity(EI,FRoot,FRoot);
+            if (Conti == GeomAbs_CN) {
+              B.Continuity(OE,F1,F1,GeomAbs_CN);
+            }
+            else if ( Conti > GeomAbs_C0) {
+              B.Continuity(OE,F1,F1,GeomAbs_G1);
+            }
+          }
+        }
+      }
+      continue;
+    }
+
+
+    //  code regularities G1 between :
+    //    - sphere and tube : one root is a vertex, the other is an edge 
+    //                        and the vertex is included in the edge
+    //    - face and tube   : one root is a face, the other an edge 
+    //                        and the edge is included in the face
+    //    - face and face    : if two root faces are tangent in 
+    //                        the initial shape, they will be tangent in the offset shape
+    //    - tube and tube  : if 2 edges generating tubes are
+    //                        tangents, the 2 will be tangent either.
+    if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_VERTEX) {
+      TopoDS_Vertex V1,V2;
+      TopExp::Vertices(TopoDS::Edge(Root1), V1, V2);
+      if ( V1.IsSame(Root2) || V2.IsSame(Root2)) {
+        B.Continuity(OE,F1,F2,GeomAbs_G1);
+      }
+    }
+    else if ( Type1 == TopAbs_VERTEX && Type2 == TopAbs_EDGE) {
+      TopoDS_Vertex V1,V2;
+      TopExp::Vertices(TopoDS::Edge(Root2), V1, V2);
+      if ( V1.IsSame(Root1) || V2.IsSame(Root1)) {
+        B.Continuity(OE,F1,F2,GeomAbs_G1);
+      }
+    }
+    else if ( Type1 == TopAbs_FACE && Type2 == TopAbs_EDGE) {
+      TopExp_Explorer exp2(Root1,TopAbs_EDGE);
+      for ( ; exp2.More(); exp2.Next()) {
+        if ( exp2.Current().IsSame(Root2)) {
+          B.Continuity(OE,F1,F2,GeomAbs_G1);
+          break;
+        }
+      }
+    }
+    else if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_FACE) {
+      TopExp_Explorer exp2(Root2,TopAbs_EDGE);
+      for ( ; exp2.More(); exp2.Next()) {
+        if ( exp2.Current().IsSame(Root1)) {
+          B.Continuity(OE,F1,F2,GeomAbs_G1);
+          break;
+        }
+      }
+    }
+    else if ( Type1 == TopAbs_FACE && Type2 == TopAbs_FACE) {
+    //  if two root faces are tangent in 
+    //  the initial shape, they will be tangent in the offset shape
+      TopTools_ListOfShape LE,LV;
+      BRepOffset_Tool::HasCommonShapes(TopoDS::Face(Root1),
+                                       TopoDS::Face(Root2),
+                                       LE,LV);
+      if ( LE.Extent() == 1) { 
+        const TopoDS_Edge& Ed = TopoDS::Edge(LE.First());
+        if ( myAnalyse.HasAncestor(Ed)) {
+          const BRepOffset_ListOfInterval& LI = myAnalyse.Type(Ed);
+          if (LI.Extent()       == 1   && 
+              LI.First().Type() == BRepOffset_Tangent) {
+            B.Continuity(OE,F1,F2,GeomAbs_G1);
+          }
+        }
+      }
+    }
+    else if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_EDGE) {
+      TopTools_ListOfShape LV;
+      TopExp_Explorer exp1,exp2;
+      for (exp1.Init(Root1,TopAbs_VERTEX); exp1.More(); exp1.Next()) {
+        TopExp_Explorer exp2(F2,TopAbs_EDGE);
+        for (exp2.Init(Root2,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
+          if (exp1.Current().IsSame(exp2.Current())) {
+            LV.Append(exp1.Current());
+          }
+        }
+      }
+      if ( LV.Extent() == 1) {
+        TopTools_ListOfShape LEdTg;
+        myAnalyse.TangentEdges(TopoDS::Edge(Root1),
+                               TopoDS::Vertex(LV.First()),
+                               LEdTg);
+        TopTools_ListIteratorOfListOfShape it(LEdTg);
+        for (; it.More(); it.Next()) {
+          if ( it.Value().IsSame(Root2)) {
+            B.Continuity(OE,F1,F2,GeomAbs_G1);
+            break;
+          }
+        }
+      }
+    }
+  }
+
+#ifdef OCCT_DEBUG
+  if ( ChronBuild) Clock.Show();
+#endif
+}
+
+
+//=======================================================================
+// static methods implementation
+//=======================================================================
+
+//=======================================================================
+//function : UpDateTolerance
+//purpose  : 
+//=======================================================================
+void UpdateTolerance (TopoDS_Shape& S,
+                      const TopTools_IndexedMapOfShape& Faces)
+{
+  BRep_Builder B;
+  TopTools_MapOfShape View;
+  TopoDS_Vertex V[2];
+
+  // The edges of caps are not modified.
+  Standard_Integer j;
+  for (j = 1; j <= Faces.Extent(); j++) {
+    const TopoDS_Shape& F = Faces(j);
+    TopExp_Explorer Exp;
+    for (Exp.Init(F,TopAbs_EDGE); Exp.More(); Exp.Next()) {
+      View.Add(Exp.Current());
+    }
+  }
+  
+  TopExp_Explorer Exp;
+  for (Exp.Init(S,TopAbs_EDGE); Exp.More(); Exp.Next()) {
+    TopoDS_Edge E = TopoDS::Edge(Exp.Current());
+    if (View.Add(E)) {
+      Handle(BRepCheck_Edge) EdgeCorrector = new BRepCheck_Edge(E);
+      Standard_Real    Tol = EdgeCorrector->Tolerance();
+      B.UpdateEdge (E,Tol);
+      
+      // Update the vertices.
+      TopExp::Vertices(E,V[0],V[1]);
+     
+      for (Standard_Integer i = 0 ; i <=1 ; i++) {
+        if (View.Add(V[i])) {
+          Handle(BRep_TVertex) TV = Handle(BRep_TVertex)::DownCast(V[i].TShape());
+          TV->Tolerance(0.);
+          Handle(BRepCheck_Vertex) VertexCorrector = new BRepCheck_Vertex(V[i]);
+          B.UpdateVertex (V[i],VertexCorrector->Tolerance());
+          // use the occasion to clean the vertices.
+          (TV->ChangePoints()).Clear();
+        }
+        B.UpdateVertex(V[i],Tol);
+      }
+    }
+  }
+}
+
+//=======================================================================
+//function : FindParameter
+//purpose  : 
+//=======================================================================
+Standard_Boolean FindParameter(const TopoDS_Vertex& V, 
+                               const TopoDS_Edge& E,
+                               Standard_Real& U)
+{
+  // Search the vertex in the edge
+
+  Standard_Boolean rev = Standard_False;
+  TopoDS_Shape VF;
+  TopAbs_Orientation orient = TopAbs_INTERNAL;
+
+  TopoDS_Iterator itv(E.Oriented(TopAbs_FORWARD));
+
+  // if the edge has no vertices
+  // and is degenerated use the vertex orientation
+  // RLE, june 94
+
+  if (!itv.More() && BRep_Tool::Degenerated(E)) {
+    orient = V.Orientation();
+  }
+
+  while (itv.More()) {
+    const TopoDS_Shape& Vcur = itv.Value();
+    if (V.IsSame(Vcur)) {
+      if (VF.IsNull()) {
+        VF = Vcur;
+      }
+      else {
+        rev = E.Orientation() == TopAbs_REVERSED;
+        if (Vcur.Orientation() == V.Orientation()) {
+          VF = Vcur;
+        }
+      }
+    }
+    itv.Next();
+  }
+  
+  if (!VF.IsNull()) orient = VF.Orientation();
+  Standard_Real f,l;
+
+  if (orient ==  TopAbs_FORWARD) {
+    BRep_Tool::Range(E,f,l);
+    //return (rev) ? l : f;
+    U = (rev) ? l : f;
+    return Standard_True;
+  }
+  else if (orient ==  TopAbs_REVERSED) {
+    BRep_Tool::Range(E,f,l);
+    //return (rev) ? f : l;
+    U = (rev) ? f : l;
+    return Standard_True;
+   }
+
+  else {
+    TopLoc_Location L;
+    const Handle(Geom_Curve)& C = BRep_Tool::Curve(E,L,f,l);
+    L = L.Predivided(V.Location());
+    if (!C.IsNull() || BRep_Tool::Degenerated(E)) {
+      BRep_ListIteratorOfListOfPointRepresentation itpr
+        ((*((Handle(BRep_TVertex)*) &V.TShape()))->Points());
+
+      while (itpr.More()) {
+        const Handle(BRep_PointRepresentation)& pr = itpr.Value();
+        if (pr->IsPointOnCurve(C,L)) {
+          Standard_Real p = pr->Parameter();
+          Standard_Real res = p;// SVV 4 nov 99 - to avoid warnings on Linux
+          if (!C.IsNull()) {
+            // Closed curves RLE 16 june 94
+            if (Precision::IsNegativeInfinite(f))
+              {
+                //return pr->Parameter();//p;
+                U = pr->Parameter();
+                return Standard_True;
+              }
+            if (Precision::IsPositiveInfinite(l))
+              {
+                //return pr->Parameter();//p;
+                U = pr->Parameter();
+                return Standard_True;
+              }
+            gp_Pnt Pf = C->Value(f).Transformed(L.Transformation());
+            gp_Pnt Pl = C->Value(l).Transformed(L.Transformation());
+            Standard_Real tol = BRep_Tool::Tolerance(V);
+            if (Pf.Distance(Pl) < tol) {
+              if (Pf.Distance(BRep_Tool::Pnt(V)) < tol) {
+                if (V.Orientation() == TopAbs_FORWARD) res = f;//p = f;
+                else                                   res = l;//p = l;
+              }
+            }
+          }
+          //return res;//p;
+          U = res;
+          return Standard_True;
+        }
+        itpr.Next();
+      }
+    }
+    else {
+      // no 3d curve !!
+      // let us try with the first pcurve
+      Handle(Geom2d_Curve) PC;
+      Handle(Geom_Surface) S;
+      BRep_Tool::CurveOnSurface(E,PC,S,L,f,l);
+      L = L.Predivided(V.Location()); 
+      BRep_ListIteratorOfListOfPointRepresentation itpr
+        ((*((Handle(BRep_TVertex)*) &V.TShape()))->Points());
+
+      while (itpr.More()) {
+        const Handle(BRep_PointRepresentation)& pr = itpr.Value();
+        if (pr->IsPointOnCurveOnSurface(PC,S,L)) {
+          Standard_Real p = pr->Parameter();
+          // Closed curves RLE 16 june 94
+          if (PC->IsClosed()) {
+            if ((p == PC->FirstParameter()) || 
+                (p == PC->LastParameter())) {
+              if (V.Orientation() == TopAbs_FORWARD) p = PC->FirstParameter();
+              else                                   p = PC->LastParameter();
+            }
+          }
+          //return p;
+          U = p;
+          return Standard_True;
+        }
+        itpr.Next();
+      }
+    }
+  }
+  
+  //Standard_NoSuchObject::Raise("BRep_Tool:: no parameter on edge");
+  return Standard_False;
+}
+
+//=======================================================================
+//function : GetEdgePoints
+//purpose  : gets the first, last and middle points of the edge
+//=======================================================================
+void GetEdgePoints(const TopoDS_Edge& anEdge,
+                   const TopoDS_Face& aFace,
+                   gp_Pnt& fPnt, gp_Pnt& mPnt,
+                   gp_Pnt& lPnt)
+{
+  Standard_Real f, l;
+  Handle(Geom2d_Curve) theCurve = BRep_Tool::CurveOnSurface( anEdge, aFace, f, l );
+  gp_Pnt2d fPnt2d = theCurve->Value(f);
+  gp_Pnt2d lPnt2d = theCurve->Value(l);
+  gp_Pnt2d mPnt2d = theCurve->Value(0.5*(f + l));
+  Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
+  fPnt = aSurf->Value(fPnt2d.X(),fPnt2d.Y());
+  lPnt = aSurf->Value(lPnt2d.X(),lPnt2d.Y());
+  mPnt = aSurf->Value(mPnt2d.X(), mPnt2d.Y());
+}
+
+//=======================================================================
+//function : FillContours
+//purpose  : fills free boundary contours and faces connected (MapEF)
+//=======================================================================
+void FillContours(const TopoDS_Shape& aShape,
+                  const BRepOffset_Analyse& Analyser,
+                  TopTools_DataMapOfShapeListOfShape& Contours,
+                  TopTools_DataMapOfShapeShape& MapEF)
+{
+  TopTools_ListOfShape Edges;
+
+  TopExp_Explorer Explo(aShape, TopAbs_FACE);
+  BRepTools_WireExplorer Wexp;
+
+  for (; Explo.More(); Explo.Next())
+    {
+      TopoDS_Face aFace = TopoDS::Face(Explo.Current());
+      TopoDS_Iterator itf(aFace);
+      for (; itf.More(); itf.Next())
+        {
+          TopoDS_Wire aWire = TopoDS::Wire(itf.Value());
+          for (Wexp.Init(aWire, aFace); Wexp.More(); Wexp.Next())
+            {
+              TopoDS_Edge anEdge = Wexp.Current();
+              if (BRep_Tool::Degenerated(anEdge))
+                continue;
+              const BRepOffset_ListOfInterval& Lint = Analyser.Type(anEdge);
+              if (!Lint.IsEmpty() && Lint.First().Type() == BRepOffset_FreeBoundary)
+                {
+                  MapEF.Bind(anEdge, aFace);
+                  Edges.Append(anEdge);
+                }
+            }
+        }
+    }
+
+  TopTools_ListIteratorOfListOfShape itl;
+  while (!Edges.IsEmpty())
+    {
+      TopoDS_Edge StartEdge = TopoDS::Edge(Edges.First());
+      Edges.RemoveFirst();
+      TopoDS_Vertex StartVertex, CurVertex;
+      TopExp::Vertices(StartEdge, StartVertex, CurVertex, Standard_True);
+      TopTools_ListOfShape aContour;
+      aContour.Append(StartEdge);
+      while (!CurVertex.IsSame(StartVertex))
+        for (itl.Initialize(Edges); itl.More(); itl.Next())
+          {
+            TopoDS_Edge anEdge = TopoDS::Edge(itl.Value());
+            TopoDS_Vertex V1, V2;
+            TopExp::Vertices(anEdge, V1, V2);
+            if (V1.IsSame(CurVertex) || V2.IsSame(CurVertex))
+              {
+                aContour.Append(anEdge);
+                CurVertex = (V1.IsSame(CurVertex))? V2 : V1;
+                Edges.Remove(itl);
+                break;
+              }
+          }
+      Contours.Bind(StartVertex, aContour);
+    }
+}
+
+//=======================================================================
+//function : RemoveCorks
+//purpose  : 
+//=======================================================================
+void RemoveCorks (TopoDS_Shape&               S,
+                  TopTools_IndexedMapOfShape& Faces)
+{  
+  TopoDS_Compound SS;
+  BRep_Builder    B;
+  B.MakeCompound (SS);
+  //-----------------------------------------------------
+  // Construction of a shape without caps.
+  // and Orientation of caps as in shape S.
+  //-----------------------------------------------------
+  TopExp_Explorer exp(S,TopAbs_FACE);
+  for (; exp.More(); exp.Next()) {
+    const TopoDS_Shape& Cork = exp.Current(); 
+    if (!Faces.Contains(Cork)) {
+      B.Add(SS,Cork);
+    }
+    else {
+      //Faces.Remove (Cork);
+      //begin instead of Remove//
+      TopoDS_Shape LastShape = Faces(Faces.Extent());
+      Faces.RemoveLast();
+      if (Faces.FindIndex(Cork) != 0)
+        Faces.Substitute(Faces.FindIndex(Cork), LastShape);
+      //end instead of Remove  //
+      Faces.Add(Cork); // to reset it with proper orientation.
+    }
+  }
+  S = SS;
+#ifdef DRAW
+  if ( AffichOffC) 
+    DBRep::Set("myInit", SS);
+#endif
+
+}
+
+//=======================================================================
+//function : IsConnectedShell
+//purpose  : 
+//=======================================================================
+Standard_Boolean IsConnectedShell( const TopoDS_Shape& S )
+{  
+  BRepTools_Quilt Glue;
+  Glue.Add( S );
+
+  TopoDS_Shape SS = Glue.Shells();
+  TopExp_Explorer Explo( SS, TopAbs_SHELL );
+  Explo.Next();
+  if (Explo.More())
+    return Standard_False;
+  
+  return Standard_True;
+}
+
+//=======================================================================
+//function : MakeList
+//purpose  : 
+//=======================================================================
+void MakeList (TopTools_ListOfShape&             OffsetFaces,
+               const BRepAlgo_Image&             myInitOffsetFace,
+               const TopTools_IndexedMapOfShape& myFaces)
+{
+  TopTools_ListIteratorOfListOfShape itLOF(myInitOffsetFace.Roots());
+  for ( ; itLOF.More(); itLOF.Next()) {
+    const TopoDS_Shape& Root = itLOF.Value();
+    if (myInitOffsetFace.HasImage(Root)) {
+      if (!myFaces.Contains(Root)) {
+        OffsetFaces.Append(myInitOffsetFace.Image(Root).First());
+      }
+    }
+  }
 }
 
 //=======================================================================
-//function : MakeSolid
+//function : EvalMax
 //purpose  : 
 //=======================================================================
-
-void BRepOffset_MakeOffset::MakeSolid ()
+void EvalMax(const TopoDS_Shape& S, 
+             Standard_Real& Tol)
 {
- if (myOffsetShape.IsNull()) return;
+  TopExp_Explorer exp;
+  for (exp.Init(S,TopAbs_VERTEX); exp.More(); exp.Next()) {
+    const TopoDS_Vertex& V    = TopoDS::Vertex(exp.Current());
+    Standard_Real        TolV = BRep_Tool::Tolerance(V); 
+    if (TolV > Tol) Tol = TolV;
+  }
+  //Patch
+  Tol *= 5.;
+}
 
-//  Modified by skv - Mon Apr  4 18:17:27 2005 Begin
-//  Supporting history.
-  UpdateInitOffset (myInitOffsetFace,myImageOffset,myOffsetShape, TopAbs_FACE);
-  UpdateInitOffset (myInitOffsetEdge,myImageOffset,myOffsetShape, TopAbs_EDGE);
-//  Modified by skv - Mon Apr  4 18:17:27 2005 End
-  TopExp_Explorer             exp;
-  BRep_Builder                B;
-  Standard_Integer            NbShell = 0;
-  TopoDS_Compound             NC;
-  TopoDS_Shape                S1;
-  B.MakeCompound (NC);
+//=======================================================================
+//function : TrimEdge
+//purpose  : Trim the edge of the largest of descendants in AsDes2d.
+//           Order in AsDes two vertices that have trimmed the edge.
+//=======================================================================
+void TrimEdge(TopoDS_Edge&                  NE,
+              const Handle(BRepAlgo_AsDes)& AsDes2d,
+              Handle(BRepAlgo_AsDes)& AsDes)
+{
+  Standard_Real aSameParTol = Precision::Confusion();
+  
+  TopoDS_Vertex V1,V2;
+  Standard_Real U = 0.;
+  Standard_Real UMin =  Precision::Infinite();
+  Standard_Real UMax = -UMin;
 
-  for (exp.Init(myOffsetShape,TopAbs_SHELL); exp.More(); exp.Next()) {
-    TopoDS_Shell Sh = TopoDS::Shell(exp.Current());
-    if (myThickening && myOffset > 0.)
-      Sh.Reverse();
-    NbShell++;
-    if (Sh.Closed()) {
-      TopoDS_Solid  Sol;
-      B.MakeSolid  (Sol);
-      B.Add        (Sol,Sh);
-      Sol.Closed(Standard_True);
-      B.Add (NC,Sol);
-      if (NbShell == 1) S1 = Sol;
+  const TopTools_ListOfShape& LE = AsDes2d->Descendant(NE);
+  //
+  Standard_Boolean bTrim = Standard_False;
+  //
+  if (LE.Extent() > 1) {
+    TopTools_ListIteratorOfListOfShape it (LE);
+    for (; it.More(); it.Next()) {
+      TopoDS_Vertex V = TopoDS::Vertex(it.Value());
+      if (NE.Orientation() == TopAbs_REVERSED)
+        V.Reverse();
+      //V.Orientation(TopAbs_INTERNAL);
+      if (!FindParameter(V, NE, U)) {
+        Standard_Real f, l;
+        Handle(Geom_Curve) theCurve = BRep_Tool::Curve(NE, f, l);
+        gp_Pnt thePoint = BRep_Tool::Pnt(V);
+        GeomAPI_ProjectPointOnCurve Projector(thePoint, theCurve);
+        if (Projector.NbPoints() == 0)
+          Standard_ConstructionError::Raise("BRepOffset_MakeOffset::TrimEdge no projection");
+        U = Projector.LowerDistanceParameter();
+      }
+      if (U < UMin) {
+        UMin = U; V1   = V;
+      }
+      if (U > UMax) {
+        UMax = U; V2   = V;
+      }
     }
-    else {
-      B.Add (NC,Sh);
-      if (NbShell == 1) S1 = Sh;
+    //
+    if (V1.IsNull() || V2.IsNull()) {
+      Standard_ConstructionError::Raise("BRepOffset_MakeOffset::TrimEdge");
+    }
+    if (!V1.IsSame(V2)) {
+      NE.Free( Standard_True );
+      BRep_Builder B;
+      TopAbs_Orientation Or = NE.Orientation();
+      NE.Orientation(TopAbs_FORWARD);
+      TopoDS_Vertex VF,VL;
+      TopExp::Vertices (NE,VF,VL);
+      B.Remove(NE,VF);
+      B.Remove(NE,VL);
+      B.Add  (NE,V1.Oriented(TopAbs_FORWARD));
+      B.Add  (NE,V2.Oriented(TopAbs_REVERSED));
+      B.Range(NE,UMin,UMax);
+      NE.Orientation(Or);
+      AsDes->Add(NE,V1.Oriented(TopAbs_FORWARD));
+      AsDes->Add(NE,V2.Oriented(TopAbs_REVERSED));
+      BRepLib::SameParameter(NE, aSameParTol, Standard_True);
+      //
+      bTrim = Standard_True;
+    }
+  }
+  //
+  if (!bTrim) {
+    if (!BRep_Tool::Degenerated(NE)) {
+      BRepAdaptor_Curve aBAC(NE);
+      if (!aBAC.IsClosed()) {
+        if (AsDes->HasAscendant(NE)) {
+          AsDes->Remove(NE);
+        }
+      }
     }
   }
-  if (NbShell == 1) myOffsetShape = S1;
-  else              myOffsetShape = NC;
 }
 
 //=======================================================================
-//function : SelectShells
+//function : SortFaces
 //purpose  : 
 //=======================================================================
-
-void BRepOffset_MakeOffset::SelectShells ()
-{  
-  TopTools_MapOfShape FreeEdges;
-  TopExp_Explorer exp(myShape,TopAbs_EDGE);
-  //-------------------------------------------------------------
-  // FreeEdges all edges that can have free border in the  
-  // parallel shell
-  // 1 - free borders of myShape .
-  //-------------------------------------------------------------
-  for ( ; exp.More(); exp.Next()) {
-    const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
-    const TopTools_ListOfShape& LA = myAnalyse.Ancestors(E);
-    if (LA.Extent() < 2) {
-      if (myAnalyse.Type(E).First().Type() == BRepOffset_FreeBoundary) {
-        FreeEdges.Add(E);                       
+void SortFaces(const TopTools_ListOfShape& theLIm, 
+               TopTools_ListOfShape& theLFImages,
+               const Standard_Boolean bKeepFirst)
+{
+  Standard_Integer bKeep; // 1 - keep; -1 - remove
+  Standard_Boolean bFlag;
+  TopTools_IndexedDataMapOfShapeListOfShape aDMELF;
+  TopTools_ListOfShape aLFKeep, aLFLeft, aLFTmp;
+  TopTools_MapOfShape aMV;
+  TopTools_ListIteratorOfListOfShape aItLF;
+  TopExp_Explorer aExp;
+  //
+  aLFLeft = theLIm;
+  //
+  bKeep = bKeepFirst ? 1 : -1;
+  for (;;) {
+    aLFTmp = aLFLeft;
+    //
+    aLFLeft.Clear();
+    aLFKeep.Clear();
+    aDMELF.Clear();
+    //
+    // map list of images  edge - faces
+    aItLF.Initialize(aLFTmp);
+    for (; aItLF.More(); aItLF.Next()) {
+      const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
+      TopExp::MapShapesAndAncestors(aFIm, TopAbs_EDGE, TopAbs_FACE, aDMELF);
+    }
+    //
+    // find images that have edge attached to only one face
+    aItLF.Initialize(aLFTmp);
+    for (; aItLF.More(); aItLF.Next()) {
+      const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
+      aExp.Init(aFIm, TopAbs_EDGE);
+      for (bFlag = Standard_False; aExp.More(); aExp.Next()) {
+        const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExp.Current();
+        const TopTools_ListOfShape& aLEF = aDMELF.FindFromKey(aE);
+        if (aLEF.Extent() == 1) {
+          TopoDS_Vertex aV1, aV2;
+          TopExp::Vertices(aE, aV1, aV2);
+          aMV.Add(aV1);
+          aMV.Add(aV2);
+          //
+          bFlag = Standard_True;
+        }
       }
-    }  
+      //
+      if (bFlag) {
+        aLFKeep.Append(aFIm);
+      }
+      else {
+        aLFLeft.Append(aFIm);
+      }
+    }
+    //
+    // map shapes left for processing
+    aDMELF.Clear();
+    aLFTmp = aLFLeft;
+    aLFLeft.Clear();
+    //
+    aItLF.Initialize(aLFTmp);
+    for (; aItLF.More(); aItLF.Next()) {
+      const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
+      TopExp::MapShapesAndAncestors(aFIm, TopAbs_EDGE, TopAbs_FACE, aDMELF);
+    }
+    //
+    // find outer edges and check if they touch the first part of edges
+    aItLF.Initialize(aLFTmp);
+    for (; aItLF.More(); aItLF.Next()) {
+      const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
+      aExp.Init(aFIm, TopAbs_EDGE);
+      for (bFlag = Standard_False; aExp.More() && !bFlag; aExp.Next()) {
+        const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExp.Current();
+        const TopTools_ListOfShape& aLEF = aDMELF.FindFromKey(aE);
+        if (aLEF.Extent() == 1) {
+          TopoDS_Vertex aV1, aV2;
+          TopExp::Vertices(aE, aV1, aV2);
+          //
+          bFlag = aMV.Contains(aV1) || aMV.Contains(aV2);
+        }
+      }
+      //
+      if (bFlag) {
+        aLFKeep.Append(aFIm);
+      }
+      else {
+        aLFLeft.Append(aFIm);
+      }
+    }
+    //
+    if (bKeep == 1) {
+      // aLFKeep should be kept
+      // aLFLeft left for further processing
+      aItLF.Initialize(aLFKeep);
+      for (; aItLF.More(); aItLF.Next()) {
+        const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
+        theLFImages.Append(aFIm);
+      }
+    }
+    //
+    if (aLFLeft.IsEmpty()) {
+      break;
+    }
+    //
+    bKeep *= -1;
   }
-  // myShape has free borders and there are no caps
-  // no unwinding 3d.
-  if (!FreeEdges.IsEmpty() && myFaces.IsEmpty()) return;
-
-  myOffsetShape = BRepOffset_Tool::Deboucle3D(myOffsetShape,FreeEdges);
 }
 
 //=======================================================================
-//function : OffsetFacesFromShapes
+//function : FindShape
 //purpose  : 
 //=======================================================================
-
-const BRepAlgo_Image& BRepOffset_MakeOffset::OffsetFacesFromShapes() const
+Standard_Boolean FindShape(const TopoDS_Shape& theSWhat,
+                           const TopoDS_Shape& theSWhere,
+                           TopoDS_Shape& theRes)
 {
-  return myInitOffsetFace;
+  Standard_Boolean bFound = Standard_False;
+  TopAbs_ShapeEnum aType = theSWhat.ShapeType();
+  TopExp_Explorer aExp(theSWhere, aType);
+  for (; aExp.More(); aExp.Next()) {
+    const TopoDS_Shape& aS = aExp.Current();
+    if (aS.IsSame(theSWhat)) {
+      theRes = aS;
+      bFound = Standard_True;
+      break;
+    }
+  }
+  return bFound;
 }
 
-//  Modified by skv - Tue Mar 15 16:20:43 2005 Begin
-
 //=======================================================================
-//function : GetJoinType
-//purpose  : Query offset join type.
+//function : UpdateOrigins
+//purpose  : 
 //=======================================================================
-
-GeomAbs_JoinType BRepOffset_MakeOffset::GetJoinType() const
+void UpdateOrigins(TopTools_IndexedDataMapOfShapeListOfShape& theOrigins,
+                   BOPAlgo_Builder& theGF)
 {
-  return myJoin;
+  TopTools_ListOfShape aLSTmp;
+  TopTools_MapOfShape aMFence;
+  BOPCol_ListIteratorOfListOfShape aItA;
+  TopTools_ListIteratorOfListOfShape aIt, aIt1;
+  //
+  const BOPCol_ListOfShape& aLSU = theGF.Arguments();
+  aItA.Initialize(aLSU);
+  for (; aItA.More(); aItA.Next()) {
+    const TopoDS_Shape& aS = aItA.Value();
+    //
+    if (!theOrigins.Contains(aS)) {
+      continue;
+    }
+    //
+    const TopTools_ListOfShape& aLSIm = theGF.Modified(aS);
+    if (aLSIm.IsEmpty()) {
+      continue;
+    }
+    //
+    const TopTools_ListOfShape& aLS = theOrigins.FindFromKey(aS);
+    //      
+    aIt.Initialize(aLSIm);
+    for (; aIt.More(); aIt.Next()) {
+      const TopoDS_Shape& aSIm = aIt.Value();
+      //
+      if (!theOrigins.Contains(aSIm)) {
+        theOrigins.Add(aSIm, aLS);
+        continue;
+      }
+      //
+      aMFence.Clear();
+      //
+      TopTools_ListOfShape& aLS1 = theOrigins.ChangeFromKey(aSIm);
+      aLSTmp.Assign(aLS1);
+      //
+      aLS1.Clear();
+      aIt1.Initialize(aLSTmp);
+      for (; aIt1.More(); aIt1.Next()) {
+        const TopoDS_Shape& aS1 = aIt1.Value();
+        if (aMFence.Add(aS1)) {
+          aLS1.Append(aS1);
+        }
+      }
+      //
+      aIt1.Initialize(aLS);
+      for (; aIt1.More(); aIt1.Next()) {
+        const TopoDS_Shape& aS1 = aIt1.Value();
+        if (aMFence.Add(aS1)) {
+          aLS1.Append(aS1);
+        }
+      }
+    }
+  }
 }
 
 //=======================================================================
-//function : OffsetEdgesFromShapes
+//function : IsMicroEdge
 //purpose  : 
 //=======================================================================
-
-const BRepAlgo_Image& BRepOffset_MakeOffset::OffsetEdgesFromShapes() const
+Standard_Boolean IsMicroEdge(const TopoDS_Edge& theEdge,
+                             const Handle(IntTools_Context)& theCtx,
+                             Standard_Real& theFuzz)
 {
-  return myInitOffsetEdge;
+  TopoDS_Vertex aV1, aV2;
+  TopExp::Vertices(theEdge, aV1, aV2);
+  Standard_Boolean bNull = aV1.IsNull() || aV2.IsNull();
+  if (bNull) {
+    return Standard_False;
+  }
+  //
+  Standard_Boolean bMicro;
+  Standard_Real aT1, aT2;
+  IntTools_ShrunkRange aSR;
+  //
+  BRepAdaptor_Curve aBAC(theEdge);
+  //
+  aT1 = BRep_Tool::Parameter(aV1, theEdge);
+  aT2 = BRep_Tool::Parameter(aV2, theEdge);
+  if (aT2 < aT1) {
+    Standard_Real aTmp = aT1;
+    aT1 = aT2;
+    aT2 = aTmp;
+  }
+  //
+  aSR.SetContext(theCtx);
+  aSR.SetData(theEdge, aT1, aT2, aV1, aV2);
+  aSR.Perform();
+  bMicro = (aSR.ErrorStatus() != 0);
+  if (!bMicro) {
+    Standard_Real anEps, aTS1, aTS2, aTolV1, aTolV2;
+    //
+    aTolV1 = BRep_Tool::Tolerance(aV1);
+    aTolV2 = BRep_Tool::Tolerance(aV2);
+    //
+    anEps = aBAC.Resolution(aTolV1 + aTolV2);
+    if (anEps < 1.e-8) {
+      anEps = 1.e-8;
+    }
+    //
+    aSR.ShrunkRange(aTS1, aTS2);
+    bMicro = (aTS2 - aTS1) <= anEps;
+  }
+  //
+  if (bMicro) {
+    Standard_Real aLen = CPnts_AbscissaPoint::Length(aBAC);
+    if (aLen > theFuzz) {
+      theFuzz = aLen;
+    }
+  }
+  //
+  return bMicro;
 }
 
-//  Modified by skv - Tue Mar 15 16:20:43 2005 End
-
 //=======================================================================
-//function : ClosingFaces
+//function : ComputeBiNormal
 //purpose  : 
 //=======================================================================
-
-const TopTools_IndexedMapOfShape& BRepOffset_MakeOffset::ClosingFaces () const
+Standard_Boolean ComputeBiNormal(const TopoDS_Face& theF,
+                                 const TopoDS_Edge& theE,
+                                 gp_Dir& theDB)
 {
-  return myFaces;
+  Standard_Boolean bDone = Standard_False;
+  Standard_Real aT1, aT2, aTm;
+  //
+  const Handle(Geom2d_Curve)& aC2d = 
+    BRep_Tool::CurveOnSurface(theE, theF, aT1, aT2);
+  if (aC2d.IsNull()) {
+    return bDone;
+  }
+  //
+  gp_Pnt2d aP2dNear;
+  gp_Pnt aP, aPNear;
+  //
+  const Handle(Geom_Curve)& aC3d = 
+    BRep_Tool::Curve(theE, aT1, aT2);
+  //
+  aTm = (aT1 + aT2) * 0.5;
+  aP = aC3d->Value(aTm);
+  //
+  BOPTools_AlgoTools3D::PointNearEdge(theE, theF, aTm, 1.e-5, aP2dNear, aPNear);
+  //
+  gp_Vec aVB(aP, aPNear);
+  theDB = gp_Dir(aVB);
+  return !bDone;
 }
 
-
-
 //=======================================================================
-//function : EncodeRegularity
+//function : CheckBiNormals
 //purpose  : 
 //=======================================================================
-
-void BRepOffset_MakeOffset::EncodeRegularity ()
+Standard_Boolean CheckBiNormals
+  (const TopoDS_Face& aFIm,
+   const TopoDS_Face& aFOr,
+   const TopTools_IndexedDataMapOfShapeListOfShape& theOrigins,
+   const TopTools_MapOfShape& theMFence,
+   Standard_Boolean& bKeep,
+   Standard_Boolean& bRem)
 {
-#ifdef OCCT_DEBUG
-  if (ChronBuild) {  
-    cout << " CODING OF REGULARITIES:" << endl;
-    Clock.Reset();
-    Clock.Start();
-  }
-#endif
-
-  if (myOffsetShape.IsNull()) return;
-  // find edges G1 in the result
-  TopExp_Explorer exp(myOffsetShape,TopAbs_EDGE);
-
-  BRep_Builder B;
-  TopTools_MapOfShape MS;
-
-  for ( ; exp.More(); exp.Next()) {
-    TopoDS_Edge OE  = TopoDS::Edge(exp.Current());
-    BRepLib::BuildCurve3d(OE,myTol);
-    TopoDS_Edge ROE = OE;
-    
-    if ( !MS.Add(OE)) continue;
-      
-    if ( myImageOffset.IsImage(OE)) 
-      ROE = TopoDS::Edge(myImageOffset.Root(OE));
-
-    const TopTools_ListOfShape& LofOF    = myAsDes->Ascendant(ROE);
-    
-    if (LofOF.Extent() != 2) {
-#ifdef OCCT_DEBUG_VERB
-    cout << " Edge shared by " << LofOF.Extent() << " Faces" << endl;
-#endif
-      continue;
-    }
-
-    const TopoDS_Face& F1 = TopoDS::Face(LofOF.First());
-    const TopoDS_Face& F2 = TopoDS::Face(LofOF.Last() );
-    
-    if ( F1.IsNull() || F2.IsNull()) 
-      continue;
-   
-    const TopoDS_Shape& Root1 = myInitOffsetFace.Root(F1);
-    const TopoDS_Shape& Root2 = myInitOffsetFace.Root(F2);
-
-    TopAbs_ShapeEnum Type1 = Root1.ShapeType();
-    TopAbs_ShapeEnum Type2 = Root2.ShapeType();
-    if (F1.IsSame(F2)) {      
-      if (BRep_Tool::IsClosed(OE,F1)) {
-        // Temporary Debug for the Bench.
-        // Check with YFR.
-        // In mode intersection, the edges are not coded in myInitOffsetEdge
-        // so, manage case by case
-        // Note DUB; for Hidden parts, it is NECESSARY to code CN 
-        // Analytic Surfaces.
-        if (myJoin == GeomAbs_Intersection) {
-          BRepAdaptor_Surface BS(F1,Standard_False);
-          GeomAbs_SurfaceType SType = BS.GetType();
-          if (SType == GeomAbs_Cylinder ||
-              SType == GeomAbs_Cone     ||
-              SType == GeomAbs_Sphere   ||
-              SType == GeomAbs_Torus      ) {
-            B.Continuity(OE,F1,F1,GeomAbs_CN);
-          }
-          else {
-            // See YFR : MaJ of myInitOffsetFace
-          }
-        }
-        else if (myInitOffsetEdge.IsImage(ROE)) {
-          if ( Type1 == TopAbs_FACE && Type2 == TopAbs_FACE) {
-            const TopoDS_Face& FRoot = TopoDS::Face(Root1);
-            const TopoDS_Edge& EI = TopoDS::Edge(myInitOffsetEdge.ImageFrom(ROE));
-            GeomAbs_Shape Conti = BRep_Tool::Continuity(EI,FRoot,FRoot);
-            if (Conti == GeomAbs_CN) {
-              B.Continuity(OE,F1,F1,GeomAbs_CN);
-            }
-            else if ( Conti > GeomAbs_C0) {
-              B.Continuity(OE,F1,F1,GeomAbs_G1);
-            }
-          }
-        }
-      }
+  Standard_Boolean bChecked;
+  Standard_Real anAngle;
+  //
+  bKeep = Standard_False;
+  bRem = Standard_True;
+  bChecked = Standard_False;
+  //
+  const TopoDS_Wire& aWIm = BRepTools::OuterWire(aFIm);
+  //
+  TopExp_Explorer aExp(aWIm, TopAbs_EDGE);
+  for (; aExp.More(); aExp.Next()) {
+    const TopoDS_Edge& aEIm = *(TopoDS_Edge*)&aExp.Current();
+    //
+    if (BRep_Tool::Degenerated(aEIm)) {
       continue;
     }
-
-
-    //  code regularities G1 between :
-    //    - sphere and tube : one root is a vertex, the other is an edge 
-    //                        and the vertex is included in the edge
-    //    - face and tube   : one root is a face, the other an edge 
-    //                        and the edge is included in the face
-    //    - face and face    : if two root faces are tangent in 
-    //                        the initial shape, they will be tangent in the offset shape
-    //    - tube and tube  : if 2 edges generating tubes are
-    //                        tangents, the 2 will be tangent either.
-    if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_VERTEX) {
-      TopoDS_Vertex V1,V2;
-      TopExp::Vertices(TopoDS::Edge(Root1), V1, V2);
-      if ( V1.IsSame(Root2) || V2.IsSame(Root2)) {
-        B.Continuity(OE,F1,F2,GeomAbs_G1);
-      }
+    //
+    if (!theOrigins.Contains(aEIm)) {
+      continue;
     }
-    else if ( Type1 == TopAbs_VERTEX && Type2 == TopAbs_EDGE) {
-      TopoDS_Vertex V1,V2;
-      TopExp::Vertices(TopoDS::Edge(Root2), V1, V2);
-      if ( V1.IsSame(Root1) || V2.IsSame(Root1)) {
-        B.Continuity(OE,F1,F2,GeomAbs_G1);
-      }
+    //
+    const TopTools_ListOfShape& aLEOr = theOrigins.FindFromKey(aEIm);
+    const TopoDS_Shape& aSOr = aLEOr.First();
+    if (aSOr.ShapeType() != TopAbs_EDGE) {
+      bRem = Standard_False;
+      continue;
     }
-    else if ( Type1 == TopAbs_FACE && Type2 == TopAbs_EDGE) {
-      TopExp_Explorer exp2(Root1,TopAbs_EDGE);
-      for ( ; exp2.More(); exp2.Next()) {
-        if ( exp2.Current().IsSame(Root2)) {
-          B.Continuity(OE,F1,F2,GeomAbs_G1);
-          break;
+    //
+    if (aLEOr.Extent() > 1) {
+      TopTools_MapOfShape aME, aMV;
+      Standard_Integer aNbE, aNbV;
+      //
+      TopTools_ListIteratorOfListOfShape aItLS(aLEOr);
+      for (; aItLS.More(); aItLS.Next()) {
+        const TopoDS_Edge& aEOr = *(TopoDS_Edge*)&aItLS.Value();
+        aME.Add(aEOr);
+        //
+        TopExp_Explorer aExpE(aEOr, TopAbs_VERTEX);
+        for (; aExpE.More(); aExpE.Next()) {
+          const TopoDS_Shape& aV = aExpE.Current();
+          aMV.Add(aV);
         }
       }
-    }
-    else if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_FACE) {
-      TopExp_Explorer exp2(Root2,TopAbs_EDGE);
-      for ( ; exp2.More(); exp2.Next()) {
-        if ( exp2.Current().IsSame(Root1)) {
-          B.Continuity(OE,F1,F2,GeomAbs_G1);
-          break;
-        }
+      //
+      aNbV = aMV.Extent();
+      aNbE = aME.Extent();
+      //
+      if ((aNbE > 1) && (aNbV == 2*aNbE)) {
+        continue;
       }
     }
-    else if ( Type1 == TopAbs_FACE && Type2 == TopAbs_FACE) {
-    //  if two root faces are tangent in 
-    //  the initial shape, they will be tangent in the offset shape
-      TopTools_ListOfShape LE,LV;
-      BRepOffset_Tool::HasCommonShapes(TopoDS::Face(Root1),
-                                       TopoDS::Face(Root2),
-                                       LE,LV);
-      if ( LE.Extent() == 1) { 
-        const TopoDS_Edge& Ed = TopoDS::Edge(LE.First());
-        if ( myAnalyse.HasAncestor(Ed)) {
-          const BRepOffset_ListOfInterval& LI = myAnalyse.Type(Ed);
-          if (LI.Extent()       == 1   && 
-              LI.First().Type() == BRepOffset_Tangent) {
-            B.Continuity(OE,F1,F2,GeomAbs_G1);
-          }
-        }
-      }
+    //
+    if (theMFence.Contains(aEIm)) {
+      bChecked = Standard_True;
+      bKeep = Standard_True;
+      bRem = Standard_False;
+      break;
+    }      
+    //
+    const TopoDS_Edge& aEOr = *(TopoDS_Edge*)&aLEOr.First();
+    //
+    TopoDS_Edge aEOrF;
+    if (!FindShape(aEOr, aFOr, aEOrF)) {
+      continue;
     }
-    else if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_EDGE) {
-      TopTools_ListOfShape LV;
-      TopExp_Explorer exp1,exp2;
-      for (exp1.Init(Root1,TopAbs_VERTEX); exp1.More(); exp1.Next()) {
-        TopExp_Explorer exp2(F2,TopAbs_EDGE);
-        for (exp2.Init(Root2,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
-          if (exp1.Current().IsSame(exp2.Current())) {
-            LV.Append(exp1.Current());
-          }
-        }
-      }
-      if ( LV.Extent() == 1) {
-        TopTools_ListOfShape LEdTg;
-        myAnalyse.TangentEdges(TopoDS::Edge(Root1),
-                               TopoDS::Vertex(LV.First()),
-                               LEdTg);
-        TopTools_ListIteratorOfListOfShape it(LEdTg);
-        for (; it.More(); it.Next()) {
-          if ( it.Value().IsSame(Root2)) {
-            B.Continuity(OE,F1,F2,GeomAbs_G1);
-            break;
-          }
-        }
-      }
+    //
+    // compute bi-normal for face aFIm on the edge aEIm
+    gp_Dir aDB1;
+    if (!ComputeBiNormal(aFIm, aEIm, aDB1)) {
+      continue;
+    }
+    //
+    // compute bi-normal for face aFOr on the edge aEOrF
+    gp_Dir aDB2;
+    if (!ComputeBiNormal(aFOr, aEOrF, aDB2)) {
+      continue;
+    }
+    //
+    bChecked = Standard_True;
+    // check coincidence of bi-normals
+    anAngle = aDB1.Angle(aDB2);
+    if (Abs(anAngle - M_PI) < Precision::Confusion()) {
+      bRem = bRem && Standard_True;
+    }
+    else {
+      bRem = Standard_False;
+      bKeep = Standard_True;
+      break;
     }
   }
-
-#ifdef OCCT_DEBUG
-  if ( ChronBuild) Clock.Show();
-#endif
+  //
+  return bChecked;
 }
 
-
-
 //=======================================================================
-//function : UpDateTolerance
+//function : CheckBiNormals
 //purpose  : 
 //=======================================================================
-
-static void UpdateTolerance (TopoDS_Shape& S,
-                             const TopTools_IndexedMapOfShape& Faces)
+void CheckBiNormals
+  (TopTools_ListOfShape&  theLFImages,
+   const TopoDS_Face& theF,
+   const TopTools_IndexedDataMapOfShapeListOfShape& theOrigins,
+   TopTools_ListOfShape& theLFKeep)
 {
-  BRep_Builder B;
-  TopTools_MapOfShape View;
-  TopoDS_Vertex V[2];
-
-  // The edges of caps are not modified.
-  Standard_Integer j;
-  for (j = 1; j <= Faces.Extent(); j++) {
-    const TopoDS_Shape& F = Faces(j);
-    TopExp_Explorer Exp;
-    for (Exp.Init(F,TopAbs_EDGE); Exp.More(); Exp.Next()) {
-      View.Add(Exp.Current());
+  Standard_Boolean bChecked, bKeep, bRem;
+  Standard_Integer i, aNb;
+  TopTools_ListOfShape aLFKeep;
+  TopTools_MapOfShape aMEToKeep;
+  TopTools_IndexedDataMapOfShapeListOfShape aDMELF;
+  TopTools_ListIteratorOfListOfShape aItLF;
+  //
+  // collect outer edges
+  aItLF.Initialize(theLFImages);
+  for (; aItLF.More(); aItLF.Next()) {
+    const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
+    TopExp::MapShapesAndAncestors(aFIm, TopAbs_EDGE, TopAbs_FACE, aDMELF);
+  }
+  //
+  aNb = aDMELF.Extent();
+  for (i = 1; i <= aNb; ++i) {
+    const TopTools_ListOfShape& aLF = aDMELF(i);
+    if (aLF.Extent() == 1) {
+      const TopoDS_Shape& aE = aDMELF.FindKey(i);
+      aMEToKeep.Add(aE);
     }
   }
-  
-  TopExp_Explorer Exp;
-  for (Exp.Init(S,TopAbs_EDGE); Exp.More(); Exp.Next()) {
-    TopoDS_Edge E = TopoDS::Edge(Exp.Current());
-    if (View.Add(E)) {
-      Handle(BRepCheck_Edge) EdgeCorrector = new BRepCheck_Edge(E);
-      Standard_Real    Tol = EdgeCorrector->Tolerance();
-      B.UpdateEdge (E,Tol);
-      
-      // Update the vertices.
-      TopExp::Vertices(E,V[0],V[1]);
-     
-      for (Standard_Integer i = 0 ; i <=1 ; i++) {
-        if (View.Add(V[i])) {
-          Handle(BRep_TVertex) TV = Handle(BRep_TVertex)::DownCast(V[i].TShape());
-          TV->Tolerance(0.);
-          Handle(BRepCheck_Vertex) VertexCorrector = new BRepCheck_Vertex(V[i]);
-          B.UpdateVertex (V[i],VertexCorrector->Tolerance());
-          // use the occasion to clean the vertices.
-          (TV->ChangePoints()).Clear();
+  //
+  const TopoDS_Face& aFOr = *(TopoDS_Face*)&theOrigins.FindFromKey(theF).First();
+  //
+  aItLF.Initialize(theLFImages);
+  for (; aItLF.More(); ) {
+    const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
+    //
+    bChecked = CheckBiNormals(aFIm, aFOr, theOrigins, aMEToKeep, bKeep, bRem);
+    //
+    if (bChecked) {
+      if (bRem) {
+        theLFImages.Remove(aItLF);
+      }
+      else {
+        if (bKeep) {
+          theLFKeep.Append(aFIm);
         }
-        B.UpdateVertex(V[i],Tol);
+        aItLF.Next();
       }
     }
+    else {
+      aItLF.Next();
+    }
+  }
+}
+
+//=======================================================================
+//function : CheckNormals
+//purpose  : 
+//=======================================================================
+Standard_Boolean CheckNormals(const TopoDS_Face& theFIm,
+                              const TopoDS_Face& theFOr)
+{
+  
+  Standard_Real aUMin, aUMax, aVMin, aVMax, aU, aV, anAngle;
+  gp_Pnt aP;
+  gp_Vec aVecU, aVecV, aVNIm, aVNOr;
+  Standard_Boolean bIsCollinear;
+  //
+  BRepAdaptor_Surface aSFIm(theFIm), aSFOr(theFOr);
+  //
+  aUMin = aSFIm.FirstUParameter();
+  aUMax = aSFIm.LastUParameter();
+  aVMin = aSFIm.FirstVParameter();
+  aVMax = aSFIm.LastVParameter();
+  //
+  aU = (aUMin + aUMax) * 0.5;
+  if (Precision::IsInfinite(aUMin) && 
+      Precision::IsInfinite(aUMax)) {
+    aU = 0.;
+  }
+  else if (Precision::IsInfinite(aUMin) && 
+           !Precision::IsInfinite(aUMax)) {
+    aU = aUMax;
+  }
+  else if (!Precision::IsInfinite(aUMin) && 
+           Precision::IsInfinite(aUMax)) {
+    aU = aUMin;
+  }
+  //
+  aV = (aVMin + aVMax) * 0.5;
+  if (Precision::IsInfinite(aVMin) && 
+      Precision::IsInfinite(aVMax)) {
+    aV = 0.;
+  }
+  else if (Precision::IsInfinite(aVMin) && 
+           !Precision::IsInfinite(aVMax)) {
+    aV = aVMax;
+  }
+  else if (!Precision::IsInfinite(aVMin) && 
+           Precision::IsInfinite(aVMax)) {
+    aV = aVMin;
   }
+  //
+  aSFIm.D1(aU, aV, aP, aVecU, aVecV);
+  aVNIm = aVecU.Crossed(aVecV);
+  if (theFIm.Orientation() == TopAbs_REVERSED) {
+    aVNIm.Reverse();
+  }
+  //
+  aSFOr.D1(aU, aV, aP, aVecU, aVecV);
+  aVNOr = aVecU.Crossed(aVecV);
+  if (theFOr.Orientation() == TopAbs_REVERSED) {
+    aVNOr.Reverse();
+  }
+  //
+  anAngle = aVNIm.Angle(aVNOr);
+  bIsCollinear = (anAngle < Precision::Confusion());
+  return bIsCollinear;
 }
 
+//=======================================================================
+//function : UpdateInitOffset
+//purpose  : Update and cleaning of myInitOffset 
+//=======================================================================
+void UpdateInitOffset(BRepAlgo_Image&         myInitOffset,
+                      BRepAlgo_Image&         myImageOffset,
+                      const TopoDS_Shape&     myOffsetShape,
+                      const TopAbs_ShapeEnum &theShapeType) // skv
+{
+  BRepAlgo_Image NIOF;
+  const TopTools_ListOfShape& Roots = myInitOffset.Roots();
+  TopTools_ListIteratorOfListOfShape it(Roots);
+  for (; it.More(); it.Next()) {
+    NIOF.SetRoot (it.Value());    
+  }
+  for (it.Initialize(Roots); it.More(); it.Next()) {
+    const TopoDS_Shape& SI = it.Value();
+    TopTools_ListOfShape LI;
+    TopTools_ListOfShape L1;
+    myInitOffset.LastImage(SI,L1);
+    TopTools_ListIteratorOfListOfShape itL1(L1);
+    for (; itL1.More(); itL1.Next()) {
+      const TopoDS_Shape& O1 = itL1.Value();
+      TopTools_ListOfShape L2;
+      myImageOffset.LastImage(O1,L2);
+      LI.Append(L2);
+    }
+    NIOF.Bind(SI,LI);
+  }
+//  Modified by skv - Mon Apr  4 18:17:27 2005 Begin
+//  Supporting history.
+//   NIOF.Filter(myOffsetShape,TopAbs_FACE);
+  NIOF.Filter(myOffsetShape, theShapeType);
+//  Modified by skv - Mon Apr  4 18:17:27 2005 End
+  myInitOffset = NIOF;
+}