Salome HOME
22833: [CEA 1346] to extrude a group of faces following the normal of each face
authoreap <eap@opencascade.com>
Fri, 23 Jan 2015 15:49:49 +0000 (18:49 +0300)
committereap <eap@opencascade.com>
Fri, 23 Jan 2015 15:49:49 +0000 (18:49 +0300)
+ Optimize Belong to geom filter
+ Avoid SIGSEGV after re-computing a mesh if showing numbers was ON before

32 files changed:
doc/salome/gui/SMESH/images/extrusion_box.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/extrusion_groups.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/extrusion_groups_res.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/extrusionalongaline1.png
doc/salome/gui/SMESH/images/extrusionalongaline2.png
doc/salome/gui/SMESH/images/extrusionalongaline3.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/extrusionbynormal_alongavgnorm.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/extrusionbynormal_useonly.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/image75.jpg [new file with mode: 0644]
doc/salome/gui/SMESH/images/image76.jpg [changed mode: 0755->0644]
doc/salome/gui/SMESH/images/image77.jpg [changed mode: 0755->0644]
doc/salome/gui/SMESH/input/basic_meshing_algos.doc
doc/salome/gui/SMESH/input/constructing_meshes.doc
doc/salome/gui/SMESH/input/extrusion.doc
doc/salome/gui/SMESH/input/modifying_meshes.doc
doc/salome/gui/SMESH/input/removing_nodes_and_elements.doc
idl/SMESH_MeshEditor.idl
src/Controls/SMESH_Controls.cxx
src/Controls/SMESH_ControlsDef.hxx
src/OBJECT/SMESH_Object.cxx
src/SMDS/SMDS_MeshElement.hxx
src/SMESH/SMESH_Algo.cxx
src/SMESH/SMESH_Algo.hxx
src/SMESH/SMESH_MeshEditor.cxx
src/SMESH/SMESH_MeshEditor.hxx
src/SMESHGUI/SMESHGUI_ExtrusionDlg.cxx
src/SMESHGUI/SMESHGUI_ExtrusionDlg.h
src/SMESHGUI/SMESHGUI_RevolutionDlg.cxx
src/SMESHGUI/SMESH_msg_en.ts
src/SMESH_I/SMESH_MeshEditor_i.cxx
src/SMESH_I/SMESH_MeshEditor_i.hxx
src/SMESH_SWIG/smeshBuilder.py

diff --git a/doc/salome/gui/SMESH/images/extrusion_box.png b/doc/salome/gui/SMESH/images/extrusion_box.png
new file mode 100644 (file)
index 0000000..fb08486
Binary files /dev/null and b/doc/salome/gui/SMESH/images/extrusion_box.png differ
diff --git a/doc/salome/gui/SMESH/images/extrusion_groups.png b/doc/salome/gui/SMESH/images/extrusion_groups.png
new file mode 100644 (file)
index 0000000..c58e397
Binary files /dev/null and b/doc/salome/gui/SMESH/images/extrusion_groups.png differ
diff --git a/doc/salome/gui/SMESH/images/extrusion_groups_res.png b/doc/salome/gui/SMESH/images/extrusion_groups_res.png
new file mode 100644 (file)
index 0000000..7063c82
Binary files /dev/null and b/doc/salome/gui/SMESH/images/extrusion_groups_res.png differ
index 0cc13d5..25dfdec 100644 (file)
Binary files a/doc/salome/gui/SMESH/images/extrusionalongaline1.png and b/doc/salome/gui/SMESH/images/extrusionalongaline1.png differ
index 987a66c..af69891 100644 (file)
Binary files a/doc/salome/gui/SMESH/images/extrusionalongaline2.png and b/doc/salome/gui/SMESH/images/extrusionalongaline2.png differ
diff --git a/doc/salome/gui/SMESH/images/extrusionalongaline3.png b/doc/salome/gui/SMESH/images/extrusionalongaline3.png
new file mode 100644 (file)
index 0000000..beb14ec
Binary files /dev/null and b/doc/salome/gui/SMESH/images/extrusionalongaline3.png differ
diff --git a/doc/salome/gui/SMESH/images/extrusionbynormal_alongavgnorm.png b/doc/salome/gui/SMESH/images/extrusionbynormal_alongavgnorm.png
new file mode 100644 (file)
index 0000000..ecb550e
Binary files /dev/null and b/doc/salome/gui/SMESH/images/extrusionbynormal_alongavgnorm.png differ
diff --git a/doc/salome/gui/SMESH/images/extrusionbynormal_useonly.png b/doc/salome/gui/SMESH/images/extrusionbynormal_useonly.png
new file mode 100644 (file)
index 0000000..1c63a2b
Binary files /dev/null and b/doc/salome/gui/SMESH/images/extrusionbynormal_useonly.png differ
diff --git a/doc/salome/gui/SMESH/images/image75.jpg b/doc/salome/gui/SMESH/images/image75.jpg
new file mode 100644 (file)
index 0000000..54718d4
Binary files /dev/null and b/doc/salome/gui/SMESH/images/image75.jpg differ
old mode 100755 (executable)
new mode 100644 (file)
index 88ec89f..cdeb880
Binary files a/doc/salome/gui/SMESH/images/image76.jpg and b/doc/salome/gui/SMESH/images/image76.jpg differ
old mode 100755 (executable)
new mode 100644 (file)
index c253eac..9205644
Binary files a/doc/salome/gui/SMESH/images/image77.jpg and b/doc/salome/gui/SMESH/images/image77.jpg differ
index 977b505..b92148c 100644 (file)
@@ -9,9 +9,9 @@ used for meshing entities (1D, 2D, 3D) composing geometrical objects.
 <li>For meshing of 1D entities (<b>edges</b>):</li>
 
 <ul>
-<li>Wire Discretization meshing algorithm - splits a wire into a
-number of mesh segments following any 1D hypothesis.</li>
-<li>Composite Side Discretization algorithm - allows to apply any 1D
+<li>Wire Discretization meshing algorithm - splits an edge into a
+number of mesh segments following an 1D hypothesis.</li>
+<li>Composite Side Discretization algorithm - allows to apply an 1D
 hypothesis to a whole side of a geometrical face even if it is
 composed of several edges provided that they form C1 curve, have the
 same hypotheses assigned and form one side in all faces of the main
index 2a1a0c3..5d65f4e 100644 (file)
@@ -314,8 +314,14 @@ click "Compute" button of the toolbar.
 </center>
 
 After the mesh computation finishes, the Mesh Computation information
-box appears. In case of a success, the box shows
-information on number of entities of different types in the mesh.
+box appears. If you close this box and click "Compute" button again,
+without previously changing hypotheses and/or algorithms, the mesh is
+NOT re-computed and the Mesh Computation information box with
+the same contents is shown. (To fully re-compute the mesh, invoke \ref
+clear_mesh_anchor "Clear Mesh Data" command before).
+
+In case of a success, the box shows information on number of entities
+of different types in the mesh.
 
 \image html meshcomputationsucceed.png
 
index 126e3b0..e3ea63c 100644 (file)
@@ -5,7 +5,11 @@
 \n Extrusion is used to build mesh elements of plus one
 dimension than the input ones. Boundary elements around elements of
 plus one dimension are additionally created. All created elements
-can be automatically grouped.
+can be automatically grouped. Extrusion can be used to create a
+\ref extrusion_struct "structured mesh from scratch".
+
+\image html extrusion_box.png "If you extruded e.g. several quadrangles, you get exactly same mesh as if you meshed a geometrical box (except that the initial quadrangles can be incorrectly oriented)"
+
 <p>Any node, segment or 2D element can be extruded. Each type of
 elements is extruded into a corresponding type of result elements:
 <table>
@@ -28,12 +32,14 @@ elements is extruded into a corresponding type of result elements:
 <em>"Extrusion" button</em>
 </center>
 
-The following dialog common for line and planar elements will appear:
+The following dialog common for node, segments and faces will appear:
 
 \image html extrusionalongaline1.png
 
 \image html extrusionalongaline2.png
 
+\image html extrusionalongaline3.png
+
 </li>
 
 <li>In this dialog:
@@ -43,7 +49,7 @@ The following dialog common for line and planar elements will appear:
   <li>Specify the IDs of the elements which will be extruded by one
     following means:
     <ul>
-      <li><b>Select the whole mesh, submesh or group</b> activating this
+      <li><b>Select the whole mesh, sub-mesh or group</b> activating this
         checkbox.</li>
       <li>Choose mesh elements with the mouse in the 3D Viewer. It is
         possible to select a whole area with a mouse frame.</li> 
@@ -54,35 +60,75 @@ The following dialog common for line and planar elements will appear:
         the \ref filtering_elements "Selection filters" page.</li> 
     </ul>
   </li>
-  <li>If the <b>Extrude to Distance</b> radio button is selected</li>
+  <li>If the <b>Extrusion to Distance</b> radio button is selected</li>
   <ul>
-    <li>specify the distance at which the elements will be extruded.</li>
+    <li>specify the translation vector by which the elements will be extruded.</li>
   </ul>
-  <li>If the <b>Extrude Along Vector</b> radio button is selected</li>
+  <li>If the <b>Extrusion Along Vector</b> radio button is selected</li>
   <ul>
-    <li>specify the coordinates of the vector along which the elements
+    <li>specify the coordinates of the \b Vector along which the elements
       will be extruded, or select the face (the normal to the face will
       define the vector),</li>
-    <li>specify the distance of extrusion along the vector.</li>
+    <li>specify the \b Distance of extrusion along the vector (it can
+    be negative).</li>
+  </ul>
+  <li>If the <b>Extrusion By Normal</b> radio button is selected,
+    which is visible in \b 2D mode only, every node of selected
+    elements is extruded along the \a average of the \a normal vectors to
+    the faces sharing the node.</li>
+  <ul>
+    <li>Specify the \b Distance of extrusion (it can be negative),</li>
+    <li>Use <b>Along average normal</b> check-box to specify along
+      what vector the distance is measured. If it is \a activated the
+      distance is measured along the average normal mentioned
+      above. If it is \a deactivated every node is extruded along the
+      average normal till its intersection with the virtual plane got
+      by translation of the face sharing the node along its own normal
+      by the distance. <br>
+      The picture below shows a cross-section of a 2D mesh extruded
+      with <b>Along average normal</b> activated (to the left) and
+      deactivated (to the right). 
+
+      \image html extrusionbynormal_alongavgnorm.png
+    <p></li>
+    <li>Using <b>Use only input elements</b> check-box to specify what
+      elements to use to compute the average normal. If it is \a
+      activated only selected faces, among faces sharing the node,
+      are used to compute the average normal at the node. Else all
+      faces sharing the node are used. <br>
+      The picture below shows a cross-section of a 2D mesh the upper
+      plane of which is extruded with <b>Use only input elements</b>
+      activated (to the left) and deactivated (to the right). 
+
+      \image html extrusionbynormal_useonly.png
+    <p></li>
   </ul>
-  <li>Specify the number of steps.</li>
+  <li>Specify the <b>Number of steps</b>.</li>
   <li>If you activate <b>Generate Groups</b> check-box, the <em>result elements</em>
-    created from <em>extruded elements</em> contained in groups will be
+    created from <em>selected elements</em> contained in groups will be
     included into new groups named by pattern "<old group
-    name>_extruded" and "<old group name>_top". For example if an
-    extruded quadrangle is included in \a Group_1 group then result
-    hexahedra will be included in \a Group_1_extruded group and a
-    quadrangle created at the "top" of extruded mesh will
-    be included in \a Group_1_top group. <br>This check-box is active
-    only if there are some groups in the mesh.</li>
+    name>_extruded" and "<old group name>_top". For example if a
+    selected quadrangle is included in \a g_Faces group (see figures
+    below) then result hexahedra will be included in \a
+    g_Faces_extruded group and a quadrangle created at the "top" of
+    extruded mesh will be included in \a g_Faces_top group. <br> 
+\image html extrusion_groups.png
+\image html extrusion_groups_res.png
+    <p> This check-box is active only if there are some groups in the mesh.
+  </li>
 </ul>
 
 <li>Click \b Apply or <b> Apply and Close</b>  button to confirm the operation.</li>
 </ol>
+\anchor extrusion_struct
+<h2>Example: creation of a structured mesh from scratch</h2>
 
-\image html image77.jpg "The mesh with an edge selected for extrusion"
+\image html image75.jpg "A node is extruded into a line of segments"
+<br>
+\image html image76.jpg "The line of segments is extruded into a quadrangle mesh"
+<br>
+\image html image77.jpg "The quadrangle mesh is revolved into a hexahedral mesh"
 
-\image html image76.jpg "The mesh with extruded edge" 
 
 <br><b>See Also</b> a sample TUI Script of an 
 \ref tui_extrusion "Extrusion" operation. 
index f09ab21..e857a96 100755 (executable)
@@ -39,7 +39,8 @@ with consequent transformation of all adjacent elements and edges.</li>
 <li>\subpage split_to_tetra_page "Split" volumic elements into tetrahedra or prisms.</li>
 <li>\subpage smoothing_page "Smooth" elements, reducung distortions in
 them by adjusting the locations of element corners.</li>
-<li>Create an \subpage extrusion_page "extrusion" along a vector.</li>
+<li>Create an \subpage extrusion_page "extrusion" along a vector or by
+normal to a discretized surface.</li>
 <li>Create an \subpage extrusion_along_path_page "extrusion along a path".</li>
 <li>Create an edge or a surface by \subpage revolution_page "revolution"
 of the selected node or edge.</li>
index 63f2f3b..fd506d2 100644 (file)
@@ -130,7 +130,7 @@ Object Browser and select Clear Mesh Data in the pop-up menu.</li>
   <li> if the mesh is computed on a geometry, then "Clear Mesh Data" removes
     all elements and nodes.</li>
   <li> if the mesh is not based on a geometry (imported, compound, created from
-    scratch etc), then "Clear Mesh Data" removes only the elements and
+    scratch etc.), then "Clear Mesh Data" removes only the elements and
     nodes computed by algorithms. If no such elements or nodes have been created, can remove nothing.</li></ul>
 
 <br><b>See Also</b> a sample TUI Script of a 
index 293c8c8..254d889 100644 (file)
@@ -587,6 +587,14 @@ module SMESH
                                                   in DirStruct      StepVector,
                                                   in long           NbOfSteps) 
       raises (SALOME::SALOME_Exception);
