]> SALOME platform Git repositories - modules/geom.git/commitdiff
Salome HOME
Implementation of PipeWithShellSections.
authorskl <skl@opencascade.com>
Mon, 9 Apr 2007 13:10:07 +0000 (13:10 +0000)
committerskl <skl@opencascade.com>
Mon, 9 Apr 2007 13:10:07 +0000 (13:10 +0000)
14 files changed:
idl/GEOM_Gen.idl
idl/GEOM_Superv.idl
src/GEOMImpl/GEOMImpl_I3DPrimOperations.cxx
src/GEOMImpl/GEOMImpl_I3DPrimOperations.hxx
src/GEOMImpl/GEOMImpl_IPipeDiffSect.hxx
src/GEOMImpl/GEOMImpl_IPipeShellSect.hxx [new file with mode: 0644]
src/GEOMImpl/GEOMImpl_PipeDriver.cxx
src/GEOMImpl/GEOMImpl_PipeDriver.hxx
src/GEOMImpl/GEOMImpl_Types.hxx
src/GEOM_I/GEOM_I3DPrimOperations_i.cc
src/GEOM_I/GEOM_I3DPrimOperations_i.hh
src/GEOM_I_Superv/GEOM_Superv_i.cc
src/GEOM_I_Superv/GEOM_Superv_i.hh
src/GEOM_SWIG/geompy.py

index 33d31bbcaf7f54da2821fa8293da37dc162fd921..6eba34398b165c3b559aef95287020181aee925c 100644 (file)
@@ -888,6 +888,29 @@ module GEOM
                                               in boolean theWithContact ,
                                               in boolean theWithCorrection );
     
+    /*!
+     *  Create a shape by extrusion of the profile shape along
+     *  the path shape. The path shape can be a shell or a face.
+     *  the several profiles can be specified in the several locations of path.        
+     *  \param theSeqBases - list of  Bases shape to be extruded.
+     *  \param theSeqSubBases - list of corresponding subshapes of section shapes.
+     *  \param theLocations - list of locations on the path corresponding
+     *                        specified list of the Bases shapes. Number of locations
+     *                        should be equal to number of bases or list of locations can be empty.
+     *  \param thePath - Path shape to extrude the base shape along it.
+     *  \param theWithContact - the mode defining that the section is translated to be in
+     *                          contact with the spine.
+     *  \param - WithCorrection - defining that the section is rotated to be
+     *                          orthogonal to the spine tangent in the correspondent point
+     *  \return New GEOM_Object, containing the created pipe.
+     */
+    GEOM_Object MakePipeWithShellSections (in ListOfGO theSeqBases,
+                                          in ListOfGO theSeqSubBases,
+                                          in ListOfGO theLocations,
+                                          in GEOM_Object thePath,
+                                          in boolean theWithContact ,
+                                          in boolean theWithCorrection );
+    
   };
 
   /*!
index 75f67c8eb3b17af89eff3592f1fd40d8a74b5ced..074ff9e5ae7851f0219e174d61e754dd5a0085fa 100644 (file)
@@ -177,6 +177,13 @@ module GEOM
                                               in boolean theWithContact ,
                                               in boolean theWithCorrection );
     
+    GEOM_Object MakePipeWithShellSections (in ListOfGO theSeqBases,
+                                          in ListOfGO theSeqSubBases,
+                                          in ListOfGO theLocations,
+                                          in GEOM_Object thePath,
+                                          in boolean theWithContact ,
+                                          in boolean theWithCorrection );
+    
     //-----------------------------------------------------------//
     // BooleanOperations                                         //
     //-----------------------------------------------------------//
index a4ed0e79e300eb53dc15ffde2290b6f6624f67b0..de70f12593474c28353968098390da78e7401a07 100644 (file)
@@ -59,6 +59,7 @@
 #include <GEOMImpl_IFilling.hxx>
 #include <GEOMImpl_IThruSections.hxx>
 #include <GEOMImpl_IPipeDiffSect.hxx>
+#include <GEOMImpl_IPipeShellSect.hxx>
 
 #include <Standard_Failure.hxx>
 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
@@ -1091,17 +1092,18 @@ Handle(GEOM_Object) GEOMImpl_I3DPrimOperations::MakeThruSections(
    
 }
 
+
 //=============================================================================
 /*!
  *  MakePipeWithDifferentSections
  */
 //=============================================================================
 Handle(GEOM_Object) GEOMImpl_I3DPrimOperations::MakePipeWithDifferentSections(
-                                               const Handle(TColStd_HSequenceOfTransient)& theBases,
-                                               const Handle(TColStd_HSequenceOfTransient)& theLocations,
-                                               const Handle(GEOM_Object)& thePath,
-                                               bool theWithContact,
-                                                bool theWithCorrections)
+               const Handle(TColStd_HSequenceOfTransient)& theBases,
+               const Handle(TColStd_HSequenceOfTransient)& theLocations,
+               const Handle(GEOM_Object)& thePath,
+               bool theWithContact,
+               bool theWithCorrections)
 {
   Handle(GEOM_Object) anObj;
   SetErrorCode(KO);
@@ -1232,3 +1234,165 @@ Handle(GEOM_Object) GEOMImpl_I3DPrimOperations::MakePipeWithDifferentSections(
   
    
 }
+
+
+//=============================================================================
+/*!
+ *  MakePipeWithShellSections
+ */
+//=============================================================================
+Handle(GEOM_Object) GEOMImpl_I3DPrimOperations::MakePipeWithShellSections(
+               const Handle(TColStd_HSequenceOfTransient)& theBases,
+               const Handle(TColStd_HSequenceOfTransient)& theSubBases,
+               const Handle(TColStd_HSequenceOfTransient)& theLocations,
+               const Handle(GEOM_Object)& thePath,
+               bool theWithContact,
+               bool theWithCorrections)
+{
+  Handle(GEOM_Object) anObj;
+  SetErrorCode(KO);
+  if(theBases.IsNull())
+    return anObj;
+
+  Standard_Integer nbBases = theBases->Length();
+  
+  if (!nbBases)
+    return anObj;
+  
+  Standard_Integer nbSubBases =  (theSubBases.IsNull() ? 0 :theSubBases->Length());
+
+  Standard_Integer nbLocs =  (theLocations.IsNull() ? 0 :theLocations->Length());
+
+  //Add a new Pipe object
+  Handle(GEOM_Object) aPipeDS = GetEngine()->AddObject(GetDocID(), GEOM_PIPE);
+  //Add a new Pipe function
+
+  Handle(GEOM_Function) aFunction =
+    aPipeDS->AddFunction(GEOMImpl_PipeDriver::GetID(), PIPE_SHELL_SECTIONS);
+  if (aFunction.IsNull()) return anObj;
+
+  //Check if the function is set correctly
+  if (aFunction->GetDriverGUID() != GEOMImpl_PipeDriver::GetID()) return anObj;
+
+  //GEOMImpl_IPipeDiffSect aCI (aFunction);
+  GEOMImpl_IPipeShellSect aCI (aFunction);
+
+  Handle(GEOM_Function) aRefPath = thePath->GetLastFunction();
+  if(aRefPath.IsNull())
+    return anObj;
+
+  Handle(TColStd_HSequenceOfTransient) aSeqBases = new TColStd_HSequenceOfTransient;
+  Handle(TColStd_HSequenceOfTransient) aSeqSubBases = new TColStd_HSequenceOfTransient;
+  Handle(TColStd_HSequenceOfTransient) aSeqLocs = new TColStd_HSequenceOfTransient;
+
+  Standard_Integer i =1;
+  for( ; i <= nbBases; i++) {
+
+    Handle(Standard_Transient) anItem = theBases->Value(i);
+    if(anItem.IsNull())
+      continue;
+    Handle(GEOM_Object) aBase = Handle(GEOM_Object)::DownCast(anItem);
+    if(aBase.IsNull())
+      continue;
+    Handle(GEOM_Function) aRefBase = aBase->GetLastFunction();
+    if(aRefBase.IsNull())
+      continue;
+
+    if( nbSubBases >= nbBases ) {
+      Handle(Standard_Transient) aSubItem = theSubBases->Value(i);
+      if(aSubItem.IsNull())
+       continue;
+      Handle(GEOM_Object) aSubBase = Handle(GEOM_Object)::DownCast(aSubItem);
+      if(aSubBase.IsNull())
+       continue;
+      Handle(GEOM_Function) aRefSubBase = aSubBase->GetLastFunction();
+      if(aRefSubBase.IsNull())
+       continue;
+      aSeqSubBases->Append(aRefSubBase);
+    }
+
+    if(nbLocs) {
+      Handle(Standard_Transient) anItemLoc = theLocations->Value(i);
+      if(anItemLoc.IsNull())
+       continue;
+      Handle(GEOM_Object) aLoc = Handle(GEOM_Object)::DownCast(anItemLoc);
+      if(aLoc.IsNull())
+       continue;
+      Handle(GEOM_Function) aRefLoc = aLoc->GetLastFunction();
+      if(aRefLoc.IsNull())
+       continue;
+      aSeqLocs->Append(aRefLoc);
+    }
+
+    aSeqBases->Append(aRefBase);
+  }
+
+  if(!aSeqBases->Length())
+    return anObj;
+
+  aCI.SetBases(aSeqBases);
+  aCI.SetSubBases(aSeqSubBases);
+  aCI.SetLocations(aSeqLocs);
+  aCI.SetPath(aRefPath);
+  aCI.SetWithContactMode(theWithContact);
+  aCI.SetWithCorrectionMode(theWithCorrections);
+  
+  //Compute the Pipe value
+  try {
+#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
+    OCC_CATCH_SIGNALS;
+#endif
+    if (!GetSolver()->ComputeFunction(aFunction)) {
+      SetErrorCode("Pipe with shell sections driver failed");
+      return anObj;
+    }
+  }
+  catch (Standard_Failure) {
+    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
+    SetErrorCode(aFail->GetMessageString());
+    return anObj;
+  }
+
+  //Make a Python command
+  GEOM::TPythonDump pyDump(aFunction);
+  pyDump << aPipeDS << " = geompy.MakePipeWithShellSections([";
+
+  for(i =1 ; i <= nbBases; i++) {
+
+    Handle(Standard_Transient) anItem = theBases->Value(i);
+    if(anItem.IsNull())
+      continue;
+    
+    Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(anItem);
+    if(!anObj.IsNull()) {
+      pyDump<< anObj;
+      if(i < nbBases)
+       pyDump<<", ";
+    }
+    
+  }
+  
+  pyDump<< "], [";
+   
+  for(i =1 ; i <= nbLocs; i++) {
+
+    Handle(Standard_Transient) anItem = theLocations->Value(i);
+    if(anItem.IsNull())
+      continue;
+    
+    Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(anItem);
+    if(!anObj.IsNull()) {
+      pyDump<< anObj;
+      if(i < nbLocs)
+       pyDump<<", ";
+    }
+  }  
+
+  pyDump<< "], "<<thePath<<","<<theWithContact << "," << theWithCorrections<<")";
+
+  SetErrorCode(OK);
+  return aPipeDS;
+
+}
+
index 3808e4db0f94f6ed7ee7fab1d564ea522ae53d2c..5773f2f47f6dd5a8df88808d07a89558acc1f193 100644 (file)
@@ -80,11 +80,20 @@ class GEOMImpl_I3DPrimOperations : public GEOM_IOperations {
                                                        bool theRuled);
 
   Standard_EXPORT Handle(GEOM_Object) MakePipeWithDifferentSections(
-                                                 const Handle(TColStd_HSequenceOfTransient)& theBases,
-                                                 const Handle(TColStd_HSequenceOfTransient)& theLocations,
-                                                 const Handle(GEOM_Object)& thePath,
-                                                 bool theWithContact,
-                                                  bool theWithCorrections);
+               const Handle(TColStd_HSequenceOfTransient)& theBases,
+               const Handle(TColStd_HSequenceOfTransient)& theLocations,
+               const Handle(GEOM_Object)& thePath,
+               bool theWithContact,
+               bool theWithCorrections);
+
+  Standard_EXPORT Handle(GEOM_Object) MakePipeWithShellSections(
+               const Handle(TColStd_HSequenceOfTransient)& theBases,
+               const Handle(TColStd_HSequenceOfTransient)& theSubBases,
+               const Handle(TColStd_HSequenceOfTransient)& theLocations,
+               const Handle(GEOM_Object)& thePath,
+               bool theWithContact,
+               bool theWithCorrections);
+
 };
 
 #endif
