0026555: Modeling Algorithms - Exception-safe status reporting in BRepOffset_MakeOffset
[occt.git] / src / BRepOffset / BRepOffset_MakeOffset.cxx
index 9539271..2c3077f 100644 (file)
 #include <TopTools_MapIteratorOfMapOfShape.hxx>
 #include <TopTools_MapOfShape.hxx>
 #include <TopTools_SequenceOfShape.hxx>
+#include <BRepBuilderAPI_Sewing.hxx>
+#include <Geom_Line.hxx>
+#include <NCollection_Vector.hxx>
+#include <NCollection_IncAllocator.hxx>
+//
+#include <BOPAlgo_MakerVolume.hxx>
+#include <BOPTools_AlgoTools.hxx>
 
 #include <stdio.h>
 // POP for NT
 //=======================================================================
 
 static void DEBVerticesControl (const TopTools_IndexedMapOfShape& NewEdges,
-                                     Handle(BRepAlgo_AsDes)      AsDes)
+                                      Handle(BRepAlgo_AsDes)      AsDes)
 {
   TopTools_ListOfShape               LVP;
   TopTools_ListIteratorOfListOfShape it1LE ;    
@@ -150,34 +157,34 @@ static void DEBVerticesControl (const TopTools_IndexedMapOfShape& NewEdges,
     const TopoDS_Edge& NE = TopoDS::Edge(NewEdges(i));
     if (AsDes->HasDescendant(NE)) {
       for (it1LE.Initialize(AsDes->Descendant(NE)); it1LE.More(); it1LE.Next()) {
-       if (AsDes->Ascendant(it1LE.Value()).Extent() < 3) {
-         LVP.Append(it1LE.Value());
-         cout <<"Vertex on at least 3 edges."<<endl;
+        if (AsDes->Ascendant(it1LE.Value()).Extent() < 3) {
+          LVP.Append(it1LE.Value());
+          std::cout <<"Vertex on at least 3 edges."<<std::endl;
 #ifdef DRAW
-         if (AffichInt2d) {
-           sprintf (name,"VP_%d",NVP++);
-           DBRep::Set(name,it1LE.Value());
-         }
+          if (AffichInt2d) {
+            sprintf (name,"VP_%d",NVP++);
+            DBRep::Set(name,it1LE.Value());
+          }
 #endif
-       }
-       else if (AsDes->Ascendant(it1LE.Value()).Extent() > 3) {
-         cout <<"Vertex on more than 3 edges."<<endl;
+        }
+        else if (AsDes->Ascendant(it1LE.Value()).Extent() > 3) {
+          std::cout <<"Vertex on more than 3 edges."<<std::endl;
 #ifdef DRAW
-         if (AffichInt2d) {
-           sprintf (name,"VM_%d",NVM++);
-           DBRep::Set(name,it1LE.Value());
-         }
+          if (AffichInt2d) {
+            sprintf (name,"VM_%d",NVM++);
+            DBRep::Set(name,it1LE.Value());
+          }
 #endif
-         
-       }
-       else {
+          
+        }
+        else {
 #ifdef DRAW
-         if (AffichInt2d) {
-           sprintf (name,"VN_%d",NVN++);
-           DBRep::Set(name,it1LE.Value());
-         }
+          if (AffichInt2d) {
+            sprintf (name,"VN_%d",NVN++);
+            DBRep::Set(name,it1LE.Value());
+          }
 #endif
-       }
+        }
       }
     }
   }
@@ -200,49 +207,144 @@ static void DEBVerticesControl (const TopTools_IndexedMapOfShape& NewEdges,
 
     for ( ; it2.More(); it2.Next()) {
       if (j > i) {
-       TopoDS_Shape V2 = it2.Value();
-       gp_Pnt       P2 = BRep_Tool::Pnt(TopoDS::Vertex(V2));
-       if (!V1.IsSame(V2)) {
-         Standard_Real       dist    = P1.Distance(P2);
-         if (dist < distmin) distmin = dist;
-         if (dist < TolConf) {
-           Standard_Real UV2;
-           TopoDS_Edge   EWE2;
-           const TopTools_ListOfShape& EdgeWithV2 = AsDes->Ascendant(V2);
-           TopTools_ListIteratorOfListOfShape itAsDes;
-           for (itAsDes.Initialize(EdgeWithV2); itAsDes.More(); itAsDes.Next()) {
-             EWE2  = TopoDS::Edge(itAsDes.Value());
-             TopoDS_Shape aLocalShape = V2.Oriented(TopAbs_INTERNAL);
-             UV2   = BRep_Tool::Parameter(TopoDS::Vertex(aLocalShape),EWE2);
-             aLocalShape = V1.Oriented(TopAbs_INTERNAL) ;
-             B.UpdateVertex(TopoDS::Vertex(aLocalShape),UV2,EWE2,Tol);
-//           UV2   = 
-//             BRep_Tool::Parameter(TopoDS::Vertex(),EWE2);
-//           B.UpdateVertex(TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)),
-//                          UV2,EWE2,Tol);
-           }
-           AsDes->Replace(V2,V1);
-         }
-       }
+        TopoDS_Shape V2 = it2.Value();
+        gp_Pnt       P2 = BRep_Tool::Pnt(TopoDS::Vertex(V2));
+        if (!V1.IsSame(V2)) {
+          Standard_Real       dist    = P1.Distance(P2);
+          if (dist < distmin) distmin = dist;
+          if (dist < TolConf) {
+            Standard_Real UV2;
+            TopoDS_Edge   EWE2;
+            const TopTools_ListOfShape& EdgeWithV2 = AsDes->Ascendant(V2);
+            TopTools_ListIteratorOfListOfShape itAsDes;
+            for (itAsDes.Initialize(EdgeWithV2); itAsDes.More(); itAsDes.Next()) {
+              EWE2  = TopoDS::Edge(itAsDes.Value());
+              TopoDS_Shape aLocalShape = V2.Oriented(TopAbs_INTERNAL);
+              UV2   = BRep_Tool::Parameter(TopoDS::Vertex(aLocalShape),EWE2);
+              aLocalShape = V1.Oriented(TopAbs_INTERNAL) ;
+              B.UpdateVertex(TopoDS::Vertex(aLocalShape),UV2,EWE2,Tol);
+//              UV2   = 
+//                BRep_Tool::Parameter(TopoDS::Vertex(),EWE2);
+//              B.UpdateVertex(TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)),
+//                             UV2,EWE2,Tol);
+            }
+            AsDes->Replace(V2,V1);
+          }
+        }
       }
       j++;
     }
     i++;
-    cout <<" distmin between VP : "<<distmin<<endl;
+    std::cout <<" distmin between VP : "<<distmin<<std::endl;
   }
 }  
 #endif
 
+
+//=======================================================================
+// static methods
+//=======================================================================
+static
+  void GetEnlargedFaces(const TopTools_ListOfShape& theFaces,
+                        const BRepOffset_DataMapOfShapeOffset& theMapSF,
+                        const TopTools_DataMapOfShapeShape& theMES,
+                        TopTools_DataMapOfShapeShape& theFacesOrigins,
+                        BRepAlgo_Image& theImage,
+                        TopTools_ListOfShape& theLSF);
+
+static
+  Standard_Boolean BuildShellsCompleteInter(const TopTools_ListOfShape& theLF,
+                                            BRepAlgo_Image& theImage,
+                                            TopoDS_Shape& theShells);
+
+static
+  Standard_Boolean GetSubShapes(const TopoDS_Shape& theShape,
+                                const TopAbs_ShapeEnum theSSType,
+                                TopoDS_Shape& theResult);
+
+static 
+  void UpdateInitOffset(BRepAlgo_Image&         myInitOffset,
+                        BRepAlgo_Image&         myImageOffset,
+                        const TopoDS_Shape&     myOffsetShape,
+                        const TopAbs_ShapeEnum &theShapeType);
+
+static 
+  void RemoveShapes(TopoDS_Shape& theS,
+                    const TopTools_ListOfShape& theLS);
+
+static 
+  Standard_Boolean IsSolid(const TopoDS_Shape& theS);
+
+static 
+  void UpdateHistory(const TopTools_ListOfShape& theLF,
+                     BOPAlgo_Builder& theGF,
+                     BRepAlgo_Image& theImage);
+
+static
+  Standard_Boolean IsPlanar(const TopoDS_Shape& theS);
+
+static
+  Standard_Boolean TrimEdge(TopoDS_Edge& NE,
+                            const Handle(BRepAlgo_AsDes)& AsDes2d,
+                            Handle(BRepAlgo_AsDes)& AsDes,
+                            TopTools_DataMapOfShapeShape& theETrimEInf);
+
+static 
+  Standard_Boolean TrimEdges(const TopoDS_Shape& theShape,
+                             const Standard_Real theOffset,
+                             const BRepOffset_Analyse& Analyse,
+                             BRepOffset_DataMapOfShapeOffset& theMapSF,
+                             TopTools_DataMapOfShapeShape& theMES,
+                             TopTools_DataMapOfShapeShape& theBuild,
+                             Handle(BRepAlgo_AsDes)& theAsDes,
+                             Handle(BRepAlgo_AsDes)& theAsDes2d,
+                             TopTools_IndexedMapOfShape& theNewEdges,
+                             TopTools_DataMapOfShapeShape& theETrimEInf,
+                             TopTools_DataMapOfShapeListOfShape& theEdgesOrigins);
+
+static
+  void AppendToList(TopTools_ListOfShape& theL,
+                    const TopoDS_Shape& theS);
+
+static BRepOffset_Error checkSinglePoint(const Standard_Real theUParam,
+                                         const Standard_Real theVParam,
+                                         const Handle(Geom_Surface)& theSurf,
+                                         const NCollection_Vector<gp_Pnt>& theBadPoints);
+
 //---------------------------------------------------------------------
 static void UpdateTolerance (      TopoDS_Shape&               myShape,
-                            const TopTools_IndexedMapOfShape& myFaces);
+                             const TopTools_IndexedMapOfShape& myFaces);
+static Standard_Real ComputeMaxDist(const gp_Pln& thePlane, 
+                                    const Handle(Geom_Curve)& theCrv,
+                                    const Standard_Real theFirst,
+                                    const Standard_Real theLast);
 
 static void CorrectSolid(TopoDS_Solid& theSol, TopTools_ListOfShape& theSolList);
 //---------------------------------------------------------------------