+    ListOfGroups ExtrusionByNormal(in SMESH_IDSource theObject,
+                                   in double         stepSize,
+                                   in long           nbOfSteps,
+                                   in boolean        byAverageNormal,
+                                   in boolean        useInputElemsOnly,
+                                   in boolean        makeGroups,
+                                   in short          dim)
+      raises (SALOME::SALOME_Exception);
 
     enum Extrusion_Error {
       EXTR_OK,
index 6311da7..9cfbc31 100644 (file)
@@ -1526,7 +1526,7 @@ SMDSAbs_ElementType Length::GetType() const
 */
 //================================================================================
 
-double Length2D::GetValue( long theElementId)
+double Length2D::GetValue( long theElementId )
 {
   TSequenceOfXYZ P;
 
@@ -1558,7 +1558,7 @@ double Length2D::GetValue( long theElementId)
         double L1 = getDistance(P( 1 ),P( 2 ));
         double L2 = getDistance(P( 2 ),P( 3 ));
         double L3 = getDistance(P( 3 ),P( 1 ));
-        aVal = Max(L1,Max(L2,L3));
+        aVal = Min(L1,Min(L2,L3));
         break;
       }
       else if (len == 4){ // quadrangles
@@ -1566,14 +1566,14 @@ double Length2D::GetValue( long theElementId)
         double L2 = getDistance(P( 2 ),P( 3 ));
         double L3 = getDistance(P( 3 ),P( 4 ));
         double L4 = getDistance(P( 4 ),P( 1 ));
-        aVal = Max(Max(L1,L2),Max(L3,L4));
+        aVal = Min(Min(L1,L2),Min(L3,L4));
         break;
       }
       if (len == 6){ // quadratic triangles
         double L1 = getDistance(P( 1 ),P( 2 )) + getDistance(P( 2 ),P( 3 ));
         double L2 = getDistance(P( 3 ),P( 4 )) + getDistance(P( 4 ),P( 5 ));
         double L3 = getDistance(P( 5 ),P( 6 )) + getDistance(P( 6 ),P( 1 ));
-        aVal = Max(L1,Max(L2,L3));
+        aVal = Min(L1,Min(L2,L3));
         //cout<<"L1="<<L1<<" L2="<<L2<<"L3="<<L3<<" aVal="<<aVal<<endl;
         break;
       }
@@ -1582,7 +1582,7 @@ double Length2D::GetValue( long theElementId)
         double L2 = getDistance(P( 3 ),P( 4 )) + getDistance(P( 4 ),P( 5 ));
         double L3 = getDistance(P( 5 ),P( 6 )) + getDistance(P( 6 ),P( 7 ));
         double L4 = getDistance(P( 7 ),P( 8 )) + getDistance(P( 8 ),P( 1 ));
-        aVal = Max(Max(L1,L2),Max(L3,L4));
+        aVal = Min(Min(L1,L2),Min(L3,L4));
         break;
       }
     case SMDSAbs_Volume:
@@ -1593,7 +1593,7 @@ double Length2D::GetValue( long theElementId)
         double L4 = getDistance(P( 1 ),P( 4 ));
         double L5 = getDistance(P( 2 ),P( 4 ));
         double L6 = getDistance(P( 3 ),P( 4 ));
-        aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
+        aVal = Min(Min(Min(L1,L2),Min(L3,L4)),Min(L5,L6));
         break;
       }
       else if (len == 5){ // piramids
@@ -1606,8 +1606,8 @@ double Length2D::GetValue( long theElementId)
         double L7 = getDistance(P( 3 ),P( 5 ));
         double L8 = getDistance(P( 4 ),P( 5 ));
 
-        aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
-        aVal = Max(aVal,Max(L7,L8));
+        aVal = Min(Min(Min(L1,L2),Min(L3,L4)),Min(L5,L6));
+        aVal = Min(aVal,Min(L7,L8));
         break;
       }
       else if (len == 6){ // pentaidres
@@ -1621,8 +1621,8 @@ double Length2D::GetValue( long theElementId)
         double L8 = getDistance(P( 2 ),P( 5 ));
         double L9 = getDistance(P( 3 ),P( 6 ));
 
-        aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
-        aVal = Max(aVal,Max(Max(L7,L8),L9));
+        aVal = Min(Min(Min(L1,L2),Min(L3,L4)),Min(L5,L6));
+        aVal = Min(aVal,Min(Min(L7,L8),L9));
         break;
       }
       else if (len == 8){ // hexaider
@@ -1639,9 +1639,9 @@ double Length2D::GetValue( long theElementId)
         double L11= getDistance(P( 3 ),P( 7 ));
         double L12= getDistance(P( 4 ),P( 8 ));
 
-        aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
-        aVal = Max(aVal,Max(Max(L7,L8),Max(L9,L10)));
-        aVal = Max(aVal,Max(L11,L12));
+        aVal = Min(Min(Min(L1,L2),Min(L3,L4)),Min(L5,L6));
+        aVal = Min(aVal,Min(Min(L7,L8),Min(L9,L10)));
+        aVal = Min(aVal,Min(L11,L12));
         break;
 
       }
@@ -1653,7 +1653,7 @@ double Length2D::GetValue( long theElementId)
         double L4 = getDistance(P( 1 ),P( 8 )) + getDistance(P( 8 ),P( 4 ));
         double L5 = getDistance(P( 2 ),P( 9 )) + getDistance(P( 9 ),P( 4 ));
         double L6 = getDistance(P( 3 ),P( 10 )) + getDistance(P( 10 ),P( 4 ));
-        aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
+        aVal = Min(Min(Min(L1,L2),Min(L3,L4)),Min(L5,L6));
         break;
       }
       else if (len == 13){ // quadratic piramids
@@ -1665,8 +1665,8 @@ double Length2D::GetValue( long theElementId)
         double L6 = getDistance(P( 2 ),P( 11 )) + getDistance(P( 11 ),P( 5 ));
         double L7 = getDistance(P( 3 ),P( 12 )) + getDistance(P( 12 ),P( 5 ));
         double L8 = getDistance(P( 4 ),P( 13 )) + getDistance(P( 13 ),P( 5 ));
-        aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
-        aVal = Max(aVal,Max(L7,L8));
+        aVal = Min(Min(Min(L1,L2),Min(L3,L4)),Min(L5,L6));
+        aVal = Min(aVal,Min(L7,L8));
         break;
       }
       else if (len == 15){ // quadratic pentaidres
@@ -1679,8 +1679,8 @@ double Length2D::GetValue( long theElementId)
         double L7 = getDistance(P( 1 ),P( 13 )) + getDistance(P( 13 ),P( 4 ));
         double L8 = getDistance(P( 2 ),P( 14 )) + getDistance(P( 14 ),P( 5 ));
         double L9 = getDistance(P( 3 ),P( 15 )) + getDistance(P( 15 ),P( 6 ));
-        aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
-        aVal = Max(aVal,Max(Max(L7,L8),L9));
+        aVal = Min(Min(Min(L1,L2),Min(L3,L4)),Min(L5,L6));
+        aVal = Min(aVal,Min(Min(L7,L8),L9));
         break;
       }
       else if (len == 20){ // quadratic hexaider
@@ -1696,9 +1696,9 @@ double Length2D::GetValue( long theElementId)
         double L10= getDistance(P( 2 ),P( 18 )) + getDistance(P( 18 ),P( 6 ));
         double L11= getDistance(P( 3 ),P( 19 )) + getDistance(P( 19 ),P( 7 ));
         double L12= getDistance(P( 4 ),P( 20 )) + getDistance(P( 20 ),P( 8 ));
-        aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
-        aVal = Max(aVal,Max(Max(L7,L8),Max(L9,L10)));
-        aVal = Max(aVal,Max(L11,L12));
+        aVal = Min(Min(Min(L1,L2),Min(L3,L4)),Min(L5,L6));
+        aVal = Min(aVal,Min(Min(L7,L8),Min(L9,L10)));
+        aVal = Min(aVal,Min(L11,L12));
         break;
 
       }
@@ -1706,7 +1706,7 @@ double Length2D::GetValue( long theElementId)
     default: aVal=-1;
     }
 
-    if (aVal <0){
+    if (aVal < 0 ) {
       return 0.;
     }
 
@@ -1724,7 +1724,7 @@ double Length2D::GetValue( long theElementId)
 
 double Length2D::GetBadRate( double Value, int /*nbNodes*/ ) const
 {
-  // meaningless as it is not quality control functor
+  // meaningless as it is not quality control functor
   return Value;
 }
 
@@ -3999,7 +3999,41 @@ void ElementsOnShape::SetAllNodes (bool theAllNodes)
 
 void ElementsOnShape::SetMesh (const SMDS_Mesh* theMesh)
 {
-  myMesh = theMesh;
+  myMeshModifTracer.SetMesh( theMesh );
+  if ( myMeshModifTracer.IsMeshModified())
+  {
+    size_t nbNodes = theMesh ? theMesh->NbNodes() : 0;
+    if ( myNodeIsChecked.size() == nbNodes )
+    {
+      std::fill( myNodeIsChecked.begin(), myNodeIsChecked.end(), false );
+    }
+    else
+    {
+      SMESHUtils::FreeVector( myNodeIsChecked );
+      SMESHUtils::FreeVector( myNodeIsOut );
+      myNodeIsChecked.resize( nbNodes, false );
+      myNodeIsOut.resize( nbNodes );
+    }
+  }
+}
+
+bool ElementsOnShape::getNodeIsOut( const SMDS_MeshNode* n, bool& isOut )
+{
+  if ( n->GetID() >= (int) myNodeIsChecked.size() ||
+       !myNodeIsChecked[ n->GetID() ])
+    return false;
+
+  isOut = myNodeIsOut[ n->GetID() ];
+  return true;
+}
+
+void ElementsOnShape::setNodeIsOut( const SMDS_MeshNode* n, bool  isOut )
+{
+  if ( n->GetID() < (int) myNodeIsChecked.size() )
+  {
+    myNodeIsChecked[ n->GetID() ] = true;
+    myNodeIsOut    [ n->GetID() ] = isOut;
+  }
 }
 
 void ElementsOnShape::SetShape (const TopoDS_Shape&       theShape,
@@ -4008,7 +4042,7 @@ void ElementsOnShape::SetShape (const TopoDS_Shape&       theShape,
   myType  = theType;
   myShape = theShape;
   if ( myShape.IsNull() ) return;
-  
+
   TopTools_IndexedMapOfShape shapesMap;
   TopAbs_ShapeEnum shapeTypes[4] = { TopAbs_SOLID, TopAbs_FACE, TopAbs_EDGE, TopAbs_VERTEX };
   TopExp_Explorer sub;
@@ -4026,6 +4060,16 @@ void ElementsOnShape::SetShape (const TopoDS_Shape&       theShape,
   myClassifiers.resize( shapesMap.Extent() );
   for ( int i = 0; i < shapesMap.Extent(); ++i )
     myClassifiers[ i ] = new TClassifier( shapesMap( i+1 ), myToler );
+
+  if ( theType == SMDSAbs_Node )
+  {
+    SMESHUtils::FreeVector( myNodeIsChecked );
+    SMESHUtils::FreeVector( myNodeIsOut );
+  }
+  else
+  {
+    std::fill( myNodeIsChecked.begin(), myNodeIsChecked.end(), false );
+  }
 }
 
 void ElementsOnShape::clearClassifiers()
@@ -4037,23 +4081,30 @@ void ElementsOnShape::clearClassifiers()
 
 bool ElementsOnShape::IsSatisfy (long elemId)
 {
+  const SMDS_Mesh*        mesh = myMeshModifTracer.GetMesh();
   const SMDS_MeshElement* elem =
-    ( myType == SMDSAbs_Node ? myMesh->FindNode( elemId ) : myMesh->FindElement( elemId ));
+    ( myType == SMDSAbs_Node ? mesh->FindNode( elemId ) : mesh->FindElement( elemId ));
   if ( !elem || myClassifiers.empty() )
     return false;
 
   for ( size_t i = 0; i < myClassifiers.size(); ++i )
   {
     SMDS_ElemIteratorPtr aNodeItr = elem->nodesIterator();
-    bool isSatisfy = myAllNodesFlag;
+    bool isSatisfy = myAllNodesFlag, isNodeOut;
     
     gp_XYZ centerXYZ (0, 0, 0);
 
     while (aNodeItr->more() && (isSatisfy == myAllNodesFlag))
     {
-      SMESH_TNodeXYZ aPnt ( aNodeItr->next() );
-      centerXYZ += aPnt;
-      isSatisfy = ! myClassifiers[i]->IsOut( aPnt );
+      const SMDS_MeshNode* n = (const SMDS_MeshNode*) aNodeItr->next();
+      if ( !getNodeIsOut( n, isNodeOut ))
+      {
+        SMESH_TNodeXYZ aPnt( n );
+        centerXYZ += aPnt;
+        isNodeOut = myClassifiers[i]->IsOut( aPnt );
+        setNodeIsOut( n, isNodeOut );
+      }
+      isSatisfy = !isNodeOut;
     }
 
     // Check the center point for volumes MantisBug 0020168
index 36b86c9..861b8a3 100644 (file)
@@ -867,14 +867,18 @@ namespace SMESH{
         double                      myTol;
       };
       void clearClassifiers();
+      bool getNodeIsOut( const SMDS_MeshNode* n, bool& isOut );
+      void setNodeIsOut( const SMDS_MeshNode* n, bool  isOut );
 
       std::vector< TClassifier* > myClassifiers;
-      const SMDS_Mesh*            myMesh;
       SMDSAbs_ElementType         myType;
       TopoDS_Shape                myShape;
       double                      myToler;
       bool                        myAllNodesFlag;
 
+      TMeshModifTracer            myMeshModifTracer;
+      std::vector<bool>           myNodeIsChecked;
+      std::vector<bool>           myNodeIsOut;
     };
 
     typedef boost::shared_ptr<ElementsOnShape> ElementsOnShapePtr;
index 71711f8..038a2a2 100644 (file)
@@ -151,48 +151,56 @@ SMESH_VisualObjDef::~SMESH_VisualObjDef()
 //=================================================================================
 vtkIdType SMESH_VisualObjDef::GetNodeObjId( int theVTKID )
 {
-        if (myLocalGrid)
-        {
-                TMapOfIds::const_iterator i = myVTK2SMDSNodes.find(theVTKID);
-                return i == myVTK2SMDSNodes.end() ? -1 : i->second;
-        }
-  return this->GetMesh()->FindNodeVtk(theVTKID)->GetID();
+  if (myLocalGrid)
+  {
+    TMapOfIds::const_iterator i = myVTK2SMDSNodes.find(theVTKID);
+    return i == myVTK2SMDSNodes.end() ? -1 : i->second;
+  }
+  const SMDS_MeshNode* aNode = 0;
+  if( this->GetMesh() )
+    aNode = this->GetMesh()->FindNodeVtk( theVTKID );
+
+  return aNode ? aNode->GetID() : -1;
 }
 
 vtkIdType SMESH_VisualObjDef::GetNodeVTKId( int theObjID )
 {
-        if (myLocalGrid)
-        {
-                TMapOfIds::const_iterator i = mySMDS2VTKNodes.find(theObjID);
+  if (myLocalGrid)
+  {
+    TMapOfIds::const_iterator i = mySMDS2VTKNodes.find(theObjID);
     return i == mySMDS2VTKNodes.end() ? -1 : i->second;
-        }
+  }
 
-        const SMDS_MeshNode* aNode = 0;
-        if( this->GetMesh() ) {
-          aNode = this->GetMesh()->FindNode(theObjID);
-        }
-        return aNode ? aNode->getVtkId() : -1;
+  const SMDS_MeshNode* aNode = 0;
+  if( this->GetMesh() ) {
+    aNode = this->GetMesh()->FindNode(theObjID);
+  }
+  return aNode ? aNode->getVtkId() : -1;
 }
 
 vtkIdType SMESH_VisualObjDef::GetElemObjId( int theVTKID )
 {
-        if (myLocalGrid)
-        {
-                TMapOfIds::const_iterator i = myVTK2SMDSElems.find(theVTKID);
-                return i == myVTK2SMDSElems.end() ? -1 : i->second;
-        }
+  if (myLocalGrid)
+  {
+    TMapOfIds::const_iterator i = myVTK2SMDSElems.find(theVTKID);
+    return i == myVTK2SMDSElems.end() ? -1 : i->second;
+  }
   return this->GetMesh()->fromVtkToSmds(theVTKID);
 }
 
 vtkIdType SMESH_VisualObjDef::GetElemVTKId( int theObjID )
 {
-        if (myLocalGrid)
-        {
-                TMapOfIds::const_iterator i = mySMDS2VTKElems.find(theObjID);
-                return i == mySMDS2VTKElems.end() ? -1 : i->second;
-        }
-  return this->GetMesh()->FindElement(theObjID)->getVtkId();
-  //return this->GetMesh()->fromSmdsToVtk(theObjID);
+  if (myLocalGrid)
+  {
+    TMapOfIds::const_iterator i = mySMDS2VTKElems.find(theObjID);
+    return i == mySMDS2VTKElems.end() ? -1 : i->second;
+  }
+
+  const SMDS_MeshElement* e = 0;
+  if ( this->GetMesh() )
+    e = this->GetMesh()->FindElement(theObjID);
+
+  return e ? e->getVtkId() : -1;
 }
 
 //=================================================================================
index f28ff59..371639b 100644 (file)
@@ -79,7 +79,7 @@ public:
   virtual int NbNodes() const;
   virtual int NbEdges() const;
   virtual int NbFaces() const;
-  inline int GetID() const { return myID; };
+  inline int GetID() const { return myID; }
 
   ///Return the type of the current element
   virtual SMDSAbs_ElementType GetType() const = 0;
index 5ec1240..dbf7ab6 100644 (file)
@@ -403,7 +403,8 @@ bool SMESH_Algo::GetNodeParamOnEdge(const SMESHDS_Mesh* theMesh,
 bool SMESH_Algo::GetSortedNodesOnEdge(const SMESHDS_Mesh*                   theMesh,
                                       const TopoDS_Edge&                    theEdge,
                                       const bool                            ignoreMediumNodes,
-                                      map< double, const SMDS_MeshNode* > & theNodes)
+                                      map< double, const SMDS_MeshNode* > & theNodes,
+                                      const SMDSAbs_ElementType             typeToCheck)
 {
   theNodes.clear();
 
@@ -423,11 +424,8 @@ bool SMESH_Algo::GetSortedNodesOnEdge(const SMESHDS_Mesh*                   theM
     while ( nIt->more() )
     {
       const SMDS_MeshNode* node = nIt->next();
-      if ( ignoreMediumNodes ) {
-        SMDS_ElemIteratorPtr elemIt = node->GetInverseElementIterator();
-        if ( elemIt->more() && elemIt->next()->IsMediumNode( node ))
-          continue;
-      }
+      if ( ignoreMediumNodes && SMESH_MesherHelper::IsMedium( node, typeToCheck ))
+        continue;
       const SMDS_PositionPtr& pos = node->GetPosition();
       if ( pos->GetTypeOfPosition() != SMDS_TOP_EDGE )
         return false;
index 4e5dc4a..ccd66bb 100644 (file)
@@ -323,12 +323,14 @@ public:
    * \param theEdge - The geometrical edge of interest
    * \param theNodes - The resulting map
    * \param ignoreMediumNodes - to store medium nodes of quadratic elements or not
+   * \param typeToCheck - type of elements to check for medium nodes
    * \retval bool - false if not all parameters are OK
    */
   static bool GetSortedNodesOnEdge(const SMESHDS_Mesh*                        theMesh,
                                    const TopoDS_Edge&                         theEdge,
                                    const bool                                 ignoreMediumNodes,
-                                   std::map< double, const SMDS_MeshNode* > & theNodes);
+                                   std::map< double, const SMDS_MeshNode* > & theNodes,
+                                   const SMDSAbs_ElementType                  typeToCheck = SMDSAbs_All);
   /*!
    * Moved to SMESH_MesherHelper
    */
index 7083261..ad57de4 100644 (file)
@@ -2180,10 +2180,6 @@ namespace
 void SMESH_MeshEditor::SplitVolumes (const TFacetOfElem & theElems,
                                      const int            theMethodFlags)
 {
-  // std-like iterator on coordinates of nodes of mesh element
-  typedef SMDS_StdIterator< SMESH_TNodeXYZ, SMDS_ElemIteratorPtr > NXyzIterator;
-  NXyzIterator xyzEnd;
-
   SMDS_VolumeTool    volTool;
   SMESH_MesherHelper helper( *GetMesh()), fHelper(*GetMesh());
   fHelper.ToFixNodeParameters( true );
@@ -4339,6 +4335,29 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement*               elem,
       }
     }
   }
+  else if ( elem->GetType() == SMDSAbs_Edge )
+  {
+    // orient a new face same as adjacent one
+    int i1, i2;
+    const SMDS_MeshElement* e;
+    TIDSortedElemSet dummy;
+    if (( e = SMESH_MeshAlgos::FindFaceInSet( nextNod[0], prevNod[0], dummy,dummy, &i1, &i2 )) ||
+        ( e = SMESH_MeshAlgos::FindFaceInSet( prevNod[1], nextNod[1], dummy,dummy, &i1, &i2 )) ||
+        ( e = SMESH_MeshAlgos::FindFaceInSet( prevNod[0], prevNod[1], dummy,dummy, &i1, &i2 )))
+    {
+      // there is an adjacent face, check order of nodes in it
+      bool sameOrder = ( Abs( i2 - i1 ) == 1 ) ? ( i2 > i1 ) : ( i2 < i1 );
+      if ( sameOrder )
+      {
+        std::swap( itNN[0],    itNN[1] );
+        std::swap( prevNod[0], prevNod[1] );
+        std::swap( nextNod[0], nextNod[1] );
+        if ( nbSame > 0 )
+          sames[0] = 1 - sames[0];
+        iNotSameNode = 1 - iNotSameNode;
+      }
+    }
+  }
 
   int iSameNode = 0, iBeforeSame = 0, iAfterSame = 0, iOpposSame = 0;
   if ( nbSame > 0 ) {
@@ -4444,11 +4463,11 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement*               elem,
                 return; // medium node on axis
               }
               else if(sames[0]==0)
-                aNewElem = aMesh->AddFace(prevNod[0], nextNod[1], prevNod[1],
-                                          nextNod[2], midlNod[1], prevNod[2]);
+                aNewElem = aMesh->AddFace(prevNod[0], prevNod[1], nextNod[1],
+                                          prevNod[2], midlNod[1], nextNod[2] );
               else // sames[0]==1
-                aNewElem = aMesh->AddFace(prevNod[0], nextNod[0], prevNod[1],
-                                          midlNod[0], nextNod[2], prevNod[2]);
+                aNewElem = aMesh->AddFace(prevNod[0], prevNod[1], nextNod[0],
+                                          prevNod[2], nextNod[2], midlNod[0]);
             }
           }
           else if ( nbDouble == 3 )
@@ -4614,8 +4633,8 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement*               elem,
 
       default:
         break;
-      }
-    }
+      } // switch ( baseType )
+    } // scope
 
     if ( !aNewElem && elem->GetType() == SMDSAbs_Face ) // try to create a polyherdal prism
     {
@@ -4669,7 +4688,8 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement*               elem,
           polyedre_nodes.resize( prevNbNodes );
       }
       aNewElem = aMesh->AddPolyhedralVolume (polyedre_nodes, quantities);
