Salome HOME
23620: EDF 10301 - Completing Extrusion along a path
authoreap <eap@opencascade.com>
Thu, 24 Jan 2019 15:28:24 +0000 (18:28 +0300)
committereap <eap@opencascade.com>
Thu, 24 Jan 2019 15:28:24 +0000 (18:28 +0300)
Add scale factors to Extrusion along line
Add angles to Extrusion along path

32 files changed:
doc/salome/examples/modifying_meshes_ex22.py
doc/salome/examples/modifying_meshes_ex23.py
doc/salome/gui/SMESH/images/extrusion_along_path_dlg.png
doc/salome/gui/SMESH/images/extrusionalongaline1.png
doc/salome/gui/SMESH/input/extrusion.rst
doc/salome/gui/SMESH/input/extrusion_along_path.rst
idl/SMESH_MeshEditor.idl
src/SMESH/SMESH_MeshEditor.cxx
src/SMESH/SMESH_MeshEditor.hxx
src/SMESH/SMESH_MesherHelper.cxx
src/SMESH/SMESH_MesherHelper.hxx
src/SMESH/SMESH_Pattern.cxx
src/SMESHDS/SMESHDS_Mesh.cxx
src/SMESHGUI/SMESHGUI_ExtrusionAlongPathDlg.cxx
src/SMESHGUI/SMESHGUI_ExtrusionAlongPathDlg.h
src/SMESHGUI/SMESHGUI_ExtrusionDlg.cxx
src/SMESHGUI/SMESHGUI_ExtrusionDlg.h
src/SMESHGUI/SMESH_msg_en.ts
src/SMESHUtils/SMESH_Delaunay.hxx
src/SMESHUtils/SMESH_MeshAlgos.cxx
src/SMESH_I/SMESH_MeshEditor_i.cxx
src/SMESH_I/SMESH_MeshEditor_i.hxx
src/SMESH_SWIG/smeshBuilder.py
src/StdMeshers/StdMeshers_FaceSide.cxx
src/StdMeshers/StdMeshers_Import_1D.cxx
src/StdMeshers/StdMeshers_Import_1D2D.cxx
src/StdMeshers/StdMeshers_Prism_3D.cxx
src/StdMeshers/StdMeshers_ProjectionUtils.cxx
src/StdMeshers/StdMeshers_Projection_2D.cxx
src/StdMeshers/StdMeshers_SegmentLengthAroundVertex.cxx
src/StdMeshers/StdMeshers_ViscousLayers.cxx
src/StdMeshers/StdMeshers_ViscousLayers2D.cxx

index d9e1f97d9431a6ca63509bb465fe4d45310abb0a..fe99d13e3cd757e3f02741ee3524c5799ab9bcd5 100644 (file)
@@ -1,5 +1,7 @@
 # Extrusion
 
+# There is a series of Extrusion Along Line methods added at different times;
+# a fully functional method is ExtrusionSweepObjects()
 
 import salome, math
 salome.salome_init()
@@ -48,22 +50,13 @@ stepVector = [0.,0.,1.]
 mesh.ExtrusionSweepObject1D( obj, stepVector, nbSteps )
 
 # extrude a group
-lineExtruded = None
-for g in mesh.GetGroups( SMESH.FACE ):
-    if g.GetName() == "line_extruded":
-        lineExtruded = g
-        break
-obj        = lineExtruded
+obj        = mesh.GetGroupByName( "line_extruded", SMESH.FACE )[0]
 stepVector = [0,-5.,0.]
 nbSteps    = 1
 mesh.ExtrusionSweepObject( obj, stepVector, nbSteps )
 
 # extrude all nodes and triangle faces of the disk quarter, applying a scale factor
-diskGroup = None
-for g in mesh.GetGroups( SMESH.FACE ):
-    if g.GetName() == "line_rotated":
-        diskGroup = g
-        break
+diskGroup = mesh.GetGroupByName( "line_rotated", SMESH.FACE )[0]
 crit = [ smesh.GetCriterion( SMESH.FACE, SMESH.FT_ElemGeomType,'=',SMESH.Geom_TRIANGLE ),
          smesh.GetCriterion( SMESH.FACE, SMESH.FT_BelongToMeshGroup,'=', diskGroup )]
 trianglesFilter = smesh.GetFilterFromCriteria( crit )
index 65b57ff36d2e552d080817eb967d90412d982c14..d7f413440df5108c465d6e94acdcaa34790443fe 100644 (file)
@@ -19,7 +19,7 @@ iv = 1
 vertices = []
 for point in points:
     vert = geompy.MakeVertex(point[0], point[1], 0)
-    geompy.addToStudy(vert, "Vertex_" + repr(iv))
+    #geompy.addToStudy(vert, "Vertex_" + repr(iv))
     vertices.append(vert)
     iv += 1
     pass