index 81458260be20aec76eba985bf7c01840d4157840..711348b97ef503cc50895dcae73076a4c1c80712 100644 (file)
@@ -42,13 +42,15 @@ class GEOMImpl_IPipeDiffSect : public GEOMImpl_IPipe
   GEOMImpl_IPipeDiffSect(const Handle(GEOM_Function)& theFunction):GEOMImpl_IPipe(theFunction) {}
   
   void SetBases (const Handle(TColStd_HSequenceOfTransient)& theBases) 
-  { _func->SetReferenceList(PIPEDS_LIST_BASES,theBases); }
+  {
+    _func->SetReferenceList(PIPEDS_LIST_BASES,theBases);
+  }
 
   Handle(TColStd_HSequenceOfTransient) GetBases ()
   { 
     Handle(TColStd_HSequenceOfTransient) aBases = _func->GetReferenceList(PIPEDS_LIST_BASES);
     return aBases; 
-   }
+  }
 
   void SetLocations (const Handle(TColStd_HSequenceOfTransient)& theLocations) 
   { _func->SetReferenceList(PIPEDS_LIST_LOCATIONS,theLocations); }
diff --git a/src/GEOMImpl/GEOMImpl_IPipeShellSect.hxx b/src/GEOMImpl/GEOMImpl_IPipeShellSect.hxx
new file mode 100644 (file)
index 0000000..590e836
--- /dev/null
@@ -0,0 +1,55 @@
+// Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either 
+// version 2.1 of the License.
+// 
+// This library is distributed in the hope that it will be useful 
+// but WITHOUT ANY WARRANTY; without even the implied warranty of 
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public  
+// License along with this library; if not, write to the Free Software 
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+//NOTE: This is an intreface to a function for the Pipe creation.
+
+#ifndef _GEOMImpl_IPIPESHELLSECT_HXX_
+#define _GEOMImpl_IPIPESHELLSECT_HXX_
+
+#include "GEOM_Function.hxx"
+
+#ifndef _GEOMImpl_IPIPEDIFFSECT_HXX_
+#include "GEOMImpl_IPipeDiffSect.hxx"
+#endif
+
+#define PIPEDS_LIST_SUBBASES 6
+
+
+class GEOMImpl_IPipeShellSect : public GEOMImpl_IPipeDiffSect
+{
+ public:
+
+  GEOMImpl_IPipeShellSect(const Handle(GEOM_Function)& theFunction):
+    GEOMImpl_IPipeDiffSect(theFunction) {}
+  
+  void SetSubBases (const Handle(TColStd_HSequenceOfTransient)& theSubBases) 
+  {
+    _func->SetReferenceList(PIPEDS_LIST_SUBBASES,theSubBases);
+  }
+
+  Handle(TColStd_HSequenceOfTransient) GetSubBases ()
+  { 
+    Handle(TColStd_HSequenceOfTransient) aSubBases =
+      _func->GetReferenceList(PIPEDS_LIST_SUBBASES);
+    return aSubBases; 
+  }
+
+};
+
+#endif
index d0875f8428f7f7276ef445348766c6164bf172a8..b14de152b39ee58f130d32391accd5b9c53510b9 100644 (file)
 #include <TopoDS_Wire.hxx>
 #include <TopoDS_Edge.hxx>
 #include <TopoDS_Shape.hxx>
+#include <TopoDS_Solid.hxx>
+#include <TopoDS_Shell.hxx>
+#include <TopoDS_Face.hxx>
 #include <BRepOffsetAPI_MakePipeShell.hxx>
 #include <TColStd_HSequenceOfTransient.hxx>
 #include <GEOMImpl_IPipeDiffSect.hxx>
+#include <GEOMImpl_IPipeShellSect.hxx>
 
 #include <Standard_NullObject.hxx>
 #include <Standard_TypeMismatch.hxx>
 #include <TopTools_SequenceOfShape.hxx>
 #include <BRep_Builder.hxx>
 #include <TopoDS_Compound.hxx>
+#include <ShapeAnalysis_FreeBounds.hxx>
+#include <TColgp_SequenceOfPnt.hxx>
+#include <ShapeAnalysis_Edge.hxx>
+#include <TopTools_IndexedDataMapOfShapeShape.hxx>
+#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
+#include <TopExp.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <GeomAPI_ProjectPointOnCurve.hxx>
+#include <Precision.hxx>
+#include <Geom_TrimmedCurve.hxx>
+#include <BRepBuilderAPI_Sewing.hxx>
+
+//#include <BRepTools.hxx>
+
 
 //=======================================================================
 //function : GetID
@@ -67,6 +85,834 @@ GEOMImpl_PipeDriver::GEOMImpl_PipeDriver()
 {
 }
 