+
+static TopAbs_Orientation OrientationOfEdgeInFace(const TopoDS_Edge& theEdge,
+                                                  const TopoDS_Face& theFace)
+{
+  TopAbs_Orientation anOr = TopAbs_EXTERNAL;
+  
+  TopExp_Explorer Explo(theFace, TopAbs_EDGE);
+  for (; Explo.More(); Explo.Next())
+  {
+    const TopoDS_Shape& anEdge = Explo.Current();
+    if (anEdge.IsSame(theEdge))
+    {
+      anOr = anEdge.Orientation();
+      break;
+    }
+  }
+
+  return anOr;
+}
+
 //
 static Standard_Boolean FindParameter(const TopoDS_Vertex& V, 
-                                     const TopoDS_Edge& E,
-                                     Standard_Real& U)
+                                      const TopoDS_Edge& E,
+                                      Standard_Real& U)
 {
   // Search the vertex in the edge
 
@@ -264,13 +366,13 @@ static Standard_Boolean FindParameter(const TopoDS_Vertex& V,
     const TopoDS_Shape& Vcur = itv.Value();
     if (V.IsSame(Vcur)) {
       if (VF.IsNull()) {
-       VF = Vcur;
+        VF = Vcur;
       }
       else {
-       rev = E.Orientation() == TopAbs_REVERSED;
-       if (Vcur.Orientation() == V.Orientation()) {
-         VF = Vcur;
-       }
+        rev = E.Orientation() == TopAbs_REVERSED;
+        if (Vcur.Orientation() == V.Orientation()) {
+          VF = Vcur;
+        }
       }
     }
     itv.Next();
@@ -300,42 +402,42 @@ static Standard_Boolean FindParameter(const TopoDS_Vertex& V,
     L = L.Predivided(V.Location());
     if (!C.IsNull() || BRep_Tool::Degenerated(E)) {
       BRep_ListIteratorOfListOfPointRepresentation itpr
-       ((*((Handle(BRep_TVertex)*) &V.TShape()))->Points());
+        ((*((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();
+        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 {
@@ -346,30 +448,30 @@ static Standard_Boolean FindParameter(const TopoDS_Vertex& V,
       BRep_Tool::CurveOnSurface(E,PC,S,L,f,l);
       L = L.Predivided(V.Location()); 
       BRep_ListIteratorOfListOfPointRepresentation itpr
-       ((*((Handle(BRep_TVertex)*) &V.TShape()))->Points());
+        ((*((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();
+        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");
+  //throw Standard_NoSuchObject("BRep_Tool:: no parameter on edge");
   return Standard_False;
 }
 
@@ -398,9 +500,9 @@ static void GetEdgePoints(const TopoDS_Edge& anEdge,
 //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)
+                         const BRepOffset_Analyse& Analyser,
+                         TopTools_IndexedDataMapOfShapeListOfShape& Contours,
+                         TopTools_DataMapOfShapeShape& MapEF)
 {
   TopTools_ListOfShape Edges;
 
@@ -408,26 +510,26 @@ static void FillContours(const TopoDS_Shape& aShape,
   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_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);
-               }
-           }
-       }
+      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() == ChFiDS_FreeBound)
+        {
+          MapEF.Bind(anEdge, aFace);
+          Edges.Append(anEdge);
+        }
+      }
     }
+  }
 
   TopTools_ListIteratorOfListOfShape itl;
   while (!Edges.IsEmpty())
@@ -439,24 +541,23 @@ static void FillContours(const TopoDS_Shape& aShape,
       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);
+        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.Add(StartVertex, aContour);
     }
 }
 
-
 //
 //-----------------------------------------------------------------------
 //
@@ -477,13 +578,14 @@ BRepOffset_MakeOffset::BRepOffset_MakeOffset()
 //=======================================================================
 
 BRepOffset_MakeOffset::BRepOffset_MakeOffset(const TopoDS_Shape&    S, 
-                                            const Standard_Real    Offset, 
-                                            const Standard_Real    Tol, 
-                                            const BRepOffset_Mode  Mode, 
-                                            const Standard_Boolean Inter, 
-                                            const Standard_Boolean SelfInter, 
-                                            const GeomAbs_JoinType Join,
-                                            const Standard_Boolean Thickening)
+                                             const Standard_Real    Offset, 
+                                             const Standard_Real    Tol, 
+                                             const BRepOffset_Mode  Mode, 
+                                             const Standard_Boolean Inter, 
+                                             const Standard_Boolean SelfInter, 
+                                             const GeomAbs_JoinType Join,
+                                             const Standard_Boolean Thickening,
+                                             const Standard_Boolean RemoveIntEdges)
 : 
 myOffset     (Offset),
 myTol        (Tol),
@@ -492,9 +594,9 @@ myMode       (Mode),
 myInter      (Inter),
 mySelfInter  (SelfInter),
 myJoin       (Join),
-myThickening (Thickening),
+myThickening    (Thickening),
+myRemoveIntEdges(RemoveIntEdges),
 myDone     (Standard_False)
-
 {
   myAsDes = new BRepAlgo_AsDes();
   MakeOffsetShape();
@@ -507,13 +609,14 @@ myDone     (Standard_False)
 //=======================================================================
 
 void BRepOffset_MakeOffset::Initialize(const TopoDS_Shape&    S, 
-                                      const Standard_Real    Offset, 
-                                      const Standard_Real    Tol, 
-                                      const BRepOffset_Mode  Mode,
-                                      const Standard_Boolean Inter,
-                                      const Standard_Boolean SelfInter,
-                                      const GeomAbs_JoinType Join,
-                                      const Standard_Boolean Thickening)
+                                       const Standard_Real    Offset, 
+                                       const Standard_Real    Tol, 
+                                       const BRepOffset_Mode  Mode,
+                                       const Standard_Boolean Inter,
+                                       const Standard_Boolean SelfInter,
+                                       const GeomAbs_JoinType Join,
+                                       const Standard_Boolean Thickening,
+                                       const Standard_Boolean RemoveIntEdges)
 {
   myOffset     = Offset;
   myShape      = S;
@@ -522,8 +625,11 @@ void BRepOffset_MakeOffset::Initialize(const TopoDS_Shape&    S,
   myInter      = Inter;
   mySelfInter  = SelfInter;
   myJoin       = Join;
-  myThickening = Thickening;
+  myThickening     = Thickening;
+  myRemoveIntEdges = RemoveIntEdges;
   myDone     = Standard_False;
+  myIsPerformSewing = Standard_False;
+  myIsPlanar = Standard_False;
   Clear();
 }
 
@@ -543,6 +649,8 @@ void BRepOffset_MakeOffset::Clear()
   myFaceOffset     .Clear();
   myAsDes          ->Clear();
   myDone     = Standard_False;
+  myGenerated.Clear();
+  myResMap.Clear();
 }
 
 //=======================================================================
@@ -566,7 +674,7 @@ void BRepOffset_MakeOffset::AddFace(const TopoDS_Face& F) {
 //=======================================================================
 
 void BRepOffset_MakeOffset::SetOffsetOnFace(const TopoDS_Face&  F, 
-                                           const Standard_Real Off)
+                                            const Standard_Real Off)
 {
   if ( myFaceOffset.IsBound(F)) myFaceOffset.UnBind(F);
   myFaceOffset.Bind(F,Off);
@@ -578,7 +686,7 @@ void BRepOffset_MakeOffset::SetOffsetOnFace(const TopoDS_Face&  F,
 //=======================================================================
 
 static void RemoveCorks (TopoDS_Shape&               S,
-                        TopTools_IndexedMapOfShape& Faces)
+                         TopTools_IndexedMapOfShape& Faces)
 {  
   TopoDS_Compound SS;
   BRep_Builder    B;
@@ -594,13 +702,7 @@ static void RemoveCorks (TopoDS_Shape&               S,
       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.RemoveKey(Cork);
       Faces.Add(Cork); // to reset it with proper orientation.
     }
   }
@@ -612,6 +714,10 @@ static void RemoveCorks (TopoDS_Shape&               S,
 
 }
 
+//=======================================================================
+//function : IsConnectedShell
+//purpose  : 
+//=======================================================================
 static Standard_Boolean IsConnectedShell( const TopoDS_Shape& S )
 {  
   BRepTools_Quilt Glue;
@@ -633,14 +739,20 @@ static Standard_Boolean IsConnectedShell( const TopoDS_Shape& S )
 //=======================================================================
 
 static void MakeList (TopTools_ListOfShape&             OffsetFaces,
-                     const BRepAlgo_Image&             myInitOffsetFace,
-                     const TopTools_IndexedMapOfShape& myFaces)
+                      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 (!myFaces.Contains(Root))
-      OffsetFaces.Append(myInitOffsetFace.Image(Root).First());
+    if (!myFaces.Contains(Root)) {
+      if (myInitOffsetFace.HasImage(Root)) {
+        TopTools_ListIteratorOfListOfShape aItLS(myInitOffsetFace.Image(Root));
+        for (; aItLS.More(); aItLS.Next()) {
+          OffsetFaces.Append(aItLS.Value());
+        }
+      }
+    }
   }
 }
 
@@ -659,6 +771,7 @@ static void EvalMax(const TopoDS_Shape& S, Standard_Real& Tol)
   }
 }
 
+
 //=======================================================================
 //function : MakeOffsetShape
 //purpose  : 
@@ -666,7 +779,10 @@ static void EvalMax(const TopoDS_Shape& S, Standard_Real& Tol)
 
 void BRepOffset_MakeOffset::MakeOffsetShape()
 {  
-  myDone     = Standard_False;
+  myDone = Standard_False;
+  //
+  // check if shape consists of only planar faces
+  myIsPlanar = IsPlanar(myShape);
   //------------------------------------------
   // Construction of myShape without caps.
   //------------------------------------------
@@ -674,21 +790,29 @@ void BRepOffset_MakeOffset::MakeOffsetShape()
   {
     RemoveCorks (myShape,myFaces);
   }
-  
-  if (! IsConnectedShell(myShape))
-    Standard_ConstructionError::Raise("BRepOffset_MakeOffset : Incorrect set of faces to remove, the remaining shell is not connected");
-
-  if (Abs(myOffset) < myTol) return;
 
+  if (!CheckInputData())
+  {
+    // There is error in input data.
+    // Check Error() method.
+    return;
+  }
+  myError = BRepOffset_NoError;
   TopAbs_State       Side = TopAbs_IN;
   if (myOffset < 0.) Side = TopAbs_OUT;
+
   // ------------
   // Preanalyse.
   // ------------
   EvalMax(myShape,myTol);
   // There are possible second variant: analytical continuation of arcsin.
-  Standard_Real TolAngleCoeff = Min(myTol/Abs(myOffset*0.5), 1.0);
+  Standard_Real TolAngleCoeff = Min(myTol / (Abs(myOffset * 0.5) + Precision::Confusion()), 1.0);
   Standard_Real TolAngle = 4*ASin(TolAngleCoeff);
+  if ((myJoin == GeomAbs_Intersection) && myInter && myIsPlanar)
+  {
+    myAnalyse.SetOffsetValue (myOffset);
+    myAnalyse.SetFaceOffsetMap (myFaceOffset);
+  }
   myAnalyse.Perform(myShape,TolAngle);
   //---------------------------------------------------
   // Construction of Offset from preanalysis.
@@ -702,6 +826,10 @@ void BRepOffset_MakeOffset::MakeOffsetShape()
     BuildOffsetByArc();
   else if (myJoin == GeomAbs_Intersection) 
     BuildOffsetByInter();
+  if (myError != BRepOffset_NoError)
+  {
+    return;
+  }
   //-----------------
   // Auto unwinding.
   //-----------------
@@ -735,14 +863,29 @@ void BRepOffset_MakeOffset::MakeOffsetShape()
   // Construction of shells.
   //-------------------------
   MakeShells ();
+  if (myOffsetShape.IsNull()) {
+    // not done
+    myDone = Standard_False;
+    return;
+  }
   //--------------
   // Unwinding 3D.
   //--------------
   SelectShells ();
   //----------------------------------
+  // Remove INTERNAL edges if necessary
+  //----------------------------------
+  if (myRemoveIntEdges) {
+    RemoveInternalEdges();
+  }
+  //----------------------------------
   // Coding of regularities.
   //----------------------------------
   EncodeRegularity();
+  //----------------------------------
+  // Replace roots in history maps
+  //----------------------------------
+  ReplaceRoots();
   //----------------------
   // Creation of solids.
   //----------------------
@@ -758,6 +901,21 @@ void BRepOffset_MakeOffset::MakeOffsetShape()
 
   CorrectConicalFaces();
 
+  // Result solid should be computed in MakeOffset scope.
+  if (myThickening &&
+      myIsPerformSewing)
+  {
+    BRepBuilderAPI_Sewing aSew(myTol);
+    aSew.Add(myOffsetShape);
+    aSew.Perform();
+    myOffsetShape = aSew.SewedShape();
+
+    // Rebuild solid.
+    // Offset shape expected to be really closed after sewing.
+    myOffsetShape.Closed(Standard_True);
+    MakeSolid();
+  }
+
   myDone = Standard_True;
 }
 
@@ -775,11 +933,18 @@ void BRepOffset_MakeOffset::MakeThickSolid()
   //--------------------------------------------------------------
   MakeOffsetShape ();
 
+  if (!myDone)
+  {
+    // Save return code and myDone state.
+    return;
+  }
+
   //--------------------------------------------------------------------
   // Construction of a solid with the initial shell, parallel shell 
   // limited by caps.
   //--------------------------------------------------------------------
-  if (!myFaces.IsEmpty()) {
+  if (!myFaces.IsEmpty())
+  {
     TopoDS_Solid    Res;
     TopExp_Explorer exp;
     BRep_Builder    B;
@@ -788,7 +953,8 @@ void BRepOffset_MakeOffset::MakeThickSolid()
     B.MakeSolid(Res);
 
     BRepTools_Quilt Glue;
-    for (exp.Init(myShape,TopAbs_FACE); exp.More(); exp.Next()) {
+    for (exp.Init(myShape,TopAbs_FACE); exp.More(); exp.Next())
+    {
       NbF++;
       Glue.Add (exp.Current());
     } 
@@ -803,25 +969,27 @@ void BRepOffset_MakeOffset::MakeThickSolid()
 #ifdef OCCT_DEBUG
       if(YaResult == 0)
         {
-        cout << "OffsetShape does not contain a FACES." << endl;
+        std::cout << "OffsetShape does not contain a FACES." << std::endl;
         }
 #endif
       }
 #ifdef OCCT_DEBUG
     else
       {
-      cout << "OffsetShape is null!" << endl;
+      std::cout << "OffsetShape is null!" << std::endl;
       }
 #endif
 
     if (YaResult == 0)
       {
       myDone = Standard_False;
+      myError = BRepOffset_UnknownError;
       return;
       }
 
     myOffsetShape = Glue.Shells();
-    for (exp.Init(myOffsetShape,TopAbs_SHELL); exp.More(); exp.Next()) {
+    for (exp.Init(myOffsetShape,TopAbs_SHELL); exp.More(); exp.Next())
+    {
       B.Add(Res,exp.Current());
     }
     Res.Closed(Standard_True);
@@ -829,18 +997,20 @@ void BRepOffset_MakeOffset::MakeThickSolid()
 
     // Test of Validity of the result of thick Solid 
     // more face than the initial solid.
-        
     Standard_Integer NbOF = 0;
-    for (exp.Init(myOffsetShape,TopAbs_FACE);exp.More(); exp.Next()) {
+    for (exp.Init(myOffsetShape,TopAbs_FACE);exp.More(); exp.Next())
+    {
       NbOF++;
     }
-    if (NbOF <= NbF) {
+    if (NbOF <= NbF)
+    {
       myDone = Standard_False;
+      myError = BRepOffset_UnknownError;
       return;
     }
   }
 
-  if (myOffset > 0 ) myOffsetShape.Reverse();  
+  if (myOffset > 0 ) myOffsetShape.Reverse();
 
   myDone = Standard_True;
 }
@@ -876,68 +1046,62 @@ const TopoDS_Shape&  BRepOffset_MakeOffset::Shape() const
 }
 
 //=======================================================================
-//function : TrimEdge
-//purpose  : Trim the edge of the largest of descendants in AsDes2d.
-//           Order in AsDes two vertices that have trimmed the edge.
+//function : MakeOffsetFaces
+//purpose  : 
 //=======================================================================
-
-static void TrimEdge (TopoDS_Edge&                  NE,
-                     const Handle(BRepAlgo_AsDes)& AsDes2d,
-                           Handle(BRepAlgo_AsDes)& AsDes)
+void BRepOffset_MakeOffset::MakeOffsetFaces(BRepOffset_DataMapOfShapeOffset& theMapSF)
 {
-  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);
-  
-  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;
+  Standard_Real aCurOffset;
+  TopTools_ListOfShape aLF;
+  TopTools_DataMapOfShapeShape ShapeTgt;
+  TopTools_ListIteratorOfListOfShape aItLF;
+  //
+  Standard_Boolean OffsetOutside = (myOffset > 0.);
+  //
+  BRepLib::SortFaces(myShape, aLF);
+  //
+  aItLF.Initialize(aLF);
+  for (; aItLF.More(); aItLF.Next()) {
+    const TopoDS_Face& aF = TopoDS::Face(aItLF.Value());
+    aCurOffset = myFaceOffset.IsBound(aF) ? myFaceOffset(aF) : myOffset;
+    BRepOffset_Offset OF(aF, aCurOffset, ShapeTgt, OffsetOutside, myJoin);
+    TopTools_ListOfShape Let;
+    myAnalyse.Edges(aF,ChFiDS_Tangential,Let);
+    TopTools_ListIteratorOfListOfShape itl(Let);    
+    for (; itl.More(); itl.Next()) {
+      const TopoDS_Edge& Cur = TopoDS::Edge(itl.Value());
+      if ( !ShapeTgt.IsBound(Cur) && !myAnalyse.HasGenerated (Cur)) {
+        TopoDS_Shape aLocalShape = OF.Generated(Cur);
+        const TopoDS_Edge& OTE = TopoDS::Edge(aLocalShape);
+        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,ChFiDS_Tangential,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,ChFiDS_Tangential,LE);
+          const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V2);
+          if (LE.Extent() == LA.Extent())
+            ShapeTgt.Bind(V2,OV2);
+        }
       }
     }
-    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);
-    }
+    theMapSF.Bind(aF,OF);
+  }
+  //
+  const TopTools_ListOfShape& aNewFaces = myAnalyse.NewFaces();
+  for (TopTools_ListOfShape::Iterator it (aNewFaces); it.More(); it.Next())
+  {
+    const TopoDS_Face& aF = TopoDS::Face (it.Value());
+    BRepOffset_Offset OF(aF, 0.0, ShapeTgt, OffsetOutside, myJoin);
+    theMapSF.Bind (aF, OF);
   }
 }
 
@@ -949,62 +1113,20 @@ void BRepOffset_MakeOffset::BuildOffsetByInter()
 {
 #ifdef OCCT_DEBUG
   if ( ChronBuild) {
-    cout << " CONSTRUCTION OF OFFSETS :" << endl;
+    std::cout << " CONSTRUCTION OF OFFSETS :" << std::endl;
     Clock.Reset();
     Clock.Start();
   }
 #endif
 
-  BRepOffset_DataMapOfShapeOffset MapSF;
-  TopTools_MapOfShape             Done;
-  Standard_Boolean OffsetOutside = (myOffset > 0.)? Standard_True : Standard_False;
+  TopExp_Explorer Exp, Exp2, ExpC;
+  TopTools_ListIteratorOfListOfShape itLF;
+  
   //--------------------------------------------------------
   // 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);
-  }
+  BRepOffset_DataMapOfShapeOffset MapSF;
+  MakeOffsetFaces(MapSF);
   //--------------------------------------------------------------------
   // MES   : Map of OffsetShape -> Extended Shapes.
   // Build : Map of Initial SS  -> OffsetShape build by Inter.
@@ -1024,212 +1146,190 @@ void BRepOffset_MakeOffset::BuildOffsetByInter()
 
   BRepOffset_Inter3d Inter3 (AsDes,Side,myTol);
   // Intersection between parallel faces
-  Inter3.ConnexIntByInt(myShape,MapSF,myAnalyse,MES,Build,Failed );
+  Inter3.ConnexIntByInt(myShape,MapSF,myAnalyse,MES,Build,Failed,myIsPlanar);
   // Intersection with caps.
-  Inter3.ContextIntByInt(myFaces,ExtentContext,MapSF,myAnalyse,MES,Build,Failed );
-
+  Inter3.ContextIntByInt(myFaces,ExtentContext,MapSF,myAnalyse,MES,Build,Failed,myIsPlanar);
 
+  TopTools_ListOfShape aLFaces;
+  for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next())
+    aLFaces.Append (Exp.Current());
+  for (TopTools_ListOfShape::Iterator it (myAnalyse.NewFaces()); it.More(); it.Next())
+    aLFaces.Append (it.Value());
   //---------------------------------------------------------------------------------
   // 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,AsDes2d,myOffset, myTol);
-//  Modified by skv - Mon Jan 12 11:50:03 2004 OCC4455 End
+  IntersectEdges(aLFaces, MapSF, MES, Build, AsDes, AsDes2d);
+  if (myError != BRepOffset_NoError)
+  {
+    return;
   }
   //-----------------------------------------------------------
   // Great restriction of new edges and update of AsDes.
   //------------------------------------------ ----------------
+  TopTools_DataMapOfShapeListOfShape anEdgesOrigins; // offset edge - initial edges
   TopTools_IndexedMapOfShape NewEdges;
-  TopExp_Explorer Exp2,ExpC;
-  TopoDS_Shape    NE;
-  TopoDS_Edge     TNE;
-  TopoDS_Face     NF;
-  
-  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;
-    for (Exp2.Init(FI.Oriented(TopAbs_FORWARD),TopAbs_EDGE); Exp2.More(); Exp2.Next()) {
-      const TopoDS_Edge& EI = TopoDS::Edge(Exp2.Current());
-      if (View.Add(EI)) {
-       if (Build.IsBound(EI)) {
-         NE = Build(EI);
-         if (NE.ShapeType() == TopAbs_EDGE) {
-           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()) {
-             if (NewEdges.Add(ExpC.Current())) {
-               TopoDS_Edge NEC = TopoDS::Edge(ExpC.Current());
-               NEC.Free(Standard_True);
-               if (!AsDes2d->Descendant(NEC).IsEmpty()) {
-                 TrimEdge (NEC,AsDes2d,AsDes);
-               }
-               else {
-                 AsDes->Remove(NEC);
-               }
-             }
-           }
-         }
-       }
-       else {
-         NE = MapSF(FI).Generated(EI);
-         //// modified by jgv, 19.12.03 for OCC4455 ////
-         NE.Orientation( EI.Orientation() );
-         ///////////////////////////////////////////////
-         if (MES.IsBound(NE)) {
-           NE = MES(NE);
-           NE.Orientation(EI.Orientation());
-           if (NewEdges.Add(NE)) {TrimEdge (TopoDS::Edge(NE),AsDes2d,AsDes);} 
-         }
-         AsDes->Add(NF,NE);
-       } 
-      }
-    }
+  TopTools_DataMapOfShapeShape aETrimEInf; // trimmed - not trimmed edges
+  //
+  //Map of edges obtained after FACE-FACE (offsetted) intersection.
+  //Key1 is edge trimmed by intersection points with other edges;
+  //Item is not-trimmed edge. 
+  if (!TrimEdges(myShape, myOffset, myAnalyse, MapSF, MES, Build, AsDes, AsDes2d, NewEdges, aETrimEInf, anEdgesOrigins))
+  {
+    myError = BRepOffset_CannotTrimEdges;
+    return;
   }
-  
+  //
   //--------------------------------- 
   // Intersection 2D on //
   //---------------------------------  
+  TopTools_IndexedDataMapOfShapeListOfShape aDMVV;
+  TopTools_DataMapOfShapeShape aFacesOrigins; // offset face - initial face
   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);
-    }
-  }
-  
+  GetEnlargedFaces(aLFaces, MapSF, MES, aFacesOrigins, IMOE, LFE);
+  //
   TopTools_ListIteratorOfListOfShape itLFE(LFE);
-  for (; itLFE.More(); itLFE.Next()) {
+  for (; itLFE.More(); itLFE.Next())
+  {
     const TopoDS_Face& NEF = TopoDS::Face(itLFE.Value());
-    BRepOffset_Inter2d::Compute(AsDes,NEF,NewEdges,myTol);
+    Standard_Real aCurrFaceTol = BRep_Tool::Tolerance(NEF);
+    BRepOffset_Inter2d::Compute(AsDes, NEF, NewEdges, aCurrFaceTol, aDMVV);
   }
   //----------------------------------------------
   // Intersections 2d on caps.
   //----------------------------------------------
   Standard_Integer i;
-  for (i = 1; i <= myFaces.Extent(); i++) {
+  for (i = 1; i <= myFaces.Extent(); i++)
+  {
     const TopoDS_Face& Cork = TopoDS::Face(myFaces(i));
-    BRepOffset_Inter2d::Compute(AsDes,Cork,NewEdges,myTol);
+    Standard_Real aCurrFaceTol = BRep_Tool::Tolerance(Cork);
+    BRepOffset_Inter2d::Compute(AsDes, Cork, NewEdges, aCurrFaceTol, aDMVV);
   }
-
+  //
+  BRepOffset_Inter2d::FuseVertices(aDMVV, AsDes);
   //-------------------------------
   // Unwinding of extended Faces.
   //-------------------------------
-  myMakeLoops.Build(LFE  ,AsDes,IMOE);
-
+  //
+  TopTools_MapOfShape aMFDone;
+  //
+  if ((myJoin == GeomAbs_Intersection) && myInter && myIsPlanar) {
+    BuildSplitsOfExtendedFaces(LFE, myAnalyse, AsDes, anEdgesOrigins, aFacesOrigins, aETrimEInf, IMOE);
+    //
+    TopTools_ListIteratorOfListOfShape aItLF(LFE);
+    for (; aItLF.More(); aItLF.Next()) {
+      const TopoDS_Shape& aS = aItLF.Value();
+      aMFDone.Add(aS);
+    }
+  }
+  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();
+  for (TopTools_ListOfShape::Iterator it (aLFaces); it.More(); it.Next())
+  {
+    const TopoDS_Shape& FI   = it.Value();
     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);
+        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);
-         }
+          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);
+          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);
-           }
+            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));     
-             }
-           }
-         }
-       }
+            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);
+        if (aMFDone.Contains(OF)) {
+          continue;
+        }
+        //
+        myInitOffsetFace.Bind(FI,OF);
+        myImageOffset.SetRoot(OF);
 #ifdef DRAW 
-       if (AffichInt2d) {
-         sprintf(name,"AF_%d",NbAF++);
-         DBRep::Set(name,OF);
-       }
+        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);
+        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);
-             }
+              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);
+              
+              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);
-           }
+            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);
-         }
-       }
+            const TopTools_ListOfShape& LV = AsDes->Descendant(OE);
+            myAsDes->Add(OE,LV);
+          }
+        }
       }
     }
     else {
@@ -1237,26 +1337,26 @@ void BRepOffset_MakeOffset::BuildOffsetByInter()
       myImageOffset.SetRoot(OF);
       TopTools_MapOfShape View;
       for (Exp2.Init(OF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
-          Exp2.More(); Exp2.Next()) {
+           Exp2.More(); Exp2.Next()) {
 
-       const TopoDS_Edge& COE = TopoDS::Edge(Exp2.Current());
-       myAsDes->Add (OF,COE);
+        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);
-       }
+        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)); 
-         }
-       }
+        
+        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));        
+          }
+        }
       } 
     }
   }