@@ -97,8 +97,8 @@ Edge_Circle_mesh   = Mesh1D(Edge_Circle  , 8, "Edge_Circle"  , smesh_builder=sme
 # IDsOfElements, PathMesh, PathShape, NodeStart,
 # HasAngles, Angles, HasRefPoint, RefPoint
 refPoint = SMESH.PointStruct(0, 0, 0)
-a10 = 10.0*math.pi/180.0
-a45 = 45.0*math.pi/180.0
+a10 = math.radians( 10.0 )
+a45 = math.radians( 45.0 )
 
 # 1. Extrusion of two mesh edges along a straight path
 error = quad_1.ExtrusionAlongPath([1,2], Edge_straight_mesh, Edge_straight, 1,
@@ -128,4 +128,53 @@ error = quad_6.ExtrusionAlongPath(ff_6 , Edge_Circle_mesh, Edge_Circle, 1,
 error = quad_7.ExtrusionAlongPath(ff_7, Edge_Circle_mesh, Edge_Circle, 1,
                                   1, [a45, -a45, a45, -a45, a45, -a45, a45, -a45], 0, refPoint)
 
+
+
+# Make the same meshes using a fully functional method ExtrusionAlongPathObjects() having
+# the following arguments:
+#   Nodes, Edges, Faces, PathObject, PathShape=None,
+#   NodeStart=1, HasAngles=False, Angles=[], LinearVariation=False,
+#   HasRefPoint=False, RefPoint=[0,0,0], MakeGroups=False,
+#   ScaleFactors=[], ScalesVariation=False
+
+quad_1 = MakeQuadMesh2("quad_1", smesh_builder=smesh)[0]
+quad_2 = MakeQuadMesh2("quad_2", smesh_builder=smesh)[0]
+quad_3 = MakeQuadMesh2("quad_3", smesh_builder=smesh)[0]
+quad_4 = MakeQuadMesh2("quad_4", smesh_builder=smesh)[0]
+quad_5 = MakeQuadMesh2("quad_5", smesh_builder=smesh)[0]
+quad_6 = MakeQuadMesh2("quad_6", smesh_builder=smesh)[0]
+quad_7 = MakeQuadMesh2("quad_7", smesh_builder=smesh)[0]
+
+# 1. Extrusion of two mesh edges along a straight path
+nn, ee, ff = [], [1,2], []
+error = quad_1.ExtrusionAlongPathObjects( nn, ee, ff, Edge_straight_mesh )
+
+# 2. Extrusion of one mesh edge along a curved path
+nn, ee, ff = [], [2], []
+error = quad_2.ExtrusionAlongPathObjects( nn, ee, ff, Edge_bezierrr_mesh )
+
+# 3. Extrusion of one mesh edge along a curved path with usage of angles
+error = quad_3.ExtrusionAlongPathObjects( nn, ee, ff, Edge_bezierrr_mesh,
+                                          Angles=[a45, a45, a45, 0, -a45, -a45, -a45])
+
+# 4. Extrusion of one mesh edge along the path, which is a part of a meshed wire
+nn, ee, ff = [], [4], []
+error = quad_4.ExtrusionAlongPathObjects( nn, ee, ff, Wire_polyline_mesh, Wire_polyline_edges[0],
+                                          Angles=[a10, a10, a10])
+
+# 5. Extrusion of two mesh faces along the path, which is a part of a meshed wire
+nn, ee, ff = [], [], quad_5
+error = quad_5.ExtrusionAlongPathObjects( nn, ee, ff, Wire_polyline_mesh, Wire_polyline_edges[2],
+                                          NodeStart=4 )
+
+# 6. Extrusion of two mesh faces along a closed path
+nn, ee, ff = [], [], quad_6
+error = quad_6.ExtrusionAlongPathObjects( nn, ee, ff, Edge_Circle_mesh )
+
+# 7. Extrusion of two mesh faces along a closed path with usage of angles
+nn, ee, ff = [], [], quad_7
+error = quad_7.ExtrusionAlongPathObjects( nn, ee, ff, Edge_Circle_mesh, Edge_Circle,
+                                          Angles=[a45, -a45, a45, -a45, a45, -a45, a45, -a45])
+
+
 salome.sg.updateObjBrowser()
index bdc1eff88c7f175904f644fd8bcd23f1d2dba8ea..98e362f388837641fa0a85dbae8fb0897715334c 100644 (file)
Binary files a/doc/salome/gui/SMESH/images/extrusion_along_path_dlg.png and b/doc/salome/gui/SMESH/images/extrusion_along_path_dlg.png differ
index 7de580be18c7ef18d5903b7752fdfb665fda67ae..761f09bda1e6c4894c3d05039b96a2eeb4da4078 100644 (file)
Binary files a/doc/salome/gui/SMESH/images/extrusionalongaline1.png and b/doc/salome/gui/SMESH/images/extrusionalongaline1.png differ
index c13ab9f0a7857c8ef26e33e5855d4f182858f31f..3cee68e31ff9ab9e0d0fc6274a7404cca48cf294 100644 (file)
@@ -63,10 +63,10 @@ When 2D elements are extruded, in addition to 3D elements segments are created o
                * Input the element IDs directly in **Node IDs**, **Edge IDs** and **Face IDs** fields. The selected elements will be highlighted in the viewer, if the mesh is shown there. 
                * Apply Filters. **Set filter** button allows to apply a filter to the selection of elements. See more about filters in the :ref:`filtering_elements` page. 
 
-       * If the **Extrusion to Distance** radio button is selected 
+       * If the **Extrusion to distance** radio button is selected 
                * specify the translation vector by which the elements will be extruded.
 
-       * If the **Extrusion Along Vector** radio button is selected
+       * If the **Extrusion along vector** radio button is selected
 
                .. image:: ../images/extrusionalongaline2.png  
                        :align: center
@@ -76,7 +76,7 @@ When 2D elements are extruded, in addition to 3D elements segments are created o
     
   
 
-       * If the **Extrusion By Normal** radio button is selected, every node of the selected faces is extruded along the *average* of the *normal* vectors to the faces sharing the node. (Nodes and edges cannot be extruded in this mode.)
+       * If the **Extrusion by normal** radio button is selected, every node of the selected faces is extruded along the *average* of the *normal* vectors to the faces sharing the node. (Nodes and edges cannot be extruded in this mode.)
 
                .. image:: ../images/extrusionalongaline3.png 
                        :align: center
@@ -115,11 +115,15 @@ When 2D elements are extruded, in addition to 3D elements segments are created o
 
 
        * Specify the **Number of steps**.
-       * Optionally specify **Scale Factors**. Each scale factor in the list is applied to nodes of a corresponding extrusion step unless **Linear Variation of Scale Factors** is checked, is which case the scale factors are spread over all extrusion steps.
-               * **Scaling Center** can be defined either using spin boxes or by picking a node in the Viewer or by picking a geometrical vertex in the Object Browser.
+       * Optionally specify **Scale factors**. Each scale factor in the list is applied to nodes of a corresponding extrusion step unless **Linear variation of factors** is checked, is which case the scale factors are spread over all extrusion steps.
+               * **Base point** serving as a scaling canter can be defined either using spin boxes or by picking a node in the Viewer or by picking a geometrical vertex in the Object Browser.
                * **Add** button |add| adds a scale factor to the list.   
                * **Remove** button |rm| removes selected scale factors from the list.
 
+        * The elements can also be rotated around the **Base point** to get the resulting mesh in a helical fashion. You can set the values of **Rotation angles** to the list by pressing the *"Add"* button |add| and remove them from the list by pressing the *"Remove"* button |rm|.
+
+          **Linear variation of angles** option allows defining the angle of gradual rotation for the whole path. At each step the elements will be rotated by *( angle / nb. of steps )*.
+
        * If you activate **Generate Groups** check-box, the *result elements* created from *selected elements* contained in groups will be included into new groups named by pattern "<old group name>_extruded" and "<old group name>_top". For example if a selected quadrangle is included in *g_Faces* group (see figures below) then result hexahedra will be included in *g_Faces_extruded* group and a quadrangle created at the "top" of extruded mesh will be included in *g_Faces_top group*.  
 
                .. image:: ../images/extrusion_groups.png
index 71851c8ef55c6c31cc13804abda51f07dc8624ff..70fb0cb2f420d19e9f2f415f5bcba2b4059a890d 100644 (file)
@@ -123,7 +123,7 @@ Extrusion of 2d elements along a closed path
                * **Start node** - the start node of the Path. It is used to define the direction of extrusion. 
       
     
-       * If you activate **Generate Groups** check-box, the **result elements** created from **selected elements** contained in groups will be included into new groups named by pattern "<old group name>_extruded" and "<old group name>_top". For example if a  selected quadrangle is included in *g_Faces* group (see figures below) then result hexahedra will be included in *g_Faces_extruded* group and a quadrangle created at the "top" of extruded mesh will be included in *g_Faces_top group*.  
+       * If you activate **Generate groups** check-box, the *result elements* created from *selected elements* contained in groups will be included into new groups named by pattern "<old group name>_extruded" and "<old group name>_top". For example if a  selected quadrangle is included in *g_Faces* group (see figures below) then result hexahedra will be included in *g_Faces_extruded* group and a quadrangle created at the "top" of extruded mesh will be included in *g_Faces_top group*.  
 
        .. image:: ../images/extrusion_groups.png
                :align: center
@@ -138,16 +138,18 @@ Extrusion of 2d elements along a closed path
 
 #. There are two optional parameters, which can be very useful:
 
-   * If the path of extrusion is curvilinear, at each iteration the extruded elements are rotated to keep its initial angularity to the curve. By default, the **Base Point** around which the elements are rotated is the mass center of the elements (note that it can differ from the gravity center computed by *Geometry* module for the  underlying shape), however, you can specify any point as the **Base Point** and the elements will be rotated with respect to this point. Note that only the displacement of the **Base Point** exactly equals to the path, and all other extruded elements simply keep their position relatively to the **Base Point** at each iteration.
+   * If the path of extrusion is curvilinear, at each iteration the extruded elements are rotated to keep its initial angularity to the curve. By default, the **Base point** around which the elements are rotated is the mass center of the elements (note that it can differ from the gravity center computed by *Geometry* module for the  underlying shape), however, you can specify any point as the **Base point** and the elements will be rotated with respect to this point. Note that only the displacement of the **Base point** exactly equals to the path, and all other extruded elements simply keep their position relatively to the **Base point** at each iteration.
 
    .. |add| image:: ../images/add.png
    .. |rem| image:: ../images/remove.png
 
-   * The elements can also be rotated around the path to get the resulting mesh in a helical fashion. You can set the values of angles at the right, add them to the list of angles at the left by pressing the *"Add"* button |add| and remove them from the list by pressing the *"Remove"* button |rem|.
+   * The elements can also be rotated around the path with rotaion center at the **Base point** to get the resulting mesh in a helical fashion. You can set the values of angles at the right, add them to **Rotation angles** list at the left by pressing the *"Add"* button |add| and remove them from the list by pressing the *"Remove"* button |rem|.
 
+     **Linear variation of angles** option allows defining the angle of gradual rotation for the whole path. At each step the elements will be rotated by *( angle / nb. of steps )*.
 
-     **Linear variation of the angles** option allows defining the angle of gradual rotation for the whole path. At each step the elements will be rotated by *( angle / nb. of steps )*.
-
+   * Each of optional **Scale factors** in the list is applied to nodes of a corresponding extrusion step unless **Linear variation of factors** is checked, is which case the scale factors are spread over all extrusion steps. **Base point** serves as a scaling canter.
+       * *"Add"* button |add| adds a scale factor to the list.   
+       * *"Remove"* button |rem| removes selected scale factors from the list.
 
 
 #. Click **Apply** or **Apply and Close**  button to confirm the operation. Mesh edges will be extruded into faces, faces into volumes. The external surface of the resulting 3d mesh (if faces have been extruded) is covered with faces, and corners with edges. If the path is closed, the resulting mesh can contain duplicated nodes and faces, because no sewing is done.
index 482f8e9b6c909fe169983565ad044fd3979d6e7b..83ed605faf0fd0ed9f2e6d86840c3e971ba97ee9 100644 (file)
@@ -510,13 +510,21 @@ module SMESH
 
     /*!
      * \brief Generate dim+1 elements by extrusion of elements along vector
-     *  \param nodes - nodes to extrude: a list including groups, sub-meshes or a mesh
-     *  \param edges - edges to extrude: a list including groups, sub-meshes or a mesh
-     *  \param faces - faces to extrude: a list including groups, sub-meshes or a mesh
-     *  \param stepVector - vector giving direction and distance of an extrusion step
-     *  \param nbOfSteps - number of elements to generate from one element
+     *  \param nodes - nodes to extrude: a list including groups, sub-meshes or a mesh.
+     *  \param edges - edges to extrude: a list including groups, sub-meshes or a mesh.
+     *  \param faces - faces to extrude: a list including groups, sub-meshes or a mesh.
+     *  \param stepVector - vector giving direction and distance of an extrusion step.
+     *  \param nbOfSteps - number of elements to generate from one element.
      *  \param toMakeGroups - if true, new elements will be included into new groups
      *         corresponding to groups the input elements included in.
+     *  \param scaleFactors - optional scale factors to apply during extrusion; it's
+     *         usage depends on \a scalesVariation parameter.
+     *  \param scalesVariation - if \c True, \a scaleFactors are spread over all \a NbOfSteps,
+                otherwise \a scaleFactors[i] is applied to nodes at the i-th extrusion step.
+     *  \param angles - optional rotation angles to apply during extrusion; it's
+     *         usage depends on \a anglesVariation parameter.
+     *  \param anglesVariation - if \c True, \a angles are spread over all \a NbOfSteps,
+                otherwise \a angle[i] is applied to nodes at the i-th extrusion step.
      *  \return ListOfGroups - new groups created if \a toMakeGroups is true
      */
     ListOfGroups ExtrusionSweepObjects(in ListOfIDSources nodes,
@@ -524,10 +532,12 @@ module SMESH
                                        in ListOfIDSources faces,
                                        in DirStruct       stepVector,
                                        in long            nbOfSteps,
+                                       in boolean         toMakeGroups,
                                        in double_array    scaleFactors,
-                                       in boolean         linearVariation,
+                                       in boolean         scaleVariation,
                                        in double_array    basePoint,
-                                       in boolean         toMakeGroups)
+                                       in double_array    angles,
+                                       in boolean         angleVariation)
       raises (SALOME::SALOME_Exception);
 
     /*! Generates new elements by extrusion along the normal to a discretized surface or wire
@@ -569,18 +579,20 @@ module SMESH
       EXTR_CANT_GET_TANGENT
     };
 
-    ListOfGroups ExtrusionAlongPathObjects(in ListOfIDSources Nodes,
-                                           in ListOfIDSources Edges,
-                                           in ListOfIDSources Faces,
+    ListOfGroups ExtrusionAlongPathObjects(in ListOfIDSources   Nodes,
+                                           in ListOfIDSources   Edges,
+                                           in ListOfIDSources   Faces,
                                            in SMESH_IDSource    Path,
                                            in GEOM::GEOM_Object PathShape,
                                            in long              NodeStart,
                                            in boolean           HasAngles,
                                            in double_array      Angles,
-                                           in boolean           LinearVariation,
+                                           in boolean           AnglesVariation,
                                            in boolean           HasRefPoint,
                                            in PointStruct       RefPoint,
                                            in boolean           MakeGroups,
+                                           in double_array      ScaleFactors,
+                                           in boolean           ScaleVariation,
                                            out Extrusion_Error  Error)
       raises (SALOME::SALOME_Exception);
 
index 81db6b65f296d5cd3ed12332810c2732bd98efcc..69cb3e94bedffe31246db959fbe1ad846c9c25b8 100644 (file)
@@ -606,25 +606,6 @@ static void shiftNodesQuadTria(vector< const SMDS_MeshNode* >& aNodes)
   aNodes[5] = nd2;
 }
 
-//=======================================================================
-//function : nbEdgeConnectivity
-//purpose  : return number of the edges connected with the theNode.
-//           if theEdges has connections with the other type of the
-//           elements, return -1
-//=======================================================================
-
-static int nbEdgeConnectivity(const SMDS_MeshNode* theNode)
-{
-  // SMDS_ElemIteratorPtr elemIt = theNode->GetInverseElementIterator();
-  // int nb=0;
-  // while(elemIt->more()) {
-  //   elemIt->next();
-  //   nb++;
-  // }
-  // return nb;
-  return theNode->NbInverseElements();
-}
-
 //=======================================================================
 //function : getNodesFromTwoTria
 //purpose  : 
@@ -5183,6 +5164,7 @@ SMESH_MeshEditor::RotationSweep(TIDSortedElemSet   theElemSets[2],
 SMESH_MeshEditor::ExtrusParam::ExtrusParam( const gp_Vec&            theStep,
                                             const int                theNbSteps,
                                             const std::list<double>& theScales,
+                                            const std::list<double>& theAngles,
                                             const gp_XYZ*            theBasePoint,
                                             const int                theFlags,
                                             const double             theTolerance):
@@ -5197,32 +5179,52 @@ SMESH_MeshEditor::ExtrusParam::ExtrusParam( const gp_Vec&            theStep,
   for (int i=1; i<=theNbSteps; i++ )
     mySteps->Append( stepSize );
 
-  int nbScales = theScales.size();
-  if ( nbScales > 0 )
+  if ( !theScales.empty() )
   {
-    if ( IsLinearVariation() && nbScales < theNbSteps )
+    if ( IsScaleVariation() && (int)theScales.size() < theNbSteps )
+      linearScaleVariation( theNbSteps, const_cast< std::list<double>& >( theScales ));
+
+    // add medium scales
+    std::list<double>::const_iterator s2 = theScales.begin(), s1 = s2++;
+    myScales.reserve( theNbSteps * 2 );
+    myScales.push_back( 0.5 * ( *s1 + 1. ));
+    myScales.push_back( *s1 );
+    for ( ; s2 != theScales.end(); s1 = s2++ )
     {
-      myScales.reserve( theNbSteps );
-      std::list<double>::const_iterator scale = theScales.begin();
-      double prevScale = 1.0;
-      for ( int iSc = 1; scale != theScales.end(); ++scale, ++iSc )
-      {
-        int      iStep = int( iSc / double( nbScales ) * theNbSteps + 0.5 );
-        int    stDelta = Max( 1, iStep - myScales.size());
-        double scDelta = ( *scale - prevScale ) / stDelta;
-        for ( int iStep = 0; iStep < stDelta; ++iStep )
-        {
-          myScales.push_back( prevScale + scDelta );
-          prevScale = myScales.back();
-        }
-        prevScale = *scale;
-      }
+      myScales.push_back( 0.5 * ( *s1 + *s2 ));
+      myScales.push_back( *s2 );
     }
-    else
+  }
+
+  if ( !theAngles.empty() )
+  {
+    std::list<double>& angles = const_cast< std::list<double>& >( theAngles );
+    if ( IsAngleVariation() && (int)theAngles.size() < theNbSteps )
+      linearAngleVariation( theNbSteps, angles );
+
+    // accumulate angles
+    double angle = 0;
+    int nbAngles = 0;
+    std::list<double>::iterator a1 = angles.begin(), a2;
+    for ( ; a1 != angles.end(); ++a1, ++nbAngles )
+    {
+      angle += *a1;
+      *a1 = angle;
+    }
+    while ( nbAngles++ < theNbSteps )
+      angles.push_back( angles.back() );
+
+    // add medium angles
+    a2 = angles.begin(), a1 = a2++;
+    myAngles.push_back( 0.5 * *a1 );
+    myAngles.push_back( *a1 );
+    for ( ; a2 != angles.end(); a1 = a2++ )
     {
-      myScales.assign( theScales.begin(), theScales.end() );
+      myAngles.push_back( 0.5 * ( *a1 + *a2 ));
+      myAngles.push_back( *a2 );
     }
   }
+
   if ( theBasePoint )
   {
     myBaseP = *theBasePoint;
@@ -5293,6 +5295,41 @@ SMESH_MeshEditor::ExtrusParam::ExtrusParam( const double theStepSize,
   }
 }
 
+//=======================================================================
+//function : ExtrusParam
+//purpose  : for extrusion along path
+//=======================================================================
+
+SMESH_MeshEditor::ExtrusParam::ExtrusParam( const std::vector< PathPoint >& thePoints,
+                                            const gp_Pnt*                   theBasePoint,
+                                            const std::list<double>&        theScales,
+                                            const bool                      theMakeGroups )
+  : myBaseP( Precision::Infinite(), 0, 0 ),
+    myFlags( EXTRUSION_FLAG_BOUNDARY | ( theMakeGroups ? EXTRUSION_FLAG_GROUPS : 0 )),
+    myPathPoints( thePoints )
+{
+  if ( theBasePoint )
+  {
+    myBaseP = theBasePoint->XYZ();
+  }
+
+  if ( !theScales.empty() )
+  {
+    // add medium scales
+    std::list<double>::const_iterator s2 = theScales.begin(), s1 = s2++;
+    myScales.reserve( thePoints.size() * 2 );
+    myScales.push_back( 0.5 * ( 1. + *s1 ));
+    myScales.push_back( *s1 );
+    for ( ; s2 != theScales.end(); s1 = s2++ )
+    {
+      myScales.push_back( 0.5 * ( *s1 + *s2 ));
+      myScales.push_back( *s2 );
+    }
+  }
+
+  myMakeNodesFun = & SMESH_MeshEditor::ExtrusParam::makeNodesAlongTrack;
+}
+
 //=======================================================================
 //function : ExtrusParam::SetElementsToUse
 //purpose  : stores elements to use for extrusion by normal, depending on
@@ -5398,38 +5435,37 @@ makeNodesByDir( SMESHDS_Mesh*                     mesh,
     newNodes.push_back( newNode );
   }
 
-  if ( !myScales.empty() )
+  if ( !myScales.empty() || !myAngles.empty() )
   {
-    if ( makeMediumNodes && myMediumScales.empty() )
-    {
-      myMediumScales.resize( myScales.size() );
-      double prevFactor = 1.;
-      for ( size_t i = 0; i < myScales.size(); ++i )
-      {
-        myMediumScales[i] = 0.5 * ( prevFactor + myScales[i] );
-        prevFactor = myScales[i];
-      }
-    }
-    typedef std::vector<double>::iterator ScaleIt;
-    ScaleIt scales[] = { myScales.begin(), myMediumScales.begin() };
-
-    size_t iSc = 0, nbScales = myScales.size() + myMediumScales.size();
+    gp_XYZ  center = myBaseP;
+    gp_Ax1  ratationAxis( center, myDir );
+    gp_Trsf rotation;
 
-    gp_XYZ center = myBaseP;
     std::list<const SMDS_MeshNode*>::iterator nIt = newNodes.begin();
-    size_t iN  = 0;
-    for ( beginStepIter( makeMediumNodes ); moreSteps() && ( iN < nbScales ); ++nIt, ++iN )
+    size_t i = !makeMediumNodes;
+    for ( beginStepIter( makeMediumNodes );
+          moreSteps();
+          ++nIt, i += 1 + !makeMediumNodes )
     {
       center += myDir.XYZ() * nextStep();
 
-      iSc += int( makeMediumNodes );
-      ScaleIt& scale = scales[ iSc % 2 ];
-      
       gp_XYZ xyz = SMESH_NodeXYZ( *nIt );
-      xyz = ( *scale * ( xyz - center )) + center;
-      mesh->MoveNode( *nIt, xyz.X(), xyz.Y(), xyz.Z() );
-
-      ++scale;
+      bool moved = false;
+      if ( i < myScales.size() )
+      {
+        xyz = ( myScales[i] * ( xyz - center )) + center;
+        moved = true;
+      }
+      if ( !myAngles.empty() )
+      {
+        rotation.SetRotation( ratationAxis, myAngles[i] );
+        rotation.Transforms( xyz );
+        moved = true;
+      }
+      if ( moved )
+        mesh->MoveNode( *nIt, xyz.X(), xyz.Y(), xyz.Z() );
+      else
+        break;
     }
   }
   return nbNodes;
@@ -5596,6 +5632,100 @@ makeNodesByNormal1D( SMESHDS_Mesh*                     mesh,
   return 0;
 }
 
+//=======================================================================
+//function : ExtrusParam::makeNodesAlongTrack
+//purpose  : create nodes for extrusion along path
+//=======================================================================
+
+int SMESH_MeshEditor::ExtrusParam::
+makeNodesAlongTrack( SMESHDS_Mesh*                     mesh,
+                     const SMDS_MeshNode*              srcNode,
+                     std::list<const SMDS_MeshNode*> & newNodes,
+                     const bool                        makeMediumNodes)
+{
+  const Standard_Real aTolAng=1.e-4;
+
+  gp_Pnt aV0x = myBaseP;
+  gp_Pnt aPN0 = SMESH_NodeXYZ( srcNode );
+
+  const PathPoint& aPP0 = myPathPoints[0];
+  gp_Pnt aP0x = aPP0.myPnt;
+  gp_Dir aDT0x= aPP0.myTgt;
+
+  std::vector< gp_Pnt > centers;
+  centers.reserve( NbSteps() * 2 );
+
+  gp_Trsf aTrsf, aTrsfRot, aTrsfRotT1T0;
+
+  for ( size_t j = 1; j < myPathPoints.size(); ++j )
+  {
+    const PathPoint&  aPP  = myPathPoints[j];
+    const gp_Pnt&     aP1x = aPP.myPnt;
+    const gp_Dir&    aDT1x = aPP.myTgt;
+
+    // Translation
+    gp_Vec aV01x( aP0x, aP1x );
+    aTrsf.SetTranslation( aV01x );
+    gp_Pnt aV1x = aV0x.Transformed( aTrsf );
+    gp_Pnt aPN1 = aPN0.Transformed( aTrsf );
+
+    // rotation 1 [ T1,T0 ]
+    Standard_Real aAngleT1T0 = -aDT1x.Angle( aDT0x );
+    if ( fabs( aAngleT1T0 ) > aTolAng )
+    {
+      gp_Dir aDT1T0 = aDT1x ^ aDT0x;
+      aTrsfRotT1T0.SetRotation( gp_Ax1( aV1x, aDT1T0 ), aAngleT1T0 );
+
+      aPN1 = aPN1.Transformed( aTrsfRotT1T0 );
+    }
+
+    // rotation 2
+    if ( aPP.myAngle != 0. )
+    {
+      aTrsfRot.SetRotation( gp_Ax1( aV1x, aDT1x ), aPP.myAngle );
+      aPN1 = aPN1.Transformed( aTrsfRot );
+    }
+
+    // make new node
+    if ( makeMediumNodes )
+    {
+      // create additional node
+      gp_XYZ midP = 0.5 * ( aPN1.XYZ() + aPN0.XYZ() );
+      const SMDS_MeshNode* newNode = mesh->AddNode( midP.X(), midP.Y(), midP.Z() );
+      newNodes.push_back( newNode );
+
+    }
+    const SMDS_MeshNode* newNode = mesh->AddNode( aPN1.X(), aPN1.Y(), aPN1.Z() );
+    newNodes.push_back( newNode );
+
+    centers.push_back( 0.5 * ( aV0x.XYZ() + aV1x.XYZ() ));
+    centers.push_back( aV1x );
+
+    aPN0 = aPN1;
+    aP0x = aP1x;
+    aV0x = aV1x;
+    aDT0x = aDT1x;
+  }
+
+  // scale
+  if ( !myScales.empty() )
+  {
+    gp_Trsf aTrsfScale;
+    std::list<const SMDS_MeshNode*>::iterator node = newNodes.begin();
+    for ( size_t i = !makeMediumNodes;
+          i < myScales.size() && node != newNodes.end();
+          i += ( 1 + !makeMediumNodes ), ++node )
+    {
+      aTrsfScale.SetScale( centers[ i ], myScales[ i ] );
+      gp_Pnt aN = SMESH_NodeXYZ( *node );
+      gp_Pnt aP = aN.Transformed( aTrsfScale );
+      mesh->MoveNode( *node, aP.X(), aP.Y(), aP.Z() );
+    }
+  }
+
+  return myPathPoints.size() + makeMediumNodes * ( myPathPoints.size() - 2 );
+}
+
 //=======================================================================
 //function : ExtrusionSweep
 //purpose  :
@@ -5609,10 +5739,31 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet     theElems[2],
                                   const int            theFlags,
                                   const double         theTolerance)
 {
-  ExtrusParam aParams( theStep, theNbSteps, std::list<double>(), 0, theFlags, theTolerance );
+  std::list<double> dummy;
+  ExtrusParam aParams( theStep, theNbSteps, dummy, dummy, 0,
+                       theFlags, theTolerance );
   return ExtrusionSweep( theElems, aParams, newElemsMap );
 }
 
+namespace
+{
+
+//=======================================================================
+//function : getOriFactor
+//purpose  : Return -1 or 1 depending on if order of given nodes corresponds to
+//           edge curve orientation
+//=======================================================================
+
+  double getOriFactor( const TopoDS_Edge&   edge,
+                       const SMDS_MeshNode* n1,
+                       const SMDS_MeshNode* n2,
+                       SMESH_MesherHelper&  helper)
+  {
+    double u1 = helper.GetNodeU( edge, n1, n2 );
+    double u2 = helper.GetNodeU( edge, n2, n1 );
+    return u1 < u2 ? 1. : -1.;
+  }
+}
 
 //=======================================================================
 //function : ExtrusionSweep
@@ -5661,11 +5812,11 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet     theElemSets[2],
       newNodesItVec.reserve( nbNodes );
 
       // loop on elem nodes
-      SMDS_ElemIteratorPtr itN = elem->nodesIterator();
+      SMDS_NodeIteratorPtr itN = elem->nodeIterator();
       while ( itN->more() )
       {
         // check if a node has been already sweeped
-        const SMDS_MeshNode* node = cast2Node( itN->next() );
+        const SMDS_MeshNode* node = itN->next();
         TNodeOfNodeListMap::iterator nIt =
           mapNewNodes.insert( make_pair( node, list<const SMDS_MeshNode*>() )).first;
         list<const SMDS_MeshNode*>& listNewNodes = nIt->second;
@@ -5726,726 +5877,183 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet     theElemSets[2],
 //=======================================================================
 SMESH_MeshEditor::Extrusion_Error
 SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
-                                       SMESH_subMesh*       theTrack,
+                                       SMESH_Mesh*          theTrackMesh,
+                                       SMDS_ElemIteratorPtr theTrackIterator,
                                        const SMDS_MeshNode* theN1,
-                                       const bool           theHasAngles,
-                                       list<double>&        theAngles,
-                                       const bool           theLinearVariation,
-                                       const bool           theHasRefPoint,
-                                       const gp_Pnt&        theRefPoint,
+                                       std::list<double>&   theAngles,
+                                       const bool           theAngleVariation,
+                                       std::list<double>&   theScales,
+                                       const bool           theScaleVariation,
+                                       const gp_Pnt*        theRefPoint,
                                        const bool           theMakeGroups)
 {
   ClearLastCreated();
 
-  int aNbE;
-  std::list<double> aPrms;
-  TIDSortedElemSet::iterator itElem;
-
-  gp_XYZ aGC;
-  TopoDS_Edge aTrackEdge;
-  TopoDS_Vertex aV1, aV2;
-
-  SMDS_ElemIteratorPtr aItE;
-  SMDS_NodeIteratorPtr aItN;
-  SMDSAbs_ElementType aTypeE;
-
-  TNodeOfNodeListMap mapNewNodes;
-
   // 1. Check data
-  aNbE = theElements[0].size() + theElements[1].size();
-  // nothing to do
-  if ( !aNbE )
+  if ( theElements[0].empty() && theElements[1].empty() )
     return EXTR_NO_ELEMENTS;
 
-  // 1.1 Track Pattern
-  ASSERT( theTrack );
-
-  SMESHDS_SubMesh* pSubMeshDS = theTrack->GetSubMeshDS();
-  if ( !pSubMeshDS )
-    return ExtrusionAlongTrack( theElements, theTrack->GetFather(), theN1,
-                                theHasAngles, theAngles, theLinearVariation,
-                                theHasRefPoint, theRefPoint, theMakeGroups );
-
-  aItE = pSubMeshDS->GetElements();
-  while ( aItE->more() ) {
-    const SMDS_MeshElement* pE = aItE->next();
-    aTypeE = pE->GetType();
-    // Pattern must contain links only
-    if ( aTypeE != SMDSAbs_Edge )
-      return EXTR_PATH_NOT_EDGE;
-  }
-
-  list<SMESH_MeshEditor_PathPoint> fullList;
-
-  const TopoDS_Shape& aS = theTrack->GetSubShape();
-  // Sub-shape for the Pattern must be an Edge or Wire
-  if( aS.ShapeType() == TopAbs_EDGE ) {
-    aTrackEdge = TopoDS::Edge( aS );
-    // the Edge must not be degenerated
-    if ( SMESH_Algo::isDegenerated( aTrackEdge ) )
-      return EXTR_BAD_PATH_SHAPE;
-    TopExp::Vertices( aTrackEdge, aV1, aV2 );
-    aItN = theTrack->GetFather()->GetSubMesh( aV1 )->GetSubMeshDS()->GetNodes();
-    const SMDS_MeshNode* aN1 = aItN->next();
-    aItN = theTrack->GetFather()->GetSubMesh( aV2 )->GetSubMeshDS()->GetNodes();
-    const SMDS_MeshNode* aN2 = aItN->next();
-    // starting node must be aN1 or aN2
-    if ( !( aN1 == theN1 || aN2 == theN1 ) )
-      return EXTR_BAD_STARTING_NODE;
-    aItN = pSubMeshDS->GetNodes();
-    while ( aItN->more() ) {
-      const SMDS_MeshNode*  pNode = aItN->next();
-      SMDS_EdgePositionPtr pEPos = pNode->GetPosition();
-      double aT = pEPos->GetUParameter();
-      aPrms.push_back( aT );
-    }
-    //Extrusion_Error err =
-    makeEdgePathPoints(aPrms, aTrackEdge, (aN1==theN1), fullList);
-  } else if( aS.ShapeType() == TopAbs_WIRE ) {
-    list< SMESH_subMesh* > LSM;
-    TopTools_SequenceOfShape Edges;
-    SMESH_subMeshIteratorPtr itSM = theTrack->getDependsOnIterator(false,true);
-    while(itSM->more()) {
-      SMESH_subMesh* SM = itSM->next();
-      LSM.push_back(SM);
-      const TopoDS_Shape& aS = SM->GetSubShape();
-      Edges.Append(aS);
-    }
-    list< list<SMESH_MeshEditor_PathPoint> > LLPPs;
-    int startNid = theN1->GetID();
-    TColStd_MapOfInteger UsedNums;
-
-    int NbEdges = Edges.Length();
-    int i = 1;
-    for(; i<=NbEdges; i++) {
-      int k = 0;
-      list< SMESH_subMesh* >::iterator itLSM = LSM.begin();
-      for(; itLSM!=LSM.end(); itLSM++) {
-        k++;
-        if(UsedNums.Contains(k)) continue;
-        aTrackEdge = TopoDS::Edge( Edges.Value(k) );
-        SMESH_subMesh* locTrack = *itLSM;
-        SMESHDS_SubMesh* locMeshDS = locTrack->GetSubMeshDS();
-        TopExp::Vertices( aTrackEdge, aV1, aV2 );
-        aItN = locTrack->GetFather()->GetSubMesh(aV1)->GetSubMeshDS()->GetNodes();
-        const SMDS_MeshNode* aN1 = aItN->next();
-        aItN = locTrack->GetFather()->GetSubMesh(aV2)->GetSubMeshDS()->GetNodes();
-        const SMDS_MeshNode* aN2 = aItN->next();
-        // starting node must be aN1 or aN2
-        if ( !( aN1->GetID() == startNid || aN2->GetID() == startNid ) ) continue;
-        // 2. Collect parameters on the track edge
-        aPrms.clear();
-        aItN = locMeshDS->GetNodes();
-        while ( aItN->more() ) {
-          const SMDS_MeshNode* pNode = aItN->next();
-          SMDS_EdgePositionPtr pEPos = pNode->GetPosition();
-          double aT = pEPos->GetUParameter();
-          aPrms.push_back( aT );
-        }
-        list<SMESH_MeshEditor_PathPoint> LPP;
-        //Extrusion_Error err =
-        makeEdgePathPoints(aPrms, aTrackEdge,(aN1->GetID()==startNid), LPP);
-        LLPPs.push_back(LPP);
-        UsedNums.Add(k);
-        // update startN for search following edge
-        if( aN1->GetID() == startNid ) startNid = aN2->GetID();
-        else startNid = aN1->GetID();
-        break;
-      }
-    }
-    list< list<SMESH_MeshEditor_PathPoint> >::iterator itLLPP = LLPPs.begin();
-    list<SMESH_MeshEditor_PathPoint> firstList = *itLLPP;
-    list<SMESH_MeshEditor_PathPoint>::iterator itPP = firstList.begin();
-    for(; itPP!=firstList.end(); itPP++) {
-      fullList.push_back( *itPP );
-    }
-    SMESH_MeshEditor_PathPoint PP1 = fullList.back();
-    fullList.pop_back();
-    itLLPP++;
-    for(; itLLPP!=LLPPs.end(); itLLPP++) {
-      list<SMESH_MeshEditor_PathPoint> currList = *itLLPP;
-      itPP = currList.begin();
-      SMESH_MeshEditor_PathPoint PP2 = currList.front();
-      gp_Dir D1 = PP1.Tangent();
-      gp_Dir D2 = PP2.Tangent();
-      gp_Dir Dnew( gp_Vec( (D1.X()+D2.X())/2, (D1.Y()+D2.Y())/2,
-                           (D1.Z()+D2.Z())/2 ) );
-      PP1.SetTangent(Dnew);
-      fullList.push_back(PP1);
-      itPP++;
-      for(; itPP!=firstList.end(); itPP++) {
-        fullList.push_back( *itPP );
-      }
-      PP1 = fullList.back();
-      fullList.pop_back();
-    }
-    // if wire not closed
-    fullList.push_back(PP1);
-    // else ???
-  }
-  else {
-    return EXTR_BAD_PATH_SHAPE;
-  }
-
-  return makeExtrElements(theElements, fullList, theHasAngles, theAngles, theLinearVariation,
-                          theHasRefPoint, theRefPoint, theMakeGroups);
-}
-
-
-//=======================================================================
-//function : ExtrusionAlongTrack
-//purpose  :
-//=======================================================================
-SMESH_MeshEditor::Extrusion_Error
-SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
-                                       SMESH_Mesh*          theTrack,
-                                       const SMDS_MeshNode* theN1,
-                                       const bool           theHasAngles,
-                                       list<double>&        theAngles,
-                                       const bool           theLinearVariation,
-                                       const bool           theHasRefPoint,
-                                       const gp_Pnt&        theRefPoint,
-                                       const bool           theMakeGroups)
-{
-  ClearLastCreated();
-
-  int aNbE;
-  std::list<double> aPrms;
-  TIDSortedElemSet::iterator itElem;
-
-  gp_XYZ aGC;
-  TopoDS_Edge aTrackEdge;
-  TopoDS_Vertex aV1, aV2;
-
-  SMDS_ElemIteratorPtr aItE;
-  SMDS_NodeIteratorPtr aItN;
-  SMDSAbs_ElementType aTypeE;
+  ASSERT( theTrackMesh );
+  if ( ! theTrackIterator || !theTrackIterator->more() )
+    return EXTR_NO_ELEMENTS;
 
-  TNodeOfNodeListMap mapNewNodes;
+  // 2. Get ordered nodes
+  SMESH_MeshAlgos::TElemGroupVector branchEdges;
+  SMESH_MeshAlgos::TNodeGroupVector branchNods;
+  SMESH_MeshAlgos::Get1DBranches( theTrackIterator, branchEdges, branchNods, theN1 );
+  if ( branchEdges.empty() )
+    return EXTR_PATH_NOT_EDGE;
 
-  // 1. Check data
-  aNbE = theElements[0].size() + theElements[1].size();
-  // nothing to do
-  if ( !aNbE )
-    return EXTR_NO_ELEMENTS;
+  if ( branchEdges.size() > 1 )
+    return EXTR_BAD_PATH_SHAPE;
 
-  // 1.1 Track Pattern
-  ASSERT( theTrack );
-
-  SMESHDS_Mesh* pMeshDS = theTrack->GetMeshDS();
-
-  aItE = pMeshDS->elementsIterator();
-  while ( aItE->more() ) {
-    const SMDS_MeshElement* pE = aItE->next();
-    aTypeE = pE->GetType();
-    // Pattern must contain links only
-    if ( aTypeE != SMDSAbs_Edge )
-      return EXTR_PATH_NOT_EDGE;
-  }
-
-  list<SMESH_MeshEditor_PathPoint> fullList;
-
-  const TopoDS_Shape& aS = theTrack->GetShapeToMesh();
-
-  if ( !theTrack->HasShapeToMesh() ) {
-    //Mesh without shape
-    const SMDS_MeshNode* currentNode = NULL;
-    const SMDS_MeshNode* prevNode = theN1;
-    std::vector<const SMDS_MeshNode*> aNodesList;
-    aNodesList.push_back(theN1);
-    int nbEdges = 0, conn=0;
-    const SMDS_MeshElement* prevElem = NULL;
-    const SMDS_MeshElement* currentElem = NULL;
-    int totalNbEdges = theTrack->NbEdges();
-    SMDS_ElemIteratorPtr nIt;
-
-    //check start node
-    if( !theTrack->GetMeshDS()->Contains( theN1 )) {
-      return EXTR_BAD_STARTING_NODE;
-    }
-
-    conn = nbEdgeConnectivity(theN1);
-    if( conn != 1 )
-      return EXTR_PATH_NOT_EDGE;
-
-    aItE = theN1->GetInverseElementIterator();
-    prevElem = aItE->next();
-    currentElem = prevElem;
-    //Get all nodes
-    if(totalNbEdges == 1 ) {
-      nIt = currentElem->nodesIterator();
-      currentNode = static_cast<const SMDS_MeshNode*>(nIt->next());
-      if(currentNode == prevNode)
-        currentNode = static_cast<const SMDS_MeshNode*>(nIt->next());
-      aNodesList.push_back(currentNode);
-    } else {
-      nIt = currentElem->nodesIterator();
-      while( nIt->more() ) {
-        currentNode = static_cast<const SMDS_MeshNode*>(nIt->next());
-        if(currentNode == prevNode)
-          currentNode = static_cast<const SMDS_MeshNode*>(nIt->next());
-        aNodesList.push_back(currentNode);
-
-        //case of the closed mesh
-        if(currentNode == theN1) {
-          nbEdges++;
-          break;
-        }
+  std::vector< const SMDS_MeshNode* >&    pathNodes = branchNods[0];
+  std::vector< const SMDS_MeshElement* >& pathEdges = branchEdges[0];
+  if ( pathNodes[0] != theN1 && pathNodes[1] != theN1 )
+    return EXTR_BAD_STARTING_NODE;
 
-        conn = nbEdgeConnectivity(currentNode);
-        if(conn > 2) {
-          return EXTR_PATH_NOT_EDGE;
-        }else if( conn == 1 && nbEdges > 0 ) {
-          //End of the path
-          nbEdges++;
-          break;
-        }else {
-          prevNode = currentNode;
-          aItE = currentNode->GetInverseElementIterator();
-          currentElem = aItE->next();
-          if( currentElem  == prevElem)
-            currentElem = aItE->next();
-          nIt = currentElem->nodesIterator();
-          prevElem = currentElem;
-          nbEdges++;
-        }
-      }
-    }
-
-    if(nbEdges != totalNbEdges)
-      return EXTR_PATH_NOT_EDGE;
-
-    TopTools_SequenceOfShape Edges;
-    list< list<SMESH_MeshEditor_PathPoint> > LLPPs;
-    int startNid = theN1->GetID();
-    for ( size_t i = 1; i < aNodesList.size(); i++ )
-    {
-      gp_Pnt     p1 = SMESH_NodeXYZ( aNodesList[i-1] );
-      gp_Pnt     p2 = SMESH_NodeXYZ( aNodesList[i] );
-      TopoDS_Edge e = BRepBuilderAPI_MakeEdge( p1, p2 );
-      list<SMESH_MeshEditor_PathPoint> LPP;
-      aPrms.clear();
-      makeEdgePathPoints(aPrms, e, (aNodesList[i-1]->GetID()==startNid), LPP);
-      LLPPs.push_back(LPP);
-      if ( aNodesList[i-1]->GetID() == startNid ) startNid = aNodesList[i  ]->GetID();
-      else                                        startNid = aNodesList[i-1]->GetID();
-    }
-
-    list< list<SMESH_MeshEditor_PathPoint> >::iterator itLLPP = LLPPs.begin();
-    list<SMESH_MeshEditor_PathPoint> firstList = *itLLPP;
-    list<SMESH_MeshEditor_PathPoint>::iterator itPP = firstList.begin();
-    for(; itPP!=firstList.end(); itPP++) {
-      fullList.push_back( *itPP );
-    }
-
-    SMESH_MeshEditor_PathPoint PP1 = fullList.back();
-    SMESH_MeshEditor_PathPoint PP2;
-    fullList.pop_back();
-    itLLPP++;
-    for(; itLLPP!=LLPPs.end(); itLLPP++) {
-      list<SMESH_MeshEditor_PathPoint> currList = *itLLPP;
-      itPP = currList.begin();
-      PP2 = currList.front();
-      gp_Dir D1 = PP1.Tangent();
-      gp_Dir D2 = PP2.Tangent();
-      gp_Dir Dnew( 0.5 * ( D1.XYZ() + D2.XYZ() ));
-      PP1.SetTangent(Dnew);
-      fullList.push_back(PP1);
-      itPP++;
-      for(; itPP!=currList.end(); itPP++) {
-        fullList.push_back( *itPP );
-      }
-      PP1 = fullList.back();
-      fullList.pop_back();
-    }
-    fullList.push_back(PP1);
-
-  } // Sub-shape for the Pattern must be an Edge or Wire
-  else if ( aS.ShapeType() == TopAbs_EDGE )
-  {
-    aTrackEdge = TopoDS::Edge( aS );
-    // the Edge must not be degenerated
-    if ( SMESH_Algo::isDegenerated( aTrackEdge ) )
-      return EXTR_BAD_PATH_SHAPE;
-    TopExp::Vertices( aTrackEdge, aV1, aV2 );
-    const SMDS_MeshNode* aN1 = SMESH_Algo::VertexNode( aV1, pMeshDS );
-    const SMDS_MeshNode* aN2 = SMESH_Algo::VertexNode( aV2, pMeshDS );
-    // starting node must be aN1 or aN2
-    if ( !( aN1 == theN1 || aN2 == theN1 ) )
-      return EXTR_BAD_STARTING_NODE;
-    aItN = pMeshDS->nodesIterator();
-    while ( aItN->more() ) {
-      const SMDS_MeshNode* pNode = aItN->next();
-      if( pNode==aN1 || pNode==aN2 ) continue;
-      SMDS_EdgePositionPtr pEPos = pNode->GetPosition();
-      double aT = pEPos->GetUParameter();
-      aPrms.push_back( aT );
-    }
-    //Extrusion_Error err =
-    makeEdgePathPoints(aPrms, aTrackEdge, (aN1==theN1), fullList);
-  }
-  else if( aS.ShapeType() == TopAbs_WIRE ) {
-    list< SMESH_subMesh* > LSM;
-    TopTools_SequenceOfShape Edges;
-    TopExp_Explorer eExp(aS, TopAbs_EDGE);
-    for(; eExp.More(); eExp.Next()) {
-      TopoDS_Edge E = TopoDS::Edge( eExp.Current() );
-      if( SMESH_Algo::isDegenerated(E) ) continue;
-      SMESH_subMesh* SM = theTrack->GetSubMesh(E);
-      if(SM) {
-        LSM.push_back(SM);
-        Edges.Append(E);
-      }
-    }
-    list< list<SMESH_MeshEditor_PathPoint> > LLPPs;
-    TopoDS_Vertex aVprev;
-    TColStd_MapOfInteger UsedNums;
-    int NbEdges = Edges.Length();
-    int i = 1;
-    for(; i<=NbEdges; i++) {
-      int k = 0;
-      list< SMESH_subMesh* >::iterator itLSM = LSM.begin();
-      for(; itLSM!=LSM.end(); itLSM++) {
-        k++;
-        if(UsedNums.Contains(k)) continue;
-        aTrackEdge = TopoDS::Edge( Edges.Value(k) );
-        SMESH_subMesh* locTrack = *itLSM;
-        SMESHDS_SubMesh* locMeshDS = locTrack->GetSubMeshDS();
-        TopExp::Vertices( aTrackEdge, aV1, aV2 );
-        bool aN1isOK = false, aN2isOK = false;
-        if ( aVprev.IsNull() ) {
-          // if previous vertex is not yet defined, it means that we in the beginning of wire
-          // and we have to find initial vertex corresponding to starting node theN1
-          const SMDS_MeshNode* aN1 = SMESH_Algo::VertexNode( aV1, pMeshDS );
-          const SMDS_MeshNode* aN2 = SMESH_Algo::VertexNode( aV2, pMeshDS );
-          // starting node must be aN1 or aN2
-          aN1isOK = ( aN1 && aN1 == theN1 );
-          aN2isOK = ( aN2 && aN2 == theN1 );
-        }
-        else {
-          // we have specified ending vertex of the previous edge on the previous iteration
-          // and we have just to check that it corresponds to any vertex in current segment
-          aN1isOK = aVprev.IsSame( aV1 );
-          aN2isOK = aVprev.IsSame( aV2 );
-        }
-        if ( !aN1isOK && !aN2isOK ) continue;
-        // 2. Collect parameters on the track edge
-        aPrms.clear();
-        aItN = locMeshDS->GetNodes();
-        while ( aItN->more() ) {
-          const SMDS_MeshNode*  pNode = aItN->next();
-          SMDS_EdgePositionPtr pEPos = pNode->GetPosition();
-          double aT = pEPos->GetUParameter();
-          aPrms.push_back( aT );
-        }
-        list<SMESH_MeshEditor_PathPoint> LPP;
-        //Extrusion_Error err =
-        makeEdgePathPoints(aPrms, aTrackEdge, aN1isOK, LPP);
-        LLPPs.push_back(LPP);
-        UsedNums.Add(k);
-        // update startN for search following edge
-        if ( aN1isOK ) aVprev = aV2;
-        else           aVprev = aV1;
-        break;
+  if ( theTrackMesh->NbEdges( ORDER_QUADRATIC ) > 0 )
+  {
+    // add medium nodes to pathNodes
+    std::vector< const SMDS_MeshNode* >    pathNodes2;
+    std::vector< const SMDS_MeshElement* > pathEdges2;
+    pathNodes2.reserve( pathNodes.size() * 2 );
+    pathEdges2.reserve( pathEdges.size() * 2 );
+    for ( size_t i = 0; i < pathEdges.size(); ++i )
+    {
+      pathNodes2.push_back( pathNodes[i] );
+      pathEdges2.push_back( pathEdges[i] );
+      if ( pathEdges[i]->IsQuadratic() )
+      {
+        pathNodes2.push_back( pathEdges[i]->GetNode(2) );
+        pathEdges2.push_back( pathEdges[i] );
       }
     }
-    list< list<SMESH_MeshEditor_PathPoint> >::iterator itLLPP = LLPPs.begin();
-    list<SMESH_MeshEditor_PathPoint>& firstList = *itLLPP;
-    fullList.splice( fullList.end(), firstList );
-
-    SMESH_MeshEditor_PathPoint PP1 = fullList.back();
-    fullList.pop_back();
-    itLLPP++;
-    for(; itLLPP!=LLPPs.end(); itLLPP++) {
-      list<SMESH_MeshEditor_PathPoint>& currList = *itLLPP;
-      SMESH_MeshEditor_PathPoint PP2 = currList.front();
-      gp_Dir D1 = PP1.Tangent();
-      gp_Dir D2 = PP2.Tangent();
-      gp_Dir Dnew( D1.XYZ() + D2.XYZ() );
-      PP1.SetTangent(Dnew);
-      fullList.push_back(PP1);
-      fullList.splice( fullList.end(), currList, ++currList.begin(), currList.end() );
-      PP1 = fullList.back();
-      fullList.pop_back();
-    }
-    // if wire not closed
-    fullList.push_back(PP1);
-    // else ???
-  }
-  else {
-    return EXTR_BAD_PATH_SHAPE;
+    pathNodes2.push_back( pathNodes.back() );
+    pathEdges.swap( pathEdges2 );
+    pathNodes.swap( pathNodes2 );
   }
 
-  return makeExtrElements(theElements, fullList, theHasAngles, theAngles, theLinearVariation,
-                          theHasRefPoint, theRefPoint, theMakeGroups);
-}
+  // 3. Get path data at pathNodes
 
+  std::vector< ExtrusParam::PathPoint > points( pathNodes.size() );
 
-//=======================================================================
-//function : makeEdgePathPoints
-//purpose  : auxiliary for ExtrusionAlongTrack
-//=======================================================================
-SMESH_MeshEditor::Extrusion_Error
-SMESH_MeshEditor::makeEdgePathPoints(std::list<double>&                aPrms,
-                                     const TopoDS_Edge&                aTrackEdge,
-                                     bool                              FirstIsStart,
-                                     list<SMESH_MeshEditor_PathPoint>& LPP)
-{
-  Standard_Real aTx1, aTx2, aL2, aTolVec, aTolVec2;
-  aTolVec=1.e-7;
-  aTolVec2=aTolVec*aTolVec;
-  double aT1, aT2;
-  TopoDS_Vertex aV1, aV2;
-  TopExp::Vertices( aTrackEdge, aV1, aV2 );
-  aT1=BRep_Tool::Parameter( aV1, aTrackEdge );
-  aT2=BRep_Tool::Parameter( aV2, aTrackEdge );
-  // 2. Collect parameters on the track edge
-  aPrms.push_front( aT1 );
-  aPrms.push_back( aT2 );
-  // sort parameters
-  aPrms.sort();
-  if( FirstIsStart ) {
-    if ( aT1 > aT2 ) {
-      aPrms.reverse();
-    }
-  }
-  else {
-    if ( aT2 > aT1 ) {
-      aPrms.reverse();
-    }
-  }
-  // 3. Path Points
-  SMESH_MeshEditor_PathPoint aPP;
-  Handle(Geom_Curve) aC3D = BRep_Tool::Curve( aTrackEdge, aTx1, aTx2 );
-  std::list<double>::iterator aItD = aPrms.begin();
-  for(; aItD != aPrms.end(); ++aItD) {
-    double aT = *aItD;
-    gp_Pnt aP3D;
-    gp_Vec aVec;
-    aC3D->D1( aT, aP3D, aVec );
-    aL2 = aVec.SquareMagnitude();
-    if ( aL2 < aTolVec2 )
-      return EXTR_CANT_GET_TANGENT;
-    gp_Dir aTgt( FirstIsStart ? aVec : -aVec );
-    aPP.SetPnt( aP3D );
-    aPP.SetTangent( aTgt );
-    aPP.SetParameter( aT );
-    LPP.push_back(aPP);
-  }
-  return EXTR_OK;
-}
+  if ( theAngleVariation )
+    linearAngleVariation( points.size()-1, theAngles );
+  if ( theScaleVariation )
+    linearScaleVariation( points.size()-1, theScales );
 
+  theAngles.push_front( 0 ); // for the 1st point that is not transformed
+  std::list<double>::iterator angle = theAngles.begin();
 
-//=======================================================================
-//function : makeExtrElements
-//purpose  : auxiliary for ExtrusionAlongTrack
-//=======================================================================
-SMESH_MeshEditor::Extrusion_Error
-SMESH_MeshEditor::makeExtrElements(TIDSortedElemSet                  theElemSets[2],
-                                   list<SMESH_MeshEditor_PathPoint>& fullList,
-                                   const bool                        theHasAngles,
-                                   list<double>&                     theAngles,
-                                   const bool                        theLinearVariation,
-                                   const bool                        theHasRefPoint,
-                                   const gp_Pnt&                     theRefPoint,
-                                   const bool                        theMakeGroups)
-{
-  const int aNbTP = fullList.size();
+  SMESHDS_Mesh* pathMeshDS = theTrackMesh->GetMeshDS();
 
-  // Angles
-  if( theHasAngles && !theAngles.empty() && theLinearVariation )
-    linearAngleVariation(aNbTP-1, theAngles);
+  std::map< int, double > edgeID2OriFactor; // orientation of EDGEs
+  std::map< int, double >::iterator id2factor;
+  SMESH_MesherHelper pathHelper( *theTrackMesh );
+  gp_Pnt p; gp_Vec tangent;
+  const double tol2 = gp::Resolution() * gp::Resolution();
 
-  // fill vector of path points with angles
-  vector<SMESH_MeshEditor_PathPoint> aPPs;
-  list<SMESH_MeshEditor_PathPoint>::iterator itPP = fullList.begin();
-  list<double>::iterator                 itAngles = theAngles.begin();
-  aPPs.push_back( *itPP++ );
-  for( ; itPP != fullList.end(); itPP++) {
-    aPPs.push_back( *itPP );
-    if ( theHasAngles && itAngles != theAngles.end() )
-      aPPs.back().SetAngle( *itAngles++ );
-  }
+  for ( size_t i = 0; i < pathNodes.size(); ++i )
+  {
+    ExtrusParam::PathPoint & point = points[ i ];
 
-  TNodeOfNodeListMap   mapNewNodes;
-  TElemOfVecOfNnlmiMap mapElemNewNodes;
-  TTElemOfElemListMap  newElemsMap;
-  TIDSortedElemSet::iterator itElem;
-  // source elements for each generated one
-  SMESH_SequenceOfElemPtr srcElems, srcNodes;
+    point.myPnt = SMESH_NodeXYZ( pathNodes[ i ]);
 
-  // 3. Center of rotation aV0
-  gp_Pnt aV0 = theRefPoint;
-  if ( !theHasRefPoint )
-  {
-    gp_XYZ aGC( 0.,0.,0. );
-    TIDSortedElemSet newNodes;
+    if ( angle != theAngles.end() )
+      point.myAngle = *angle++;
 
-    for ( int is2ndSet = 0; is2ndSet < 2; ++is2ndSet )
+    tangent.SetCoord( 0,0,0 );
+    const int          shapeID = pathNodes[ i ]->GetShapeID();
+    const TopoDS_Shape&  shape = pathMeshDS->IndexToShape( shapeID );
+    TopAbs_ShapeEnum shapeType = shape.IsNull() ? TopAbs_SHAPE : shape.ShapeType();
+    switch ( shapeType )
+    {
+    case TopAbs_EDGE:
     {
-      TIDSortedElemSet& theElements = theElemSets[ is2ndSet ];
-      itElem = theElements.begin();
-      for ( ; itElem != theElements.end(); itElem++ )
+      TopoDS_Edge edge = TopoDS::Edge( shape );
+      id2factor = edgeID2OriFactor.insert( std::make_pair( shapeID, 0 )).first;
+      if ( id2factor->second == 0 )
       {
-        const SMDS_MeshElement* elem = *itElem;
-        SMDS_ElemIteratorPtr     itN = elem->nodesIterator();
-        while ( itN->more() ) {
-          const SMDS_MeshElement* node = itN->next();
-          if ( newNodes.insert( node ).second )
-            aGC += SMESH_NodeXYZ( node );
-        }
+        if ( i ) id2factor->second = getOriFactor( edge, pathNodes[i-1], pathNodes[i], pathHelper );
+        else     id2factor->second = getOriFactor( edge, pathNodes[i], pathNodes[i+1], pathHelper );
       }
+      double u = pathHelper.GetNodeU( edge, pathNodes[i] ), u0, u1;
+      Handle(Geom_Curve) curve = BRep_Tool::Curve( edge, u0, u1 );
+      curve->D1( u, p, tangent );
+      tangent *= id2factor->second;
+      break;
     }
-    aGC /= newNodes.size();
-    aV0.SetXYZ( aGC );
-  } // if (!theHasRefPoint) {
-
-  // 4. Processing the elements
-  SMESHDS_Mesh* aMesh = GetMeshDS();
-  list<const SMDS_MeshNode*> emptyList;
-
-  setElemsFirst( theElemSets );
-  for ( int is2ndSet = 0; is2ndSet < 2; ++is2ndSet )
-  {
-    TIDSortedElemSet& theElements = theElemSets[ is2ndSet ];
-    for ( itElem = theElements.begin(); itElem != theElements.end(); itElem++ )
+    case TopAbs_VERTEX:
     {
-      const SMDS_MeshElement* elem = *itElem;
-
-      vector<TNodeOfNodeListMapItr> & newNodesItVec = mapElemNewNodes[ elem ];
-      newNodesItVec.reserve( elem->NbNodes() );
-
-      // loop on elem nodes
-      int nodeIndex = -1;
-      SMDS_ElemIteratorPtr itN = elem->nodesIterator();
-      while ( itN->more() )
+      int nbEdges = 0;
+      PShapeIteratorPtr shapeIt = pathHelper.GetAncestors( shape, *theTrackMesh, TopAbs_EDGE );
+      while ( const TopoDS_Shape* edgePtr = shapeIt->next() )
       {
-        ++nodeIndex;
-        // check if a node has been already processed
-        const SMDS_MeshNode* node = cast2Node( itN->next() );
-        TNodeOfNodeListMap::iterator nIt = mapNewNodes.insert( make_pair( node, emptyList )).first;
-        list<const SMDS_MeshNode*>& listNewNodes = nIt->second;
-        if ( listNewNodes.empty() )
+        int edgeID = pathMeshDS->ShapeToIndex( *edgePtr );
+        for ( int di = -1; di <= 0; ++di )
         {
-          // make new nodes
-          Standard_Real aAngle1x, aAngleT1T0, aTolAng;
-          gp_Pnt aP0x, aP1x, aPN0, aPN1, aV0x, aV1x;
-          gp_Ax1 anAx1, anAxT1T0;
-          gp_Dir aDT1x, aDT0x, aDT1T0;
-
-          aTolAng=1.e-4;
-
-          aV0x = aV0;
-          aPN0 = SMESH_NodeXYZ( node );
-
-          const SMESH_MeshEditor_PathPoint& aPP0 = aPPs[0];
-          aP0x = aPP0.Pnt();
-          aDT0x= aPP0.Tangent();
-
-          for ( int j = 1; j < aNbTP; ++j ) {
-            const SMESH_MeshEditor_PathPoint& aPP1 = aPPs[j];
-            aP1x     = aPP1.Pnt();
-            aDT1x    = aPP1.Tangent();
-            aAngle1x = aPP1.Angle();
-
-            gp_Trsf aTrsf, aTrsfRot, aTrsfRotT1T0;
-            // Translation
-            gp_Vec aV01x( aP0x, aP1x );
-            aTrsf.SetTranslation( aV01x );
-
-            // translated point
-            aV1x = aV0x.Transformed( aTrsf );
-            aPN1 = aPN0.Transformed( aTrsf );
-
-            // rotation 1 [ T1,T0 ]
-            aAngleT1T0=-aDT1x.Angle( aDT0x );
-            if (fabs(aAngleT1T0) > aTolAng)
+          size_t j = i + di;
+          if ( j < pathEdges.size() && edgeID == pathEdges[ j ]->GetShapeID() )
+          {
+            TopoDS_Edge edge = TopoDS::Edge( *edgePtr );
+            id2factor = edgeID2OriFactor.insert( std::make_pair( edgeID, 0 )).first;
+            if ( id2factor->second == 0 )
             {
-              aDT1T0=aDT1x^aDT0x;
-              anAxT1T0.SetLocation( aV1x );
-              anAxT1T0.SetDirection( aDT1T0 );
-              aTrsfRotT1T0.SetRotation( anAxT1T0, aAngleT1T0 );
-
-              aPN1 = aPN1.Transformed( aTrsfRotT1T0 );
-            }
-
-            // rotation 2
-            if ( theHasAngles ) {
-              anAx1.SetLocation( aV1x );
-              anAx1.SetDirection( aDT1x );
-              aTrsfRot.SetRotation( anAx1, aAngle1x );
-
-              aPN1 = aPN1.Transformed( aTrsfRot );
+              if ( j < i )
+                id2factor->second = getOriFactor( edge, pathNodes[i-1], pathNodes[i], pathHelper );
+              else
+                id2factor->second = getOriFactor( edge, pathNodes[i], pathNodes[i+1], pathHelper );
             }
-
-            // make new node
-            if ( elem->IsQuadratic() && !elem->IsMediumNode(node) )
+            double u = pathHelper.GetNodeU( edge, pathNodes[i] ), u0, u1;
+            Handle(Geom_Curve) curve = BRep_Tool::Curve( edge, u0, u1 );
+            gp_Vec du;
+            curve->D1( u, p, du );
+            double size2 = du.SquareMagnitude();
+            if ( du.SquareMagnitude() > tol2 )
             {
-              // create additional node
-              gp_XYZ midP = 0.5 * ( aPN1.XYZ() + aPN0.XYZ() );
-              const SMDS_MeshNode* newNode = aMesh->AddNode( midP.X(), midP.Y(), midP.Z() );
-              myLastCreatedNodes.push_back(newNode);
-              srcNodes.push_back( node );
-              listNewNodes.push_back( newNode );
+              tangent += du.Divided( Sqrt( size2 )) * id2factor->second;
+              nbEdges++;
             }
-            const SMDS_MeshNode* newNode = aMesh->AddNode( aPN1.X(), aPN1.Y(), aPN1.Z() );
-            myLastCreatedNodes.push_back(newNode);
-            srcNodes.push_back( node );
-            listNewNodes.push_back( newNode );
-
-            aPN0 = aPN1;
-            aP0x = aP1x;
-            aV0x = aV1x;
-            aDT0x = aDT1x;
+            break;
           }
         }
-        else if( elem->IsQuadratic() && !elem->IsMediumNode(node) )
+      }
+      if ( nbEdges > 0 )
+        break;
+    }
+    default:
+    {
+      for ( int di = -1; di <= 1; di += 2 )
+      {
+        size_t j = i + di;
+        if ( j < pathNodes.size() )
         {
-          // if current elem is quadratic and current node is not medium
-          // we have to check - may be it is needed to insert additional nodes
-          list< const SMDS_MeshNode* > & listNewNodes = nIt->second;
-          if ((int) listNewNodes.size() == aNbTP-1 )
-          {
-            vector<const SMDS_MeshNode*> aNodes(2*(aNbTP-1));
-            gp_XYZ P(node->X(), node->Y(), node->Z());
-            list< const SMDS_MeshNode* >::iterator it = listNewNodes.begin();
-            int i;
-            for(i=0; i<aNbTP-1; i++) {
-              const SMDS_MeshNode* N = *it;
-              double x = ( N->X() + P.X() )/2.;
-              double y = ( N->Y() + P.Y() )/2.;
-              double z = ( N->Z() + P.Z() )/2.;
-              const SMDS_MeshNode* newN = aMesh->AddNode(x,y,z);
-              srcNodes.push_back( node );
-              myLastCreatedNodes.push_back(newN);
-              aNodes[2*i] = newN;
-              aNodes[2*i+1] = N;
-              P = gp_XYZ(N->X(),N->Y(),N->Z());
-            }
-            listNewNodes.clear();
-            for(i=0; i<2*(aNbTP-1); i++) {
-              listNewNodes.push_back(aNodes[i]);
-            }
-          }
+          gp_Vec dir( point.myPnt, SMESH_NodeXYZ( pathNodes[ j ]));
+          double size2 = dir.SquareMagnitude();
+          if ( size2 > tol2 )
+            tangent += dir.Divided( Sqrt( size2 )) * di;
         }
-
-        newNodesItVec.push_back( nIt );
       }
-
-      // make new elements
-      sweepElement( elem, newNodesItVec, newElemsMap[elem], aNbTP-1, srcElems );
     }
-  }
+    } // switch ( shapeType )
 
-  makeWalls( mapNewNodes, newElemsMap, mapElemNewNodes, theElemSets[0], aNbTP-1, srcElems );
+    if ( tangent.SquareMagnitude() < tol2 )
+      return EXTR_CANT_GET_TANGENT;
 
-  if ( theMakeGroups )
-    generateGroups( srcNodes, srcElems, "extruded");
+    point.myTgt = tangent;
+
+  } // loop on pathNodes
+
+
+  ExtrusParam nodeMaker( points, theRefPoint, theScales, theMakeGroups );
+  TTElemOfElemListMap newElemsMap;
+
+  ExtrusionSweep( theElements, nodeMaker, newElemsMap );
 
   return EXTR_OK;
 }
 
-
 //=======================================================================
 //function : linearAngleVariation
 //purpose  : spread values over nbSteps
@@ -6490,6 +6098,33 @@ void SMESH_MeshEditor::linearAngleVariation(const int     nbSteps,
   }
 }
 
+//=======================================================================
+//function : linearScaleVariation
+//purpose  : spread values over nbSteps 
+//=======================================================================
+
+void SMESH_MeshEditor::linearScaleVariation(const int          theNbSteps,
+                                            std::list<double>& theScales)
+{
+  int nbScales = theScales.size();
+  std::vector<double> myScales;
+  myScales.reserve( theNbSteps );
+  std::list<double>::const_iterator scale = theScales.begin();
+  double prevScale = 1.0;
+  for ( int iSc = 1; scale != theScales.end(); ++scale, ++iSc )
+  {
+    int      iStep = int( iSc / double( nbScales ) * theNbSteps + 0.5 );
+    int    stDelta = Max( 1, iStep - myScales.size());
+    double scDelta = ( *scale - prevScale ) / stDelta;
+    for ( int iStep = 0; iStep < stDelta; ++iStep )
+    {
+      myScales.push_back( prevScale + scDelta );
+      prevScale = myScales.back();
+    }
+    prevScale = *scale;
+  }
+  theScales.assign( myScales.begin(), myScales.end() );
+}
 
 //================================================================================
 /*!
index 221a78d46494c1bb01334b345fe1d38bfac87948..de89a3c4eb382abca5689356f2c0b2ccc6454dd7 100644 (file)
@@ -297,6 +297,7 @@ public:
    * USE_INPUT_ELEMS_ONLY: to use only input elements to compute extrusion direction
    *                       for ExtrusionByNormal()
    * SCALE_LINEAR_VARIATION: to make linear variation of scale factors
+   * ANGLE_LINEAR_VARIATION: to make linear variation of angles
    */
   enum ExtrusionFlags {
     EXTRUSION_FLAG_BOUNDARY = 0x01,
@@ -304,7 +305,8 @@ public:
     EXTRUSION_FLAG_GROUPS = 0x04,
     EXTRUSION_FLAG_BY_AVG_NORMAL = 0x08,
     EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY = 0x10,
-    EXTRUSION_FLAG_SCALE_LINEAR_VARIATION = 0x20
+    EXTRUSION_FLAG_SCALE_LINEAR_VARIATION = 0x20,
+    EXTRUSION_FLAG_ANGLE_LINEAR_VARIATION = 0x40
   };
 
   /*!
@@ -312,24 +314,20 @@ public:
    */
   class SMESH_EXPORT ExtrusParam
   {
-    gp_Dir                          myDir;   // direction of extrusion
-    Handle(TColStd_HSequenceOfReal) mySteps; // magnitudes for each step
-    std::vector<double>             myScales, myMediumScales;// scale factors
-    gp_XYZ                          myBaseP; // scaling center
-    SMESH_SequenceOfNode            myNodes; // nodes for using in sewing
-    int                             myFlags; // see ExtrusionFlags
-    double                          myTolerance; // tolerance for sewing nodes
-    const TIDSortedElemSet*         myElemsToUse; // elements to use for extrusion by normal
-
-    int (ExtrusParam::*myMakeNodesFun)(SMESHDS_Mesh*                     mesh,
-                                       const SMDS_MeshNode*              srcNode,
-                                       std::list<const SMDS_MeshNode*> & newNodes,
-                                       const bool                        makeMediumNodes);
-
   public:
+    //! Point on extrusion path
+    struct PathPoint
+    {
+      gp_Pnt myPnt;
+      gp_Dir myTgt;
+      double myAngle, myScale;
+      PathPoint(): myPnt(99., 99., 99.), myTgt(1.,0.,0.), myAngle(0), myScale(0) {}
+    };
+
     ExtrusParam( const gp_Vec&                   theStep,
                  const int                       theNbSteps,
                  const std::list<double>&        theScales,
+                 const std::list<double>&        theAngles,
                  const gp_XYZ*                   theBaseP,
                  const int                       theFlags = 0,
                  const double                    theTolerance = 1e-6);
@@ -341,15 +339,21 @@ public:
                  const int                       theNbSteps,
                  const int                       theFlags,
                  const int                       theDim); // for extrusion by normal
+    ExtrusParam( const std::vector< PathPoint >& thePoints,
+                 const gp_Pnt*                   theBaseP,
+                 const std::list<double>&        theScales,
+                 const bool                      theMakeGroups); // for extrusion along path
 
     SMESH_SequenceOfNode& ChangeNodes() { return myNodes; }
     int& Flags()                   { return myFlags; }
     bool ToMakeBoundary()    const { return myFlags & EXTRUSION_FLAG_BOUNDARY; }
     bool ToMakeGroups()      const { return myFlags & EXTRUSION_FLAG_GROUPS; }
     bool ToUseInpElemsOnly() const { return myFlags & EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY; }
-    bool IsLinearVariation() const { return myFlags & EXTRUSION_FLAG_SCALE_LINEAR_VARIATION; }
-    int  NbSteps()           const { return mySteps->Length(); }
-
+    bool IsScaleVariation()  const { return myFlags & EXTRUSION_FLAG_SCALE_LINEAR_VARIATION; }
+    bool IsAngleVariation()  const { return myFlags & EXTRUSION_FLAG_ANGLE_LINEAR_VARIATION; }
+    int  NbSteps()           const {
+      return mySteps.IsNull() ? myPathPoints.size() - 1: mySteps->Length();
+    }
     // stores elements to use for extrusion by normal, depending on
     // state of EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY flag;
     // define myBaseP for scaling
@@ -365,6 +369,20 @@ public:
     }
   private:
 
+    gp_Dir                          myDir;   // direction of extrusion
+    Handle(TColStd_HSequenceOfReal) mySteps; // magnitudes for each step
+    std::vector<double>             myScales;// scale factors
+    std::vector<double>             myAngles;// angles
+    gp_XYZ                          myBaseP; // scaling/rotation center
+    SMESH_SequenceOfNode            myNodes; // nodes for using in sewing
+    int                             myFlags; // see ExtrusionFlags
+    double                          myTolerance; // tolerance for sewing nodes
+    const TIDSortedElemSet*         myElemsToUse; // elements to use for extrusion by normal
+    std::vector< PathPoint >        myPathPoints; // points along a path
+    int (ExtrusParam::*             myMakeNodesFun)(SMESHDS_Mesh*, // function of extrusion method
+                                                    const SMDS_MeshNode*,
+                                                    std::list<const SMDS_MeshNode*> &,
+                                                    const bool);
     int makeNodesByDir( SMESHDS_Mesh*                     mesh,
                         const SMDS_MeshNode*              srcNode,
                         std::list<const SMDS_MeshNode*> & newNodes,
@@ -381,6 +399,10 @@ public:
                              const SMDS_MeshNode*              srcNode,
                              std::list<const SMDS_MeshNode*> & newNodes,
                              const bool                        makeMediumNodes);
+    int makeNodesAlongTrack( SMESHDS_Mesh*                     mesh,
+                             const SMDS_MeshNode*              srcNode,
+                             std::list<const SMDS_MeshNode*> & newNodes,
+                             const bool                        makeMediumNodes);
     // step iteration
     void   beginStepIter( bool withMediumNodes );
     bool   moreSteps();
@@ -438,24 +460,16 @@ public:
     };
   
   Extrusion_Error ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