+
+//=======================================================================
+//function : FillForOtherEdges
+//purpose  : auxilary 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);
+  const TopoDS_Shape& F2 = FF.FindFromKey(F1);
+  const TopoDS_Shape& E2 = FF.FindFromKey(E1);
+  const TopoDS_Shape& V2 = FF.FindFromKey(V1);
+  TopTools_IndexedDataMapOfShapeListOfShape aMapVertEdge2;
+  TopExp::MapShapesAndAncestors(F2, TopAbs_VERTEX, TopAbs_EDGE, aMapVertEdge2);
+
+  TopoDS_Edge ES1 = TopoDS::Edge(E1);
+  TopoDS_Edge ES2 = TopoDS::Edge(E2);
+  TopoDS_Shape VS1 = V1;
+  TopoDS_Shape VS2 = V2;
+
+  ShapeAnalysis_Edge sae;
+  while(1) {
+    const TopTools_ListOfShape& aList1 = aMapVertEdge1.FindFromKey(VS1);
+    //TopoDS_Shape E1next;
+    TopTools_ListIteratorOfListOfShape anIter1(aList1);
+    if(anIter1.Value().IsSame(ES1)) {
+      anIter1.Next();
+    }
+    //E1next = anIter1.Value();
+    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)) {
+      FF.Add(ES1,ES2);
+    }
+    if(VS1.IsSame(sae.FirstVertex(ES1)))
+      VS1 = sae.LastVertex(ES1);
+    else
+      VS1 = sae.FirstVertex(ES1);
+    if(VS2.IsSame(sae.FirstVertex(ES2)))
+      VS2 = sae.LastVertex(ES2);
+    else
+      VS2 = sae.FirstVertex(ES2);
+    if(VS1.IsSame(V1))
+      break;
+    if(!FF.Contains(VS1)) {
+      FF.Add(VS1,VS2);
+    }
+  }
+
+  return true;
+}
+
+
+//=======================================================================
+//function : FillCorrespondingEdges
+//purpose  : auxilary for CreatePipeForShellSections()
+//=======================================================================
+static bool FillCorrespondingEdges(const TopoDS_Shape& FS1,
+                                  const TopoDS_Shape& FS2,
+                                  const TopoDS_Vertex& aLoc1,
+                                  const TopoDS_Vertex& aLoc2,
+                                  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());
+  //exp = TopExp_Explorer(FS2,TopAbs_WIRE);
+  TopExp_Explorer expw2(FS2,TopAbs_WIRE);
+  TopoDS_Wire aWire2 = TopoDS::Wire(expw2.Current());
+  BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
+  aBuilder.Add(aWire1, aLoc1);
+  aBuilder.Add(aWire2, aLoc2);
+  if(!aBuilder.IsReady()) {
+    return false;
+  }
+  aBuilder.Build();
+  TopoDS_Shape aShape = aBuilder.Shape();
+  /*
+  TopoDS_Compound C;
+  BRep_Builder B;
+  B.MakeCompound(C);
+  B.Add(C,aShape);
+  B.Add(C,FS1);
+  B.Add(C,FS2);
+  BRepTools::Write(C,"/dn02/users_Linux/skl/work/Bugs/14857/comp.brep");
+  */
+  ShapeAnalysis_Edge sae;
+  double tol = Max( BRep_Tool::Tolerance(TopoDS::Face(FS1)),
+                   BRep_Tool::Tolerance(TopoDS::Face(FS2)) );
+  TopTools_MapOfShape Vs1,Vs2;
+  TopExp_Explorer exp;
+  exp.Init( FS1, TopAbs_EDGE );
+  TopoDS_Edge E1 = TopoDS::Edge(exp.Current());
+  TopoDS_Vertex V11 = sae.FirstVertex(E1);
+  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() ) {
+    TopoDS_Vertex V = TopoDS::Vertex(exp.Current());
+    gp_Pnt P = BRep_Tool::Pnt(V);
+    if(P.Distance(P11)<tol) {
+      VN11 = V;
+    }
+    if(P.Distance(P21)<tol) {
+      VN21 = V;
+    }
+  }
+  // find edge contains VN11 and VN21 and corresponding vertexes
+  TopoDS_Vertex VN12,VN22;
+  for( exp.Init( aShape, TopAbs_FACE ); exp.More(); exp.Next() ) {
+    TopoDS_Shape F = exp.Current();
+    TopExp_Explorer expe;
+    bool IsFind = false;
+    for( expe.Init( F, TopAbs_EDGE ); expe.More(); expe.Next() ) {
+      TopoDS_Edge E = TopoDS::Edge(expe.Current());
+      TopoDS_Vertex VF = sae.FirstVertex(E);
+      TopoDS_Vertex VL = sae.LastVertex(E);
+      if( (VF.IsSame(VN11) && VL.IsSame(VN21)) || (VF.IsSame(VN21) && VL.IsSame(VN11)) ) {
+       IsFind = true;
+       break;
+      }
+    }
+    if(IsFind) {
+      for( expe.Init( F, TopAbs_EDGE ); expe.More(); expe.Next() ) {
+       TopoDS_Edge E = TopoDS::Edge(expe.Current());
+       TopoDS_Vertex VF = sae.FirstVertex(E);
+       TopoDS_Vertex VL = sae.LastVertex(E);
+       if( VF.IsSame(VN11) && !VL.IsSame(VN21) )
+         VN12 = VL;
+       if( VL.IsSame(VN11) && !VF.IsSame(VN21) )
+         VN12 = VF;
+       if( VF.IsSame(VN21) && !VL.IsSame(VN11) )
+         VN22 = VL;
+       if( VL.IsSame(VN21) && !VF.IsSame(VN11) )
+         VN22 = VF;
+      }
+      break;
+    }
+  }
+  // find vertexes from FS2 corresponded to VN12 and VN22
+  // and find edge from FS2 contains V12 and V22,
+  // this edge will be corresponded to edge E1
+  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() ) {
+    TopoDS_Edge E = TopoDS::Edge(expe.Current());
+    TopoDS_Vertex VF = sae.FirstVertex(E);
+    TopoDS_Vertex VL = sae.LastVertex(E);
+    gp_Pnt PF = BRep_Tool::Pnt(VF);
+    gp_Pnt PL = BRep_Tool::Pnt(VL);
+    if( PF.Distance(PN12)<tol && PL.Distance(PN22)<tol ) {
+      V12 = VF;
+      V22 = VL;
+      E2 = E;
+      break;
+    }
+    if( PF.Distance(PN22)<tol && PL.Distance(PN12)<tol ) {
+      V12 = VL;
+      V22 = VF;
+      E2 = E;
+      break;
+    }
+  }
+  FF.Add(V11,V12);
+  FF.Add(V21,V22);
+  FF.Add(E1,E2);
+
+  // find other pairs for vertexes and edges
+  // creating map of vertex edges for both faces
+  return FillForOtherEdges(FS1,E1,V21,FF);
+
+  //return true;
+}
+
+
+//=======================================================================
+//function : FindNextPairOfFaces
+//purpose  : auxilary for CreatePipeForShellSections()
+//=======================================================================
+static void FindNextPairOfFaces(const TopoDS_Shape& aCurFace,
+                               TopTools_IndexedDataMapOfShapeListOfShape& aMapEdgeFaces1,
+                               TopTools_IndexedDataMapOfShapeListOfShape& aMapEdgeFaces2,
+                               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();
+    if(!FF.Contains(E1)) {
+      if(aCI) delete aCI;
+      Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not find edge in map");
+    }
+    const TopoDS_Shape& E2 = FF.FindFromKey(E1);
+    TopExp_Explorer anExpV;
+    anExpV.Init( E1, TopAbs_VERTEX );
+    TopoDS_Shape V1 = anExpV.Current();
+    if(!FF.Contains(V1)) {
+      if(aCI) delete aCI;
+      Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not find vertex in map");
+    }
+
+    const TopTools_ListOfShape& aList1 = aMapEdgeFaces1.FindFromKey(E1);
+    if(aList1.Extent()<2)
+      continue;
+    TopTools_ListIteratorOfListOfShape anIter(aList1);
+    if(anIter.Value().IsEqual(aCurFace)) {
+      anIter.Next();
+    }
+    TopoDS_Shape F1other = anIter.Value();
+    if(FF.Contains(F1other))
+      continue;
+
+    const TopoDS_Shape& F2 = FF.FindFromKey(aCurFace);
+    const TopTools_ListOfShape& aList2 = aMapEdgeFaces2.FindFromKey(E2);
+    if(aList2.Extent()<2) {
+      if(aCI) delete aCI;
+      Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not find corresponding face");
+    }
+    TopTools_ListIteratorOfListOfShape anIter2(aList2);
+    if(anIter2.Value().IsEqual(F2)) {
+      anIter2.Next();
+    }
+    TopoDS_Shape F2other = anIter2.Value();
+    FF.Add(F1other,F2other);
+
+    // add pairs of edges to FF
+    bool stat =  FillForOtherEdges(F1other,E1,V1,FF);
+    if( !stat ) {
+      if(aCI) delete aCI;
+      Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not mapping other egdes");
+    }
+
+    FindNextPairOfFaces(F1other, aMapEdgeFaces1, aMapEdgeFaces2, FF, aCI);
+    
+  }
+}
+
+
+//=======================================================================
+//function : CreatePipeForShellSections
+//purpose  : auxilary for Execute()
+//=======================================================================
+static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath,
+                                              GEOMImpl_IPipe* aCI)
+{
+  //cout<<"CreatePipeForShellSections"<<endl;
+  //TopoDS_Shape res;
+  int i,j;
+  BRep_Builder B;
+
+  GEOMImpl_IPipeShellSect* aCIDS = (GEOMImpl_IPipeShellSect*)aCI;
+  Handle(TColStd_HSequenceOfTransient) aBasesObjs = aCIDS->GetBases();
+  Handle(TColStd_HSequenceOfTransient) aSubBasesObjs = aCIDS->GetSubBases();
+  Handle(TColStd_HSequenceOfTransient) aLocObjs = aCIDS->GetLocations();
+  Standard_Boolean aWithContact = (aCIDS->GetWithContactMode());
+  Standard_Boolean aWithCorrect = (aCIDS->GetWithCorrectionMode());
+
+  Standard_Integer nbBases = aBasesObjs->Length(), 
+    nbSubBases = (aSubBasesObjs.IsNull() ? 0 :aSubBasesObjs->Length()),
+    nbLocs = (aLocObjs.IsNull() ? 0 :aLocObjs->Length());
+    
+  if( nbLocs != nbBases) {
+    if(aCI) delete aCI;
+    Standard_ConstructionError::Raise("Number of sections is not equal to number of locations ");
+  }
+  if( nbSubBases && nbSubBases != nbBases) {
+    if(aCI) delete aCI;
+    Standard_ConstructionError::Raise("Number of sections is not equal to number of subsections ");
+  }
+
+  //BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
+
+  TopTools_SequenceOfShape VLocs;
+  for(i=1; i<=nbBases; i++) {
+    Handle(Standard_Transient) anItemLoc = aLocObjs->Value(i);
+    if(anItemLoc.IsNull())
+      continue;
+    Handle(GEOM_Function) aRefLoc = Handle(GEOM_Function)::DownCast(anItemLoc);
+    TopoDS_Shape aShapeLoc = aRefLoc->GetValue();
+    if(aShapeLoc.IsNull() || aShapeLoc.ShapeType() != TopAbs_VERTEX)
+      continue;
+    VLocs.Append(aShapeLoc);
+  }
+  nbLocs = VLocs.Length();
+  if( nbLocs != nbBases) {
+    if(aCI) delete aCI;
+    Standard_ConstructionError::Raise("One of location shapes is not a vertex");
+  }
+  // split wire path by location points
+  TColgp_SequenceOfPnt PLocs;
+  for(i=1; i<=nbLocs; i++) {
+    TopoDS_Vertex V = TopoDS::Vertex(VLocs.Value(i));
+    PLocs.Append(BRep_Tool::Pnt(V));
+  }
+  TopTools_SequenceOfShape Edges;
+  TopTools_SequenceOfShape Wires;
+  TopExp_Explorer anExp;
+  for ( anExp.Init( aWirePath, TopAbs_EDGE ); anExp.More(); anExp.Next() ) {
+    Edges.Append(anExp.Current());
+  }
+  ShapeAnalysis_Edge sae;
+  TopoDS_Edge edge = TopoDS::Edge(Edges.First());
+  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
+      ("First location shapes is not coincided with first vertex of aWirePath");
+  }
+  edge = TopoDS::Edge(Edges.Last());
+  tol = BRep_Tool::Tolerance(edge);
+  TopoDS_Vertex VL = sae.LastVertex(edge);
+  gp_Pnt PL = BRep_Tool::Pnt(VL);
+  if( PL.Distance(PLocs.Last()) > tol ) {
+    if(aCI) delete aCI;
+    Standard_ConstructionError::Raise
+      ("Last location shapes is not coincided with last vertex of aWirePath");
+  }
+  int jcurr = 2;
+  TopTools_SequenceOfShape tmpEdges;
+  for(i=1; i<=Edges.Length() && jcurr<nbLocs; i++) {
+    TopoDS_Edge E = TopoDS::Edge(Edges.Value(i));
+    tol = BRep_Tool::Tolerance(edge);
+    TopoDS_Vertex V1 = sae.FirstVertex(E);
+    TopoDS_Vertex V2 = sae.LastVertex(E);
+    gp_Pnt P1 = BRep_Tool::Pnt(V1);
+    gp_Pnt P2 = BRep_Tool::Pnt(V2);
+    if( P2.Distance(PLocs.Value(jcurr)) < tol ) {
+      // make wire from current edge and add created
+      // wire to Wires
+      TopoDS_Wire W;
+      B.MakeWire(W);
+      for(j=1; j<=tmpEdges.Length(); j++)
+       B.Add(W,tmpEdges.Value(j));
+      B.Add(W,E);
+      Wires.Append(W);
+      jcurr++;
+      tmpEdges.Clear();
+    }
+    else {
+      // find distance between E and aLocs(icurr)
+      double fp,lp;
+      Handle(Geom_Curve) C = BRep_Tool::Curve(E,fp,lp);
+      GeomAPI_ProjectPointOnCurve PPC (PLocs.Value(jcurr),C);
+      if( PPC.NbPoints()>0 &&
+         PLocs.Value(jcurr).Distance(PPC.Point(1)) < tol ) {
+       double param = PPC.Parameter(1);
+       gp_Pnt PC1;
+       C->D0(param,PC1);
+       // split current edge
+       Handle(Geom_TrimmedCurve) tc1 = new Geom_TrimmedCurve(C,fp,param);
+       Handle(Geom_TrimmedCurve) tc2 = new Geom_TrimmedCurve(C,param,lp);
+       TopoDS_Edge E1,E2;
+       if(PC1.Distance(P1)<tol) {
+         B.MakeEdge(E1,tc1,tol);
+         B.Add(E1,V1);
+         TopoDS_Shape tmpV = VLocs.Value(jcurr).Oriented(TopAbs_REVERSED);
+         B.Add(E1,TopoDS::Vertex(tmpV));
+         tmpEdges.Append(E1);
+         B.MakeEdge(E2,tc2,tol);
+         tmpV = VLocs.Value(jcurr).Oriented(TopAbs_FORWARD);
+         B.Add(E2,TopoDS::Vertex(tmpV));
+         B.Add(E2,V2);
+       }
+       else {
+         B.MakeEdge(E1,tc2,tol);
+         TopoDS_Shape tmpV = VLocs.Value(jcurr).Oriented(TopAbs_FORWARD);
+         B.Add(E1,TopoDS::Vertex(tmpV));
+         B.Add(E1,V1);
+         E1.Reverse();
+         tmpEdges.Append(E1);
+         B.MakeEdge(E2,tc1,tol);
+         B.Add(E2,V2);
+         tmpV = VLocs.Value(jcurr).Oriented(TopAbs_REVERSED);
+         B.Add(E2,TopoDS::Vertex(tmpV));
+         E2.Reverse();
+       }
+       // create wire from tmpEdges
+       TopoDS_Wire W;
+       B.MakeWire(W);
+       for(j=1; j<=tmpEdges.Length(); j++)
+         B.Add(W,tmpEdges.Value(j));
+       Wires.Append(W);
+       jcurr++;
+       tmpEdges.Clear();
+       Edges.Remove(i);
+       Edges.InsertAfter(i-1,E1);
+       Edges.InsertAfter(i,E2);
+      }
+      else {
+       tmpEdges.Append(edge);
+      }
+    }
+  }
+  // create wire from other edges
+  TopoDS_Wire W;
+  B.MakeWire(W);
+  for(; i<=Edges.Length(); i++)
+    B.Add(W,Edges.Value(i));
+  Wires.Append(W);
+  //cout<<"Wires.Length()="<<Wires.Length()<<endl;
+
+  if( Wires.Length() != nbLocs-1 ) {
+    if(aCI) delete aCI;
+    Standard_ConstructionError::Raise
+      ("One of location shapes is not lied on the path");
+  }
+
+  //TopTools_SequenceOfShape aSeqBases;
+  //TopTools_SequenceOfShape aSeqSubBases;
+  //TopTools_SequenceOfShape aSeqFaces;
+  TopoDS_Compound aComp;
+  B.MakeCompound(aComp);
+  for(i=1 ; i<nbBases; i++) {
+    TopoDS_Wire WPath = TopoDS::Wire(Wires.Value(i));
+    // 1 section
+    Handle(Standard_Transient) anItem1 = aBasesObjs->Value(i);
+    if(anItem1.IsNull())
+      continue;
+    Handle(GEOM_Function) aRefBase1 = Handle(GEOM_Function)::DownCast(anItem1);
+    if(aRefBase1.IsNull())
+      continue;
+    TopoDS_Shape aShBase1 = aRefBase1->GetValue();
+    if(aShBase1.IsNull())
+      continue;
+    TopAbs_ShapeEnum aType1 = aShBase1.ShapeType();
+    // 2 section
+    Handle(Standard_Transient) anItem2 = aBasesObjs->Value(i+1);
+    if(anItem2.IsNull())
+      continue;
+    Handle(GEOM_Function) aRefBase2 = Handle(GEOM_Function)::DownCast(anItem2);
+    if(aRefBase2.IsNull())
+      continue;
+    TopoDS_Shape aShBase2 = aRefBase2->GetValue();
+    if(aShBase2.IsNull())
+      continue;
+    TopAbs_ShapeEnum aType2 = aShBase2.ShapeType();
+    
+    //BRepTools::Write(aShBase1,"/dn02/users_Linux/skl/work/Bugs/14857/base1.brep");
+
+    bool OkSec = ( aType1==TopAbs_SHELL || aType1==TopAbs_FACE ) &&
+                 ( aType2==TopAbs_SHELL || aType2==TopAbs_FACE );
+    if( !OkSec ) {
+      if(aCI) delete aCI;
+      Standard_ConstructionError::Raise("One of section shapes has invalid type");
+    }
+
+    bool CreateFewSolids = false;
+    // compare sections
+    TopExp_Explorer anExp;
+    Standard_Integer nbf1 = 0;
+    for ( anExp.Init( aShBase1, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
+      nbf1++;
+    }
+    Standard_Integer nbf2 = 0;
+    for ( anExp.Init( aShBase2, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
+      nbf2++;
+    }
+    if(nbf1==nbf2) {
+      CreateFewSolids = true;
+    }
+
+    if(!CreateFewSolids) {
+      // we can create only one solid
+      TopoDS_Shape aWire1, aWire2;
+      // prepare aWire1
+      if(aType1==TopAbs_SHELL) {
+       // create wire as boundary contour if shell is no closed
+       // get free boundary shapes
+       ShapeAnalysis_FreeBounds anAnalizer( aShBase1 );
+       TopoDS_Compound aClosed = anAnalizer.GetClosedWires();
+       //TopExp_Explorer anExp;
+       Standard_Integer NbWires = 0;
+       for ( anExp.Init( aClosed, TopAbs_WIRE ); anExp.More(); anExp.Next() ) {
+         NbWires++;
+         aWire1 = anExp.Current();
+       }
+       if(NbWires!=1) {
+         // bad case
+         if(aCI) delete aCI;
+         Standard_ConstructionError::Raise("Bad shell is used as section ");
+       }
+      }
+      else { // aType1==TopAbs_FACE
+       TopExp_Explorer aExpW(aShBase1,TopAbs_WIRE);
+       aWire1 = aExpW.Current();
+      }
+      // prepare aWire2
+      if(aType2==TopAbs_SHELL) {
+       // create wire as boundary contour if shell is no closed
+       // get free boundary shapes
+       ShapeAnalysis_FreeBounds anAnalizer( aShBase2 );
+       TopoDS_Compound aClosed = anAnalizer.GetClosedWires();
+       //TopExp_Explorer anExp;
+       Standard_Integer NbWires = 0;
+       for ( anExp.Init( aClosed, TopAbs_WIRE ); anExp.More(); anExp.Next() ) {
+         NbWires++;
+         aWire2 = anExp.Current();
+       }
+       if(NbWires!=1) {
+         // bad case
+         if(aCI) delete aCI;
+         Standard_ConstructionError::Raise("Bad shell is used as section ");
+       }
+      }
+      else { // aType2==TopAbs_FACE
+       TopExp_Explorer aExpW(aShBase2,TopAbs_WIRE);
+       aWire2 = aExpW.Current();
+      }
+      // make pipe using aWire1 and aWire2
+      if( !aWire1.IsNull() && !aWire2.IsNull() ) {
+       //BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
+       BRepOffsetAPI_MakePipeShell aBuilder(WPath);
+       aBuilder.Add(aWire1, TopoDS::Vertex(VLocs(i)),
+                    aWithContact, aWithCorrect);
+       aBuilder.Add(aWire2, TopoDS::Vertex(VLocs(i+1)),
+                    aWithContact, aWithCorrect);
+       if(!aBuilder.IsReady()) {
+         if(aCI) delete aCI;
+         Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
+       }
+       aBuilder.Build();
+       TopoDS_Shape aShape = aBuilder.Shape();
+       TopoDS_Shell aShell;
+       B.MakeShell(aShell);
+       for ( anExp.Init( aShape, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
+         B.Add(aShell,anExp.Current());
+       }
+       for ( anExp.Init( aShBase1, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
+         B.Add(aShell,anExp.Current());
+       }
+       for ( anExp.Init( aShBase2, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
+         B.Add(aShell,anExp.Current());
+       }
+       // make sewing for this shell
+       Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing;
+       aSewing->SetTolerance(Precision::Confusion());
+       aSewing->SetFaceMode(Standard_True);
+       aSewing->SetFloatingEdgesMode(Standard_False);
+       aSewing->SetNonManifoldMode(Standard_False);
+       for ( anExp.Init( aShell, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
+         aSewing->Add(anExp.Current());
+       }
+       aSewing->Perform();
+       const TopoDS_Shape aSewShape = aSewing->SewedShape();
+       if( aSewShape.ShapeType() == TopAbs_SHELL ) {
+         aShell = TopoDS::Shell(aSewShape);
+         if(BRep_Tool::IsClosed(aShell)) {
+           TopoDS_Solid aSolid;
+           B.MakeSolid(aSolid);
+           B.Add(aSolid,aShell);
+           B.Add(aComp,aSolid);
+         }
+         else {
+           B.Add(aComp,aShell);
+         }
+       }
+       else {
+         B.Add(aComp,aShell);
+       }
+      }
+    }
+    else {
+      // main block - creation few solids (for each pair of faces)
+      TopTools_MapOfShape aFaces1,aFaces2;
+      for ( anExp.Init( aShBase1, TopAbs_FACE ); anExp.More(); anExp.Next() )
+       aFaces1.Add(anExp.Current());
+      for ( anExp.Init( aShBase2, TopAbs_FACE ); anExp.More(); anExp.Next() )
+       aFaces2.Add(anExp.Current());
+      // creating map of edge faces
+      TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces1;
+      TopExp::MapShapesAndAncestors(aShBase1, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces1);
+      TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces2;
+      TopExp::MapShapesAndAncestors(aShBase2, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces2);
+  
+      // constuct map face->face
+      TopTools_IndexedDataMapOfShapeShape FF;
+      TopoDS_Shape FS1,FS2;
+      if(nbSubBases==0) {
+       // find edge the most distant from location point
+       // (this edge is not shared by two faces)
+       double maxdist = 0.;
+       TopoDS_Shape E1;
+       TopoDS_Vertex V11,V21;
+       for(j=1; j<=aMapEdgeFaces1.Extent(); j++) {
+         TopoDS_Shape tmp = aMapEdgeFaces1.FindKey(j);
+         const TopTools_ListOfShape& aList = aMapEdgeFaces1.FindFromKey(tmp);
+         if(aList.Extent()>1)
+           continue;
+         TopExp_Explorer expv;
+         expv.Init( tmp, TopAbs_VERTEX );
+         TopoDS_Vertex V1 = TopoDS::Vertex(expv.Current());
+         expv.Next();
+         TopoDS_Vertex V2 = TopoDS::Vertex(expv.Current());
+         gp_Pnt P1 = BRep_Tool::Pnt(V1);
+         gp_Pnt P2 = BRep_Tool::Pnt(V2);
+         double dist = PLocs.Value(i).Distance(P1) + PLocs.Value(i).Distance(P2);
+         if(dist>maxdist) {
+           E1 = tmp;
+           V11 = V1;
+           V21 = V2;
+           TopTools_ListIteratorOfListOfShape anIter(aList);
+           FS1 = anIter.Value();
+           maxdist = dist;
+         }
+       }
+       // main direction for comparing
+       gp_Vec VM(PLocs.Value(i),PLocs.Value(i+1));
+       // find corresponding edge from next section
+       double minang = PI;
+       gp_Pnt P11 = BRep_Tool::Pnt(V11);
+       gp_Pnt P21 = BRep_Tool::Pnt(V21);
+       TopoDS_Shape E2;
+       TopoDS_Vertex V12,V22;
+       for(j=1; j<=aMapEdgeFaces2.Extent(); j++) {
+         TopoDS_Shape tmp = aMapEdgeFaces2.FindKey(j);
+         const TopTools_ListOfShape& aList = aMapEdgeFaces2.FindFromKey(tmp);
+         if(aList.Extent()>1)
+           continue;
+         TopExp_Explorer expv;
+         expv.Init( tmp, TopAbs_VERTEX );
+         TopoDS_Vertex V1tmp = TopoDS::Vertex(expv.Current());
+         expv.Next();
+         TopoDS_Vertex V2tmp = TopoDS::Vertex(expv.Current());
+         gp_Pnt P1tmp = BRep_Tool::Pnt(V1tmp);
+         gp_Pnt P2tmp = BRep_Tool::Pnt(V2tmp);
+         double d1 = P1tmp.Distance(P11) + P2tmp.Distance(P21);
+         double d2 = P1tmp.Distance(P21) + P2tmp.Distance(P11);
+         TopoDS_Vertex V1,V2;
+         gp_Pnt P1,P2;
+         if(d1>d2) {
+           V1 = V2tmp; P1 = P2tmp;
+           V2 = V1tmp; P2 = P1tmp;
+         }
+         else {
+           V1 = V1tmp; P1 = P1tmp;
+           V2 = V2tmp; P2 = P2tmp;
+         }
+         gp_Vec Vec1(P11,P1);
+         gp_Vec Vec2(P21,P2);
+         double ang = fabs(Vec1.Angle(VM)) + fabs(Vec2.Angle(VM));
+         if(ang<minang) {
+           E2 = tmp;
+           V12 = V1;
+           V22 = V2;
+           TopTools_ListIteratorOfListOfShape anIter(aList);
+           FS2 = anIter.Value();
+           minang = ang;
+         }
+       }
+       // put all pairs to map FF
+       FF.Add(FS1,FS2);
+       FF.Add(E1,E2);
+       FF.Add(V11,V12);
+       FF.Add(V21,V22);
+
+       // add pairs of edges to FF
+       bool stat =  FillForOtherEdges(FS1,E1,V11,FF);
+       if( !stat ) {
+         if(aCI) delete aCI;
+         Standard_ConstructionError::Raise("FindForOtherEdges: Can not mapping other egdes");
+       }
+
+      }
+      else {
+       { // 1 section
+         Handle(Standard_Transient) anItem = aSubBasesObjs->Value(i);
+         if(anItem.IsNull()) {
+           if(aCI) delete aCI;
+           Standard_ConstructionError::Raise("Invalid subbase shape");
+         }
+         Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem);
+         if(aRefBase.IsNull()) {
+           if(aCI) delete aCI;
+           Standard_ConstructionError::Raise("Invalid subbase shape");
+         }
+         TopoDS_Shape aSh = aRefBase->GetValue();
+         if(aSh.IsNull()) {
+           if(aCI) delete aCI;
+           Standard_ConstructionError::Raise("Invalid subbase shape");
+         }
+         if(aSh.ShapeType()!=TopAbs_FACE) {
+           if(aCI) delete aCI;
+           Standard_ConstructionError::Raise("Invalid subbase shape");
+         }
+         FS1 = aSh;
+       }       
+       { // 2 section
+         Handle(Standard_Transient) anItem = aSubBasesObjs->Value(i+1);
+         if(anItem.IsNull()) {
+           if(aCI) delete aCI;
+           Standard_ConstructionError::Raise("Invalid subbase shape");
+         }
+         Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem);
+         if(aRefBase.IsNull()) {
+           if(aCI) delete aCI;
+           Standard_ConstructionError::Raise("Invalid subbase shape");
+         }
+         TopoDS_Shape aSh = aRefBase->GetValue();
+         if(aSh.IsNull()) {
+           if(aCI) delete aCI;
+           Standard_ConstructionError::Raise("Invalid subbase shape");
+         }
+         if(aSh.ShapeType()!=TopAbs_FACE) {
+           if(aCI) delete aCI;
+           Standard_ConstructionError::Raise("Invalid subbase shape");
+         }
+         FS2 = aSh;
+       }
+
+       if( !aFaces1.Contains(FS1) || !aFaces2.Contains(FS2) ) {
+         if(aCI) delete aCI;
+         Standard_ConstructionError::Raise("Invalid subbase shape");
+       }
+      
+       FF.Add(FS1,FS2);
+
+       // add pairs of edges to FF
+       bool stat =  FillCorrespondingEdges(FS1, FS2, TopoDS::Vertex(VLocs(i)),
+                                           TopoDS::Vertex(VLocs(i+1)), WPath, FF);
+       if( !stat ) {
+         if(aCI) delete aCI;
+         Standard_ConstructionError::Raise("Can not create correct pipe");
+       }
+      }
+
+      FindNextPairOfFaces(FS1, aMapEdgeFaces1, aMapEdgeFaces2, FF, aCI);
+
+
+      // make pipe for each pair of faces
+      //BRepTools::Write(WPath,"/dn02/users_Linux/skl/work/Bugs/14857/wpath.brep");
+      for(j=1; j<=FF.Extent(); j++) {
+       TopoDS_Shape F1 = FF.FindKey(j);
+       if( F1.ShapeType() != TopAbs_FACE )
+         continue;
+       TopoDS_Shape F2 = FF.FindFromIndex(j);
+       TopExp_Explorer aExpW1(F1,TopAbs_WIRE);
+       TopoDS_Wire aWire1 = TopoDS::Wire(aExpW1.Current());
+       TopExp_Explorer aExpW2(F2,TopAbs_WIRE);
+       TopoDS_Wire aWire2 = TopoDS::Wire(aExpW2.Current());
+       // make pipe using aWire1 and aWire2
+       if( !aWire1.IsNull() && !aWire2.IsNull() ) {
+         BRepOffsetAPI_MakePipeShell aBuilder(WPath);
+         aBuilder.Add(aWire1, TopoDS::Vertex(VLocs(i)),
+                      aWithContact, aWithCorrect);
+         aBuilder.Add(aWire2, TopoDS::Vertex(VLocs(i+1)),
+                      aWithContact, aWithCorrect);
+         if(!aBuilder.IsReady()) {
+           if(aCI) delete aCI;
+           Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
+         }
+         aBuilder.Build();
+         TopoDS_Shape aShape = aBuilder.Shape();
+         TopoDS_Shell aShell;
+         B.MakeShell(aShell);
+         //int nbf=0;
+         for ( anExp.Init( aShape, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
+           //nbf++;
+           //cout<<"nbf="<<nbf<<endl;
+           B.Add(aShell,anExp.Current());
+         }
+         B.Add(aShell,F1);
+         B.Add(aShell,F2);
+         // make sewing for this shell
+         Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing;
+         aSewing->SetTolerance(Precision::Confusion());
+         aSewing->SetFaceMode(Standard_True);
+         aSewing->SetFloatingEdgesMode(Standard_False);
+         aSewing->SetNonManifoldMode(Standard_False);
+         for ( anExp.Init( aShell, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
+           aSewing->Add(anExp.Current());
+         }
+         aSewing->Perform();
+         const TopoDS_Shape aSewShape = aSewing->SewedShape();
+         if( aSewShape.ShapeType() == TopAbs_SHELL ) {
+           aShell = TopoDS::Shell(aSewShape);
+           if(BRep_Tool::IsClosed(aShell)) {
+             TopoDS_Solid aSolid;
+             B.MakeSolid(aSolid);
+             B.Add(aSolid,aShell);
+             B.Add(aComp,aSolid);
+           }
+           else {
+             B.Add(aComp,aShell);
+           }
+         }
+         else {
+           B.Add(aComp,aShell);
+         }
+       }
+      }
+
+    }
+  }
+
+  return aComp;
+}
+
+
 //=======================================================================
 //function : Execute
 //purpose  :
@@ -81,6 +927,8 @@ Standard_Integer GEOMImpl_PipeDriver::Execute(TFunction_Logbook& log) const
     aCI = new GEOMImpl_IPipe(aFunction);
   else if(aType == PIPE_DIFFERENT_SECTIONS)
     aCI = new GEOMImpl_IPipeDiffSect(aFunction);
+  else if(aType == PIPE_SHELL_SECTIONS)
+    aCI = new GEOMImpl_IPipeShellSect(aFunction);
   else
     return 0;
 
@@ -88,8 +936,7 @@ Standard_Integer GEOMImpl_PipeDriver::Execute(TFunction_Logbook& log) const
   TopoDS_Shape aShapePath = aRefPath->GetValue();
 
 
-  if (aShapePath.IsNull())
-  {
+  if (aShapePath.IsNull()) {
     cout<<"Driver : path is null"<<endl;
     if(aCI) delete aCI;
     Standard_NullObject::Raise("MakePipe aborted : null path argument");
@@ -102,9 +949,8 @@ Standard_Integer GEOMImpl_PipeDriver::Execute(TFunction_Logbook& log) const
   } 
   else {
     if (aShapePath.ShapeType() == TopAbs_EDGE) {
-         
-        TopoDS_Edge anEdge = TopoDS::Edge(aShapePath);
-        aWirePath = BRepBuilderAPI_MakeWire(anEdge);
+      TopoDS_Edge anEdge = TopoDS::Edge(aShapePath);
+      aWirePath = BRepBuilderAPI_MakeWire(anEdge);
     } 
     else {
       if(aCI) delete aCI;
@@ -114,8 +960,7 @@ Standard_Integer GEOMImpl_PipeDriver::Execute(TFunction_Logbook& log) const
   
   TopoDS_Shape aShape;
 
-  if (aType == PIPE_BASE_PATH) 
-  {
+  if (aType == PIPE_BASE_PATH) {
      
     Handle(GEOM_Function) aRefBase = aCI->GetBase();
    
@@ -167,8 +1012,31 @@ Standard_Integer GEOMImpl_PipeDriver::Execute(TFunction_Logbook& log) const
 
       //if for section was specified face with a few wires then a few
       //    pipes were build and make solid 
-      if(aTypeBase == TopAbs_FACE)
+      Standard_Boolean NeedCreateSolid = Standard_False;
+      if(aTypeBase == TopAbs_SHELL) {
+       // create wire as boundary contour if shell is no closed
+       // get free boundary shapes
+       ShapeAnalysis_FreeBounds anAnalizer( aShapeBase );
+       TopoDS_Compound aClosed = anAnalizer.GetClosedWires();
+       TopExp_Explorer anExp;
+       TopoDS_Shape aWire;
+       Standard_Integer NbWires = 0;
+       for ( anExp.Init( aClosed, TopAbs_WIRE ); anExp.More(); anExp.Next() ) {
+         NbWires++;
+         aWire = anExp.Current();
+       }
+       if(NbWires!=1) {
+         // bad case
+         if(aCI) delete aCI;
+         Standard_ConstructionError::Raise("Bad shell is used as section ");
+       }
+       NeedCreateSolid = Standard_True;
+        aSeqFaces.Append(aShapeBase);
+       aSeqBases.Append(aWire);
+      }
+      else if(aTypeBase == TopAbs_FACE)
       {
+       NeedCreateSolid = Standard_True;
        //for case one path should be used other type function
         aSeqFaces.Append(aShapeBase);
         TopExp_Explorer aExpW(aShapeBase,TopAbs_WIRE);
@@ -178,8 +1046,9 @@ Standard_Integer GEOMImpl_PipeDriver::Execute(TFunction_Logbook& log) const
          aSeqBases.Append(aWireProf);
        }
       }
-      else if(aTypeBase == TopAbs_WIRE || aTypeBase == TopAbs_VERTEX) 
+      else if(aTypeBase == TopAbs_WIRE || aTypeBase == TopAbs_VERTEX) {
         aSeqBases.Append(aShapeBase);
+      }
       else if(aTypeBase == TopAbs_EDGE)
       {
         TopoDS_Edge anEdge = TopoDS::Edge(aShapeBase);
@@ -252,6 +1121,12 @@ Standard_Integer GEOMImpl_PipeDriver::Execute(TFunction_Logbook& log) const
       aShape = aComp;
     }
   }
+
+  //building pipe with shell sections
+  else if (aType == PIPE_SHELL_SECTIONS) {
+    aShape = CreatePipeForShellSections(aWirePath,aCI);
+  }
+
   if (aShape.IsNull()) return 0;
 
   BRepCheck_Analyzer ana (aShape, Standard_False);
@@ -309,3 +1184,4 @@ const Handle(GEOMImpl_PipeDriver) Handle(GEOMImpl_PipeDriver)::DownCast(const Ha
 
   return _anOtherObject ;
 }
+
index 888b2cd5d43b1e79162047bb5c3c9fe8d48b75cb..b57defc89988bff0d3040bf0168c7a1fdcccaa63 100644 (file)
@@ -48,6 +48,7 @@
 #include <Handle_TFunction_Driver.hxx>
 #endif
 
+
 class Standard_Transient;
 class Handle_Standard_Type;
 class Handle(TFunction_Driver);
@@ -136,22 +137,25 @@ public:
         if (anAddress) Standard::Free((Standard_Address&)anAddress); 
       }
 
- // Methods PUBLIC
- // 
-Standard_EXPORT GEOMImpl_PipeDriver();
-Standard_EXPORT virtual  Standard_Integer Execute(TFunction_Logbook& log) const; 
-Standard_EXPORT virtual void Validate(TFunction_Logbook&) const {}
-Standard_EXPORT Standard_Boolean MustExecute(const TFunction_Logbook&) const { return Standard_True; }
-Standard_EXPORT static const Standard_GUID& GetID();
-Standard_EXPORT ~GEOMImpl_PipeDriver() {};
-
-
- // Type management
- //
-Standard_EXPORT friend Handle_Standard_Type& GEOMImpl_PipeDriver_Type_();
-Standard_EXPORT const Handle(Standard_Type)& DynamicType() const  { return STANDARD_TYPE(GEOMImpl_PipeDriver) ; }
-Standard_EXPORT Standard_Boolean IsKind(const Handle(Standard_Type)& AType) const { return (STANDARD_TYPE(GEOMImpl_PipeDriver) == AType || TFunction_Driver::IsKind(AType)); } 
-
+  // Methods PUBLIC
+  // 
+  Standard_EXPORT GEOMImpl_PipeDriver();
+  Standard_EXPORT virtual  Standard_Integer Execute(TFunction_Logbook& log) const; 
+  Standard_EXPORT virtual void Validate(TFunction_Logbook&) const {}
+  Standard_EXPORT Standard_Boolean MustExecute(const TFunction_Logbook&) const
+  { return Standard_True; }
+  Standard_EXPORT static const Standard_GUID& GetID();
+  Standard_EXPORT ~GEOMImpl_PipeDriver() {};
+
+
+  // Type management
+  //
+  Standard_EXPORT friend Handle_Standard_Type& GEOMImpl_PipeDriver_Type_();
+  Standard_EXPORT const Handle(Standard_Type)& DynamicType() const
+  { return STANDARD_TYPE(GEOMImpl_PipeDriver) ; }
+  Standard_EXPORT Standard_Boolean IsKind(const Handle(Standard_Type)& AType) const
+  { return (STANDARD_TYPE(GEOMImpl_PipeDriver) == AType ||
+           TFunction_Driver::IsKind(AType)); } 
 
 };
 
index 897873d097c220357535128b9afbc67bb9f5a88c..2e0170267da5d6a0cd16d625bcff3f2568fce275 100755 (executable)
 
 #define PIPE_BASE_PATH 1
 #define PIPE_DIFFERENT_SECTIONS 2
+#define PIPE_SHELL_SECTIONS 3
 
 #define THRUSECTIONS_RULED 1
 #define THRUSECTIONS_SMOOTHED 2
index 561d24512201b2d46869621ae1ee04152129c130..83a98e3a40a427682b8c71d7d40f389805f016ae 100644 (file)
@@ -582,3 +582,80 @@ GEOM::GEOM_Object_ptr GEOM_I3DPrimOperations_i::MakePipeWithDifferentSections(co
 
   return GetObject(anObject);
 }
+
+
+//=============================================================================
+/*!
+ *  MakePipeWithShellSections
+ */
+//=============================================================================
+GEOM::GEOM_Object_ptr GEOM_I3DPrimOperations_i::MakePipeWithShellSections
+                 (const GEOM::ListOfGO& theBases,
+                 const GEOM::ListOfGO& theSubBases,
+                 const GEOM::ListOfGO& theLocations,
+                 GEOM::GEOM_Object_ptr thePath,
+                 CORBA::Boolean theWithContact,
+                 CORBA::Boolean theWithCorrections)
+{
+   GEOM::GEOM_Object_var aGEOMObject;
+
+  //Set a not done flag
+  GetOperations()->SetNotDone();
+  Handle(TColStd_HSequenceOfTransient) aSeqBases = new TColStd_HSequenceOfTransient;
+  Handle(TColStd_HSequenceOfTransient) aSeqSubBases = new TColStd_HSequenceOfTransient;
+  Handle(TColStd_HSequenceOfTransient) aSeqLocations = new TColStd_HSequenceOfTransient;
+  int ind=0, aNbBases=0, aNbSubBases=0, aNbLocs=0;
+  
+  //Get the shapes
+  aNbBases = theBases.length();
+  aNbSubBases = theSubBases.length();
+  aNbLocs = theLocations.length();
+
+  if( aNbLocs &&  aNbBases != aNbLocs)
+    return aGEOMObject._retn();
+  
+   Handle(GEOM_Object) aPath = GetOperations()->GetEngine()->GetObject
+      (thePath->GetStudyID(), thePath->GetEntry());
+   if(aPath.IsNull())
+     return aGEOMObject._retn();
+
+  for (ind = 0; ind < aNbBases; ind++) {
+    if (theBases[ind] == NULL) continue;
+    Handle(GEOM_Object) aBase = GetOperations()->GetEngine()->
+      GetObject(theBases[ind]->GetStudyID(), theBases[ind]->GetEntry());
+    if(aBase.IsNull())
+      continue;
+    if(aNbLocs) {
+      Handle(GEOM_Object) aLoc = GetOperations()->GetEngine()->GetObject
+       (theLocations[ind]->GetStudyID(), theLocations[ind]->GetEntry());
+      if(aLoc.IsNull())
+       continue;
+      aSeqLocations->Append(aLoc);
+    }
+    aSeqBases->Append(aBase);
+
+    if(aNbSubBases>=aNbBases) {
+      Handle(GEOM_Object) aSubBase = GetOperations()->GetEngine()->
+       GetObject(theSubBases[ind]->GetStudyID(), theSubBases[ind]->GetEntry());
+      if(aSubBase.IsNull()) {
+       aSeqSubBases->Clear();
+       aNbSubBases = 0;
+       continue;
+      }
+      aSeqSubBases->Append(aSubBase);
+    }
+
+  }
+  if(!aSeqBases->Length())
+    return aGEOMObject._retn();
+
+  // Make pipe
+  Handle(GEOM_Object) anObject =
+    GetOperations()->MakePipeWithShellSections(aSeqBases, aSeqSubBases,
+                                              aSeqLocations, aPath,
+                                              theWithContact, theWithCorrections);
+  if (!GetOperations()->IsDone() || anObject.IsNull())
+    return aGEOMObject._retn();
+
+  return GetObject(anObject);
+}
index 97c6f16cba8e298e0ea60562d38948fc807ddbcb..a9cae2c0b84f78bf429f9ead94684ed009d91c71 100644 (file)
@@ -105,6 +105,13 @@ class GEOM_I3DPrimOperations_i :
                                                      CORBA::Boolean theWithContact,
                                                      CORBA::Boolean theWithCorrections);
 
+  GEOM::GEOM_Object_ptr MakePipeWithShellSections(const GEOM::ListOfGO& theBases,
+                                                 const GEOM::ListOfGO& theSubBases,
+                                                 const GEOM::ListOfGO& theLocations,
+                                                 GEOM::GEOM_Object_ptr thePath,
+                                                 CORBA::Boolean theWithContact,
+                                                 CORBA::Boolean theWithCorrections);
+
   ::GEOMImpl_I3DPrimOperations* GetOperations()
   { return (::GEOMImpl_I3DPrimOperations*)GetImpl(); }
 };
index c67fb1735ac1471b74ce33efd7d31a4b516e828e..24b2f0f11652275b9bf3b7a5110173b630b7cbcc 100644 (file)
@@ -978,11 +978,12 @@ GEOM::GEOM_Object_ptr GEOM_Superv_i::MakeThruSections(const GEOM::ListOfGO& theS
 //=============================================================================
 //  MakePipe:
 //=============================================================================
-GEOM::GEOM_Object_ptr GEOM_Superv_i::MakePipeWithDifferentSections(const GEOM::ListOfGO& theBases,
-                                                     const GEOM::ListOfGO& theLocations,
-                                                     GEOM::GEOM_Object_ptr thePath,
-                                                     CORBA::Boolean theWithContact,
-                                                     CORBA::Boolean theWithCorrections)
+GEOM::GEOM_Object_ptr GEOM_Superv_i::MakePipeWithDifferentSections
+                     (const GEOM::ListOfGO& theBases,
+                     const GEOM::ListOfGO& theLocations,
+                     GEOM::GEOM_Object_ptr thePath,
+                     CORBA::Boolean theWithContact,
+                     CORBA::Boolean theWithCorrections)
 {
   beginService( " GEOM_Superv_i::MakePipeWithDifferentSections" );
   MESSAGE("GEOM_Superv_i::MakePipeWithDifferentSections");
@@ -991,6 +992,31 @@ GEOM::GEOM_Object_ptr GEOM_Superv_i::MakePipeWithDifferentSections(const GEOM::L
   endService( " GEOM_Superv_i::MakePipeWithDifferentSections" );
   return anObj;
 }
+
+
+//=============================================================================
+//  MakePipe:
+//=============================================================================
+GEOM::GEOM_Object_ptr GEOM_Superv_i::MakePipeWithShellSections
+                   (const GEOM::ListOfGO& theBases,
+                   const GEOM::ListOfGO& theSubBases,
+                   const GEOM::ListOfGO& theLocations,
+                   GEOM::GEOM_Object_ptr thePath,
+                   CORBA::Boolean theWithContact,
+                   CORBA::Boolean theWithCorrections)
+{
+  beginService( " GEOM_Superv_i::MakePipeWithShellSections" );
+  MESSAGE("GEOM_Superv_i::MakePipeWithShellSections");
+  get3DPrimOp();
+  GEOM::GEOM_Object_ptr anObj =
+    my3DPrimOp->MakePipeWithShellSections(theBases, theSubBases,
+                                         theLocations, thePath,
+                                         theWithContact, theWithCorrections);
+  endService( " GEOM_Superv_i::MakePipeWithShellSections" );
+  return anObj;
+}
+
+
 //=============================================================================
 //  MakeFuse:
 //=============================================================================
index 1d8f5b94cacdd4b01a2c1b00f6c58a9feff47ad4..3ec66530b1fe7ce4044bedc2c502ff38a5230fe4 100644 (file)
@@ -237,6 +237,13 @@ public:
                                                      CORBA::Boolean theWithContact,
                                                      CORBA::Boolean theWithCorrections);
   
+  GEOM::GEOM_Object_ptr MakePipeWithShellSections(const GEOM::ListOfGO& theBases,
+                                                 const GEOM::ListOfGO& theSubBases,
+                                                 const GEOM::ListOfGO& theLocations,
+                                                 GEOM::GEOM_Object_ptr thePath,
+                                                 CORBA::Boolean theWithContact,
+                                                 CORBA::Boolean theWithCorrections);
+  
   //-----------------------------------------------------------//
   // BooleanOperations                                         //
   //-----------------------------------------------------------//
index 119e2d9764c2f50d0f1f152a40471adeb1f39ace..ce42e671b9cd628cea7acd72da7ddb0c13815ca1 100644 (file)
@@ -740,6 +740,32 @@ def MakePipeWithDifferentSections(theSeqBases, theLocations,thePath,theWithConta
       print "MakePipeWithDifferentSections : ", PrimOp.GetErrorCode()
     return anObj
 
+## Create a shape by extrusion of the profile shape along
+#  the path shape. The path shape can be a shell or a face.
+#  the several profiles can be specified in the several locations of path.     
+#  @param theSeqBases - list of  Bases shape to be extruded.
+#  @param theSeqSubBases - list of corresponding subshapes of section shapes.
+#  @param theLocations - list of locations on the path corresponding
+#                        specified list of the Bases shapes. Number of locations
+#                        should be equal to number of bases or list of locations can be empty.
+#  @param thePath - Path shape to extrude the base shape along it.
+#  @param theWithContact - the mode defining that the section is translated to be in
+#                          contact with the spine.
+#  @param - WithCorrection - defining that the section is rotated to be
+#                            orthogonal to the spine tangent in the correspondent point
+#  @return New GEOM_Object, containing the created solids.
+#
+#  Example: see GEOM_TestAll.py
+def MakePipeWithShellSections(theSeqBases, theSeqSubBases,
+                              theLocations, thePath,
+                              theWithContact, theWithCorrection):
+    anObj = PrimOp.MakePipeWithShellSections(theSeqBases, theSeqSubBases,
+                                             theLocations, thePath,
+                                             theWithContact, theWithCorrection)
+    if PrimOp.IsDone() == 0:
+      print "MakePipeWithShellSections : ", PrimOp.GetErrorCode()
+    return anObj
+
 # -----------------------------------------------------------------------------
 # Create base shapes
 # -----------------------------------------------------------------------------