-    }
+
+    } //  // try to create a polyherdal prism
 
     if ( aNewElem ) {
       newElems.push_back( aNewElem );
@@ -4681,7 +4701,7 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement*               elem,
     for ( iNode = 0; iNode < nbNodes; iNode++ )
       prevNod[ iNode ] = nextNod[ iNode ];
 
-  } // for steps
+  } // loop on steps
 }
 
 //=======================================================================
@@ -5218,50 +5238,328 @@ SMESH_MeshEditor::RotationSweep(TIDSortedElemSet & theElems,
   return newGroupIDs;
 }
 
+//=======================================================================
+//function : ExtrusParam
+//purpose  : standard construction
+//=======================================================================
+
+SMESH_MeshEditor::ExtrusParam::ExtrusParam( const gp_Vec&  theStep,
+                                            const int      theNbSteps,
+                                            const int      theFlags,
+                                            const double   theTolerance):
+  myDir( theStep ),
+  myFlags( theFlags ),
+  myTolerance( theTolerance ),
+  myElemsToUse( NULL )
+{
+  mySteps = new TColStd_HSequenceOfReal;
+  const double stepSize = theStep.Magnitude();
+  for (int i=1; i<=theNbSteps; i++ )
+    mySteps->Append( stepSize );
+
+  if (( theFlags & EXTRUSION_FLAG_SEW ) &&
+      ( theTolerance > 0 ))
+  {
+    myMakeNodesFun = & SMESH_MeshEditor::ExtrusParam::makeNodesByDirAndSew;
+  }
+  else
+  {
+    myMakeNodesFun = & SMESH_MeshEditor::ExtrusParam::makeNodesByDir;
+  }
+}
+
+//=======================================================================
+//function : ExtrusParam
+//purpose  : steps are given explicitly
+//=======================================================================
+
+SMESH_MeshEditor::ExtrusParam::ExtrusParam( const gp_Dir&                   theDir,
+                                            Handle(TColStd_HSequenceOfReal) theSteps,
+                                            const int                       theFlags,
+                                            const double                    theTolerance):
+  myDir( theDir ),
+  mySteps( theSteps ),
+  myFlags( theFlags ),
+  myTolerance( theTolerance ),
+  myElemsToUse( NULL )
+{
+  if (( theFlags & EXTRUSION_FLAG_SEW ) &&
+      ( theTolerance > 0 ))
+  {
+    myMakeNodesFun = & SMESH_MeshEditor::ExtrusParam::makeNodesByDirAndSew;
+  }
+  else
+  {
+    myMakeNodesFun = & SMESH_MeshEditor::ExtrusParam::makeNodesByDir;
+  }
+}
 
 //=======================================================================
-//function : CreateNode
-//purpose  :
+//function : ExtrusParam
+//purpose  : for extrusion by normal
 //=======================================================================
-const SMDS_MeshNode* SMESH_MeshEditor::CreateNode(const double x,
-                                                  const double y,
-                                                  const double z,
-                                                  const double tolnode,
-                                                  SMESH_SequenceOfNode& aNodes)
+
+SMESH_MeshEditor::ExtrusParam::ExtrusParam( const double theStepSize,
+                                            const int    theNbSteps,
+                                            const int    theFlags,
+                                            const int    theDim ):
+  myDir( 1,0,0 ),
+  mySteps( new TColStd_HSequenceOfReal ),
+  myFlags( theFlags ),
+  myTolerance( 0 ),
+  myElemsToUse( NULL )
 {
-  // myLastCreatedElems.Clear();
-  // myLastCreatedNodes.Clear();
+  for (int i = 0; i < theNbSteps; i++ )
+    mySteps->Append( theStepSize );
 
-  gp_Pnt P1(x,y,z);
-  SMESHDS_Mesh * aMesh = myMesh->GetMeshDS();
+  if ( theDim == 1 )
+  {
+    myMakeNodesFun = & SMESH_MeshEditor::ExtrusParam::makeNodesByNormal1D;
+  }
+  else
+  {
+    myMakeNodesFun = & SMESH_MeshEditor::ExtrusParam::makeNodesByNormal2D;
+  }
+}
 