-                                       SMESH_subMesh*       theTrackPattern,
+                                       SMESH_Mesh*          theTrackMesh,
+                                       SMDS_ElemIteratorPtr theTrackIterator,
                                        const SMDS_MeshNode* theNodeStart,
-                                       const bool           theHasAngles,
                                        std::list<double>&   theAngles,
-                                       const bool           theLinearVariation,
-                                       const bool           theHasRefPoint,
-                                       const gp_Pnt&        theRefPoint,
+                                       const bool           theAngleVariation,
+                                       std::list<double>&   theScales,
+                                       const bool           theScaleVariation,
+                                       const gp_Pnt*        theRefPoint,
                                        const bool           theMakeGroups);
-  Extrusion_Error ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
-                                       SMESH_Mesh*          theTrackPattern,
-                                       const SMDS_MeshNode* theNodeStart,
-                                       const bool           theHasAngles,
-                                       std::list<double>&   theAngles,
-                                       const bool           theLinearVariation,
-                                       const bool           theHasRefPoint,
-                                       const gp_Pnt&        theRefPoint,
-                                       const bool           theMakeGroups);
-  // Generate new elements by extrusion of theElements along path given by theTrackPattern,
+  // Generate new elements by extrusion of theElements along path given by theTrackIterator,
   // theHasAngles are the rotation angles, base point can be given by theRefPoint
 
   PGroupIDs Transform (TIDSortedElemSet & theElements,
@@ -791,36 +805,10 @@ public:
                   const int                nbSteps,
                   SMESH_SequenceOfElemPtr& srcElements);
 
