Salome HOME
Merge changes for HYDRO project : hydro/imps_2017_salome_84 branch.
[modules/geom.git] / src / GEOMImpl / GEOMImpl_PipeDriver.cxx
index cf660675f21080d4e5eaccf0a7fc0fdb6505ee33..aab459299de06e618e3ebc1d9fc5192d03fe34bc 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
 #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);
@@ -115,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
@@ -141,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)
 {
@@ -178,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();
@@ -194,24 +202,20 @@ 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,
                               const TopoDS_Shape& V1,
                               TopTools_IndexedDataMapOfShapeShape& FF)
 {
-  //cout<<"FillForOtherEdges"<<endl;
   // find other pairs for vertexes and edges
   // creating map of vertex edges for both faces
   TopTools_IndexedDataMapOfShapeListOfShape aMapVertEdge1;
   TopExp::MapShapesAndAncestors(F1, TopAbs_VERTEX, TopAbs_EDGE, aMapVertEdge1);
-  if (!FF.Contains(F1))
-    MESSAGE("    FillForOtherEdges: map FF not contains key F1");
-  if (!FF.Contains(E1))
-    MESSAGE("    FillForOtherEdges: map FF not contains key E1");
-  if (!FF.Contains(V1))
-    MESSAGE("    FillForOtherEdges: map FF not contains key V1");
+  if (!FF.Contains(F1)) MESSAGE("    FillForOtherEdges: map FF not contains key F1");
+  if (!FF.Contains(E1)) MESSAGE("    FillForOtherEdges: map FF not contains key E1");
+  if (!FF.Contains(V1)) MESSAGE("    FillForOtherEdges: map FF not contains key V1");
   const TopoDS_Shape& F2 = FF.FindFromKey(F1);
   const TopoDS_Shape& E2 = FF.FindFromKey(E1);
   const TopoDS_Shape& V2 = FF.FindFromKey(V1);
@@ -225,26 +229,18 @@ static bool FillForOtherEdges(const TopoDS_Shape& F1,
 
   ShapeAnalysis_Edge sae;
   while(1) {
-    if (!aMapVertEdge1.Contains(VS1))
-      MESSAGE ("    FillForOtherEdges: map aMapVertEdge1 not contains key VS1");
+    if (!aMapVertEdge1.Contains(VS1)) MESSAGE ("    FillForOtherEdges: map aMapVertEdge1 not contains key VS1");
     const TopTools_ListOfShape& aList1 = aMapVertEdge1.FindFromKey(VS1);
-    //TopoDS_Shape E1next;
     TopTools_ListIteratorOfListOfShape anIter1(aList1);
     if (anIter1.Value().IsSame(ES1)) {
       anIter1.Next();
     }
-    //E1next = anIter1.Value();
-    if (!aMapVertEdge2.Contains(VS2))
-      MESSAGE ("    FillForOtherEdges: map aMapVertEdge2 not contains key VS2");
+    if (!aMapVertEdge2.Contains(VS2)) MESSAGE ("    FillForOtherEdges: map aMapVertEdge2 not contains key VS2");
     const TopTools_ListOfShape& aList2 = aMapVertEdge2.FindFromKey(VS2);
-    //TopoDS_Shape E2next;
     TopTools_ListIteratorOfListOfShape anIter2(aList2);
     if (anIter2.Value().IsSame(ES2)) {
       anIter2.Next();
     }
-    //E2next = anIter2.Value();
-    //ES1 = TopoDS::Edge(E1next);
-    //ES2 = TopoDS::Edge(E2next);
     ES1 = TopoDS::Edge(anIter1.Value());
     ES2 = TopoDS::Edge(anIter2.Value());
     if (!FF.Contains(ES1)) {
@@ -270,7 +266,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,
@@ -279,7 +275,6 @@ static bool FillCorrespondingEdges(const TopoDS_Shape& FS1,
                                    const TopoDS_Wire& aWirePath,
                                    TopTools_IndexedDataMapOfShapeShape& FF)
 {
-  //cout<<"FillCorrespondingEdges"<<endl;
   // find corresponding edges
   TopExp_Explorer expw1(FS1,TopAbs_WIRE);
   TopoDS_Wire aWire1 = TopoDS::Wire(expw1.Current());
@@ -310,8 +305,6 @@ static bool FillCorrespondingEdges(const TopoDS_Shape& FS1,
   TopoDS_Vertex V21 = sae.LastVertex(E1);
   gp_Pnt P11 = BRep_Tool::Pnt(V11);
   gp_Pnt P21 = BRep_Tool::Pnt(V21);
-  //cout<<"P11("<<P11.X()<<","<<P11.Y()<<","<<P11.Z()<<")"<<endl;
-  //cout<<"P21("<<P21.X()<<","<<P21.Y()<<","<<P21.Z()<<")"<<endl;
   // find corresponding vertexes from created shape
   TopoDS_Vertex VN11,VN21;
   for (exp.Init(aShape, TopAbs_VERTEX); exp.More(); exp.Next()) {
@@ -362,8 +355,6 @@ static bool FillCorrespondingEdges(const TopoDS_Shape& FS1,
   TopoDS_Vertex V12,V22;
   gp_Pnt PN12 = BRep_Tool::Pnt(VN12);
   gp_Pnt PN22 = BRep_Tool::Pnt(VN22);
-  //cout<<"PN12("<<PN12.X()<<","<<PN12.Y()<<","<<PN12.Z()<<")"<<endl;
-  //cout<<"PN22("<<PN22.X()<<","<<PN22.Y()<<","<<PN22.Z()<<")"<<endl;
   TopoDS_Edge E2;
   TopExp_Explorer expe;
   for (expe.Init(FS2, TopAbs_EDGE); expe.More(); expe.Next()) {
@@ -398,7 +389,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,
@@ -406,8 +397,6 @@ static bool FillCorrespondingEdges(const TopoDS_Shape& FS1,
                                    const TopoDS_Vertex& aLoc2,
                                    TopTools_IndexedDataMapOfShapeShape& FF)
 {
-  //cout<<"FillCorrespondingEdges"<<endl;
-
   gp_Pnt P1 = BRep_Tool::Pnt(aLoc1);
   gp_Pnt P2 = BRep_Tool::Pnt(aLoc2);
   gp_Vec aDir(P1,P2);
@@ -427,8 +416,6 @@ static bool FillCorrespondingEdges(const TopoDS_Shape& FS1,
     TopoDS_Vertex V2 = sae.LastVertex(E1);
     gp_Pnt Ptmp1 = BRep_Tool::Pnt(V1);
     gp_Pnt Ptmp2 = BRep_Tool::Pnt(V2);
-    //cout<<"P11("<<P11.X()<<","<<P11.Y()<<","<<P11.Z()<<")"<<endl;
-    //cout<<"P21("<<P21.X()<<","<<P21.Y()<<","<<P21.Z()<<")"<<endl;
     if (P1.Distance(Ptmp1)<tol) {
       V21 = V2;
       break;
@@ -500,7 +487,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,
@@ -508,7 +495,6 @@ static void FindNextPairOfFaces(const TopoDS_Shape& aCurFace,
                                 TopTools_IndexedDataMapOfShapeShape& FF,
                                 GEOMImpl_IPipe* aCI)
 {
-  //cout<<"FindNextPairOfFaces"<<endl;
   TopExp_Explorer anExp;
   for (anExp.Init(aCurFace, TopAbs_EDGE); anExp.More(); anExp.Next()) {
     TopoDS_Shape E1 = anExp.Current();
@@ -516,8 +502,7 @@ static void FindNextPairOfFaces(const TopoDS_Shape& aCurFace,
       if (aCI) delete aCI;
       Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not find edge in map");
     }
-    if (!FF.Contains(E1))
-      MESSAGE ("    FindNextPairOfFaces: map FF not contains key E1");
+    if (!FF.Contains(E1)) MESSAGE ("    FindNextPairOfFaces: map FF not contains key E1");
     const TopoDS_Shape& E2 = FF.FindFromKey(E1);
     TopExp_Explorer anExpV;
     anExpV.Init(E1, TopAbs_VERTEX);
@@ -527,8 +512,7 @@ static void FindNextPairOfFaces(const TopoDS_Shape& aCurFace,
       Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not find vertex in map");
     }
 
-    if (!aMapEdgeFaces1.Contains(E1))
-      MESSAGE ("    FindNextPairOfFaces: map aMapEdgeFaces1 not contains key E1");
+    if (!aMapEdgeFaces1.Contains(E1)) MESSAGE ("    FindNextPairOfFaces: map aMapEdgeFaces1 not contains key E1");
     const TopTools_ListOfShape& aList1 = aMapEdgeFaces1.FindFromKey(E1);
     if (aList1.Extent()<2)
       continue;
@@ -540,11 +524,9 @@ static void FindNextPairOfFaces(const TopoDS_Shape& aCurFace,
     if (FF.Contains(F1other))
       continue;
 
-    if (!FF.Contains(aCurFace))
-      MESSAGE ("    FindNextPairOfFaces: map FF not contains key aCurFace");
+    if (!FF.Contains(aCurFace)) MESSAGE ("    FindNextPairOfFaces: map FF not contains key aCurFace");
     const TopoDS_Shape& F2 = FF.FindFromKey(aCurFace);
-    if (!aMapEdgeFaces2.Contains(E2))
-      MESSAGE ("    FindNextPairOfFaces: map aMapEdgeFaces2 not contains key E2");
+    if (!aMapEdgeFaces2.Contains(E2)) MESSAGE ("    FindNextPairOfFaces: map aMapEdgeFaces2 not contains key E2");
     const TopTools_ListOfShape& aList2 = aMapEdgeFaces2.FindFromKey(E2);
     if (aList2.Extent()<2) {
       if (aCI) delete aCI;
@@ -561,7 +543,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);
@@ -570,14 +552,12 @@ 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,
                                TopoDS_Shape& FS1, TopoDS_Shape& FS2)
 {
-  //cout<<"FindFirstPairFaces"<<endl;
-
   // check if vertexes are sub-shapes of sections
   gp_Pnt P1 = BRep_Tool::Pnt(V1);
   gp_Pnt P2 = BRep_Tool::Pnt(V2);
@@ -604,13 +584,6 @@ static void FindFirstPairFaces(const TopoDS_Shape& S1, const TopoDS_Shape& S2,
     }
   }
 
-  //gp_Pnt P1new = BRep_Tool::Pnt(V1new);
-  //gp_Pnt P2new = BRep_Tool::Pnt(V2new);
-  //cout<<"  P1("<<P1.X()<<","<<P1.Y()<<","<<P1.Z()<<")"<<endl;
-  //cout<<"  P2("<<P2.X()<<","<<P2.Y()<<","<<P2.Z()<<")"<<endl;
-  //cout<<"  P1new("<<P1new.X()<<","<<P1new.Y()<<","<<P1new.Z()<<")"<<endl;
-  //cout<<"  P2new("<<P2new.X()<<","<<P2new.Y()<<","<<P2new.Z()<<")"<<endl;
-
   // replace vertexes if it is needed
   if (!V1.IsSame(V1new)) {
     V1 = V1new;
@@ -692,7 +665,7 @@ static void FindFirstPairFaces(const TopoDS_Shape& S1, const TopoDS_Shape& S2,
 //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. Auxilary for CreatePipeWithDifferentSections
+//           a compound otherwise. Auxiliary for CreatePipeWithDifferentSections
 //           method.
 //=======================================================================
 static TopoDS_Shape RemoveFaces(const TopoDS_Shape &theShapeFrom,
@@ -724,6 +697,93 @@ static TopoDS_Shape RemoveFaces(const TopoDS_Shape &theShapeFrom,
   return aResult;
 }
 
+//=======================================================================
+//function : makeSolid
+//purpose  : auxilary for CreatePipeWithDifferentSections
+//=======================================================================
+Standard_Boolean makeSolid(
+  BRepOffsetAPI_MakePipeShell aBuilder,
+  const TopoDS_Shape& aSh1,
+  const TopoDS_Shape& aSh2,
+  TopoDS_Shape& aShape)
+{
+  Standard_Boolean isDone = Standard_True;
+  Standard_Integer nbPlanar = 0;
+  if (aSh1.ShapeType() == TopAbs_FACE && aSh2.ShapeType() == TopAbs_FACE)
+  {
+    Handle(Geom_Surface) aS = BRep_Tool::Surface(TopoDS::Face(aSh1));
+    if (aS->IsKind(STANDARD_TYPE(Geom_Plane))) {
+      nbPlanar++;
+    }
+    else if (aS->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
+      Handle(Geom_RectangularTrimmedSurface) aTS = Handle(Geom_RectangularTrimmedSurface)::DownCast(aS);
+      if (aTS->BasisSurface()->IsKind(STANDARD_TYPE(Geom_Plane))) {
+        nbPlanar++;
+      }
+    }
+    aS = BRep_Tool::Surface(TopoDS::Face(aSh2));
+    if (aS->IsKind(STANDARD_TYPE(Geom_Plane))) {
+      nbPlanar++;
+    }
+    else if (aS->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
+      Handle(Geom_RectangularTrimmedSurface) aTS = Handle(Geom_RectangularTrimmedSurface)::DownCast(aS);
+      if (aTS->BasisSurface()->IsKind(STANDARD_TYPE(Geom_Plane))) {
+        nbPlanar++;
+      }
+    }
+  }
+  if (nbPlanar < 2) {
+    TopoDS_Shape aPipe = aBuilder.Shape();
+    // make sewing for result
+    Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing;
+    Standard_Real aTol = Precision::Confusion();
+    aSewing->SetTolerance(aTol);
+    aSewing->SetFaceMode(Standard_True);
+    aSewing->SetFloatingEdgesMode(Standard_False);
+    aSewing->SetNonManifoldMode(Standard_False);
+    TopExp_Explorer anExp;
+    for (anExp.Init(aPipe, TopAbs_FACE); anExp.More(); anExp.Next()) {
+      aSewing->Add(anExp.Current());
+    }
+    aSewing->Add(aSh1);
+    aSewing->Add(aSh2);
+    aSewing->Perform();
+    aShape = aSewing->SewedShape();
+    if (aShape.ShapeType() == TopAbs_SHELL) {
+      // Build a solid.
+      BRepBuilderAPI_MakeSolid aMkSolid;
+      aMkSolid.Add(TopoDS::Shell(aShape));
+      if (!aMkSolid.IsDone()) {
+        isDone = Standard_False;
+      }
+      else {
+        TopoDS_Solid aSolid = aMkSolid.Solid();
+        BRepClass3d_SolidClassifier aSC(aSolid);
+        aSC.PerformInfinitePoint(Precision::Confusion());
+        if (aSC.State() == TopAbs_IN) {
+          aShape = aSolid.Reversed();
+        }
+        else {
+          aShape = aSolid;
+        }
+      }
+    }
+    else {
+      isDone = Standard_False;
+    }
+  }
+  else {
+    isDone = Standard_False;
+  }
+  if (!isDone) {
+    isDone = aBuilder.MakeSolid();
+    if (isDone) {
+      aShape = aBuilder.Shape();
+    }
+  }
+  return isDone;
+}
+
 //=======================================================================
 //function : CreatePipeWithDifferentSections
 //purpose  :
@@ -837,7 +897,6 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections
     double tol = BRep_Tool::Tolerance(edge);
     TopoDS_Vertex VF = sae.FirstVertex(edge);
     gp_Pnt PF = BRep_Tool::Pnt(VF);
-    //cout<<"PF("<<PF.X()<<","<<PF.Y()<<","<<PF.Z()<<")"<<endl;
     if (PF.Distance(PLocs.First()) > tol) {
       Standard_ConstructionError::Raise
         ("First location shapes is not coincided with first vertex of aWirePath");
@@ -911,7 +970,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);
@@ -973,7 +1032,6 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections
       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);
@@ -1063,7 +1121,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");
           }
 
@@ -1125,7 +1184,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");
         }
 
@@ -1259,25 +1319,32 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections
 
         Standard_Boolean isDone = BuildPipeShell(aBuilder);
 
-        if (isDone && NeedCreateSolid) {
-          isDone = aBuilder.MakeSolid();
+        if (isDone) {
+          if (NeedCreateSolid) {
+            TopoDS_Shape aSh1 = aSeqFaces.Value(1);
+            TopoDS_Shape aSh2 = aSeqFaces.Value(aSeqFaces.Length());
+            isDone = makeSolid(aBuilder, aSh1, aSh2, aShape);
+          }
+          else {
+            aShape = aBuilder.Shape();
+          }
         }
 
         if (!isDone) {
           Standard_ConstructionError::Raise("Pipe construction failure");
         }
-        aShape = aBuilder.Shape();
 
         if (isCreateGroups) {
           // 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();
 
@@ -1298,7 +1365,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)
@@ -1396,7 +1463,6 @@ static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath,
     double tol = BRep_Tool::Tolerance(edge);
     TopoDS_Vertex VF = sae.FirstVertex(edge);
     gp_Pnt PF = BRep_Tool::Pnt(VF);
-    //cout<<"PF("<<PF.X()<<","<<PF.Y()<<","<<PF.Z()<<")"<<endl;
     if (PF.Distance(PLocs.First()) > tol) {
       if (aCI) delete aCI;
       Standard_ConstructionError::Raise
@@ -1627,7 +1693,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");
           }
@@ -1813,7 +1879,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");
         }
 
       }
@@ -1914,7 +1980,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");
             }
@@ -1955,8 +2021,7 @@ static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath,
             aShell = TopoDS::Shell(aSewShape);
             GProp_GProps aSystem;
             BRepGProp::VolumeProperties(aShell, aSystem);
-            if (aSystem.Mass()<0) {
-              //cout<<"aSewShape is reversed"<<endl;
+            if (aSystem.Mass() < 0) {
               aShell.Reverse();
             }
             if (BRep_Tool::IsClosed(aShell)) {
@@ -2023,11 +2088,10 @@ 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)
 {
-  //cout<<"CreatePipeShellsWithoutPath"<<endl;
   int i,j;
   BRep_Builder B;
 
@@ -2091,7 +2155,6 @@ static TopoDS_Shape CreatePipeShellsWithoutPath(GEOMImpl_IPipe* aCI)
     for (anExp.Init(aShBase2, TopAbs_FACE); anExp.More(); anExp.Next()) {
       nbf2++;
     }
-    //cout<<"nbf1="<<nbf1<<" nbf2="<<nbf2<<endl;
     if (nbf1!=nbf2) {
       if (aCI) delete aCI;
       Standard_ConstructionError::Raise("Different number of faces in the sections");
@@ -2143,16 +2206,15 @@ 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;
     int nbff = 0;
     for (j=1; j<=FF.Extent(); j++) {
       TopoDS_Shape F1 = FF.FindKey(j);
@@ -2214,7 +2276,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;
         }
@@ -2289,26 +2351,13 @@ static TopoDS_Shape CreatePipeShellsWithoutPath(GEOMImpl_IPipe* aCI)
 
         double fp,lp;
         Handle(Geom_Curve) C1 = BRep_Tool::Curve(E1,fp,lp);
-        //bool IsConicC1 = false;
-        //if (C1->IsKind(STANDARD_TYPE(Geom_Conic))) {
-        //  IsConicC1 = true;
-        //  cout<<"C1 - Geom_Conic"<<endl;
-        //}
         if (C1->IsKind(STANDARD_TYPE(Geom_Line)) || C1->IsKind(STANDARD_TYPE(Geom_Conic))) {
           C1 = new Geom_TrimmedCurve(C1,fp,lp);
         }
-        //if (IsConicC1) {
-        //  double tol = BRep_Tool::Tolerance(E1);
-        //  GeomConvert_ApproxCurve ApxC1(C1,tol,GeomAbs_C1,10,5);
-        //  C1 = ApxC1.Curve();
-        //}
         Handle(Geom_Curve) C3 = BRep_Tool::Curve(E3,fp,lp);
         if (C3->IsKind(STANDARD_TYPE(Geom_Line)) || C3->IsKind(STANDARD_TYPE(Geom_Conic))) {
           C3 = new Geom_TrimmedCurve(C3,fp,lp);
         }
-        //filebuf fic;
-        //ostream os(&fic);
-        //os.precision(15);
         Handle(Geom_BSplineCurve) CE1 =
           GeomConvert::CurveToBSplineCurve(C1,Convert_RationalC1);
         if (CE1->Degree()<3)
@@ -2395,7 +2444,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);
@@ -2464,8 +2513,7 @@ static TopoDS_Shape CreatePipeShellsWithoutPath(GEOMImpl_IPipe* aCI)
         aShell = TopoDS::Shell(aSewShape);
         GProp_GProps aSystem;
         BRepGProp::VolumeProperties(aShell, aSystem);
-        if (aSystem.Mass()<0) {
-          //cout<<"aSewShape is reversed"<<endl;
+        if (aSystem.Mass() < 0) {
           aShell.Reverse();
         }
         if (BRep_Tool::IsClosed(aShell)) {
@@ -2531,7 +2579,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)
@@ -2598,7 +2646,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");
   }
@@ -2608,7 +2656,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,
@@ -2641,7 +2689,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)
@@ -2669,7 +2717,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,
@@ -2733,11 +2781,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;
 
@@ -2746,7 +2795,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.
@@ -2777,8 +2827,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;
             }
           }
@@ -2786,7 +2843,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);
 
@@ -2815,6 +2872,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;
@@ -2828,11 +2892,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.
@@ -2842,7 +2907,7 @@ bool CreateGroups(BRepOffsetAPI_MakePipeShell &theSweep,
   // Make groups.
   TopTools_SequenceOfShape aGroups[5];
 
-  if (!DoGroups(theSweep, aGroups)) {
+  if (!DoGroups1(theProfile, theSweep, aGroups)) {
     return false;
   }
 
@@ -2864,13 +2929,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;
 
@@ -2914,7 +2979,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);
 
@@ -2953,12 +3018,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.
@@ -2968,7 +3033,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;
   }
 
@@ -2993,7 +3058,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());
@@ -3088,21 +3153,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);
 
@@ -3114,7 +3179,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");
       }
@@ -3122,24 +3187,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");
           }
@@ -3346,7 +3412,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;
 }
 
@@ -3425,5 +3491,4 @@ GetCreationInformation(std::string&             theOperationName,
   return true;
 }
 
-IMPLEMENT_STANDARD_HANDLE (GEOMImpl_PipeDriver,GEOM_BaseDriver);
 IMPLEMENT_STANDARD_RTTIEXT (GEOMImpl_PipeDriver,GEOM_BaseDriver);