-  // try to search in sequence of existing nodes
-  // if aNodes.Length()>0 we 'nave to use given sequence
-  // else - use all nodes of mesh
-  if(aNodes.Length()>0) {
-    int i;
-    for(i=1; i<=aNodes.Length(); i++) {
-      gp_Pnt P2(aNodes.Value(i)->X(),aNodes.Value(i)->Y(),aNodes.Value(i)->Z());
-      if(P1.Distance(P2)<tolnode)
-        return aNodes.Value(i);
+//=======================================================================
+//function : ExtrusParam::SetElementsToUse
+//purpose  : stores elements to use for extrusion by normal, depending on
+//           state of EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY flag
+//=======================================================================
+
+void SMESH_MeshEditor::ExtrusParam::SetElementsToUse( const TIDSortedElemSet& elems )
+{
+  myElemsToUse = ToUseInpElemsOnly() ? & elems : 0;
+}
+
+//=======================================================================
+//function : ExtrusParam::beginStepIter
+//purpose  : prepare iteration on steps
+//=======================================================================
+
+void SMESH_MeshEditor::ExtrusParam::beginStepIter( bool withMediumNodes )
+{
+  myWithMediumNodes = withMediumNodes;
+  myNextStep = 1;
+  myCurSteps.clear();
+}
+//=======================================================================
+//function : ExtrusParam::moreSteps
+//purpose  : are there more steps?
+//=======================================================================
+
+bool SMESH_MeshEditor::ExtrusParam::moreSteps()
+{
+  return myNextStep <= mySteps->Length() || !myCurSteps.empty();
+}
+//=======================================================================
+//function : ExtrusParam::nextStep
+//purpose  : returns the next step
+//=======================================================================
+
+double SMESH_MeshEditor::ExtrusParam::nextStep()
+{
+  double res = 0;
+  if ( !myCurSteps.empty() )
+  {
+    res = myCurSteps.back();
+    myCurSteps.pop_back();
+  }
+  else if ( myNextStep <= mySteps->Length() )
+  {
+    myCurSteps.push_back( mySteps->Value( myNextStep ));
+    ++myNextStep;
+    if ( myWithMediumNodes )
+    {
+      myCurSteps.back() /= 2.;
+      myCurSteps.push_back( myCurSteps.back() );
     }
+    res = nextStep();
   }
-  else {
-    SMDS_NodeIteratorPtr itn = aMesh->nodesIterator();
-    while(itn->more()) {
-      const SMDS_MeshNode* aN = static_cast<const SMDS_MeshNode*> (itn->next());
-      gp_Pnt P2(aN->X(),aN->Y(),aN->Z());
-      if(P1.Distance(P2)<tolnode)
-        return aN;
+  return res;
+}
+
+//=======================================================================
+//function : ExtrusParam::makeNodesByDir
+//purpose  : create nodes for standard extrusion
+//=======================================================================
+
+int SMESH_MeshEditor::ExtrusParam::
+makeNodesByDir( SMESHDS_Mesh*                     mesh,
+                const SMDS_MeshNode*              srcNode,
+                std::list<const SMDS_MeshNode*> & newNodes,
+                const bool                        makeMediumNodes)
+{
+  gp_XYZ p = SMESH_TNodeXYZ( srcNode );
+
+  int nbNodes = 0;
+  for ( beginStepIter( makeMediumNodes ); moreSteps(); ++nbNodes ) // loop on steps
+  {
+    p += myDir.XYZ() * nextStep();
+    const SMDS_MeshNode * newNode = mesh->AddNode( p.X(), p.Y(), p.Z() );
+    newNodes.push_back( newNode );
+  }
+  return nbNodes;
+}
+
+//=======================================================================
+//function : ExtrusParam::makeNodesByDirAndSew
+//purpose  : create nodes for standard extrusion with sewing
+//=======================================================================
+
+int SMESH_MeshEditor::ExtrusParam::
+makeNodesByDirAndSew( SMESHDS_Mesh*                     mesh,
+                      const SMDS_MeshNode*              srcNode,
+                      std::list<const SMDS_MeshNode*> & newNodes,
+                      const bool                        makeMediumNodes)
+{
+  gp_XYZ P1 = SMESH_TNodeXYZ( srcNode );
+
+  int nbNodes = 0;
+  for ( beginStepIter( makeMediumNodes ); moreSteps(); ++nbNodes ) // loop on steps
+  {
+    P1 += myDir.XYZ() * nextStep();
+
+    // try to search in sequence of existing nodes
+    // if myNodes.Length()>0 we 'nave to use given sequence
+    // else - use all nodes of mesh
+    const SMDS_MeshNode * node = 0;
+    if ( myNodes.Length() > 0 ) {
+      int i;
+      for(i=1; i<=myNodes.Length(); i++) {
+        gp_XYZ P2 = SMESH_TNodeXYZ( myNodes.Value(i) );
+        if (( P1 - P2 ).SquareModulus() < myTolerance * myTolerance )
+        {
+          node = myNodes.Value(i);
+          break;
+        }
+      }
     }
+    else {
+      SMDS_NodeIteratorPtr itn = mesh->nodesIterator();
+      while(itn->more()) {
+        SMESH_TNodeXYZ P2( itn->next() );
+        if (( P1 - P2 ).SquareModulus() < myTolerance * myTolerance )
+        {
+          node = P2._node;
+          break;
+        }
+      }
+    }
+
+    if ( !node )
+      node = mesh->AddNode( P1.X(), P1.Y(), P1.Z() );
+
+    newNodes.push_back( node );
+
+  } // loop on steps
+
+  return nbNodes;
+}
+
+//=======================================================================
+//function : ExtrusParam::makeNodesByNormal2D
+//purpose  : create nodes for extrusion using normals of faces
+//=======================================================================
+
+int SMESH_MeshEditor::ExtrusParam::
+makeNodesByNormal2D( SMESHDS_Mesh*                     mesh,
+                     const SMDS_MeshNode*              srcNode,
+                     std::list<const SMDS_MeshNode*> & newNodes,
+                     const bool                        makeMediumNodes)
+{
+  const bool alongAvgNorm = ( myFlags & EXTRUSION_FLAG_BY_AVG_NORMAL );
+
+  gp_XYZ p = SMESH_TNodeXYZ( srcNode );
+
+  // get normals to faces sharing srcNode
+  vector< gp_XYZ > norms, baryCenters;
+  gp_XYZ norm, avgNorm( 0,0,0 );
+  SMDS_ElemIteratorPtr faceIt = srcNode->GetInverseElementIterator( SMDSAbs_Face );
+  while ( faceIt->more() )
+  {
+    const SMDS_MeshElement* face = faceIt->next();
+    if ( myElemsToUse && !myElemsToUse->count( face ))
+      continue;
+    if ( SMESH_MeshAlgos::FaceNormal( face, norm, /*normalized=*/true ))
+    {
+      norms.push_back( norm );
+      avgNorm += norm;
+      if ( !alongAvgNorm )
+      {
+        gp_XYZ bc(0,0,0);
+        int nbN = 0;
+        for ( SMDS_ElemIteratorPtr nIt = face->nodesIterator(); nIt->more(); ++nbN )
+          bc += SMESH_TNodeXYZ( nIt->next() );
+        baryCenters.push_back( bc / nbN );
+      }
+    }
+  }
+
+  if ( norms.empty() ) return 0;
+
+  double normSize = avgNorm.Modulus();
+  if ( normSize < std::numeric_limits<double>::min() )
+    return 0;
+
+  if ( myFlags & EXTRUSION_FLAG_BY_AVG_NORMAL ) // extrude along avgNorm
+  {
+    myDir = avgNorm;
+    return makeNodesByDir( mesh, srcNode, newNodes, makeMediumNodes );
   }
 
-  // create new node and return it
-  const SMDS_MeshNode* NewNode = aMesh->AddNode(x,y,z);
-  //myLastCreatedNodes.Append(NewNode);
-  return NewNode;
+  avgNorm /= normSize;
+
+  int nbNodes = 0;
+  for ( beginStepIter( makeMediumNodes ); moreSteps(); ++nbNodes ) // loop on steps
+  {
+    gp_XYZ pNew = p;
+    double stepSize = nextStep();
+
+    if ( norms.size() > 1 )
+    {
+      for ( size_t iF = 0; iF < norms.size(); ++iF ) // loop on faces
+      {
+        // translate plane of a face
+        baryCenters[ iF ] += norms[ iF ] * stepSize;
+
+        // find point of intersection of the face plane located at baryCenters[ iF ]
+        // and avgNorm located at pNew
+        double d    = -( norms[ iF ] * baryCenters[ iF ]); // d of plane equation ax+by+cz+d=0
+        double dot  = ( norms[ iF ] * avgNorm );
+        if ( dot < std::numeric_limits<double>::min() )
+          dot = stepSize * 1e-3;
+        double step = -( norms[ iF ] * pNew + d ) / dot;
+        pNew += step * avgNorm;
+      }
+    }
+    else
+    {
+      pNew += stepSize * avgNorm;
+    }
+    p = pNew;
+
+    const SMDS_MeshNode * newNode = mesh->AddNode( p.X(), p.Y(), p.Z() );
+    newNodes.push_back( newNode );
+  }
+  return nbNodes;
 }
 
+//=======================================================================
+//function : ExtrusParam::makeNodesByNormal1D
+//purpose  : create nodes for extrusion using normals of edges
+//=======================================================================
+
+int SMESH_MeshEditor::ExtrusParam::
+makeNodesByNormal1D( SMESHDS_Mesh*                     mesh,
+                     const SMDS_MeshNode*              srcNode,
+                     std::list<const SMDS_MeshNode*> & newNodes,
+                     const bool                        makeMediumNodes)
+{
+  throw SALOME_Exception("Extrusion 1D by Normal not implemented");
+  return 0;
+}
 
 //=======================================================================
 //function : ExtrusionSweep
@@ -5273,20 +5571,11 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet &   theElems,
                                   const gp_Vec&        theStep,
                                   const int            theNbSteps,
                                   TTElemOfElemListMap& newElemsMap,
-                                  const bool           theMakeGroups,
                                   const int            theFlags,
                                   const double         theTolerance)
 {
-  ExtrusParam aParams;
-  aParams.myDir = gp_Dir(theStep);
-  aParams.myNodes.Clear();
-  aParams.mySteps = new TColStd_HSequenceOfReal;
-  int i;
-  for(i=1; i<=theNbSteps; i++)
-    aParams.mySteps->Append(theStep.Magnitude());
-
-  return
-    ExtrusionSweep(theElems,aParams,newElemsMap,theMakeGroups,theFlags,theTolerance);
+  ExtrusParam aParams( theStep, theNbSteps, theFlags, theTolerance );
+  return ExtrusionSweep( theElems, aParams, newElemsMap );
 }
 
 
@@ -5298,10 +5587,7 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet &   theElems,
 SMESH_MeshEditor::PGroupIDs
 SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet &   theElems,
                                   ExtrusParam&         theParams,
-                                  TTElemOfElemListMap& newElemsMap,
-                                  const bool           theMakeGroups,
-                                  const int            theFlags,
-                                  const double         theTolerance)
+                                  TTElemOfElemListMap& newElemsMap)
 {
   myLastCreatedElems.Clear();
   myLastCreatedNodes.Clear();
@@ -5311,7 +5597,8 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet &   theElems,
 
   SMESHDS_Mesh* aMesh = GetMeshDS();
 
-  int nbsteps = theParams.mySteps->Length();
+  const int nbSteps = theParams.NbSteps();
+  theParams.SetElementsToUse( theElems );
 
   TNodeOfNodeListMap mapNewNodes;
   //TNodeOfNodeVecMap mapNewNodes;
@@ -5323,14 +5610,16 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet &   theElems,
                                      myMesh->NbVolumes(ORDER_QUADRATIC) );
   // loop on theElems
   TIDSortedElemSet::iterator itElem;
-  for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
+  for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
+  {
     // check element type
     const SMDS_MeshElement* elem = *itElem;
     if ( !elem  || elem->GetType() == SMDSAbs_Volume )
       continue;
 
+    const size_t nbNodes = elem->NbNodes();
     vector<TNodeOfNodeListMapItr> & newNodesItVec = mapElemNewNodes[ elem ];
-    newNodesItVec.reserve( elem->NbNodes() );
+    newNodesItVec.reserve( nbNodes );
 
     // loop on elem nodes
     SMDS_ElemIteratorPtr itN = elem->nodesIterator();
@@ -5359,55 +5648,33 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet &   theElems,
               needMediumNodes = true;
           }
         }
-
-        double coord[] = { node->X(), node->Y(), node->Z() };
-        for ( int i = 0; i < nbsteps; i++ )
+        // create nodes for all steps
+        if ( theParams.MakeNodes( GetMeshDS(), node, listNewNodes, needMediumNodes ))
         {
-          if ( needMediumNodes ) // create a medium node
+          list<const SMDS_MeshNode*>::iterator newNodesIt = listNewNodes.begin();
+          for ( ; newNodesIt != listNewNodes.end(); ++newNodesIt )
           {
-            double x = coord[0] + theParams.myDir.X()*theParams.mySteps->Value(i+1)/2.;
-            double y = coord[1] + theParams.myDir.Y()*theParams.mySteps->Value(i+1)/2.;
-            double z = coord[2] + theParams.myDir.Z()*theParams.mySteps->Value(i+1)/2.;
-            if( theFlags & EXTRUSION_FLAG_SEW ) {
-              const SMDS_MeshNode * newNode = CreateNode(x, y, z,
-                                                         theTolerance, theParams.myNodes);
-              listNewNodes.push_back( newNode );
-            }
-            else {
-              const SMDS_MeshNode * newNode = aMesh->AddNode(x, y, z);
-              myLastCreatedNodes.Append(newNode);
-              srcNodes.Append( node );
-              listNewNodes.push_back( newNode );
-            }
-          }
-          // create a corner node
-          coord[0] = coord[0] + theParams.myDir.X()*theParams.mySteps->Value(i+1);
-          coord[1] = coord[1] + theParams.myDir.Y()*theParams.mySteps->Value(i+1);
-          coord[2] = coord[2] + theParams.myDir.Z()*theParams.mySteps->Value(i+1);
-          if( theFlags & EXTRUSION_FLAG_SEW ) {
-            const SMDS_MeshNode * newNode = CreateNode(coord[0], coord[1], coord[2],
-                                                       theTolerance, theParams.myNodes);
-            listNewNodes.push_back( newNode );
-          }
-          else {
-            const SMDS_MeshNode * newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
-            myLastCreatedNodes.Append(newNode);
+            myLastCreatedNodes.Append( *newNodesIt );
             srcNodes.Append( node );
-            listNewNodes.push_back( newNode );
           }
         }
+        else
+        {
+          break; // newNodesItVec will be shorter than nbNodes
+        }
       }
       newNodesItVec.push_back( nIt );
     }
     // make new elements
-    sweepElement( elem, newNodesItVec, newElemsMap[elem], nbsteps, srcElems );
+    if ( newNodesItVec.size() == nbNodes )
+      sweepElement( elem, newNodesItVec, newElemsMap[elem], nbSteps, srcElems );
   }
 
-  if( theFlags & EXTRUSION_FLAG_BOUNDARY ) {
-    makeWalls( mapNewNodes, newElemsMap, mapElemNewNodes, theElems, nbsteps, srcElems );
+  if ( theParams.ToMakeBoundary() ) {
+    makeWalls( mapNewNodes, newElemsMap, mapElemNewNodes, theElems, nbSteps, srcElems );
   }
   PGroupIDs newGroupIDs;
-  if ( theMakeGroups )
+  if ( theParams.ToMakeGroups() )
     newGroupIDs = generateGroups( srcNodes, srcElems, "extruded");
 
   return newGroupIDs;
index 014437c..51b54ef 100644 (file)
@@ -240,35 +240,100 @@ public:
   // by theAngle by theNbSteps
 
   /*!
-   * Auxilary flag for advanced extrusion.
+   * Flags of extrusion.
    * BOUNDARY: create or not boundary for result of extrusion
    * SEW:      try to use existing nodes or create new nodes in any case
+   * GROUPS:   to create groups
+   * BY_AVG_NORMAL: step size is measured along average normal to elements,
+   *                else step size is measured along average normal of any element
+   * USE_INPUT_ELEMS_ONLY: to use only input elements to compute extrusion direction
+   *                       for ExtrusionByNormal()
    */
   enum ExtrusionFlags {
     EXTRUSION_FLAG_BOUNDARY = 0x01,
-    EXTRUSION_FLAG_SEW = 0x02
+    EXTRUSION_FLAG_SEW = 0x02,
+    EXTRUSION_FLAG_GROUPS = 0x04,
+    EXTRUSION_FLAG_BY_AVG_NORMAL = 0x08,
+    EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY = 0x10
   };
-  
+
   /*!
-   * special structure for control of extrusion functionality
+   * Generator of nodes for extrusion functionality
    */
-  struct ExtrusParam {
-    gp_Dir myDir; // direction of extrusion
+  class ExtrusParam {
+    gp_Dir                          myDir;   // direction of extrusion
     Handle(TColStd_HSequenceOfReal) mySteps; // magnitudes for each step
-    SMESH_SequenceOfNode myNodes; // nodes for using in sewing
+    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:
+    ExtrusParam( const gp_Vec&  theStep,
+                 const int      theNbSteps,
+                 const int      theFlags = 0,
+                 const double   theTolerance = 1e-6);
+    ExtrusParam( const gp_Dir&                   theDir,
+                 Handle(TColStd_HSequenceOfReal) theSteps,
+                 const int                       theFlags = 0,
+                 const double                    theTolerance = 1e-6);
+    ExtrusParam( const double theStep,
+                 const int    theNbSteps,
+                 const int    theFlags,
+                 const int    theDim); // for extrusion by normal
+
+    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; }
+    int  NbSteps()           const { return mySteps->Length(); }
+
+    // stores elements to use for extrusion by normal, depending on
+    // state of EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY flag
+    void SetElementsToUse( const TIDSortedElemSet& elems );
+
+    // creates nodes and returns number of nodes added in \a newNodes
+    int MakeNodes( SMESHDS_Mesh*                     mesh,
+                   const SMDS_MeshNode*              srcNode,
+                   std::list<const SMDS_MeshNode*> & newNodes,
+                   const bool                        makeMediumNodes)
+    {
+      return (this->*myMakeNodesFun)( mesh, srcNode, newNodes, makeMediumNodes );
+    }
+  private:
+
+    int makeNodesByDir( SMESHDS_Mesh*                     mesh,
+                        const SMDS_MeshNode*              srcNode,
+                        std::list<const SMDS_MeshNode*> & newNodes,
+                        const bool                        makeMediumNodes);
+    int makeNodesByDirAndSew( SMESHDS_Mesh*                     mesh,
+                              const SMDS_MeshNode*              srcNode,
+                              std::list<const SMDS_MeshNode*> & newNodes,
+                              const bool                        makeMediumNodes);
+    int makeNodesByNormal2D( SMESHDS_Mesh*                     mesh,
+                             const SMDS_MeshNode*              srcNode,
+                             std::list<const SMDS_MeshNode*> & newNodes,
+                             const bool                        makeMediumNodes);
+    int makeNodesByNormal1D( SMESHDS_Mesh*                     mesh,
+                             const SMDS_MeshNode*              srcNode,
+                             std::list<const SMDS_MeshNode*> & newNodes,
+                             const bool                        makeMediumNodes);
+    // step iteration
+    void   beginStepIter( bool withMediumNodes );
+    bool   moreSteps();
+    double nextStep();
+    std::vector< double > myCurSteps;
+    bool                  myWithMediumNodes;
+    int                   myNextStep;
   };
 
   /*!
-   * Create new node in the mesh with given coordinates
-   * (auxiliary for advanced extrusion)
-   */
-  const SMDS_MeshNode* CreateNode(const double x,
-                                  const double y,
-                                  const double z,
-                                  const double tolnode,
-                                  SMESH_SequenceOfNode& aNodes);
-
-  /*!
    * Generate new elements by extrusion of theElements
    * It is a method used in .idl file. All functionality
    * is implemented in the next method (see below) which
@@ -284,8 +349,7 @@ public:
                             const gp_Vec&        theStep,
                             const int            theNbSteps,
                             TTElemOfElemListMap& newElemsMap,
-                            const bool           theMakeGroups,
-                            const int            theFlags = EXTRUSION_FLAG_BOUNDARY,
+                            const int            theFlags,
                             const double         theTolerance = 1.e-6);
   
   /*!
@@ -300,10 +364,7 @@ public:
    */
   PGroupIDs ExtrusionSweep (TIDSortedElemSet &   theElems,
                             ExtrusParam&         theParams,
-                            TTElemOfElemListMap& newElemsMap,
-                            const bool           theMakeGroups,
-                            const int            theFlags,
-                            const double         theTolerance);
+                            TTElemOfElemListMap& newElemsMap);
 
 
   // Generate new elements by extrusion of theElements 