-  struct SMESH_MeshEditor_PathPoint
-  {
-    gp_Pnt myPnt;
-    gp_Dir myTgt;
-    double myAngle, myPrm;
-
-    SMESH_MeshEditor_PathPoint(): myPnt(99., 99., 99.), myTgt(1.,0.,0.), myAngle(0), myPrm(0) {}
-    void          SetPnt      (const gp_Pnt& aP3D)  { myPnt  =aP3D; }
-    void          SetTangent  (const gp_Dir& aTgt)  { myTgt  =aTgt; }
-    void          SetAngle    (const double& aBeta) { myAngle=aBeta; }
-    void          SetParameter(const double& aPrm)  { myPrm  =aPrm; }
-    const gp_Pnt& Pnt         ()const               { return myPnt; }
-    const gp_Dir& Tangent     ()const               { return myTgt; }
-    double        Angle       ()const               { return myAngle; }
-    double        Parameter   ()const               { return myPrm; }
-  };
-  Extrusion_Error makeEdgePathPoints(std::list<double>&                     aPrms,
-                                     const TopoDS_Edge&                     aTrackEdge,
-                                     bool                                   aFirstIsStart,
-                                     std::list<SMESH_MeshEditor_PathPoint>& aLPP);
-  Extrusion_Error makeExtrElements(TIDSortedElemSet                       theElements[2],
-                                   std::list<SMESH_MeshEditor_PathPoint>& theFullList,
-                                   const bool                             theHasAngles,
-                                   std::list<double>&                     theAngles,
-                                   const bool                             theLinearVariation,
-                                   const bool                             theHasRefPoint,
-                                   const gp_Pnt&                          theRefPoint,
-                                   const bool                             theMakeGroups);
   static void linearAngleVariation(const int          NbSteps,
                                    std::list<double>& theAngles);