@@ -1264,65 +1364,65 @@ void BRepOffset_MakeOffset::BuildOffsetByInter()
   // Add methods for supporting history.
   TopTools_MapOfShape aMapEdges;
 
-  for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
-    const TopoDS_Shape& aFaceRef = Exp.Current();
-
+  for (TopTools_ListOfShape::Iterator it (aLFaces); it.More(); it.Next())
+  {
+    const TopoDS_Shape& aFaceRef = it.Value();
     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);
-       }
+        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 
+  // MAJ SD. for caps
   //---------------------------
   //TopTools_MapOfShape View; 
   for (i = 1; i <= myFaces.Extent(); i++) {
@@ -1331,38 +1431,38 @@ void BRepOffset_MakeOffset::BuildOffsetByInter()
     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())) ;
+        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);
-         }
+          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));   
-         }
-       }
+          
+          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));
-       }
+        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);
-       }
+        if (AffichInt2d) {
+          sprintf(name,"AE_%d",NbAE++);
+          DBRep::Set(name,OE);
+          COES.Add(OE);
+        }
 #endif
       }
     }
@@ -1372,8 +1472,47 @@ void BRepOffset_MakeOffset::BuildOffsetByInter()
   DEBVerticesControl (COES,myAsDes);
   if ( ChronBuild) Clock.Show();
 #endif
+
 }
 
+//=======================================================================
+//function : ReplaceRoots
+//purpose  : 
+//=======================================================================
+void BRepOffset_MakeOffset::ReplaceRoots()
+{
+  // Replace the artificial faces and edges in InitOffset maps with the original ones.
+  TopTools_MapOfShape View;
+  for (TopExp_Explorer anExpF (myShape, TopAbs_EDGE); anExpF.More(); anExpF.Next())
+  {
+    const TopoDS_Shape& aF = anExpF.Current();
+    for (TopExp_Explorer anExpE (aF, TopAbs_EDGE); anExpE.More(); anExpE.Next())
+    {
+      const TopoDS_Shape& aE = anExpE.Current();
+      if (!View.Add (aE))
+        continue;
+
+      TopoDS_Shape aFGen = myAnalyse.Generated (aE);
+      if (aFGen.IsNull())
+        continue;
+
+      myInitOffsetFace.ReplaceRoot (aFGen, aE);
+
+      for (TopoDS_Iterator itV (aE); itV.More(); itV.Next())
+      {
+        const TopoDS_Shape& aV = itV.Value();
+        if (!View.Add (aV))
+          continue;
+
+        TopoDS_Shape aEGen = myAnalyse.Generated (aV);
+        if (aEGen.IsNull())
+          continue;
+
+        myInitOffsetEdge.ReplaceRoot (aEGen, aV);
+      }
+    }
+  }
+}
 
 //=======================================================================
 //function : BuildOffsetByArc
@@ -1383,127 +1522,86 @@ void BRepOffset_MakeOffset::BuildOffsetByArc()
 {
 #ifdef OCCT_DEBUG
   if ( ChronBuild) {
-    cout << " CONSTRUCTION OF OFFSETS :" << endl;
+    std::cout << " CONSTRUCTION OF OFFSETS :" << std::endl;
     Clock.Reset();
     Clock.Start();
   }
 #endif
 
-  BRepOffset_DataMapOfShapeOffset MapSF;
-  TopTools_MapOfShape             Done;
-  Standard_Boolean OffsetOutside = (myOffset > 0.)? Standard_True : Standard_False;
+  TopExp_Explorer Exp;
+  TopTools_ListIteratorOfListOfShape itLF;
+  TopTools_MapOfShape Done;
+  
   //--------------------------------------------------------
   // 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);
-  }
+  BRepOffset_DataMapOfShapeOffset MapSF;
+  MakeOffsetFaces(MapSF);
   //--------------------------------------------------------
   // Construction of tubes on edge.
   //--------------------------------------------------------
-  BRepOffset_Type    OT = BRepOffset_Convex;
-  if (myOffset < 0.) OT = BRepOffset_Concave; 
+  ChFiDS_TypeOfConcavity OT = ChFiDS_Convex;
+  if (myOffset < 0.) OT = ChFiDS_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));
+        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 aLocalShapeGen = MapSF(Anc.First()).Generated(E);
+          TopoDS_Edge EOn1 = TopoDS::Edge(aLocalShapeGen);
+          aLocalShapeGen = MapSF(Anc.Last()).Generated(E);
+          TopoDS_Edge EOn2 = TopoDS::Edge(aLocalShapeGen);
+//          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);      
+        myInitOffsetEdge.Bind (E,EOn1);      
       }
     }
   }
@@ -1522,42 +1620,42 @@ void BRepOffset_MakeOffset::BuildOffsetByArc()
       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);
+        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));
-         }
-       } 
+      myAnalyse.Edges(V,ChFiDS_FreeBound,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));
+          }
+        
       }
     }
   }
@@ -1571,19 +1669,19 @@ void BRepOffset_MakeOffset::BuildOffsetByArc()
   //------------------------------------------------------
   // MAJ SD.
   //------------------------------------------------------
-  BRepOffset_Type    RT = BRepOffset_Concave;
-  if (myOffset < 0.) RT = BRepOffset_Convex;
+  ChFiDS_TypeOfConcavity RT = ChFiDS_Concave;
+  if (myOffset < 0.) RT = ChFiDS_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 ) {
+        SF.Status() == BRepOffset_Degenerated ) {
       //------------------------------------------------
       // Degenerated or returned faces are not stored.
       //------------------------------------------------
       continue; 
-    }  
+    }        
 
     const TopoDS_Face&  OF = It.Value().Face();
     myInitOffsetFace.Bind    (SI,OF);      
@@ -1592,27 +1690,27 @@ void BRepOffset_MakeOffset::BuildOffsetByArc()
     
     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));
-       }
+           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());
+           Exp.More(); Exp.Next()) {
+        myAsDes->Add (OF,Exp.Current());
       }
     }
   }
@@ -1633,17 +1731,13 @@ void BRepOffset_MakeOffset::SelfInter(TopTools_MapOfShape& /*Modif*/)
 {
 #ifdef OCCT_DEBUG
   if ( ChronBuild) {
-    cout << " AUTODEBOUCLAGE:" << endl;
+    std::cout << " AUTODEBOUCLAGE:" << std::endl;
     Clock.Reset();
     Clock.Start();
   }    
 #endif  
 
-  Standard_NotImplemented::Raise();
-
-#ifdef OCCT_DEBUG
-  if ( ChronBuild) Clock.Show();
-#endif
+  throw Standard_NotImplemented();
 }
 
 
@@ -1670,14 +1764,14 @@ void BRepOffset_MakeOffset::ToContext (BRepOffset_DataMapOfShapeOffset& MapSF)
   for (i = 1; i <= myFaces.Extent(); i++) {
     const TopoDS_Face& CF = TopoDS::Face(myFaces(i));
     for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
-        exp.More(); exp.Next()) {
+         exp.More(); exp.Next()) {
       const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
       if (!myAnalyse.HasAncestor(E)) {
-       //----------------------------------------------------------------
-       // The edges of context faces that are not in the initial shape
-       // can appear in the result.
-       //----------------------------------------------------------------
-       //myAsDes->Add(CF,E);
+        //----------------------------------------------------------------
+        // The edges of context faces that are not in the initial shape
+        // can appear in the result.
+        //----------------------------------------------------------------
+        //myAsDes->Add(CF,E);
       }  
     }
   }
@@ -1691,28 +1785,28 @@ void BRepOffset_MakeOffset::ToContext (BRepOffset_DataMapOfShapeOffset& MapSF)
   for (j = 1; j <= myFaces.Extent(); j++) {
     const TopoDS_Face& CF = TopoDS::Face(myFaces(j));
     for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
-        exp.More(); exp.Next()) {
+         exp.More(); exp.Next()) {
       const TopoDS_Edge& E = TopoDS::Edge(exp.Current()); 
       if (myAnalyse.HasAncestor(E)) {
-       const TopTools_ListOfShape& LEA = myAnalyse.Ancestors(E);
-       for (itl.Initialize(LEA); itl.More(); itl.Next()) {
-         const BRepOffset_Offset& OF = MapSF(itl.Value());
-         FacesToBuild.Add(itl.Value());
-         MEF.Bind(OF.Generated(E),CF);
-       }
-       TopoDS_Vertex V[2];
-       TopExp::Vertices(E,V[0],V[1]);
-       for (Standard_Integer i = 0; i < 2; i++) {
-         const TopTools_ListOfShape& LVA =  myAnalyse.Ancestors(V[i]);
-         for ( itl.Initialize(LVA); itl.More(); itl.Next()) {
-           const TopoDS_Edge& EV = TopoDS::Edge(itl.Value());
-           if (MapSF.IsBound(EV)) {
-             const BRepOffset_Offset& OF = MapSF(EV);
-             FacesToBuild.Add(EV);
-             MEF.Bind(OF.Generated(V[i]),CF);
-           }
-         }
-       }
+        const TopTools_ListOfShape& LEA = myAnalyse.Ancestors(E);
+        for (itl.Initialize(LEA); itl.More(); itl.Next()) {
+          const BRepOffset_Offset& OF = MapSF(itl.Value());
+          FacesToBuild.Add(itl.Value());
+          MEF.Bind(OF.Generated(E),CF);
+        }
+         TopoDS_Vertex V[2];
+        TopExp::Vertices(E,V[0],V[1]);
+        for (Standard_Integer i = 0; i < 2; i++) {
+          const TopTools_ListOfShape& LVA =  myAnalyse.Ancestors(V[i]);
+          for ( itl.Initialize(LVA); itl.More(); itl.Next()) {
+            const TopoDS_Edge& EV = TopoDS::Edge(itl.Value());
+            if (MapSF.IsBound(EV)) {
+              const BRepOffset_Offset& OF = MapSF(EV);
+              FacesToBuild.Add(EV);
+              MEF.Bind(OF.Generated(V[i]),CF);
+            }
+          }
+        }
       }
     }
   }
@@ -1720,8 +1814,8 @@ void BRepOffset_MakeOffset::ToContext (BRepOffset_DataMapOfShapeOffset& MapSF)
   // Reconstruction of faces.
   //---------------------------
   TopoDS_Face        F,NF;
-  BRepOffset_Type    RT = BRepOffset_Concave;
-  if (myOffset < 0.) RT = BRepOffset_Convex;
+  ChFiDS_TypeOfConcavity RT = ChFiDS_Concave;
+  if (myOffset < 0.) RT = ChFiDS_Convex;
   TopoDS_Shape       OE,NE;
   TopAbs_Orientation Or;
 
