]> SALOME platform Git repositories - modules/geom.git/blobdiff - src/GEOMImpl/GEOMImpl_PipeDriver.cxx
Salome HOME
Typo-fix by Kunda
[modules/geom.git] / src / GEOMImpl / GEOMImpl_PipeDriver.cxx
index 31f53f8733646d575ccde04cd27e3d70967bc88f..d84397a4c72512f8fdd7c2b85dbf4b3c4b29d629 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
 #include <BRep_Builder.hxx>
 #include <BRepBuilderAPI_Copy.hxx>
 #include <BRepBuilderAPI_MakeFace.hxx>
+#include <BRepBuilderAPI_MakeSolid.hxx>
 #include <BRepBuilderAPI_MakeWire.hxx>
 #include <BRepBuilderAPI_Sewing.hxx>
+#include <BRepClass3d_SolidClassifier.hxx>
 #include <BRepGProp.hxx>
 #include <GeomFill_Trihedron.hxx>
 #include <GeomFill_CorrectedFrenet.hxx>
 #define GROUP_SIDE2 3
 #define GROUP_OTHER 4
 
+static const Standard_Real TolPipeSurf = 5.e-4;
+
 static bool FillGroups(const TopTools_SequenceOfShape         *theGroups,
                        const TopTools_IndexedMapOfShape       &theIndices,
                              Handle(TColStd_HArray1OfInteger) *theGroupIds);