+  static void linearScaleVariation(const int          NbSteps,
+                                   std::list<double>& theScales);
 
   bool doubleNodes( SMESHDS_Mesh*           theMeshDS,
                     const TIDSortedElemSet& theElems,
index 5925964b06d03df0014bdc17f291ce85bb60122d..eb859d61ec8ebe37e2d57de1c47daa5d2b09c64a 100644 (file)
@@ -36,6 +36,7 @@
 #include "SMESH_HypoFilter.hxx"
 #include "SMESH_Mesh.hxx"
 #include "SMESH_MeshAlgos.hxx"
+#include "SMESH_MeshEditor.hxx"
 #include "SMESH_ProxyMesh.hxx"
 #include "SMESH_subMesh.hxx"
 
@@ -73,7 +74,7 @@ using namespace std;
 
 namespace {
 
-  inline SMESH_TNodeXYZ XYZ(const SMDS_MeshNode* n) { return SMESH_TNodeXYZ(n); }
+  inline SMESH_NodeXYZ XYZ(const SMDS_MeshNode* n) { return SMESH_NodeXYZ(n); }
 
   enum { U_periodic = 1, V_periodic = 2 };
 }
@@ -1035,6 +1036,16 @@ double SMESH_MesherHelper::GetNodeU(const TopoDS_Edge&   E,
       int vertexID = n->getshapeId();
       const TopoDS_Vertex& V = TopoDS::Vertex(meshDS->IndexToShape(vertexID));
       param =  BRep_Tool::Parameter( V, E );
+
+      if ( inEdgeNode )
+      {
+        BRepAdaptor_Curve curve( E );
+        if ( curve.IsPeriodic() )
+        {
+          double uInEdge = GetNodeU( E, inEdgeNode );
+          param += ShapeAnalysis::AdjustByPeriod( param, uInEdge, curve.Period() );
+        }
+      }
     }
   }
   if ( check )
index 3b516baa01615d717c74363a5e0f0d8613acad4a..8c9aea094484e247dbeb362fb91a49e1a74b2cf9 100644 (file)
@@ -29,7 +29,8 @@
 
 #include "SMESH_SMESH.hxx"
 
-#include "SMESH_MeshEditor.hxx" // needed for many meshers
+#include "SMESH_ComputeError.hxx"
+#include "SMESH_TypeDefs.hxx"
 
 #include <Geom_Surface.hxx>
 #include <ShapeAnalysis_Surface.hxx>
@@ -44,8 +45,15 @@ class GeomAPI_ProjectPointOnCurve;
 class GeomAPI_ProjectPointOnSurf;
 class SMDS_MeshNode;
 class SMESHDS_Hypothesis;
+class SMESHDS_Mesh;
+class SMESHDS_SubMesh;
 class SMESH_Gen;
+class SMESH_Mesh;
 class SMESH_ProxyMesh;
+class SMESH_subMesh;
+class TopoDS_Edge;
+class TopoDS_Face;
+class TopoDS_Vertex;
 
 typedef std::map<SMESH_TLink, const SMDS_MeshNode*>           TLinkNodeMap;
 typedef std::map<SMESH_TLink, const SMDS_MeshNode*>::iterator ItTLinkNode;
index f032ae475df0b522a7bfba9215e39cd17377f41b..e069d62b64881f9830a0a5f139f884e252085be9 100644 (file)
@@ -38,6 +38,7 @@
 #include "SMESH_Block.hxx"
 #include "SMESH_Mesh.hxx"
 #include "SMESH_MeshAlgos.hxx"
+#include "SMESH_MeshEditor.hxx"
 #include "SMESH_MesherHelper.hxx"
 #include "SMESH_subMesh.hxx"
 
index 7a8714424974831a8fe72e7c73b9aa4a7041c9aa..3a641ec74f971d8d47603952fcc633652e79e2bc 100644 (file)
@@ -1202,7 +1202,7 @@ bool SMESHDS_Mesh::IsGroupOfSubShapes (const TopoDS_Shape& theShape) const
     return true;
 
   for ( TopoDS_Iterator it( theShape ); it.More(); it.Next() )
-    if (IsGroupOfSubShapes( it.Value() ))
+    if ( IsGroupOfSubShapes( it.Value() ))
       return true;
 
   return false;