@@ -1741,26 +1835,26 @@ void BRepOffset_MakeOffset::ToContext (BRepOffset_DataMapOfShapeOffset& MapSF)
 
     if (S.ShapeType() == TopAbs_FACE) {
       for (exp.Init(S.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
-          exp.More(); exp.Next()) {
-       
-       const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
-       const BRepOffset_ListOfInterval& L  = myAnalyse.Type(E);
-       OE = BOF.Generated(E);
-       Or = E.Orientation();
-       OE.Orientation(Or);
-       if (!L.IsEmpty() && L.First().Type() != RT) {
-         if (Created.IsBound(OE)) {
-           NE = Created(OE); 
-           if (NE.Orientation() == TopAbs_REVERSED) 
-             NE.Orientation(TopAbs::Reverse(Or));
-           else
-             NE.Orientation(Or);
-           myAsDes->Add(NF,NE);
-         }
-         else {
-           myAsDes->Add(NF,OE);
-         }
-       }
+           exp.More(); exp.Next()) {
+        
+        const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
+        const BRepOffset_ListOfInterval& L  = myAnalyse.Type(E);
+        OE = BOF.Generated(E);
+        Or = E.Orientation();
+        OE.Orientation(Or);
+        if (!L.IsEmpty() && L.First().Type() != RT) {
+          if (Created.IsBound(OE)) {
+            NE = Created(OE); 
+            if (NE.Orientation() == TopAbs_REVERSED) 
+              NE.Orientation(TopAbs::Reverse(Or));
+            else
+              NE.Orientation(Or);
+            myAsDes->Add(NF,NE);
+          }
+          else {
+            myAsDes->Add(NF,OE);
+          }
+        }
       }
     }
     else {
@@ -1768,8 +1862,8 @@ void BRepOffset_MakeOffset::ToContext (BRepOffset_DataMapOfShapeOffset& MapSF)
       // Tube
       //---------------------
       for (exp.Init(NF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
-          exp.More(); exp.Next()) {
-       myAsDes->Add (NF,exp.Current());
+           exp.More(); exp.Next()) {
+        myAsDes->Add (NF,exp.Current());
       }
     }    
     MapSF.UnBind(S);
@@ -1786,9 +1880,9 @@ void BRepOffset_MakeOffset::ToContext (BRepOffset_DataMapOfShapeOffset& MapSF)
       TopoDS_Shape E = myInitOffsetEdge.ImageFrom (OE);
       Or = myInitOffsetEdge.Image(E).First().Orientation();
       if (NE.Orientation() == TopAbs_REVERSED) 
-       NE.Orientation(TopAbs::Reverse(Or));
+        NE.Orientation(TopAbs::Reverse(Or));
       else
-       NE.Orientation(Or);
+        NE.Orientation(Or);
       myInitOffsetEdge.Remove(OE);
       myInitOffsetEdge.Bind(E,NE);
     }
@@ -1808,8 +1902,8 @@ void BRepOffset_MakeOffset::UpdateFaceOffset()
   CopiedMap.Assign(myFaceOffset);
   TopTools_DataMapIteratorOfDataMapOfShapeReal it(CopiedMap);
 
-  BRepOffset_Type    RT = BRepOffset_Convex;
-  if (myOffset < 0.) RT = BRepOffset_Concave;
+  ChFiDS_TypeOfConcavity RT = ChFiDS_Convex;
+  if (myOffset < 0.) RT = ChFiDS_Concave;
 
   for ( ; it.More(); it.Next()) {
     const TopoDS_Face& F = TopoDS::Face(it.Key());
@@ -1821,16 +1915,16 @@ void BRepOffset_MakeOffset::UpdateFaceOffset()
     TopTools_MapOfShape Dummy;
     Build.Add(Co,F);
     if (myJoin == GeomAbs_Arc)
-      myAnalyse.AddFaces(F,Co,Dummy,BRepOffset_Tangent,RT);
+      myAnalyse.AddFaces(F,Co,Dummy,ChFiDS_Tangential,RT);
     else   
-      myAnalyse.AddFaces(F,Co,Dummy,BRepOffset_Tangent);
+      myAnalyse.AddFaces(F,Co,Dummy,ChFiDS_Tangential);
 
     TopExp_Explorer exp(Co,TopAbs_FACE);
     for (; exp.More(); exp.Next()) {
       const TopoDS_Face& FF = TopoDS::Face(exp.Current());
       if ( !M.Add(FF)) continue;
       if ( myFaceOffset.IsBound(FF))
-       myFaceOffset.UnBind(FF);
+        myFaceOffset.UnBind(FF);
       myFaceOffset.Bind(FF,CurOffset);
     }
   }
@@ -1990,7 +2084,7 @@ void BRepOffset_MakeOffset::CorrectConicalFaces()
         Ul = 2.*M_PI;
       Handle(Geom_Curve) aCurv = aSphSurf->VIso(Vf);
       /*
-       if (!isFirstFace)
+        if (!isFirstFace)
         {
         gp_Circ aCircle = (Handle(Geom_Circle)::DownCast(aCurv))->Circ();
         if (Abs(Uf - f) > Precision::Confusion())
@@ -2097,7 +2191,7 @@ void BRepOffset_MakeOffset::CorrectConicalFaces()
         break;
       }
     }
-    NewEdges.Append(FirstEdge);
+    NewEdges.Append(FirstEdge.Oriented(TopAbs_FORWARD));
     TopoDS_Vertex Vf1, CurVertex;
     TopExp::Vertices(FirstEdge, Vf1, CurVertex);
     itl.Initialize(EdgesOfWire);
@@ -2108,7 +2202,7 @@ void BRepOffset_MakeOffset::CorrectConicalFaces()
       TopExp::Vertices(anEdge, V1, V2);
       if (V1.IsSame(CurVertex) || V2.IsSame(CurVertex))
       {
-        NewEdges.Append(anEdge);
+        NewEdges.Append(anEdge.Oriented(TopAbs_FORWARD));
         CurVertex = (V1.IsSame(CurVertex))? V2 : V1;
         EdgesOfWire.Remove(itl);
       }
@@ -2126,30 +2220,32 @@ void BRepOffset_MakeOffset::CorrectConicalFaces()
       Vfirst = -M_PI/2.; Vlast = p2d1.Y();
     }
     TopoDS_Face NewSphericalFace = BRepLib_MakeFace(aSphSurf, Ufirst, Ulast, Vfirst, Vlast, Precision::Confusion());
-    TopoDS_Edge OldEdge;
+    TopoDS_Edge OldEdge, DegEdge;
+    for (Explo.Init(NewSphericalFace, TopAbs_EDGE); Explo.More(); Explo.Next())
+    {
+      DegEdge = TopoDS::Edge(Explo.Current());
+      if (BRep_Tool::Degenerated(DegEdge))
+        break;
+    }
+    TopoDS_Vertex DegVertex = TopExp::FirstVertex(DegEdge);
     for (Explo.Init(NewSphericalFace, TopAbs_EDGE); Explo.More(); Explo.Next())
     {
       OldEdge = TopoDS::Edge(Explo.Current());
-      if (!BRep_Tool::Degenerated(OldEdge))
-      {
-        BRepAdaptor_Curve2d BAc2d(OldEdge, NewSphericalFace);
-        p2d1 = BAc2d.Value(BAc2d.FirstParameter());
-        p2d2 = BAc2d.Value(BAc2d.LastParameter());
-        if (Abs(p2d1.X() - Ufirst) <= Precision::Confusion() &&
-            Abs(p2d2.X() - Ulast)  <= Precision::Confusion())
-          break;
-      }
+      TopoDS_Vertex V1, V2;
+      TopExp::Vertices(OldEdge, V1, V2);
+      if (!V1.IsSame(DegVertex) && !V2.IsSame(DegVertex))
+        break;
     }
     TopoDS_Vertex V1, V2;
     TopExp::Vertices(OldEdge, V1, V2);
     TopTools_ListOfShape LV1, LV2;
-    LV1.Append(Vf1);
-    LV2.Append(CurVertex);
+    LV1.Append(Vf1.Oriented(TopAbs_FORWARD));
+    LV2.Append(CurVertex.Oriented(TopAbs_FORWARD));
     BRepTools_Substitution theSubstitutor;
-    theSubstitutor.Substitute(V1, LV1);
+    theSubstitutor.Substitute(V1.Oriented(TopAbs_FORWARD), LV1);
     if (!V1.IsSame(V2))
-      theSubstitutor.Substitute(V2, LV2);
-    theSubstitutor.Substitute(OldEdge, NewEdges);
+      theSubstitutor.Substitute(V2.Oriented(TopAbs_FORWARD), LV2);
+    theSubstitutor.Substitute(OldEdge.Oriented(TopAbs_FORWARD), NewEdges);
     theSubstitutor.Build(NewSphericalFace);
     if (theSubstitutor.IsCopied(NewSphericalFace))
     {
@@ -2210,36 +2306,30 @@ void BRepOffset_MakeOffset::CorrectConicalFaces()
         }
       }
     }
-    TopoDS_Iterator anIt(Sol);
-    Standard_Boolean SolIsNull = !anIt.More();
+    Standard_Integer nbs = Sol.NbChildren();
+    Standard_Boolean SolIsNull = (nbs == 0);
     //Checking solid
-    if(!SolIsNull)
+    if (nbs > 1)
     {
-      Standard_Integer nbs = 0;
-      while(anIt.More()) {anIt.Next(); ++nbs;}
-      if(nbs > 1)
+      BRepCheck_Analyzer aCheck (Sol, Standard_False);
+      if (!aCheck.IsValid ())
       {
-        BRepCheck_Analyzer aCheck(Sol, Standard_False);
-        if(!aCheck.IsValid())
+        TopTools_ListOfShape aSolList;
+        CorrectSolid (Sol, aSolList);
+        if (!aSolList.IsEmpty ())
         {
-          TopTools_ListOfShape aSolList;
-          CorrectSolid(Sol, aSolList);
-          if(!aSolList.IsEmpty())
+          BB.Add (NC, Sol);
+          TopTools_ListIteratorOfListOfShape aSLIt (aSolList);
+          for (; aSLIt.More (); aSLIt.Next ())
           {
-            BB.Add(NC, Sol);
-            TopTools_ListIteratorOfListOfShape aSLIt(aSolList);
-            for(; aSLIt.More(); aSLIt.Next())
-            {
-              BB.Add(NC, aSLIt.Value());
-            }
-            SolIsNull = Standard_True;
+            BB.Add (NC, aSLIt.Value ());
           }
+          SolIsNull = Standard_True;
         }
       }
     }
     //
-    anIt.Initialize(NC);
-    Standard_Boolean NCIsNull = !anIt.More();
+    Standard_Boolean NCIsNull = (NC.NbChildren() == 0);
     if((!SolIsNull) && (!NCIsNull))
     {
       BB.Add(NC, Sol);
@@ -2277,11 +2367,24 @@ void BRepOffset_MakeOffset::Intersection3D(BRepOffset_Inter3d& Inter)
 {
 #ifdef OCCT_DEBUG
   if (ChronBuild) {
-    cout << " INTERSECTION 3D:" << endl;
+    std::cout << " INTERSECTION 3D:" << std::endl;
     Clock.Reset();
     Clock.Start();  
   }
 #endif
+
+  // In the Complete Intersection mode, implemented currently for planar
+  // solids only, there is no need to intersect the faces here.
+  // This intersection will be performed in the method BuildShellsCompleteInter
+  // where the special treatment is applied to produced faces.
+  //
+  // Make sure to match the parameters in which the method
+  // BuildShellsCompleteInter is called.
+  if (myInter && (myJoin == GeomAbs_Intersection) && myIsPlanar &&
+      !myThickening && myFaces.IsEmpty() && IsSolid(myShape))
+    return;
+
+
   TopTools_ListOfShape OffsetFaces;  // list of faces // created.
   MakeList (OffsetFaces,myInitOffsetFace,myFaces);
 
@@ -2320,11 +2423,11 @@ void BRepOffset_MakeOffset::Intersection3D(BRepOffset_Inter3d& Inter)
 //=======================================================================
 
 void BRepOffset_MakeOffset::Intersection2D(const TopTools_IndexedMapOfShape& Modif,
-                                          const TopTools_IndexedMapOfShape& NewEdges)
+                                           const TopTools_IndexedMapOfShape& NewEdges)
 {
 #ifdef OCCT_DEBUG
   if (ChronBuild) {
-    cout << " INTERSECTION 2D:" << endl;
+    std::cout << " INTERSECTION 2D:" << std::endl;
     Clock.Reset();
     Clock.Start();  
   }
@@ -2337,12 +2440,15 @@ void BRepOffset_MakeOffset::Intersection2D(const TopTools_IndexedMapOfShape& Mod
   //-----------------------------------------------
   // Intersection of edges 2 by 2.
   //-----------------------------------------------
+  TopTools_IndexedDataMapOfShapeListOfShape aDMVV;
   Standard_Integer i;
   for (i = 1; i <= Modif.Extent(); i++) {
     const TopoDS_Face& F  = TopoDS::Face(Modif(i));
-    BRepOffset_Inter2d::Compute(myAsDes,F,NewEdges,myTol);
+    BRepOffset_Inter2d::Compute(myAsDes,F,NewEdges,myTol, aDMVV);
   }
-
+  //
+  BRepOffset_Inter2d::FuseVertices(aDMVV, myAsDes);
+  //
 #ifdef OCCT_DEBUG
   if (AffichInt2d) {
     DEBVerticesControl (NewEdges,myAsDes);
@@ -2361,7 +2467,7 @@ void BRepOffset_MakeOffset::MakeLoops(TopTools_IndexedMapOfShape& Modif)
 {
 #ifdef OCCT_DEBUG
   if (ChronBuild) {
-     cout << " DEBOUCLAGE 2D:" << endl;
+     std::cout << " DEBOUCLAGE 2D:" << std::endl;
      Clock.Reset();
      Clock.Start(); 
   }
@@ -2376,7 +2482,13 @@ void BRepOffset_MakeOffset::MakeLoops(TopTools_IndexedMapOfShape& Modif)
     if (!myFaces.Contains(Modif(i)))
       LF.Append(Modif(i));
   }
-  myMakeLoops.Build(LF,myAsDes,myImageOffset);
+  //
+  if ((myJoin == GeomAbs_Intersection) && myInter && myIsPlanar) {
+    BuildSplitsOfTrimmedFaces(LF, myAsDes, myImageOffset);
+  }
+  else {
+    myMakeLoops.Build(LF,myAsDes,myImageOffset);
+  }
 
   //-----------------------------------------
   // unwinding of caps.
@@ -2403,7 +2515,7 @@ void BRepOffset_MakeOffset::MakeFaces(TopTools_IndexedMapOfShape& /*Modif*/)
 {
 #ifdef OCCT_DEBUG
   if (ChronBuild) {  
-    cout << " RECONSTRUCTION OF FACES:" << endl;
+    std::cout << " RECONSTRUCTION OF FACES:" << std::endl;
     Clock.Reset();
     Clock.Start();
   }
@@ -2416,9 +2528,17 @@ void BRepOffset_MakeOffset::MakeFaces(TopTools_IndexedMapOfShape& /*Modif*/)
   //----------------------------------
   for (itr.Initialize(Roots); itr.More(); itr.Next()) {
     TopoDS_Face F = TopoDS::Face(myInitOffsetFace.Image(itr.Value()).First());
-    LOF.Append(F);
+    if (!myImageOffset.HasImage(F)) {
+      LOF.Append(F);
+    }
+  }
+  //
+  if ((myJoin == GeomAbs_Intersection) && myInter && myIsPlanar) {
+    BuildSplitsOfTrimmedFaces(LOF, myAsDes, myImageOffset);
+  }
+  else {
+    myMakeLoops.BuildFaces(LOF,myAsDes,myImageOffset);
   }
-  myMakeLoops.BuildFaces(LOF,myAsDes,myImageOffset);
   
 #ifdef OCCT_DEBUG
   if ( ChronBuild) Clock.Show();
@@ -2429,11 +2549,10 @@ void BRepOffset_MakeOffset::MakeFaces(TopTools_IndexedMapOfShape& /*Modif*/)
 //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&         myImageOffset,
+                              const TopoDS_Shape&     myOffsetShape,
+                              const TopAbs_ShapeEnum &theShapeType) // skv
 {
   BRepAlgo_Image NIOF;
   const TopTools_ListOfShape& Roots = myInitOffset.Roots();
@@ -2467,372 +2586,432 @@ static void UpdateInitOffset (BRepAlgo_Image&         myInitOffset,
 //function : MakeMissingWalls
 //purpose  : 
 //=======================================================================
-
 void BRepOffset_MakeOffset::MakeMissingWalls ()
 {
-  TopTools_DataMapOfShapeListOfShape Contours; //Start vertex + list of connected edges (free boundary)
+  TopTools_IndexedDataMapOfShapeListOfShape Contours; //Start vertex + list of connected edges (free boundary)
   TopTools_DataMapOfShapeShape MapEF; //Edges of contours: edge + face
   Standard_Real OffsetVal = Abs(myOffset);
 
   FillContours(myShape, myAnalyse, Contours, MapEF);
 
-  TopTools_DataMapIteratorOfDataMapOfShapeListOfShape iter(Contours);
-  for (; iter.More(); iter.Next())
+  for (Standard_Integer ic = 1; ic <= Contours.Extent(); ic++)
+  {
+    TopoDS_Vertex StartVertex = TopoDS::Vertex(Contours.FindKey(ic));
+    TopoDS_Edge StartEdge;
+    const TopTools_ListOfShape& aContour = Contours(ic);
+    TopTools_ListIteratorOfListOfShape itl(aContour);
+    Standard_Boolean FirstStep = Standard_True;
+    TopoDS_Edge PrevEdge;
+    TopoDS_Vertex PrevVertex = StartVertex;
+    Standard_Boolean isBuildFromScratch = Standard_False; // Problems with edges.
+    for (; itl.More(); itl.Next())
     {
-      TopoDS_Vertex StartVertex = TopoDS::Vertex(iter.Key());
-      TopoDS_Edge StartEdge;
-      const TopTools_ListOfShape& aContour = iter.Value();
-      TopTools_ListIteratorOfListOfShape itl(aContour);
-      Standard_Boolean FirstStep = Standard_True;
-      TopoDS_Edge PrevEdge;
-      TopoDS_Vertex PrevVertex = StartVertex;
-      for (; itl.More(); itl.Next())
-       {
-         TopoDS_Edge anEdge = TopoDS::Edge(itl.Value());
-         if (!myInitOffsetEdge.HasImage(anEdge))
-           continue;
-         //if (BRep_Tool::Degenerated(anEdge))
-           //continue;
-         TopoDS_Face aFace = TopoDS::Face(MapEF(anEdge));
-         //TopoDS_Edge OE = TopoDS::Edge(myInitOffsetEdge.Image(anEdge).First());
-         TopTools_ListOfShape LOE, LOE2;
-         myInitOffsetEdge.LastImage( anEdge, LOE );
-         myImageOffset.LastImage( LOE.Last(), LOE2 );
-         TopoDS_Edge OE = TopoDS::Edge( LOE2.Last() );
-         ////////////////////////////////////////////////////////////////////////
-         TopoDS_Vertex V1, V2, V3, V4;
-         TopExp::Vertices(anEdge, V1, V2/*, Standard_True*/);
-         TopExp::Vertices(OE,     V4, V3/*, Standard_True*/);
-         Standard_Boolean ToReverse = Standard_False;
-         if (!V1.IsSame(PrevVertex))
-           {
-             TopoDS_Vertex aVtx = V1; V1 = V2; V2 = aVtx;
-             aVtx = V3; V3 = V4; V4 = aVtx;
-             ToReverse = Standard_True;
-           }
-         //Temporary
-         //anEdge.Reverse();
-         OE.Orientation(TopAbs::Reverse(anEdge.Orientation()));
-         TopoDS_Edge E3, E4;
-         if (FirstStep)
-           {
-             E4 = BRepLib_MakeEdge( V1, V4 );
-             StartEdge = E4;
-           }
-         else
-           E4 = PrevEdge;
-         Standard_Boolean ArcOnV2 = ((myJoin == GeomAbs_Arc) && (myInitOffsetEdge.HasImage(V2)));
-         if (V2.IsSame(StartVertex) && !ArcOnV2)
-           E3 = StartEdge;
-         else
-           E3 = BRepLib_MakeEdge( V2, V3 );
-         E4.Reverse();
-         TopoDS_Shape localAnEdge = anEdge.Oriented(TopAbs_FORWARD);
-         const TopoDS_Edge& anEdgeFWD = TopoDS::Edge(localAnEdge);
-         Standard_Real ParV1 = BRep_Tool::Parameter(V1, anEdgeFWD);
-         Standard_Real ParV2 = BRep_Tool::Parameter(V2, anEdgeFWD);
-         BRep_Builder BB;
-         TopoDS_Wire theWire;
-         BB.MakeWire(theWire);
-         if (ToReverse)
-           {
-             BB.Add(theWire, anEdge.Reversed());
-             BB.Add(theWire, E3.Reversed());
-             BB.Add(theWire, OE.Reversed());
-             BB.Add(theWire, E4.Reversed());
-           }
-         else
-           {
-             BB.Add(theWire, anEdge);
-             BB.Add(theWire, E3);
-             BB.Add(theWire, OE);
-             BB.Add(theWire, E4);
-           }
-         BRepLib::BuildCurves3d( theWire, myTol );
-         theWire.Closed(Standard_True);
-         TopoDS_Face NewFace;
-         Handle(Geom_Surface) theSurf;
-         BRepAdaptor_Curve BAcurve(anEdge);
-         BRepAdaptor_Curve BAcurveOE(OE);
-         Standard_Real fpar = BAcurve.FirstParameter();
-         Standard_Real lpar = BAcurve.LastParameter();
-         gp_Pnt PonE  = BAcurve.Value(fpar);
-         gp_Pnt PonOE = BAcurveOE.Value(fpar);
-         gp_Dir OffsetDir = gce_MakeDir( PonE, PonOE );
-         Handle(Geom2d_Line) EdgeLine2d, OELine2d, aLine2d, aLine2d2;
-         Standard_Boolean IsPlanar = Standard_False;
-         if (BAcurve.GetType() == GeomAbs_Circle &&
-             BAcurveOE.GetType() == GeomAbs_Circle)
+      TopoDS_Edge anEdge = TopoDS::Edge(itl.Value());
+      TopoDS_Face aFaceOfEdge = TopoDS::Face(MapEF(anEdge));
+
+      // Check for offset existence.
+      if (!myInitOffsetEdge.HasImage(anEdge))
+        continue;
+
+      // Check for existence of two different vertices.
+      TopTools_ListOfShape LOE, LOE2;
+      myInitOffsetEdge.LastImage( anEdge, LOE );
+      myImageOffset.LastImage( LOE.Last(), LOE2 );
+      TopoDS_Edge OE = TopoDS::Edge( LOE2.Last() );
+      TopoDS_Vertex V1, V2, V3, V4;
+      TopExp::Vertices(OE,     V4, V3);
+      TopExp::Vertices(anEdge, V1, V2);
+      Standard_Real aF, aL;
+      const Handle(Geom_Curve) aC = BRep_Tool::Curve(anEdge, aF, aL);
+      if (!aC.IsNull() &&
+         (!aC->IsClosed() && !aC->IsPeriodic()))
+      {
+        gp_Pnt aPntF = BRep_Tool::Pnt(V1);
+        gp_Pnt aPntL = BRep_Tool::Pnt(V2);
+        Standard_Real aDistE = aPntF.SquareDistance(aPntL);
+        if ( aDistE < Precision::SquareConfusion())
+        {
+          // Bad case: non closed, but vertexes mapped to same 3d point.
+          continue;
+        }
+
+        Standard_Real anEdgeTol = BRep_Tool::Tolerance(anEdge);
+        if (aDistE < anEdgeTol)
+        {
+          // Potential problems not detected via checkshape.
+          gp_Pnt aPntOF = BRep_Tool::Pnt(V4);
+          gp_Pnt aPntOL = BRep_Tool::Pnt(V3);
+          if (aPntOF.SquareDistance(aPntOL) > gp::Resolution())
           {
-            gp_Circ aCirc = BAcurve.Circle();
-            gp_Circ aCircOE = BAcurveOE.Circle();
-            gp_Lin anAxisLine(aCirc.Axis());
-            gp_Dir CircAxisDir = aCirc.Axis().Direction();
-            if (aCirc.Axis().IsParallel(aCircOE.Axis(), Precision::Confusion()) &&
-                anAxisLine.Contains(aCircOE.Location(), Precision::Confusion()))
-            { //cylinder, plane or cone
-              if (Abs(aCirc.Radius() - aCircOE.Radius()) <= Precision::Confusion()) //case of cylinder
-                theSurf = GC_MakeCylindricalSurface(aCirc).Value();
-              else if (aCirc.Location().Distance(aCircOE.Location()) <= Precision::Confusion()) {//case of plane
-                IsPlanar = Standard_True;
+            // To avoid computation of complex analytical continuation of Sin / ArcSin.
+            Standard_Real aSinValue = Min(2 * anEdgeTol / aPntOF.Distance(aPntOL), 1.0);
+            Standard_Real aMaxAngle = Min(Abs(ASin(aSinValue)), M_PI_4); // Maximal angle.
+            Standard_Real aCurrentAngle =  gp_Vec(aPntF, aPntL).Angle(gp_Vec(aPntOF, aPntOL));
+            if (aC->IsKind(STANDARD_TYPE(Geom_Line)) &&
+                Abs (aCurrentAngle) > aMaxAngle)
+            {
+              // anEdge not collinear to offset edge.
+              isBuildFromScratch = Standard_True;
+              myIsPerformSewing = Standard_True;
+              continue;
+            }
+          }
+        }
+      }
+
+      Standard_Boolean ToReverse = Standard_False;
+      if (!V1.IsSame(PrevVertex))
+      {
+        TopoDS_Vertex aVtx = V1; V1 = V2; V2 = aVtx;
+        aVtx = V3; V3 = V4; V4 = aVtx;
+        ToReverse = Standard_True;
+      }
+
+      OE.Orientation(TopAbs::Reverse(anEdge.Orientation()));
+      TopoDS_Edge E3, E4;
+      Standard_Boolean ArcOnV2 = ((myJoin == GeomAbs_Arc) && (myInitOffsetEdge.HasImage(V2)));
+      if (FirstStep || isBuildFromScratch)
+      {
+        E4 = BRepLib_MakeEdge( V1, V4 );
+        if (FirstStep)
+          StartEdge = E4;
+      }
+      else
+        E4 = PrevEdge;
+      if (V2.IsSame(StartVertex) && !ArcOnV2)
+        E3 = StartEdge;
+      else
+        E3 = BRepLib_MakeEdge( V2, V3 );
+      E4.Reverse();
+
+      if (isBuildFromScratch)
+      {
+        E3.Reverse();
+        E4.Reverse();
+      }
+
+      TopoDS_Shape localAnEdge = anEdge.Oriented(TopAbs_FORWARD);
+      const TopoDS_Edge& anEdgeFWD = TopoDS::Edge(localAnEdge);
+      Standard_Real ParV1 = BRep_Tool::Parameter(V1, anEdgeFWD);
+      Standard_Real ParV2 = BRep_Tool::Parameter(V2, anEdgeFWD);
+      BRep_Builder BB;
+      TopoDS_Wire theWire;
+      BB.MakeWire(theWire);
+      if (ToReverse)
+      {
+        BB.Add(theWire, anEdge.Reversed());
+        BB.Add(theWire, E3.Reversed());
+        BB.Add(theWire, OE.Reversed());
+        BB.Add(theWire, E4.Reversed());
+      }
+      else
+      {
+        BB.Add(theWire, anEdge);
+        BB.Add(theWire, E3);
+        BB.Add(theWire, OE);
+        BB.Add(theWire, E4);
+      }
+
+      BRepLib::BuildCurves3d( theWire, myTol );
+      theWire.Closed(Standard_True);
+      TopoDS_Face NewFace;
+      Handle(Geom_Surface) theSurf;
+      BRepAdaptor_Curve BAcurve(anEdge);
+      BRepAdaptor_Curve BAcurveOE(OE);
+      Standard_Real fpar = BAcurve.FirstParameter();
+      Standard_Real lpar = BAcurve.LastParameter();
+      gp_Pnt PonE  = BAcurve.Value(fpar);
+      gp_Pnt PonOE = BAcurveOE.Value(fpar);
+      gp_Dir OffsetDir = gce_MakeDir( PonE, PonOE );
+      Handle(Geom2d_Line) EdgeLine2d, OELine2d, aLine2d, aLine2d2;
+      Standard_Boolean IsPlanar = Standard_False;
+      if (BAcurve.GetType() == GeomAbs_Circle &&
+        BAcurveOE.GetType() == GeomAbs_Circle)
+      {
+        gp_Circ aCirc = BAcurve.Circle();
+        gp_Circ aCircOE = BAcurveOE.Circle();
+        gp_Lin anAxisLine(aCirc.Axis());
+        gp_Dir CircAxisDir = aCirc.Axis().Direction();
+        if (aCirc.Axis().IsParallel(aCircOE.Axis(), Precision::Confusion()) &&
+          anAxisLine.Contains(aCircOE.Location(), Precision::Confusion()))
+        { //cylinder, plane or cone
+          if (Abs(aCirc.Radius() - aCircOE.Radius()) <= Precision::Confusion()) //case of cylinder
+            theSurf = GC_MakeCylindricalSurface(aCirc).Value();
+          else if (aCirc.Location().Distance(aCircOE.Location()) <= Precision::Confusion()) {//case of plane
+            IsPlanar = Standard_True;
+            //
+            gp_Pnt PonEL = BAcurve.Value(lpar);
+            if (PonEL.Distance(PonE) <= Precision::PConfusion()) {
+              Standard_Boolean bIsHole;
+              TopoDS_Edge aE1, aE2;
+              TopoDS_Wire aW1, aW2;
+              Handle(Geom_Plane) aPL;
+              IntTools_FClass2d aClsf;
+              //
+              if (aCirc.Radius()>aCircOE.Radius()) {
+                aE1 = anEdge;
+                aE2 = OE;
+              } else {
+                aE1 = OE;
+                aE2 = anEdge;
+              }
+              //
+              BB.MakeWire(aW1);
+              BB.Add(aW1, aE1);
+              BB.MakeWire(aW2);
+              BB.Add(aW2, aE2);
+              //
+              aPL = new Geom_Plane(aCirc.Location(), CircAxisDir);
+              for (Standard_Integer i = 0; i < 2; ++i) {
+                TopoDS_Wire& aW = (i==0) ? aW1 : aW2;
+                TopoDS_Edge& aE = (i==0) ? aE1 : aE2;
                 //
-                gp_Pnt PonEL = BAcurve.Value(lpar);
-                if (PonEL.Distance(PonE) <= Precision::PConfusion()) {
-                  Standard_Boolean bIsHole;
-                  TopoDS_Edge aE1, aE2;
-                  TopoDS_Wire aW1, aW2;
-                  Handle(Geom_Plane) aPL;
-                  IntTools_FClass2d aClsf;
-                  //
-                  if (aCirc.Radius()>aCircOE.Radius()) {
-                    aE1 = anEdge;
-                    aE2 = OE;
-                  } else {
-                    aE1 = OE;
-                    aE2 = anEdge;
-                  }
-                  //
-                  BB.MakeWire(aW1);
-                  BB.Add(aW1, aE1);
-                  BB.MakeWire(aW2);
-                  BB.Add(aW2, aE2);
-                  //
-                  aPL = new Geom_Plane(aCirc.Location(), CircAxisDir);
-                  for (Standard_Integer i = 0; i < 2; ++i) {
-                    TopoDS_Wire& aW = (i==0) ? aW1 : aW2;
-                    TopoDS_Edge& aE = (i==0) ? aE1 : aE2;
-                    //
-                    TopoDS_Face aFace;
-                    BB.MakeFace(aFace, aPL, Precision::Confusion());
-                    BB.Add (aFace, aW);
-                    aClsf.Init(aFace, Precision::Confusion());
-                    bIsHole=aClsf.IsHole();
-                    if ((bIsHole && !i) || (!bIsHole && i)) {
-                      aW.Nullify();
-                      BB.MakeWire(aW);
-                      BB.Add(aW, aE.Reversed());
-                    }
-                  }
-                  //
-                  BB.MakeFace(NewFace, aPL, Precision::Confusion());
-                  BB.Add(NewFace, aW1);
-                  BB.Add(NewFace, aW2);
+                TopoDS_Face aFace;
+                BB.MakeFace(aFace, aPL, Precision::Confusion());
+                BB.Add (aFace, aW);
+                aClsf.Init(aFace, Precision::Confusion());
+                bIsHole=aClsf.IsHole();
+                if ((bIsHole && !i) || (!bIsHole && i)) {
+                  aW.Nullify();
+                  BB.MakeWire(aW);
+                  BB.Add(aW, aE.Reversed());
                 }
               }
-              else //case of cone
+              //
+              BB.MakeFace(NewFace, aPL, Precision::Confusion());
+              BB.Add(NewFace, aW1);
+              BB.Add(NewFace, aW2);
+            }
+          }
+          else //case of cone
+          {
+            gp_Cone theCone = gce_MakeCone(aCirc.Location(), aCircOE.Location(),
+              aCirc.Radius(), aCircOE.Radius());
+            gp_Ax3 theAx3(aCirc.Position());
+            if (CircAxisDir * theCone.Axis().Direction() < 0.)
+            {
+              theAx3.ZReverse();
+              CircAxisDir.Reverse();
+            }
+            theCone.SetPosition(theAx3);
+            theSurf = new Geom_ConicalSurface(theCone);
+          }
+          if (!IsPlanar) {
+            TopLoc_Location Loc;
+            EdgeLine2d = new Geom2d_Line(gp_Pnt2d(0., 0.), gp_Dir2d(1., 0.));
+            BB.UpdateEdge(anEdge, EdgeLine2d, theSurf, Loc, Precision::Confusion());
+            Standard_Real Coeff = (OffsetDir * CircAxisDir > 0.)? 1. : -1.;
+            OELine2d = new Geom2d_Line(gp_Pnt2d(0., OffsetVal*Coeff), gp_Dir2d(1., 0.));
+            BB.UpdateEdge(OE, OELine2d, theSurf, Loc, Precision::Confusion());
+            aLine2d  = new Geom2d_Line(gp_Pnt2d(ParV2, 0.), gp_Dir2d(0., Coeff));
+            aLine2d2 = new Geom2d_Line(gp_Pnt2d(ParV1, 0.), gp_Dir2d(0., Coeff));
+            if (E3.IsSame(E4))
+            {
+              if (Coeff > 0.)
+                BB.UpdateEdge(E3, aLine2d, aLine2d2, theSurf, Loc, Precision::Confusion());
+              else
               {
-                gp_Cone theCone = gce_MakeCone(aCirc.Location(), aCircOE.Location(),
-                                               aCirc.Radius(), aCircOE.Radius());
-                gp_Ax3 theAx3(aCirc.Position());
-                if (CircAxisDir * theCone.Axis().Direction() < 0.)
-                {
-                  theAx3.ZReverse();
-                  CircAxisDir.Reverse();
-                }
-                theCone.SetPosition(theAx3);
-                theSurf = new Geom_ConicalSurface(theCone);
-              }
-              if (!IsPlanar) {
-                TopLoc_Location Loc;
-                EdgeLine2d = new Geom2d_Line(gp_Pnt2d(0., 0.), gp_Dir2d(1., 0.));
-                BB.UpdateEdge(anEdge, EdgeLine2d, theSurf, Loc, Precision::Confusion());
-                Standard_Real Coeff = (OffsetDir * CircAxisDir > 0.)? 1. : -1.;
-                OELine2d = new Geom2d_Line(gp_Pnt2d(0., OffsetVal*Coeff), gp_Dir2d(1., 0.));
-                BB.UpdateEdge(OE, OELine2d, theSurf, Loc, Precision::Confusion());
-                aLine2d  = new Geom2d_Line(gp_Pnt2d(ParV2, 0.), gp_Dir2d(0., Coeff));
-                aLine2d2 = new Geom2d_Line(gp_Pnt2d(ParV1, 0.), gp_Dir2d(0., Coeff));
-                if (E3.IsSame(E4))
-                {
-                  if (Coeff > 0.)
-                    BB.UpdateEdge(E3, aLine2d, aLine2d2, theSurf, Loc, Precision::Confusion());
-                  else
-                  {
-                    BB.UpdateEdge(E3, aLine2d2, aLine2d, theSurf, Loc, Precision::Confusion());
-                    theWire.Nullify();
-                    BB.MakeWire(theWire);
-                    BB.Add(theWire, anEdge.Oriented(TopAbs_REVERSED));
-                    BB.Add(theWire, E4);
-                    BB.Add(theWire, OE.Oriented(TopAbs_FORWARD));
-                    BB.Add(theWire, E3);
-                    theWire.Closed(Standard_True);
-                  }
-                }
-                else
-                {
-                  BB.SameParameter(E3, Standard_False);
-                  BB.SameRange(E3, Standard_False);
-                  BB.SameParameter(E4, Standard_False);
-                  BB.SameRange(E4, Standard_False);
-                  BB.UpdateEdge(E3, aLine2d,  theSurf, Loc, Precision::Confusion());
-                  BB.Range(E3, theSurf, Loc, 0., OffsetVal);
-                  BB.UpdateEdge(E4, aLine2d2, theSurf, Loc, Precision::Confusion());
-                  BB.Range(E4, theSurf, Loc, 0., OffsetVal);
-                }
-                NewFace = BRepLib_MakeFace(theSurf, theWire);
+                BB.UpdateEdge(E3, aLine2d2, aLine2d, theSurf, Loc, Precision::Confusion());
+                theWire.Nullify();
+                BB.MakeWire(theWire);
+                BB.Add(theWire, anEdge.Oriented(TopAbs_REVERSED));
+                BB.Add(theWire, E4);
+                BB.Add(theWire, OE.Oriented(TopAbs_FORWARD));
+                BB.Add(theWire, E3);
+                theWire.Closed(Standard_True);
               }
-            } //cylinder or cone
-          } //if both edges are arcs of circles
-         if (NewFace.IsNull())
-           {
-             BRepLib_MakeFace MF(theWire, Standard_True); //Only plane
-             if (MF.Error() == BRepLib_FaceDone)
-               {
-                 NewFace = MF.Face();
-                 IsPlanar = Standard_True;
-               }
-             else //Extrusion (by thrusections)
-               {
-                 Handle(Geom_Curve) EdgeCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
-                 Handle(Geom_TrimmedCurve) TrEdgeCurve =
-                   new Geom_TrimmedCurve( EdgeCurve, fpar, lpar );
-                 Standard_Real fparOE, lparOE;
-                 Handle(Geom_Curve) OffsetCurve = BRep_Tool::Curve(OE, fparOE, lparOE);
-                 Handle(Geom_TrimmedCurve) TrOffsetCurve =
-                   new Geom_TrimmedCurve( OffsetCurve, fparOE, lparOE );
-                 GeomFill_Generator ThrusecGenerator;
-                 ThrusecGenerator.AddCurve( TrEdgeCurve );
-                 ThrusecGenerator.AddCurve( TrOffsetCurve );
-                 ThrusecGenerator.Perform( Precision::PConfusion() );
-                 theSurf = ThrusecGenerator.Surface();
-                 //theSurf = new Geom_SurfaceOfLinearExtrusion( TrOffsetCurve, OffsetDir );
-                 Standard_Real Uf, Ul, Vf, Vl;
-                 theSurf->Bounds(Uf, Ul, Vf, Vl);
-                 TopLoc_Location Loc;
-                 EdgeLine2d = new Geom2d_Line(gp_Pnt2d(0., Vf), gp_Dir2d(1., 0.));
-                 BB.UpdateEdge(anEdge, EdgeLine2d, theSurf, Loc, Precision::Confusion());
-                 OELine2d = new Geom2d_Line(gp_Pnt2d(0., Vl), gp_Dir2d(1., 0.));
-                 BB.UpdateEdge(OE, OELine2d, theSurf, Loc, Precision::Confusion());
-                 Standard_Real UonV1 = (ToReverse)? Ul : Uf;
-                 Standard_Real UonV2 = (ToReverse)? Uf : Ul;
-                 aLine2d  = new Geom2d_Line(gp_Pnt2d(UonV2, 0.), gp_Dir2d(0., 1.));
-                 aLine2d2 = new Geom2d_Line(gp_Pnt2d(UonV1, 0.), gp_Dir2d(0., 1.));
-                 if (E3.IsSame(E4))
-                   {
-                     BB.UpdateEdge(E3, aLine2d, aLine2d2, theSurf, Loc, Precision::Confusion());
-                     Handle(Geom_Curve) BSplC34 = theSurf->UIso( Uf );
-                     BB.UpdateEdge(E3, BSplC34, Precision::Confusion());
-                     BB.Range(E3, Vf, Vl);
-                   }
-                 else
-                   {
-                     BB.SameParameter(E3, Standard_False);
-                     BB.SameRange(E3, Standard_False);
-                     BB.SameParameter(E4, Standard_False);
-                     BB.SameRange(E4, Standard_False);
-                     BB.UpdateEdge(E3, aLine2d,  theSurf, Loc, Precision::Confusion());
-                     BB.Range(E3, theSurf, Loc, Vf, Vl);
-                     BB.UpdateEdge(E4, aLine2d2, theSurf, Loc, Precision::Confusion());
-                     BB.Range(E4, theSurf, Loc, Vf, Vl);
-                     Handle(Geom_Curve) BSplC3 = theSurf->UIso( UonV2 );
-                     BB.UpdateEdge(E3, BSplC3, Precision::Confusion());
-                     BB.Range(E3, Vf, Vl, Standard_True); //only for 3d curve
-                     Handle(Geom_Curve) BSplC4 = theSurf->UIso( UonV1 );
-                     BB.UpdateEdge(E4, BSplC4, Precision::Confusion());
-                     BB.Range(E4, Vf, Vl, Standard_True); //only for 3d curve
-                   }
-                 NewFace = BRepLib_MakeFace(theSurf, theWire);
-               }
-           }
-         if (!IsPlanar)
-           {
-             Standard_Real fparOE = BAcurveOE.FirstParameter();
-             Standard_Real lparOE = BAcurveOE.LastParameter();
-             TopLoc_Location Loc;
-             if (Abs(fpar - fparOE) > Precision::Confusion())
-               {
-                 const TopoDS_Edge& anE4 = (ToReverse)? E3 : E4;
-                 gp_Pnt2d fp2d   = EdgeLine2d->Value(fpar);
-                 gp_Pnt2d fp2dOE = OELine2d->Value(fparOE);
-                 aLine2d2 = GCE2d_MakeLine( fp2d, fp2dOE ).Value();
-                 Handle(Geom_Curve) aCurve;
-                 Standard_Real FirstPar = 0., LastPar = fp2d.Distance(fp2dOE);
-                 Geom2dAdaptor_Curve AC2d( aLine2d2, FirstPar, LastPar );
-                 GeomAdaptor_Surface GAsurf( theSurf );
-                 Handle(Geom2dAdaptor_HCurve) HC2d  = new Geom2dAdaptor_HCurve( AC2d );
-                 Handle(GeomAdaptor_HSurface) HSurf = new GeomAdaptor_HSurface( GAsurf );
-                 Adaptor3d_CurveOnSurface ConS( HC2d, HSurf );
-                 Standard_Real max_deviation = 0., average_deviation;
-                 GeomLib::BuildCurve3d(Precision::Confusion(),
-                                       ConS, FirstPar, LastPar,
-                                       aCurve, max_deviation, average_deviation);
-                 BB.UpdateEdge( anE4, aCurve, max_deviation );
-                 BB.UpdateEdge( anE4, aLine2d2, theSurf, Loc, max_deviation );
-                 BB.Range( anE4, FirstPar, LastPar );
-               }
-             if (Abs(lpar - lparOE) > Precision::Confusion())
-               {
-                 const TopoDS_Edge& anE3 = (ToReverse)? E4 : E3;
-                 gp_Pnt2d lp2d   = EdgeLine2d->Value(lpar);
-                 gp_Pnt2d lp2dOE = OELine2d->Value(lparOE);
-                 aLine2d = GCE2d_MakeLine( lp2d, lp2dOE ).Value();
-                 Handle(Geom_Curve) aCurve;
-                 Standard_Real FirstPar = 0., LastPar = lp2d.Distance(lp2dOE);
-                 Geom2dAdaptor_Curve AC2d( aLine2d, FirstPar, LastPar );
-                 GeomAdaptor_Surface GAsurf( theSurf );
-                 Handle(Geom2dAdaptor_HCurve) HC2d  = new Geom2dAdaptor_HCurve( AC2d );
-                 Handle(GeomAdaptor_HSurface) HSurf = new GeomAdaptor_HSurface( GAsurf );
-                 Adaptor3d_CurveOnSurface ConS( HC2d, HSurf );
-                 Standard_Real max_deviation = 0., average_deviation;
-                 GeomLib::BuildCurve3d(Precision::Confusion(),
-                                       ConS, FirstPar, LastPar,
-                                       aCurve, max_deviation, average_deviation);
-                 BB.UpdateEdge( anE3, aCurve, max_deviation );
-                 BB.UpdateEdge( anE3, aLine2d, theSurf, Loc, max_deviation );
-                 BB.Range( anE3, FirstPar, LastPar );
-               }
-           }
-         BRepLib::SameParameter(NewFace);
-         BRepTools::Update(NewFace);
-         myWalls.Append(NewFace);
-         if (ArcOnV2)
-           {
-             TopoDS_Edge anArc = TopoDS::Edge(myInitOffsetEdge.Image(V2).First());
-             TopoDS_Vertex arcV1, arcV2;
-             TopExp::Vertices(anArc, arcV1, arcV2);
-             Standard_Boolean ArcReverse = Standard_False;
-             if (!arcV1.IsSame(V3))
-               {
-                 TopoDS_Vertex aVtx = arcV1; arcV1 = arcV2; arcV2 = aVtx;
-                 ArcReverse = Standard_True;
-               }
-             TopoDS_Edge EA1, EA2;
-             //EA1 = (ToReverse)? E3 : TopoDS::Edge(E3.Reversed());
-             EA1 = E3;
-             EA1.Reverse();
-             if (ToReverse)
-               EA1.Reverse();
-             //////////////////////////////////////////////////////
-             if (V2.IsSame(StartVertex))
-               EA2 = StartEdge;
-             else
-               EA2 = BRepLib_MakeEdge( V2, arcV2 );
-             anArc.Orientation( ((ArcReverse)? TopAbs_REVERSED : TopAbs_FORWARD) );
-             if (EA1.Orientation() == TopAbs_REVERSED)
-               anArc.Reverse();
-             EA2.Orientation(TopAbs::Reverse(EA1.Orientation()));
-             TopoDS_Wire arcWire;
-             BB.MakeWire(arcWire);
-             BB.Add(arcWire, EA1);
-             BB.Add(arcWire, anArc);
-             BB.Add(arcWire, EA2);
-             BRepLib::BuildCurves3d( arcWire, myTol );
-             arcWire.Closed(Standard_True);
-             TopoDS_Face arcFace = BRepLib_MakeFace(arcWire, Standard_True);
-             BRepTools::Update(arcFace);
-             myWalls.Append(arcFace);
-             TopoDS_Shape localEA2 = EA2.Oriented(TopAbs_FORWARD);
-             const TopoDS_Edge& CEA2 = TopoDS::Edge(localEA2);
-             PrevEdge = CEA2;
-             PrevVertex = V2;
-           }
-         else
-           {
-             PrevEdge = E3;
-             PrevVertex = V2;
-           }
-         FirstStep = Standard_False;
-       }
+            }
+            else
+            {
+              BB.SameParameter(E3, Standard_False);
+              BB.SameRange(E3, Standard_False);
+              BB.SameParameter(E4, Standard_False);
+              BB.SameRange(E4, Standard_False);
+              BB.UpdateEdge(E3, aLine2d,  theSurf, Loc, Precision::Confusion());
+              BB.Range(E3, theSurf, Loc, 0., OffsetVal);
+              BB.UpdateEdge(E4, aLine2d2, theSurf, Loc, Precision::Confusion());
+              BB.Range(E4, theSurf, Loc, 0., OffsetVal);
+            }
+            NewFace = BRepLib_MakeFace(theSurf, theWire);
+          }
+        } //cylinder or cone
+      } //if both edges are arcs of circles
+      if (NewFace.IsNull())
+      {
+        BRepLib_MakeFace MF(theWire, Standard_True); //Only plane
+        if (MF.Error() == BRepLib_FaceDone)
+        {
+          NewFace = MF.Face();
+          IsPlanar = Standard_True;
+        }
+        else //Extrusion (by thrusections)
+        {
+          Handle(Geom_Curve) EdgeCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
+          Handle(Geom_TrimmedCurve) TrEdgeCurve =
+            new Geom_TrimmedCurve( EdgeCurve, fpar, lpar );
+          Standard_Real fparOE, lparOE;
+          Handle(Geom_Curve) OffsetCurve = BRep_Tool::Curve(OE, fparOE, lparOE);
+          Handle(Geom_TrimmedCurve) TrOffsetCurve =
+            new Geom_TrimmedCurve( OffsetCurve, fparOE, lparOE );
+          GeomFill_Generator ThrusecGenerator;
+          ThrusecGenerator.AddCurve( TrEdgeCurve );
+          ThrusecGenerator.AddCurve( TrOffsetCurve );
+          ThrusecGenerator.Perform( Precision::PConfusion() );
+          theSurf = ThrusecGenerator.Surface();
+          //theSurf = new Geom_SurfaceOfLinearExtrusion( TrOffsetCurve, OffsetDir );
+          Standard_Real Uf, Ul, Vf, Vl;
+          theSurf->Bounds(Uf, Ul, Vf, Vl);
+          TopLoc_Location Loc;
+          EdgeLine2d = new Geom2d_Line(gp_Pnt2d(0., Vf), gp_Dir2d(1., 0.));
+          BB.UpdateEdge(anEdge, EdgeLine2d, theSurf, Loc, Precision::Confusion());
+          OELine2d = new Geom2d_Line(gp_Pnt2d(0., Vl), gp_Dir2d(1., 0.));
+          BB.UpdateEdge(OE, OELine2d, theSurf, Loc, Precision::Confusion());
+          Standard_Real UonV1 = (ToReverse)? Ul : Uf;
+          Standard_Real UonV2 = (ToReverse)? Uf : Ul;
+          aLine2d  = new Geom2d_Line(gp_Pnt2d(UonV2, 0.), gp_Dir2d(0., 1.));
+          aLine2d2 = new Geom2d_Line(gp_Pnt2d(UonV1, 0.), gp_Dir2d(0., 1.));
+          if (E3.IsSame(E4))
+          {
+            BB.UpdateEdge(E3, aLine2d, aLine2d2, theSurf, Loc, Precision::Confusion());
+            Handle(Geom_Curve) BSplC34 = theSurf->UIso( Uf );
+            BB.UpdateEdge(E3, BSplC34, Precision::Confusion());
+            BB.Range(E3, Vf, Vl);
+          }
+          else
+          {
+            BB.SameParameter(E3, Standard_False);
+            BB.SameRange(E3, Standard_False);
+            BB.SameParameter(E4, Standard_False);
+            BB.SameRange(E4, Standard_False);
+            BB.UpdateEdge(E3, aLine2d,  theSurf, Loc, Precision::Confusion());
+            BB.Range(E3, theSurf, Loc, Vf, Vl);
+            BB.UpdateEdge(E4, aLine2d2, theSurf, Loc, Precision::Confusion());
+            BB.Range(E4, theSurf, Loc, Vf, Vl);
+            Handle(Geom_Curve) BSplC3 = theSurf->UIso( UonV2 );
+            BB.UpdateEdge(E3, BSplC3, Precision::Confusion());
+            BB.Range(E3, Vf, Vl, Standard_True); //only for 3d curve
+            Handle(Geom_Curve) BSplC4 = theSurf->UIso( UonV1 );
+            BB.UpdateEdge(E4, BSplC4, Precision::Confusion());
+            BB.Range(E4, Vf, Vl, Standard_True); //only for 3d curve
+          }
+          NewFace = BRepLib_MakeFace(theSurf, theWire);
+        }
+      }
+      if (!IsPlanar)
+      {
+        Standard_Real fparOE = BAcurveOE.FirstParameter();
+        Standard_Real lparOE = BAcurveOE.LastParameter();
+        TopLoc_Location Loc;
+        if (Abs(fpar - fparOE) > Precision::Confusion())
+        {
+          const TopoDS_Edge& anE4 = (ToReverse)? E3 : E4;
+          gp_Pnt2d fp2d   = EdgeLine2d->Value(fpar);
+          gp_Pnt2d fp2dOE = OELine2d->Value(fparOE);
+          aLine2d2 = GCE2d_MakeLine( fp2d, fp2dOE ).Value();
+          Handle(Geom_Curve) aCurve;
+          Standard_Real FirstPar = 0., LastPar = fp2d.Distance(fp2dOE);
+          Geom2dAdaptor_Curve AC2d( aLine2d2, FirstPar, LastPar );
+          GeomAdaptor_Surface GAsurf( theSurf );
+          Handle(Geom2dAdaptor_HCurve) HC2d  = new Geom2dAdaptor_HCurve( AC2d );
+          Handle(GeomAdaptor_HSurface) HSurf = new GeomAdaptor_HSurface( GAsurf );
+          Adaptor3d_CurveOnSurface ConS( HC2d, HSurf );
+          Standard_Real max_deviation = 0., average_deviation;
+          GeomLib::BuildCurve3d(Precision::Confusion(),
+            ConS, FirstPar, LastPar,
+            aCurve, max_deviation, average_deviation);
+          BB.UpdateEdge( anE4, aCurve, max_deviation );
+          BB.UpdateEdge( anE4, aLine2d2, theSurf, Loc, max_deviation );
+          BB.Range( anE4, FirstPar, LastPar );
+        }
+        if (Abs(lpar - lparOE) > Precision::Confusion())
+        {
+          const TopoDS_Edge& anE3 = (ToReverse)? E4 : E3;
+          gp_Pnt2d lp2d   = EdgeLine2d->Value(lpar);
+          gp_Pnt2d lp2dOE = OELine2d->Value(lparOE);
+          aLine2d = GCE2d_MakeLine( lp2d, lp2dOE ).Value();
+          Handle(Geom_Curve) aCurve;
+          Standard_Real FirstPar = 0., LastPar = lp2d.Distance(lp2dOE);
+          Geom2dAdaptor_Curve AC2d( aLine2d, FirstPar, LastPar );
+          GeomAdaptor_Surface GAsurf( theSurf );
+          Handle(Geom2dAdaptor_HCurve) HC2d  = new Geom2dAdaptor_HCurve( AC2d );
+          Handle(GeomAdaptor_HSurface) HSurf = new GeomAdaptor_HSurface( GAsurf );
+          Adaptor3d_CurveOnSurface ConS( HC2d, HSurf );
+          Standard_Real max_deviation = 0., average_deviation;
+          GeomLib::BuildCurve3d(Precision::Confusion(),
+            ConS, FirstPar, LastPar,
+            aCurve, max_deviation, average_deviation);
+          BB.UpdateEdge( anE3, aCurve, max_deviation );
+          BB.UpdateEdge( anE3, aLine2d, theSurf, Loc, max_deviation );
+          BB.Range( anE3, FirstPar, LastPar );
+        }
+      }
+      BRepLib::SameParameter(NewFace);
+      BRepTools::Update(NewFace);
+      //Check orientation
+      TopAbs_Orientation anOr = OrientationOfEdgeInFace(anEdge, aFaceOfEdge);
+      TopAbs_Orientation OrInNewFace = OrientationOfEdgeInFace(anEdge, NewFace);
+      if (OrInNewFace != TopAbs::Reverse(anOr))
+        NewFace.Reverse();
+      ///////////////////
+      myWalls.Append(NewFace);
+      if (ArcOnV2)
+      {
+        TopoDS_Edge anArc = TopoDS::Edge(myInitOffsetEdge.Image(V2).First());
+        TopoDS_Vertex arcV1, arcV2;
+        TopExp::Vertices(anArc, arcV1, arcV2);
+        Standard_Boolean ArcReverse = Standard_False;
+        if (!arcV1.IsSame(V3))
+        {
+          TopoDS_Vertex aVtx = arcV1; arcV1 = arcV2; arcV2 = aVtx;
+          ArcReverse = Standard_True;
+        }
+        TopoDS_Edge EA1, EA2;
+        //EA1 = (ToReverse)? E3 : TopoDS::Edge(E3.Reversed());
+        EA1 = E3;
+        EA1.Reverse();
+        if (ToReverse)
+          EA1.Reverse();
+        //////////////////////////////////////////////////////
+        if (V2.IsSame(StartVertex))
+          EA2 = StartEdge;
+        else
+          EA2 = BRepLib_MakeEdge( V2, arcV2 );
+        anArc.Orientation( ((ArcReverse)? TopAbs_REVERSED : TopAbs_FORWARD) );
+        if (EA1.Orientation() == TopAbs_REVERSED)
+          anArc.Reverse();
+        EA2.Orientation(TopAbs::Reverse(EA1.Orientation()));
+        TopoDS_Wire arcWire;
+        BB.MakeWire(arcWire);
+        BB.Add(arcWire, EA1);
+        BB.Add(arcWire, anArc);
+        BB.Add(arcWire, EA2);
+        BRepLib::BuildCurves3d( arcWire, myTol );
+        arcWire.Closed(Standard_True);
+        TopoDS_Face arcFace = BRepLib_MakeFace(arcWire, Standard_True);
+        BRepTools::Update(arcFace);
+        myWalls.Append(arcFace);
+        TopoDS_Shape localEA2 = EA2.Oriented(TopAbs_FORWARD);
+        const TopoDS_Edge& CEA2 = TopoDS::Edge(localEA2);
+        PrevEdge = CEA2;
+        PrevVertex = V2;
+      }
+      else
+      {
+        if (isBuildFromScratch)
+        {
+          PrevEdge = TopoDS::Edge(E4);
+          PrevVertex = V1;
+          isBuildFromScratch = Standard_False;
+        }
+        else
+        {
+          PrevEdge = E3;
+          PrevVertex = V2;
+        }
+      }
+      FirstStep = Standard_False;
     }
+  }
 }
 
 //=======================================================================
@@ -2844,35 +3023,69 @@ void BRepOffset_MakeOffset::MakeShells ()
 {
 #ifdef OCCT_DEBUG
   if (ChronBuild) {  
-    cout << " RECONSTRUCTION OF SHELLS:" << endl;
+    std::cout << " RECONSTRUCTION OF SHELLS:" << std::endl;
     Clock.Reset();
     Clock.Start();
   }
 #endif
-  BRepTools_Quilt Glue;
+  //
+  // Prepare list of splits of the offset faces to make the shells
+  TopTools_ListOfShape aLSF;
   const TopTools_ListOfShape& R = myImageOffset.Roots();
   TopTools_ListIteratorOfListOfShape it(R);
-
-  for ( ; it.More(); it.Next()) {
+  //
+  for (; it.More(); it.Next()) {
+    TopoDS_Shape aF = it.Value();
+    if (myThickening) //offsetted faces must change their orientations
+      aF.Reverse();
+    //
     TopTools_ListOfShape Image;
-    myImageOffset.LastImage(it.Value(),Image);
+    myImageOffset.LastImage(aF,Image);
     TopTools_ListIteratorOfListOfShape it2(Image);
-    for ( ; it2.More(); it2.Next()) {
-      Glue.Add(it2.Value());
+    for (; it2.More(); it2.Next()) {
+      const TopoDS_Shape& aFIm = it2.Value();
+      aLSF.Append(aFIm);
     }
   }
-
-  if (myThickening)
-  {
+  //
+  if (myThickening) {
     TopExp_Explorer Explo(myShape, TopAbs_FACE);
-    for (; Explo.More(); Explo.Next())
-           Glue.Add(Explo.Current());
-      
-    for (it.Initialize(myWalls); it.More(); it.Next())
-           Glue.Add(it.Value());
+    for (; Explo.More(); Explo.Next()) {
+      const TopoDS_Shape& aF = Explo.Current();
+      aLSF.Append(aF);
+    }
+    //
+    it.Initialize(myWalls);
+    for (; it.More(); it.Next()) {
+      const TopoDS_Shape& aF = it.Value();
+      aLSF.Append(aF);
+    }
+  }
+  //
+  if (aLSF.IsEmpty()) {
+    return;
+  }
+  //
+  Standard_Boolean bDone = Standard_False;
+  if ((myJoin == GeomAbs_Intersection) && myInter &&
+      !myThickening && myFaces.IsEmpty() &&
+      IsSolid(myShape) && myIsPlanar) {
+    //
+    TopoDS_Shape aShells;
+    bDone = BuildShellsCompleteInter(aLSF, myImageOffset, aShells);
+    if (bDone) {
+      myOffsetShape = aShells;
+    }
+  }
+  //
+  if (!bDone) {
+    BRepTools_Quilt Glue;
+    TopTools_ListIteratorOfListOfShape aItLS(aLSF);
+    for (; aItLS.More(); aItLS.Next()) {
+      Glue.Add(aItLS.Value());
+    }
+    myOffsetShape = Glue.Shells();
   }
-
-  myOffsetShape = Glue.Shells();
   //
   //Set correct value for closed flag
   TopExp_Explorer Explo(myOffsetShape, TopAbs_SHELL);
@@ -2886,7 +3099,7 @@ void BRepOffset_MakeOffset::MakeShells ()
         aS.Closed(Standard_True);
       }
     }
-  }               
+  }
 }
 
 //=======================================================================
@@ -2930,35 +3143,29 @@ void BRepOffset_MakeOffset::MakeSolid ()
       }
     }
   }