index 798b6b9..0dcc27c 100644 (file)
@@ -116,20 +116,20 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule)
   ConstructorsBoxLayout->setSpacing(SPACING);
   ConstructorsBoxLayout->setMargin(MARGIN);
 
-  RadioButton0= new QRadioButton(ConstructorsBox);
-  RadioButton0->setIcon(image3);
-  RadioButton1= new QRadioButton(ConstructorsBox);
-  RadioButton1->setIcon(image0);
-  RadioButton2= new QRadioButton(ConstructorsBox);
-  RadioButton2->setIcon(image1);
+  Contructor_RBut0= new QRadioButton(ConstructorsBox);
+  Contructor_RBut0->setIcon(image3);
+  Contructor_RBut1= new QRadioButton(ConstructorsBox);
+  Contructor_RBut1->setIcon(image0);
+  Contructor_RBut2= new QRadioButton(ConstructorsBox);
+  Contructor_RBut2->setIcon(image1);
 
-  ConstructorsBoxLayout->addWidget(RadioButton0);
-  ConstructorsBoxLayout->addWidget(RadioButton1);
-  ConstructorsBoxLayout->addWidget(RadioButton2);
+  ConstructorsBoxLayout->addWidget(Contructor_RBut0);
+  ConstructorsBoxLayout->addWidget(Contructor_RBut1);
+  ConstructorsBoxLayout->addWidget(Contructor_RBut2);
 
-  GroupConstructors->addButton(RadioButton0, 0);
-  GroupConstructors->addButton(RadioButton1, 1);
-  GroupConstructors->addButton(RadioButton2, 2);
+  GroupConstructors->addButton(Contructor_RBut0, 0);
+  GroupConstructors->addButton(Contructor_RBut1, 1);
+  GroupConstructors->addButton(Contructor_RBut2, 2);
 
   /***************************************************************/
   GroupButtons = new QGroupBox(this);
@@ -178,10 +178,12 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule)
   // Control for the whole mesh selection
   CheckBoxMesh = new QCheckBox(tr("SMESH_SELECT_WHOLE_MESH"), GroupArguments);
 
-  RadioButton3 = new QRadioButton(GroupArguments);
-  RadioButton3->setText( tr("SMESH_EXTRUSION_TO_DISTANCE") );
-  RadioButton4 = new QRadioButton(GroupArguments);
-  RadioButton4->setText( tr("SMESH_EXTRUSION_ALONG_VECTOR") );
+  ExtrMethod_RBut0 = new QRadioButton(GroupArguments);
+  ExtrMethod_RBut0->setText( tr("SMESH_EXTRUSION_TO_DISTANCE") );
+  ExtrMethod_RBut1 = new QRadioButton(GroupArguments);
+  ExtrMethod_RBut1->setText( tr("SMESH_EXTRUSION_ALONG_VECTOR") );
+  ExtrMethod_RBut2 = new QRadioButton(GroupArguments);
+  ExtrMethod_RBut2->setText( tr("SMESH_EXTRUSION_BY_NORMAL") );
 
   //Control for the Distance selection
   TextLabelDistance = new QLabel(tr("SMESH_DISTANCE"), GroupArguments);
@@ -221,6 +223,12 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule)
   // CheckBox for groups generation
   MakeGroupsCheck = new QCheckBox(tr("SMESH_MAKE_GROUPS"), GroupArguments);
 
+  // CheckBox for ByAverageNormal arg of ExtrusionByNormal()
+  ByAverageNormalCheck = new QCheckBox(tr("BY_AVERAGE_NORMAL"), GroupArguments);
+
+  // CheckBox for UseInputElemsOnly arg of ExtrusionByNormal()
+  UseInputElemsOnlyCheck = new QCheckBox(tr("USE_INPUT_ELEMS_ONLY"), GroupArguments);
+
   //Preview check box
   myPreviewCheckBox = new QCheckBox(tr("PREVIEW"), GroupArguments);
 
@@ -229,8 +237,9 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule)
   GroupArgumentsLayout->addWidget(LineEditElements,     0, 2, 1, 5);
   GroupArgumentsLayout->addWidget(myFilterBtn,          0, 7);
   GroupArgumentsLayout->addWidget(CheckBoxMesh,         1, 0, 1, 8);
-  GroupArgumentsLayout->addWidget(RadioButton3,         2, 1, 1, 3);
-  GroupArgumentsLayout->addWidget(RadioButton4,         2, 5, 1, 3);
+  GroupArgumentsLayout->addWidget(ExtrMethod_RBut0,     2, 0, 1, 3);
+  GroupArgumentsLayout->addWidget(ExtrMethod_RBut1,     2, 3, 1, 3);
+  GroupArgumentsLayout->addWidget(ExtrMethod_RBut2,     2, 6, 1, 3);
   GroupArgumentsLayout->addWidget(TextLabelDistance,    3, 0);
   GroupArgumentsLayout->addWidget(TextLabelDx,          3, 2);
   GroupArgumentsLayout->addWidget(SpinBox_Dx,           3, 3);
@@ -247,12 +256,14 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule)
   GroupArgumentsLayout->addWidget(TextLabelVz,          4, 6);
   GroupArgumentsLayout->addWidget(SpinBox_Vz,           4, 7);
   GroupArgumentsLayout->addWidget(TextLabelDist,        5, 0);
-  GroupArgumentsLayout->addWidget(SpinBox_VDist,         5, 3);
+  GroupArgumentsLayout->addWidget(SpinBox_VDist,        5, 3);
   GroupArgumentsLayout->addWidget(TextLabelNbSteps,     6, 0, 1, 3);
   GroupArgumentsLayout->addWidget(SpinBox_NbSteps,      6, 3);
-  GroupArgumentsLayout->addWidget(myPreviewCheckBox,    7, 0, 1, 8);
-  GroupArgumentsLayout->addWidget(MakeGroupsCheck,      8, 0, 1, 8);
-  GroupArgumentsLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding), 8, 0);
+  GroupArgumentsLayout->addWidget(ByAverageNormalCheck,   7, 0, 1, 4);
+  GroupArgumentsLayout->addWidget(UseInputElemsOnlyCheck, 7, 4, 1, 4);
+  GroupArgumentsLayout->addWidget(myPreviewCheckBox,    8, 0, 1, 8);
+  GroupArgumentsLayout->addWidget(MakeGroupsCheck,      9, 0, 1, 8);
+  GroupArgumentsLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding), 10, 0);
 
 
   /***************************************************************/
@@ -261,19 +272,20 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule)
   SMESHGUI_ExtrusionDlgLayout->addWidget(GroupButtons);
 
   /* Initialisations */
-  SpinBox_Vx->RangeStepAndValidator(COORD_MIN, COORD_MAX, 0.01, "length_precision");
-  SpinBox_Vy->RangeStepAndValidator(COORD_MIN, COORD_MAX, 0.01, "length_precision");
-  SpinBox_Vz->RangeStepAndValidator(COORD_MIN, COORD_MAX, 0.01, "length_precision");
+  SpinBox_Vx->RangeStepAndValidator(COORD_MIN, COORD_MAX, 0.1, "length_precision");
+  SpinBox_Vy->RangeStepAndValidator(COORD_MIN, COORD_MAX, 0.1, "length_precision");
+  SpinBox_Vz->RangeStepAndValidator(COORD_MIN, COORD_MAX, 0.1, "length_precision");
 
   SpinBox_Dx->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
   SpinBox_Dy->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
   SpinBox_Dz->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
   
   SpinBox_NbSteps->setRange(1, 999999);
-  SpinBox_VDist->RangeStepAndValidator(0, COORD_MAX, 10.0, "length_precision");
+  SpinBox_VDist->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
 
-  RadioButton0->setChecked(true);
-  RadioButton3->setChecked(true);
+  Contructor_RBut0->setChecked(true);
+  ExtrMethod_RBut0->setChecked(true);
+  UseInputElemsOnlyCheck->setChecked(true);
   MakeGroupsCheck->setChecked(true);
 
   mySelector = (SMESH::GetViewWindow( mySMESHGUI ))->GetSelector();
@@ -309,8 +321,9 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule)
   connect(buttonApply,  SIGNAL(clicked()), this, SLOT(ClickOnApply()));
   connect(buttonHelp,   SIGNAL(clicked()), this, SLOT(ClickOnHelp()));
 
-  connect(RadioButton3, SIGNAL(clicked()), this, SLOT(ClickOnRadio()));
-  connect(RadioButton4, SIGNAL(clicked()), this, SLOT(ClickOnRadio()));
+  connect(ExtrMethod_RBut0, SIGNAL(clicked()), this, SLOT(ClickOnRadio()));
+  connect(ExtrMethod_RBut1, SIGNAL(clicked()), this, SLOT(ClickOnRadio()));
+  connect(ExtrMethod_RBut2, SIGNAL(clicked()), this, SLOT(ClickOnRadio()));
 
   // to update state of the Ok & Apply buttons
   connect(SpinBox_Vx, SIGNAL(valueChanged(double)), SLOT(CheckIsEnable()));
@@ -330,14 +343,16 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule)
   connect(LineEditElements,     SIGNAL(textChanged(const QString&)), SLOT(onTextChange(const QString&)));
   connect(CheckBoxMesh,         SIGNAL(toggled(bool)),               SLOT(onSelectMesh(bool)));
 