index f6b5f80bf413c6cea63c341c0adc29891a32629f..866dd1ad2563e90cb43d3f3682a63c56c3fe870d 100644 (file)
@@ -200,6 +200,7 @@ SMESHGUI_ExtrusionAlongPathDlg::SMESHGUI_ExtrusionAlongPathDlg( SMESHGUI* theMod
   BasePointGrpLayout->addWidget(ZLab);
   BasePointGrpLayout->addWidget(ZSpin);
 
+  // Angles
   AnglesGrp = new QGroupBox(tr("SMESH_ANGLES"), GroupArguments);
   AnglesGrp->setCheckable(true);
   AnglesGrp->setChecked(false);
@@ -219,15 +220,42 @@ SMESHGUI_ExtrusionAlongPathDlg::SMESHGUI_ExtrusionAlongPathDlg( SMESHGUI* theMod
 
   LinearAnglesCheck = new QCheckBox(tr("LINEAR_ANGLES"), AnglesGrp);
 
-  // layouting
   AnglesGrpLayout->addWidget(AnglesList,        0, 0, 4, 1);
   AnglesGrpLayout->addWidget(AddAngleButton,    0, 1);
   AnglesGrpLayout->addWidget(RemoveAngleButton, 2, 1);
   AnglesGrpLayout->addWidget(AngleSpin,         0, 2);
-  AnglesGrpLayout->addWidget(LinearAnglesCheck, 4, 0);
+  AnglesGrpLayout->addWidget(LinearAnglesCheck, 4, 0, 1, 3);
   AnglesGrpLayout->setRowMinimumHeight(1, 10);
   AnglesGrpLayout->setRowStretch(3, 10);
 
+  // Scales
+  ScalesGrp = new QGroupBox(tr("SMESH_SCALES"), GroupArguments);
+  ScalesGrp->setCheckable(true);
+  ScalesGrp->setChecked(false);
+  QGridLayout* ScalesGrpLayout = new QGridLayout(ScalesGrp);
+  ScalesGrpLayout->setSpacing(SPACING); ScalesGrpLayout->setMargin(MARGIN);
+
+  ScalesList = new QListWidget(ScalesGrp);
+  ScalesList->setSelectionMode(QListWidget::ExtendedSelection);
+
+  AddScaleButton = new QToolButton(ScalesGrp);
+  AddScaleButton->setIcon(addImage);
+
+  RemoveScaleButton = new QToolButton(ScalesGrp);
+  RemoveScaleButton->setIcon(removeImage);
+
+  ScaleSpin = new SMESHGUI_SpinBox(ScalesGrp);
+
+  LinearScalesCheck = new QCheckBox(tr("LINEAR_SCALES"), ScalesGrp);
+
+  ScalesGrpLayout->addWidget(ScalesList,        0, 0, 4, 1);
+  ScalesGrpLayout->addWidget(AddScaleButton,    0, 1);
+  ScalesGrpLayout->addWidget(RemoveScaleButton, 2, 1);
+  ScalesGrpLayout->addWidget(ScaleSpin,         0, 2);
+  ScalesGrpLayout->addWidget(LinearScalesCheck, 4, 0, 1, 3);
+  ScalesGrpLayout->setRowMinimumHeight(1, 10);
+  ScalesGrpLayout->setRowStretch(3, 10);
+
   // CheckBox for groups generation
   MakeGroupsCheck = new QCheckBox(tr("SMESH_MAKE_GROUPS"), GroupArguments);
   MakeGroupsCheck->setChecked(true);
@@ -236,10 +264,11 @@ SMESHGUI_ExtrusionAlongPathDlg::SMESHGUI_ExtrusionAlongPathDlg( SMESHGUI* theMod
   myPreviewCheckBox = new QCheckBox(tr("PREVIEW"), GroupArguments);
 
   // layouting
-  GroupArgumentsLayout->addWidget(SelectorWdg,          0, 0);
-  GroupArgumentsLayout->addWidget(PathGrp,              1, 0);
-  GroupArgumentsLayout->addWidget(BasePointGrp,         2, 0);
+  GroupArgumentsLayout->addWidget(SelectorWdg,          0, 0, 1, 2);
+  GroupArgumentsLayout->addWidget(PathGrp,              1, 0, 1, 2);
+  GroupArgumentsLayout->addWidget(BasePointGrp,         2, 0, 1, 2);
   GroupArgumentsLayout->addWidget(AnglesGrp,            3, 0);
+  GroupArgumentsLayout->addWidget(ScalesGrp,            3, 1);
   GroupArgumentsLayout->addWidget(myPreviewCheckBox,    4, 0);
   GroupArgumentsLayout->addWidget(MakeGroupsCheck,      5, 0);
 
@@ -282,12 +311,13 @@ SMESHGUI_ExtrusionAlongPathDlg::SMESHGUI_ExtrusionAlongPathDlg( SMESHGUI* theMod
   YSpin->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
   ZSpin->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
   AngleSpin->RangeStepAndValidator(-180.0, 180.0, 5.0, "angle_precision");
+  ScaleSpin->RangeStepAndValidator(COORD_MIN, COORD_MAX, 1.0, "length_precision");
 
-  mySelector = (SMESH::GetViewWindow( mySMESHGUI ))->GetSelector();
+  mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector();
 
   mySMESHGUI->SetActiveDialogBox(this);
 
-  myPathMeshFilter = new SMESH_TypeFilter(SMESH::MESHorSUBMESH);
+  myPathMeshFilter = new SMESH_TypeFilter(SMESH::IDSOURCE_EDGE);
 
   myHelpFileName = "extrusion_along_path.html";
 
@@ -302,6 +332,8 @@ SMESHGUI_ExtrusionAlongPathDlg::SMESHGUI_ExtrusionAlongPathDlg( SMESHGUI* theMod
 
   connect(AddAngleButton,    SIGNAL(clicked()), this, SLOT(OnAngleAdded()));
   connect(RemoveAngleButton, SIGNAL(clicked()), this, SLOT(OnAngleRemoved()));
+  connect(AddScaleButton,    SIGNAL(clicked()), this, SLOT(OnAngleAdded()));
+  connect(RemoveScaleButton, SIGNAL(clicked()), this, SLOT(OnAngleRemoved()));
 
   connect(SelectPathMeshButton,   SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
   connect(SelectStartPointButton, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
@@ -324,19 +356,27 @@ SMESHGUI_ExtrusionAlongPathDlg::SMESHGUI_ExtrusionAlongPathDlg( SMESHGUI* theMod
   connect(ZSpin,  SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
   connect(AddAngleButton,    SIGNAL(clicked()), this, SLOT(toDisplaySimulation()));
   connect(RemoveAngleButton, SIGNAL(clicked()), this, SLOT(toDisplaySimulation()));
-  //connect(LinearAnglesCheck, SIGNAL(toggled(bool)), SLOT(onSelectMesh()));
+  connect(AddScaleButton,    SIGNAL(clicked()), this, SLOT(toDisplaySimulation()));
+  connect(RemoveScaleButton, SIGNAL(clicked()), this, SLOT(toDisplaySimulation()));
+  connect(LinearScalesCheck, SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation()));
+  connect(LinearAnglesCheck, SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation()));
+  connect(ScalesGrp, SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation()));
+  connect(AnglesGrp, SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation()));
 
 
   //To Connect preview check box
   connectPreviewControl();
 
   AnglesList        ->installEventFilter(this);
+  ScalesList        ->installEventFilter(this);
   StartPointLineEdit->installEventFilter(this);
   XSpin->editor()   ->installEventFilter(this);
   YSpin->editor()   ->installEventFilter(this);
   ZSpin->editor()   ->installEventFilter(this);
 
   CheckIsEnable();
+
+  resize( minimumSizeHint() );
 }
 
 //=================================================================================
@@ -369,6 +409,7 @@ void SMESHGUI_ExtrusionAlongPathDlg::Init (bool ResetControls)
     ZSpin->SetValue(0.0);
 
     AngleSpin->SetValue(45);
+    ScaleSpin->SetValue(2);
     myPreviewCheckBox->setChecked(false);
     onDisplaySimulation(false);
   }
@@ -416,12 +457,10 @@ bool SMESHGUI_ExtrusionAlongPathDlg::ClickOnApply()
   QStringList aParameters;
   
   //get angles
-  SMESH::double_array_var anAngles = getAngles();
-  
+  SMESH::double_array_var anAngles = getAngles(); 
   for (int i = 0; i < myAnglesList.count(); i++)
     aParameters << AnglesList->item(i)->text();
 
-
   // get base point
   SMESH::PointStruct aBasePoint;
   if (BasePointGrp->isChecked()) {
@@ -433,6 +472,11 @@ bool SMESHGUI_ExtrusionAlongPathDlg::ClickOnApply()
   aParameters << YSpin->text();
   aParameters << ZSpin->text();
 
+  //get scales
+  SMESH::double_array_var aScales = getScales();
+  for (int i = 0; i < myScalesList.count(); i++)
+    aParameters << ScalesList->item(i)->text();
+
   bool meshHadNewTypeBefore = true;
   int  maxSelType = 0;
   const bool makeGroups = ( MakeGroupsCheck->isEnabled() && MakeGroupsCheck->isChecked() );
@@ -464,8 +508,8 @@ bool SMESHGUI_ExtrusionAlongPathDlg::ClickOnApply()
                                               GEOM::GEOM_Object::_nil(),
                                               aNodeStart, AnglesGrp->isChecked(),
                                               anAngles, LinearAnglesCheck->isChecked(),
-                                              BasePointGrp->isChecked(), aBasePoint,
-                                              makeGroups, retVal );
+                                              BasePointGrp->isChecked(), aBasePoint, makeGroups,
+                                              aScales, LinearScalesCheck->isChecked(), retVal );
 
     wc.suspend();
     switch (retVal) {
@@ -911,17 +955,34 @@ void SMESHGUI_ExtrusionAlongPathDlg::enterEvent (QEvent*)
 //=======================================================================
 void SMESHGUI_ExtrusionAlongPathDlg::OnAngleAdded()
 {
-  QString msg;
-  if( !AngleSpin->isValid( msg, true ) ) {
-    QString str( tr( "SMESH_INCORRECT_INPUT" ) );
-    if ( !msg.isEmpty() )
-      str += "\n" + msg;
-    SUIT_MessageBox::critical( this, tr( "SMESH_ERROR" ), str );
-    return;
+  if ( sender() == AddAngleButton )
+  {
+    QString msg;
+    if( !AngleSpin->isValid( msg, true ) ) {
+      QString str( tr( "SMESH_INCORRECT_INPUT" ) );
+      if ( !msg.isEmpty() )
+        str += "\n" + msg;
+      SUIT_MessageBox::critical( this, tr( "SMESH_ERROR" ), str );
+      return;
+    }
+    AnglesList->addItem(AngleSpin->text());
+    myAnglesList.append(AngleSpin->GetValue());
   }
-  AnglesList->addItem(AngleSpin->text());
-  myAnglesList.append(AngleSpin->GetValue());
-
+  
+  if ( sender() == AddScaleButton )
+  {
+    QString msg;
+    if( !ScaleSpin->isValid( msg, true ) ) {
+      QString str( tr( "SMESH_INCORRECT_INPUT" ) );
+      if ( !msg.isEmpty() )
+        str += "\n" + msg;
+      SUIT_MessageBox::critical( this, tr( "SMESH_ERROR" ), str );
+      return;
+    }
+    ScalesList->addItem(ScaleSpin->text());
+    myScalesList.append(ScaleSpin->GetValue());
+  }
+  
   updateLinearAngles();
 }
 
@@ -931,10 +992,23 @@ void SMESHGUI_ExtrusionAlongPathDlg::OnAngleAdded()
 //=======================================================================
 void SMESHGUI_ExtrusionAlongPathDlg::OnAngleRemoved()
 {
-  QList<QListWidgetItem*> aList = AnglesList->selectedItems();
+  QListWidget* widget;
+  QList<double>* list;
+  if ( sender() == RemoveScaleButton )
+  {
+    widget = ScalesList;
+    list   = & myScalesList;
+  }
+  else
+  {
+    widget = AnglesList;
+    list   = & myAnglesList;
+  }
+
+  QList<QListWidgetItem*> aList = widget->selectedItems();
   QListWidgetItem* anItem;
   foreach(anItem, aList) {
-    myAnglesList.removeAt(AnglesList->row(anItem));
+    list->removeAt( widget->row( anItem ));
     delete anItem;
   }
 
@@ -951,7 +1025,11 @@ bool SMESHGUI_ExtrusionAlongPathDlg::eventFilter (QObject* object, QEvent* event
     QKeyEvent* ke = (QKeyEvent*)event;
     if (object == AnglesList) {
       if (ke->key() == Qt::Key_Delete)
-        OnAngleRemoved();
+        RemoveAngleButton->click();
+    }
+    if (object == ScalesList) {
+      if (ke->key() == Qt::Key_Delete)
+        RemoveScaleButton->click();
     }
   }
   else if (event->type() == QEvent::FocusIn) {
@@ -1023,6 +1101,19 @@ void SMESHGUI_ExtrusionAlongPathDlg::updateLinearAngles()
   if( !enableLinear )
     LinearAnglesCheck->setChecked( false );
   LinearAnglesCheck->setEnabled( enableLinear );
+
+  enableLinear = true;
+  for( int row = 0, nbRows = ScalesList->count(); row < nbRows; row++ ) {
+    if( QListWidgetItem* anItem = ScalesList->item( row ) ) {
+      enableLinear = false;
+      anItem->text().toDouble(&enableLinear);
+      if( !enableLinear )
+        break;
+    }
+  }
+  if( !enableLinear )
+    LinearScalesCheck->setChecked( false );
+  LinearScalesCheck->setEnabled( enableLinear );
 }
 
 //=================================================================================
@@ -1074,9 +1165,10 @@ void SMESHGUI_ExtrusionAlongPathDlg::onDisplaySimulation( bool toDisplayPreview
   if ( myPreviewCheckBox->isChecked() && toDisplayPreview ) {
     if ( SelectorWdg->IsAnythingSelected() && isValid() && isValuesValid())
     {
-      // get angles
+      // get angles and scales
       SMESH::double_array_var anAngles = getAngles();
-      
+      SMESH::double_array_var aScales  = getScales();
+
       // get base point
       SMESH::PointStruct aBasePoint;
       if (BasePointGrp->isChecked()) {
@@ -1107,7 +1199,9 @@ void SMESHGUI_ExtrusionAlongPathDlg::onDisplaySimulation( bool toDisplayPreview
                                                    aNodeStart, AnglesGrp->isChecked(),
                                                    anAngles, LinearAnglesCheck->isChecked(),
                                                    BasePointGrp->isChecked(), aBasePoint,
-                                                   makeGroups, retVal );
+                                                   makeGroups,
+                                                   aScales, LinearScalesCheck->isChecked(),
+                                                   retVal);
 
           if( retVal == SMESH::SMESH_MeshEditor::EXTR_OK )
           {
@@ -1133,18 +1227,36 @@ void SMESHGUI_ExtrusionAlongPathDlg::onDisplaySimulation( bool toDisplayPreview
   }
 }
 
+//=======================================================================
+//function : getAngles
+//purpose  : return CORBA array of angles
+//=======================================================================
+
 SMESH::double_array_var SMESHGUI_ExtrusionAlongPathDlg::getAngles()
 {
   SMESH::double_array_var anAngles = new SMESH::double_array;
-  if (AnglesGrp->isChecked())
+  if ( AnglesGrp->isChecked() )
   {
-    anAngles->length(myAnglesList.count());
-    int j = 0;
-    for (int i = 0; i < myAnglesList.count(); i++) {
-      double angle = myAnglesList[i];
-      anAngles[ j++ ] = angle*M_PI/180.;
-    }
-    anAngles->length(j);
+    anAngles->length( myAnglesList.count() );
+    for (int i = 0; i < myAnglesList.count(); i++)
+      anAngles[ i ] = myAnglesList[ i ] * M_PI / 180.;
   }
   return anAngles;
 }
+
+//=======================================================================
+//function : getScales
+//purpose  : return CORBA array of scale factors
+//=======================================================================
+
+SMESH::double_array_var SMESHGUI_ExtrusionAlongPathDlg::getScales()
+{
+  SMESH::double_array_var anScales = new SMESH::double_array;
+  if ( ScalesGrp->isChecked() )
+  {
+    anScales->length( myScalesList.count() );
+    for (int i = 0; i < myScalesList.count(); i++)
+      anScales[ i ] = myScalesList[ i ];
+  }
+  return anScales;
+}
index 18cd048ae8369d95bdb60ca720190589716de86c..2bd6f1d21fce302a290ef0f1a070e579abaef370 100644 (file)
@@ -82,6 +82,7 @@ private:
   bool                      isValuesValid();
   
   SMESH::double_array_var   getAngles();
+  SMESH::double_array_var   getScales();
 
   void                      updateLinearAngles();
   
@@ -94,6 +95,7 @@ private:
   SMESH::SMESH_IDSource_var myPath;
   SUIT_SelectionFilter*     myPathMeshFilter;
   QList<double>             myAnglesList;
+  QList<double>             myScalesList;
 
   // widgets
   SMESHGUI_3TypesSelector*  SelectorWdg;
@@ -103,12 +105,21 @@ private:
   QLineEdit*                PathMeshLineEdit;
   QPushButton*              SelectStartPointButton;
   QLineEdit*                StartPointLineEdit;
+
   QCheckBox*                LinearAnglesCheck;
   QGroupBox*                AnglesGrp;
   QListWidget*              AnglesList;
   QToolButton*              AddAngleButton;
   QToolButton*              RemoveAngleButton;
   SMESHGUI_SpinBox*         AngleSpin;
+
+  QCheckBox*                LinearScalesCheck;
+  QGroupBox*                ScalesGrp;
+  QListWidget*              ScalesList;
+  QToolButton*              AddScaleButton;
+  QToolButton*              RemoveScaleButton;
+  SMESHGUI_SpinBox*         ScaleSpin;
+
   QGroupBox*                BasePointGrp;
   QPushButton*              SelectBasePointButton;
   SMESHGUI_SpinBox*         XSpin;
index d17be56aa2458390eb1dab3825c15a1e9d2b4814..ad1bb208bf4a338522ebe175c5d9d34b52d65d71 100644 (file)
@@ -709,6 +709,8 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule)
   // Scales
 
   ScalesGrp = new QGroupBox(tr("SMESH_SCALES"), GroupArguments);
+  ScalesGrp->setCheckable(true);
+  ScalesGrp->setChecked(false);
   QGridLayout* ScalesGrpLayout = new QGridLayout( ScalesGrp );
   ScalesGrpLayout->setSpacing(SPACING); ScalesGrpLayout->setMargin(MARGIN);
 
@@ -730,10 +732,40 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule)
   ScalesGrpLayout->addWidget(AddScaleButton,    0, 1);
   ScalesGrpLayout->addWidget(RemoveScaleButton, 2, 1);
   ScalesGrpLayout->addWidget(ScaleSpin,         0, 2);
-  ScalesGrpLayout->addWidget(LinearScalesCheck, 4, 0);
+  ScalesGrpLayout->addWidget(LinearScalesCheck, 4, 0, 1, 3);
   ScalesGrpLayout->setRowMinimumHeight(1, 10);
   ScalesGrpLayout->setRowStretch(3, 10);
 
+  // Angles
+
+  AnglesGrp = new QGroupBox(tr("SMESH_ANGLES"), GroupArguments);
+  AnglesGrp->setCheckable(true);
+  AnglesGrp->setChecked(false);
+  QGridLayout* AnglesGrpLayout = new QGridLayout( AnglesGrp );
+  AnglesGrpLayout->setSpacing(SPACING); AnglesGrpLayout->setMargin(MARGIN);
+
+  AnglesList = new QListWidget( AnglesGrp );
+  AnglesList->setSelectionMode(QListWidget::ExtendedSelection);
+
+  AddAngleButton = new QToolButton( AnglesGrp );
+  AddAngleButton->setIcon( addImage );
+
+  RemoveAngleButton = new QToolButton( AnglesGrp );
+  RemoveAngleButton->setIcon( removeImage );
+
+  AngleSpin = new SMESHGUI_SpinBox( AnglesGrp );
+  AngleSpin->SetValue(10);
+
+  LinearAnglesCheck = new QCheckBox(tr("LINEAR_ANGLES"), AnglesGrp );
+
+  AnglesGrpLayout->addWidget(AnglesList,        0, 0, 4, 1);
+  AnglesGrpLayout->addWidget(AddAngleButton,    0, 1);
+  AnglesGrpLayout->addWidget(RemoveAngleButton, 2, 1);
+  AnglesGrpLayout->addWidget(AngleSpin,         0, 2);
+  AnglesGrpLayout->addWidget(LinearAnglesCheck, 4, 0, 1, 3);
+  AnglesGrpLayout->setRowMinimumHeight(1, 10);
+  AnglesGrpLayout->setRowStretch(3, 10);
+
   // layouting
   GroupArgumentsLayout->addWidget(SelectorWdg,            0, 0, 1, 9);
   GroupArgumentsLayout->addWidget(ExtrMethod_RBut0,       1, 0, 1, 3);
@@ -761,7 +793,8 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule)
   GroupArgumentsLayout->addWidget(ByAverageNormalCheck,   6, 0, 1, 4);
   GroupArgumentsLayout->addWidget(UseInputElemsOnlyCheck, 6, 4, 1, 4);
   GroupArgumentsLayout->addWidget(BasePointGrp,           7, 0, 1, 9);
-  GroupArgumentsLayout->addWidget(ScalesGrp,              8, 0, 1, 9);
+  GroupArgumentsLayout->addWidget(ScalesGrp,              8, 0, 1, 4);
+  GroupArgumentsLayout->addWidget(AnglesGrp,              8, 5, 1, 4);
   GroupArgumentsLayout->addWidget(myPreviewCheckBox,      9, 0, 1, 8);
   GroupArgumentsLayout->addWidget(MakeGroupsCheck,        10,0, 1, 8);
   GroupArgumentsLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding), 10, 0);
@@ -810,12 +843,13 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule)
   BasePoint_YSpin->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
   BasePoint_ZSpin->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
   ScaleSpin->RangeStepAndValidator      (COORD_MIN, COORD_MAX, 1.0, "length_precision");
+  AngleSpin->RangeStepAndValidator      (-180.0, 180.0, 5.0, "angle_precision");
 
   ExtrMethod_RBut0->setChecked(true);
   UseInputElemsOnlyCheck->setChecked(true);
   MakeGroupsCheck->setChecked(true);
 
-  mySelector = (SMESH::GetViewWindow( mySMESHGUI ))->GetSelector();
+  mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector();
 
   mySMESHGUI->SetActiveDialogBox(this);
 
@@ -844,6 +878,8 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule)
 
   connect(AddScaleButton,    SIGNAL(clicked()), this, SLOT(OnScaleAdded()));
   connect(RemoveScaleButton, SIGNAL(clicked()), this, SLOT(OnScaleRemoved()));
+  connect(AddAngleButton,    SIGNAL(clicked()), this, SLOT(OnScaleAdded()));
+  connect(RemoveAngleButton, SIGNAL(clicked()), this, SLOT(OnScaleRemoved()));
 
   connect(SelectVectorButton,   SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
   connect(SelectBasePointButton,SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
@@ -871,10 +907,15 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule)
   connect(AddScaleButton,         SIGNAL(clicked()),     this, SLOT(toDisplaySimulation()));
   connect(RemoveScaleButton,      SIGNAL(clicked()),     this, SLOT(toDisplaySimulation()));
   connect(LinearScalesCheck,      SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation()));
+  connect(AddAngleButton,         SIGNAL(clicked()),     this, SLOT(toDisplaySimulation()));
+  connect(RemoveAngleButton,      SIGNAL(clicked()),     this, SLOT(toDisplaySimulation()));
+  connect(LinearAnglesCheck,      SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation()));
   connect(BasePointGrp,           SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation()));
   connect(BasePoint_XSpin, SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
   connect(BasePoint_YSpin, SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
   connect(BasePoint_ZSpin, SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
+  connect(ScalesGrp,       SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation()));
+  connect(AnglesGrp,       SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation()));
 
   //To Connect preview check box
   connectPreviewControl();
@@ -964,14 +1005,26 @@ bool SMESHGUI_ExtrusionDlg::isValuesValid()
 //purpose  : return 3 scaling parameters
 //=======================================================================
 
-bool SMESHGUI_ExtrusionDlg::getScaleParams( SMESH::double_array*& scales,
-                                            SMESH::double_array*& basePoint )
+void SMESHGUI_ExtrusionDlg::getScaleParams( SMESH::double_array*& scales,
+                                            SMESH::double_array*& basePoint,
+                                            bool &                scalesVariation,
+                                            SMESH::double_array*& angles,
+                                            bool &                anglesVariation )
 {
   scales = new SMESH::double_array;
-  scales->length( myScalesList.count() );
-  for ( int i = 0; i < myScalesList.count(); ++i )
-    (*scales)[i] = myScalesList[i];
-
+  if ( ScalesGrp->isChecked() )
+  {
+    scales->length( myScalesList.count() );
+    for ( int i = 0; i < myScalesList.count(); ++i )
+      (*scales)[i] = myScalesList[i];
+  }
+  angles = new SMESH::double_array;
+  if ( AnglesGrp->isChecked() )
+  {
+    angles->length( myAnglesList.count() );
+    for ( int i = 0; i < myAnglesList.count(); ++i )
+      (*angles)[i] = myAnglesList[i]*M_PI/180.;
+  }
   basePoint = new SMESH::double_array;
   if ( BasePointGrp->isChecked() )
   {
@@ -981,7 +1034,8 @@ bool SMESHGUI_ExtrusionDlg::getScaleParams( SMESH::double_array*& scales,
     (*basePoint)[2] = BasePoint_ZSpin->GetValue();
   }
 
-  return ( scales->length() > 0 && LinearScalesCheck->isChecked() );
+  scalesVariation = ( scales->length() > 0 && LinearScalesCheck->isChecked() );
+  anglesVariation = ( angles->length() > 0 && LinearAnglesCheck->isChecked() );
 }
 
 //=================================================================================
@@ -1074,6 +1128,7 @@ void SMESHGUI_ExtrusionDlg::ClickOnRadio()
 
   BasePointGrp->setEnabled( !ExtrMethod_RBut2->isChecked() );
   ScalesGrp   ->setEnabled( !ExtrMethod_RBut2->isChecked() );
+  AnglesGrp   ->setEnabled( !ExtrMethod_RBut2->isChecked() );
 
 
   CheckIsEnable();
@@ -1126,13 +1181,11 @@ bool SMESHGUI_ExtrusionDlg::ClickOnApply()
     long aNbSteps = (long)SpinBox_NbSteps->value();
     aParameters << SpinBox_NbSteps->text();
 
-    SMESH::double_array_var scales = new SMESH::double_array;
-    scales->length( myScalesList.count() );
     for (int i = 0; i < myScalesList.count(); i++)
-    {
-      scales[i] = myScalesList[i];
       aParameters << ScalesList->item(i)->text();
-    }
+
+    for (int i = 0; i < myAnglesList.count(); i++)
+      aParameters << AnglesList->item(i)->text();
 
     bool meshHadNewTypeBefore = true;
     int  maxSelType = 0;
@@ -1175,12 +1228,14 @@ bool SMESHGUI_ExtrusionDlg::ClickOnApply()
       }
       else
       {
-        SMESH::double_array_var scales, basePoint;
-        bool linVariation = getScaleParams( scales.out(), basePoint.out() );
+        SMESH::double_array_var scales, basePoint, angles;
+        bool scalesVariation, anglesVariation;
+        getScaleParams( scales.out(), basePoint.out(), scalesVariation,
+                        angles.out(), anglesVariation );
         groups = meshEditor->ExtrusionSweepObjects( nodes, edges, faces,
-                                                    aVector, aNbSteps,
-                                                    scales, linVariation, basePoint,
-                                                    makeGroups );
+                                                    aVector, aNbSteps, makeGroups,
+                                                    scales, scalesVariation, basePoint,
+                                                    angles, anglesVariation );
       }
 
     } catch (...) {
@@ -1565,12 +1620,14 @@ void SMESHGUI_ExtrusionDlg::onDisplaySimulation( bool toDisplayPreview )
         }
         else
         {
-          SMESH::double_array_var scales, basePoint;
-          bool linVariation = getScaleParams( scales.out(), basePoint.out() );
+          SMESH::double_array_var scales, basePoint, angles;
+          bool scalesVariation, anglesVariation;
+          getScaleParams( scales.out(), basePoint.out(), scalesVariation,
+                          angles.out(), anglesVariation );
           groups = meshEditor->ExtrusionSweepObjects( nodes, edges, faces,
-                                                      aVector, aNbSteps,
-                                                      scales, linVariation, basePoint,
-                                                      makeGroups );
+                                                      aVector, aNbSteps, makeGroups,
+                                                      scales, scalesVariation, basePoint,
+                                                      angles, anglesVariation );
         }
         SMESH::MeshPreviewStruct_var aMeshPreviewStruct = meshEditor->GetPreviewData();
         mySimulation->SetData(aMeshPreviewStruct);
@@ -1614,35 +1671,65 @@ void SMESHGUI_ExtrusionDlg::getExtrusionVector(SMESH::DirStruct& aVector)
 
 //=======================================================================
 // function : OnScaleAdded()