@@ -113,11 +117,14 @@ static bool FillGroups(const TopTools_SequenceOfShape         *theGroups,
 static void StoreGroups(GEOMImpl_IPipe                   *theCI,
                         Handle(TColStd_HArray1OfInteger) *theGroups);
 
-static bool DoGroups(BRepOffsetAPI_MakePipeShell &theSweep,
-                     TopTools_SequenceOfShape    *theGroups);
+// after OCCT improvement
+static bool DoGroups1(const TopoDS_Shape          &theProfile,
+                      BRepOffsetAPI_MakePipeShell &theSweep,
+                      TopTools_SequenceOfShape    *theGroups);
 
-static bool CreateGroups(BRepOffsetAPI_MakePipeShell &theSweep,
-                         GEOMImpl_IPipe              *theCI);
+static bool CreateGroups1(const TopoDS_Shape          &theProfile,
+                          BRepOffsetAPI_MakePipeShell &theSweep,
+                          GEOMImpl_IPipe              *theCI);
 
 //=======================================================================
 //function : GetID
@@ -139,7 +146,7 @@ GEOMImpl_PipeDriver::GEOMImpl_PipeDriver()
 
 //=======================================================================
 //function : EvaluateBestSweepMode
-//purpose  : auxilary for right call of MakePipe and MakePipeShell
+//purpose  : auxiliary for right call of MakePipe and MakePipeShell
 //=======================================================================
 static GeomFill_Trihedron EvaluateBestSweepMode(const TopoDS_Shape& Spine)
 {
@@ -176,11 +183,14 @@ static GeomFill_Trihedron EvaluateBestSweepMode(const TopoDS_Shape& Spine)
 //=======================================================================
 static Standard_Boolean BuildPipeShell(BRepOffsetAPI_MakePipeShell &theBuilder)
 {
+  theBuilder.SetForceApproxC1(Standard_True);
+
   theBuilder.Build();
 
   Standard_Boolean isDone = theBuilder.IsDone();
 
-  if (!isDone) {
+  if (!isDone ||
+      theBuilder.ErrorOnSurface() > TolPipeSurf) {
     // Try to use Descrete Trihedron mode.
     theBuilder.SetDiscreteMode();
     theBuilder.Build();
@@ -192,7 +202,7 @@ static Standard_Boolean BuildPipeShell(BRepOffsetAPI_MakePipeShell &theBuilder)
 
 //=======================================================================
 //function : FillForOtherEdges
-//purpose  : auxilary for CreatePipeForShellSections()
+//purpose  : auxiliary for CreatePipeForShellSections()
 //=======================================================================
 static bool FillForOtherEdges(const TopoDS_Shape& F1,
                               const TopoDS_Shape& E1,
@@ -268,7 +278,7 @@ static bool FillForOtherEdges(const TopoDS_Shape& F1,
 
 //=======================================================================
 //function : FillCorrespondingEdges
-//purpose  : auxilary for CreatePipeForShellSections()
+//purpose  : auxiliary for CreatePipeForShellSections()
 //=======================================================================
 static bool FillCorrespondingEdges(const TopoDS_Shape& FS1,
                                    const TopoDS_Shape& FS2,
@@ -396,7 +406,7 @@ static bool FillCorrespondingEdges(const TopoDS_Shape& FS1,
 
 //=======================================================================
 //function : FillCorrespondingEdges
-//purpose  : auxilary for CreatePipeShellsWithoutPath()
+//purpose  : auxiliary for CreatePipeShellsWithoutPath()
 //=======================================================================
 static bool FillCorrespondingEdges(const TopoDS_Shape& FS1,
                                    const TopoDS_Shape& FS2,
@@ -498,7 +508,7 @@ static bool FillCorrespondingEdges(const TopoDS_Shape& FS1,
 
 //=======================================================================
 //function : FindNextPairOfFaces
-//purpose  : auxilary for CreatePipeForShellSections()
+//purpose  : auxiliary for CreatePipeForShellSections()
 //=======================================================================
 static void FindNextPairOfFaces(const TopoDS_Shape& aCurFace,
                                 TopTools_IndexedDataMapOfShapeListOfShape& aMapEdgeFaces1,
@@ -559,7 +569,7 @@ static void FindNextPairOfFaces(const TopoDS_Shape& aCurFace,
     bool stat =  FillForOtherEdges(F1other,E1,V1,FF);
     if (!stat) {
       if (aCI) delete aCI;
-      Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not mapping other egdes");
+      Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not map other edges");
     }
 
     FindNextPairOfFaces(F1other, aMapEdgeFaces1, aMapEdgeFaces2, FF, aCI);
@@ -568,7 +578,7 @@ static void FindNextPairOfFaces(const TopoDS_Shape& aCurFace,
 
 //=======================================================================
 //function : FindFirstPairFaces
-//purpose  : auxilary for Execute()
+//purpose  : auxiliary for Execute()
 //=======================================================================
 static void FindFirstPairFaces(const TopoDS_Shape& S1, const TopoDS_Shape& S2,
                                TopoDS_Vertex& V1, TopoDS_Vertex& V2,
@@ -686,6 +696,42 @@ static void FindFirstPairFaces(const TopoDS_Shape& S1, const TopoDS_Shape& S2,
   FS2 = Fs(numface);
 }
 
+//=======================================================================
+//function : RemoveFaces
+//purpose  : This function returns theShapeFrom without faces of the shape
+//           theFacesToRm. It returns a shell if theShapeFrom is a solid or
+//           a compound otherwise. Auxiliary for CreatePipeWithDifferentSections
+//           method.
+//=======================================================================
+static TopoDS_Shape RemoveFaces(const TopoDS_Shape &theShapeFrom,
+                                const TopoDS_Shape &theFacesToRm)
+{
+  TopTools_IndexedMapOfShape aMapFaces;
+  TopExp_Explorer            anExp(theShapeFrom, TopAbs_FACE);
+  BRep_Builder               aBuilder;
+  TopoDS_Shape               aResult;
+
+  if (theShapeFrom.ShapeType() == TopAbs_SOLID) {
+    // Create shell
+    aBuilder.MakeShell(TopoDS::Shell(aResult));
+  } else {
+    // Create compound
+    aBuilder.MakeCompound(TopoDS::Compound(aResult));
+  }
+
+  TopExp::MapShapes(theFacesToRm, TopAbs_FACE, aMapFaces);
+
+  for (; anExp.More(); anExp.Next()) {
+    const TopoDS_Shape &aFace = anExp.Current();
+
+    if (!aMapFaces.Contains(aFace)) {
+      aBuilder.Add(aResult, aFace);
+    }
+  }
+
+  return aResult;
+}
+
 //=======================================================================
 //function : CreatePipeWithDifferentSections
 //purpose  :
@@ -696,6 +742,7 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections
                    const Handle(TopTools_HSequenceOfShape)  theHSeqLocs,
                    const Standard_Boolean                   theWithContact,
                    const Standard_Boolean                   theWithCorrect,
+                   const Standard_Boolean                   IsBySteps,
                          Handle(TColStd_HArray1OfInteger)  *theGroups)
 {
   TopoDS_Shape aShape;
@@ -872,7 +919,7 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections
       }
     }
     if (nbEdges<Edges.Length()) {
-        // one of edges was splitted => we have to update WirePath
+        // one of edges was split => we have to update WirePath
         BRep_Builder B;
         TopoDS_Wire W;
         B.MakeWire(W);
@@ -883,49 +930,82 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections
     }
   }
 
-  // check curvature of wire for condition that
-  // max summary angle between directions along
-  // wire path must be < 4*PI. If not - split wire
-  // and seguences of shapes, perform pipe for each
-  // and make sewing after that
-  double fp,lp;
-  gp_Pnt P1,P2;
-  gp_Vec Vec1,Vec2;
-  double SumAng = 0;
-  if ( Edges.Length() > 0 ) {
-    Handle(Geom_Curve) C = BRep_Tool::Curve(TopoDS::Edge(Edges.Value(1)),fp,lp);
-    C->D1(fp,P1,Vec1);
-    C->D1(lp,P2,Vec2);
-    SumAng = fabs(Vec1.Angle(Vec2));
-    Vec1 = Vec2;
-    P1 = P2;
-  }
   TColStd_SequenceOfInteger SplitEdgeNums,SplitLocNums;
-  int LastLoc = 1;
-  //cout<<"Edges.Length()="<<Edges.Length()<<endl;
-  for (i=2; i<=Edges.Length(); i++) {
-      TopoDS_Edge edge = TopoDS::Edge(Edges.Value(i));
-      double tol = BRep_Tool::Tolerance(edge);
-      Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp);
-      C->D1(lp,P2,Vec2);
-      double ang = fabs(Vec1.Angle(Vec2));
-      SumAng += ang;
-      if (SumAng>4*M_PI) {
-        SumAng = ang;
-        SplitEdgeNums.Append(i-1);
-        int j;
-        for (j=LastLoc+1; j<=aSeqLocs.Length(); j++) {
-          TopoDS_Vertex aVert = TopoDS::Vertex(aSeqLocs.Value(j));
-          gp_Pnt P = BRep_Tool::Pnt(aVert);
-          if (P1.Distance(P) < tol) {
-            SplitLocNums.Append(j);
-            LastLoc = j;
-            break;
-          }
+
+  if (IsBySteps) {
+    // Fill SplitEdgeNums and SplitLocNums with intermediate location indices
+    // and corresponding edge indices.
+    Standard_Integer i = 1;
+    Standard_Integer j;
+    TopoDS_Vertex    aVert;
+    gp_Pnt           aP;
+
+    for (j = 2; j < aSeqLocs.Length(); j++) {
+      SplitLocNums.Append(j);
+      aVert = TopoDS::Vertex(aSeqLocs.Value(j));
+      aP    = BRep_Tool::Pnt(aVert);
+
+      while (i < Edges.Length()) {
+        Standard_Real      aFp;
+        Standard_Real      aLp;
+        TopoDS_Edge        anEdge = TopoDS::Edge(Edges.Value(i));
+        Standard_Real      aTol   = BRep_Tool::Tolerance(anEdge);
+        Handle(Geom_Curve) aC     = BRep_Tool::Curve(anEdge, aFp, aLp);
+        gp_Pnt             aPLast;
+
+        aC->D0(aLp, aPLast);
+        i++;
+
+        if (aP.Distance(aPLast) < aTol) {
+          SplitEdgeNums.Append(i - 1);
+          break;
         }
       }
+    }
+  } else {
+    // check curvature of wire for condition that
+    // max summary angle between directions along
+    // wire path must be < 4*PI. If not - split wire
+    // and seguences of shapes, perform pipe for each
+    // and make sewing after that
+    double fp,lp;
+    gp_Pnt P1,P2;
+    gp_Vec Vec1,Vec2;
+    double SumAng = 0;
+    if ( Edges.Length() > 0 ) {
+      Handle(Geom_Curve) C = BRep_Tool::Curve(TopoDS::Edge(Edges.Value(1)),fp,lp);
+      C->D1(fp,P1,Vec1);
+      C->D1(lp,P2,Vec2);
+      SumAng = fabs(Vec1.Angle(Vec2));
       Vec1 = Vec2;
       P1 = P2;
+    }
+    int LastLoc = 1;
+    //cout<<"Edges.Length()="<<Edges.Length()<<endl;
+    for (i=2; i<=Edges.Length(); i++) {
+        TopoDS_Edge edge = TopoDS::Edge(Edges.Value(i));
+        double tol = BRep_Tool::Tolerance(edge);
+        Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp);
+        C->D1(lp,P2,Vec2);
+        double ang = fabs(Vec1.Angle(Vec2));
+        SumAng += ang;
+        if (SumAng>4*M_PI) {
+          SumAng = ang;
+          SplitEdgeNums.Append(i-1);
+          int j;
+          for (j=LastLoc+1; j<=aSeqLocs.Length(); j++) {
+            TopoDS_Vertex aVert = TopoDS::Vertex(aSeqLocs.Value(j));
+            gp_Pnt P = BRep_Tool::Pnt(aVert);
+            if (P1.Distance(P) < tol) {
+              SplitLocNums.Append(j);
+              LastLoc = j;
+              break;
+            }
+          }
+        }
+        Vec1 = Vec2;
+        P1 = P2;
+    }
   }
 
   bool isCreateGroups = (theGroups != NULL);
@@ -966,9 +1046,24 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections
           Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
         }
 
-        BuildPipeShell(aBuilder);
+        Standard_Boolean isDone = BuildPipeShell(aBuilder);
+
+        if (isDone && NeedCreateSolid && nn == 1) {
+          // Make solid for the first step.
+          isDone = aBuilder.MakeSolid();
+        }
+
+        if (!isDone) {
+          Standard_ConstructionError::Raise("Pipe construction failure");
+        }
 
         TopoDS_Shape resShape = aBuilder.Shape();
+
+        if (NeedCreateSolid && nn == 1) {
+          // Remove top lid from the result.
+          resShape = RemoveFaces(resShape, aBuilder.LastShape());
+        }
+
         aSeqRes.Append(resShape);
 
         // Create groups.
@@ -976,7 +1071,8 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections
           // Make groups.
           TopTools_SequenceOfShape aGroups[5];
 
-          if (!DoGroups(aBuilder, aGroups)) {
+          TopoDS_Shape aProfile = aTmpSeqBases.Value(1);
+          if (!DoGroups1(aProfile, aBuilder, aGroups)) {
             Standard_ConstructionError::Raise("Generate groups failure");
           }
 
@@ -1014,9 +1110,23 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections
         Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
       }
 
-      BuildPipeShell(aBuilder);
+      Standard_Boolean isDone = BuildPipeShell(aBuilder);
+
+      if (isDone && NeedCreateSolid) {
+        isDone = aBuilder.MakeSolid();
+      }
+
+      if (!isDone) {
+        Standard_ConstructionError::Raise("Pipe construction failure");
+      }
 
       TopoDS_Shape resShape = aBuilder.Shape();
+
+      if (NeedCreateSolid) {
+        // Remove bottom lid from the result.
+        resShape = RemoveFaces(resShape, aBuilder.FirstShape());
+      }
+
       aSeqRes.Append(resShape);
 
       // Create groups.
@@ -1024,7 +1134,8 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections
         // Make groups.
         TopTools_SequenceOfShape aGroups[5];
 
-        if (!DoGroups(aBuilder, aGroups)) {
+        TopoDS_Shape aProfile = aTmpSeqBases.Value(1);
+        if (!DoGroups1(aProfile, aBuilder, aGroups)) {
           Standard_ConstructionError::Raise("Generate groups failure");
         }
 
@@ -1046,6 +1157,28 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections
       aSewing->Perform();
       aShape = aSewing->SewedShape();
 
+      if (NeedCreateSolid && aShape.ShapeType() == TopAbs_SHELL) {
+        // Build a solid.
+        BRepBuilderAPI_MakeSolid aMkSolid;
+
+        aMkSolid.Add(TopoDS::Shell(aShape));
+
+        if (!aMkSolid.IsDone()) {
+          Standard_ConstructionError::Raise("Can't create solid pipe");
+        }
+
+        TopoDS_Solid                aSolid = aMkSolid.Solid();
+        BRepClass3d_SolidClassifier aSC(aSolid);
+
+        aSC.PerformInfinitePoint(Precision::Confusion());
+
+        if (aSC.State() == TopAbs_IN) {
+          aShape = aSolid.Reversed();
+        } else {
+          aShape = aSolid;
+        }
+      }
+
       if (isCreateGroups) {
         // Replase Group shapes by modified ones.
         TopTools_SequenceOfShape aSeqGroups[5];
@@ -1149,12 +1282,13 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections
           // Make groups.
           TopTools_SequenceOfShape aSeqGroups[5];
 
-          if (!DoGroups(aBuilder, aSeqGroups)) {
+          TopoDS_Shape aProfile = usedBases.Value(1);
+          if (!DoGroups1(aProfile, aBuilder, aSeqGroups)) {
             Standard_ConstructionError::Raise("Generate groups failure");
           }
 
           // Fill the groups.
-          Handle(TColStd_HArray1OfInteger) aGroupIds[5];
+          //Handle(TColStd_HArray1OfInteger) aGroupIds[5];
           TopTools_IndexedMapOfShape       anIndices;
           const TopoDS_Shape               aResult = aBuilder.Shape();
 
@@ -1175,7 +1309,7 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections
 
 //=======================================================================
 //function : CreatePipeForShellSections
-//purpose  : auxilary for Execute()
+//purpose  : auxiliary for Execute()
 //=======================================================================
 static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath,
                                                GEOMImpl_IPipe* aCI)
@@ -1504,7 +1638,7 @@ static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath,
         // Create groups.
         if (isGenerateGroups) {
           // Make groups.
-          if (!DoGroups(aBuilder, aLocalGroups)) {
+          if (!DoGroups1(aWire1, aBuilder, aLocalGroups)) {
             if (aCI) delete aCI;
             Standard_ConstructionError::Raise("Generate groups failure");
           }
@@ -1690,7 +1824,7 @@ static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath,
         bool stat =  FillForOtherEdges(FS1,E1,V11,FF);
         if (!stat) {
           if (aCI) delete aCI;
-          Standard_ConstructionError::Raise("FindForOtherEdges: Can not mapping other egdes");
+          Standard_ConstructionError::Raise("FindForOtherEdges: Can not map other edges");
         }
 
       }
@@ -1791,7 +1925,7 @@ static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath,
           // Create groups.
           if (isGenerateGroups) {
             // Make groups.
-            if (!DoGroups(aBuilder, aLocalGroups)) {
+            if (!DoGroups1(aWire1, aBuilder, aLocalGroups)) {
               if (aCI) delete aCI;
               Standard_ConstructionError::Raise("Generate groups failure");
             }
@@ -1900,7 +2034,7 @@ static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath,
 
 //=======================================================================
 //function : CreatePipeShellsWithoutPath
-//purpose  : auxilary for Execute()
+//purpose  : auxiliary for Execute()
 //=======================================================================
 static TopoDS_Shape CreatePipeShellsWithoutPath(GEOMImpl_IPipe* aCI)
 {
@@ -2020,13 +2154,13 @@ static TopoDS_Shape CreatePipeShellsWithoutPath(GEOMImpl_IPipe* aCI)
       if (aCI) delete aCI;
       Standard_ConstructionError::Raise("Can not create correct pipe");
     }
-    MESSAGE ("  correspondences for sub-shapes of first pair of faces is found");
+    MESSAGE ("  correspondences for sub-shapes of first pair of faces found");
 
     FindNextPairOfFaces(FS1, aMapEdgeFaces1, aMapEdgeFaces2, FF, aCI);
-    MESSAGE ("  other correspondences is found, make pipe for all pairs of faces");
+    MESSAGE ("  other correspondences found, make pipe for all pairs of faces");
 
     // make pipe for each pair of faces
-    // auxilary map vertex->edge for created pipe edges
+    // auxiliary map vertex->edge for created pipe edges
     TopTools_IndexedDataMapOfShapeShape VPE;
     ShapeAnalysis_Edge sae;
     //cout<<"FF.Extent()="<<FF.Extent()<<endl;
@@ -2091,7 +2225,7 @@ static TopoDS_Shape CreatePipeShellsWithoutPath(GEOMImpl_IPipe* aCI)
         if (VPE.Contains(E1)) {
           aNewFs.Append(VPE.FindFromKey(E1));
 #ifdef _DEBUG_
-          MESSAGE ("    using existed face");
+          MESSAGE ("    using existing face");
 #endif
           continue;
         }
@@ -2272,7 +2406,7 @@ static TopoDS_Shape CreatePipeShellsWithoutPath(GEOMImpl_IPipe* aCI)
             GeomAPI_Interpolate anInt(HAP,Standard_False,1.e-7);
             anInt.Load(aDir1,aDir2);
             anInt.Perform();
-            Handle(Geom_Curve) iso = anInt.Curve();
+            const Handle(Geom_BSplineCurve) iso = anInt.Curve();
             fp = iso->FirstParameter();
             lp = iso->LastParameter();
             step = (lp-fp)/(NbP-1);
@@ -2408,7 +2542,7 @@ static TopoDS_Shape CreatePipeShellsWithoutPath(GEOMImpl_IPipe* aCI)
 
 //=======================================================================
 //function : CreatePipeBiNormalAlongVector
-//purpose  : auxilary for Execute()
+//purpose  : auxiliary for Execute()
 //=======================================================================
 static TopoDS_Shape CreatePipeBiNormalAlongVector(const TopoDS_Wire& aWirePath,
                                                   GEOMImpl_IPipe* aCI)
@@ -2475,7 +2609,7 @@ static TopoDS_Shape CreatePipeBiNormalAlongVector(const TopoDS_Wire& aWirePath,
       PipeBuilder.MakeSolid();
   }
 
-  if (!CreateGroups(PipeBuilder, aCIBN)) {
+  if (!CreateGroups1(aProf, PipeBuilder, aCIBN)) {
     if (aCIBN) delete aCIBN;
     Standard_ConstructionError::Raise("Generate groups failure");
   }
@@ -2485,7 +2619,7 @@ static TopoDS_Shape CreatePipeBiNormalAlongVector(const TopoDS_Wire& aWirePath,
 
 //=======================================================================
 //function : FillGroups
-//purpose  : auxilary for DoGroups()
+//purpose  : auxiliary for DoGroups()
 //=======================================================================
 bool FillGroups(const TopTools_SequenceOfShape         *theGroups,
                 const TopTools_IndexedMapOfShape       &theIndices,
@@ -2518,7 +2652,7 @@ bool FillGroups(const TopTools_SequenceOfShape         *theGroups,
 
 //=======================================================================
 //function : StoreGroups
-//purpose  : auxilary for CreateGroups()
+//purpose  : auxiliary for CreateGroups()
 //=======================================================================
 void StoreGroups(GEOMImpl_IPipe                   *theCI,
                  Handle(TColStd_HArray1OfInteger) *theGroups)
@@ -2546,7 +2680,7 @@ void StoreGroups(GEOMImpl_IPipe                   *theCI,
 
 //=======================================================================
 //function : CreateDownUpGroups
-//purpose  : auxilary for DoGroups()
+//purpose  : auxiliary for DoGroups()
 //=======================================================================
 static bool CreateDownUpGroups(BRepPrimAPI_MakeSweep    *theSweep,
                                TopTools_SequenceOfShape *theGroups,
@@ -2610,11 +2744,12 @@ static bool CreateDownUpGroups(BRepPrimAPI_MakeSweep    *theSweep,
 }
 
 //=======================================================================
-//function : DoGroups
-//purpose  : auxilary for CreateGroups()
+//function : DoGroups1
+//purpose  : auxiliary for CreateGroups1()
 //=======================================================================
-bool DoGroups(BRepOffsetAPI_MakePipeShell &theSweep,
-              TopTools_SequenceOfShape    *theGroups)
+bool DoGroups1 (const TopoDS_Shape          &theProfile,
+                BRepOffsetAPI_MakePipeShell &theSweep,
+                TopTools_SequenceOfShape    *theGroups)
 {
   Standard_Boolean isDoSides = Standard_False;
 
@@ -2623,7 +2758,8 @@ bool DoGroups(BRepOffsetAPI_MakePipeShell &theSweep,
     return false;
   }
 
-  const TopoDS_Shape aDownShape = theSweep.FirstShape();
+  TopoDS_Shape aDownShape = theProfile;
+  if (aDownShape.IsNull()) aDownShape = theSweep.FirstShape();
 
   if (isDoSides) {
     // Create Side1 and Side2 groups.
@@ -2654,8 +2790,15 @@ bool DoGroups(BRepOffsetAPI_MakePipeShell &theSweep,
               if (aMapFence.Add(aSideShape)) {
                 theGroups[anIdSide].Append(aSideShape);
               }
+            } else if (aSideShape.ShapeType() == TopAbs_WIRE) {
+              if (aMapFence.Add(aSideShape)) {
+                TopExp_Explorer anExpWE (aSideShape, TopAbs_EDGE);
+                for (; anExpWE.More(); anExpWE.Next()) {
+                  theGroups[anIdSide].Append(anExpWE.Current());
+                }
+              }
             } else {
-              // Only edges can be is Side1 and Side2 groups.
+              // Only edges can be in Side1 and Side2 groups.
               return false;
             }
           }
@@ -2663,7 +2806,7 @@ bool DoGroups(BRepOffsetAPI_MakePipeShell &theSweep,
       }
     }
   } else {
-    // Create Other group. Get boudnary edges of the profile.
+    // Create Other group. Get boundary edges of the profile.
     TopTools_MapOfShape aMapBndEdges;
     TopExp_Explorer     anExp(aDownShape, TopAbs_EDGE);
 
@@ -2692,6 +2835,13 @@ bool DoGroups(BRepOffsetAPI_MakePipeShell &theSweep,
             if (aMapFence.Add(anOtherShape)) {
               theGroups[GROUP_OTHER].Append(anOtherShape);
             }
+          } else if (anOtherShape.ShapeType() == TopAbs_SHELL) {
+            if (aMapFence.Add(anOtherShape)) {
+              TopExp_Explorer anExpSHF (anOtherShape, TopAbs_FACE);
+              for (; anExpSHF.More(); anExpSHF.Next()) {
+                theGroups[GROUP_OTHER].Append(anExpSHF.Current());
+              }
+            }
           } else {
             // Only faces can be in Other group.
             return false;
@@ -2705,11 +2855,12 @@ bool DoGroups(BRepOffsetAPI_MakePipeShell &theSweep,
 }
 
 //=======================================================================
-//function : CreateGroups
-//purpose  : auxilary for Execute()
+//function : CreateGroups1
+//purpose  : auxiliary for Execute()
 //=======================================================================
-bool CreateGroups(BRepOffsetAPI_MakePipeShell &theSweep,
-                  GEOMImpl_IPipe              *theCI)
+bool CreateGroups1 (const TopoDS_Shape          &theProfile,
+                    BRepOffsetAPI_MakePipeShell &theSweep,
+                    GEOMImpl_IPipe              *theCI)
 {
   if (!theCI->GetGenerateGroups()) {
     // Nothing to do.
@@ -2719,7 +2870,7 @@ bool CreateGroups(BRepOffsetAPI_MakePipeShell &theSweep,
   // Make groups.
   TopTools_SequenceOfShape aGroups[5];
 
-  if (!DoGroups(theSweep, aGroups)) {
+  if (!DoGroups1(theProfile, theSweep, aGroups)) {
     return false;
   }
 
@@ -2741,13 +2892,13 @@ bool CreateGroups(BRepOffsetAPI_MakePipeShell &theSweep,
 }
 
 //=======================================================================
-//function : DoGroups
-//purpose  : auxilary for CreateGroups()
+//function : DoGroups2
+//purpose  : auxiliary for CreateGroups()
 //=======================================================================
-static bool DoGroups(const TopoDS_Shape             &theProfile,
-                     const TopoDS_Shape             &thePath,
-                           BRepOffsetAPI_MakePipe   &theSweep,
-                           TopTools_SequenceOfShape *theGroups)
+static bool DoGroups2(const TopoDS_Shape             &theProfile,
+                      const TopoDS_Shape             &thePath,
+                            BRepOffsetAPI_MakePipe   &theSweep,
+                            TopTools_SequenceOfShape *theGroups)
 {
   Standard_Boolean isDoSides = Standard_False;
 
@@ -2791,7 +2942,7 @@ static bool DoGroups(const TopoDS_Shape             &theProfile,
       }
     }
   } else {
-    // Create Other group. Get boudnary edges of the profile.
+    // Create Other group. Get boundary edges of the profile.
     TopTools_MapOfShape aMapBndEdges;
     TopExp_Explorer     anExp(theProfile, TopAbs_EDGE);
 
@@ -2830,12 +2981,12 @@ static bool DoGroups(const TopoDS_Shape             &theProfile,
 
 //=======================================================================
 //function : CreateGroups
-//purpose  : auxilary for Execute()
+//purpose  : auxiliary for Execute()
 //=======================================================================
-static bool CreateGroups(const TopoDS_Shape     &theProfile,
-                         const TopoDS_Shape     &thePath,
-                         BRepOffsetAPI_MakePipe &theSweep,
-                         GEOMImpl_IPipe         *theCI)
+static bool CreateGroups2(const TopoDS_Shape     &theProfile,
+                          const TopoDS_Shape     &thePath,
+                          BRepOffsetAPI_MakePipe &theSweep,
+                          GEOMImpl_IPipe         *theCI)
 {
   if (!theCI->GetGenerateGroups()) {
     // Nothing to do.
@@ -2845,7 +2996,7 @@ static bool CreateGroups(const TopoDS_Shape     &theProfile,
   // Make groups.
   TopTools_SequenceOfShape aGroups[5];
 
-  if (!DoGroups(theProfile, thePath, theSweep, aGroups)) {
+  if (!DoGroups2(theProfile, thePath, theSweep, aGroups)) {
     return false;
   }
 
@@ -2870,7 +3021,7 @@ static bool CreateGroups(const TopoDS_Shape     &theProfile,
 //function : Execute
 //purpose  :
 //=======================================================================
-Standard_Integer GEOMImpl_PipeDriver::Execute (TFunction_Logbook& log) const
+Standard_Integer GEOMImpl_PipeDriver::Execute(Handle(TFunction_Logbook)& log) const
 {
   if (Label().IsNull()) return 0;
   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
@@ -2965,21 +3116,21 @@ Standard_Integer GEOMImpl_PipeDriver::Execute (TFunction_Logbook& log) const
     if (aShapeBase.ShapeType() == TopAbs_EDGE ||
         aShapeBase.ShapeType() == TopAbs_WIRE)
     {
-      TopoDS_Wire Profile;
+      TopoDS_Wire aProfile;
       if (aShapeBase.ShapeType() == TopAbs_WIRE)
-        Profile = TopoDS::Wire(aShapeBase);
+        aProfile = TopoDS::Wire(aShapeBase);
       else
       {
         BRep_Builder BB;
-        BB.MakeWire(Profile);
-        BB.Add(Profile, aShapeBase);
+        BB.MakeWire(aProfile);
+        BB.Add(aProfile, aShapeBase);
       }
 
       BRepOffsetAPI_MakePipeShell Sweep (aWirePath);
       BRepBuilderAPI_MakeFace FaceBuilder (aWirePath, Standard_True); //to find the plane of spine
       if (FaceBuilder.IsDone())
         Sweep.SetMode(FaceBuilder.Face());
-      Sweep.Add(Profile);
+      Sweep.Add(aProfile);
 
       Standard_Boolean isDone = BuildPipeShell(Sweep);
 
@@ -2991,7 +3142,7 @@ Standard_Integer GEOMImpl_PipeDriver::Execute (TFunction_Logbook& log) const
       else
         aShape = Sweep.Shape(); //result is good
 
-      if (!CreateGroups(Sweep, aCI)) {
+      if (!CreateGroups1(aProfile, Sweep, aCI)) {
         if (aCI) delete aCI;
         Standard_ConstructionError::Raise("Generate groups failure");
       }
@@ -2999,24 +3150,25 @@ Standard_Integer GEOMImpl_PipeDriver::Execute (TFunction_Logbook& log) const
     else
     {
       GeomFill_Trihedron theBestMode = EvaluateBestSweepMode(aWirePath);
-      BRepOffsetAPI_MakePipe aMkPipe(aWirePath, aShapeBase, theBestMode);
+      BRepOffsetAPI_MakePipe aMkPipe
+        (aWirePath, aShapeBase, theBestMode, Standard_True);
 
-      if (aMkPipe.IsDone()) {
+      if (aMkPipe.IsDone() && aMkPipe.ErrorOnSurface() <= TolPipeSurf) {
         aShape = aMkPipe.Shape();
 
-        if (!CreateGroups(aShapeBase, aWirePath, aMkPipe, aCI)) {
+        if (!CreateGroups2(aShapeBase, aWirePath, aMkPipe, aCI)) {
           if (aCI) delete aCI;
           Standard_ConstructionError::Raise("Generate groups failure");
         }
       } else if (theBestMode != GeomFill_IsDiscreteTrihedron) {
         // Try to use Descrete Trihedron mode.
         BRepOffsetAPI_MakePipe aMkPipeDescrete
-          (aWirePath, aShapeBase, GeomFill_IsDiscreteTrihedron);
+          (aWirePath, aShapeBase, GeomFill_IsDiscreteTrihedron, Standard_True);
 
         if (aMkPipeDescrete.IsDone()) {
           aShape = aMkPipeDescrete.Shape();
 
-          if (!CreateGroups(aShapeBase, aWirePath, aMkPipeDescrete, aCI)) {
+          if (!CreateGroups2(aShapeBase, aWirePath, aMkPipeDescrete, aCI)) {
             if (aCI) delete aCI;
             Standard_ConstructionError::Raise("Generate groups failure");
           }
@@ -3032,6 +3184,7 @@ Standard_Integer GEOMImpl_PipeDriver::Execute (TFunction_Logbook& log) const
     Handle(TColStd_HSequenceOfTransient) aLocObjs = aCIDS->GetLocations ();
     Standard_Boolean aWithContact = (aCIDS->GetWithContactMode());
     Standard_Boolean aWithCorrect = (aCIDS->GetWithCorrectionMode());
+    Standard_Boolean isBySteps = aCIDS->GetIsBySteps();
 
     if (aCI) {
       delete aCI;
@@ -3079,7 +3232,7 @@ Standard_Integer GEOMImpl_PipeDriver::Execute (TFunction_Logbook& log) const
 
     aShape = CreatePipeWithDifferentSections
               (aWirePath, aHSeqBases, aHSeqLocs,
-               aWithContact, aWithCorrect, pGroups);
+               aWithContact, aWithCorrect, isBySteps, pGroups);
 
     if (isGenerateGroups) {
       // Store created groups.
@@ -3222,7 +3375,7 @@ Standard_Integer GEOMImpl_PipeDriver::Execute (TFunction_Logbook& log) const
   TopoDS_Shape aRes = GEOMUtils::CompsolidToCompound(aShape);
   aFunction->SetValue(aRes);
 
-  log.SetTouched(Label());
+  log->SetTouched(Label());
   return 1;
 }
 
@@ -3265,8 +3418,13 @@ GetCreationInformation(std::string&             theOperationName,
     AddParam( theParams, "Bases", aCI.GetBases() );
     AddParam( theParams, "Locations", aCI.GetLocations() );
     AddParam( theParams, "Path", aCI.GetPath() );
-    AddParam( theParams, "With contact", aCI.GetWithContactMode() );
-    AddParam( theParams, "With correction", aCI.GetWithCorrectionMode() );
+
+    if (!aCI.GetIsBySteps()) {
+      AddParam( theParams, "With contact", aCI.GetWithContactMode() );
+      AddParam( theParams, "With correction", aCI.GetWithCorrectionMode() );
+    }
+
+    AddParam( theParams, "Step by step", aCI.GetIsBySteps() );
     break;
   }
   case PIPE_SHELL_SECTIONS:
@@ -3296,5 +3454,4 @@ GetCreationInformation(std::string&             theOperationName,
   return true;
 }
 
-IMPLEMENT_STANDARD_HANDLE (GEOMImpl_PipeDriver,GEOM_BaseDriver);
 IMPLEMENT_STANDARD_RTTIEXT (GEOMImpl_PipeDriver,GEOM_BaseDriver);