-  TopoDS_Iterator anIt(Sol);
-  Standard_Boolean SolIsNull = !anIt.More();
+  Standard_Integer nbs = Sol.NbChildren();
+  Standard_Boolean SolIsNull = (nbs == 0);
   //Checking solid
-  if(!SolIsNull)
+  if (nbs > 1)
   {
-    Standard_Integer nbs = 0;
-    while(anIt.More()) {anIt.Next(); ++nbs;}
-    if(nbs > 1)
+    BRepCheck_Analyzer aCheck (Sol, Standard_False);
+    if (!aCheck.IsValid ())
     {
-      BRepCheck_Analyzer aCheck(Sol, Standard_False);
-      if(!aCheck.IsValid())
+      TopTools_ListOfShape aSolList;
+      CorrectSolid (Sol, aSolList);
+      if (!aSolList.IsEmpty ())
       {
-        TopTools_ListOfShape aSolList;
-        CorrectSolid(Sol, aSolList);
-        if(!aSolList.IsEmpty())
+        B.Add (NC, Sol);
+        TopTools_ListIteratorOfListOfShape aSLIt (aSolList);
+        for (; aSLIt.More (); aSLIt.Next ())
         {
-          B.Add(NC, Sol);
-          TopTools_ListIteratorOfListOfShape aSLIt(aSolList);
-          for(; aSLIt.More(); aSLIt.Next())
-          {
-            B.Add(NC, aSLIt.Value());
-          }
-          SolIsNull = Standard_True;
+          B.Add (NC, aSLIt.Value ());
         }
+        SolIsNull = Standard_True;
       }
     }
   }