-// purpose  : Called when user adds Scale to the list
+// purpose  : Called when user adds Scale or Angle to the list
 //=======================================================================
 void SMESHGUI_ExtrusionDlg::OnScaleAdded()
 {
-  QString msg;
-  if( !ScaleSpin->isValid( msg, true ) ) {
-    QString str( tr( "SMESH_INCORRECT_INPUT" ) );
-    if ( !msg.isEmpty() )
-      str += "\n" + msg;
-    SUIT_MessageBox::critical( this, tr( "SMESH_ERROR" ), str );
-    return;
+  if ( sender() == AddScaleButton )
+  {
+    QString msg;
+    if( !ScaleSpin->isValid( msg, true ) ) {
+      QString str( tr( "SMESH_INCORRECT_INPUT" ) );
+      if ( !msg.isEmpty() )
+        str += "\n" + msg;
+      SUIT_MessageBox::critical( this, tr( "SMESH_ERROR" ), str );
+      return;
+    }
+    ScalesList->addItem(ScaleSpin->text());
+    myScalesList.append(ScaleSpin->GetValue());
+  }
+
+  if ( sender() == AddAngleButton )
+  {
+    QString msg;
+    if( !AngleSpin->isValid( msg, true ) ) {
+      QString str( tr( "SMESH_INCORRECT_INPUT" ) );
+      if ( !msg.isEmpty() )
+        str += "\n" + msg;
+      SUIT_MessageBox::critical( this, tr( "SMESH_ERROR" ), str );
+      return;
+    }
+    AnglesList->addItem(AngleSpin->text());
+    myAnglesList.append(AngleSpin->GetValue());
   }
-  ScalesList->addItem(ScaleSpin->text());
-  myScalesList.append(ScaleSpin->GetValue());
 }
 
 //=======================================================================
 // function : OnScaleRemoved()
-// purpose  : Called when user removes Scale(s) from the list
+// purpose  : Called when user removes Scales or Angles from the list
 //=======================================================================
 void SMESHGUI_ExtrusionDlg::OnScaleRemoved()
 {
-  QList<QListWidgetItem*> aList = ScalesList->selectedItems();
+  QListWidget* widget;
+  QList<double>* list;
+  if ( sender() == RemoveScaleButton )
+  {
+    widget = ScalesList;
+    list   = & myScalesList;
+  }
+  else
+  {
+    widget = AnglesList;
+    list   = & myAnglesList;
+  }
+
+  QList<QListWidgetItem*> aList = widget->selectedItems();
   QListWidgetItem* anItem;
   int row = 0;
   foreach(anItem, aList) {
-    row = ScalesList->row(anItem);
-    myScalesList.removeAt(row);
+    row = widget->row(anItem);
+    list->removeAt(row);
     delete anItem;
   }
-  ScalesList->setCurrentRow( row, QItemSelectionModel::Select );
+  widget->setCurrentRow( row, QItemSelectionModel::Select );
 }
index b539eee98b38d95dc562cb97229a5f97421e6cf5..1b1c211001f7b44b2e104493becdcba160297636 100644 (file)
@@ -145,8 +145,11 @@ private:
   void                             getExtrusionVector(SMESH::DirStruct& aVector);
   void                             extrusionByNormal(SMESH::SMESH_MeshEditor_ptr meshEditor,
                                                      const bool                  makeGroups=false);
-  bool                             getScaleParams( SMESH::double_array*& scales,
-                                                   SMESH::double_array*& basePoint );
+  void                             getScaleParams( SMESH::double_array*& scales,
+                                                   SMESH::double_array*& basePoint,
+                                                   bool &                scalesVariation,
+                                                   SMESH::double_array*& angles,
+                                                   bool &                anglesVariation);
   
   bool                             isValid();
   bool                             isValuesValid();
@@ -154,6 +157,7 @@ private:
   LightApp_SelectionMgr*           mySelectionMgr;        /* User shape selection */
   SVTK_Selector*                   mySelector;
   QList<double>                    myScalesList;
+  QList<double>                    myAnglesList;
 
   // widgets
   SMESHGUI_3TypesSelector*         SelectorWdg;
@@ -198,6 +202,13 @@ private:
   SMESHGUI_SpinBox*                ScaleSpin;
   QCheckBox*                       LinearScalesCheck;
 
+  QGroupBox*                       AnglesGrp;
+  QListWidget*                     AnglesList;
+  QToolButton*                     AddAngleButton;
+  QToolButton*                     RemoveAngleButton;
+  SMESHGUI_SpinBox*                AngleSpin;
+  QCheckBox*                       LinearAnglesCheck;
+
   QGroupBox*                       GroupButtons;
   QPushButton*                     buttonOk;
   QPushButton*                     buttonCancel;
index 222fa1e06564861b570bfcacd5198434d76625d8..ac6bcd036893270d253c33310adf8ddc53df9bbd 100644 (file)
@@ -1847,15 +1847,15 @@ Do you want to continue?</translation>
     </message>
     <message>
         <source>SMESH_EXTRUSION_TO_DISTANCE</source>
-        <translation>Extrusion To Distance</translation>
+        <translation>Extrusion to distance</translation>
     </message>
     <message>
         <source>SMESH_EXTRUSION_ALONG_VECTOR</source>
-        <translation>Extrusion Along Vector</translation>
+        <translation>Extrusion along vector</translation>
     </message>
     <message>
         <source>SMESH_EXTRUSION_BY_NORMAL</source>
-        <translation>Extrusion By Normal</translation>
+        <translation>Extrusion by normal</translation>
     </message>
     <message>
         <source>SMESH_FACE</source>
@@ -5517,18 +5517,6 @@ Please select a group and try again</translation>
         <source>CANT_GET_TANGENT</source>
         <translation>Can&apos;t get tangent for one of the path nodes</translation>
     </message>
-    <message>
-        <source>EXTRUSION_0D</source>
-        <translation>Extrusion of 0D elements</translation>
-    </message>
-    <message>
-        <source>EXTRUSION_1D</source>
-        <translation>Extrusion of 1D elements</translation>
-    </message>
-    <message>
-        <source>EXTRUSION_2D</source>
-        <translation>Extrusion of 2D elements</translation>
-    </message>
     <message>
         <source>EXTRUSION_ALONG_PATH</source>
         <translation>Extrusion along a path</translation>
@@ -5539,7 +5527,7 @@ Please select a group and try again</translation>
     </message>
     <message>
         <source>LINEAR_ANGLES</source>
-        <translation>Linear variation of the angles</translation>
+        <translation>Linear variation of angles</translation>
     </message>
     <message>
         <source>NO_ELEMENTS_SELECTED</source>
@@ -5551,11 +5539,19 @@ Please select a group and try again</translation>
     </message>
     <message>
         <source>SMESH_ANGLES</source>
-        <translation>Rotation Angles</translation>
+        <translation>Rotation angles</translation>
     </message>
     <message>
         <source>SMESH_BASE_POINT</source>
-        <translation>Base Point</translation>
+        <translation>Base point</translation>
+    </message>
+    <message>
+        <source>SMESH_SCALES</source>
+        <translation>Scale factors</translation>
+    </message>
+    <message>
+        <source>LINEAR_SCALES</source>
+        <translation>Linear variation of factors</translation>
     </message>
     <message>
         <source>SMESH_PATH</source>
@@ -5575,11 +5571,11 @@ Please select a group and try again</translation>
     </message>
     <message>
         <source>SMESH_USE_ANGLES</source>
-        <translation>Use Angles</translation>
+        <translation>Use angles</translation>
     </message>
     <message>
         <source>SMESH_USE_BASE_POINT</source>
-        <translation>Use Base Point</translation>
+        <translation>Use base point</translation>
     </message>
     <message>
         <source>WRONG_ANGLES_NUMBER</source>
@@ -5588,18 +5584,6 @@ Please select a group and try again</translation>
 </context>
 <context>
     <name>SMESHGUI_ExtrusionDlg</name>
-    <message>
-        <source>EXTRUSION_0D</source>
-        <translation>Extrusion of nodes</translation>
-    </message>
-    <message>
-        <source>EXTRUSION_1D</source>
-        <translation>Extrusion of 1D elements</translation>
-    </message>
-    <message>
-        <source>EXTRUSION_2D</source>
-        <translation>Extrusion of 2D elements</translation>
-    </message>
     <message>
         <source>EXTRUSION_ALONG_LINE</source>
         <translation>Extrusion along a line</translation>
@@ -5614,15 +5598,23 @@ Please select a group and try again</translation>
     </message>
     <message>
         <source>SMESH_SCALES</source>
-        <translation>Scale Factors</translation>
+        <translation>Scale factors</translation>
     </message>
     <message>
         <source>LINEAR_SCALES</source>
-        <translation>Linear Variation of Scale Factors</translation>
+        <translation>Linear variation of factors</translation>
     </message>
     <message>
         <source>BASE_POINT</source>
-        <translation>Scaling Center</translation>
+        <translation>Base point</translation>
+    </message>
+    <message>
+        <source>LINEAR_ANGLES</source>
+        <translation>Linear variation of angles</translation>
+    </message>
+    <message>
+        <source>SMESH_ANGLES</source>
+        <translation>Rotation angles</translation>
     </message>
 </context>
 <context>
index 71707118bdcc3aac967ad98a04bebdf707a12e0c..8c196001146602005921ed7cf666ba22a2accfcc 100644 (file)
@@ -79,8 +79,8 @@ class SMESHUtils_EXPORT SMESH_Delaunay
   // return UV of the i-th source boundary node (zero based)
   gp_XY GetBndUV(const int iNode) const;
 
-  // return scale factor to convert real UV to/from UV used for Delauney meshing:
-  // delauney_UV = real_UV * scale
+  // return scale factor to convert real UV to/from UV used for Delaunay meshing:
+  // delaunay_UV = real_UV * scale
   const gp_XY& GetScale() const { return _scale; }
 
   void ToPython() const;
index 6cd891ccc544fe572f8150f136fb203a9625c0e6..52d7d5415d51943f7b26b5ec4db8e646590a6593 100644 (file)
@@ -1764,7 +1764,7 @@ double SMESH_MeshAlgos::GetDistance( const SMDS_MeshVolume* volume,
          !vTool.GetFaceBaryCenter( iF, bc[0], bc[1], bc[2] ))
       continue;
     gp_XYZ bcp = point.XYZ() - gp_XYZ( bc[0], bc[1], bc[2] );
-    if ( gp_XYZ( n[0], n[1], n[2] ) * bcp < 1e-6 )
+    if ( gp_XYZ( n[0], n[1], n[2] ) * bcp < -1e-12 )
       continue;
 
     // find distance to a facet
index b03eca37d8b0a2e9f5cac524fe43cb14e7603263..7ef847bf0bfed8c35733d740c45d814dcc1b14d5 100644 (file)
@@ -2496,7 +2496,8 @@ namespace MeshEditor_I
     bool myIsExtrusionByNormal;
 
     static int makeFlags( CORBA::Boolean MakeGroups,
-                          CORBA::Boolean LinearVariation = false,
+                          CORBA::Boolean ScaleVariation = false,
+                          CORBA::Boolean AngleVariation = false,
                           CORBA::Boolean ByAverageNormal = false,
                           CORBA::Boolean UseInputElemsOnly = false,
                           CORBA::Long    Flags = 0,
@@ -2505,7 +2506,8 @@ namespace MeshEditor_I
       if ( MakeGroups       ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
       if ( ByAverageNormal  ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
       if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
-      if ( LinearVariation  ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_SCALE_LINEAR_VARIATION;
+      if ( ScaleVariation  )  Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_SCALE_LINEAR_VARIATION;
+      if ( AngleVariation  )  Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_ANGLE_LINEAR_VARIATION;
       if ( MakeBoundary     ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
       return Flags;
     }
@@ -2513,7 +2515,9 @@ namespace MeshEditor_I
     ExtrusionParams(const SMESH::DirStruct &    theDir,
                     CORBA::Long                 theNbOfSteps,
                     const SMESH::double_array & theScaleFactors,
-                    CORBA::Boolean              theLinearVariation,
+                    CORBA::Boolean              theScaleVariation,
+                    const SMESH::double_array & theAngles,
+                    CORBA::Boolean              theAngleVariation,
                     const SMESH::double_array & theBasePoint,
                     CORBA::Boolean              theMakeGroups):
       ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
@@ -2521,8 +2525,9 @@ namespace MeshEditor_I
                                                 theDir.PS.z ),
                                         theNbOfSteps,
                                         toList( theScaleFactors ),
+                                        toList( theAngles ),
                                         TBasePoint( theBasePoint ),
-                                        makeFlags( theMakeGroups, theLinearVariation )),
+                                        makeFlags( theMakeGroups, theScaleVariation, theAngleVariation )),
       myIsExtrusionByNormal( false )
     {
     }
@@ -2537,8 +2542,9 @@ namespace MeshEditor_I
                                                 theDir.PS.z ),
                                         theNbOfSteps,
                                         std::list<double>(),
+                                        std::list<double>(),
                                         0,
-                                        makeFlags( theMakeGroups, false, false, false,
+                                        makeFlags( theMakeGroups, false, false, false, false,
                                                    theExtrFlags, false ),
                                         theSewTolerance ),
       myIsExtrusionByNormal( false )
@@ -2553,7 +2559,7 @@ namespace MeshEditor_I
                     CORBA::Boolean theMakeGroups ):
       ::SMESH_MeshEditor::ExtrusParam ( theStepSize, 
                                         theNbOfSteps,
-                                        makeFlags( theMakeGroups, false,
+                                        makeFlags( theMakeGroups, false, false,
                                                    theByAverageNormal, theUseInputElemsOnly ),
                                         theDim),
       myIsExtrusionByNormal( true )
@@ -2565,8 +2571,6 @@ namespace MeshEditor_I
       Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
     }
 
-  private:
-
     static std::list<double> toList( const SMESH::double_array & theScaleFactors )
     {
       std::list<double> scales;
@@ -2575,6 +2579,8 @@ namespace MeshEditor_I
       return scales;
     }
 
+  private:
+
     // structure used to convert SMESH::double_array to gp_XYZ*
     struct TBasePoint
     {
@@ -2613,17 +2619,19 @@ SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNode
                                           const SMESH::ListOfIDSources & theFaces,
                                           const SMESH::DirStruct &       theStepVector,
                                           CORBA::Long                    theNbOfSteps,
+                                          CORBA::Boolean                 theToMakeGroups,
                                           const SMESH::double_array &    theScaleFactors,
-                                          CORBA::Boolean                 theLinearVariation,
+                                          CORBA::Boolean                 theScalesVariation,
                                           const SMESH::double_array &    theBasePoint,
-                                          CORBA::Boolean                 theToMakeGroups)
+                                          const SMESH::double_array &    theAngles,
+                                          CORBA::Boolean                 theAnglesVariation)
   throw (SALOME::SALOME_Exception)
 {
   SMESH_TRY;
   initData();
 
-  ExtrusionParams params( theStepVector, theNbOfSteps, theScaleFactors,
-                          theLinearVariation, theBasePoint, theToMakeGroups );
+  ExtrusionParams params( theStepVector, theNbOfSteps, theScaleFactors, theScalesVariation,
+                          theAngles, theAnglesVariation, theBasePoint, theToMakeGroups );
 
   TIDSortedElemSet elemsNodes[2];
   for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
@@ -2664,12 +2672,17 @@ SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNode
   {
     dumpGroupsList( aPythonDump, aGroups );
     aPythonDump << this<< ".ExtrusionSweepObjects( "
-                << theNodes             << ", "
-                << theEdges             << ", "
-                << theFaces             << ", "
-                << theStepVector        << ", "
-                << TVar( theNbOfSteps ) << ", "
-                << theToMakeGroups      << " )";
+                << theNodes                << ", "
+                << theEdges                << ", "
+                << theFaces                << ", "
+                << theStepVector           << ", "
+                << TVar( theNbOfSteps )    << ", "
+                << theToMakeGroups         << ", "
+                << TVar( theScaleFactors ) << ", "
+                << theScalesVariation      << ", "
+                << TVar( theBasePoint )    << ", "
+                << TVar( theAngles )       << ", "
+                << theAnglesVariation      << " )";
   }
   else
   {
@@ -2847,15 +2860,17 @@ SMESH::ListOfGroups*
 SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes,
                                               const SMESH::ListOfIDSources & theEdges,
                                               const SMESH::ListOfIDSources & theFaces,
-                                              SMESH::SMESH_IDSource_ptr      thePathMesh,
+                                              SMESH::SMESH_IDSource_ptr      thePathObject,
                                               GEOM::GEOM_Object_ptr          thePathShape,
                                               CORBA::Long                    theNodeStart,
                                               CORBA::Boolean                 theHasAngles,
                                               const SMESH::double_array &    theAngles,
-                                              CORBA::Boolean                 theLinearVariation,
+                                              CORBA::Boolean                 theAnglesVariation,
                                               CORBA::Boolean                 theHasRefPoint,
                                               const SMESH::PointStruct &     theRefPoint,
                                               bool                           theMakeGroups,
+                                              const SMESH::double_array &    theScaleFactors,
+                                              CORBA::Boolean                 theScalesVariation,
                                               SMESH::SMESH_MeshEditor::Extrusion_Error& theError)
   throw (SALOME::SALOME_Exception)
 {
@@ -2865,45 +2880,58 @@ SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & the
   SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups;
 
   theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
-  if ( thePathMesh->_is_nil() )
+  if ( thePathObject->_is_nil() )
     return aGroups._retn();
 
-  // get a sub-mesh
-  SMESH_subMesh* aSubMesh = 0;
-  SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
-  if ( thePathShape->_is_nil() )
+
+  SMDS_ElemIteratorPtr pathEdgesIterator;
+
+  SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathObject );
+  if ( !CORBA::is_nil( thePathShape ) && aMeshImp )
   {
-    // thePathMesh should be either a sub-mesh or a mesh with 1D elements only
-    if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( thePathMesh ))
+    // get a sub-mesh of thePathShape
+    TopoDS_Shape     aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
+    SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
+    if ( !aSubMesh )
+      return aGroups._retn();
+
+    if ( !aSubMesh->GetSubMeshDS() )
     {
-      SMESH::SMESH_Mesh_var mesh = thePathMesh->GetMesh();
-      aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
-      if ( !aMeshImp ) return aGroups._retn();
-      aSubMesh = aMeshImp->GetImpl().GetSubMeshContaining( sm->GetId() );
-      if ( !aSubMesh ) return aGroups._retn();
+      SMESHDS_Mesh * meshDS = aMeshImp->GetImpl().GetMeshDS();
+      meshDS->AddCompoundSubmesh( aShape, TopAbs_EDGE );
+      if ( !aSubMesh->GetSubMeshDS() )
+        return aGroups._retn();
     }
-    else if ( !aMeshImp ||
-              aMeshImp->NbEdges() != aMeshImp->NbElements() )
-    {
+    theError = SMESH::SMESH_MeshEditor::EXTR_PATH_NOT_EDGE;
+    pathEdgesIterator = aSubMesh->GetSubMeshDS()->GetElements();
+    if ( !pathEdgesIterator->more() ||
+         pathEdgesIterator->next()->GetType() != SMDSAbs_Edge )
       return aGroups._retn();
-    }
+
+    pathEdgesIterator = aSubMesh->GetSubMeshDS()->GetElements();
   }
   else
   {
-    if ( !aMeshImp ) return aGroups._retn();
-    TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
-    aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
-    if ( !aSubMesh /*|| !aSubMesh->GetSubMeshDS()*/ )
+    theError = SMESH::SMESH_MeshEditor::EXTR_PATH_NOT_EDGE;
+    prepareIdSource( thePathObject );
+    pathEdgesIterator = SMESH_Mesh_i::GetElements( thePathObject, SMESH::EDGE );
+    if ( !pathEdgesIterator || !pathEdgesIterator->more() )
       return aGroups._retn();
   }
 