-  connect(SpinBox_Dx,  SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
-  connect(SpinBox_Dy,  SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
-  connect(SpinBox_Dz,  SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
-  connect(SpinBox_Vx,  SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
-  connect(SpinBox_Vy,  SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
-  connect(SpinBox_Vz,  SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
-  connect(SpinBox_VDist,  SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
-  connect(SpinBox_NbSteps,  SIGNAL(valueChanged(int)), this, SLOT(toDisplaySimulation()));
+  connect(SpinBox_Dx,      SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
+  connect(SpinBox_Dy,      SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
+  connect(SpinBox_Dz,      SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
+  connect(SpinBox_Vx,      SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
+  connect(SpinBox_Vy,      SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
+  connect(SpinBox_Vz,      SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
+  connect(SpinBox_VDist,   SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
+  connect(SpinBox_NbSteps, SIGNAL(valueChanged(int)),    this, SLOT(toDisplaySimulation()));
+  connect(ByAverageNormalCheck,   SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation()));
+  connect(UseInputElemsOnlyCheck, SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation()));
 
   //To Connect preview check box
   connectPreviewControl();
@@ -416,17 +431,22 @@ void SMESHGUI_ExtrusionDlg::CheckIsEnable()
 //=================================================================================
 bool SMESHGUI_ExtrusionDlg::isValuesValid() {
   double aX, aY, aZ, aModule = 0;
-  if ( RadioButton3->isChecked() ) {
+  if ( ExtrMethod_RBut0->isChecked() ) {
     aX = SpinBox_Dx->GetValue();
     aY = SpinBox_Dy->GetValue();
     aZ = SpinBox_Dz->GetValue();
     aModule = sqrt(aX*aX + aY*aY + aZ*aZ);
-  } else   if ( RadioButton4->isChecked() ) {
+  }
+  else if ( ExtrMethod_RBut1->isChecked() ) {
     aX = SpinBox_Vx->GetValue();
     aY = SpinBox_Vy->GetValue();
     aZ = SpinBox_Vz->GetValue();
     aModule = sqrt(aX*aX + aY*aY + aZ*aZ);
   }
+  else if ( ExtrMethod_RBut2->isChecked() ) {
+    aModule = 1;
+  }
+  
   return aModule > 1.0E-38;
 }
 
@@ -481,6 +501,11 @@ void SMESHGUI_ExtrusionDlg::ConstructorsClicked (int constructorId)
     }
   }
 
+  ExtrMethod_RBut2->setVisible( constructorId == 2 );
+  if ( !ExtrMethod_RBut2->isVisible() &&
+       ExtrMethod_RBut2->isChecked() )
+    ExtrMethod_RBut0->click();
+
   myEditCurrentArgument = (QWidget*)LineEditElements;
   LineEditElements->setFocus();
 
@@ -499,7 +524,8 @@ void SMESHGUI_ExtrusionDlg::ConstructorsClicked (int constructorId)
 //=================================================================================
 void SMESHGUI_ExtrusionDlg::ClickOnRadio()
 {
-  if ( RadioButton3->isChecked() ) {
+  if ( ExtrMethod_RBut0->isChecked() )
+  {
     TextLabelDistance->show();
     TextLabelDx->show();
     SpinBox_Dx->show();
@@ -518,7 +544,12 @@ void SMESHGUI_ExtrusionDlg::ClickOnRadio()
     TextLabelDist->hide();
     SpinBox_VDist->hide();
     SelectVectorButton->hide();
-  } else if ( RadioButton4->isChecked() ) {
+
+    ByAverageNormalCheck->hide();
+    UseInputElemsOnlyCheck->hide();
+  }
+  else if ( ExtrMethod_RBut1->isChecked() )
+  {
     TextLabelDistance->hide();
     TextLabelDx->hide();
     SpinBox_Dx->hide();
@@ -537,7 +568,38 @@ void SMESHGUI_ExtrusionDlg::ClickOnRadio()
     TextLabelDist->show();
     SpinBox_VDist->show();
     SelectVectorButton->show();
+
+    ByAverageNormalCheck->hide();
+    UseInputElemsOnlyCheck->hide();
   }
+  else if ( ExtrMethod_RBut2->isChecked() )
+  {
+    TextLabelDistance->hide();
+    TextLabelDx->hide();
+    SpinBox_Dx->hide();
+    TextLabelDy->hide();
+    SpinBox_Dy->hide();
+    TextLabelDz->hide();
+    SpinBox_Dz->hide();
+
+    TextLabelVector->hide();
+    TextLabelVx->hide();
+    SpinBox_Vx->hide();
+    TextLabelVy->hide();
+    SpinBox_Vy->hide();
+    TextLabelVz->hide();
+    SpinBox_Vz->hide();
+
+    TextLabelDist->show();
+    SpinBox_VDist->show();
+    SelectVectorButton->hide();
+
+    ByAverageNormalCheck->show();
+    UseInputElemsOnlyCheck->show();
+  }
+
+  CheckIsEnable();
+
   onDisplaySimulation(true);
   // AdjustSize
   qApp->processEvents();
@@ -563,79 +625,91 @@ bool SMESHGUI_ExtrusionDlg::ClickOnApply()
     getExtrusionVector(aVector);
     
     QStringList aParameters;
-    if ( RadioButton3->isChecked() ) {
+    if ( ExtrMethod_RBut0->isChecked() )
+    {
       aParameters << SpinBox_Dx->text();
       aParameters << SpinBox_Dy->text();
       aParameters << SpinBox_Dz->text();
-    } else if ( RadioButton4->isChecked() ) {
+    }
+    else if ( ExtrMethod_RBut1->isChecked() )
+    {
       // only 3 coords in a python dump command :(
       // aParameters << SpinBox_Vx->text();
       // aParameters << SpinBox_Vy->text();
       // aParameters << SpinBox_Vz->text();
       // aParameters << SpinBox_VDist->text();
     }
+    else if ( ExtrMethod_RBut2->isChecked() )
+    {
+      aParameters << SpinBox_VDist->text();
+    }
 
     long aNbSteps = (long)SpinBox_NbSteps->value();
 
     aParameters << SpinBox_NbSteps->text();
 
+    bool meshHadNewTypeBefore = true;
+
     try {
       SUIT_OverrideCursor aWaitCursor;
+
+      // is it necessary to switch on the next Display Mode?
+      SMESH::ElementType newType = (SMESH::ElementType)( SMESH::EDGE + GetConstructorId() );
+      SMESH::array_of_ElementType_var oldTypes = myMesh->GetTypes();
+      meshHadNewTypeBefore = false;
+      for ( size_t i = 0; i < oldTypes->length() && !meshHadNewTypeBefore; ++i )
+        meshHadNewTypeBefore = ( oldTypes[i] >= newType );
+
       SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditor();
 
       myMesh->SetParameters( aParameters.join(":").toLatin1().constData() );
 
-      if ( MakeGroupsCheck->isEnabled() && MakeGroupsCheck->isChecked() ) {
-        if( CheckBoxMesh->isChecked() ) 
+      const bool makeGroups = MakeGroupsCheck->isEnabled() && MakeGroupsCheck->isChecked();
+
+      if ( ExtrMethod_RBut2->isVisible() &&
+           ExtrMethod_RBut2->isChecked() ) // Extrusion by normal
+      {
+        extrusionByNormal( aMeshEditor, makeGroups );
+      }
+      else if ( makeGroups ) // create groups
+      {
+        SMESH::ListOfGroups_var groups;
+        if( CheckBoxMesh->isChecked() )
           switch (GetConstructorId() ) {
-            case 0:
-              {
-                SMESH::ListOfGroups_var groups = 
-                  aMeshEditor->ExtrusionSweepObject0DMakeGroups(mySelectedObject, aVector, aNbSteps);
-                break;
-              }
-            case 1:
-              {
-                SMESH::ListOfGroups_var groups = 
-                  aMeshEditor->ExtrusionSweepObject1DMakeGroups(mySelectedObject, aVector, aNbSteps);
-                break;
-              }
-            case 2:
-              {
-                SMESH::ListOfGroups_var groups = 
-                  aMeshEditor->ExtrusionSweepObject2DMakeGroups(mySelectedObject, aVector, aNbSteps);
-                break;
-              }
+          case 0:
+            groups = aMeshEditor->ExtrusionSweepObject0DMakeGroups(mySelectedObject, aVector,
+                                                                   aNbSteps); break;
+          case 1:
+            groups = aMeshEditor->ExtrusionSweepObject1DMakeGroups(mySelectedObject, aVector,
+                                                                   aNbSteps); break;
+          case 2:
+            groups = aMeshEditor->ExtrusionSweepObject2DMakeGroups(mySelectedObject, aVector,
+                                                                   aNbSteps); break;
           }
         else
         {
-          SMESH::ListOfGroups_var groups;
           if (GetConstructorId() == 0)
-            groups = aMeshEditor->ExtrusionSweepMakeGroups0D(myElementsId.inout(), aVector, aNbSteps);
+            groups = aMeshEditor->ExtrusionSweepMakeGroups0D(myElementsId.inout(), aVector,
+                                                             aNbSteps);
           else
-            groups = aMeshEditor->ExtrusionSweepMakeGroups(myElementsId.inout(), aVector, aNbSteps);
+            groups = aMeshEditor->ExtrusionSweepMakeGroups(myElementsId.inout(), aVector,
+                                                           aNbSteps);
         }
-
       }
-      else {
-        if( CheckBoxMesh->isChecked() ) 
+      else // no groups
+      {
+        if( CheckBoxMesh->isChecked() )
           switch( GetConstructorId() ) {
-            case 0:
-              {
-              aMeshEditor->ExtrusionSweepObject0D(mySelectedObject, aVector, aNbSteps);
-                break;
-              }
-            case 1:
-              {
-              aMeshEditor->ExtrusionSweepObject1D(mySelectedObject, aVector, aNbSteps);
-                break;
-              }
-            case 2:
-              {
-              aMeshEditor->ExtrusionSweepObject2D(mySelectedObject, aVector, aNbSteps);
-                break;
+          case 0:
+            aMeshEditor->ExtrusionSweepObject0D(mySelectedObject, aVector, aNbSteps);
+            break;
+          case 1:
+            aMeshEditor->ExtrusionSweepObject1D(mySelectedObject, aVector, aNbSteps);
+            break;
+          case 2:
+            aMeshEditor->ExtrusionSweepObject2D(mySelectedObject, aVector, aNbSteps);
+            break;
           }
-        }
         else
           if (GetConstructorId() == 0)
             aMeshEditor->ExtrusionSweep0D(myElementsId.inout(), aVector, aNbSteps);
@@ -646,14 +720,29 @@ bool SMESHGUI_ExtrusionDlg::ClickOnApply()
     } catch (...) {
     }
 
+    if ( myActor && !meshHadNewTypeBefore )
+    {
+      unsigned int aMode = myActor->GetEntityMode();
+      switch ( GetConstructorId() ) {
+      case 0: // extrude node -> edges
+        myActor->SetRepresentation(SMESH_Actor::eEdge);
+        myActor->SetEntityMode( aMode |= SMESH_Actor::eEdges ); break;
+      case 1: // edge -> faces
+        myActor->SetRepresentation(SMESH_Actor::eSurface);
+        myActor->SetEntityMode( aMode |= SMESH_Actor::eFaces ); break;
+      case 2: // faces -> volumes
+        myActor->SetRepresentation(SMESH_Actor::eSurface);
+        myActor->SetEntityMode( aMode |= SMESH_Actor::eVolumes ); break;
+      }
+    }
     SMESH::Update(myIO, SMESH::eDisplay);
     if ( MakeGroupsCheck->isEnabled() && MakeGroupsCheck->isChecked() )
       mySMESHGUI->updateObjBrowser(true); // new groups may appear
     Init(false);
-    ConstructorsClicked(GetConstructorId());
     mySelectionMgr->clearSelected();
     mySelectedObject = SMESH::SMESH_IDSource::_nil();
     SelectionIntoArgument();
+    ConstructorsClicked(GetConstructorId());
 
     SMESHGUI::Modified();
   }
@@ -1160,11 +1249,11 @@ bool SMESHGUI_ExtrusionDlg::isValid()
 {
   QString msg;
   bool ok = true;
-  if ( RadioButton3->isChecked() ) {
+  if ( ExtrMethod_RBut0->isChecked() ) {
     ok = SpinBox_Dx->isValid( msg, true ) && ok;
     ok = SpinBox_Dy->isValid( msg, true ) && ok;
     ok = SpinBox_Dz->isValid( msg, true ) && ok;
-  } else if ( RadioButton4->isChecked() ) {
+  } else if ( ExtrMethod_RBut1->isChecked() ) {
     ok = SpinBox_Vx->isValid( msg, true ) && ok;
     ok = SpinBox_Vy->isValid( msg, true ) && ok;
     ok = SpinBox_Vz->isValid( msg, true ) && ok;
@@ -1186,44 +1275,53 @@ bool SMESHGUI_ExtrusionDlg::isValid()
 // function : onDisplaySimulation
 // purpose  : Show/Hide preview
 //=================================================================================
-void SMESHGUI_ExtrusionDlg::onDisplaySimulation( bool toDisplayPreview ) {
+void SMESHGUI_ExtrusionDlg::onDisplaySimulation( bool toDisplayPreview )
+{
   if (myPreviewCheckBox->isChecked() && toDisplayPreview) {
     if (myNbOkElements && isValid() && isValuesValid()) {
       //Get input vector
       SMESH::DirStruct aVector;
       getExtrusionVector(aVector);
 
-      //Get Number of the steps 
+      //Get Number of the steps
       long aNbSteps = (long)SpinBox_NbSteps->value();
-      
-      try {
+      try
+      {
         SUIT_OverrideCursor aWaitCursor;
         SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditPreviewer();
-        if( CheckBoxMesh->isChecked() ) {
+
+        if ( ExtrMethod_RBut2->isVisible() &&
+             ExtrMethod_RBut2->isChecked() ) // Extrusion by normal
+        {
+          extrusionByNormal( aMeshEditor );
+        }
+        else if ( CheckBoxMesh->isChecked() ) // Extrude the whole object
+        {
           switch (GetConstructorId()) {
-            case 0:
-              {
-                aMeshEditor->ExtrusionSweepObject0D(mySelectedObject, aVector, aNbSteps);
-                                        break;
-              }
-            case 1:
-              {
-                aMeshEditor->ExtrusionSweepObject1D(mySelectedObject, aVector, aNbSteps);
-                                        break;
-              }
-            case 2:
-              {
-                aMeshEditor->ExtrusionSweepObject2D(mySelectedObject, aVector, aNbSteps);
-                                        break;
-              }
+          case 0:
+          {
+            aMeshEditor->ExtrusionSweepObject0D(mySelectedObject, aVector, aNbSteps);
+            break;
+          }
+          case 1:
+          {
+            aMeshEditor->ExtrusionSweepObject1D(mySelectedObject, aVector, aNbSteps);
+            break;
+          }
+          case 2:
+          {
+            aMeshEditor->ExtrusionSweepObject2D(mySelectedObject, aVector, aNbSteps);
+            break;
+          }
           }
         }
-        else
+        else // extrude some elements
+        {
           if(GetConstructorId() == 0)
             aMeshEditor->ExtrusionSweep0D(myElementsId.inout(), aVector, aNbSteps);
           else
             aMeshEditor->ExtrusionSweep(myElementsId.inout(), aVector, aNbSteps);
-        
+        }
         SMESH::MeshPreviewStruct_var aMeshPreviewStruct = aMeshEditor->GetPreviewData();
         mySimulation->SetData(aMeshPreviewStruct._retn());
       } catch (...) {
@@ -1241,22 +1339,54 @@ void SMESHGUI_ExtrusionDlg::onDisplaySimulation( bool toDisplayPreview ) {
 // function : getExtrusionVector()
 // purpose  : get direction of the extrusion
 //=================================================================================
-void SMESHGUI_ExtrusionDlg::getExtrusionVector(SMESH::DirStruct& aVector) {
-  if ( RadioButton3->isChecked() ) {
+void SMESHGUI_ExtrusionDlg::getExtrusionVector(SMESH::DirStruct& aVector)
+{
+  if ( ExtrMethod_RBut0->isChecked() )
+  {
     aVector.PS.x = SpinBox_Dx->GetValue();
     aVector.PS.y = SpinBox_Dy->GetValue();
-    aVector.PS.z = SpinBox_Dz->GetValue();      
-  } else if ( RadioButton4->isChecked() ) {
+    aVector.PS.z = SpinBox_Dz->GetValue();
+  }
+  else if ( ExtrMethod_RBut1->isChecked() )
+  {
     gp_XYZ aNormale(SpinBox_Vx->GetValue(),
                     SpinBox_Vy->GetValue(),
                     SpinBox_Vz->GetValue());
-    
-    
     aNormale /= aNormale.Modulus();
     double aVDist = (double)SpinBox_VDist->value();
-    
+
     aVector.PS.x = aNormale.X()*aVDist;
     aVector.PS.y = aNormale.Y()*aVDist;
     aVector.PS.z = aNormale.Z()*aVDist;
   }
 }
+
+//=======================================================================
+//function : extrusionByNormal
+//purpose  : performs extrusion by normal
+//=======================================================================
+
+void SMESHGUI_ExtrusionDlg::extrusionByNormal( SMESH::SMESH_MeshEditor_ptr meshEditor,
+                                               const bool                  makeGroups)
+{
+  SMESH::SMESH_IDSource_wrap anIDSource;
+  if ( CheckBoxMesh->isChecked() )
+  {
+    anIDSource = mySelectedObject;
+    anIDSource->Register();
+  }
+  else // make a temporary id source
+  {
+    anIDSource = meshEditor->MakeIDSource( myElementsId, SMESH::ALL );
+  }
+
+  double stepSize          = (double) SpinBox_VDist->value();
+  long   nbSteps           = (long)SpinBox_NbSteps->value();
+  bool   useInputElemsOnly = UseInputElemsOnlyCheck->isChecked();
+  bool   byAverageNormal   = ByAverageNormalCheck->isChecked();
+  int    dim               = GetConstructorId();
+
+  SMESH::ListOfGroups_var groups =
+    meshEditor->ExtrusionByNormal( anIDSource, stepSize, nbSteps,
+                                   useInputElemsOnly, byAverageNormal, makeGroups, dim );
+}
index c3acc56..2d0e59f 100644 (file)
@@ -37,6 +37,7 @@
 // IDL includes
 #include <SALOMEconfig.h>
 #include CORBA_SERVER_HEADER(SMESH_Mesh)
+#include CORBA_SERVER_HEADER(SMESH_MeshEditor)
 
 class QButtonGroup;
 class QRadioButton;
@@ -74,6 +75,8 @@ private:
   void                             keyPressEvent( QKeyEvent* );
   int                              GetConstructorId();
   void                             getExtrusionVector(SMESH::DirStruct& aVector);
+  void                             extrusionByNormal(SMESH::SMESH_MeshEditor_ptr meshEditor,
+                                                     const bool                  makeGroups=false);
   
   bool                             isValid();
   bool                             isValuesValid();
@@ -98,11 +101,12 @@ private:
   // widgets
   QGroupBox*                       ConstructorsBox;
   QButtonGroup*                    GroupConstructors;
-  QRadioButton*                    RadioButton0;
-  QRadioButton*                    RadioButton1;
-  QRadioButton*                    RadioButton2;
-  QRadioButton*                    RadioButton3;
-  QRadioButton*                    RadioButton4;
+  QRadioButton*                    Contructor_RBut0;
+  QRadioButton*                    Contructor_RBut1;
+  QRadioButton*                    Contructor_RBut2;
+  QRadioButton*                    ExtrMethod_RBut0;
+  QRadioButton*                    ExtrMethod_RBut1;
+  QRadioButton*                    ExtrMethod_RBut2;
 
   QGroupBox*                       GroupArguments;
   QGroupBox*                       GroupDimensions;
@@ -129,6 +133,8 @@ private:
   SMESHGUI_SpinBox*                SpinBox_VDist;
   QLabel*                          TextLabelNbSteps;
   SalomeApp_IntSpinBox*            SpinBox_NbSteps;
+  QCheckBox*                       ByAverageNormalCheck;
+  QCheckBox*                       UseInputElemsOnlyCheck;
   QCheckBox*                       MakeGroupsCheck;
 
   QGroupBox*                       GroupButtons;
index 6e5ccb9..9f02c00 100644 (file)
@@ -516,8 +516,18 @@ bool SMESHGUI_RevolutionDlg::ClickOnApply()
     aParameters << SpinBox_NbSteps->text();
     aParameters << SpinBox_Tolerance->text();
 
+    bool meshHadNewTypeBefore = true;
+
     try {
       SUIT_OverrideCursor aWaitCursor;
+
+      // is it necessary to switch on the next Display Mode?
+      SMESH::ElementType newType = (SMESH::ElementType)( SMESH::FACE + GetConstructorId() );
+      SMESH::array_of_ElementType_var oldTypes = myMesh->GetTypes();
+      meshHadNewTypeBefore = false;
+      for ( size_t i = 0; i < oldTypes->length() && !meshHadNewTypeBefore; ++i )
+        meshHadNewTypeBefore = ( oldTypes[i] >= newType );
+
       SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditor();
       
       myMesh->SetParameters( aParameters.join(":").toLatin1().constData() );
@@ -552,14 +562,30 @@ bool SMESHGUI_RevolutionDlg::ClickOnApply()
     } catch (...) {
     }
 
+    if ( myActor && !meshHadNewTypeBefore )
+    {
+      unsigned int aMode = myActor->GetEntityMode();
+      switch ( GetConstructorId() ) {
+      case 0-1: // extrude node -> edges
+        myActor->SetRepresentation(SMESH_Actor::eEdge);
+        myActor->SetEntityMode( aMode |= SMESH_Actor::eEdges ); break;
+      case 1-1: // edge -> faces
+        myActor->SetRepresentation(SMESH_Actor::eSurface);
+        myActor->SetEntityMode( aMode |= SMESH_Actor::eFaces ); break;
+      case 2-1: // faces -> volumes
+        myActor->SetRepresentation(SMESH_Actor::eSurface);
+        myActor->SetEntityMode( aMode |= SMESH_Actor::eVolumes ); break;
+      }
+    }
     SMESH::UpdateView();
     SMESH::Update(myIO, SMESH::eDisplay);
     if ( MakeGroupsCheck->isEnabled() && MakeGroupsCheck->isChecked() )
       mySMESHGUI->updateObjBrowser(true); // new groups may appear
     Init(false);
-    ConstructorsClicked(GetConstructorId());
+    mySelectionMgr->clearSelected();
     mySelectedObject = SMESH::SMESH_IDSource::_nil();
     SelectionIntoArgument();
+    ConstructorsClicked(GetConstructorId());
 
     SMESHGUI::Modified();
   }
index 3f8a01c..d5d08ad 100644 (file)
@@ -1694,6 +1694,10 @@ Do you want to continue ?</translation>
         <translation>Extrusion Along Vector</translation>
     </message>
     <message>
+        <source>SMESH_EXTRUSION_BY_NORMAL</source>
+        <translation>Extrusion By Normal</translation>
+    </message>
+    <message>
         <source>SMESH_FACE</source>
         <translation>Face</translation>
     </message>
@@ -5141,6 +5145,14 @@ Please select a group and try again</translation>
         <source>EXTRUSION_ALONG_LINE</source>
         <translation>Extrusion along a line</translation>
     </message>
+    <message>
+        <source>BY_AVERAGE_NORMAL</source>
+        <translation>Along average normal</translation>
+    </message>
+    <message>
+        <source>USE_INPUT_ELEMS_ONLY</source>
+        <translation>Use only input elements</translation>
+    </message>
 </context>
 <context>
     <name>SMESHGUI_FilterDlg</name>
index 763f976..7ed7cd8 100644 (file)
@@ -418,7 +418,8 @@ namespace MeshEditor_I {
     if ( !sameElemType )
       elemType = SMDSAbs_All;
 
-    TIDSortedElemSet visitedNodes;
+    vector<bool> isNodeChecked( theMeshDS->NbNodes(), false );
+
     TIDSortedElemSet::const_iterator elemIt = theElements.begin();
     for ( ; elemIt != theElements.end(); ++elemIt )
     {
@@ -427,8 +428,9 @@ namespace MeshEditor_I {
       while ( --i != -1 )
       {
         const SMDS_MeshNode* n = e->GetNode( i );
-        if ( visitedNodes.insert( n ).second )
+        if ( !isNodeChecked[ n->GetID() ])
         {
+          isNodeChecked[ n->GetID() ] = true;
           SMDS_ElemIteratorPtr invIt = n->GetInverseElementIterator(elemType);
           while ( invIt->more() )
           {
@@ -784,16 +786,12 @@ struct SMESH_MeshEditor_i::_IDSource : public virtual POA_SMESH::SMESH_IDSource,
 SMESH::SMESH_IDSource_ptr SMESH_MeshEditor_i::MakeIDSource(const SMESH::long_array& ids,
                                                            SMESH::ElementType       type)
 {
-  // if ( myAuxIDSources.size() > 10 ) {
-  //   delete myAuxIDSources.front();
-  //   myAuxIDSources.pop_front();
-  // }
-
   _IDSource* idSrc = new _IDSource;
   idSrc->_mesh = myMesh_i->_this();
   idSrc->_ids  = ids;
   idSrc->_type = type;
-  //myAuxIDSources.push_back( idSrc );
+  if ( type == SMESH::ALL && ids.length() > 0 )
+    idSrc->_type = myMesh_i->GetElementType( ids[0], true );
 
   SMESH::SMESH_IDSource_var anIDSourceVar = idSrc->_this();
 
@@ -2687,6 +2685,77 @@ SMESH_MeshEditor_i::RotationSweepObject2DMakeGroups(SMESH::SMESH_IDSource_ptr th
   return aGroups;
 }
 
+namespace MeshEditor_I
+{
+  /*!
+   * \brief Structure used to pass extrusion parameters to ::SMESH_MeshEditor
+   */
+  struct ExtrusionParams : public ::SMESH_MeshEditor::ExtrusParam
+  {
+    bool myIsExtrusionByNormal;
+
+    static int makeFlags( CORBA::Boolean MakeGroups,
+                          CORBA::Boolean ByAverageNormal = false,
+                          CORBA::Boolean UseInputElemsOnly = false,
+                          CORBA::Long    Flags = 0,
+                          CORBA::Boolean MakeBoundary = true )
+    {
+      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 ( MakeBoundary     ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
+      return Flags;
+    }
+    // standard params
+    ExtrusionParams(const SMESH::DirStruct &  theDir,
+                    CORBA::Long               theNbOfSteps,
+                    CORBA::Boolean            theMakeGroups):
+      ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
+                                                theDir.PS.y,
+                                                theDir.PS.z ),
+                                        theNbOfSteps,
+                                        makeFlags( theMakeGroups )),
+      myIsExtrusionByNormal( false )
+    {
+    }
+    // advanced params
+    ExtrusionParams(const SMESH::DirStruct &  theDir,
+                    CORBA::Long               theNbOfSteps,
+                    CORBA::Boolean            theMakeGroups,
+                    CORBA::Long               theExtrFlags,
+                    CORBA::Double             theSewTolerance):
+      ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
+                                                theDir.PS.y,
+                                                theDir.PS.z ),
+                                        theNbOfSteps,
+                                        makeFlags( theMakeGroups, false, false,
+                                                   theExtrFlags, false ),
+                                        theSewTolerance ),
+      myIsExtrusionByNormal( false )
+    {
+    }
+    // params for extrusion by normal
+    ExtrusionParams(CORBA::Double  theStepSize,
+                    CORBA::Long    theNbOfSteps,
+                    CORBA::Short   theDim,
+                    CORBA::Boolean theUseInputElemsOnly,
+                    CORBA::Boolean theByAverageNormal,
+                    CORBA::Boolean theMakeGroups ):
+      ::SMESH_MeshEditor::ExtrusParam ( theStepSize, 
+                                        theNbOfSteps,
+                                        makeFlags( theMakeGroups,
+                                                   theByAverageNormal, theUseInputElemsOnly ),
+                                        theDim),
+      myIsExtrusionByNormal( true )
+    {
+    }
+
+    void SetNoGroups()
+    {
+      Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
+    }
+  };
+}
 
 //=======================================================================
 //function : extrusionSweep
@@ -2694,43 +2763,45 @@ SMESH_MeshEditor_i::RotationSweepObject2DMakeGroups(SMESH::SMESH_IDSource_ptr th
 //=======================================================================
 
 SMESH::ListOfGroups*
-SMESH_MeshEditor_i::extrusionSweep(const SMESH::long_array & theIDsOfElements,
-                                   const SMESH::DirStruct &  theStepVector,
-                                   CORBA::Long               theNbOfSteps,
-                                   bool                      theMakeGroups,
-                                   const SMDSAbs_ElementType theElementType)
+SMESH_MeshEditor_i::extrusionSweep(const SMESH::long_array &      theIDsOfElements,
+                                   MeshEditor_I::ExtrusionParams& theParams,
+                                   const SMDSAbs_ElementType      theElementType)
   throw (SALOME::SALOME_Exception)
 {
   SMESH_TRY;
   initData();
 
   TIDSortedElemSet elements, copyElements;
-  arrayToSet(theIDsOfElements, getMeshDS(), elements, theElementType);
-
-  const SMESH::PointStruct * P = &theStepVector.PS;
-  gp_Vec stepVec( P->x, P->y, P->z );
+  arrayToSet( theIDsOfElements, getMeshDS(), elements, theElementType );
 
   TIDSortedElemSet* workElements = & elements;
 
-  SMDSAbs_ElementType aType = SMDSAbs_Face;
-  if (theElementType == SMDSAbs_Node)
+  if ( myIsPreviewMode )
   {
-    aType = SMDSAbs_Edge;
-  }
-  if ( myIsPreviewMode ) {
+    SMDSAbs_ElementType previewType = SMDSAbs_Face;
+    if (theElementType == SMDSAbs_Node)
+      previewType = SMDSAbs_Edge;
+
     SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
-    getPreviewMesh( aType )->Copy( elements, copyElements, select, avoid );
+    getPreviewMesh( previewType )->Copy( elements, copyElements, select, avoid );
     workElements = & copyElements;
-    theMakeGroups = false;
+    theParams.SetNoGroups();
+
+    if ( theParams.myIsExtrusionByNormal && !theParams.ToUseInpElemsOnly() )
+    {
+      TIDSortedElemSet elemsAround, elemsAroundCopy;
+      getElementsAround( elements, getMeshDS(), elemsAround );
+      getPreviewMesh( previewType )->Copy( elemsAround, elemsAroundCopy, select, avoid );
+    }
   }
 
   ::SMESH_MeshEditor::TTElemOfElemListMap aHystory;
-  ::SMESH_MeshEditor::PGroupIDs groupIds = 
-      getEditor().ExtrusionSweep (*workElements, stepVec, theNbOfSteps, aHystory, theMakeGroups);
+  ::SMESH_MeshEditor::PGroupIDs groupIds =
+      getEditor().ExtrusionSweep (*workElements, theParams, aHystory );
 
   declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
 
-  return theMakeGroups ? getGroups(groupIds.get()) : 0;
+  return theParams.ToMakeGroups() ? getGroups(groupIds.get()) : 0;
 
   SMESH_CATCH( SMESH::throwCorbaException );
   return 0;
@@ -2746,7 +2817,8 @@ void SMESH_MeshEditor_i::ExtrusionSweep(const SMESH::long_array & theIDsOfElemen
                                         CORBA::Long               theNbOfSteps)
   throw (SALOME::SALOME_Exception)
 {
-  extrusionSweep (theIDsOfElements, theStepVector, theNbOfSteps, false );
+  ExtrusionParams params( theStepVector, theNbOfSteps, false );
+  extrusionSweep( theIDsOfElements, params );
   if (!myIsPreviewMode) {
     TPythonDump() << this << ".ExtrusionSweep( "
                   << theIDsOfElements << ", " << theStepVector <<", " << TVar(theNbOfSteps) << " )";
@@ -2763,7 +2835,8 @@ void SMESH_MeshEditor_i::ExtrusionSweep0D(const SMESH::long_array & theIDsOfElem
                                           CORBA::Long               theNbOfSteps)
   throw (SALOME::SALOME_Exception)
 {
-  extrusionSweep (theIDsOfElements, theStepVector, theNbOfSteps, false, SMDSAbs_Node );
+  ExtrusionParams params( theStepVector, theNbOfSteps, false );
+  extrusionSweep( theIDsOfElements, params, SMDSAbs_Node );
   if (!myIsPreviewMode) {
     TPythonDump() << this << ".ExtrusionSweep0D( "
                   << theIDsOfElements << ", " << theStepVector <<", " << TVar(theNbOfSteps)<< " )";
@@ -2782,7 +2855,8 @@ void SMESH_MeshEditor_i::ExtrusionSweepObject(SMESH::SMESH_IDSource_ptr theObjec
 {
   prepareIdSource( theObject );
   SMESH::long_array_var anElementsId = theObject->GetIDs();
-  extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false );
+  ExtrusionParams params( theStepVector, theNbOfSteps, false );
+  extrusionSweep( anElementsId, params );
   if (!myIsPreviewMode) {
     TPythonDump() << this << ".ExtrusionSweepObject( "
                   << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
@@ -2801,7 +2875,12 @@ void SMESH_MeshEditor_i::ExtrusionSweepObject0D(SMESH::SMESH_IDSource_ptr theObj
 {
   prepareIdSource( theObject );
   SMESH::long_array_var anElementsId = theObject->GetIDs();
-  extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false, SMDSAbs_Node );
+  if ( anElementsId->length() == 0 )
+    if ( SMESH_Mesh_i* mesh = SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
+      anElementsId = mesh->GetNodesId();
+
+  ExtrusionParams params( theStepVector, theNbOfSteps, false );
+  extrusionSweep( anElementsId, params, SMDSAbs_Node );
   if ( !myIsPreviewMode ) {
     TPythonDump() << this << ".ExtrusionSweepObject0D( "
                   << theObject << ", " << theStepVector << ", " << TVar( theNbOfSteps ) << " )";
@@ -2820,7 +2899,8 @@ void SMESH_MeshEditor_i::ExtrusionSweepObject1D(SMESH::SMESH_IDSource_ptr theObj
 {
   prepareIdSource( theObject );
   SMESH::long_array_var anElementsId = theObject->GetIDs();
-  extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false, SMDSAbs_Edge );
+  ExtrusionParams params( theStepVector, theNbOfSteps, false );
+  extrusionSweep( anElementsId, params, SMDSAbs_Edge );
   if ( !myIsPreviewMode ) {
     TPythonDump() << this << ".ExtrusionSweepObject1D( "
                   << theObject << ", " << theStepVector << ", " << TVar( theNbOfSteps ) << " )";
@@ -2839,7 +2919,8 @@ void SMESH_MeshEditor_i::ExtrusionSweepObject2D(SMESH::SMESH_IDSource_ptr theObj
 {
   prepareIdSource( theObject );
   SMESH::long_array_var anElementsId = theObject->GetIDs();
-  extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false, SMDSAbs_Face );
+  ExtrusionParams params( theStepVector, theNbOfSteps, false );
+  extrusionSweep( anElementsId, params, SMDSAbs_Face );
   if ( !myIsPreviewMode ) {
     TPythonDump() << this << ".ExtrusionSweepObject2D( "
                   << theObject << ", " << theStepVector << ", " << TVar( theNbOfSteps ) << " )";
@@ -2859,7 +2940,8 @@ SMESH_MeshEditor_i::ExtrusionSweepMakeGroups(const SMESH::long_array& theIDsOfEl
 {
   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
 
-  SMESH::ListOfGroups* aGroups = extrusionSweep(theIDsOfElements, theStepVector, theNbOfSteps, true);
+  ExtrusionParams params( theStepVector, theNbOfSteps, true );
+  SMESH::ListOfGroups* aGroups = extrusionSweep( theIDsOfElements, params );
 
   if (!myIsPreviewMode) {
     dumpGroupsList(aPythonDump, aGroups);
@@ -2882,7 +2964,8 @@ SMESH_MeshEditor_i::ExtrusionSweepMakeGroups0D(const SMESH::long_array& theIDsOf
 {
   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
 
-  SMESH::ListOfGroups* aGroups = extrusionSweep(theIDsOfElements, theStepVector, theNbOfSteps, true,SMDSAbs_Node);
+  ExtrusionParams params( theStepVector, theNbOfSteps, true );
+  SMESH::ListOfGroups* aGroups = extrusionSweep( theIDsOfElements, params, SMDSAbs_Node );
 
   if (!myIsPreviewMode) {
     dumpGroupsList(aPythonDump, aGroups);
@@ -2907,7 +2990,8 @@ SMESH_MeshEditor_i::ExtrusionSweepObjectMakeGroups(SMESH::SMESH_IDSource_ptr the
 
   prepareIdSource( theObject );
   SMESH::long_array_var anElementsId = theObject->GetIDs();
-  SMESH::ListOfGroups * aGroups = extrusionSweep(anElementsId, theStepVector, theNbOfSteps, true);
+  ExtrusionParams params( theStepVector, theNbOfSteps, true );
+  SMESH::ListOfGroups* aGroups = extrusionSweep( anElementsId, params );
 
   if (!myIsPreviewMode) {
     dumpGroupsList(aPythonDump, aGroups);
@@ -2932,8 +3016,9 @@ SMESH_MeshEditor_i::ExtrusionSweepObject0DMakeGroups(SMESH::SMESH_IDSource_ptr t
 
   prepareIdSource( theObject );
   SMESH::long_array_var anElementsId = theObject->GetIDs();
-  SMESH::ListOfGroups * aGroups = extrusionSweep(anElementsId, theStepVector,
-                                                 theNbOfSteps, true, SMDSAbs_Node);
+  ExtrusionParams params( theStepVector, theNbOfSteps, true );
+  SMESH::ListOfGroups* aGroups = extrusionSweep( anElementsId, params, SMDSAbs_Node );
+
   if (!myIsPreviewMode) {
     dumpGroupsList(aPythonDump, aGroups);
     aPythonDump << this << ".ExtrusionSweepObject0DMakeGroups( " << theObject
@@ -2957,8 +3042,9 @@ SMESH_MeshEditor_i::ExtrusionSweepObject1DMakeGroups(SMESH::SMESH_IDSource_ptr t
 
   prepareIdSource( theObject );
   SMESH::long_array_var anElementsId = theObject->GetIDs();
-  SMESH::ListOfGroups * aGroups = extrusionSweep(anElementsId, theStepVector,
-                                                 theNbOfSteps, true, SMDSAbs_Edge);
+  ExtrusionParams params( theStepVector, theNbOfSteps, true );
+  SMESH::ListOfGroups* aGroups = extrusionSweep( anElementsId, params, SMDSAbs_Edge );
+
   if (!myIsPreviewMode) {
     dumpGroupsList(aPythonDump, aGroups);
     aPythonDump << this << ".ExtrusionSweepObject1DMakeGroups( " << theObject
@@ -2982,8 +3068,9 @@ SMESH_MeshEditor_i::ExtrusionSweepObject2DMakeGroups(SMESH::SMESH_IDSource_ptr t
 
   prepareIdSource( theObject );
   SMESH::long_array_var anElementsId = theObject->GetIDs();
-  SMESH::ListOfGroups * aGroups = extrusionSweep(anElementsId, theStepVector,
-                                                 theNbOfSteps, true, SMDSAbs_Face);
+  ExtrusionParams params( theStepVector, theNbOfSteps, true );
+  SMESH::ListOfGroups* aGroups = extrusionSweep( anElementsId, params, SMDSAbs_Face );
+
   if (!myIsPreviewMode) {
     dumpGroupsList(aPythonDump, aGroups);
     aPythonDump << this << ".ExtrusionSweepObject2DMakeGroups( " << theObject
@@ -2992,41 +3079,49 @@ SMESH_MeshEditor_i::ExtrusionSweepObject2DMakeGroups(SMESH::SMESH_IDSource_ptr t
   return aGroups;
 }
 
-
 //=======================================================================
-//function : advancedExtrusion
+//function : ExtrusionByNormal
 //purpose  :
 //=======================================================================
 
 SMESH::ListOfGroups*
-SMESH_MeshEditor_i::advancedExtrusion(const SMESH::long_array & theIDsOfElements,
-                                      const SMESH::DirStruct &  theStepVector,
-                                      CORBA::Long               theNbOfSteps,
-                                      CORBA::Long               theExtrFlags,
-                                      CORBA::Double             theSewTolerance,
-                                      const bool                theMakeGroups)
+SMESH_MeshEditor_i::ExtrusionByNormal(SMESH::SMESH_IDSource_ptr object,
+                                      CORBA::Double             stepSize,
+                                      CORBA::Long               nbOfSteps,
+                                      CORBA::Boolean            byAverageNormal,
+                                      CORBA::Boolean            useInputElemsOnly,
+                                      CORBA::Boolean            makeGroups,
+                                      CORBA::Short              dim)
   throw (SALOME::SALOME_Exception)
 {
-  SMESH_TRY;
-  initData();
-
-  TIDSortedElemSet elements;
-  arrayToSet(theIDsOfElements, getMeshDS(), elements);
-
-  const SMESH::PointStruct * P = &theStepVector.PS;
-  gp_Vec stepVec( P->x, P->y, P->z );
-
-  ::SMESH_MeshEditor::TTElemOfElemListMap aHystory;
-  ::SMESH_MeshEditor::PGroupIDs groupIds =
-      getEditor().ExtrusionSweep (elements, stepVec, theNbOfSteps, aHystory,
-                                  theMakeGroups, theExtrFlags, theSewTolerance);
+  TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
 
-  declareMeshModified( /*isReComputeSafe=*/true );
+  ExtrusionParams params( stepSize, nbOfSteps, dim,
+                          byAverageNormal, useInputElemsOnly, makeGroups );
 
-  return theMakeGroups ? getGroups(groupIds.get()) : 0;
+  SMDSAbs_ElementType elemType = ( dim == 1 ? SMDSAbs_Edge : SMDSAbs_Face );
+  if ( !SMESH::DownCast<SMESH_Mesh_i*>( object ))
+  {
+    SMESH::array_of_ElementType_var elemTypes = object->GetTypes();
+    if (( elemTypes->length() == 1 ) &&
+        ( elemTypes[0] == SMESH::EDGE || elemTypes[0] == SMESH::FACE ))
+      elemType = ( SMDSAbs_ElementType ) elemTypes[0];
+  }
+  prepareIdSource( object );
+  SMESH::long_array_var anElementsId = object->GetIDs();
+  SMESH::ListOfGroups* aGroups = extrusionSweep( anElementsId, params, elemType );
 
-  SMESH_CATCH( SMESH::throwCorbaException );
-  return 0;
+  if (!myIsPreviewMode) {
+    dumpGroupsList(aPythonDump, aGroups);
+    aPythonDump << this << ".ExtrusionByNormal( " << object
+                << ", " << TVar( stepSize )
+                << ", " << TVar( nbOfSteps )
+                << ", " << byAverageNormal
+                << ", " << makeGroups
+                << ", " << dim
+                << " )";
+  }
+  return aGroups;
 }
 
 //=======================================================================
@@ -3041,6 +3136,9 @@ void SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfEle
                                            CORBA::Double             theSewTolerance)
   throw (SALOME::SALOME_Exception)
 {
+  ExtrusionParams params( theStepVector, theNbOfSteps, false, theExtrFlags, theSewTolerance);
+  extrusionSweep( theIDsOfElements, params );
+
   if ( !myIsPreviewMode ) {
     TPythonDump() << "stepVector = " << theStepVector;
     TPythonDump() << this << ".AdvancedExtrusion("
@@ -3050,12 +3148,6 @@ void SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfEle
                   << theExtrFlags << ", "
                   << theSewTolerance <<  " )";
   }
-  advancedExtrusion( theIDsOfElements,
-                     theStepVector,
-                     theNbOfSteps,
-                     theExtrFlags,
-                     theSewTolerance,
-                     false);
 }
 
 //=======================================================================
@@ -3075,12 +3167,8 @@ SMESH_MeshEditor_i::AdvancedExtrusionMakeGroups(const SMESH::long_array& theIDsO
   }
   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
 
-  SMESH::ListOfGroups * aGroups = advancedExtrusion( theIDsOfElements,
-                                                     theStepVector,
-                                                     theNbOfSteps,
-                                                     theExtrFlags,
-                                                     theSewTolerance,
-                                                     true);
+  ExtrusionParams params( theStepVector, theNbOfSteps, true, theExtrFlags, theSewTolerance);
+  SMESH::ListOfGroups * aGroups = extrusionSweep( theIDsOfElements, params );
 
   if (!myIsPreviewMode) {
     dumpGroupsList(aPythonDump, aGroups);
index bce7c4c..e0f054d 100644 (file)
@@ -42,6 +42,7 @@ class SMESH_Mesh_i;
 
 namespace MeshEditor_I {
   struct TPreviewMesh;
+  struct ExtrusionParams;
 }
 
 class SMESH_MeshEditor_i: public POA_SMESH::SMESH_MeshEditor
@@ -358,6 +359,14 @@ public:
                               const SMESH::DirStruct &  StepVector,
                               CORBA::Long               NbOfSteps)
     throw (SALOME::SALOME_Exception);
+  SMESH::ListOfGroups* ExtrusionByNormal(SMESH::SMESH_IDSource_ptr object,
+                                         CORBA::Double             stepSize,
+                                         CORBA::Long               nbOfSteps,
+                                         CORBA::Boolean            byAverageNormal,
+                                         CORBA::Boolean            useInputElemsOnly,
+                                         CORBA::Boolean            makeGroups,
+                                         CORBA::Short              dim)
+    throw (SALOME::SALOME_Exception);
   void AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
                          const SMESH::DirStruct &  theStepVector,
                          CORBA::Long               theNbOfSteps,
@@ -1025,11 +1034,9 @@ private: //!< private methods
                                      const bool                MakeGroups,
                                      const SMDSAbs_ElementType ElementType=SMDSAbs_All)
     throw (SALOME::SALOME_Exception);
-  SMESH::ListOfGroups* extrusionSweep(const SMESH::long_array & IDsOfElements,
-                                      const SMESH::DirStruct &  StepVector,
-                                      CORBA::Long               NbOfSteps,
-                                      bool                      MakeGroups,
-                                      const SMDSAbs_ElementType ElementType=SMDSAbs_All)
+  SMESH::ListOfGroups* extrusionSweep(const SMESH::long_array &      IDsOfElements,
+                                      MeshEditor_I::ExtrusionParams& params,
+                                      const SMDSAbs_ElementType      ElementType=SMDSAbs_All)
     throw (SALOME::SALOME_Exception);
   SMESH::ListOfGroups* advancedExtrusion(const SMESH::long_array & theIDsOfElements,
                                          const SMESH::DirStruct &  theStepVector,
index 3084728..132313e 100644 (file)
@@ -3387,7 +3387,7 @@ class Mesh:
     #  them with quadratic with the same id.
     #  @param theForce3d new node creation method:
     #         0 - the medium node lies at the geometrical entity from which the mesh element is built
-    #         1 - the medium node lies at the middle of the line segments connecting start and end node of a mesh element
+    #         1 - the medium node lies at the middle of the line segments connecting two nodes of a mesh element
     #  @param theSubMesh a group or a sub-mesh to convert; WARNING: in this case the mesh can become not conformal
     #  @param theToBiQuad If True, converts the mesh to bi-quadratic
     #  @ingroup l2_modif_tofromqu
@@ -3662,6 +3662,44 @@ class Mesh:
                                       ExtrFlags, SewTolerance)
         return []
 
+    ## Generates new elements by extrusion along the normal to a discretized surface or wire
+    #  @param Elements container of elements to extrude;
+    #         it can be Mesh, Group, Sub-mesh, Filter or list of IDs;
+    #         Only faces can be extruded so far. Sub-mesh sould be a sub-mesh on geom faces.
+    #  @param StepSize length of one extrusion step (the total extrusion
+    #         length will be \a NbOfSteps * \a StepSize ).
+    #  @param NbOfSteps number of extrusion steps.
+    #  @param ByAverageNormal if True each node is translated by \a StepSize
+    #         along the average of the normal vectors to the faces sharing the node;
+    #         else each node is translated along the same average normal till
+    #         intersection with the plane got by translation of the face sharing
+    #         the node along its own normal by \a StepSize.
+    #  @param UseInputElemsOnly to use only \a Elements when computing extrusion direction
+    #         for every node of \a Elements.
+    #  @param MakeGroups forces generation of new groups from existing ones.
+    #  @param Dim dimension of elements to extrude: 2 - faces or 1 - edges. Extrusion of edges
+    #         is not yet implemented. This parameter is used if \a Elements contains
+    #         both faces and edges, i.e. \a Elements is a Mesh.
+    #  @return the list of created groups (SMESH_GroupBase) if \a MakeGroups=True,
+    #          empty list otherwise.
+    #  @ingroup l2_modif_extrurev
+    def ExtrusionByNormal(self, Elements, StepSize, NbOfSteps,
+                          ByAverageNormal=False, UseInputElemsOnly=True, MakeGroups=False, Dim = 2):
+        unRegister = genObjUnRegister()
+        if isinstance( Elements, Mesh ):
+            Elements = Elements.GetMesh()
+        if isinstance( Elements, list ):
+            if not Elements:
+                raise RuntimeError, "List of element IDs is empty!"
+            if not isinstance( Elements[0], int ):
+                raise RuntimeError, "List must contain element IDs and not %s"% Elements[0]
+            Elements = self.GetIDSource( Elements, SMESH.ALL )
+            unRegister.set( Elements )
+        StepSize,NbOfSteps,Parameters,hasVars = ParseParameters(StepSize,NbOfSteps)
+        self.mesh.SetParameters(Parameters)
+        return self.editor.ExtrusionByNormal(Elements, StepSize, NbOfSteps,
+                                             UseInputElemsOnly, ByAverageNormal, MakeGroups, Dim)
+
     ## Generates new elements by extrusion of the elements which belong to the object
     #  @param theObject the object which elements should be processed.
     #                   It can be a mesh, a sub mesh or a group.