-  anIt.Initialize(NC);
-  Standard_Boolean NCIsNull = !anIt.More();
+  Standard_Boolean NCIsNull = (NC.NbChildren() == 0);
   if((!SolIsNull) && (!NCIsNull))
   {
     B.Add(NC, Sol);
@@ -2991,7 +3198,7 @@ void BRepOffset_MakeOffset::MakeSolid ()
 //=======================================================================
 
 void BRepOffset_MakeOffset::SelectShells ()
-{  
+{
   TopTools_MapOfShape FreeEdges;
   TopExp_Explorer exp(myShape,TopAbs_EDGE);
   //-------------------------------------------------------------
@@ -3003,8 +3210,8 @@ void BRepOffset_MakeOffset::SelectShells ()
     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);                       
+      if (myAnalyse.Type(E).First().Type() == ChFiDS_FreeBound) {
+              FreeEdges.Add(E);                       
       }
     }  
   }
@@ -3070,7 +3277,7 @@ void BRepOffset_MakeOffset::EncodeRegularity ()
 {
 #ifdef OCCT_DEBUG
   if (ChronBuild) {  
-    cout << " CODING OF REGULARITIES:" << endl;
+    std::cout << " CODING OF REGULARITIES:" << std::endl;
     Clock.Reset();
     Clock.Start();
   }
@@ -3097,7 +3304,7 @@ void BRepOffset_MakeOffset::EncodeRegularity ()
     
     if (LofOF.Extent() != 2) {
 #ifdef OCCT_DEBUG_VERB
-    cout << " Edge shared by " << LofOF.Extent() << " Faces" << endl;
+    std::cout << " Edge shared by " << LofOF.Extent() << " Faces" << std::endl;
 #endif
       continue;
     }
@@ -3116,38 +3323,38 @@ void BRepOffset_MakeOffset::EncodeRegularity ()
  
     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);