-  SMDS_MeshNode* nodeStart =
-    (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
-  if ( !nodeStart ) {
-    theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
-    return aGroups._retn();
+  if ( !aMeshImp )
+  {
+    SMESH::SMESH_Mesh_var pathMesh = thePathObject->GetMesh();
+    aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( pathMesh );
   }
 
+
+  theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
+  const SMDS_MeshNode* nodeStart = aMeshImp->GetImpl().GetMeshDS()->FindNode( theNodeStart );
+  if ( !nodeStart )
+    return aGroups._retn();
+
+
   TIDSortedElemSet elemsNodes[2];
   for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
     if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
@@ -2914,12 +2942,11 @@ SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & the
   for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
     idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
 
-  list<double> angles;
-  for ( CORBA::ULong i = 0; i < theAngles.length(); i++ ) {
-    angles.push_back( theAngles[i] );
-  }
+  list<double> angles = ExtrusionParams::toList( theAngles );
+  list<double> scales = ExtrusionParams::toList( theScaleFactors );
 
   gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
+  const gp_Pnt *refPntPtr = theHasRefPoint ? &refPnt : 0;
 
   int nbOldGroups = myMesh->NbGroup();
 
@@ -2934,15 +2961,12 @@ SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & the
     theMakeGroups = false;
   }
 
-  ::SMESH_MeshEditor::Extrusion_Error error;
-  if ( !aSubMesh )
-    error = getEditor().ExtrusionAlongTrack( workElements, &(aMeshImp->GetImpl()), nodeStart,
-                                             theHasAngles, angles, theLinearVariation,
-                                             theHasRefPoint, refPnt, theMakeGroups );
-  else
-    error = getEditor().ExtrusionAlongTrack( workElements, aSubMesh, nodeStart,
-                                             theHasAngles, angles, theLinearVariation,
-                                             theHasRefPoint, refPnt, theMakeGroups );
+  ::SMESH_MeshEditor::Extrusion_Error error =
+      getEditor().ExtrusionAlongTrack( workElements,
+                                       &(aMeshImp->GetImpl()), pathEdgesIterator, nodeStart,
+                                       angles, theAnglesVariation,
+                                       scales, theScalesVariation,
+                                       refPntPtr, theMakeGroups );
 
   declareMeshModified( /*isReComputeSafe=*/true );
   theError = convExtrError( error );
@@ -2964,18 +2988,20 @@ SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & the
                 << theNodes            << ", "
                 << theEdges            << ", "
                 << theFaces            << ", "
-                << thePathMesh         << ", "
+                << thePathObject       << ", "
                 << thePathShape        << ", "
                 << theNodeStart        << ", "
                 << theHasAngles        << ", "
                 << TVar( theAngles )   << ", "
-                << theLinearVariation  << ", "
+                << theAnglesVariation  << ", "
                 << theHasRefPoint      << ", "
                 << "SMESH.PointStruct( "
                 << TVar( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
                 << TVar( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
                 << TVar( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
-                << theMakeGroups       << " )";
+                << theMakeGroups           << ", "
+                << TVar( theScaleFactors ) << ", "
+                << theScalesVariation      << " )";
   }
   else
   {
index d8c46a64f77641695ba48795a25469db84bdcc87..016f000554147b674d0146899692be08a592f373 100644 (file)
@@ -322,25 +322,27 @@ public:
   void RenumberNodes() throw (SALOME::SALOME_Exception);
   void RenumberElements() throw (SALOME::SALOME_Exception);
 
-  SMESH::ListOfGroups* RotationSweepObjects(const SMESH::ListOfIDSources & nodes,
-                                            const SMESH::ListOfIDSources & edges,
-                                            const SMESH::ListOfIDSources & faces,
+  SMESH::ListOfGroups* RotationSweepObjects(const SMESH::ListOfIDSources & Nodes,
+                                            const SMESH::ListOfIDSources & Edges,
+                                            const SMESH::ListOfIDSources & Faces,
                                             const SMESH::AxisStruct &      Axis,
                                             CORBA::Double                  AngleInRadians,
                                             CORBA::Long                    NbOfSteps,
                                             CORBA::Double                  Tolerance,
-                                            CORBA::Boolean                 toMakeGroups)
+                                            CORBA::Boolean                 ToMakeGroups)
     throw (SALOME::SALOME_Exception);
 
-  SMESH::ListOfGroups* ExtrusionSweepObjects(const SMESH::ListOfIDSources & nodes,
-                                             const SMESH::ListOfIDSources & edges,
-                                             const SMESH::ListOfIDSources & faces,
-                                             const SMESH::DirStruct &       stepVector,
-                                             CORBA::Long                    nbOfSteps,
-                                             const SMESH::double_array &    theScaleFactors,
-                                             CORBA::Boolean                 theLinearVariation,
-                                             const SMESH::double_array &    theBasePoint,
-                                             CORBA::Boolean                 toMakeGroups)
+  SMESH::ListOfGroups* ExtrusionSweepObjects(const SMESH::ListOfIDSources & Nodes,
+                                             const SMESH::ListOfIDSources & Edges,
+                                             const SMESH::ListOfIDSources & Faces,
+                                             const SMESH::DirStruct &       StepVector,
+                                             CORBA::Long                    NbOfSteps,
+                                             CORBA::Boolean                 ToMakeGroups,
+                                             const SMESH::double_array &    ScaleFactors,
+                                             CORBA::Boolean                 ScalesVariation,
+                                             const SMESH::double_array &    BasePoint,
+                                             const SMESH::double_array &    Angles,
+                                             CORBA::Boolean                 AnglesVariation)
     throw (SALOME::SALOME_Exception);
 
   SMESH::ListOfGroups* ExtrusionByNormal(const SMESH::ListOfIDSources& objects,
@@ -360,18 +362,20 @@ public:
     throw (SALOME::SALOME_Exception);
 
   SMESH::ListOfGroups*
-    ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & nodes,
-                              const SMESH::ListOfIDSources & edges,
-                              const SMESH::ListOfIDSources & faces,
+    ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & Nodes,
+                              const SMESH::ListOfIDSources & Edges,
+                              const SMESH::ListOfIDSources & Faces,
                               SMESH::SMESH_IDSource_ptr      PathMesh,
                               GEOM::GEOM_Object_ptr          PathShape,
                               CORBA::Long                    NodeStart,
                               CORBA::Boolean                 HasAngles,
                               const SMESH::double_array &    Angles,
-                              CORBA::Boolean                 LinearVariation,
+                              CORBA::Boolean                 AnglesVariation,
                               CORBA::Boolean                 HasRefPoint,
                               const SMESH::PointStruct &     RefPoint,
                               bool                           MakeGroups,
+                              const SMESH::double_array &    ScaleFactors,
+                              CORBA::Boolean                 ScalesVariation,
                               SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
     throw (SALOME::SALOME_Exception);
 
index 20b7bc0389f1193f49de9895aaa7a0911ddc6c8c..f3e83622c0582d6ccf3b58f73774d3a720513b6f 100755 (executable)
@@ -752,26 +752,28 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
         """
 
         if not meshes: return None
-        for i,m in enumerate(meshes):
-            if isinstance(m, Mesh):
+        if not isinstance( meshes, list ):
+            meshes = [ meshes ]
+        for i,m in enumerate( meshes ):
+            if isinstance( m, Mesh ):
                 meshes[i] = m.GetMesh()
-        mergeTolerance,Parameters,hasVars = ParseParameters(mergeTolerance)
+        mergeTolerance,Parameters,hasVars = ParseParameters( mergeTolerance )
         if hasattr(meshes[0], "SetParameters"):
-            meshes[0].SetParameters(Parameters)
+            meshes[0].SetParameters( Parameters )
         else:
-            meshes[0].GetMesh().SetParameters(Parameters)
+            meshes[0].GetMesh().SetParameters( Parameters )
         if isinstance( meshToAppendTo, Mesh ):
             meshToAppendTo = meshToAppendTo.GetMesh()
         if allGroups:
             aSmeshMesh = SMESH._objref_SMESH_Gen.ConcatenateWithGroups(
                 self,meshes,uniteIdenticalGroups,mergeNodesAndElements,
-                mergeTolerance,meshToAppendTo)
+                mergeTolerance,meshToAppendTo )
         else:
             aSmeshMesh = SMESH._objref_SMESH_Gen.Concatenate(
                 self,meshes,uniteIdenticalGroups,mergeNodesAndElements,
-                mergeTolerance,meshToAppendTo)
+                mergeTolerance,meshToAppendTo )
 
-        aMesh = Mesh(self, self.geompyD, aSmeshMesh, name=name)
+        aMesh = Mesh( self, self.geompyD, aSmeshMesh, name=name )
         return aMesh
 
     def CopyMesh( self, meshPart, meshName, toCopyGroups=False, toKeepIDs=False):
@@ -2501,6 +2503,25 @@ class Mesh(metaclass = MeshMeta):
         minor = -1
         # invoke engine's function
         self.mesh.ExportMED(fileName, auto_groups, minor, overwrite, autoDimension)
+        return
+
+
+    def Append(self, meshes, uniteIdenticalGroups = True,
+                     mergeNodesAndElements = False, mergeTolerance = 1e-5, allGroups = False):
+        """
+        Append given meshes into this mesh.
+        All groups of input meshes will be created in this mesh.
+
+        Parameters:
+                meshes: :class:`meshes, sub-meshes, groups or filters <SMESH.SMESH_IDSource>` to append
+                uniteIdenticalGroups: if True, groups with same names are united, else they are renamed
+                mergeNodesAndElements: if True, equal nodes and elements are merged
+                mergeTolerance: tolerance for merging nodes
+                allGroups: forces creation of groups corresponding to every input mesh
+        """
+        self.smeshpyD.Concatenate( meshes, uniteIdenticalGroups,
+                                   mergeNodesAndElements, mergeTolerance, allGroups,
+                                   meshToAppendTo = self.GetMesh() )
 
     # Operations with groups:
     # ----------------------
@@ -5340,7 +5361,8 @@ class Mesh(metaclass = MeshMeta):
                                          NbOfSteps, Tolerance, MakeGroups, TotalAngle)
 
     def ExtrusionSweepObjects(self, nodes, edges, faces, StepVector, NbOfSteps, MakeGroups=False,
-                              scaleFactors=[], linearVariation=False, basePoint=[] ):
+                              scaleFactors=[], linearVariation=False, basePoint=[],
+                              angles=[], anglesVariation=False):
         """
         Generate new elements by extrusion of the given elements and nodes
 
@@ -5354,15 +5376,19 @@ class Mesh(metaclass = MeshMeta):
             NbOfSteps: the number of steps
             MakeGroups: forces the generation of new groups from existing ones
             scaleFactors: optional scale factors to apply during extrusion
-            linearVariation: if *True*, scaleFactors are spread over all *scaleFactors*,
-                else scaleFactors[i] is applied to nodes at the i-th extrusion step
-            basePoint: optional scaling center; if not provided, a gravity center of
+            linearVariation: if *True*, *scaleFactors* are spread over all *NbOfSteps*,
+                else *scaleFactors* [i] is applied to nodes at the i-th extrusion step
+            basePoint: optional scaling and rotation center; if not provided, a gravity center of
                 nodes and elements being extruded is used as the scaling center.
                 It can be either
 
                         - a list of tree components of the point or
                         - a node ID or
                         - a GEOM point
+            angles: list of angles in radians. Nodes at each extrusion step are rotated 
+                around *basePoint*, additionally to previous steps.
+            anglesVariation: forces the computation of rotation angles as linear
+                variation of the given *angles* along path steps
         Returns:
             the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
 
@@ -5387,13 +5413,17 @@ class Mesh(metaclass = MeshMeta):
             basePoint = self.geompyD.PointCoordinates( basePoint )
 
         NbOfSteps,Parameters,hasVars = ParseParameters(NbOfSteps)
-        Parameters = StepVector.PS.parameters + var_separator + Parameters
+        scaleFactors,scaleParameters,hasVars = ParseParameters(scaleFactors)
+        angles,angleParameters,hasVars = ParseAngles(angles)
+        Parameters = StepVector.PS.parameters + var_separator + \
+                     Parameters + var_separator + \
+                     scaleParameters + var_separator + angleParameters
         self.mesh.SetParameters(Parameters)
 
         return self.editor.ExtrusionSweepObjects( nodes, edges, faces,
-                                                  StepVector, NbOfSteps,
+                                                  StepVector, NbOfSteps, MakeGroups,
                                                   scaleFactors, linearVariation, basePoint,
-                                                  MakeGroups)
+                                                  angles, anglesVariation )
 
 
     def ExtrusionSweep(self, IDsOfElements, StepVector, NbOfSteps, MakeGroups=False, IsNodes = False):
@@ -5555,9 +5585,10 @@ class Mesh(metaclass = MeshMeta):
         return self.editor.AdvancedExtrusion(IDsOfElements, StepVector, NbOfSteps,
                                              ExtrFlags, SewTolerance, MakeGroups)
 
-    def ExtrusionAlongPathObjects(self, Nodes, Edges, Faces, PathMesh, PathShape=None,
+    def ExtrusionAlongPathObjects(self, Nodes, Edges, Faces, PathObject, PathShape=None,
                                   NodeStart=1, HasAngles=False, Angles=[], LinearVariation=False,
-                                  HasRefPoint=False, RefPoint=[0,0,0], MakeGroups=False):
+                                  HasRefPoint=False, RefPoint=[0,0,0], MakeGroups=False,
+                                  ScaleFactors=[], ScalesVariation=False):
         """
         Generate new elements by extrusion of the given elements and nodes along the path.
         The path of extrusion must be a meshed edge.
@@ -5566,20 +5597,22 @@ class Mesh(metaclass = MeshMeta):
             Nodes: nodes to extrude: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
             Edges: edges to extrude: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
             Faces: faces to extrude: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
-            PathMesh: 1D mesh or 1D sub-mesh, along which proceeds the extrusion
-            PathShape: shape (edge) defines the sub-mesh of PathMesh if PathMesh
-                contains not only path segments, else it can be None
+            PathObject: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>` containing edges along which proceeds the extrusion
+            PathShape: optional shape (edge or wire) which defines the sub-mesh of the mesh defined by *PathObject* if the mesh contains not only path segments, else it can be None
             NodeStart: the first or the last node on the path. Defines the direction of extrusion
-            HasAngles: allows the shape to be rotated around the path
-                to get the resulting mesh in a helical fashion
-            Angles: list of angles
+            HasAngles: not used obsolete
+            Angles: list of angles in radians. Nodes at each extrusion step are rotated 
+                around *basePoint*, additionally to previous steps.
             LinearVariation: forces the computation of rotation angles as linear
                 variation of the given Angles along path steps
             HasRefPoint: allows using the reference point
-            RefPoint: the reference point around which the shape is rotated (the mass center of the
-                shape by default). The User can specify any point as the Reference Point. 
+            RefPoint: optional scaling and rotation center (mass center of the extruded
+                elements by default). The User can specify any point as the Reference Point. 
                 *RefPoint* can be either GEOM Vertex, [x,y,z] or :class:`SMESH.PointStruct`
             MakeGroups: forces the generation of new groups from existing ones
+            ScaleFactors: optional scale factors to apply during extrusion
+            ScalesVariation: if *True*, *scaleFactors* are spread over all *NbOfSteps*,
+                else *scaleFactors* [i] is applied to nodes at the i-th extrusion step
 
         Returns:
             list of created :class:`groups <SMESH.SMESH_GroupBase>` and 
@@ -5597,15 +5630,18 @@ class Mesh(metaclass = MeshMeta):
         if isinstance( RefPoint, list ):
             if not RefPoint: RefPoint = [0,0,0]
             RefPoint = SMESH.PointStruct( *RefPoint )
-        if isinstance( PathMesh, Mesh ):
-            PathMesh = PathMesh.GetMesh()
+        if isinstance( PathObject, Mesh ):
+            PathObject = PathObject.GetMesh()
         Angles,AnglesParameters,hasVars = ParseAngles(Angles)
-        Parameters = AnglesParameters + var_separator + RefPoint.parameters
+        ScaleFactors,ScalesParameters,hasVars = ParseParameters(ScaleFactors)
+        Parameters = AnglesParameters + var_separator + \
+                     RefPoint.parameters + var_separator + ScalesParameters 
         self.mesh.SetParameters(Parameters)
         return self.editor.ExtrusionAlongPathObjects(Nodes, Edges, Faces,
-                                                     PathMesh, PathShape, NodeStart,
+                                                     PathObject, PathShape, NodeStart,
                                                      HasAngles, Angles, LinearVariation,
-                                                     HasRefPoint, RefPoint, MakeGroups)
+                                                     HasRefPoint, RefPoint, MakeGroups,
+                                                     ScaleFactors, ScalesVariation)
 
     def ExtrusionAlongPathX(self, Base, Path, NodeStart,
                             HasAngles=False, Angles=[], LinearVariation=False,
@@ -5619,9 +5655,9 @@ class Mesh(metaclass = MeshMeta):
             Base: :class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>`, or list of ids of elements for extrusion
             Path: 1D mesh or 1D sub-mesh, along which proceeds the extrusion
             NodeStart: the start node from Path. Defines the direction of extrusion
-            HasAngles: allows the shape to be rotated around the path
-                to get the resulting mesh in a helical fashion
-            Angles: list of angles in radians
+            HasAngles: not used obsolete
+            Angles: list of angles in radians. Nodes at each extrusion step are rotated 
+                around *basePoint*, additionally to previous steps.
             LinearVariation: forces the computation of rotation angles as linear
                 variation of the given Angles along path steps
             HasRefPoint: allows using the reference point
@@ -5662,9 +5698,9 @@ class Mesh(metaclass = MeshMeta):
             PathMesh: mesh containing a 1D sub-mesh on the edge, along which proceeds the extrusion
             PathShape: shape (edge) defines the sub-mesh for the path
             NodeStart: the first or the last node on the edge. Defines the direction of extrusion
-            HasAngles: allows the shape to be rotated around the path
-                to get the resulting mesh in a helical fashion
-            Angles: list of angles in radians
+            HasAngles: not used obsolete
+            Angles: list of angles in radians. Nodes at each extrusion step are rotated 
+                around *basePoint*, additionally to previous steps.
             HasRefPoint: allows using the reference point
             RefPoint: the reference point around which the shape is rotated (the mass center of the shape by default).
                 The User can specify any point as the Reference Point.
@@ -5703,9 +5739,9 @@ class Mesh(metaclass = MeshMeta):
             PathMesh: mesh containing a 1D sub-mesh on the edge, along which the extrusion proceeds
             PathShape: shape (edge) defines the sub-mesh for the path
             NodeStart: the first or the last node on the edge. Defines the direction of extrusion
-            HasAngles: allows the shape to be rotated around the path
-                to get the resulting mesh in a helical fashion
-            Angles: list of angles
+            HasAngles: not used obsolete
+            Angles: list of angles in radians. Nodes at each extrusion step are rotated 
+                around *basePoint*, additionally to previous steps.
             HasRefPoint: allows using the reference point
             RefPoint: the reference point around which the shape is rotated (the mass center of the shape by default).
                 The User can specify any point as the Reference Point.
@@ -5741,9 +5777,9 @@ class Mesh(metaclass = MeshMeta):
             PathMesh: mesh containing a 1D sub-mesh on the edge, along which the extrusion proceeds
             PathShape: shape (edge) defines the sub-mesh for the path
             NodeStart: the first or the last node on the edge. Defines the direction of extrusion
-            HasAngles: allows the shape to be rotated around the path
-                to get the resulting mesh in a helical fashion
-            Angles: list of angles
+            HasAngles: not used obsolete
+            Angles: list of angles in radians. Nodes at each extrusion step are rotated 
+                around *basePoint*, additionally to previous steps.
             HasRefPoint: allows using the reference point
             RefPoint:  the reference point around which the shape is rotated (the mass center of the shape by default).
                 The User can specify any point as the Reference Point.
@@ -5779,9 +5815,9 @@ class Mesh(metaclass = MeshMeta):
             PathMesh: mesh containing a 1D sub-mesh on the edge, along which the extrusion proceeds
             PathShape: shape (edge) defines the sub-mesh for the path
             NodeStart: the first or the last node on the edge. Defines the direction of extrusion
-            HasAngles: allows the shape to be rotated around the path
-                to get the resulting mesh in a helical fashion
-            Angles: list of angles
+            HasAngles: not used obsolete
+            Angles: list of angles in radians. Nodes at each extrusion step are rotated 
+                around *basePoint*, additionally to previous steps.
             HasRefPoint: allows using the reference point
             RefPoint: the reference point around which the shape is rotated (the mass center of the shape by default).
                 The User can specify any point as the Reference Point.
index 0b684862296ee8a1bf585377aae8389421c7ab10..2f312a6f4360119ae6a323e1486ace16fd0260d5 100644 (file)
 #include "SMESHDS_Mesh.hxx"
 #include "SMESHDS_SubMesh.hxx"
 #include "SMESH_Algo.hxx"
+#include "SMESH_Block.hxx"
+#include "SMESH_ComputeError.hxx"
 #include "SMESH_Mesh.hxx"
+#include "SMESH_MeshEditor.hxx"
 #include "SMESH_MesherHelper.hxx"
-#include "SMESH_ComputeError.hxx"
-#include "SMESH_Block.hxx"
 
 #include <Adaptor2d_Curve2d.hxx>
 #include <BRepAdaptor_CompCurve.hxx>
index a313cd6a361ed0b1227aef6b2a2f648a604a3fb4..0d8466cccfe289ccadf76f2bfd434822e49a66b7 100644 (file)
@@ -36,6 +36,7 @@
 #include "SMESH_Group.hxx"
 #include "SMESH_HypoFilter.hxx"
 #include "SMESH_Mesh.hxx"
+#include "SMESH_MeshEditor.hxx"
 #include "SMESH_MesherHelper.hxx"
 #include "SMESH_subMesh.hxx"
 #include "SMESH_subMeshEventListener.hxx"
index f0d4925c82cbdad6c6a7a5d59a41926880b16409..1ab0f675356ae553e31be0ffad35bae977d4c057 100644 (file)
@@ -40,6 +40,7 @@
 #include "SMESH_Mesh.hxx"
 #include "SMESH_MesherHelper.hxx"
 #include "SMESH_OctreeNode.hxx"
+#include "SMESH_MeshEditor.hxx"
 #include "SMESH_subMesh.hxx"
 
 #include "Utils_SALOME_Exception.hxx"
index 4c82b5271a1cc56c0d5728dfb79a8e38086964d3..cb11b0613940b3ef7fd006a4037732779cdfda01 100644 (file)
@@ -33,6 +33,7 @@
 #include "SMESH_Comment.hxx"
 #include "SMESH_Gen.hxx"
 #include "SMESH_HypoFilter.hxx"
+#include "SMESH_MeshEditor.hxx"
 #include "SMESH_MesherHelper.hxx"
 #include "StdMeshers_FaceSide.hxx"
 #include "StdMeshers_ProjectionSource1D.hxx"
index 9425e9a17cc47b22a897581295511a92d7a0a156..ec175baf0c742cf478da0a57f277489a8479b1c0 100644 (file)
@@ -37,6 +37,7 @@
 #include "SMESH_Hypothesis.hxx"
 #include "SMESH_Mesh.hxx"
 #include "SMESH_MeshAlgos.hxx"
+#include "SMESH_MeshEditor.hxx"
 #include "SMESH_MesherHelper.hxx"
 #include "SMESH_subMesh.hxx"
 #include "SMESH_subMeshEventListener.hxx"
index d9b01603c42160118aaa1db7c60c4b548712a94d..79fb6f05efc8b824e99973415ec6a02d632be6fa 100644 (file)
@@ -42,6 +42,7 @@
 #include "SMESH_Gen.hxx"
 #include "SMESH_Mesh.hxx"
 #include "SMESH_MeshAlgos.hxx"
+#include "SMESH_MeshEditor.hxx"
 #include "SMESH_MesherHelper.hxx"
 #include "SMESH_Pattern.hxx"
 #include "SMESH_subMesh.hxx"
index e221883ec35d3a09e8a17c909049eca7958f151a..0ccb2aa87deaa4287f6c58837b985390a82baa99 100644 (file)
@@ -31,6 +31,7 @@
 #include "SMDS_MeshNode.hxx"
 #include "SMESHDS_Mesh.hxx"
 #include "SMESHDS_SubMesh.hxx"
+#include "SMESH_MeshEditor.hxx"
 #include "SMESH_MesherHelper.hxx"
 
 #include "utilities.h"
index a384191b2be9903701f64001acb577d3e5007b28..62488c6d686a344db9921966eabb674a5d3ba255 100644 (file)
@@ -43,6 +43,7 @@
 #include "SMESH_MesherHelper.hxx"
 #include "SMESH_ProxyMesh.hxx"
 #include "SMESH_subMesh.hxx"
+#include "SMESH_MeshEditor.hxx"
 #include "SMESH_subMeshEventListener.hxx"
 #include "StdMeshers_FaceSide.hxx"
 #include "StdMeshers_ViscousLayers2D.hxx"
index f759c4ba08470ebbb0680321be638682213de6f1..53118b73f70840bc5a0db79bbf3e0242c92d2216 100644 (file)
@@ -38,6 +38,7 @@
 #include "SMESH_Group.hxx"
 #include "SMESH_HypoFilter.hxx"
 #include "SMESH_Mesh.hxx"
+#include "SMESH_MeshEditor.hxx"
 #include "SMESH_MesherHelper.hxx"
 #include "SMESH_ProxyMesh.hxx"
 #include "SMESH_Quadtree.hxx"