-           }
-         }
-       }
+        // 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;
     }
@@ -3166,75 +3373,65 @@ void BRepOffset_MakeOffset::EncodeRegularity ()
       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);
+        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);
+        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;
-       }
+        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;
-       }
+        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);
-         }
-       }
+      TopTools_ListOfShape LE;
+      BRepOffset_Tool::FindCommonShapes(Root1, Root2, TopAbs_EDGE, LE);
+      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() == ChFiDS_Tangential) {
+            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());
-         }
-       }
-      }
+      BRepOffset_Tool::FindCommonShapes(Root1, Root2, TopAbs_VERTEX, LV);
       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;
-         }
-       }
+        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;
+          }
+        }
       }
     }
   }
@@ -3244,15 +3441,39 @@ void BRepOffset_MakeOffset::EncodeRegularity ()
 #endif
 }
 
-
-
+//=======================================================================
+//function : ComputeMaxDist
+//purpose  : 
+//=======================================================================
+Standard_Real ComputeMaxDist(const gp_Pln& thePlane,
+                             const Handle(Geom_Curve)& theCrv,
+                             const Standard_Real theFirst,
+                             const Standard_Real theLast)
+{
+  Standard_Real aMaxDist = 0.;
+  Standard_Integer i, NCONTROL = 23;
+  Standard_Real aPrm, aDist2;
+  gp_Pnt aP;
+  for (i = 0; i< NCONTROL; i++) {
+    aPrm = ((NCONTROL - 1 - i)*theFirst + i*theLast) / (NCONTROL - 1);
+    aP = theCrv->Value(aPrm);
+    if (Precision::IsInfinite(aP.X()) || Precision::IsInfinite(aP.Y())
+      || Precision::IsInfinite(aP.Z()))
+    {
+      return Precision::Infinite();
+    }
+    aDist2 = thePlane.SquareDistance(aP);
+    if (aDist2 > aMaxDist) aMaxDist = aDist2;  
+  }
+  return sqrt(aMaxDist)*1.05;
+}
 //=======================================================================
 //function : UpDateTolerance
 //purpose  : 
 //=======================================================================
 
 void UpdateTolerance (TopoDS_Shape& S,
-                                       const TopTools_IndexedMapOfShape& Faces)
+                      const TopTools_IndexedMapOfShape& Faces)
 {
   BRep_Builder B;
   TopTools_MapOfShape View;
@@ -3268,27 +3489,55 @@ void UpdateTolerance (TopoDS_Shape& S,
     }
   }
   
-  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);
+  Standard_Real Tol;
+  TopExp_Explorer ExpF;
+  for (ExpF.Init(S, TopAbs_FACE); ExpF.More(); ExpF.Next())
+  {
+    const TopoDS_Shape& F = ExpF.Current();
+    if (Faces.Contains(F))
+    {
+      continue;
+    }
+    BRepAdaptor_Surface aBAS(TopoDS::Face(F), Standard_False);
+    TopExp_Explorer Exp;
+    for (Exp.Init(F, TopAbs_EDGE); Exp.More(); Exp.Next()) {
+      TopoDS_Edge E = TopoDS::Edge(Exp.Current());
+      Standard_Boolean isUpdated = Standard_False;
+      if (aBAS.GetType() == GeomAbs_Plane)
+      {
+        //Edge does not seem to have pcurve on plane,
+        //so EdgeCorrector does not include it in tolerance calculation
+        Standard_Real aFirst, aLast;
+        Handle(Geom_Curve) aCrv = BRep_Tool::Curve(E, aFirst, aLast);
+        Standard_Real aMaxDist = ComputeMaxDist(aBAS.Plane(), aCrv, aFirst, aLast);
+        B.UpdateEdge(E, aMaxDist);
+        isUpdated = Standard_True;
+      }
+      if (View.Add(E))
+      {
+
+        BRepCheck_Edge EdgeCorrector(E);
+        Tol = EdgeCorrector.Tolerance();
+        B.UpdateEdge(E, Tol);
+        isUpdated = Standard_True;
+      }
+      if (isUpdated)
+      {
+        Tol = BRep_Tool::Tolerance(E);
+        // 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.);
+            BRepCheck_Vertex VertexCorrector(V[i]);
+            B.UpdateVertex(V[i], VertexCorrector.Tolerance());
+            // use the occasion to clean the vertices.
+            (TV->ChangePoints()).Clear();
+          }
+          B.UpdateVertex(V[i], Tol);
+        }
       }
     }
   }
@@ -3320,6 +3569,9 @@ void CorrectSolid(TopoDS_Solid& theSol, TopTools_ListOfShape& theSolList)
     aVols.Append(aVProps.Mass());
   }
   //
+  if (Abs(anOuterVol) < Precision::Confusion()) {
+    return;
+  }
   if(anOuterVol < 0.)
   {
     anOuterShell.Reverse();
@@ -3369,3 +3621,911 @@ void CorrectSolid(TopoDS_Solid& theSol, TopTools_ListOfShape& theSolList)
   }
   theSol = aNewSol;
 }
+
+//=======================================================================
+//function : CheckInputData
+//purpose  : Check input data for possiblity of offset perform.
+//=======================================================================
+Standard_Boolean BRepOffset_MakeOffset::CheckInputData()
+{
+  // Set initial error state.
+  myError = BRepOffset_NoError;
+  TopoDS_Shape aTmpShape;
+  myBadShape = aTmpShape;
+
+  // Non-null offset.
+  if (Abs(myOffset) <= myTol)
+  {
+    Standard_Boolean isFound = Standard_False;
+    TopTools_DataMapIteratorOfDataMapOfShapeReal anIter(myFaceOffset);
+    for( ; anIter.More(); anIter.Next())
+    {
+      if (Abs(anIter.Value()) > myTol)
+      {
+        isFound = Standard_True;
+        break;
+      }
+    }
+
+    if (!isFound)
+    {
+      // No face with non-null offset found.
+      myError = BRepOffset_NullOffset;
+      return Standard_False;
+    }
+  }
+
+  // Connectivity of input shape.
+  if (!IsConnectedShell(myShape))
+  {
+    myError = BRepOffset_NotConnectedShell;
+    return Standard_False;
+  }
+
+  // Normals check and continuity check.
+  const Standard_Integer aPntPerDim = 20; // 21 points on each dimension.
+  Standard_Real aUmin, aUmax, aVmin, aVmax;
+  TopExp_Explorer anExpSF(myShape, TopAbs_FACE);
+  NCollection_Map<Handle(TopoDS_TShape)> aPresenceMap;
+  TopLoc_Location L;
+  gp_Pnt2d aPnt2d;
+  for( ; anExpSF.More(); anExpSF.Next())
+  {
+    const TopoDS_Face& aF = TopoDS::Face(anExpSF.Current());
+
+    if (aPresenceMap.Contains(aF.TShape()))
+    {
+      // Not perform computations with partner shapes,
+      // since they are contain same geometry.
+      continue;
+    }
+    aPresenceMap.Add(aF.TShape());
+
+    const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(aF, L);
+    BRepTools::UVBounds(aF, aUmin, aUmax, aVmin, aVmax);
+
+    // Continuity check.
+    if (aSurf->Continuity() == GeomAbs_C0)
+    {
+      myError = BRepOffset_C0Geometry;
+      return Standard_False;
+    }
+
+    // Get degenerated points, to avoid check them.
+    NCollection_Vector<gp_Pnt> aBad3dPnts;
+    TopExp_Explorer anExpFE(aF, TopAbs_EDGE);
+    for( ; anExpFE.More(); anExpFE.Next())
+    {
+      const TopoDS_Edge &aE = TopoDS::Edge(anExpFE.Current());
+      if (BRep_Tool::Degenerated(aE))
+      {
+        aBad3dPnts.Append(BRep_Tool::Pnt((TopExp::FirstVertex(aE))));
+      }
+    }
+
+    // Geometry grid check.
+    for(Standard_Integer i = 0; i <= aPntPerDim; i++)
+    {
+      Standard_Real aUParam = aUmin + (aUmax - aUmin) * i / aPntPerDim;
+      for(Standard_Integer j = 0; j <= aPntPerDim; j++)
+      {
+        Standard_Real aVParam = aVmin + (aVmax - aVmin) * j / aPntPerDim;
+
+        myError = checkSinglePoint(aUParam, aVParam, aSurf, aBad3dPnts);
+        if (myError != BRepOffset_NoError)
+          return Standard_False;
+      }
+    }
+
+    // Vertex list check.
+    TopExp_Explorer anExpFV(aF, TopAbs_VERTEX);
+    for( ; anExpFV.More(); anExpFV.Next())
+    {
+      const TopoDS_Vertex &aV = TopoDS::Vertex(anExpFV.Current());
+      aPnt2d = BRep_Tool::Parameters(aV, aF);
+
+      myError = checkSinglePoint(aPnt2d.X(), aPnt2d.Y(), aSurf, aBad3dPnts);
+      if (myError != BRepOffset_NoError)
+        return Standard_False;
+    }
+  }
+
+  return Standard_True;
+}
+
+
+//=======================================================================
+//function : GetBadShape
+//purpose  : Get shape where problems detected.
+//=======================================================================
+const TopoDS_Shape& BRepOffset_MakeOffset::GetBadShape() const
+{
+  return myBadShape;
+}
+
+//=======================================================================
+//function : RemoveInternalEdges
+//purpose  : 
+//=======================================================================
+void BRepOffset_MakeOffset::RemoveInternalEdges()
+{
+  Standard_Boolean bRemoveWire, bRemoveEdge;
+  TopExp_Explorer aExpF, aExpW, aExpE;
+  TopTools_IndexedDataMapOfShapeListOfShape aDMELF;
+  //
+  TopExp::MapShapesAndAncestors(myOffsetShape, TopAbs_EDGE, TopAbs_FACE, aDMELF);
+  //
+  aExpF.Init(myOffsetShape, TopAbs_FACE);
+  for (; aExpF.More(); aExpF.Next()) {
+    TopoDS_Face& aF = *(TopoDS_Face*)&aExpF.Current();
+    //
+    TopTools_ListOfShape aLIW;
+    //
+    aExpW.Init(aF, TopAbs_WIRE);
+    for (; aExpW.More(); aExpW.Next()) {
+      TopoDS_Wire& aW = *(TopoDS_Wire*)&aExpW.Current();
+      //
+      bRemoveWire = Standard_True;
+      TopTools_ListOfShape aLIE;
+      //
+      aExpE.Init(aW, TopAbs_EDGE);
+      for (; aExpE.More(); aExpE.Next()) {
+        const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExpE.Current();
+        if (aE.Orientation() != TopAbs_INTERNAL) {
+          bRemoveWire = Standard_False;
+          continue;
+        }
+        //
+        const TopTools_ListOfShape& aLF = aDMELF.FindFromKey(aE);
+        bRemoveEdge = (aLF.Extent() == 1);
+        if (bRemoveEdge) {
+          aLIE.Append(aE);
+        }
+        else {
+          bRemoveWire = Standard_False;
+        }
+      }
+      //
+      if (bRemoveWire) {
+        aLIW.Append(aW);
+      }
+      else if (aLIE.Extent()) {
+        RemoveShapes(aW, aLIE);
+      }
+    }
+    //
+    if (aLIW.Extent()) {
+      RemoveShapes(aF, aLIW);
+    }
+  }
+}
+
+//=======================================================================
+// static methods implementation
+//=======================================================================
+
+//=======================================================================
+//function : checkSinglePoint
+//purpose  : Check single point on surface for bad normals
+//=======================================================================
+BRepOffset_Error checkSinglePoint(const Standard_Real theUParam,
+                                  const Standard_Real theVParam,
+                                  const Handle(Geom_Surface)& theSurf,
+                                  const NCollection_Vector<gp_Pnt>& theBadPoints)
+{
+  gp_Pnt aPnt;
+  gp_Vec aD1U, aD1V;
+  theSurf->D1(theUParam, theVParam, aPnt, aD1U, aD1V);
+
+  if (aD1U.SquareMagnitude() < Precision::SquareConfusion() ||
+      aD1V.SquareMagnitude() < Precision::SquareConfusion() )
+  {
+    Standard_Boolean isKnownBadPnt = Standard_False;
+    for(Standard_Integer anIdx  = theBadPoints.Lower();
+                         anIdx <= theBadPoints.Upper();
+                       ++anIdx)
+    {
+      if (aPnt.SquareDistance(theBadPoints(anIdx)) < Precision::SquareConfusion())
+      {
+        isKnownBadPnt = Standard_True;
+        break;
+      }
+    } // for(Standard_Integer anIdx  = theBadPoints.Lower();
+
+    if (!isKnownBadPnt)
+    {
+      return BRepOffset_BadNormalsOnGeometry;
+    }
+    else
+    {
+      return BRepOffset_NoError;
+    }
+  } //  if (aD1U.SquareMagnitude() < Precision::SquareConfusion() ||
+
+  if (aD1U.IsParallel(aD1V, Precision::Confusion()))
+  {
+    // Isolines are collinear.
+    return BRepOffset_BadNormalsOnGeometry;
+  }
+
+  return BRepOffset_NoError;
+}
+
+//=======================================================================
+//function : RemoveShapes
+//purpose  : Removes the shapes <theLS> from the shape <theS>
+//=======================================================================
+void RemoveShapes(TopoDS_Shape& theS,
+                  const TopTools_ListOfShape& theLS)
+{
+  BRep_Builder aBB;
+  //
+  Standard_Boolean bFree = theS.Free();
+  theS.Free(Standard_True);
+  //
+  TopTools_ListIteratorOfListOfShape aIt(theLS);
+  for (; aIt.More(); aIt.Next()) {
+    const TopoDS_Shape& aSI = aIt.Value();
+    aBB.Remove(theS, aSI);
+  }
+  //
+  theS.Free(bFree);
+}
+
+//=======================================================================
+//function : UpdateHistory
+//purpose  : Updates the history information
+//=======================================================================
+void UpdateHistory(const TopTools_ListOfShape& theLF,
+                   BOPAlgo_Builder& theGF,
+                   BRepAlgo_Image& theImage)
+{
+  TopTools_ListIteratorOfListOfShape aIt(theLF);
+  for (; aIt.More(); aIt.Next()) {
+    const TopoDS_Shape& aF = aIt.Value();
+    const TopTools_ListOfShape& aLFIm = theGF.Modified(aF);
+    if (aLFIm.Extent()) {
+      if (theImage.HasImage(aF)) {
+        theImage.Add(aF, aLFIm);
+      }
+      else {
+        theImage.Bind(aF, aLFIm);
+      }
+    }
+  }
+}
+
+//=======================================================================
+//function : IntersectEdges
+//purpose  : 
+//=======================================================================
+void BRepOffset_MakeOffset::IntersectEdges(const TopTools_ListOfShape& theFaces,
+                                           BRepOffset_DataMapOfShapeOffset& theMapSF,
+                                           TopTools_DataMapOfShapeShape& theMES,
+                                           TopTools_DataMapOfShapeShape& theBuild,
+                                           Handle(BRepAlgo_AsDes)& theAsDes,
+                                           Handle(BRepAlgo_AsDes)& theAsDes2d)
+{
+  Standard_Real aTolF;
+  TopTools_IndexedDataMapOfShapeListOfShape aDMVV;
+  // intersect edges created from edges
+  TopTools_IndexedMapOfShape aMFV;
+  for (TopTools_ListOfShape::Iterator it (theFaces); it.More(); it.Next())
+  {
+    const TopoDS_Face& aF  = TopoDS::Face (it.Value());
+    aTolF = BRep_Tool::Tolerance (aF);
+    if (!BRepOffset_Inter2d::ConnexIntByInt(aF, theMapSF(aF), theMES, theBuild, theAsDes2d,
+                                            myOffset, aTolF, myAnalyse, aMFV, aDMVV))
+    {
+      myError = BRepOffset_CannotExtentEdge;
+      return;
+    }
+  }
+  // intersect edges created from vertices
+  Standard_Integer i, aNbF = aMFV.Extent();
+  for (i = 1; i <= aNbF; ++i) {
+    const TopoDS_Face& aF = TopoDS::Face(aMFV(i));
+    aTolF = BRep_Tool::Tolerance(aF);
+    BRepOffset_Inter2d::ConnexIntByIntInVert
+      (aF, theMapSF(aF), theMES, theBuild, theAsDes, theAsDes2d, aTolF, myAnalyse, aDMVV);
+  }
+  //
+  // fuse vertices on edges
+  if (!BRepOffset_Inter2d::FuseVertices(aDMVV, theAsDes2d))
+  {
+    myError = BRepOffset_CannotFuseVertices;
+    return;
+  }
+}
+
+//=======================================================================
+//function : TrimEdges
+//purpose  : 
+//=======================================================================
+Standard_Boolean TrimEdges(const TopoDS_Shape& theShape,
+                 const Standard_Real theOffset,
+                 const BRepOffset_Analyse& Analyse,
+                 BRepOffset_DataMapOfShapeOffset& theMapSF,
+                 TopTools_DataMapOfShapeShape& theMES,
+                 TopTools_DataMapOfShapeShape& theBuild,
+                 Handle(BRepAlgo_AsDes)& theAsDes,
+                 Handle(BRepAlgo_AsDes)& theAsDes2d,
+                 TopTools_IndexedMapOfShape& theNewEdges,
+                 TopTools_DataMapOfShapeShape& theETrimEInf,
+                 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins)
+{
+  TopExp_Explorer Exp,Exp2,ExpC;
+  TopoDS_Shape    NE;
+  TopoDS_Edge     TNE;
+  TopoDS_Face     NF;
+
+  TopTools_ListOfShape aLFaces;
+  for (Exp.Init (theShape, TopAbs_FACE); Exp.More(); Exp.Next())
+    aLFaces.Append (Exp.Current());
+
+  TopTools_MapOfShape aMFGenerated;
+  TopTools_IndexedDataMapOfShapeListOfShape aDMEF;
+  for (TopTools_ListOfShape::Iterator it (Analyse.NewFaces()); it.More(); it.Next())
+  {
+    const TopoDS_Shape& aFG = it.Value();
+    aLFaces.Append (aFG);
+    aMFGenerated.Add (aFG);
+    TopExp::MapShapesAndUniqueAncestors (aFG, TopAbs_EDGE, TopAbs_FACE, aDMEF);
+  }
+
+  for (TopTools_ListOfShape::Iterator it (aLFaces); it.More(); it.Next())
+  {
+    const TopoDS_Face& FI  = TopoDS::Face (it.Value());
+    NF = theMapSF(FI).Face();
+    if (theMES.IsBound(NF)) {
+      NF = TopoDS::Face(theMES(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 (theBuild.IsBound(aS)) {
+        NE = theBuild(aS);
+        // keep connection to original edges
+        ExpC.Init(NE, TopAbs_EDGE);
+        for (; ExpC.More(); ExpC.Next()) {
+          const TopoDS_Edge& NEC = TopoDS::Edge(ExpC.Current());
+          TopTools_ListOfShape* pLEOr = theEdgesOrigins.ChangeSeek(NEC);
+          if (!pLEOr) {
+            pLEOr = theEdgesOrigins.Bound(NEC, TopTools_ListOfShape());
+          }
+          AppendToList(*pLEOr, aS);
+        }
+        // trim edges
+        if (NE.ShapeType() == TopAbs_EDGE) {
+          if (theNewEdges.Add(NE)) {
+            if (!TrimEdge (TopoDS::Edge(NE),theAsDes2d,theAsDes, theETrimEInf))
+              return Standard_False;
+          }
+        }
+        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 (theNewEdges.Add(NEC)) {
+              if (!theAsDes2d->Descendant(NEC).IsEmpty()) {
+                if(!TrimEdge (NEC,theAsDes2d, theAsDes, theETrimEInf))
+                  return Standard_False;
+              }
+              else {
+                if (theAsDes->HasAscendant(NEC)) {
+                  theAsDes->Remove(NEC);
+                }
+              }
+            }
+          }
+        }
+      }
+      else {
+        if (aS.ShapeType() != TopAbs_EDGE) {
+          continue;
+        }
+        if (aMFGenerated.Contains (FI) && aDMEF.FindFromKey (aS).Extent() == 1)
+          continue;
+
+        NE = theMapSF(FI).Generated(aS);
+        //// modified by jgv, 19.12.03 for OCC4455 ////
+        NE.Orientation(aS.Orientation());
+        //
+        TopTools_ListOfShape* pLEOr = theEdgesOrigins.ChangeSeek(NE);
+        if (!pLEOr) {
+          pLEOr = theEdgesOrigins.Bound(NE, TopTools_ListOfShape());
+        }
+        AppendToList(*pLEOr, aS);
+        //
+        if (theMES.IsBound(NE)) {
+          NE = theMES(NE);
+          NE.Orientation(aS.Orientation());
+          if (theNewEdges.Add(NE)) {
+            if (!TrimEdge (TopoDS::Edge(NE), theAsDes2d, theAsDes, theETrimEInf))
+              return Standard_False;
+          } 
+        }
+        else {
+          TopoDS_Edge& anEdge = TopoDS::Edge(NE);
+          BRepAdaptor_Curve aBAC(anEdge);
+          if (aBAC.GetType() == GeomAbs_Line) {
+            TopoDS_Edge aNewEdge;
+            BRepOffset_Inter2d::ExtentEdge(anEdge, aNewEdge, theOffset);
+            theETrimEInf.Bind(anEdge, aNewEdge);
+          }
+        }
+        theAsDes->Add(NF,NE);
+      } 
+    }
+  }
+  return Standard_True;
+}
+
+//=======================================================================
+//function : TrimEdge
+//purpose  : Trim the edge of the largest of descendants in AsDes2d.
+//           Order in AsDes two vertices that have trimmed the edge.
+//=======================================================================
+Standard_Boolean TrimEdge(TopoDS_Edge&                  NE,
+              const Handle(BRepAlgo_AsDes)& AsDes2d,
+              Handle(BRepAlgo_AsDes)& AsDes,
+              TopTools_DataMapOfShapeShape& theETrimEInf)
+{
+  TopoDS_Edge aSourceEdge;
+  TopoDS_Vertex V1,V2;
+  Standard_Real aT1, aT2;
+  //
+  TopExp::Vertices(NE, V1, V2);
+  BRep_Tool::Range(NE, aT1, aT2);
+  //
+  BOPTools_AlgoTools::MakeSplitEdge(NE, V1, aT1, V2, aT2, aSourceEdge);
+  //
+  //
+  Standard_Real aSameParTol = Precision::Confusion();
+  
+  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)
+        {
+          return Standard_False;
+        }
+        U = Projector.LowerDistanceParameter();
+      }
+      if (U < UMin) {
+        UMin = U; V1   = V;
+      }
+      if (U > UMax) {
+        UMax = U; V2   = V;
+      }
+    }
+    //
+    if (V1.IsNull() || V2.IsNull()) {
+      return Standard_False;
+    }
+    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) {
+    BRepAdaptor_Curve aBAC(NE);
+    if (aBAC.GetType() == GeomAbs_Line) {
+      if (AsDes->HasAscendant(NE)) {
+        AsDes->Remove(NE);
+      }
+    }
+  }
+  else
+  {
+    if (!theETrimEInf.IsBound(NE)) {
+      theETrimEInf.Bind(NE, aSourceEdge);
+    }
+  }
+  return Standard_True;
+}
+
+//=======================================================================
+//function : GetEnlargedFaces
+//purpose  : 
+//=======================================================================
+void GetEnlargedFaces(const TopTools_ListOfShape& theFaces,
+                      const BRepOffset_DataMapOfShapeOffset& theMapSF,
+                      const TopTools_DataMapOfShapeShape& theMES,
+                      TopTools_DataMapOfShapeShape& theFacesOrigins,
+                      BRepAlgo_Image& theImage,
+                      TopTools_ListOfShape& theLSF)
+{
+  for (TopTools_ListOfShape::Iterator it (theFaces); it.More(); it.Next())
+  {
+    const TopoDS_Shape& FI  = it.Value();
+    const TopoDS_Shape& OFI = theMapSF(FI).Face();
+    if (theMES.IsBound(OFI)) {
+      const TopoDS_Face& aLocalFace = TopoDS::Face(theMES(OFI));
+      theLSF.Append(aLocalFace);
+      theImage.SetRoot(aLocalFace);
+      theFacesOrigins.Bind(aLocalFace, FI);
+    }
+  }
+}
+
+//=======================================================================
+//function : BuildShellsCompleteInter
+//purpose  : Make the shells from list of faces using MakerVolume algorithm.
+//           In case there will be more than just one solid, it will be
+//           rebuilt using only outer faces.
+//=======================================================================
+Standard_Boolean BuildShellsCompleteInter(const TopTools_ListOfShape& theLF,
+                                          BRepAlgo_Image& theImage,
+                                          TopoDS_Shape& theShells)
+{
+  // make solids
+  BOPAlgo_MakerVolume aMV1;
+  aMV1.SetArguments(theLF);
+  // we need to intersect the faces to process the tangential faces
+  aMV1.SetIntersect(Standard_True);
+  aMV1.SetAvoidInternalShapes(Standard_True);
+  aMV1.Perform();
+  //
+  Standard_Boolean bDone = ! aMV1.HasErrors();
+  if (!bDone) {
+    return bDone;
+  }
+  //
+  UpdateHistory(theLF, aMV1, theImage);
+  //
+  const TopoDS_Shape& aResult1 = aMV1.Shape();
+  if (aResult1.ShapeType() == TopAbs_SOLID) {
+    // result is the alone solid, nothing to do
+    return GetSubShapes(aResult1, TopAbs_SHELL, theShells);
+  }
+
+  // Allocators for effective memory allocations
+  // Global allocator for the long-living containers
+  Handle(NCollection_IncAllocator) anAllocGlob = new NCollection_IncAllocator;
+  // Local allocator for the local containers
+  Handle(NCollection_IncAllocator) anAllocLoc = new NCollection_IncAllocator;
+
+  // Since the <theImage> object does not support multiple ancestors,
+  // prepare local copy of the origins, which will be used to resolve
+  // non-manifold solids produced by Maker Volume algorithm by comparison
+  // of the normal directions of the split faces with their origins.
+  TopTools_DataMapOfShapeListOfShape anOrigins(1, anAllocGlob);
+  TopTools_ListIteratorOfListOfShape aItLR(theImage.Roots());
+  for (; aItLR.More(); aItLR.Next())
+  {
+    const TopoDS_Shape& aFR = aItLR.Value();
+
+    // Reset the local allocator
+    anAllocLoc->Reset();
+    // Find the last splits of the root face, including the ones
+    // created during MakeVolume operation
+    TopTools_ListOfShape aLFIm(anAllocLoc);
+    theImage.LastImage(aFR, aLFIm);
+
+    TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
+    for (; aItLFIm.More(); aItLFIm.Next())
+    {
+      const TopoDS_Shape& aFIm = aItLFIm.Value();
+      TopTools_ListOfShape *pLFOr = anOrigins.ChangeSeek(aFIm);
+      if (!pLFOr) {
+        pLFOr = anOrigins.Bound(aFIm, TopTools_ListOfShape(anAllocGlob));
+      }
+      pLFOr->Append(aFR);
+    }
+  }
+
+  // Reset the local allocator
+  anAllocLoc->Reset();
+  // It is necessary to rebuild the solids, avoiding internal faces
+  // Map faces to solids
+  TopTools_IndexedDataMapOfShapeListOfShape aDMFS(1, anAllocLoc);
+  TopExp::MapShapesAndAncestors(aResult1, TopAbs_FACE, TopAbs_SOLID, aDMFS);
+  //
+  Standard_Integer i, aNb = aDMFS.Extent();
+  bDone = (aNb > 0);
+  if (!bDone) {
+    // unable to build any solid
+    return bDone;
+  }
+  //
+  // get faces attached to only one solid
+  TopTools_ListOfShape aLF(anAllocLoc);
+  for (i = 1; i <= aNb; ++i) {
+    const TopTools_ListOfShape& aLS = aDMFS(i);
+    if (aLS.Extent() == 1) {
+      const TopoDS_Shape& aF = aDMFS.FindKey(i);
+      aLF.Append(aF);
+    }
+  }
+  //
+  // make solids from the new list
+  BOPAlgo_MakerVolume aMV2;
+  aMV2.SetArguments(aLF);
+  // no need to intersect this time
+  aMV2.SetIntersect(Standard_False);
+  aMV2.SetAvoidInternalShapes(Standard_True);
+  aMV2.Perform();
+  bDone = ! aMV2.HasErrors();
+  if (!bDone) {
+    return bDone;
+  }
+  //
+  const TopoDS_Shape& aResult2 = aMV2.Shape();
+  if (aResult2.ShapeType() == TopAbs_SOLID) {
+    return GetSubShapes(aResult2, TopAbs_SHELL, theShells);
+  }
+  //
+  TopExp_Explorer aExp(aResult2, TopAbs_FACE);
+  bDone = aExp.More();
+  if (!bDone) {
+    return bDone;
+  }
+  //
+  aLF.Clear();
+  aDMFS.Clear();
+  anAllocLoc->Reset();
+
+  // the result is non-manifold - resolve it comparing normal
+  // directions of the offset faces and original faces
+  for (; aExp.More(); aExp.Next())
+  {
+    const TopoDS_Face& aF = TopoDS::Face(aExp.Current());
+    const TopTools_ListOfShape* pLFOr = anOrigins.Seek(aF);
+    if (!pLFOr)
+    {
+      Standard_ASSERT_INVOKE("BRepOffset_MakeOffset::BuildShellsCompleteInterSplit(): "
+                             "Origins map does not contain the split face");
+      continue;
+    }
+    // Check orientation
+    TopTools_ListIteratorOfListOfShape aItLOr(*pLFOr);
+    for (; aItLOr.More(); aItLOr.Next())
+    {
+      const TopoDS_Face& aFOr = TopoDS::Face(aItLOr.Value());
+      if (BRepOffset_Tool::CheckPlanesNormals(aF, aFOr))
+      {
+        aLF.Append(aF);
+        break;
+      }
+    }
+  }
+  //
+  // make solid from most outer faces with correct normal direction
+  BOPAlgo_MakerVolume aMV3;
+  aMV3.SetArguments(aLF);
+  aMV3.SetIntersect(Standard_False);
+  aMV3.SetAvoidInternalShapes(Standard_True);
+  aMV3.Perform();
+  bDone = ! aMV3.HasErrors();
+  if (!bDone) {
+    return bDone;
+  }
+  //
+  const TopoDS_Shape& aResult3 = aMV3.Shape();
+  return GetSubShapes(aResult3, TopAbs_SHELL, theShells);
+}
+
+//=======================================================================
+//function : Generated
+//purpose  : 
+//=======================================================================
+const TopTools_ListOfShape& BRepOffset_MakeOffset::Generated (const TopoDS_Shape& theS)
+{
+  myGenerated.Clear();
+  const TopAbs_ShapeEnum aType = theS.ShapeType();
+  switch (aType)
+  {
+    case TopAbs_VERTEX:
+    {
+      if (myAnalyse.HasAncestor (theS))
+      {
+        TopTools_MapOfShape aMFence;
+        const TopTools_ListOfShape& aLA = myAnalyse.Ancestors (theS);
+        TopTools_ListOfShape::Iterator itLA (aLA);
+        for (; myGenerated.IsEmpty() && itLA.More(); itLA.Next())
+        {
+          const TopoDS_Shape& aE = itLA.Value();
+          if (!myInitOffsetEdge.HasImage (aE))
+            continue;
+          TopTools_ListOfShape aLEIm;
+          myInitOffsetEdge.LastImage (aE, aLEIm);
+          TopTools_ListOfShape::Iterator itLEIm (aLEIm);
+          for (; myGenerated.IsEmpty() && itLEIm.More(); itLEIm.Next())
+          {
+            TopoDS_Iterator itV (itLEIm.Value());
+            for (; itV.More(); itV.Next())
+            {
+              if (!aMFence.Add (itV.Value()))
+              {
+                myGenerated.Append (itV.Value());
+                break;
+              }
+            }
+          }
+        }
+      }
+    }
+    Standard_FALLTHROUGH
+    case TopAbs_EDGE:
+    {
+      if (myInitOffsetEdge.HasImage (theS))
+      {
+        myInitOffsetEdge.LastImage (theS, myGenerated);
+      }
+    }
+    Standard_FALLTHROUGH
+    case TopAbs_FACE:
+    {
+      if (myInitOffsetFace.HasImage (theS))
+      {
+        myInitOffsetFace.LastImage (theS, myGenerated);
+      }
+      break;
+    }
+    case TopAbs_SOLID:
+    {
+      if (theS.IsSame (myShape))
+        myGenerated.Append (myOffsetShape);
+      break;
+    }
+    default:
+      break;
+  }
+
+  if (myResMap.IsEmpty())
+    TopExp::MapShapes (myOffsetShape, myResMap);
+
+  for (TopTools_ListOfShape::Iterator it (myGenerated); it.More();)
+  {
+    if (myResMap.Contains (it.Value()))
+      it.Next();
+    else
+      myGenerated.Remove (it);
+  }
+
+  return myGenerated;
+}
+
+//=======================================================================
+//function : Modified
+//purpose  : 
+//=======================================================================
+const TopTools_ListOfShape& BRepOffset_MakeOffset::Modified (const TopoDS_Shape&)
+{
+  myGenerated.Clear();
+  return myGenerated;
+}
+
+//=======================================================================
+//function : IsDeleted
+//purpose  : 
+//=======================================================================
+Standard_Boolean BRepOffset_MakeOffset::IsDeleted (const TopoDS_Shape& theS)
+{
+  if (myResMap.IsEmpty())
+    TopExp::MapShapes (myOffsetShape, myResMap);
+
+  if (myResMap.Contains (theS))
+    return Standard_False;
+
+  return Generated (theS).IsEmpty()
+      && Modified  (theS).IsEmpty();
+}
+
+//=======================================================================
+//function : GetSubShapes
+//purpose  : 
+//=======================================================================
+Standard_Boolean GetSubShapes(const TopoDS_Shape& theShape,
+                              const TopAbs_ShapeEnum theSSType,
+                              TopoDS_Shape& theResult)
+{
+  TopExp_Explorer aExp(theShape, theSSType);
+  if (!aExp.More()) {
+    return Standard_False;
+  }
+  //
+  TopoDS_Compound aResult;
+  BRep_Builder().MakeCompound(aResult);
+  //
+  for (; aExp.More(); aExp.Next()) {
+    const TopoDS_Shape& aSS = aExp.Current();
+    BRep_Builder().Add(aResult, aSS);
+  }
+  theResult = aResult;
+  return Standard_True;
+}
+
+//=======================================================================
+//function : IsPlanar
+//purpose  : Checks if all the faces of the shape are planes
+//=======================================================================
+Standard_Boolean IsPlanar(const TopoDS_Shape& theS)
+{
+  TopExp_Explorer aExp(theS, TopAbs_FACE);
+  for (; aExp.More(); aExp.Next()) {
+    const TopoDS_Face& aF = *(TopoDS_Face*)&aExp.Current();
+    BRepAdaptor_Surface aBAS(aF, Standard_False);
+    if (aBAS.GetType() != GeomAbs_Plane) {
+      break;
+    }
+  }
+  return !aExp.More();
+}
+
+//=======================================================================
+//function : IsSolid
+//purpose  : Checks if the shape is solid
+//=======================================================================
+Standard_Boolean IsSolid(const TopoDS_Shape& theS)
+{
+  TopExp_Explorer aExp(theS, TopAbs_SOLID);
+  return aExp.More();
+}
+
+//=======================================================================
+//function : AppendToList
+//purpose  : Add to a list only unique elements
+//=======================================================================
+void AppendToList(TopTools_ListOfShape& theList,
+                  const TopoDS_Shape& theShape)
+{
+  TopTools_ListIteratorOfListOfShape aIt(theList);
+  for (; aIt.More(); aIt.Next()) {
+    const TopoDS_Shape& aS = aIt.Value();
+    if (aS.IsSame(theShape)) {
+      return;
+    }
+  }
+  theList.Append(theShape);
+}