Salome HOME
Merge branch 'abn/configuration'
authorrnv <rnv@opencascade.com>
Wed, 10 Aug 2016 13:53:05 +0000 (16:53 +0300)
committerrnv <rnv@opencascade.com>
Wed, 10 Aug 2016 13:53:05 +0000 (16:53 +0300)
51 files changed:
CMakeLists.txt
SalomeSMESHConfig.cmake.in
doc/salome/examples/creating_meshes_ex02.py
doc/salome/gui/SMESH/CMakeLists.txt
doc/salome/gui/SMESH/images/extrusionalongaline1.png
doc/salome/gui/SMESH/images/topo_equality.png [new file with mode: 0644]
doc/salome/gui/SMESH/input/constructing_submeshes.doc
doc/salome/gui/SMESH/input/extrusion.doc
doc/salome/gui/SMESH/input/prism_3d_algo.doc
doc/salome/gui/SMESH/input/projection_algos.doc
doc/salome/gui/SMESH/input/radial_quadrangle_1D2D_algo.doc
idl/SMESH_MeshEditor.idl
src/DriverMED/DriverMED_W_SMESHDS_Mesh.cxx
src/OBJECT/SMESH_Actor.cxx
src/OBJECT/SMESH_Actor.h
src/OBJECT/SMESH_ActorDef.h
src/OBJECT/SMESH_DeviceActor.cxx
src/OBJECT/SMESH_ScalarBarActor.cxx
src/OBJECT/SMESH_ScalarBarActor.h
src/PluginUtils/CMakeLists.txt
src/PluginUtils/GeomSelectionTools.h
src/PluginUtils/SMESH_AdvOptionsWdg.cxx [new file with mode: 0644]
src/PluginUtils/SMESH_AdvOptionsWdg.h [new file with mode: 0644]
src/PluginUtils/SMESH_PluginUtils.h [new file with mode: 0644]
src/SMESH/SMESH_MeshEditor.cxx
src/SMESH/SMESH_MeshEditor.hxx
src/SMESH/SMESH_subMesh.cxx
src/SMESHGUI/SMESHGUI.cxx
src/SMESHGUI/SMESHGUI_ComputeDlg.cxx
src/SMESHGUI/SMESHGUI_ComputeDlg.h
src/SMESHGUI/SMESHGUI_ExtrusionDlg.cxx
src/SMESHGUI/SMESHGUI_ExtrusionDlg.h
src/SMESHGUI/SMESHGUI_MeshDlg.cxx
src/SMESHGUI/SMESHGUI_MeshDlg.h
src/SMESHGUI/SMESHGUI_MeshOp.cxx
src/SMESHGUI/SMESHGUI_Operations.h
src/SMESHGUI/SMESHGUI_Selection.cxx
src/SMESHGUI/SMESH_msg_en.ts
src/SMESHUtils/SMESH_MeshAlgos.cxx
src/SMESH_I/SMESH_Gen_i.cxx
src/SMESH_I/SMESH_MeshEditor_i.cxx
src/SMESH_I/SMESH_MeshEditor_i.hxx
src/SMESH_SWIG/smeshBuilder.py
src/StdMeshers/StdMeshers_FaceSide.cxx
src/StdMeshers/StdMeshers_FaceSide.hxx
src/StdMeshers/StdMeshers_QuadFromMedialAxis_1D2D.cxx
src/StdMeshers/StdMeshers_RadialQuadrangle_1D2D.cxx
src/StdMeshers/StdMeshers_RadialQuadrangle_1D2D.hxx
src/Tools/YamsPlug/monViewText.py
src/Tools/YamsPlug/yamsplug_plugin.py
src/Tools/smesh_plugins.py

index 490c0e00878465dc01cf356c332fdb633ac8805b..ece28f210cdab30d0709f889bf0ea4377feea676 100755 (executable)
@@ -21,6 +21,9 @@ PROJECT(SalomeSMESH C CXX)
 
 # Ensure a proper linker behavior:
 CMAKE_POLICY(SET CMP0003 NEW)
+IF(WIN32)
+  CMAKE_POLICY(SET CMP0020 OLD) # disable automatic linking to qtmain.lib 
+ENDIF(WIN32)
 
 # Versioning
 # ===========
@@ -306,7 +309,7 @@ ENDIF(SALOME_SMESH_ENABLE_MEFISTO)
 
 IF(SALOME_BUILD_GUI)
   LIST(APPEND _${PROJECT_NAME}_exposed_targets
-      SMESHObject SMESHFiltersSelection SMESH GeomSelectionTools StdMeshersGUI
+      SMESHObject SMESHFiltersSelection SMESH PluginUtils StdMeshersGUI
   )
 ENDIF(SALOME_BUILD_GUI)
 
index 5b42334258a4eda7e8416740b812ce918933cf03..6fe86346c53f50c6ce095014790dfdd9fe25e44d 100644 (file)
@@ -145,7 +145,7 @@ IF(SALOME_SMESH_ENABLE_MEFISTO)
   SET(SMESH_MEFISTO2D MEFISTO2D)
 ENDIF(SALOME_SMESH_ENABLE_MEFISTO)
 SET(SMESH_SMESHObject SMESHObject)
-SET(SMESH_GeomSelectionTools GeomSelectionTools)
+SET(SMESH_PluginUtils PluginUtils)
 SET(SMESH_SMDS SMDS)
 SET(SMESH_SMESHimpl SMESHimpl)
 SET(SMESH_SMESHEngine SMESHEngine)
index 3980d4d74ebd3b4cd1fc5f8387981bb5c5faa9bc..230e67a00f8f9ec9886c5288fc37d5941c5d3677 100644 (file)
@@ -40,11 +40,27 @@ algo_local = mesh.Segment(EdgeX)
 algo_local.Arithmetic1D(1, 4)
 
 # define "Propagation" hypothesis that propagates algo_local and "Arithmetic1D" hypothesis
-# on all parallel edges of the box
+# from EdgeX to all parallel edges
 algo_local.Propagation()
 
 # assign a hexahedral algorithm
 mesh.Hexahedron()
 
-# compute the mesh
+
+# any sub-shape can be meshed individually --
+# compute mesh on two surfaces using different methods
+
+# get surfaces
+surfaces = geompy.SubShapeAll(box, geompy.ShapeType["FACE"])
+
+# method 1: no sub-mesh is created
+mesh.Compute( surfaces[0] )
+
+# method 2: a sub-mesh is created
+submesh = mesh.GetSubMesh( surfaces[2], "submesh 2" )
+submesh.Compute()
+
+
+
+# compute the whole mesh
 mesh.Compute()
index 2060a5b09344f003a52d196e3ec34999cffe1151..9479329a00f6cf4b6c0f8747c0b30b0b47e8bbe1 100644 (file)
@@ -48,8 +48,6 @@ ADD_CUSTOM_TARGET(usr_docs ${CMAKE_COMMAND} -E make_directory tmp1
   WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
 )
 
-#ADD_DEPENDENCIES(usr_docs html_docs)
-
 INSTALL(CODE "EXECUTE_PROCESS(COMMAND \"${CMAKE_COMMAND}\" --build ${PROJECT_BINARY_DIR} --target usr_docs)")
 INSTALL(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/SMESH DESTINATION ${SALOME_INSTALL_DOC}/gui)
 INSTALL(FILES images/head.png DESTINATION ${SALOME_INSTALL_DOC}/gui/SMESH)
index 5f0d13039f1082c3c0e498abefb40c61dcbfe7b7..7de580be18c7ef18d5903b7752fdfb665fda67ae 100644 (file)
Binary files a/doc/salome/gui/SMESH/images/extrusionalongaline1.png and b/doc/salome/gui/SMESH/images/extrusionalongaline1.png differ
diff --git a/doc/salome/gui/SMESH/images/topo_equality.png b/doc/salome/gui/SMESH/images/topo_equality.png
new file mode 100644 (file)
index 0000000..119251a
Binary files /dev/null and b/doc/salome/gui/SMESH/images/topo_equality.png differ
index 43f99e5c599e71976cd33d0a38dfb9377b32dd54..b7fe2feee549fd60768816ed9c5949257d15cec3 100644 (file)
@@ -2,6 +2,8 @@
 
 \page constructing_submeshes_page Constructing sub-meshes
 
+\tableofcontents
+
 By purpose, the sub-mesh is an object used to assign to a sub-shape
 different meshing parameters than those assigned to the main shape.
 
@@ -14,6 +16,12 @@ Creation of a sub-mesh allows to control individually meshing of a
 certain sub-shape, thus to get a locally coarser or finer mesh, to get
 elements of different types in the same mesh, etc.
 
+A sub-mesh can be meshed individually. To achieve this, select a
+sub-mesh and either invoke <b>Compute Sub-mesh</b> vai the contextual
+menu in the Object Browser or invoke <b> Mesh > Compute </b> menu.
+
+\section submesh_shape_section How to get a sub-shape for sub-mesh construction
+
 A sub-shape to create a sub-mesh on should be retrieved from the main shape
 in one of the following ways: <ul>
 <li> In Geometry module, via <em>New Entity > Explode</em> menu.</li>
@@ -27,6 +35,8 @@ in one of the following ways: <ul>
       dialog showing \ref meshing_failed_anchor "meshing errors".</li> 
 </ul>
 
+\section submesh_priority How hypotheses are selected among sub-meshes
+
 Internally, definition of meshing parameters to apply for
 discretization of a certain sub-shape, for example an edge of a
 compound of solids, starts from searching an algorithm, 1D as for the
@@ -62,6 +72,8 @@ an edge, the hypothesis assigned to a sub-shape with a lower ID will
 be used for meshing. You can \ref submesh_order_anchor "change" mutual
 priority of such concurrent sub-meshes. 
 
+\section submesh_definition How to construct a sub-mesh
+
 \n Construction of a sub-mesh consists of:
 <ul>
 <li>Selecting a mesh which will encapsulate the sub-mesh</li>
@@ -123,6 +135,8 @@ ID in <b> Element ID</b> field.
 with which the sub-shape will appear in the Object Browser (if not yet
 there).
 
+\section submesh_tree Sub-mesh in the Object Browser
+
 In the Object Browser the structure of the new sub-mesh will be
 displayed as follows:
 
@@ -133,9 +147,9 @@ It contains:
 <li>a sub-mesh name (\a SubMeshFace1)
 <li>a reference to the geometrical object on the basis of which the
   sub-mesh has been constructed (<em>Cylindrical Face_1</em>);</li>
-<li><em>Applied hypotheses</em> folder containing the references to the
+<li><em>Applied hypotheses</em> folder containing references to
 hypotheses assigned to the sub-mesh;</li>
-<li><em>Applied algorithms</em> folder containing the references to the
+<li><em>Applied algorithms</em> folder containing references to
 algorithms assigned to the sub-mesh.</li>
 </ul>
 
index 6b07af9e1aa89d836a8adb0cb9140eb05388f725..96da45d43f1c7610f36ca0fae33714c044746b2f 100644 (file)
@@ -128,6 +128,25 @@ The following dialog will appear:
   </ul>
 
   <li>Specify the <b>Number of steps</b>.</li>
+
+  <li>Optionally specify <b>Scale Factors</b>. Each scale factor in
+  the list is applied to nodes of a corresponding extrusion step
+  unless <b>Linear Variation of Scale Factors</b> is checked, is
+  which case the scale factors are spread over all extrusion steps.</li>
+  <ul>
+    <li><b>Scaling Center</b> can be defined either using spin boxes
+    or by picking a node in the Viewer or by picking a geometrical
+    vertex in the Object Browser.</li>
+    <li>\b Add button adds a scale factor to the list.
+      \image html add.png
+      <center><em>"Add" button</em></center>
+    </li>
+    <li>\b Remove button removes selected scale factors from the list.
+      \image html remove.png
+      <center><em>"Remove" button</em></center>
+    </li>
+  </ul>
+
   <li>If you activate <b>Generate Groups</b> check-box, the <em>result elements</em>
     created from <em>selected elements</em> contained in groups will be
     included into new groups named by pattern "<old group
index 71ba2a9125d6d26b4fbd0807a2597e8f8ecb2b38..5f98399c76ce6601f0b0b78cd5ff38b6b0738057 100644 (file)
@@ -49,21 +49,35 @@ The \b Local algorithms and hypotheses to be chosen at
 \ref constructing_submeshes_page "Construction of sub-meshes" are:
 <ul>
   <li> 1D and 2D algorithms and hypotheses that will be applied for
-    meshing the top and the base prism faces. These faces can be meshed
+    meshing the top and the base prism
+    \ref submesh_shape_section "faces". These faces can be meshed
     with any type of 2D elements: quadrangles, triangles, polygons or
-    their mix. It is enough to define a sub-mesh on either the top or the base
-    face. In the sample picture above, "NETGEN_1D2D" algorithm meshes
-    "bottom disk" face with triangles. (1D algorithm is not
-    assigned as "NETGEN_1D2D" does not require divided edges to create a 2D mesh.)
+    their mix. It is enough to define a sub-mesh on either the top or
+    the base face. In the sample picture above, "NETGEN_1D2D"
+    algorithm meshes "bottom disk" face with triangles. (1D algorithm
+    is not assigned as "NETGEN_1D2D" does not require divided edges to
+    create a 2D mesh.)
   </li>
-  <li> Optionally you can define a 1D sub-mesh on some vertical edges
-    of stacked prisms, which will override the global 1D hypothesis mentioned
-    above. In the <b>Prism stacks</b> picture, the
-    vertical division is not equidistant on the whole length because 
-    a "Number Of Segments" hypothesis with Scale Factor=3 is assigned to
-    the highlighted edge. 
+  <li> Optionally you can define a 1D sub-mesh on some vertical
+    \ref submesh_shape_section "edges" of stacked prisms, which will
+    override the global 1D hypothesis mentioned above. In the <b>Prism
+    stacks</b> picture, the vertical division is not equidistant on
+    the whole length because a "Number Of Segments" hypothesis with
+    Scale Factor=3 is assigned to the highlighted edge.
 </li></ul>
 
+If <em>3D extrusion</em> algorithm is assigned to a sub-mesh in a mesh
+with multiple sub-meshes, the described above approach may not work as
+expected. For example the bottom face may be meshed by other algorithm
+before <em>3D extrusion</em> have a chance to project a mesh from the
+base face. This thing can happen with vertical edges as well. All
+these can lead to either a meshing failure or to an incorrect meshing.
+
+In such a case, it's necessary to explicitly define algorithms
+that <em>3D extrusion</em> implicitly applies in a simple case:
+- assign \ref projection_1D2D algorithm to the top face and
+- assign a 1D algorithm to a group of all vertical edges.
+
 \image html image157.gif "Prism with 3D extrusion meshing. Vertical division is different on neighbor edges because several local 1D hypotheses are assigned."
 
 \sa a sample TUI Script of
index 4e5b6e90d4e0ed7932631fb04d1682de30b2b277..de11a7ee0e17db89daa865ab09ecd8561e6005fb 100644 (file)
@@ -2,9 +2,20 @@
 
 \page projection_algos_page Projection Algorithms
 
-\n Projection algorithms allow to define the mesh of a geometrical
+\tableofcontents
+
+Projection algorithms allow to define the mesh of a geometrical
 object by the projection of another already meshed geometrical object.
 
+\note Source and target geometrical objects mush be topologically
+equal, i.e. they must have same number of sub-shapes, connected to
+corresponding counterparts.
+
+\image html topo_equality.png Topologically equal faces suitable for 2D projection.
+
+
+\section projection_1D Projection 1D
+
 <b>Projection 1D</b> algorithm allows to define the mesh of an edge
 (or group of edges)
 by the projection of another already meshed edge (or group of edges).
@@ -34,6 +45,8 @@ vertices are specified, the edges in the group must be connected.
 The source and target groups must contain equal number of edges
 and they must form topologically equal structures.
 
+\section projection_2D Projection 2D
+
 \n <b>Projection 2D</b> algorithm allows to define the mesh of a face
 (or group of faces) by the projection of another already meshed face
 (or group of faces). This algorithm works only if all edges of the
@@ -64,12 +77,16 @@ The groups of faces are suitable for this algorithm only if they
 contain an equal number of faces and form topologically equal
 structures.
 
-\n <b>Projection 1D-2D</b> algorithm differs from <b>Projection 2D</b>
-algorithm in one aspect: it generates mesh segments on edges of
-the face according to the projected 2D elements; thus it does not
-require the edges to be meshed by any other 1D algorithm; moreover it
-does not allow to mesh edges of the face using another algorithm via
-definition of sub-meshes.
+\section projection_1D2D Projection 1D-2D
+
+\n <b>Projection 1D-2D</b> algorithm differs from
+\ref projection_2D algorithm in one aspect: it generates mesh segments
+on edges of the face according to the projected 2D elements; thus it
+does not require the edges to be meshed by any other 1D algorithm;
+moreover it does not allow to mesh edges of the face using another
+algorithm via definition of sub-meshes.
+
+\section projection_3D Projection 3D
 
 \n <b>Projection 3D</b> algorithm allows to define the mesh of a shape by
 the projection of another already meshed shape.  This algorithm works
index 0854941eadda5303c36ae6d8f77f85841c154200..097d217c2161782865726a05a94af15eaddc6f05 100644 (file)
@@ -3,20 +3,26 @@
 \page radial_quadrangle_1D2D_algo_page Radial Quadrangle 1D2D
 
 \n This algorithm applies to the meshing of 2D shapes under the
-following conditions: the face must be a full circle or a part of circle
-(i.e. the number of edges is less or equal to 3 and one of them is a circle curve).
+following conditions: the face must be a full ellipse or a part of ellipse
+(i.e. the number of edges is less or equal to 3 and one of them is an ellipse curve).
 The resulting mesh consists of triangles (near the center point) and
 quadrangles.
 
-This algorithm is optionally parametrized by the hypothesis indicating the number
-of mesh layers along the radius. The distribution of layers can be set with any 1D Hypothesis.
+This algorithm is optionally parametrized by the hypothesis indicating
+the number of mesh layers along the radius. The distribution of layers
+can be set with any 1D Hypothesis. If the face boundary includes
+radial edges, this distribution is applied to the longest radial
+edge. If the face boundary does not include radial edges, this
+distribution is applied to the longest virtual radial edge. The
+distribution is applied to the longest radial edge starting from its
+end lying on the elliptic curve.
 
-If no own hypothesis of the algorithm is assigned, any local or global hypothesis is used 
-by the algorithm to discretize edges. Note that if the geometrical face has two radial edges,
-they must be meshed with equal number of segments.
 
-If no 1D hypothesis is assigned to an edge, "Default Number of Segments" preferences parameter
-is used to discretize the edge.
+If no own hypothesis of the algorithm is assigned, any local or global
+hypothesis is used by the algorithm to discretize edges.
+
+If no 1D hypothesis is assigned to an edge, "Default Number of
+Segments" preferences parameter is used to discretize the edge.
 
 \image html hypo_radquad_dlg.png
 
index 28bc6f9122db21ead20e863a68b44c535e3ac32c..120e41e49fa05a9cccdbd790fde417c56a12072f 100644 (file)
@@ -487,6 +487,9 @@ module SMESH
                                        in ListOfIDSources faces,
                                        in DirStruct       stepVector,
                                        in long            nbOfSteps,
+                                       in double_array    scaleFactors,
+                                       in boolean         linearVariation,
+                                       in double_array    basePoint,
                                        in boolean         toMakeGroups)
       raises (SALOME::SALOME_Exception);
 
index f279c08c8f0452e244f19391a1a3c3284a2a7fcc..f31f262c03438b16bd4bcd561a227484f13ab973 100644 (file)
@@ -60,7 +60,7 @@ DriverMED_W_SMESHDS_Mesh::DriverMED_W_SMESHDS_Mesh():
   myDoGroupOfVolumes (false),
   myDoGroupOf0DElems(false),
   myDoGroupOfBalls(false),
-  myAutoDimension(true),
+  myAutoDimension(false),
   myAddODOnVertices(false)
 {}
 
@@ -331,13 +331,22 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform()
     }
 
     // Mesh dimension definition
+
+    TInt aMeshDimension = 0;
+    if ( myMesh->NbEdges() > 0 )
+      aMeshDimension = 1;
+    if ( myMesh->NbFaces() > 0 )
+      aMeshDimension = 2;
+    if ( myMesh->NbVolumes() > 0 )
+      aMeshDimension = 3;
+
     TInt aSpaceDimension = 3;
     TCoordHelperPtr aCoordHelperPtr;
     {
       bool anIsXDimension = false;
       bool anIsYDimension = false;
       bool anIsZDimension = false;
-      if ( myAutoDimension )
+      if ( myAutoDimension && aMeshDimension < 3 )
       {
         SMDS_NodeIteratorPtr aNodesIter = myMesh->nodesIterator();
         double aBounds[6];
@@ -380,7 +389,7 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform()
         anIsXDimension = (aBounds[1] - aBounds[0]) + abs(aBounds[1]) + abs(aBounds[0]) > EPS;
         anIsYDimension = (aBounds[3] - aBounds[2]) + abs(aBounds[3]) + abs(aBounds[2]) > EPS;
         anIsZDimension = (aBounds[5] - aBounds[4]) + abs(aBounds[5]) + abs(aBounds[4]) > EPS;
-        aSpaceDimension = anIsXDimension + anIsYDimension + anIsZDimension;
+        aSpaceDimension = Max( aMeshDimension, anIsXDimension + anIsYDimension + anIsZDimension );
         if ( !aSpaceDimension )
           aSpaceDimension = 3;
         // PAL16857(SMESH not conform to the MED convention):
@@ -420,13 +429,6 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform()
         break;
       }
     }
-    TInt aMeshDimension = 0;
-    if ( myMesh->NbEdges() > 0 )
-      aMeshDimension = 1;
-    if ( myMesh->NbFaces() > 0 )
-      aMeshDimension = 2;
-    if ( myMesh->NbVolumes() > 0 )
-      aMeshDimension = 3;
     
     MED::PWrapper myMed = CrWrapper(myFile,myMedVersion);
     PMeshInfo aMeshInfo = myMed->CrMeshInfo(aMeshDimension,aSpaceDimension,aMeshName);
index b0136d8e4f62a00ca5e9409bbc50b65eef3f6244..4006b506df86350067c6e2e3daca7fd29ff5ef93 100644 (file)
@@ -988,28 +988,33 @@ SetControlMode( eControl theMode, bool theCheckEntityMode )
 
     vtkUnstructuredGrid* aGrid = myControlActor->GetUnstructuredGrid();
     vtkIdType aNbCells = aGrid->GetNumberOfCells();
+    bool aShowOnlyScalarBarTitle = false;
     if(aNbCells){
       myControlMode = theMode;
       switch(myControlMode){
       case eFreeNodes:
       case eCoincidentNodes:
         myNodeExtActor->SetExtControlMode(myFunctor);
+        aShowOnlyScalarBarTitle = true;
         break;
       case eFreeEdges:
       case eFreeBorders:
       case eCoincidentElems1D:
         my1DExtActor->SetExtControlMode(myFunctor);
+        aShowOnlyScalarBarTitle = true;
         break;
       case eFreeFaces:
       case eBareBorderFace:
       case eOverConstrainedFace:
       case eCoincidentElems2D:
         my2DExtActor->SetExtControlMode(myFunctor);
+        aShowOnlyScalarBarTitle = true;
         break;
       case eBareBorderVolume:
       case eOverConstrainedVolume:
       case eCoincidentElems3D:
         my3DExtActor->SetExtControlMode(myFunctor);
+        aShowOnlyScalarBarTitle = true;
         break;
       case eLength2D:
       case eMultiConnection2D:
@@ -1020,6 +1025,7 @@ SetControlMode( eControl theMode, bool theCheckEntityMode )
         myControlActor->SetControlMode(myFunctor,myScalarBarActor,myLookupTable);
         UpdateDistribution();
       }
+      myScalarBarActor->SetTitleOnlyVisibility(aShowOnlyScalarBarTitle);
     }
 
     if(theCheckEntityMode) {
@@ -1057,6 +1063,9 @@ SetControlMode( eControl theMode, bool theCheckEntityMode )
         SetEntityMode(eVolumes);
     }
     }
+    QString aTitle = QString(myScalarBarActor->GetTitle());
+    aTitle.replace(QRegExp("(:\\s).*"),"\\1"+ QString::number(GetNumberControlEntities()));
+    myScalarBarActor->SetTitle(aTitle.toLatin1().constData());
 
   }
   else {
@@ -1081,6 +1090,34 @@ SetControlMode( eControl theMode, bool theCheckEntityMode )
   Update();
 }
 
+int
+SMESH_ActorDef::
+GetNumberControlEntities(){
+  SMESH_DeviceActor* anAct = NULL;
+  switch(myControlMode){
+    case eFreeNodes:
+    case eCoincidentNodes:
+      anAct = myNodeExtActor;
+      break;
+    case eFreeEdges:
+    case eFreeBorders:
+    case eCoincidentElems1D:
+      anAct = my1DExtActor;
+      break;
+    case eFreeFaces:
+    case eBareBorderFace:
+    case eOverConstrainedFace:
+    case eCoincidentElems2D:
+      anAct = my2DExtActor;
+      break;
+    case eBareBorderVolume:
+    case eOverConstrainedVolume:
+    case eCoincidentElems3D:
+      anAct = my3DExtActor;
+      break;
+  }
+  return (anAct) ? anAct->GetUnstructuredGrid()->GetNumberOfCells() : -1;
+}
 
 void SMESH_ActorDef::AddToRender(vtkRenderer* theRenderer){
 
@@ -1424,10 +1461,10 @@ void SMESH_ActorDef::SetVisibility(int theMode, bool theIsUpdateRepersentation){
       case eLength2D:
       case eMultiConnection2D:
         my1DExtActor->VisibilityOn();
-      default:
-        if(myControlActor->GetUnstructuredGrid()->GetNumberOfCells())
-          myScalarBarActor->VisibilityOn();
+        break;
       }
+      if(myControlActor->GetUnstructuredGrid()->GetNumberOfCells())
+        myScalarBarActor->VisibilityOn();
     }
 
     if(myRepresentation != ePoint)
index 5fc9a92b9abe99ed9f495ef7d316b0d04dfa71b1..abe27bb4e3a8adf901fe64df8ae9699127952002 100644 (file)
@@ -150,6 +150,7 @@ class SMESHOBJECT_EXPORT SMESH_Actor: public SALOME_Actor
   virtual void SetControlMode(eControl theMode) = 0;
   virtual eControl GetControlMode() = 0;
   virtual SMESH::Controls::FunctorPtr GetFunctor() = 0;
+  virtual int GetNumberControlEntities() = 0;
 
   virtual SMESH_ScalarBarActor* GetScalarBarActor() = 0;
 
index 927199488bd9e8edc0d6a79906edde0eb7721f47..eb3654ab2054ea4c7159d7e4c34b95dbb7245dfb 100644 (file)
@@ -207,6 +207,7 @@ class SMESH_ActorDef : public SMESH_Actor
   virtual bool GetFacesOrientation3DVectors();
 
   virtual void SetControlMode(eControl theMode);
+  virtual int GetNumberControlEntities();
   virtual eControl GetControlMode(){ return myControlMode;}
   virtual SMESH::Controls::FunctorPtr GetFunctor() { return myFunctor; }
 
index 4520d93273d8de3912bc104d4cb2673795b42168..f9195f19f98ba7899856aac42ee7d7e0bf1f1528 100644 (file)
@@ -142,7 +142,7 @@ SMESH_DeviceActor
   if(MYDEBUG) MESSAGE("~SMESH_DeviceActor - "<<this);
 
   myMapper->Delete();
-
+  myPlaneCollection->Delete();
   myProperty->Delete();
 
   myExtractGeometry->Delete();
index 92a8a94b4d98a463b8c4fae8b133fa029b8df50d..1f5b00b63a5ee13e16f5c72587cd3addce35024e 100644 (file)
@@ -115,6 +115,9 @@ SMESH_ScalarBarActor::SMESH_ScalarBarActor() {
 
   // By default monocolor
   myDistributionColoringType = SMESH_MONOCOLOR_TYPE;
+
+  // By default scalar map is shown
+  myTitleOnlyVisibility = false;
   // rnv end
 }
 
@@ -194,19 +197,20 @@ int SMESH_ScalarBarActor::RenderOverlay(vtkViewport *viewport)
     {
     renderedSomething += this->TitleActor->RenderOverlay(viewport);
     }
-  this->ScalarBarActor->RenderOverlay(viewport);
-  this->myDistributionActor->RenderOverlay(viewport);
-  if( this->TextActors == NULL)
-    {
-     vtkWarningMacro(<<"Need a mapper to render a scalar bar");
-     return renderedSomething;
-    }
+  if (!myTitleOnlyVisibility) {
+    this->ScalarBarActor->RenderOverlay(viewport);
+    this->myDistributionActor->RenderOverlay(viewport);
+    if( this->TextActors == NULL)
+      {
+       vtkWarningMacro(<<"Need a mapper to render a scalar bar");
+       return renderedSomething;
+      }
   
-  for (i=0; i<this->NumberOfLabels; i++)
-    {
-    renderedSomething += this->TextActors[i]->RenderOverlay(viewport);
-    }
-
+    for (i=0; i<this->NumberOfLabels; i++)
+      {
+      renderedSomething += this->TextActors[i]->RenderOverlay(viewport);
+      }
+  }  
   renderedSomething = (renderedSomething > 0)?(1):(0);
 
   return renderedSomething;
@@ -574,7 +578,7 @@ int SMESH_ScalarBarActor::RenderOpaqueGeometry(vtkViewport *viewport)
       
       // rnv begin
       // Customization of the vtkScalarBarActor to show distribution histogram.
-      if(myNbValues[i] && myDistributionColoringType == SMESH_MULTICOLOR_TYPE && GetDistributionVisibility() && distrVisibility)
+      if(myDistributionColoringType == SMESH_MULTICOLOR_TYPE && GetDistributionVisibility() && distrVisibility)
         {
           rgb = distColors->GetPointer(3*dcCount); //write into array directly
           rgb[0] = rgba[0];
@@ -920,3 +924,11 @@ void SMESH_ScalarBarActor::SetDistributionColor (double rgb[3]) {
 void SMESH_ScalarBarActor::GetDistributionColor (double rgb[3]) {
   myDistributionActor->GetProperty()->GetColor(rgb);
 }
+
+void SMESH_ScalarBarActor::SetTitleOnlyVisibility( bool theTitleOnlyVisibility) {
+  myTitleOnlyVisibility = theTitleOnlyVisibility;
+}
+
+bool SMESH_ScalarBarActor::GetTitleOnlyVisibility() {
+  return myTitleOnlyVisibility;
+}
index 4dda0ad52e2fc16ff8c98f2d1427c22e9154481e..ffc91bb118b54aef89cd046e5d3c5991ad9ef377 100644 (file)
@@ -192,7 +192,13 @@ class SMESHOBJECT_EXPORT SMESH_ScalarBarActor: public vtkActor2D {
   // Get Distribution Color
   void GetDistributionColor (double rgb[3]);
   
+  // Description:
+  // Set visibility status of scalar map 
+  void SetTitleOnlyVisibility( bool );
 
+  // Description:
+  // Get visibility status of scalar map 
+  bool GetTitleOnlyVisibility();
 
  protected:
   SMESH_ScalarBarActor();
@@ -237,6 +243,7 @@ class SMESHOBJECT_EXPORT SMESH_ScalarBarActor: public vtkActor2D {
   vtkPolyDataMapper2D*   myDistributionMapper;       //Distribution mapper
   std::vector<int>       myNbValues;                 //Nb values for the range
   int                    myDistributionColoringType; //Distribution color type (monocolor or multicolor)
+  bool                   myTitleOnlyVisibility;      //Show scalar map or not
   
  private:
   SMESH_ScalarBarActor(const SMESH_ScalarBarActor&);  // Not implemented.
index 2c2613c90f229dd48eb2aa72f8454983e639d206..b72bb89aea9894656afa64e55098914a5cae45de 100644 (file)
@@ -35,6 +35,7 @@ INCLUDE_DIRECTORIES(
 
 # additional preprocessor / compiler flags
 ADD_DEFINITIONS(
+  ${QT_DEFINITIONS}
   ${CAS_DEFINITIONS}
   ${BOOST_DEFINITIONS}
   ${OMNIORB_DEFINITIONS}
@@ -47,6 +48,8 @@ SET(_link_LIBRARIES
   ${KERNEL_SalomeLifeCycleCORBA}
   ${CAS_TKBRep}
   ${CAS_TKV3d}
+  ${QT_LIBRARIES}
+  ${QT_MT_LIBS}
   ${GUI_SalomeObject}
   ${GUI_suit}
   ${GUI_LightApp}
@@ -58,21 +61,28 @@ SET(_link_LIBRARIES
 # --- headers ---
 
 # header files / to be processed by moc
-SET(GeomSelectionTools_HEADERS
+SET(PluginUtils_HEADERS
   GeomSelectionTools.h
+  SMESH_PluginUtils.h
+  SMESH_AdvOptionsWdg.h
 )
 
 # --- sources ---
 
+# sources / moc wrappings
+QT_WRAP_MOC(_moc_SOURCES SMESH_AdvOptionsWdg.h)
+
 # sources / static
-SET(GeomSelectionTools_SOURCES
+SET(PluginUtils_SOURCES
   GeomSelectionTools.cxx
+  SMESH_AdvOptionsWdg.cxx
+  ${_moc_SOURCES}
 )
 
 # --- rules ---
 
-ADD_LIBRARY(GeomSelectionTools ${GeomSelectionTools_SOURCES})
-TARGET_LINK_LIBRARIES(GeomSelectionTools ${_link_LIBRARIES} )
-INSTALL(TARGETS GeomSelectionTools EXPORT ${PROJECT_NAME}TargetGroup DESTINATION ${SALOME_INSTALL_LIBS})
+ADD_LIBRARY(PluginUtils ${PluginUtils_SOURCES})
+TARGET_LINK_LIBRARIES(PluginUtils ${_link_LIBRARIES} )
+INSTALL(TARGETS PluginUtils EXPORT ${PROJECT_NAME}TargetGroup DESTINATION ${SALOME_INSTALL_LIBS})
 
-INSTALL(FILES ${GeomSelectionTools_HEADERS} DESTINATION ${SALOME_INSTALL_HEADERS})
+INSTALL(FILES ${PluginUtils_HEADERS} DESTINATION ${SALOME_INSTALL_HEADERS})
index 55337150cad856ecc0264dbc60904b6a0f141ff9..c4013ff99ea1be648e251a9a78ea043a81f92f09 100644 (file)
 #ifndef _GEOMSELECTIONTOOLS_H_
 #define _GEOMSELECTIONTOOLS_H_
 
-#ifdef WIN32
-#  ifdef GeomSelectionTools_EXPORTS
-#    define GEOMSELECTIONTOOLS_EXPORT __declspec( dllexport )
-#  else
-#    define GEOMSELECTIONTOOLS_EXPORT __declspec( dllimport )
-#  endif
-#else
-#  define GEOMSELECTIONTOOLS_EXPORT
-#endif
-
-#include "SALOMEDSClient.hxx"
-#include "SALOME_InteractiveObject.hxx"
+#include "SMESH_PluginUtils.h"
+
+#include <SALOMEDSClient.hxx>
+#include <SALOME_InteractiveObject.hxx>
 #include <SALOME_ListIO.hxx>
 #include <SalomeApp_Application.h>
 
@@ -54,7 +46,7 @@ class LightApp_SelectionMgr;
  *
  */
 
-class GEOMSELECTIONTOOLS_EXPORT GeomSelectionTools
+class PLUGINUTILS_EXPORT GeomSelectionTools
 {
 
 private:
@@ -84,7 +76,7 @@ public:
 
 namespace PluginUtils
 {
-  GEOMSELECTIONTOOLS_EXPORT QString PrintDoubleValue( double, int = 16 );
+  PLUGINUTILS_EXPORT QString PrintDoubleValue( double, int = 16 );
 };
 
 #endif // _GEOMSELECTIONTOOLS_H_
diff --git a/src/PluginUtils/SMESH_AdvOptionsWdg.cxx b/src/PluginUtils/SMESH_AdvOptionsWdg.cxx
new file mode 100644 (file)
index 0000000..5ae7c92
--- /dev/null
@@ -0,0 +1,155 @@
+// Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// File   : SMESH_AdvOptionsWdg.h
+// Author : Open CASCADE S.A.S.
+
+#include "SMESH_AdvOptionsWdg.h"
+
+#include <QTableWidget>
+#include <QPushButton>
+#include <QGridLayout>
+#include <QCheckBox>
+#include <QHeaderView>
+
+#define SPACING 6
+#define MARGIN  11
+
+namespace
+{
+  const int IS_CUSTOM = Qt::UserRole;
+}
+
+SMESH_AdvOptionsWdg::SMESH_AdvOptionsWdg( QWidget* parent )
+  : QWidget( parent )
+{
+  myTable = new QTableWidget( /*nbrows=*/0, /*nbcol=*/3, this );
+  QPushButton* addBtn = new QPushButton( tr("ADD_OPTION_BTN"), this );
+
+  myTable->setHorizontalHeaderLabels
+    ( QStringList() << tr("CHOICE") << tr("OPTION_NAME") << tr("OPTION_VALUE") );
+  QHeaderView * header = myTable->horizontalHeader();
+  header->setSectionResizeMode( 0, QHeaderView::ResizeToContents );
+  header->setSectionResizeMode( 1, QHeaderView::Stretch );
+  header->setSectionResizeMode( 2, QHeaderView::ResizeToContents );
+
+  QGridLayout* lay = new QGridLayout( this );
+  lay->setMargin( MARGIN );
+  lay->setSpacing( SPACING );
+  lay->addWidget( myTable, 0,0, 1,3 );
+  lay->addWidget( addBtn,  1,0 );
+
+  connect( addBtn, SIGNAL( clicked() ), SLOT( onAdd() ));
+}
+
+SMESH_AdvOptionsWdg::~SMESH_AdvOptionsWdg()
+{
+}
+
+void SMESH_AdvOptionsWdg::AddOption( QString name, QString value, bool isDefault, bool isCustom )
+{
+  int row = myTable->rowCount();
+  myTable->insertRow( row );
+
+  QTableWidgetItem*  nameItem = new QTableWidgetItem( name );
+  QTableWidgetItem* valueItem = new QTableWidgetItem( value );
+  if ( !name.isEmpty() )
+    nameItem->setFlags( nameItem->flags() & ~Qt::ItemIsEditable );
+  myTable->setItem( row, 1, nameItem );
+  myTable->setItem( row, 2, valueItem );
+  nameItem->setData( IS_CUSTOM, isCustom );
+
+  QCheckBox* chkBox = new QCheckBox();
+  QWidget*      wdg = new QWidget();
+  QHBoxLayout*  lay = new QHBoxLayout( wdg );
+  lay->setContentsMargins(0,0,0,0);
+  lay->addStretch();
+  lay->addWidget(chkBox);
+  lay->addStretch();
+  myTable->setCellWidget( row, 0, wdg );
+  connect( chkBox, SIGNAL(toggled(bool)), this, SLOT(onToggle()));
+  myTable->setCurrentCell( row, 1, QItemSelectionModel::NoUpdate );
+  chkBox->setChecked( !isDefault );
+
+  if ( name.isEmpty() )
+    myTable->editItem( nameItem );
+}
+
+void SMESH_AdvOptionsWdg::SetCustomOptions( const QString& text )
+{
+  QStringList nameVals = text.split(" ");
+  for ( int i = 1; i < nameVals.count(); i += 2 )
+    AddOption( nameVals[i-1], nameVals[i], false, true );
+}
+
+void SMESH_AdvOptionsWdg::onAdd()
+{
+  AddOption( "", "", false, true );
+  
+}
+void SMESH_AdvOptionsWdg::onToggle()
+{
+  int row = myTable->currentRow();
+  QTableWidgetItem* valueItem = myTable->item( row, 2 );
+
+  bool isActive = isChecked( row );
+  int c = isActive ? 0 : 150;
+  valueItem->setForeground( QBrush( QColor( c, c, c )));
+  if ( isActive )
+    valueItem->setFlags( valueItem->flags() | Qt::ItemIsEditable );
+  else
+    valueItem->setFlags( valueItem->flags() & ~Qt::ItemIsEditable );
+}
+
+void SMESH_AdvOptionsWdg::GetOption( int      row,
+                                     QString& name,
+                                     QString& value,
+                                     bool&    isDefault,
+                                     bool &   isCustom)
+{
+  if ( row < myTable->rowCount() )
+  {
+    name      = myTable->item( row, 1 )->text();
+    value     = myTable->item( row, 2 )->text();
+    isDefault = !isChecked( row );
+    isCustom  = myTable->item( row, 1 )->data( IS_CUSTOM ).toInt();
+  }
+}
+
+QString SMESH_AdvOptionsWdg::GetCustomOptions()
+{
+  QString text, value, name;
+  bool isDefault, isCustom;
+  for ( int row = 0; row < myTable->rowCount(); ++row )
+  {
+    GetOption( row, name, value, isDefault, isCustom );
+    if ( !name.isEmpty() && !value.isEmpty() && isCustom && !isDefault )
+      text += name + " " + value + " ";
+  }
+  return text;
+}
+
+bool SMESH_AdvOptionsWdg::isChecked( int row )
+{
+  QCheckBox* cb = myTable->cellWidget( row, 0 )->findChild<QCheckBox *>();
+  return cb->isChecked();
+}
diff --git a/src/PluginUtils/SMESH_AdvOptionsWdg.h b/src/PluginUtils/SMESH_AdvOptionsWdg.h
new file mode 100644 (file)
index 0000000..3ba3e35
--- /dev/null
@@ -0,0 +1,66 @@
+// Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// File   : SMESH_AdvOptionsWdg.h
+// Author : Open CASCADE S.A.S.
+//
+#ifndef SMESH_ADVOPTIONSWDG_H
+#define SMESH_ADVOPTIONSWDG_H
+
+#include "SMESH_PluginUtils.h"
+
+// Qt includes
+#include <QWidget>
+
+class QTableWidget;
+
+/*!
+ *  \brief Widget for entering options as strings
+ */
+class PLUGINUTILS_EXPORT SMESH_AdvOptionsWdg : public QWidget
+{
+  Q_OBJECT
+
+public:
+  SMESH_AdvOptionsWdg( QWidget* parent = 0 );
+  ~SMESH_AdvOptionsWdg();
+
+  void AddOption( QString name, QString value, bool isDefault, bool isCustom );
+  void SetCustomOptions( const QString& text );
+
+  int  GetNbRows();
+  void GetOption( int row, QString& name, QString& value, bool& isDefault, bool &isCustom);
+  QString GetCustomOptions();
+
+private slots:
+
+  void onAdd();
+  void onToggle();
+
+private:
+
+  bool isChecked( int row );
+
+  QTableWidget* myTable;
+};
+
+#endif
diff --git a/src/PluginUtils/SMESH_PluginUtils.h b/src/PluginUtils/SMESH_PluginUtils.h
new file mode 100644 (file)
index 0000000..3f4484b
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// File   : SMESH_StdMeshersGUI.hxx
+// Author : Alexander BORODIN, Open CASCADE S.A.S.
+//
+#ifndef SMESH_PLUGINUTILS_HXX
+#define SMESH_PLUGINUTILS_HXX
+
+#ifdef WIN32
+ #if defined PLUGINUTILS_EXPORTS || defined PluginUtils_EXPORTS
+  #define PLUGINUTILS_EXPORT __declspec( dllexport )
+ #else
+  #define PLUGINUTILS_EXPORT __declspec( dllimport )
+ #endif
+#else
+ #define PLUGINUTILS_EXPORT
+#endif
+
+#endif // SMESH_PLUGINUTILS_HXX
index f9eeb5755b97bf692bab72bc5807df54366d8108..f7fcec03e8fd5a6fdd42a1e261cdb4f0329a30f3 100644 (file)
@@ -5480,11 +5480,14 @@ SMESH_MeshEditor::RotationSweep(TIDSortedElemSet   theElemSets[2],
 //purpose  : standard construction
 //=======================================================================
 
-SMESH_MeshEditor::ExtrusParam::ExtrusParam( const gp_Vec&  theStep,
-                                            const int      theNbSteps,
-                                            const int      theFlags,
-                                            const double   theTolerance):
+SMESH_MeshEditor::ExtrusParam::ExtrusParam( const gp_Vec&            theStep,
+                                            const int                theNbSteps,
+                                            const std::list<double>& theScales,
+                                            const gp_XYZ*            theBasePoint,
+                                            const int                theFlags,
+                                            const double             theTolerance):
   myDir( theStep ),
+  myBaseP( Precision::Infinite(), 0, 0 ),
   myFlags( theFlags ),
   myTolerance( theTolerance ),
   myElemsToUse( NULL )
@@ -5494,6 +5497,37 @@ SMESH_MeshEditor::ExtrusParam::ExtrusParam( const gp_Vec&  theStep,
   for (int i=1; i<=theNbSteps; i++ )
     mySteps->Append( stepSize );
 
+  int nbScales = theScales.size();
+  if ( nbScales > 0 )
+  {
+    if ( IsLinearVariation() && nbScales < theNbSteps )
+    {
+      myScales.reserve( theNbSteps );
+      std::list<double>::const_iterator scale = theScales.begin();
+      double prevScale = 1.0;
+      for ( int iSc = 1; scale != theScales.end(); ++scale, ++iSc )
+      {
+        int      iStep = int( iSc / double( nbScales ) * theNbSteps + 0.5 );
+        int    stDelta = Max( 1, iStep - myScales.size());
+        double scDelta = ( *scale - prevScale ) / stDelta;
+        for ( int iStep = 0; iStep < stDelta; ++iStep )
+        {
+          myScales.push_back( prevScale + scDelta );
+          prevScale = myScales.back();
+        }
+        prevScale = *scale;
+      }
+    }
+    else
+    {
+      myScales.assign( theScales.begin(), theScales.end() );
+    }
+  }
+  if ( theBasePoint )
+  {
+    myBaseP = *theBasePoint;
+  }
+
   if (( theFlags & EXTRUSION_FLAG_SEW ) &&
       ( theTolerance > 0 ))
   {
@@ -5562,12 +5596,38 @@ SMESH_MeshEditor::ExtrusParam::ExtrusParam( const double theStepSize,
 //=======================================================================
 //function : ExtrusParam::SetElementsToUse
 //purpose  : stores elements to use for extrusion by normal, depending on
-//           state of EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY flag
+//           state of EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY flag;
+//           define myBaseP for scaling
 //=======================================================================
 
-void SMESH_MeshEditor::ExtrusParam::SetElementsToUse( const TIDSortedElemSet& elems )
+void SMESH_MeshEditor::ExtrusParam::SetElementsToUse( const TIDSortedElemSet& elems,
+                                                      const TIDSortedElemSet& nodes )
 {
   myElemsToUse = ToUseInpElemsOnly() ? & elems : 0;
+
+  if ( Precision::IsInfinite( myBaseP.X() )) // myBaseP not defined
+  {
+    myBaseP.SetCoord( 0.,0.,0. );
+    TIDSortedElemSet newNodes;
+
+    const TIDSortedElemSet* elemSets[] = { &elems, &nodes };
+    for ( int is2ndSet = 0; is2ndSet < 2; ++is2ndSet )
+    {
+      const TIDSortedElemSet& elements = *( elemSets[ is2ndSet ]);
+      TIDSortedElemSet::const_iterator itElem = elements.begin();
+      for ( ; itElem != elements.end(); itElem++ )
+      {
+        const SMDS_MeshElement* elem = *itElem;
+        SMDS_ElemIteratorPtr     itN = elem->nodesIterator();
+        while ( itN->more() ) {
+          const SMDS_MeshElement* node = itN->next();
+          if ( newNodes.insert( node ).second )
+            myBaseP += SMESH_TNodeXYZ( node );
+        }
+      }
+    }
+    myBaseP /= newNodes.size();
+  }
 }
 
 //=======================================================================
@@ -5637,6 +5697,41 @@ makeNodesByDir( SMESHDS_Mesh*                     mesh,
     const SMDS_MeshNode * newNode = mesh->AddNode( p.X(), p.Y(), p.Z() );
     newNodes.push_back( newNode );
   }
+
+  if ( !myScales.empty() )
+  {
+    if ( makeMediumNodes && myMediumScales.empty() )
+    {
+      myMediumScales.resize( myScales.size() );
+      double prevFactor = 1.;
+      for ( size_t i = 0; i < myScales.size(); ++i )
+      {
+        myMediumScales[i] = 0.5 * ( prevFactor + myScales[i] );
+        prevFactor = myScales[i];
+      }
+    }
+    typedef std::vector<double>::iterator ScaleIt;
+    ScaleIt scales[] = { myScales.begin(), myMediumScales.begin() };
+
+    size_t iSc = 0, nbScales = myScales.size() + myMediumScales.size();
+
+    gp_XYZ center = myBaseP;
+    std::list<const SMDS_MeshNode*>::iterator nIt = newNodes.begin();
+    size_t iN  = 0;
+    for ( beginStepIter( makeMediumNodes ); moreSteps() && ( iN < nbScales ); ++nIt, ++iN )
+    {
+      center += myDir.XYZ() * nextStep();
+
+      iSc += int( makeMediumNodes );
+      ScaleIt& scale = scales[ iSc % 2 ];
+      
+      gp_XYZ xyz = SMESH_TNodeXYZ( *nIt );
+      xyz = ( *scale * ( xyz - center )) + center;
+      mesh->MoveNode( *nIt, xyz.X(), xyz.Y(), xyz.Z() );
+
+      ++scale;
+    }
+  }
   return nbNodes;
 }
 
@@ -5811,7 +5906,7 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet     theElems[2],
                                   const int            theFlags,
                                   const double         theTolerance)
 {
-  ExtrusParam aParams( theStep, theNbSteps, theFlags, theTolerance );
+  ExtrusParam aParams( theStep, theNbSteps, std::list<double>(), 0, theFlags, theTolerance );
   return ExtrusionSweep( theElems, aParams, newElemsMap );
 }
 
@@ -5832,16 +5927,12 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet     theElemSets[2],
   // source elements for each generated one
   SMESH_SequenceOfElemPtr srcElems, srcNodes;
 
-  //SMESHDS_Mesh* aMesh = GetMeshDS();
-
   setElemsFirst( theElemSets );
   const int nbSteps = theParams.NbSteps();
-  theParams.SetElementsToUse( theElemSets[0] );
+  theParams.SetElementsToUse( theElemSets[0], theElemSets[1] );
 
-  TNodeOfNodeListMap mapNewNodes;
-  //TNodeOfNodeVecMap mapNewNodes;
+  TNodeOfNodeListMap   mapNewNodes;
   TElemOfVecOfNnlmiMap mapElemNewNodes;
-  //TElemOfVecOfMapNodesMap mapElemNewNodes;
 
   const bool isQuadraticMesh = bool( myMesh->NbEdges(ORDER_QUADRATIC) +
                                      myMesh->NbFaces(ORDER_QUADRATIC) +
@@ -6656,24 +6747,23 @@ SMESH_MeshEditor::MakeExtrElements(TIDSortedElemSet                  theElemSets
 
 //=======================================================================
 //function : LinearAngleVariation
-//purpose  : auxilary for ExtrusionAlongTrack
+//purpose  : spread values over nbSteps
 //=======================================================================
-void SMESH_MeshEditor::LinearAngleVariation(const int nbSteps,
+
+void SMESH_MeshEditor::LinearAngleVariation(const int     nbSteps,
                                             list<double>& Angles)
 {
   int nbAngles = Angles.size();
-  if( nbSteps > nbAngles ) {
+  if( nbSteps > nbAngles && nbAngles > 0 )
+  {
     vector<double> theAngles(nbAngles);
-    list<double>::iterator it = Angles.begin();
-    int i = -1;
-    for(; it!=Angles.end(); it++) {
-      i++;
-      theAngles[i] = (*it);
-    }
+    theAngles.assign( Angles.begin(), Angles.end() );
+
     list<double> res;
     double rAn2St = double( nbAngles ) / double( nbSteps );
     double angPrev = 0, angle;
-    for ( int iSt = 0; iSt < nbSteps; ++iSt ) {
+    for ( int iSt = 0; iSt < nbSteps; ++iSt )
+    {
       double angCur = rAn2St * ( iSt+1 );
       double angCurFloor  = floor( angCur );
       double angPrevFloor = floor( angPrev );
@@ -6695,10 +6785,7 @@ void SMESH_MeshEditor::LinearAngleVariation(const int nbSteps,
       res.push_back(angle);
       angPrev = angCur;
     }
-    Angles.clear();
-    it = res.begin();
-    for(; it!=res.end(); it++)
-      Angles.push_back( *it );
+    Angles.swap( res );
   }
 }
 
index 4e9d0220d7940726dbb371cf797fc4e2247faac5..5dd53807a813bcac52c0ba0270c3b0c8f1d4f79b 100644 (file)
@@ -293,21 +293,26 @@ public:
    *                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()
+   * SCALE_LINEAR_VARIATION: to make linear variation of scale factors
    */
   enum ExtrusionFlags {
     EXTRUSION_FLAG_BOUNDARY = 0x01,
     EXTRUSION_FLAG_SEW = 0x02,
     EXTRUSION_FLAG_GROUPS = 0x04,
     EXTRUSION_FLAG_BY_AVG_NORMAL = 0x08,
-    EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY = 0x10
+    EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY = 0x10,
+    EXTRUSION_FLAG_SCALE_LINEAR_VARIATION = 0x20
   };
 
   /*!
    * Generator of nodes for extrusion functionality
    */
-  class SMESH_EXPORT ExtrusParam {
+  class SMESH_EXPORT ExtrusParam
+  {
     gp_Dir                          myDir;   // direction of extrusion
     Handle(TColStd_HSequenceOfReal) mySteps; // magnitudes for each step
+    std::vector<double>             myScales, myMediumScales;// scale factors
+    gp_XYZ                          myBaseP; // scaling center
     SMESH_SequenceOfNode            myNodes; // nodes for using in sewing
     int                             myFlags; // see ExtrusionFlags
     double                          myTolerance; // tolerance for sewing nodes
@@ -319,29 +324,33 @@ public:
                                        const bool                        makeMediumNodes);
 
   public:
-    ExtrusParam( const gp_Vec&  theStep,
-                 const int      theNbSteps,
-                 const int      theFlags = 0,
-                 const double   theTolerance = 1e-6);
+    ExtrusParam( const gp_Vec&                   theStep,
+                 const int                       theNbSteps,
+                 const std::list<double>&        theScales,
+                 const gp_XYZ*                   theBaseP,
+                 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
+    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; }
+    bool IsLinearVariation() const { return myFlags & EXTRUSION_FLAG_SCALE_LINEAR_VARIATION; }
     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 );
+    // state of EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY flag;
+    // define myBaseP for scaling
+    void SetElementsToUse( const TIDSortedElemSet& elems, const TIDSortedElemSet& nodes );
 
     // creates nodes and returns number of nodes added in \a newNodes
     int MakeNodes( SMESHDS_Mesh*                     mesh,
@@ -784,8 +793,8 @@ public:
                                    const bool                             theHasRefPoint,
                                    const gp_Pnt&                          theRefPoint,
                                    const bool                             theMakeGroups);
-  void LinearAngleVariation(const int          NbSteps,
-                            std::list<double>& theAngles);
+  static void LinearAngleVariation(const int          NbSteps,
+                                   std::list<double>& theAngles);
 
   bool doubleNodes( SMESHDS_Mesh*           theMeshDS,
                     const TIDSortedElemSet& theElems,
index 5bb8a34b38ee33a051faa7636d8ab1e23c0c4c52..128316dcf55c87817dbf3e556cb61bf02a660d35 100644 (file)
@@ -2079,10 +2079,10 @@ TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen,
     const TopoDS_Shape&  S = subMesh->_subShape;
     if ( S.ShapeType() != this->_subShape.ShapeType() )
       continue;
-    theSubs.push_back( subMesh );
     if ( subMesh == this )
     {
       aBuilder.Add( aCompound, S );
+      theSubs.push_back( subMesh );
     }
     else if ( subMesh->GetComputeState() == READY_TO_COMPUTE )
     {
@@ -2093,6 +2093,7 @@ TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen,
         aBuilder.Add( aCompound, S );
         if ( !subMesh->SubMeshesComputed() )
           theSubComputed = false;
+        theSubs.push_back( subMesh );
       }
     }
   }
index a14b72eed2c353479538fccc2bf3a81b852e9896..6aff7a098e72518fe77f222f19df7c02e812077d 100644 (file)
@@ -1668,6 +1668,9 @@ namespace
                 if ( anActor->GetControlMode() != aControl )
                   anActor->SetControlMode( aControl );
                 QString functorName = functorToString( anActor->GetFunctor() );
+                int anEntitiesCount = anActor->GetNumberControlEntities();
+                if (anEntitiesCount >= 0)
+                  functorName = functorName + ": " + QString::number(anEntitiesCount);
                 anActor->GetScalarBarActor()->SetTitle( functorName.toLatin1().constData() );
                 SMESH::RepaintCurrentView();
 #ifndef DISABLE_PLOT2DVIEWER
@@ -2688,7 +2691,10 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
   case SMESHOp::OpCreateMesh:
   case SMESHOp::OpCreateSubMesh:
   case SMESHOp::OpEditMeshOrSubMesh:
+  case SMESHOp::OpEditMesh:
+  case SMESHOp::OpEditSubMesh:
   case SMESHOp::OpCompute:
+  case SMESHOp::OpComputeSubMesh:
   case SMESHOp::OpPreCompute:
   case SMESHOp::OpEvaluate:
   case SMESHOp::OpMeshOrder:
@@ -3806,9 +3812,12 @@ void SMESHGUI::initialize( CAM_Application* app )
   createSMESHAction( SMESHOp::OpCreateMesh,           "CREATE_MESH",             "ICON_DLG_INIT_MESH" );
   createSMESHAction( SMESHOp::OpCreateSubMesh,        "CREATE_SUBMESH",          "ICON_DLG_ADD_SUBMESH" );
   createSMESHAction( SMESHOp::OpEditMeshOrSubMesh,    "EDIT_MESHSUBMESH",        "ICON_DLG_EDIT_MESH" );
+  createSMESHAction( SMESHOp::OpEditMesh,             "EDIT_MESH",               "ICON_DLG_EDIT_MESH" );
+  createSMESHAction( SMESHOp::OpEditSubMesh,          "EDIT_SUBMESH",            "ICON_DLG_EDIT_MESH" );
   createSMESHAction( SMESHOp::OpBuildCompoundMesh,    "BUILD_COMPOUND",          "ICON_BUILD_COMPOUND" );
   createSMESHAction( SMESHOp::OpCopyMesh,             "COPY_MESH",               "ICON_COPY_MESH" );
   createSMESHAction( SMESHOp::OpCompute,              "COMPUTE",                 "ICON_COMPUTE" );
+  createSMESHAction( SMESHOp::OpComputeSubMesh,        "COMPUTE_SUBMESH",         "ICON_COMPUTE" );
   createSMESHAction( SMESHOp::OpPreCompute,           "PRECOMPUTE",              "ICON_PRECOMPUTE" );
   createSMESHAction( SMESHOp::OpEvaluate,             "EVALUATE",                "ICON_EVALUATE" );
   createSMESHAction( SMESHOp::OpMeshOrder,            "MESH_ORDER",              "ICON_MESH_ORDER");
@@ -4303,24 +4312,26 @@ void SMESHGUI::initialize( CAM_Application* app )
   QString dc = "selcount"; // VSR : instead of QtxPopupSelection::defSelCountParam()
 
   myRules.clear();
-  QString OB = "'ObjectBrowser'",
-          View = "'" + SVTK_Viewer::Type() + "'",
-          pat = "'%1'",
-          mesh    = pat.arg( SMESHGUI_Selection::typeName( SMESH::MESH ) ),
-          group   = pat.arg( SMESHGUI_Selection::typeName( SMESH::GROUP ) ),
-          hypo    = pat.arg( SMESHGUI_Selection::typeName( SMESH::HYPOTHESIS ) ),
-          algo    = pat.arg( SMESHGUI_Selection::typeName( SMESH::ALGORITHM ) ),
-          elems   = QString( "'%1' '%2' '%3' '%4' '%5' '%6'" ).
-                       arg( SMESHGUI_Selection::typeName( SMESH::SUBMESH_VERTEX ) ).
-                       arg( SMESHGUI_Selection::typeName( SMESH::SUBMESH_EDGE ) ).
-                       arg( SMESHGUI_Selection::typeName( SMESH::SUBMESH_FACE ) ).
-                       arg( SMESHGUI_Selection::typeName( SMESH::SUBMESH_SOLID ) ).
-                       arg( SMESHGUI_Selection::typeName( SMESH::SUBMESH_COMPOUND ) ).
-                       arg( SMESHGUI_Selection::typeName( SMESH::SUBMESH ) ),
-          subMesh = elems,
-          mesh_part = mesh + " " + subMesh + " " + group,
-          mesh_group = mesh + " " + group,
-          hyp_alg = hypo + " " + algo;
+  QString
+    OB      = "'ObjectBrowser'",
+    View    = "'" + SVTK_Viewer::Type() + "'",
+    pat     = "'%1'",
+    mesh    = pat.arg( SMESHGUI_Selection::typeName( SMESH::MESH ) ),
+    group   = pat.arg( SMESHGUI_Selection::typeName( SMESH::GROUP ) ),
+    hypo    = pat.arg( SMESHGUI_Selection::typeName( SMESH::HYPOTHESIS ) ),
+    algo    = pat.arg( SMESHGUI_Selection::typeName( SMESH::ALGORITHM ) ),
+    elems   = QString( "'%1' '%2' '%3' '%4' '%5' '%6'" ).
+    arg( SMESHGUI_Selection::typeName( SMESH::SUBMESH_VERTEX ) ).
+    arg( SMESHGUI_Selection::typeName( SMESH::SUBMESH_EDGE ) ).
+    arg( SMESHGUI_Selection::typeName( SMESH::SUBMESH_FACE ) ).
+    arg( SMESHGUI_Selection::typeName( SMESH::SUBMESH_SOLID ) ).
+    arg( SMESHGUI_Selection::typeName( SMESH::SUBMESH_COMPOUND ) ).
+    arg( SMESHGUI_Selection::typeName( SMESH::SUBMESH ) ),
+    subMesh      = elems,
+    mesh_part    = mesh + " " + subMesh + " " + group,
+    mesh_group   = mesh + " " + group,
+    mesh_submesh = mesh + " " + subMesh,
+    hyp_alg      = hypo + " " + algo;
 
   // popup for object browser
   QString
@@ -4339,36 +4350,36 @@ void SMESHGUI::initialize( CAM_Application* app )
     hasVolumes("({'Volume'} in elemTypes)"),
     hasFacesOrVolumes("(({'Face'} in elemTypes) || ({'Volume'} in elemTypes)) ");
 
-  createPopupItem( SMESHOp::OpFileInformation,      OB, mesh, "&& selcount=1 && isImported" );
-  createPopupItem( SMESHOp::OpCreateSubMesh,        OB, mesh, "&& hasGeomReference");
-  createPopupItem( SMESHOp::OpEditMeshOrSubMesh,    OB, mesh );
-  createPopupItem( SMESHOp::OpEditMeshOrSubMesh,    OB, subMesh, "&& hasGeomReference" );
-  createPopupItem( SMESHOp::OpEditGroup,            OB, group );
+  createPopupItem( SMESHOp::OpFileInformation,   OB, mesh, "&& selcount=1 && isImported" );
+  createPopupItem( SMESHOp::OpCreateSubMesh,     OB, mesh, "&& hasGeomReference");
+  createPopupItem( SMESHOp::OpEditMesh,          OB, mesh, "&& selcount=1" );
+  createPopupItem( SMESHOp::OpEditSubMesh,       OB, subMesh, "&& selcount=1 && hasGeomReference" );
+  createPopupItem( SMESHOp::OpEditGroup,         OB, group );
   createPopupItem( SMESHOp::OpEditGeomGroupAsGroup, OB, group, "&& groupType != 'Group'" );
 
   popupMgr()->insert( separator(), -1, 0 );
-  createPopupItem( SMESHOp::OpCompute,                OB, mesh, "&& isComputable" );
-  createPopupItem( SMESHOp::OpPreCompute,             OB, mesh, "&& isPreComputable" );
-  createPopupItem( SMESHOp::OpEvaluate,               OB, mesh, "&& isComputable" );
-  createPopupItem( SMESHOp::OpMeshOrder,              OB, mesh, "&& isComputable && hasGeomReference" );
-  createPopupItem( SMESHOp::OpUpdate,                 OB, mesh_part );
-  createPopupItem( SMESHOp::OpMeshInformation,        OB, mesh_part );
-  createPopupItem( SMESHOp::OpFindElementByPoint,     OB, mesh_group );
-  createPopupItem( SMESHOp::OpOverallMeshQuality,     OB, mesh_part );
+  createPopupItem( SMESHOp::OpCompute,           OB, mesh, "&& selcount=1 && isComputable" );
+  createPopupItem( SMESHOp::OpComputeSubMesh,    OB, subMesh, "&& selcount=1 && isComputable" );
+  createPopupItem( SMESHOp::OpPreCompute,        OB, mesh, "&& selcount=1 && isPreComputable" );
+  createPopupItem( SMESHOp::OpEvaluate,          OB, mesh, "&& selcount=1 && isComputable" );
+  createPopupItem( SMESHOp::OpMeshOrder,         OB, mesh, "&& selcount=1 && isComputable && hasGeomReference" );
+  createPopupItem( SMESHOp::OpUpdate,            OB, mesh_part );
+  createPopupItem( SMESHOp::OpMeshInformation,   OB, mesh_part );
+  createPopupItem( SMESHOp::OpFindElementByPoint,OB, mesh_group, "&& selcount=1" );
+  createPopupItem( SMESHOp::OpOverallMeshQuality,OB, mesh_part );
   popupMgr()->insert( separator(), -1, 0 );
-  createPopupItem( SMESHOp::OpCreateGroup,            OB, mesh );
-  createPopupItem( SMESHOp::OpCreateGeometryGroup,    OB, mesh, "&& hasGeomReference" );
-  createPopupItem( SMESHOp::OpConstructGroup,         OB, subMesh );
+  createPopupItem( SMESHOp::OpCreateGroup,       OB, mesh, "&& selcount=1" );
+  createPopupItem( SMESHOp::OpCreateGeometryGroup, OB, mesh, "&& selcount=1 && hasGeomReference" );
+  createPopupItem( SMESHOp::OpConstructGroup,    OB, subMesh );
   popupMgr()->insert( separator(), -1, 0 );
-  createPopupItem( SMESHOp::OpEditHypothesis,         OB, hypo, "&& isEditableHyp");
-  createPopupItem( SMESHOp::OpUnassign,               OB, hyp_alg );     // REMOVE HYPOTHESIS / ALGORITHMS
+  createPopupItem( SMESHOp::OpEditHypothesis,    OB, hypo, "&& isEditableHyp");
+  createPopupItem( SMESHOp::OpUnassign,          OB, hyp_alg );
   popupMgr()->insert( separator(), -1, 0 );
-  createPopupItem( SMESHOp::OpConvertMeshToQuadratic, OB, mesh + " " + subMesh );  // convert to quadratic
-  createPopupItem( SMESHOp::OpCreateBoundaryElements, OB, mesh + " " + group,      // create 2D mesh from 3D
-                   "&& dim>=2");
+  createPopupItem( SMESHOp::OpConvertMeshToQuadratic, OB, mesh_submesh );
+  createPopupItem( SMESHOp::OpCreateBoundaryElements, OB, mesh_group, "&& selcount=1 && dim>=2");
   popupMgr()->insert( separator(), -1, 0 );
   createPopupItem( SMESHOp::OpClearMesh,              OB, mesh );
-  popupMgr()->insert( separator(), -1, 0 );
+  //popupMgr()->insert( separator(), -1, 0 );
 
   QString only_one_non_empty = QString( " && %1=1 && numberOfNodes>0" ).arg( dc );
   QString multiple_non_empty = QString( " && %1>0 && numberOfNodes>0" ).arg( dc );
@@ -5489,9 +5500,12 @@ LightApp_Operation* SMESHGUI::createOperation( const int id ) const
       op = new SMESHGUI_MeshOp( true, false );
     break;
     case SMESHOp::OpEditMeshOrSubMesh:
+    case SMESHOp::OpEditMesh:
+    case SMESHOp::OpEditSubMesh:
       op = new SMESHGUI_MeshOp( false );
     break;
     case SMESHOp::OpCompute:
+    case SMESHOp::OpComputeSubMesh:
       op = new SMESHGUI_ComputeOp();
     break;
     case SMESHOp::OpPreCompute:
@@ -6219,8 +6233,7 @@ void SMESHGUI::restoreVisualParameters (int savePoint)
               if (ac->IsA("SMESH_Actor")) {
                 SMESH_Actor* aGeomAc = SMESH_Actor::SafeDownCast(ac);
                 if (aGeomAc->hasIO()) {
-                  Handle(SALOME_InteractiveObject) io =
-                    Handle(SALOME_InteractiveObject)::DownCast(aGeomAc->getIO());
+                  Handle(SALOME_InteractiveObject) io = aGeomAc->getIO();
                   if (io->hasEntry() && strcmp(io->getEntry(), entry.toLatin1().data()) == 0) {
                     isFound = true;
                     vtkActors.Bind(viewIndex, aGeomAc);
index 8627f72fcd7d0f0604cc2ee5569bf299f8e2795b..072b481752a647c102876e2dcfde1d6e226e7315 100644 (file)
@@ -683,6 +683,7 @@ void SMESHGUI_BaseComputeOp::startOperation()
 
   myMesh      = SMESH::SMESH_Mesh::_nil();
   myMainShape = GEOM::GEOM_Object::_nil();
+  myCurShape  = GEOM::GEOM_Object::_nil();
 
   // check selection
   LightApp_SelectionMgr *Sel = selectionMgr();
@@ -698,7 +699,23 @@ void SMESHGUI_BaseComputeOp::startOperation()
   }
 
   myIObject = selected.First();
-  myMesh = SMESH::GetMeshByIO(myIObject);
+  CORBA::Object_var anObj = SMESH::IObjectToObject( myIObject );
+
+  myMesh = SMESH::SMESH_Mesh::_narrow(anObj);
+  if ( myMesh->_is_nil() )
+  {
+    SMESH::SMESH_subMesh_var aSubMesh = SMESH::SMESH_subMesh::_narrow(anObj);
+    if ( !aSubMesh->_is_nil() )
+    {
+      myMesh      = aSubMesh->GetFather();
+      myCurShape  = aSubMesh->GetSubShape();
+    }
+  }
+  else
+  {
+    myCurShape = myMesh->GetShapeToMesh();
+  }
+
   if (myMesh->_is_nil()) {
     SUIT_MessageBox::warning(desktop(),
                              tr("SMESH_WRN_WARNING"),
@@ -706,6 +723,7 @@ void SMESHGUI_BaseComputeOp::startOperation()
     onCancel();
     return;
   }
+
   myMainShape = myMesh->GetShapeToMesh();
 
   SMESHGUI_Operation::startOperation();
@@ -882,10 +900,8 @@ void SMESHGUI_BaseComputeOp::computeMesh()
       myMesh->Clear();
     SUIT_OverrideCursor aWaitCursor;
     try {
-#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
       OCC_CATCH_SIGNALS;
-#endif
-      SMESHGUI_ComputeDlg_QThreadQDialog qthreaddialog(desktop(), gen, myMesh, myMainShape);
+      SMESHGUI_ComputeDlg_QThreadQDialog qthreaddialog(desktop(), gen, myMesh, myCurShape);
       qthreaddialog.exec();
       computeFailed = !qthreaddialog.result();
     }
@@ -893,9 +909,7 @@ void SMESHGUI_BaseComputeOp::computeMesh()
       memoryLack = true;
     }
     try {
-#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
       OCC_CATCH_SIGNALS;
-#endif
       aCompErrors = gen->GetComputeErrors( myMesh, myMainShape );
       // check if there are memory problems
       for ( CORBA::ULong i = 0; (i < aCompErrors->length()) && !memoryLack; ++i )
@@ -911,7 +925,8 @@ void SMESHGUI_BaseComputeOp::computeMesh()
 
     // NPAL16631: if ( !memoryLack )
     {
-      SMESH::ModifiedMesh( aMeshSObj,
+      _PTR(SObject) sobj = SMESH::GetActiveStudyDocument()->FindObjectID(myIObject->getEntry());
+      SMESH::ModifiedMesh( sobj,
                            !computeFailed && aHypErrors.isEmpty(),
                            myMesh->NbNodes() == 0);
       update( UF_ObjBrowser | UF_Model );
@@ -1245,8 +1260,9 @@ void SMESHGUI_BaseComputeOp::stopOperation()
 
 void SMESHGUI_BaseComputeOp::onPublishShape()
 {
-  GEOM::GEOM_Gen_var geomGen = SMESH::GetGEOMGen();
-  SALOMEDS::Study_var study = SMESHGUI::GetSMESHGen()->GetCurrentStudy();
+  GEOM::GEOM_Gen_var      geomGen = SMESH::GetGEOMGen();
+  SALOMEDS::Study_var       study = SMESHGUI::GetSMESHGen()->GetCurrentStudy();
+  GEOM::GEOM_Object_var meshShape = myMesh->GetShapeToMesh();
 
   QStringList entryList;
   QList<int> rows;
@@ -1754,14 +1770,15 @@ void SMESHGUI_PrecomputeOp::initDialog()
  */
 //================================================================================
 
-void SMESHGUI_PrecomputeOp::getAssignedAlgos(_PTR(SObject) theMesh,
+void SMESHGUI_PrecomputeOp::getAssignedAlgos(_PTR(SObject)  theMesh,
                                              QMap<int,int>& theModeMap)
 {
   if ( !theMesh ) return;
+
   _PTR(SObject)          aHypFolder;
   _PTR(GenericAttribute) anAttr;
   int aPart = SMESH::Tag_RefOnAppliedAlgorithms;
-  if ( theMesh->FindSubObject( aPart, aHypFolder ) )
+  if ( theMesh->FindSubObject( aPart, aHypFolder ))
   {
     _PTR(ChildIterator) anIter =
       SMESH::GetActiveStudyDocument()->NewChildIterator( aHypFolder );
index 759648dade0ef2e9c510f8c60c90c5f43129fa41..afd451c7427eddc06e1677ee3b1e8e6b87917741 100644 (file)
@@ -112,6 +112,7 @@ private:
 protected:
   SMESH::SMESH_Mesh_var            myMesh;
   GEOM::GEOM_Object_var            myMainShape;
+  GEOM::GEOM_Object_var            myCurShape;
   SMESH::TShapeDisplayer*          myTShapeDisplayer;
   SMESHGUI_MeshEditPreview*        myBadMeshDisplayer;
   Handle(SALOME_InteractiveObject) myIObject;
index af09f482c79952659ca2dc63c5b50bea2aad1497..205544cfa0993ba688f3dfd69a386640774a7525 100644 (file)
 #include "SMESHGUI_ExtrusionDlg.h"
 
 #include "SMESHGUI.h"
-#include "SMESHGUI_Utils.h"
-#include "SMESHGUI_VTKUtils.h"
-#include "SMESHGUI_MeshUtils.h"
-#include "SMESHGUI_SpinBox.h"
-#include "SMESHGUI_IdValidator.h"
 #include "SMESHGUI_FilterDlg.h"
+#include "SMESHGUI_IdValidator.h"
 #include "SMESHGUI_MeshEditPreview.h"
-
+#include "SMESHGUI_MeshUtils.h"
+#include "SMESHGUI_SpinBox.h"
+#include "SMESHGUI_Utils.h"
+#include "SMESHGUI_VTKUtils.h"
+#include <GEOMBase.h>
+#include <SMDS_Mesh.hxx>
 #include <SMESH_Actor.h>
-#include <SMESH_TypeFilter.hxx>
 #include <SMESH_LogicalFilter.hxx>
-
-#include <SMDS_Mesh.hxx>
+#include <SMESH_TypeFilter.hxx>
 
 // SALOME GUI includes
-#include <SUIT_ResourceMgr.h>
+#include <LightApp_Application.h>
+#include <LightApp_SelectionMgr.h>
 #include <SUIT_Desktop.h>
 #include <SUIT_MessageBox.h>
-#include <SUIT_Session.h>
 #include <SUIT_OverrideCursor.h>
-
-#include <LightApp_Application.h>
-#include <LightApp_SelectionMgr.h>
-
+#include <SUIT_ResourceMgr.h>
+#include <SUIT_Session.h>
 #include <SVTK_ViewModel.h>
 #include <SVTK_ViewWindow.h>
-
 #include <SalomeApp_IntSpinBox.h>
 
 // OCCT includes
-#include <TColStd_MapOfInteger.hxx>
+#include <BRep_Tool.hxx>
 #include <TColStd_IndexedMapOfInteger.hxx>
+#include <TColStd_MapOfInteger.hxx>
+#include <TopoDS_Vertex.hxx>
 #include <gp_XYZ.hxx>
 
 // Qt includes
 #include <QApplication>
 #include <QButtonGroup>
+#include <QCheckBox>
+#include <QGridLayout>
 #include <QGroupBox>
+#include <QHBoxLayout>
+#include <QKeyEvent>
 #include <QLabel>
 #include <QLineEdit>
+#include <QListWidget>
 #include <QPushButton>
 #include <QRadioButton>
-#include <QCheckBox>
-#include <QHBoxLayout>
+#include <QToolButton>
 #include <QVBoxLayout>
-#include <QGridLayout>
-#include <QKeyEvent>
 
 // IDL includes
 #include <SALOMEconfig.h>
 #include CORBA_SERVER_HEADER(SMESH_Group)
 #include CORBA_SERVER_HEADER(SMESH_MeshEditor)
+#include <SMESH_NumberFilter.hxx>
 
 #define SPACING 6
 #define MARGIN  11
@@ -595,7 +596,10 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule)
   : SMESHGUI_PreviewDlg( theModule ),
     mySelectionMgr( SMESH::GetSelectionMgr( theModule ) )
 {
-  QPixmap image (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", tr("ICON_SELECT")));
+  SUIT_ResourceMgr* mgr = SMESH::GetResourceMgr( mySMESHGUI );
+  QPixmap selectImage ( mgr->loadPixmap("SMESH", tr("ICON_SELECT")));
+  QPixmap addImage    ( mgr->loadPixmap("SMESH", tr("ICON_APPEND")));
+  QPixmap removeImage ( mgr->loadPixmap("SMESH", tr("ICON_REMOVE")));
 
   setModal( false );
   setAttribute( Qt::WA_DeleteOnClose, true );
@@ -638,8 +642,8 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule)
 
   TextLabelVector = new QLabel(tr("SMESH_VECTOR"), GroupArguments);
 
-  SelectVectorButton = new QPushButton(GroupArguments);
-  SelectVectorButton->setIcon(image);
+  SelectVectorButton = new QPushButton( GroupArguments );
+  SelectVectorButton->setIcon( selectImage );
   SelectVectorButton->setCheckable( true );
   SelectorWdg->GetButtonGroup()->addButton( SelectVectorButton );
 
@@ -671,6 +675,66 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule)
   //Preview check box
   myPreviewCheckBox = new QCheckBox(tr("PREVIEW"), GroupArguments);
 
+  // Base point
+
+  BasePointGrp = new QGroupBox(tr("BASE_POINT"), GroupArguments);
+  BasePointGrp->setCheckable(true);
+  BasePointGrp->setChecked(false);
+  QHBoxLayout* BasePointGrpLayout = new QHBoxLayout(BasePointGrp);
+  BasePointGrpLayout->setSpacing(SPACING); BasePointGrpLayout->setMargin(MARGIN);
+
+  SelectBasePointButton = new QPushButton(BasePointGrp);
+  SelectBasePointButton->setIcon(selectImage);
+  SelectBasePointButton->setCheckable(true);
+  SelectorWdg->GetButtonGroup()->addButton( SelectBasePointButton );
+
+  QLabel* XLab  = new QLabel(tr("SMESH_X"), BasePointGrp);
+  BasePoint_XSpin = new SMESHGUI_SpinBox(BasePointGrp);
+  BasePoint_XSpin->SetValue(0.);
+  QLabel* YLab  = new QLabel(tr("SMESH_Y"), BasePointGrp);
+  BasePoint_YSpin = new SMESHGUI_SpinBox(BasePointGrp);
+  BasePoint_YSpin->SetValue(0.);
+  QLabel* ZLab  = new QLabel(tr("SMESH_Z"), BasePointGrp);
+  BasePoint_ZSpin = new SMESHGUI_SpinBox(BasePointGrp);
+  BasePoint_ZSpin->SetValue(0.);
+
+  BasePointGrpLayout->addWidget(SelectBasePointButton);
+  BasePointGrpLayout->addWidget(XLab);
+  BasePointGrpLayout->addWidget(BasePoint_XSpin, 1);
+  BasePointGrpLayout->addWidget(YLab);
+  BasePointGrpLayout->addWidget(BasePoint_YSpin, 1);
+  BasePointGrpLayout->addWidget(ZLab);
+  BasePointGrpLayout->addWidget(BasePoint_ZSpin, 1);
+
+  // Scales
+
+  ScalesGrp = new QGroupBox(tr("SMESH_SCALES"), GroupArguments);
+  QGridLayout* ScalesGrpLayout = new QGridLayout( ScalesGrp );
+  ScalesGrpLayout->setSpacing(SPACING); ScalesGrpLayout->setMargin(MARGIN);
+
+  ScalesList = new QListWidget( ScalesGrp );
+  ScalesList->setSelectionMode(QListWidget::ExtendedSelection);
+
+  AddScaleButton = new QToolButton( ScalesGrp );
+  AddScaleButton->setIcon( addImage );
+
+  RemoveScaleButton = new QToolButton( ScalesGrp );
+  RemoveScaleButton->setIcon( removeImage );
+
+  ScaleSpin = new SMESHGUI_SpinBox( ScalesGrp );
+  ScaleSpin->SetValue(2);
+
+  LinearScalesCheck = new QCheckBox(tr("LINEAR_SCALES"), ScalesGrp );
+
+  ScalesGrpLayout->addWidget(ScalesList,        0, 0, 4, 1);
+  ScalesGrpLayout->addWidget(AddScaleButton,    0, 1);
+  ScalesGrpLayout->addWidget(RemoveScaleButton, 2, 1);
+  ScalesGrpLayout->addWidget(ScaleSpin,         0, 2);
+  ScalesGrpLayout->addWidget(LinearScalesCheck, 4, 0);
+  ScalesGrpLayout->setRowMinimumHeight(1, 10);
+  ScalesGrpLayout->setRowStretch(3, 10);
+
+  // layouting
   GroupArgumentsLayout->addWidget(SelectorWdg,            0, 0, 1, 9);
   GroupArgumentsLayout->addWidget(ExtrMethod_RBut0,       1, 0, 1, 3);
   GroupArgumentsLayout->addWidget(ExtrMethod_RBut1,       1, 3, 1, 3);
@@ -696,8 +760,10 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule)
   GroupArgumentsLayout->addWidget(SpinBox_NbSteps,        5, 3);
   GroupArgumentsLayout->addWidget(ByAverageNormalCheck,   6, 0, 1, 4);
   GroupArgumentsLayout->addWidget(UseInputElemsOnlyCheck, 6, 4, 1, 4);
-  GroupArgumentsLayout->addWidget(myPreviewCheckBox,      7, 0, 1, 8);
-  GroupArgumentsLayout->addWidget(MakeGroupsCheck,        8, 0, 1, 8);
+  GroupArgumentsLayout->addWidget(BasePointGrp,           7, 0, 1, 9);
+  GroupArgumentsLayout->addWidget(ScalesGrp,              8, 0, 1, 9);
+  GroupArgumentsLayout->addWidget(myPreviewCheckBox,      9, 0, 1, 8);
+  GroupArgumentsLayout->addWidget(MakeGroupsCheck,        10,0, 1, 8);
   GroupArgumentsLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding), 10, 0);
 
   /***************************************************************/
@@ -740,6 +806,11 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule)
   SpinBox_NbSteps->setRange(1, 999999);
   SpinBox_VDist->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
 
+  BasePoint_XSpin->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
+  BasePoint_YSpin->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
+  BasePoint_ZSpin->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
+  ScaleSpin->RangeStepAndValidator      (COORD_MIN, COORD_MAX, 1.0, "length_precision");
+
   ExtrMethod_RBut0->setChecked(true);
   UseInputElemsOnlyCheck->setChecked(true);
   MakeGroupsCheck->setChecked(true);
@@ -771,7 +842,13 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule)
   connect(SpinBox_Dy, SIGNAL(valueChanged(double)), SLOT(CheckIsEnable()));
   connect(SpinBox_Dz, SIGNAL(valueChanged(double)), SLOT(CheckIsEnable()));
 
+  connect(AddScaleButton,    SIGNAL(clicked()), this, SLOT(OnScaleAdded()));
+  connect(RemoveScaleButton, SIGNAL(clicked()), this, SLOT(OnScaleRemoved()));
+
   connect(SelectVectorButton,   SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
+  connect(SelectBasePointButton,SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
+  connect(BasePointGrp,         SIGNAL(toggled(bool)), this, SLOT(SetEditCurrentArgument()));
+  connect(BasePointGrp,         SIGNAL(toggled(bool)), SelectBasePointButton, SLOT(click()));
   connect(mySMESHGUI,           SIGNAL(SignalDeactivateActiveDialog()), SLOT(DeactivateActiveDialog()));
   connect(mySelectionMgr,       SIGNAL(currentSelectionChanged()), SLOT(toDisplaySimulation()));
   connect(SelectorWdg,          SIGNAL(selectionChanged()), this, SLOT(toDisplaySimulation()));
@@ -791,6 +868,13 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule)
   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()));
+  connect(AddScaleButton,         SIGNAL(clicked()),     this, SLOT(toDisplaySimulation()));
+  connect(RemoveScaleButton,      SIGNAL(clicked()),     this, SLOT(toDisplaySimulation()));
+  connect(LinearScalesCheck,      SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation()));
+  connect(BasePointGrp,           SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation()));
+  connect(BasePoint_XSpin, SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
+  connect(BasePoint_YSpin, SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
+  connect(BasePoint_ZSpin, SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
 
   //To Connect preview check box
   connectPreviewControl();
@@ -875,6 +959,31 @@ bool SMESHGUI_ExtrusionDlg::isValuesValid()
   return aModule > 1.0E-38;
 }
 
+//=======================================================================
+//function : getScaleParams
+//purpose  : return 3 scaling parameters
+//=======================================================================
+
+bool SMESHGUI_ExtrusionDlg::getScaleParams( SMESH::double_array*& scales,
+                                            SMESH::double_array*& basePoint )
+{
+  scales = new SMESH::double_array;
+  scales->length( myScalesList.count() );
+  for ( int i = 0; i < myScalesList.count(); ++i )
+    (*scales)[i] = myScalesList[i];
+
+  basePoint = new SMESH::double_array;
+  if ( BasePointGrp->isChecked() )
+  {
+    basePoint->length( 3 );
+    (*basePoint)[0] = BasePoint_XSpin->GetValue();
+    (*basePoint)[1] = BasePoint_YSpin->GetValue();
+    (*basePoint)[2] = BasePoint_ZSpin->GetValue();
+  }
+
+  return ( scales->length() > 0 && LinearScalesCheck->isChecked() );
+}
+
 //=================================================================================
 // function : ClickOnRadio()
 // purpose  : Radio button management
@@ -963,6 +1072,10 @@ void SMESHGUI_ExtrusionDlg::ClickOnRadio()
     SelectorWdg->SetEnabled( false, SMESH::EDGE );
   }
 
+  BasePointGrp->setEnabled( !ExtrMethod_RBut2->isChecked() );
+  ScalesGrp   ->setEnabled( !ExtrMethod_RBut2->isChecked() );
+
+
   CheckIsEnable();
 
   onDisplaySimulation(true);
@@ -989,7 +1102,7 @@ bool SMESHGUI_ExtrusionDlg::ClickOnApply()
   {
     SMESH::DirStruct aVector;
     getExtrusionVector(aVector);
-    
+
     QStringList aParameters;
     if ( ExtrMethod_RBut0->isChecked() )
     {
@@ -1011,14 +1124,22 @@ bool SMESHGUI_ExtrusionDlg::ClickOnApply()
     }
 
     long aNbSteps = (long)SpinBox_NbSteps->value();
-
     aParameters << SpinBox_NbSteps->text();
 
+    SMESH::double_array_var scales = new SMESH::double_array;
+    scales->length( myScalesList.count() );
+    for (int i = 0; i < myScalesList.count(); i++)
+    {
+      scales[i] = myScalesList[i];
+      aParameters << ScalesList->item(i)->text();
+    }
+
     bool meshHadNewTypeBefore = true;
     int  maxSelType = 0;
     const bool makeGroups = ( MakeGroupsCheck->isEnabled() && MakeGroupsCheck->isChecked() );
 
-    try {
+    try
+    {
       SUIT_OverrideCursor aWaitCursor;
 
       SMESH::SMESH_Mesh_var mesh = SelectorWdg->GetMesh();
@@ -1054,8 +1175,12 @@ bool SMESHGUI_ExtrusionDlg::ClickOnApply()
       }
       else
       {
+        SMESH::double_array_var scales, basePoint;
+        bool linVariation = getScaleParams( scales.out(), basePoint.out() );
         groups = meshEditor->ExtrusionSweepObjects( nodes, edges, faces,
-                                                    aVector, aNbSteps, makeGroups );
+                                                    aVector, aNbSteps,
+                                                    scales, linVariation, basePoint,
+                                                    makeGroups );
       }
 
     } catch (...) {
@@ -1180,13 +1305,13 @@ void SMESHGUI_ExtrusionDlg::SelectionIntoArgument()
   if (!GroupButtons->isEnabled())
     return;
 
+  SALOME_ListIO aList;
+  mySelectionMgr->selectedObjects(aList);
+  if ( aList.IsEmpty() || aList.Extent() > 1 )
+    return;
+
   if ( SelectVectorButton->isChecked() )
   {
-    SALOME_ListIO aList;
-    mySelectionMgr->selectedObjects(aList);
-    if ( aList.IsEmpty() || aList.Extent() > 1 )
-      return;
-
     Handle(SALOME_InteractiveObject) IO = aList.First();
     TColStd_IndexedMapOfInteger aMapIndex;
     mySelector->GetIndex(IO,aMapIndex);
@@ -1207,6 +1332,56 @@ void SMESHGUI_ExtrusionDlg::SelectionIntoArgument()
     SpinBox_Vy->SetValue(aNormale.Y());
     SpinBox_Vz->SetValue(aNormale.Z());
   }
+  else if ( SelectBasePointButton->isChecked() )
+  {
+    if (!BasePointGrp->isChecked())
+      return;
+
+    // try to get shape from selection
+    Handle(SALOME_InteractiveObject) IO = aList.First();
+
+    // check if geom vertex is selected
+    GEOM::GEOM_Object_var aGeomObj = SMESH::IObjectToInterface<GEOM::GEOM_Object>(IO);
+    TopoDS_Vertex aVertex;
+    if (!aGeomObj->_is_nil()) {
+      if (aGeomObj->IsShape() && GEOMBase::GetShape(aGeomObj, aVertex) && !aVertex.IsNull()) {
+        gp_Pnt aPnt = BRep_Tool::Pnt(aVertex);
+        BasePoint_XSpin->SetValue(aPnt.X());
+        BasePoint_YSpin->SetValue(aPnt.Y());
+        BasePoint_ZSpin->SetValue(aPnt.Z());
+      }
+    }
+
+    if ( aVertex.IsNull() )
+    {
+      // check if smesh node is selected
+      SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(IO);
+      if (aMesh->_is_nil())
+        return;
+
+      QString aString;
+      int aNbUnits = SMESH::GetNameOfSelectedNodes(mySelector, IO, aString);
+      // return if more than one node is selected
+      if (aNbUnits != 1)
+        return;
+
+      SMESH_Actor* aMeshActor = SMESH::FindActorByObject(aMesh);
+      if (!aMeshActor)
+        return;
+
+      SMDS_Mesh* mesh = aMeshActor->GetObject()->GetMesh();
+      if (!mesh)
+        return;
+
+      const SMDS_MeshNode* n = mesh->FindNode(aString.toLong());
+      if (!n)
+        return;
+
+      BasePoint_XSpin->SetValue(n->X());
+      BasePoint_YSpin->SetValue(n->Y());
+      BasePoint_ZSpin->SetValue(n->Z());
+    }
+  }
 
   onDisplaySimulation(true);
   CheckIsEnable();
@@ -1229,6 +1404,21 @@ void SMESHGUI_ExtrusionDlg::SetEditCurrentArgument()
     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
       aViewWindow->SetSelectionMode(FaceSelection);
   }
+  else if ( send == SelectBasePointButton )
+  {
+    SMESH::SetPointRepresentation(true);
+    if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+      aViewWindow->SetSelectionMode(NodeSelection);
+
+    SMESH_TypeFilter* aMeshOrSubMeshFilter = new SMESH_TypeFilter(SMESH::IDSOURCE);
+    SMESH_NumberFilter* aVertexFilter      = new SMESH_NumberFilter ("GEOM", TopAbs_VERTEX,
+                                                                     1, TopAbs_VERTEX);
+    QList<SUIT_SelectionFilter*> aListOfFilters;
+    aListOfFilters << aMeshOrSubMeshFilter << aVertexFilter;
+
+    mySelectionMgr->installFilter(new SMESH_LogicalFilter
+                                  (aListOfFilters, SMESH_LogicalFilter::LO_OR, true));
+  }
   
   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
   SelectionIntoArgument();
@@ -1316,6 +1506,12 @@ bool SMESHGUI_ExtrusionDlg::isValid()
   }
   ok = SpinBox_NbSteps->isValid( msg, true ) && ok;
 
+  if ( BasePointGrp->isChecked()) {
+    ok = BasePoint_XSpin->isValid( msg, true ) && ok;
+    ok = BasePoint_YSpin->isValid( msg, true ) && ok;
+    ok = BasePoint_ZSpin->isValid( msg, true ) && ok;
+  }
+
   if( !ok ) {
     QString str( tr( "SMESH_INCORRECT_INPUT" ) );
     if ( !msg.isEmpty() )
@@ -1369,8 +1565,12 @@ void SMESHGUI_ExtrusionDlg::onDisplaySimulation( bool toDisplayPreview )
         }
         else
         {
+          SMESH::double_array_var scales, basePoint;
+          bool linVariation = getScaleParams( scales.out(), basePoint.out() );
           groups = meshEditor->ExtrusionSweepObjects( nodes, edges, faces,
-                                                      aVector, aNbSteps, makeGroups );
+                                                      aVector, aNbSteps,
+                                                      scales, linVariation, basePoint,
+                                                      makeGroups );
         }
         SMESH::MeshPreviewStruct_var aMeshPreviewStruct = meshEditor->GetPreviewData();
         mySimulation->SetData(aMeshPreviewStruct._retn());
@@ -1411,3 +1611,38 @@ void SMESHGUI_ExtrusionDlg::getExtrusionVector(SMESH::DirStruct& aVector)
     aVector.PS.z = aNormale.Z()*aVDist;
   }
 }
+
+//=======================================================================
+// function : OnScaleAdded()
+// purpose  : Called when user adds Scale to the list
+//=======================================================================
+void SMESHGUI_ExtrusionDlg::OnScaleAdded()
+{
+  QString msg;
+  if( !ScaleSpin->isValid( msg, true ) ) {
+    QString str( tr( "SMESH_INCORRECT_INPUT" ) );
+    if ( !msg.isEmpty() )
+      str += "\n" + msg;
+    SUIT_MessageBox::critical( this, tr( "SMESH_ERROR" ), str );
+    return;
+  }
+  ScalesList->addItem(ScaleSpin->text());
+  myScalesList.append(ScaleSpin->GetValue());
+}
+
+//=======================================================================
+// function : OnScaleRemoved()
+// purpose  : Called when user removes Scale(s) from the list
+//=======================================================================
+void SMESHGUI_ExtrusionDlg::OnScaleRemoved()
+{
+  QList<QListWidgetItem*> aList = ScalesList->selectedItems();
+  QListWidgetItem* anItem;
+  int row = 0;
+  foreach(anItem, aList) {
+    row = ScalesList->row(anItem);
+    myScalesList.removeAt(row);
+    delete anItem;
+  }
+  ScalesList->setCurrentRow( row, QItemSelectionModel::Select );
+}
index ed94f5c84a76a31a33b13f5ba19f99e4991fa5c6..b539eee98b38d95dc562cb97229a5f97421e6cf5 100644 (file)
 #include CORBA_SERVER_HEADER(SMESH_MeshEditor)
 
 class QButtonGroup;
-class QRadioButton;
+class QCheckBox;
 class QGroupBox;
 class QLabel;
 class QLineEdit;
-class QCheckBox;
+class QListWidget;
 class QPushButton;
+class QRadioButton;
+class QToolButton;
 
 class SMESHGUI;
 class SMESH_Actor;
@@ -59,7 +61,7 @@ class SUIT_SelectionFilter;
 class SalomeApp_IntSpinBox;
 
 //=================================================================================
-// class    : SMESHGUI_ExtrusionDlg
+// class    : SMESHGUI_3TypesSelector
 // purpose  : A widget used to select both nodes, edges and faces for
 //            Extrusion and Revolution operations
 //=================================================================================
@@ -143,12 +145,15 @@ private:
   void                             getExtrusionVector(SMESH::DirStruct& aVector);
   void                             extrusionByNormal(SMESH::SMESH_MeshEditor_ptr meshEditor,
                                                      const bool                  makeGroups=false);
+  bool                             getScaleParams( SMESH::double_array*& scales,
+                                                   SMESH::double_array*& basePoint );
   
   bool                             isValid();
   bool                             isValuesValid();
   
   LightApp_SelectionMgr*           mySelectionMgr;        /* User shape selection */
   SVTK_Selector*                   mySelector;
+  QList<double>                    myScalesList;
 
   // widgets
   SMESHGUI_3TypesSelector*         SelectorWdg;
@@ -180,6 +185,19 @@ private:
   QCheckBox*                       UseInputElemsOnlyCheck;
   QCheckBox*                       MakeGroupsCheck;
 
+  QGroupBox*                       BasePointGrp;
+  QPushButton*                     SelectBasePointButton;
+  SMESHGUI_SpinBox*                BasePoint_XSpin;
+  SMESHGUI_SpinBox*                BasePoint_YSpin;
+  SMESHGUI_SpinBox*                BasePoint_ZSpin;
+
+  QGroupBox*                       ScalesGrp;
+  QListWidget*                     ScalesList;
+  QToolButton*                     AddScaleButton;
+  QToolButton*                     RemoveScaleButton;
+  SMESHGUI_SpinBox*                ScaleSpin;
+  QCheckBox*                       LinearScalesCheck;
+
   QGroupBox*                       GroupButtons;
   QPushButton*                     buttonOk;
   QPushButton*                     buttonCancel;
@@ -205,6 +223,8 @@ private slots:
   void                            ActivateThisDialog();
   void                            onOpenView();
   void                            onCloseView();
+  void                            OnScaleAdded();
+  void                            OnScaleRemoved();
 
 };
 
index 0716cdd8e447e91ed682f1073995574f75c40203..ad2adb52012d01396aaaaee9fdae95523baef115 100644 (file)
@@ -624,12 +624,32 @@ SMESHGUI_MeshDlg::SMESHGUI_MeshDlg( const bool theToCreate, const bool theIsMesh
     objectWg( Mesh, Btn )->hide();
     objectWg( Geom, Btn )->hide();
   }
+  setTitile( theToCreate, theIsMesh );
 }
 
 SMESHGUI_MeshDlg::~SMESHGUI_MeshDlg()
 {
 }
 
+//================================================================================
+/*!
+ * \brief Set dialog title
+ */
+//================================================================================
+
+void SMESHGUI_MeshDlg::setTitile( const bool theToCreate, const bool theIsMesh )
+{
+  if ( theToCreate )
+  {
+    setWindowTitle( tr( theIsMesh ? "CREATE_MESH" : "CREATE_SUBMESH" ));
+  }
+  else
+  {
+    setWindowTitle( tr( theIsMesh ? "EDIT_MESH" : "EDIT_SUBMESH") );
+  }
+  
+}
+
 //================================================================================
 /*!
  * \brief Gets tab with given id
index 37742bbe7eec0d720ed54c2b0d2a6ccd68d70d54..9c0337420bd33907a9eeb3eefea934f9ecd95c23 100644 (file)
@@ -78,6 +78,7 @@ public:
   void                         setAvailableMeshType(const QStringList& );
   int                          currentMeshType();
   void                         setCurrentMeshType( const int );
+  void                         setTitile( const bool, const bool );
 
 signals:
   void                         hypoSet( const QString& );
index 30949d4621ed93a96aa2e8a3351605bd6718d00c..8677fad56262314587bcfdb03340fe6385e46876 100644 (file)
@@ -638,13 +638,14 @@ void SMESHGUI_MeshOp::selectionDone()
         {
           SMESH::SMESH_subMesh_var submeshVar =
             SMESH::SMESH_subMesh::_narrow( _CAST( SObject,pObj )->GetObject() );
+          myIsMesh = submeshVar->_is_nil();
+          myDlg->setTitile( myToCreate, myIsMesh );
           myDlg->setObjectShown( SMESHGUI_MeshDlg::Mesh, !submeshVar->_is_nil() );
           myDlg->setObjectShown( SMESHGUI_MeshDlg::Geom, true );
           myDlg->objectWg( SMESHGUI_MeshDlg::Mesh, SMESHGUI_MeshDlg::Btn )->hide();
           myDlg->objectWg( SMESHGUI_MeshDlg::Geom, SMESHGUI_MeshDlg::Btn )->hide();
           myDlg->updateGeometry();
           myDlg->adjustSize();
-          myIsMesh = submeshVar->_is_nil();
           readMesh();
         }
         else
index 3d6589b0d070f73a591458544eebf6e340aa05c7..784940e90360707b108ff32f29c1df80e45c7789 100644 (file)
@@ -69,12 +69,15 @@ namespace SMESHOp {
     OpCreateMesh             = 2030,   // MENU MESH  - CREATE MESH
     OpCreateSubMesh          = 2031,   // MENU MESH  - CREATE SUBMESH
     OpEditMeshOrSubMesh      = 2032,   // MENU MESH  - EDIT MESH/SUBMESH
-    OpBuildCompoundMesh      = 2033,   // MENU MESH  - BUILD COMPOUND
-    OpCopyMesh               = 2034,   // MENU MESH  - COPY MESH
+    OpEditMesh               = 2033,   // POPUP  - EDIT MESH
+    OpEditSubMesh            = 2034,   // POPUP  - EDIT SUBMESH
+    OpBuildCompoundMesh      = 2035,   // MENU MESH  - BUILD COMPOUND
+    OpCopyMesh               = 2036,   // MENU MESH  - COPY MESH
     OpCompute                = 2040,   // MENU MESH  - COMPUTE
-    OpPreCompute             = 2041,   // MENU MESH  - PREVIEW
-    OpEvaluate               = 2042,   // MENU MESH  - EVALUATE
-    OpMeshOrder              = 2043,   // MENU MESH  - CHANGE SUBMESH PRIORITY
+    OpComputeSubMesh         = 2041,   // POPUP  - COMPUTE SUBMESH
+    OpPreCompute             = 2042,   // MENU MESH  - PREVIEW
+    OpEvaluate               = 2043,   // MENU MESH  - EVALUATE
+    OpMeshOrder              = 2044,   // MENU MESH  - CHANGE SUBMESH PRIORITY
     OpCreateGroup            = 2050,   // MENU MESH  - CREATE GROUP
     OpCreateGeometryGroup    = 2051,   // MENU MESH  - CREATE GROUPS FROM GEOMETRY
     OpConstructGroup         = 2052,   // MENU MESH  - CONSTRUCT GROUP
index ab6bad8120f1049d1bb8eb93fee46b20535b9f23..832c51ec18e0597a7b5d2b600d5bbb7dc338d030 100644 (file)
@@ -518,11 +518,18 @@ int SMESHGUI_Selection::dim( int ind ) const
 
 bool SMESHGUI_Selection::isComputable( int ind ) const
 {
-  if ( ind >= 0 && ind < myTypes.count() && myTypes[ind] == "Mesh" )
+  if ( ind >= 0 && ind < myTypes.count() && ( myTypes[ind] == "Mesh" ||
+                                              myTypes[ind].startsWith("Mesh " )))
   {
     QMap<int,int> modeMap;
-    _PTR(SObject) so = SMESH::GetActiveStudyDocument()->FindObjectID( entry( ind ).toLatin1().data() );
-    SMESHGUI_PrecomputeOp::getAssignedAlgos( so, modeMap );
+    _PTR(SObject) meshSO = SMESH::GetActiveStudyDocument()->FindObjectID( entry( ind ).toLatin1().data() );
+
+    _PTR(SComponent) component = meshSO->GetFatherComponent();
+    if ( meshSO->Depth() - component->Depth() > 1 ) // sub-mesh, get a mesh
+      while ( meshSO->Depth() - component->Depth() > 1 )
+        meshSO = meshSO->GetFather();
+
+    SMESHGUI_PrecomputeOp::getAssignedAlgos( meshSO, modeMap );
     return modeMap.size() > 0;
   }
   return false;
index a235b9cc9dc8cac5118d807d583cb4f9e970029b..f6ab2b98adcde01a533d11f578a4b11b85ee6ae4 100644 (file)
         <source>AREA_ELEMENTS</source>
         <translation>Area</translation>
     </message>
+    <message>
+        <source>FREE_NODES</source>
+        <translation>Free nodes</translation>
+    </message>
+    <message>
+        <source>FREE_EDGES</source>
+        <translation>Free edges</translation>
+    </message>
+    <message>
+        <source>FREE_FACES</source>
+        <translation>Free faces</translation>
+    </message>
+    <message>
+        <source>BARE_BORDER_FACE</source>
+        <translation>Faces with bare border</translation>
+    </message>
+    <message>
+        <source>OVER_CONSTRAINED_FACE</source>
+        <translation>Over-constrained faces</translation>
+    </message>
+    <message>
+        <source>BARE_BORDER_VOLUME</source>
+        <translation>Volumes with bare border</translation>
+    </message>
+    <message>
+        <source>OVER_CONSTRAINED_VOLUME</source>
+        <translation>Over-constrained volumes</translation>
+    </message>
     <message>
         <source>MIN_DIAG_ELEMENTS</source>
         <translation>Minimum diagonal</translation>
         <source>MEN_COMPUTE</source>
         <translation>Compute</translation>
     </message>
+    <message>
+        <source>MEN_COMPUTE_SUBMESH</source>
+        <translation>Compute Sub-mesh</translation>
+    </message>
     <message>
         <source>MEN_PRECOMPUTE</source>
         <translation>Preview</translation>
         <source>MEN_EDIT_MESHSUBMESH</source>
         <translation>Edit Mesh/Sub-mesh</translation>
     </message>
+    <message>
+        <source>MEN_EDIT_MESH</source>
+        <translation>Edit Mesh</translation>
+    </message>
+    <message>
+        <source>MEN_EDIT_SUBMESH</source>
+        <translation>Edit Sub-mesh</translation>
+    </message>
     <message>
         <source>MEN_EXPORT</source>
         <translation>Export</translation>
@@ -2929,6 +2969,10 @@ Use Display Entity menu command to show them.
         <source>STB_COMPUTE</source>
         <translation>Compute</translation>
     </message>
+    <message>
+        <source>STB_COMPUTE_SUBMESH</source>
+        <translation>Compute Sub-mesh</translation>
+    </message>
     <message>
         <source>STB_PRECOMPUTE</source>
         <translation>Preview</translation>
@@ -3061,6 +3105,14 @@ Use Display Entity menu command to show them.
         <source>STB_EDIT_MESHSUBMESH</source>
         <translation>Edit Mesh/Sub-mesh</translation>
     </message>
+    <message>
+        <source>STB_EDIT_MESH</source>
+        <translation>Edit Mesh</translation>
+    </message>
+    <message>
+        <source>STB_EDIT_SUBMESH</source>
+        <translation>Edit Sub-mesh</translation>
+    </message>
     <message>
         <source>STB_EXPORT_DAT</source>
         <translation>Export to DAT file</translation>
@@ -3597,6 +3649,10 @@ Use Display Entity menu command to show them.
         <source>TOP_COMPUTE</source>
         <translation>Compute</translation>
     </message>
+    <message>
+        <source>TOP_COMPUTE_SUBMESH</source>
+        <translation>Compute Sub-mesh</translation>
+    </message>
     <message>
         <source>TOP_PRECOMPUTE</source>
         <translation>Preview</translation>
@@ -3729,6 +3785,14 @@ Use Display Entity menu command to show them.
         <source>TOP_EDIT_MESHSUBMESH</source>
         <translation>Edit Mesh/Sub-mesh</translation>
     </message>
+    <message>
+        <source>TOP_EDIT_MESH</source>
+        <translation>Edit Mesh</translation>
+    </message>
+    <message>
+        <source>TOP_EDIT_SUBMESH</source>
+        <translation>Edit Sub-mesh</translation>
+    </message>
     <message>
         <source>TOP_EXPORT_DAT</source>
         <translation>Export to DAT file</translation>
@@ -4288,6 +4352,10 @@ It can&apos;t be deleted </translation>
         <source>STB_SORT_CHILD_ITEMS</source>
         <translation>Sort child items</translation>
     </message>
+    <message>
+        <source>SMESH_ADVANCED</source>
+        <translation>Advanced</translation>
+    </message>
 </context>
 <context>
     <name>SMESHGUI_FieldSelectorWdg</name>
@@ -5267,6 +5335,18 @@ Please select a group and try again</translation>
         <source>USE_INPUT_ELEMS_ONLY</source>
         <translation>Use only input elements</translation>
     </message>
+    <message>
+        <source>SMESH_SCALES</source>
+        <translation>Scale Factors</translation>
+    </message>
+    <message>
+        <source>LINEAR_SCALES</source>
+        <translation>Linear Variation of Scale Factors</translation>
+    </message>
+    <message>
+        <source>BASE_POINT</source>
+        <translation>Scaling Center</translation>
+    </message>
 </context>
 <context>
     <name>SMESHGUI_FilterDlg</name>
@@ -6120,8 +6200,12 @@ Please specify them and try again</translation>
         <translation>3D</translation>
     </message>
     <message>
-        <source>EDIT_MESH_SUBMESH</source>
-        <translation>Edit mesh/sub-mesh</translation>
+        <source>EDIT_MESH</source>
+        <translation>Edit mesh</translation>
+    </message>
+    <message>
+        <source>EDIT_SUBMESH</source>
+        <translation>Edit sub-mesh</translation>
     </message>
     <message>
         <source>GEOMETRY</source>
@@ -7994,4 +8078,23 @@ as they are of improper type:
         <translation>At least one entity type should be chosen!</translation>
     </message>
 </context>
+<context>
+    <name>SMESH_AdvOptionsWdg</name>
+    <message>
+        <source>ADD_OPTION_BTN</source>
+        <translation>Add option</translation>
+    </message>
+    <message>
+        <source>CHOICE</source>
+        <translation>Choice</translation>
+    </message>
+    <message>
+        <source>OPTION_NAME</source>
+        <translation>Option name</translation>
+    </message>
+    <message>
+        <source>OPTION_VALUE</source>
+        <translation>Option value</translation>
+    </message>
+</context>
 </TS>
index 1776f3dd4f4227e4e7658b819572f742819ab786..e65e20114c42723fd8ec3ff435c115a73205332c 100644 (file)
@@ -906,8 +906,9 @@ TopAbs_State SMESH_ElementSearcherImpl::GetPointState(const gp_Pnt& point)
       }
       else if ( ! intersection.IsParallel() && intersection.NbPoints() > 0 )
       {
+        double tol = 1e-4 * Sqrt( fNorm.Modulus() );
         gp_Pnt intersectionPoint = intersection.Point(1);
-        if ( !SMESH_MeshAlgos::IsOut( *face, intersectionPoint, tolerance ))
+        if ( !SMESH_MeshAlgos::IsOut( *face, intersectionPoint, tol ))
           u2inters.insert(make_pair( intersection.ParamOnConic(1), TInters( *face, fNorm )));
       }
     }
@@ -1133,14 +1134,11 @@ bool SMESH_MeshAlgos::IsOut( const SMDS_MeshElement* element, const gp_Pnt& poin
 
   // get ordered nodes
 
-  vector< SMESH_TNodeXYZ > xyz;
+  vector< SMESH_TNodeXYZ > xyz; xyz.reserve( element->NbNodes()+1 );
 
   SMDS_ElemIteratorPtr nodeIt = element->interlacedNodesElemIterator();
-  while ( nodeIt->more() )
-  {
-    SMESH_TNodeXYZ node = nodeIt->next();
-    xyz.push_back( node );
-  }
+  for ( int i = 0; nodeIt->more(); ++i )
+    xyz.push_back( SMESH_TNodeXYZ( nodeIt->next() ));
 
   int i, nbNodes = (int) xyz.size(); // central node of biquadratic is missing
 
@@ -1171,8 +1169,23 @@ bool SMESH_MeshAlgos::IsOut( const SMDS_MeshElement* element, const gp_Pnt& poin
 
     // check if the point lays on face plane
     gp_Vec n2p( xyz[0], point );
-    if ( fabs( n2p * faceNorm ) > tol )
-      return true; // not on face plane
+    double dot = n2p * faceNorm;
+    if ( Abs( dot ) > tol ) // not on face plane
+    {
+      bool isOut = true;
+      if ( nbNodes > 3 ) // maybe the face is not planar
+      {
+        double elemThick = 0;
+        for ( i = 1; i < nbNodes; ++i )
+        {
+          gp_Vec n2n( xyz[0], xyz[i] );
+          elemThick = Max( elemThick, Abs( n2n * faceNorm ));
+        }
+        isOut = Abs( dot ) > elemThick + tol;
+      }
+      if ( isOut )
+        return isOut;
+    }
 
     // check if point is out of face boundary:
     // define it by closest transition of a ray point->infinity through face boundary
@@ -1184,7 +1197,7 @@ bool SMESH_MeshAlgos::IsOut( const SMDS_MeshElement* element, const gp_Pnt& poin
     normSize = plnNorm.Magnitude();
     if ( normSize <= tol ) return false; // point coincides with the first node
     plnNorm /= normSize;
-    // for each node of the face, compute its signed distance to the plane
+    // for each node of the face, compute its signed distance to the cutting plane
     vector<double> dist( nbNodes + 1);
     for ( i = 0; i < nbNodes; ++i )
     {
@@ -1194,12 +1207,12 @@ bool SMESH_MeshAlgos::IsOut( const SMDS_MeshElement* element, const gp_Pnt& poin
     dist.back() = dist.front();
     // find the closest intersection
     int    iClosest = -1;
-    double rClosest = 0, distClosest = 1e100;;
+    double rClosest = 0, distClosest = 1e100;
     gp_Pnt pClosest;
     for ( i = 0; i < nbNodes; ++i )
     {
       double r;
-      if ( fabs( dist[i]) < tol )
+      if ( fabs( dist[i] ) < tol )
         r = 0.;
       else if ( fabs( dist[i+1]) < tol )
         r = 1.;
@@ -1208,17 +1221,14 @@ bool SMESH_MeshAlgos::IsOut( const SMDS_MeshElement* element, const gp_Pnt& poin
       else
         continue; // no intersection
       gp_Pnt pInt = xyz[i] * (1.-r) + xyz[i+1] * r;
-      gp_Vec p2int ( point, pInt);
-      if ( p2int * ray > -tol ) // right half-space
+      gp_Vec p2int( point, pInt);
+      double intDist = p2int.SquareMagnitude();
+      if ( intDist < distClosest )
       {
-        double intDist = p2int.SquareMagnitude();
-        if ( intDist < distClosest )
-        {
-          iClosest = i;
-          rClosest = r;
-          pClosest = pInt;
-          distClosest = intDist;
-        }
+        iClosest = i;
+        rClosest = r;
+        pClosest = pInt;
+        distClosest = intDist;
       }
     }
     if ( iClosest < 0 )
@@ -1242,6 +1252,7 @@ bool SMESH_MeshAlgos::IsOut( const SMDS_MeshElement* element, const gp_Pnt& poin
     bool covexCorner = ( edgeNorm * edgeAdjacent * (rClosest==1. ? 1. : -1.)) < 0;
     return covexCorner ? (out || out2) : (out && out2);
   }
+
   if ( element->GetType() == SMDSAbs_Edge ) // --------------------------------------------------
   {
     // point is out of edge if it is NOT ON any straight part of edge
@@ -1269,6 +1280,7 @@ bool SMESH_MeshAlgos::IsOut( const SMDS_MeshElement* element, const gp_Pnt& poin
     }
     return true;
   }
+
   // Node or 0D element -------------------------------------------------------------------------
   {
     gp_Vec n2p ( xyz[0], point );
index 757e3977f94d22d8cea3f48fe60e15ea4ea4786e..983a3173b2072df0884602157da477409d10763f 100644 (file)
@@ -1916,8 +1916,8 @@ CORBA::Boolean SMESH_Gen_i::Compute( SMESH::SMESH_Mesh_ptr theMesh,
         myLocShape = SMESH_Mesh::PseudoShape();
       // call implementation compute
       ::SMESH_Mesh& myLocMesh = meshServant->GetImpl();
-      myGen.PrepareCompute( myLocMesh, myLocShape);
-      bool ok = myGen.Compute( myLocMesh, myLocShape);
+      myGen.PrepareCompute( myLocMesh, myLocShape );
+      bool ok = myGen.Compute( myLocMesh, myLocShape, myLocShape != myLocMesh.GetShapeToMesh());
       meshServant->CreateGroupServants(); // algos can create groups (issue 0020918)
       myLocMesh.GetMeshDS()->Modified();
       return ok;
index cecee4596fdb7606e3157d3d4213634293cb5757..f9fb06334cc561f588da2a1262c7a2f9ca49bfab 100644 (file)
@@ -2484,6 +2484,7 @@ namespace MeshEditor_I
     bool myIsExtrusionByNormal;
 
     static int makeFlags( CORBA::Boolean MakeGroups,
+                          CORBA::Boolean LinearVariation = false,
                           CORBA::Boolean ByAverageNormal = false,
                           CORBA::Boolean UseInputElemsOnly = false,
                           CORBA::Long    Flags = 0,
@@ -2492,18 +2493,24 @@ namespace MeshEditor_I
       if ( MakeGroups       ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
       if ( ByAverageNormal  ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
       if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
+      if ( LinearVariation  ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_SCALE_LINEAR_VARIATION;
       if ( MakeBoundary     ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
       return Flags;
     }
     // standard params
-    ExtrusionParams(const SMESH::DirStruct &  theDir,
-                    CORBA::Long               theNbOfSteps,
-                    CORBA::Boolean            theMakeGroups):
+    ExtrusionParams(const SMESH::DirStruct &    theDir,
+                    CORBA::Long                 theNbOfSteps,
+                    const SMESH::double_array & theScaleFactors,
+                    CORBA::Boolean              theLinearVariation,
+                    const SMESH::double_array & theBasePoint,
+                    CORBA::Boolean              theMakeGroups):
       ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
                                                 theDir.PS.y,
                                                 theDir.PS.z ),
                                         theNbOfSteps,
-                                        makeFlags( theMakeGroups )),
+                                        toList( theScaleFactors ),
+                                        TBasePoint( theBasePoint ),
+                                        makeFlags( theMakeGroups, theLinearVariation )),
       myIsExtrusionByNormal( false )
     {
     }
@@ -2517,7 +2524,9 @@ namespace MeshEditor_I
                                                 theDir.PS.y,
                                                 theDir.PS.z ),
                                         theNbOfSteps,
-                                        makeFlags( theMakeGroups, false, false,
+                                        std::list<double>(),
+                                        0,
+                                        makeFlags( theMakeGroups, false, false, false,
                                                    theExtrFlags, false ),
                                         theSewTolerance ),
       myIsExtrusionByNormal( false )
@@ -2532,7 +2541,7 @@ namespace MeshEditor_I
                     CORBA::Boolean theMakeGroups ):
       ::SMESH_MeshEditor::ExtrusParam ( theStepSize, 
                                         theNbOfSteps,
-                                        makeFlags( theMakeGroups,
+                                        makeFlags( theMakeGroups, false,
                                                    theByAverageNormal, theUseInputElemsOnly ),
                                         theDim),
       myIsExtrusionByNormal( true )
@@ -2543,6 +2552,32 @@ namespace MeshEditor_I
     {
       Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
     }
+
+  private:
+
+    static std::list<double> toList( const SMESH::double_array & theScaleFactors )
+    {
+      std::list<double> scales;
+      for ( CORBA::ULong i = 0; i < theScaleFactors.length(); ++i )
+        scales.push_back( theScaleFactors[i] );
+      return scales;
+    }
+
+    // structure used to convert SMESH::double_array to gp_XYZ*
+    struct TBasePoint
+    {
+      gp_XYZ *pp, p;
+      TBasePoint( const SMESH::double_array & theBasePoint )
+      {
+        pp = 0;
+        if ( theBasePoint.length() == 3 )
+        {
+          p.SetCoord( theBasePoint[0], theBasePoint[1], theBasePoint[2] );
+          pp = &p;
+        }
+      }
+      operator const gp_XYZ*() const { return pp; }
+    };
   };
 }
 
@@ -2566,13 +2601,17 @@ SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNode
                                           const SMESH::ListOfIDSources & theFaces,
                                           const SMESH::DirStruct &       theStepVector,
                                           CORBA::Long                    theNbOfSteps,
+                                          const SMESH::double_array &    theScaleFactors,
+                                          CORBA::Boolean                 theLinearVariation,
+                                          const SMESH::double_array &    theBasePoint,
                                           CORBA::Boolean                 theToMakeGroups)
   throw (SALOME::SALOME_Exception)
 {
   SMESH_TRY;
   initData();
 
-  ExtrusionParams params( theStepVector, theNbOfSteps, theToMakeGroups );
+  ExtrusionParams params( theStepVector, theNbOfSteps, theScaleFactors,
+                          theLinearVariation, theBasePoint, theToMakeGroups );
 
   TIDSortedElemSet elemsNodes[2];
   for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
@@ -2916,13 +2955,13 @@ SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & the
                 << thePathShape        << ", "
                 << theNodeStart        << ", "
                 << theHasAngles        << ", "
-                << theAngles           << ", "
+                << TVar( theAngles )   << ", "
                 << theLinearVariation  << ", "
                 << theHasRefPoint      << ", "
                 << "SMESH.PointStruct( "
-                << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
-                << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
-                << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
+                << TVar( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
+                << TVar( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
+                << TVar( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
                 << theMakeGroups       << " )";
   }
   else
index c3b0a42865dd01bd0be3cb9f6fb70b31978e5d2f..ab953091e279df55263738538b9012936d602461 100644 (file)
@@ -330,6 +330,9 @@ public:
                                              const SMESH::ListOfIDSources & faces,
                                              const SMESH::DirStruct &       stepVector,
                                              CORBA::Long                    nbOfSteps,
+                                             const SMESH::double_array &    theScaleFactors,
+                                             CORBA::Boolean                 theLinearVariation,
+                                             const SMESH::double_array &    theBasePoint,
                                              CORBA::Boolean                 toMakeGroups)
     throw (SALOME::SALOME_Exception);
 
index f56f9551c823039637838cf3e40964f484dda164..a37bffc803646fe4721540ff93347b086bd5b76a 100644 (file)
@@ -1497,11 +1497,12 @@ class Mesh:
                 print allReasons
             pass
         if salome.sg.hasDesktop() and self.mesh.GetStudyId() >= 0:
-            smeshgui = salome.ImportComponentGUI("SMESH")
-            smeshgui.Init(self.mesh.GetStudyId())
-            smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), ok, (self.NbNodes()==0) )
-            if refresh: salome.sg.updateObjBrowser(1)
-            pass
+            if not isinstance( refresh, list): # not a call from subMesh.Compute()
+                smeshgui = salome.ImportComponentGUI("SMESH")
+                smeshgui.Init(self.mesh.GetStudyId())
+                smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), ok, (self.NbNodes()==0) )
+                if refresh: salome.sg.updateObjBrowser(1)
+
         return ok
 
     ## Return a list of error messages (SMESH.ComputeError) of the last Compute()
@@ -3820,17 +3821,27 @@ class Mesh:
                                          NbOfSteps, Tolerance, MakeGroups, TotalAngle)
 
     ## Generates new elements by extrusion of the given elements and nodes
-    #  @param nodes nodes to extrude: a list including ids, groups, sub-meshes or a mesh
-    #  @param edges edges to extrude: a list including ids, groups, sub-meshes or a mesh
-    #  @param faces faces to extrude: a list including ids, groups, sub-meshes or a mesh
+    #  @param nodes nodes to extrude: a list including ids, groups, sub-meshes or a mesh
+    #  @param edges edges to extrude: a list including ids, groups, sub-meshes or a mesh
+    #  @param faces faces to extrude: a list including ids, groups, sub-meshes or a mesh
     #  @param StepVector vector or DirStruct or 3 vector components, defining
     #         the direction and value of extrusion for one step (the total extrusion
     #         length will be NbOfSteps * ||StepVector||)
     #  @param NbOfSteps the number of steps
     #  @param MakeGroups forces the generation of new groups from existing ones
+    #  @param scaleFactors optional scale factors to apply during extrusion
+    #  @param linearVariation if @c True, scaleFactors are spread over all @a scaleFactors,
+    #         else scaleFactors[i] is applied to nodes at the i-th extrusion step
+    #  @param basePoint optional scaling center; if not provided, a gravity center of
+    #         nodes and elements being extruded is used as the scaling center.
+    #         It can be either
+    #         - a list of tree components of the point or
+    #         - a node ID or
+    #         - a GEOM point
     #  @return the list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise
     #  @ingroup l2_modif_extrurev
-    def ExtrusionSweepObjects(self, nodes, edges, faces, StepVector, NbOfSteps, MakeGroups=False):
+    def ExtrusionSweepObjects(self, nodes, edges, faces, StepVector, NbOfSteps, MakeGroups=False,
+                              scaleFactors=[], linearVariation=False, basePoint=[] ):
         unRegister = genObjUnRegister()
         nodes = self._getIdSourceList( nodes, SMESH.NODE, unRegister )
         edges = self._getIdSourceList( edges, SMESH.EDGE, unRegister )
@@ -3841,12 +3852,22 @@ class Mesh:
         if isinstance( StepVector, list ):
             StepVector = self.smeshpyD.MakeDirStruct(*StepVector)
 
+        if isinstance( basePoint, int):
+            xyz = self.GetNodeXYZ( basePoint )
+            if not xyz:
+                raise RuntimeError, "Invalid node ID: %s" % basePoint
+            basePoint = xyz
+        if isinstance( basePoint, geomBuilder.GEOM._objref_GEOM_Object ):
+            basePoint = self.geompyD.PointCoordinates( basePoint )
+
         NbOfSteps,Parameters,hasVars = ParseParameters(NbOfSteps)
         Parameters = StepVector.PS.parameters + var_separator + Parameters
         self.mesh.SetParameters(Parameters)
 
         return self.editor.ExtrusionSweepObjects( nodes, edges, faces,
-                                                  StepVector, NbOfSteps, MakeGroups)
+                                                  StepVector, NbOfSteps,
+                                                  scaleFactors, linearVariation, basePoint,
+                                                  MakeGroups)
 
 
     ## Generates new elements by extrusion of the elements with given ids
@@ -4981,7 +5002,7 @@ class Mesh:
     pass # end of Mesh class
 
 
-## class used to compensate change of CORBA API of SMESH_Mesh for backward compatibility
+## Class used to compensate change of CORBA API of SMESH_Mesh for backward compatibility
 #  with old dump scripts which call SMESH_Mesh directly and not via smeshBuilder.Mesh
 #
 class meshProxy(SMESH._objref_SMESH_Mesh):
@@ -4997,7 +5018,40 @@ class meshProxy(SMESH._objref_SMESH_Mesh):
     pass
 omniORB.registerObjref(SMESH._objref_SMESH_Mesh._NP_RepositoryId, meshProxy)
 
-## class used to compensate change of CORBA API of SMESH_MeshEditor for backward compatibility
+
+## Class wrapping SMESH_SubMesh in order to add Compute()
+#
+class submeshProxy(SMESH._objref_SMESH_subMesh):
+    def __init__(self):
+        SMESH._objref_SMESH_subMesh.__init__(self)
+        self.mesh = None
+    def __deepcopy__(self, memo=None):
+        new = self.__class__()
+        return new
+
+    ## Computes the sub-mesh and returns the status of the computation
+    #  @param refresh if @c True, Object browser is automatically updated (when running in GUI)
+    #  @return True or False
+    #  @ingroup l2_construct
+    def Compute(self,refresh=False):
+        if not self.mesh:
+            self.mesh = Mesh( smeshBuilder(), None, self.GetMesh())
+
+        ok = self.mesh.Compute( self.GetSubShape(),refresh=[] )
+
+        if salome.sg.hasDesktop() and self.mesh.GetStudyId() >= 0:
+            smeshgui = salome.ImportComponentGUI("SMESH")
+            smeshgui.Init(self.mesh.GetStudyId())
+            smeshgui.SetMeshIcon( salome.ObjectToID( self ), ok, (self.GetNumberOfElements()==0) )
+            if refresh: salome.sg.updateObjBrowser(1)
+            pass
+
+        return ok
+    pass
+omniORB.registerObjref(SMESH._objref_SMESH_subMesh._NP_RepositoryId, submeshProxy)
+
+
+## Class used to compensate change of CORBA API of SMESH_MeshEditor for backward compatibility
 #  with old dump scripts which call SMESH_MeshEditor directly and not via smeshBuilder.Mesh
 #
 class meshEditor(SMESH._objref_SMESH_MeshEditor):
@@ -5109,7 +5163,7 @@ class algoCreator:
         raise RuntimeError, "No class found for algo type %s" % algoType
         return None
 
-# Private class used to substitute and store variable parameters of hypotheses.
+## Private class used to substitute and store variable parameters of hypotheses.
 #
 class hypMethodWrapper:
     def __init__(self, hyp, method):
@@ -5140,7 +5194,8 @@ class hypMethodWrapper:
         return result
     pass
 
-# A helper class that call UnRegister() of SALOME.GenericObj'es stored in it
+## A helper class that call UnRegister() of SALOME.GenericObj'es stored in it
+#
 class genObjUnRegister:
 
     def __init__(self, genObj=None):
@@ -5161,6 +5216,9 @@ class genObjUnRegister:
             if genObj and hasattr( genObj, "UnRegister" ):
                 genObj.UnRegister()
 
+
+## Bind methods creating mesher plug-ins to the Mesh class
+#
 for pluginName in os.environ[ "SMESH_MeshersList" ].split( ":" ):
     #
     #print "pluginName: ", pluginName
index 53a8d5dc296aa565fc492e3ae2a65eeff20e7259..66bae01e026929239ce2c94a07d007c5e86c18a5 100644 (file)
@@ -195,12 +195,14 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const StdMeshers_FaceSide*  theSide,
                                          const double                theUFirst,
                                          const double                theULast)
 {
+  myEdge.resize        ( 1 );
+  myEdgeID.resize      ( 1, 0 );
   myC2d.push_back      ( theC2d );
+  myC3dAdaptor.resize  ( 1 );
   myFirst.push_back    ( theUFirst );
   myLast.push_back     ( theULast );
   myNormPar.push_back  ( 1. );
   myIsUniform.push_back( true );
-  myEdgeID.push_back   ( 0 );
   myLength       = 0;
   myProxyMesh    = theSide->myProxyMesh;
   myDefaultPnt2d = *thePnt2d1;
@@ -324,7 +326,6 @@ const std::vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXCons
     if ( NbEdges() == 0 ) return myPoints;
 
     StdMeshers_FaceSide* me = const_cast< StdMeshers_FaceSide* >( this );
-    //SMESHDS_Mesh*    meshDS = myProxyMesh->GetMeshDS();
     SMESH_MesherHelper eHelper( *myProxyMesh->GetMesh() );
     SMESH_MesherHelper fHelper( *myProxyMesh->GetMesh() );
     fHelper.SetSubShape( myFace );
@@ -429,17 +430,19 @@ const std::vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXCons
       else
       {
         node = VertexNode( iE );
-        while ( !node && iE > 0 )
-          node = VertexNode( --iE );
-        if ( !node )
-          return myPoints;
+        if ( myProxyMesh->GetMesh()->HasModificationsToDiscard() )
+          while ( !node && iE > 1 ) // check intermediate VERTEXes
+            node = VertexNode( --iE );
       }
-      if ( u2node.rbegin()->second == node &&
-           !fHelper.IsRealSeam  ( node->getshapeId() ) &&
-           !fHelper.IsDegenShape( node->getshapeId() ))
-        u2node.erase( --u2node.end() );
+      if ( node )
+      {
+        if ( u2node.rbegin()->second == node &&
+             !fHelper.IsRealSeam  ( node->getshapeId() ) &&
+             !fHelper.IsDegenShape( node->getshapeId() ))
+          u2node.erase( --u2node.end() );
 
-      u2node.insert( u2node.end(), make_pair( 1., node ));
+        u2node.insert( u2node.end(), make_pair( 1., node ));
+      }
     }
 
     if ((int) u2node.size() + nbProxyNodes != myNbPonits &&
index eb42bee5dbe8f43d21cb82b0bdbde2724f0676ca..37e025f824eeb94b8200f47280e4e0e6ab20762b 100644 (file)
@@ -215,10 +215,14 @@ public:
    */
   const SMDS_MeshNode* VertexNode(std::size_t i, bool* isMoved = 0) const;
 
-  /*!
+  /*
    * \brief Return edge and parameter on edge by normalized parameter
    */
   inline double Parameter(double U, TopoDS_Edge & edge) const;
+  /*
+   * \brief Return edge ID and parameter on edge by normalized parameter
+   */
+  inline double Parameter(double U, int & edgeID) const;
   /*!
    * \brief Return UV by normalized parameter
    */
@@ -351,9 +355,11 @@ inline int StdMeshers_FaceSide::EdgeIndex( double U ) const
 
 //================================================================================
 /*!
- * \brief Return edge and parameter on edge by normalized parameter
-  * \param U - the parameter
+ * \brief Return an edge and parameter on the edge by a normalized parameter
+  * \param U - normalized parameter
   * \retval double - pameter on a curve
+  * \ warning The returned parameter can be inaccurate if the edge is non-uniformly
+  *           parametrized. Use Value2d() to get a precise point on the edge
  */
 //================================================================================
 
@@ -366,6 +372,25 @@ inline double StdMeshers_FaceSide::Parameter(double U, TopoDS_Edge & edge) const
   return myFirst[i] * ( 1 - r ) + myLast[i] * r;
 }
 
+//================================================================================
+/*!
+ * \brief Return an edge ID and parameter on the edge by a normalized parameter
+  * \param U - normalized parameter
+  * \retval double - pameter on a curve
+  * \ warning The returned parameter can be inaccurate if the edge is non-uniformly
+  *           parametrized. Use Value2d() to get a precise point on the edge
+ */
+//================================================================================
+
+inline double StdMeshers_FaceSide::Parameter(double U, int & edgeID) const
+{
+  int i = EdgeIndex( U );
+  edgeID = myEdgeID[ i ];
+  double prevU = i ? myNormPar[ i-1 ] : 0;
+  double r = ( U - prevU )/ ( myNormPar[ i ] - prevU );
+  return myFirst[i] * ( 1 - r ) + myLast[i] * r;
+}
+
 //================================================================================
 /*!
  * \brief Return first normalized parameter of the i-th edge
index 86b8b73766c26e7f5a615aea67b2df742942f72f..2fcf21902b20fc09f65c5d2d624824b9986286fc 100644 (file)
@@ -122,7 +122,7 @@ public:
     if ( !StdMeshers_Regular_1D::computeInternalParameters( mesh, C3D, len, f, l, theParams, false))
     {
       for ( size_t i = 1; i < 15; ++i )
-        theParams.push_back( i/15 );
+        theParams.push_back( i/15. ); // ????
     }
     else
     {
@@ -1561,7 +1561,7 @@ namespace
       uvsNew.push_back( uvPt );
       for (list<double>::iterator itU = params.begin(); itU != params.end(); ++itU )
       {
-        gp_XY uv  = ( 1 - *itU ) * uvOut + *itU * uvIn;
+        gp_XY uv  = ( 1 - *itU ) * uvOut + *itU * uvIn; // applied in direction Out -> In
         gp_Pnt p  = surface->Value( uv.X(), uv.Y() );
         uvPt.node = theHelper.AddNode( p.X(), p.Y(), p.Z(), /*id=*/0, uv.X(), uv.Y() );
         uvPt.u    = uv.X();
index 526d1ec35cd64ada6cc0b6ad56bb286c4f5b1e35..ff3b4c871b94ac4c030cabd2ecc542c19af12b3f 100644 (file)
@@ -17,9 +17,8 @@
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
-//  SMESH SMESH : implementaion of SMESH idl descriptions
-// File      : StdMeshers_RadialQuadrangle_1D2D.cxx
-// Module    : SMESH
+// File  : StdMeshers_RadialQuadrangle_1D2D.cxx
+// Module: SMESH
 
 #include "StdMeshers_RadialQuadrangle_1D2D.hxx"
 
@@ -27,6 +26,7 @@
 #include "StdMeshers_LayerDistribution.hxx"
 #include "StdMeshers_Regular_1D.hxx"
 #include "StdMeshers_NumberOfSegments.hxx"
+#include "StdMeshers_FaceSide.hxx"
 
 #include "SMDS_MeshNode.hxx"
 #include "SMESHDS_Mesh.hxx"
 #include "SMESH_MesherHelper.hxx"
 #include "SMESH_subMesh.hxx"
 #include "SMESH_subMeshEventListener.hxx"
+#include "SMESH_Block.hxx"
 
 #include "utilities.h"
 
+#include <BRepAdaptor_CompCurve.hxx>
 #include <BRepAdaptor_Curve.hxx>
 #include <BRepBuilderAPI_MakeEdge.hxx>
+#include <BRep_Builder.hxx>
 #include <BRep_Tool.hxx>
+#include <GCPnts_AbscissaPoint.hxx>
+#include <Geom2d_Line.hxx>
+#include <Geom2d_TrimmedCurve.hxx>
 #include <GeomAPI_ProjectPointOnSurf.hxx>
 #include <Geom_Circle.hxx>
 #include <Geom_Line.hxx>
 #include <Geom_TrimmedCurve.hxx>
+#include <ShapeFix_Edge.hxx>
 #include <TColgp_SequenceOfPnt.hxx>
 #include <TColgp_SequenceOfPnt2d.hxx>
 #include <TopExp.hxx>
@@ -66,10 +73,10 @@ using namespace std;
 //purpose  : 
 //=======================================================================
 
-StdMeshers_RadialQuadrangle_1D2D::StdMeshers_RadialQuadrangle_1D2D(int hypId,
-                                                                   int studyId,
+StdMeshers_RadialQuadrangle_1D2D::StdMeshers_RadialQuadrangle_1D2D(int        hypId,
+                                                                   int        studyId,
                                                                    SMESH_Gen* gen)
-  :SMESH_2D_Algo(hypId, studyId, gen)
+  :StdMeshers_Quadrangle_2D( hypId, studyId, gen )
 {
   _name = "RadialQuadrangle_1D2D";
   _shapeType = (1 << TopAbs_FACE);        // 1 bit per shape type
@@ -173,10 +180,12 @@ namespace
     }
   };
 
-  // ------------------------------------------------------------------------------
+  //================================================================================
   /*!
    * \brief Mark an edge as computed by StdMeshers_RadialQuadrangle_1D2D
    */
+  //================================================================================
+
   void markEdgeAsComputedByMe(const TopoDS_Edge& edge, SMESH_subMesh* faceSubMesh)
   {
     if ( SMESH_subMesh* edgeSM = faceSubMesh->GetFather()->GetSubMeshContaining( edge ))
@@ -187,132 +196,402 @@ namespace
                                        edgeSM);
     }
   }
-  // ------------------------------------------------------------------------------
-  /*!
-   * \brief Return true if a radial edge was meshed with StdMeshers_RadialQuadrangle_1D2D with
-   * the same radial distribution
-   */
-//   bool isEdgeCompatiballyMeshed(const TopoDS_Edge& edge, SMESH_subMesh* faceSubMesh)
-//   {
-//     if ( SMESH_subMesh* edgeSM = faceSubMesh->GetFather()->GetSubMeshContaining( edge ))
-//     {
-//       if ( SMESH_subMeshEventListenerData* otherFaceData =
-//            edgeSM->GetEventListenerData( TEdgeMarker::getListener() ))
-//       {
-//         // compare hypothesis aplied to two disk faces sharing radial edges
-//         SMESH_Mesh& mesh = *faceSubMesh->GetFather();
-//         SMESH_Algo* radialQuadAlgo = mesh.GetGen()->GetAlgo(mesh, faceSubMesh->GetSubShape() );
-//         SMESH_subMesh* otherFaceSubMesh = otherFaceData->mySubMeshes.front();
-//         list <const SMESHDS_Hypothesis *> hyps1 =
-//           radialQuadAlgo->GetUsedHypothesis( mesh, faceSubMesh->GetSubShape());
-//         list <const SMESHDS_Hypothesis *> hyps2 =
-//           radialQuadAlgo->GetUsedHypothesis( mesh, otherFaceSubMesh->GetSubShape());
-//         if( hyps1.empty() && hyps2.empty() )
-//           return true; // defaul hyps
-//         if ( hyps1.size() != hyps2.size() )
-//           return false;
-//         return *hyps1.front() == *hyps2.front();
-//       }
-//     }
-//     return false;
-//   }
 
   //================================================================================
   /*!
-   * \brief Return base curve of the edge and extremum parameters
+   * \brief Return sides of the face connected in the order: aCircEdge, aLinEdge1, aLinEdge2
+   *  \retval int - nb of sides
    */
   //================================================================================
 
-  Handle(Geom_Curve) getCurve(const TopoDS_Edge& edge, double* f=0, double* l=0)
+  int analyseFace(const TopoDS_Shape&     aShape,
+                  SMESH_Mesh*             aMesh,
+                  StdMeshers_FaceSidePtr& aCircSide,
+                  StdMeshers_FaceSidePtr& aLinSide1,
+                  StdMeshers_FaceSidePtr& aLinSide2)
   {
-    Handle(Geom_Curve) C;
-    if ( !edge.IsNull() )
+    const TopoDS_Face& face = TopoDS::Face( aShape );
+    aCircSide.reset(); aLinSide1.reset(); aLinSide2.reset();
+
+    list< TopoDS_Edge > edges;
+    list< int > nbEdgesInWire;
+    int nbWire = SMESH_Block::GetOrderedEdges ( face, edges, nbEdgesInWire );
+    if ( nbWire > 2 || nbEdgesInWire.front() < 1 ) return 0;
+
+    // remove degenerated EDGEs
+    list<TopoDS_Edge>::iterator edge = edges.begin();
+    while ( edge != edges.end() )
+      if ( SMESH_Algo::isDegenerated( *edge ))
+        edge = edges.erase( edge );
+      else
+        ++edge;
+    int nbEdges = edges.size();
+
+    // find VERTEXes between continues EDGEs
+    TopTools_MapOfShape contVV;
+    if ( nbEdges > 1 )
     {
-      double first = 0., last = 0.;
-      C = BRep_Tool::Curve(edge, first, last);
-      if ( !C.IsNull() )
+      TopoDS_Edge ePrev = edges.back();
+      for ( edge = edges.begin(); edge != edges.end(); ++edge )
       {
-        Handle(Geom_TrimmedCurve) tc = Handle(Geom_TrimmedCurve)::DownCast(C);
-        while( !tc.IsNull() ) {
-          C = tc->BasisCurve();
-          tc = Handle(Geom_TrimmedCurve)::DownCast(C);
-        }
-        if ( f ) *f = first;
-        if ( l ) *l = last;
+        if ( SMESH_Algo::IsContinuous( ePrev, *edge ))
+          contVV.Add( SMESH_MesherHelper::IthVertex( 0, *edge ));
+        ePrev = *edge;
+      }
+    }
+    // make edges start from a non-continues VERTEX
+    if ( 1 < contVV.Extent() && contVV.Extent() < nbEdges )
+    {
+      while ( contVV.Contains( SMESH_MesherHelper::IthVertex( 0, edges.front() )))
+        edges.splice( edges.end(), edges, edges.begin() );
+    }
+
+    // make face sides
+    TSideVector sides;
+    while ( !edges.empty() )
+    {
+      list< TopoDS_Edge > sideEdges;
+      sideEdges.splice( sideEdges.end(), edges, edges.begin() );
+      while ( !edges.empty() &&
+              contVV.Contains( SMESH_MesherHelper::IthVertex( 0, edges.front() )))
+        sideEdges.splice( sideEdges.end(), edges, edges.begin() );
+
+      StdMeshers_FaceSidePtr side;
+      if ( aMesh ) 
+        side = StdMeshers_FaceSide::New( face, sideEdges, aMesh,
+                                         /*isFwd=*/true, /*skipMedium=*/ true );
+      sides.push_back( side );
+    }
+
+    if ( !aMesh ) // call from IsApplicable()
+      return sides.size();
+
+    if ( sides.size() > 3 )
+      return sides.size();
+
+    if ( nbWire == 2 && (( sides.size() != 2 ) ||
+                         ( sides[0]->IsClosed() && sides[1]->IsClosed() ) ||
+                         ( !sides[0]->IsClosed() && !sides[1]->IsClosed() )))
+      return -1;
+
+    // detect an elliptic side
+
+    if ( sides.size() == 1 )
+    {
+      aCircSide = sides[0];
+      return sides.size();
+    }
+
+    // sort sides by deviation from a straight line
+    multimap< double, int > deviation2sideInd;
+    const double nbSamples = 7;
+    for ( size_t iS = 0; iS < sides.size(); ++iS )
+    {
+      gp_Pnt pf = BRep_Tool::Pnt( sides[iS]->FirstVertex() );
+      gp_Pnt pl = BRep_Tool::Pnt( sides[iS]->LastVertex() );
+      gp_Vec v1( pf, pl );
+      double v1Len = v1.Magnitude();
+      if ( v1Len < std::numeric_limits< double >::min() )
+      {
+        deviation2sideInd.insert( make_pair( sides[iS]->Length(), iS )); // the side seems closed
+        continue;
+      }
+      double devia = 0;
+      for ( int i = 0; i < nbSamples; ++i )
+      {
+        gp_Pnt pi( sides[iS]->Value3d(( i + 1 ) / nbSamples ));
+        gp_Vec vi( pf, pi );
+        double h = 0.5 * v1.Crossed( vi ).Magnitude() / v1Len;
+        devia = Max( devia, h );
+      }
+      deviation2sideInd.insert( make_pair( devia, iS ));
+    }
+
+    int iCirc = deviation2sideInd.rbegin()->second; 
+    aCircSide = sides[ iCirc ];
+    aLinSide1 = sides[( iCirc + 1 ) % sides.size() ];
+    if ( sides.size() > 2 )
+    {
+      aLinSide2 = sides[( iCirc + 2 ) % sides.size() ];
+      aLinSide2->Reverse(); // to be "parallel" to aLinSide1
+    }
+
+    if (( nbWire == 2 && aLinSide1 ) &&
+        ( aLinSide1->Edge(0).Orientation() == TopAbs_INTERNAL ) &&
+        ( aCircSide->IsClosed() ))
+    {
+      // assure that aCircSide starts at aLinSide1
+      TopoDS_Vertex v0 = aLinSide1->FirstVertex();
+      TopoDS_Vertex v1 = aLinSide1->LastVertex();
+      if ( ! aCircSide->FirstVertex().IsSame( v0 ) &&
+           ! aCircSide->FirstVertex().IsSame( v1 ))
+      {
+        int iE = 0;
+        for ( ; iE < aCircSide->NbEdges(); ++iE )
+          if ( aCircSide->FirstVertex(iE).IsSame( v0 ) ||
+               aCircSide->FirstVertex(iE).IsSame( v1 ))
+            break;
+        if ( iE == aCircSide->NbEdges() )
+          return -2;
+
+        edges.clear();
+        for ( int i = 0; i < aCircSide->NbEdges(); ++i, ++iE )
+          edges.push_back( aCircSide->Edge( iE % aCircSide->NbEdges() ));
+
+        aCircSide = StdMeshers_FaceSide::New( face, edges, aMesh,
+                                              /*isFwd=*/true, /*skipMedium=*/ true );
       }
     }
-    return C;
+
+    return sides.size();
   }
 
   //================================================================================
   /*!
-   * \brief Return edges of the face
-   *  \retval int - nb of edges
+   * \brief Checks if the common vertex between LinSide's lies inside the circle
+   *  and not outside
+   *  \return bool - false if there are 3 EDGEs and the corner is outside
    */
   //================================================================================
 
-  int analyseFace(const TopoDS_Shape& face,
-                  TopoDS_Edge&        CircEdge,
-                  TopoDS_Edge&        LinEdge1,
-                  TopoDS_Edge&        LinEdge2)
+  bool isCornerInsideCircle(const StdMeshers_FaceSidePtr& CircSide,
+                            const StdMeshers_FaceSidePtr& LinSide1,
+                            const StdMeshers_FaceSidePtr& LinSide2)
+  {
+    // if ( CircSide && LinSide1 && LinSide2 )
+    // {
+    //   Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircSide ));
+    //   TopoDS_Vertex aCommonV;
+    //   if ( !aCirc.IsNull() &&
+    //        TopExp::CommonVertex( LinSide1, LinSide2, aCommonV ))
+    //   {
+    //     gp_Pnt aCommonP = BRep_Tool::Pnt( aCommonV );
+    //     gp_Pnt  aCenter = aCirc->Location();
+    //     double     dist = aCenter.Distance( aCommonP );
+    //     return dist < 0.1 * aCirc->Radius();
+    //   }
+    // }
+    return true;
+  }
+
+  //================================================================================
+  /*!
+   * \brief Create an EDGE connecting the ellipse center with the most distant point
+   *        of the ellipse.
+   *  \param [in] circSide - the elliptic side
+  *  \param [in] face - the FACE
+  *  \param [out] circNode - a node on circSide most distant from the center
+  *  \return TopoDS_Edge - the create EDGE
+  */
+  //================================================================================
+
+  TopoDS_Edge makeEdgeToCenter( StdMeshers_FaceSidePtr& circSide,
+                                const TopoDS_Face&      face,
+                                const SMDS_MeshNode*&   circNode)
   {
-    CircEdge.Nullify(); LinEdge1.Nullify(); LinEdge2.Nullify();
-    int nbe = 0;
+    // find the center and a point most distant from it
+
+    double maxDist = 0, normPar;
+    gp_XY uv1, uv2;
+    for ( int i = 0; i < 32; ++i )
+    {
+      double    u = 0.5 * i / 32.;
+      gp_Pnt2d p1 = circSide->Value2d( u );
+      gp_Pnt2d p2 = circSide->Value2d( u + 0.5 );
+      double dist = p1.SquareDistance( p2 );
+      if ( dist > maxDist )
+      {
+        maxDist = dist;
+        uv1 = p1.XY();
+        uv2 = p2.XY();
+        normPar = u;
+      }
+    }
+    gp_XY center = 0.5 * ( uv1 + uv2 );
+    double   len = 0.5 * Sqrt( maxDist );
+    bool  isCirc = ( Abs( len - circSide->Value2d( 0 ).Distance( center )) < 1e-3 * len );
+
+    // find a node closest to the most distant point
 
-    for ( TopExp_Explorer exp( face, TopAbs_EDGE ); exp.More(); exp.Next(), ++nbe )
+    size_t iDist = 0;
+    const UVPtStructVec& circNodes = circSide->GetUVPtStruct();
+    if ( !isCirc )
     {
-      const TopoDS_Edge& E = TopoDS::Edge( exp.Current() );
-      double f,l;
-      Handle(Geom_Curve) C = getCurve(E,&f,&l);
-      if ( !C.IsNull() )
+      double minDist = 1e100;
+      for ( size_t i = 0; i <= circNodes.size(); ++i )
       {
-        if ( C->IsKind( STANDARD_TYPE(Geom_Circle)))
+        double dist = Abs( circNodes[i].normParam - normPar );
+        if ( dist < minDist )
         {
-          if ( CircEdge.IsNull() )
-            CircEdge = E;
-          else
-            return 0;
+          iDist = i;
+          minDist = dist;
         }
-        else if ( LinEdge1.IsNull() )
-          LinEdge1 = E;
-        else
-          LinEdge2 = E;
       }
     }
-    return nbe;
+    circNode = circNodes[iDist].node;
+    uv1      = circNodes[iDist].UV();
+    len      = ( uv1 - center ).Modulus();
+
+    // make the EDGE between the most distant point and the center
+
+    Handle(Geom2d_Line) line = new Geom2d_Line( uv1, gp_Dir2d( center - uv1 ) );
+    Handle(Geom2d_Curve) pcu = new Geom2d_TrimmedCurve( line, 0, len );
+
+    Handle(Geom_Surface) surface = BRep_Tool::Surface( face );
+    TopoDS_Edge edge = BRepBuilderAPI_MakeEdge( pcu, surface, 0, len );
+
+    BRep_Builder().UpdateEdge( edge, pcu, face, 1e-7 );
+    ShapeFix_Edge().FixAddCurve3d( edge );
+
+
+    // assure that circSide starts at circNode
+    if ( iDist != 0  &&  iDist != circNodes.size()-1 )
+    {
+      // create a new circSide
+      UVPtStructVec nodesNew;
+      nodesNew.reserve( circNodes.size() );
+      nodesNew.insert( nodesNew.end(), circNodes.begin() + iDist, circNodes.end() );
+      nodesNew.insert( nodesNew.end(), circNodes.begin() + 1, circNodes.begin() + iDist + 1 );
+      circSide = StdMeshers_FaceSide::New( nodesNew );
+    }
+
+    return edge;
   }
+
   //================================================================================
   /*!
-   * \brief Checks if the common vertex between LinEdge's lies inside the circle
-   *  and not outside
-   *  \param [in] CircEdge - 
-   *  \param [in] LinEdge1 - 
-   *  \param [in] LinEdge2 - 
-   *  \return bool - false if there are 3 EDGEs and the corner is outside
+   * \brief Set nodes existing on a linSide to UVPtStructVec and create missing nodes
+   *        corresponding to layerPositions
    */
   //================================================================================
 
-  bool isCornerInsideCircle(const TopoDS_Edge& CircEdge,
-                            const TopoDS_Edge& LinEdge1,
-                            const TopoDS_Edge& LinEdge2)
+  void makeMissingMesh( StdMeshers_FaceSidePtr& linSide,
+                        UVPtStructVec&          nodes,
+                        const vector< double >& layerPositions,
+                        SMESH_MesherHelper*     helper )
   {
-    if ( !CircEdge.IsNull() &&
-         !LinEdge1.IsNull() &&
-         !LinEdge2.IsNull() )
+    // tolerance to compare normParam
+    double tol = 1e100;
+    for ( size_t i = 1; i < layerPositions.size(); ++i )
+      tol = Min( tol, layerPositions[i] - layerPositions[i-1] );
+    tol *= 0.05;
+
+    // merge existing nodes with layerPositions into UVPtStructVec
+    // ------------------------------------------------------------
+
+    const UVPtStructVec& exiNodes = linSide->GetUVPtStruct();
+    nodes.clear();
+    nodes.reserve( layerPositions.size() + exiNodes.size() );
+    vector< double >::const_iterator pos = layerPositions.begin(), posEnd = layerPositions.end();
+    for ( size_t i = 0; i < exiNodes.size(); ++i )
     {
-      Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge ));
-      TopoDS_Vertex aCommonV;
-      if ( !aCirc.IsNull() &&
-           TopExp::CommonVertex( LinEdge1, LinEdge2, aCommonV ))
+      switch ( exiNodes[i].node->GetPosition()->GetTypeOfPosition() )
+      {
+      case SMDS_TOP_VERTEX:
+      {
+        // allocate UVPtStruct's for non-existing nodes
+        while ( pos != posEnd && *pos < exiNodes[i].normParam - tol )
+        {
+          UVPtStruct uvPS;
+          uvPS.normParam = *pos++;
+          nodes.push_back( uvPS );
+        }
+        // save existing node on a VERTEX
+        nodes.push_back( exiNodes[i] );
+        break;
+      }
+      case SMDS_TOP_EDGE:
+      {
+        // save existing nodes on an EDGE
+        while ( i < exiNodes.size() && exiNodes[i].node->GetPosition()->GetDim() == 1 )
+        {
+          nodes.push_back( exiNodes[i++] );
+        }
+        // save existing node on a VERTEX
+        if ( i < exiNodes.size() && exiNodes[i].node->GetPosition()->GetDim() == 0 )
+        {
+          nodes.push_back( exiNodes[i] );
+        }
+        break;
+      }
+      default:;
+      }
+
+      // skip layer positions covered by saved nodes
+      while ( pos != posEnd && *pos < nodes.back().normParam + tol )
       {
-        gp_Pnt aCommonP = BRep_Tool::Pnt( aCommonV );
-        gp_Pnt  aCenter = aCirc->Location();
-        double     dist = aCenter.Distance( aCommonP );
-        return dist < 0.1 * aCirc->Radius();
+        ++pos;
       }
     }
-    return true;
-  }
+    // allocate UVPtStruct's for the rest non-existing nodes
+    while ( pos != posEnd )
+    {
+      UVPtStruct uvPS;
+      uvPS.normParam = *pos++;
+      nodes.push_back( uvPS );
+    }
+
+    // create missing nodes
+    // ---------------------
+
+    SMESHDS_Mesh * meshDS = helper->GetMeshDS();
+    const TopoDS_Face& F  = TopoDS::Face( helper->GetSubShape() );
+    Handle(ShapeAnalysis_Surface) surface = helper->GetSurface( F );
+
+    helper->SetElementsOnShape( false ); // we create nodes on EDGEs, not on the FACE
+
+    for ( size_t i = 0; i < nodes.size(); ++i )
+    {
+      if ( nodes[ i ].node ) continue;
+
+      gp_Pnt2d uv = linSide->Value2d( nodes[i].normParam );
+      gp_Pnt  xyz = surface->Value( uv.X(), uv.Y() );
+
+      nodes[ i ].SetUV( uv.XY() );
+      nodes[ i ].node = helper->AddNode( xyz.X(), xyz.Y(), xyz.Z() );
+    }
+
+    // set nodes on VERTEXes
+    for ( int iE = 0; iE < linSide->NbEdges(); ++iE )
+    {
+      TopoDS_Vertex v = linSide->LastVertex( iE );
+      if ( SMESH_Algo::VertexNode( v, meshDS ))
+        continue;
+
+      double normPar = linSide->LastParameter( iE );
+      size_t i = 0;
+      while ( nodes[ i ].normParam < normPar )
+        ++i;
+      if (( nodes[ i ].normParam - normPar ) > ( normPar - nodes[ i-1 ].normParam ))
+        --i;
+      meshDS->SetNodeOnVertex( nodes[ i ].node, v );
+    }
+
+    // set nodes on EDGEs
+    int edgeID;
+    for ( size_t i = 0; i < nodes.size(); ++i )
+    {
+      if ( nodes[ i ].node->getshapeId() > 0 ) continue;
+
+      double u = linSide->Parameter( nodes[i].normParam, edgeID );
+      meshDS->SetNodeOnEdge( nodes[ i ].node, edgeID, u );
+    }
+
+    // create segments
+    for ( size_t i = 1; i < nodes.size(); ++i )
+    {
+      if ( meshDS->FindEdge( nodes[i].node, nodes[i-1].node )) continue;
+
+      const SMDS_MeshElement* seg = helper->AddEdge( nodes[i].node, nodes[i-1].node );
+
+      double normParam = 0.5 * ( nodes[i].normParam + nodes[i-1].normParam );
+      edgeID = linSide->EdgeID( linSide->EdgeIndex( normParam ));
+      meshDS->SetMeshElementOnShape( seg, edgeID );
+    }
+
+    helper->SetElementsOnShape( true );
+
+  } // end makeMissingMesh()
 
 //================================================================================
 //================================================================================
@@ -339,47 +618,80 @@ public:
   // -----------------------------------------------------------------------------
   //! Computes distribution of nodes on a straight line ending at pIn and pOut
   bool Compute( vector< double > &      positions,
-                gp_Pnt                  pIn,
-                gp_Pnt                  pOut,
-                SMESH_Mesh&             aMesh,
+                const TopoDS_Edge&      edge,
+                Adaptor3d_Curve&        curve,
+                double                  f,
+                double                  l,
+                SMESH_Mesh&             mesh,
                 const SMESH_Hypothesis* hyp1d)
   {
     if ( !hyp1d ) return error( "Invalid LayerDistribution hypothesis");
 
-    double len = pIn.Distance( pOut );
-    if ( len <= DBL_MIN ) return error("Too close points of inner and outer shells");
-
     myUsedHyps.clear();
     myUsedHyps.push_back( hyp1d );
 
-    TopoDS_Edge edge = BRepBuilderAPI_MakeEdge( pIn, pOut );
     SMESH_Hypothesis::Hypothesis_Status aStatus;
-    if ( !StdMeshers_Regular_1D::CheckHypothesis( aMesh, edge, aStatus ))
+    if ( !StdMeshers_Regular_1D::CheckHypothesis( mesh, edge, aStatus ))
       return error( "StdMeshers_Regular_1D::CheckHypothesis() failed "
                     "with LayerDistribution hypothesis");
 
-    BRepAdaptor_Curve C3D(edge);
-    double f = C3D.FirstParameter(), l = C3D.LastParameter();
+    double len = GCPnts_AbscissaPoint::Length( curve, f, l );
+
     list< double > params;
-    if ( !StdMeshers_Regular_1D::computeInternalParameters( aMesh, C3D, len, f, l, params, false ))
+    if ( !StdMeshers_Regular_1D::computeInternalParameters( mesh, curve, len, f, l, params, false ))
       return error("StdMeshers_Regular_1D failed to compute layers distribution");
 
+    params.push_front( f );
+    params.push_back ( l );
     positions.clear();
     positions.reserve( params.size() );
     for (list<double>::iterator itU = params.begin(); itU != params.end(); itU++)
-      positions.push_back( *itU / len );
+      positions.push_back(( *itU - f ) / ( l - f ));
     return true;
   }
   // -----------------------------------------------------------------------------
   //! Make mesh on an adge using assigned 1d hyp or defaut nb of segments
-  bool ComputeCircularEdge(SMESH_Mesh&         aMesh,
-                           const TopoDS_Edge& anEdge)
+  bool ComputeCircularEdge( SMESH_Mesh&                   aMesh,
+                            const StdMeshers_FaceSidePtr& aSide )
+  {
+    bool ok = true;
+    for ( int i = 0; i < aSide->NbEdges(); ++i )
+    {
+      const TopoDS_Edge& edge = aSide->Edge( i );
+      _gen->Compute( aMesh, edge );
+      SMESH_subMesh *sm = aMesh.GetSubMesh( edge );
+      if ( sm->GetComputeState() != SMESH_subMesh::COMPUTE_OK)
+      {
+        // find any 1d hyp assigned (there can be a hyp w/o algo)
+        myUsedHyps = SMESH_Algo::GetUsedHypothesis( aMesh, edge, /*ignoreAux=*/true );
+        Hypothesis_Status aStatus;
+        if ( !StdMeshers_Regular_1D::CheckHypothesis( aMesh, edge, aStatus ))
+        {
+          // no valid 1d hyp assigned, use default nb of segments
+          _hypType                    = NB_SEGMENTS;
+          _ivalue[ DISTR_TYPE_IND ]   = StdMeshers_NumberOfSegments::DT_Regular;
+          _ivalue[ NB_SEGMENTS_IND  ] = _gen->GetDefaultNbSegments();
+        }
+        ok &= StdMeshers_Regular_1D::Compute( aMesh, edge );
+      }
+    }
+    return ok;
+  }
+  // -----------------------------------------------------------------------------
+  //! Make mesh on an adge using assigned 1d hyp or defaut nb of segments
+  bool EvaluateCircularEdge(SMESH_Mesh&                  aMesh,
+                            const StdMeshers_FaceSidePtr aSide,
+                            MapShapeNbElems&             aResMap)
   {
-    _gen->Compute( aMesh, anEdge);
-    SMESH_subMesh *sm = aMesh.GetSubMesh(anEdge);
-    if ( sm->GetComputeState() != SMESH_subMesh::COMPUTE_OK)
+    bool ok = true;
+    for ( int i = 0; i < aSide->NbEdges(); ++i )
     {
-      // find any 1d hyp assigned (there can be a hyp w/o algo)
+      const TopoDS_Edge& anEdge = aSide->Edge( i );
+      _gen->Evaluate( aMesh, anEdge, aResMap );
+      if ( aResMap.count( aMesh.GetSubMesh( anEdge )))
+        continue;
+
+      // find any 1d hyp assigned
       myUsedHyps = SMESH_Algo::GetUsedHypothesis(aMesh, anEdge, /*ignoreAux=*/true);
       Hypothesis_Status aStatus;
       if ( !StdMeshers_Regular_1D::CheckHypothesis( aMesh, anEdge, aStatus ))
@@ -389,31 +701,9 @@ public:
         _ivalue[ DISTR_TYPE_IND ]   = StdMeshers_NumberOfSegments::DT_Regular;
         _ivalue[ NB_SEGMENTS_IND  ] = _gen->GetDefaultNbSegments();
       }
-      return StdMeshers_Regular_1D::Compute( aMesh, anEdge );
-    }
-    return true;
-  }
-  // -----------------------------------------------------------------------------
-  //! Make mesh on an adge using assigned 1d hyp or defaut nb of segments
-  bool EvaluateCircularEdge(SMESH_Mesh&        aMesh,
-                            const TopoDS_Edge& anEdge,
-                            MapShapeNbElems&   aResMap)
-  {
-    _gen->Evaluate( aMesh, anEdge, aResMap );
-    if ( aResMap.count( aMesh.GetSubMesh( anEdge )))
-      return true;
-
-    // find any 1d hyp assigned
-    myUsedHyps = SMESH_Algo::GetUsedHypothesis(aMesh, anEdge, /*ignoreAux=*/true);
-    Hypothesis_Status aStatus;
-    if ( !StdMeshers_Regular_1D::CheckHypothesis( aMesh, anEdge, aStatus ))
-    {
-      // no valid 1d hyp assigned, use default nb of segments
-      _hypType                    = NB_SEGMENTS;
-      _ivalue[ DISTR_TYPE_IND ]   = StdMeshers_NumberOfSegments::DT_Regular;
-      _ivalue[ NB_SEGMENTS_IND  ] = _gen->GetDefaultNbSegments();
+      ok &= StdMeshers_Regular_1D::Evaluate( aMesh, anEdge, aResMap );
     }
-    return StdMeshers_Regular_1D::Evaluate( aMesh, anEdge, aResMap );
+    return ok;
   }
 protected:
   // -----------------------------------------------------------------------------
@@ -444,11 +734,10 @@ void StdMeshers_RadialQuadrangle_1D2D::SubmeshRestored(SMESH_subMesh* faceSubMes
 {
   if ( !faceSubMesh->IsEmpty() )
   {
-    TopoDS_Edge CircEdge, LinEdge1, LinEdge2;
-    analyseFace( faceSubMesh->GetSubShape(), CircEdge, LinEdge1, LinEdge2 );
-    if ( !CircEdge.IsNull() ) markEdgeAsComputedByMe( CircEdge, faceSubMesh );
-    if ( !LinEdge1.IsNull() ) markEdgeAsComputedByMe( LinEdge1, faceSubMesh );
-    if ( !LinEdge2.IsNull() ) markEdgeAsComputedByMe( LinEdge2, faceSubMesh );
+    for ( TopExp_Explorer e( faceSubMesh->GetSubShape(), TopAbs_EDGE ); e.More(); e.Next() )
+    {
+      markEdgeAsComputedByMe( TopoDS::Edge( e.Current() ), faceSubMesh );
+    }
   }
 }
 
@@ -460,559 +749,242 @@ void StdMeshers_RadialQuadrangle_1D2D::SubmeshRestored(SMESH_subMesh* faceSubMes
 bool StdMeshers_RadialQuadrangle_1D2D::Compute(SMESH_Mesh&         aMesh,
                                                const TopoDS_Shape& aShape)
 {
-  SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
-
-  myHelper = new SMESH_MesherHelper( aMesh );
-  // to delete helper at exit from Compute()
-  SMESHUtils::Deleter<SMESH_MesherHelper> helperDeleter( myHelper );
+  SMESH_MesherHelper helper( aMesh );
+  StdMeshers_Quadrangle_2D::myHelper     = & helper;
+  StdMeshers_Quadrangle_2D::myNeedSmooth = false;
+  StdMeshers_Quadrangle_2D::myCheckOri   = false;
+  StdMeshers_Quadrangle_2D::myQuadList.clear();
+
+  StdMeshers_FaceSidePtr circSide, linSide1, linSide2;
+  int nbSides = analyseFace( aShape, &aMesh, circSide, linSide1, linSide2 );
+  if( nbSides > 3 || nbSides < 1 )
+    return error("The face must be a full ellipse or a part of ellipse (i.e. the number "
+                 "of edges is less or equal to 3 and one of them is an ellipse curve)");
+
+  // get not yet computed EDGEs
+  list< TopoDS_Edge > emptyEdges;
+  for ( TopExp_Explorer e( aShape, TopAbs_EDGE ); e.More(); e.Next() )
+  {
+    if ( aMesh.GetSubMesh( e.Current() )->IsEmpty() )
+      emptyEdges.push_back( TopoDS::Edge( e.Current() ));
+  }
 
   TNodeDistributor* algo1d = TNodeDistributor::GetDistributor(aMesh);
 
-  TopoDS_Edge CircEdge, LinEdge1, LinEdge2;
-  int nbe = analyseFace( aShape, CircEdge, LinEdge1, LinEdge2 );
-  Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge ));
-  if( nbe > 3 || nbe < 1 || aCirc.IsNull() )
-    return error("The face must be a full circle or a part of circle (i.e. the number "
-                 "of edges is less or equal to 3 and one of them is a circle curve)");
-
-  gp_Pnt P0, P1;
-  // points for rotation
-  TColgp_SequenceOfPnt Points;
-  // angles for rotation
-  TColStd_SequenceOfReal Angles;
-  // Nodes1 and Nodes2 - nodes along radiuses
-  // CNodes - nodes on circle edge
-  vector< const SMDS_MeshNode* > Nodes1, Nodes2, CNodes;
-  SMDS_MeshNode * NC;
-  // parameters edge nodes on face
-  TColgp_SequenceOfPnt2d Pnts2d1;
-  gp_Pnt2d PC;
-
-  int faceID = meshDS->ShapeToIndex(aShape);
+  if ( !algo1d->ComputeCircularEdge( aMesh, circSide ))
+    return error( algo1d->GetComputeError() );
+
+
   TopoDS_Face F = TopoDS::Face(aShape);
   Handle(Geom_Surface) S = BRep_Tool::Surface(F);
 
+  myHelper->IsQuadraticSubMesh( aShape );
+  myHelper->SetElementsOnShape( true );
+
+  vector< double > layerPositions; // [0,1]
+
+  const SMDS_MeshNode* centerNode = 0;
+  gp_Pnt2d             centerUV(0,0);
 
-  if(nbe==1)
+  // ------------------------------------------------------------------------------------------
+  if ( nbSides == 1 ) // full ellipse
   {
-    if (!algo1d->ComputeCircularEdge( aMesh, CircEdge ))
-      return error( algo1d->GetComputeError() );
-    map< double, const SMDS_MeshNode* > theNodes;
-    if ( !GetSortedNodesOnEdge(aMesh.GetMeshDS(),CircEdge,true,theNodes))
-      return error("Circular edge is incorrectly meshed");
-
-    myHelper->IsQuadraticSubMesh( aShape );
-
-    CNodes.clear();
-    map< double, const SMDS_MeshNode* >::iterator itn = theNodes.begin();
-    const SMDS_MeshNode* NF = (*itn).second;
-    CNodes.push_back( (*itn).second );
-    double fang = (*itn).first;
-    if ( itn != theNodes.end() ) {
-      itn++;
-      for(; itn != theNodes.end(); itn++ ) {
-        CNodes.push_back( (*itn).second );
-        double ang = (*itn).first - fang;
-        if( ang>M_PI ) ang = ang - 2.*M_PI;
-        if( ang<-M_PI ) ang = ang + 2.*M_PI;
-        Angles.Append( ang ); 
-      }
-    }
-    P1 = gp_Pnt( NF->X(), NF->Y(), NF->Z() );
-    P0 = aCirc->Location();
+    const SMDS_MeshNode* circNode;
+    TopoDS_Edge linEdge = makeEdgeToCenter( circSide, F, circNode );
 
-    if ( !computeLayerPositions(P0,P1))
-      return false;
+    StdMeshers_FaceSidePtr tmpSide =
+      StdMeshers_FaceSide::New( F, linEdge, &aMesh, /*isFrw=*/true, /*skipMedium=*/true );
 
-    TopoDS_Vertex V1 = myHelper->IthVertex(0, CircEdge );
-    gp_Pnt2d p2dV = BRep_Tool::Parameters( V1, TopoDS::Face(aShape) );
+    if ( !computeLayerPositions( tmpSide, layerPositions ))
+      return false;
 
-    NC = meshDS->AddNode(P0.X(), P0.Y(), P0.Z());
-    GeomAPI_ProjectPointOnSurf PPS(P0,S);
-    double U0,V0;
-    PPS.Parameters(1,U0,V0);
-    meshDS->SetNodeOnFace(NC, faceID, U0, V0);
-    PC = gp_Pnt2d(U0,V0);
+    UVPtStructVec nodes( layerPositions.size() );
+    nodes[0].node = circNode;
+    for ( size_t i = 0; i < layerPositions.size(); ++i )
+    {
+      gp_Pnt2d uv = tmpSide->Value2d( layerPositions[i] );
+      gp_Pnt  xyz = S->Value( uv.X(), uv.Y() );
 
-    gp_Vec aVec(P0,P1);
-    gp_Vec2d aVec2d(PC,p2dV);
-    Nodes1.resize( myLayerPositions.size()+1 );
-    Nodes2.resize( myLayerPositions.size()+1 );
-    size_t i = 0;
-    for ( ; i < myLayerPositions.size(); i++ ) {
-      gp_Pnt P( P0.X() + aVec.X()*myLayerPositions[i],
-                P0.Y() + aVec.Y()*myLayerPositions[i],
-                P0.Z() + aVec.Z()*myLayerPositions[i] );
-      Points.Append(P);
-      SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
-      Nodes1[i] = node;
-      Nodes2[i] = node;
-      double U = PC.X() + aVec2d.X()*myLayerPositions[i];
-      double V = PC.Y() + aVec2d.Y()*myLayerPositions[i];
-      meshDS->SetNodeOnFace( node, faceID, U, V );
-      Pnts2d1.Append(gp_Pnt2d(U,V));
+      nodes[ i ].SetUV( uv.XY() );
+      nodes[ i ].normParam = layerPositions[i];
+      if ( i )
+        nodes[ i ].node = myHelper->AddNode( xyz.X(), xyz.Y(), xyz.Z(), 0, uv.X(), uv.Y() );
     }
-    Nodes1[Nodes1.size()-1] = NF;
-    Nodes2[Nodes1.size()-1] = NF;
+
+    linSide1 = StdMeshers_FaceSide::New( nodes );
+    linSide2 = StdMeshers_FaceSide::New( nodes );
+
+    centerNode = nodes.back().node;
+    centerUV   = nodes.back().UV();
   }
-  else if(nbe==2 && LinEdge1.Orientation() != TopAbs_INTERNAL )
+  // ------------------------------------------------------------------------------------------
+  else if ( nbSides == 2 && linSide1->Edge(0).Orientation() == TopAbs_INTERNAL )
   {
-    // one curve must be a half of circle and other curve must be
-    // a segment of line
-    double fp, lp;
-    Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge, &fp, &lp ));
-    if( fabs(fabs(lp-fp)-M_PI) > Precision::Confusion() ) {
-      // not half of circle
-      return error(COMPERR_BAD_SHAPE);
-    }
-    Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast( getCurve( LinEdge1 ));
-    if( aLine.IsNull() ) {
-      // other curve not line
-      return error(COMPERR_BAD_SHAPE);
-    }
+    // full ellipse with an internal radial side
 
-    if ( !algo1d->ComputeCircularEdge( aMesh, CircEdge ))
-      return error( algo1d->GetComputeError() );
-    map< double, const SMDS_MeshNode* > theNodes;
-    if ( !GetSortedNodesOnEdge(aMesh.GetMeshDS(),CircEdge,true,theNodes) )
-      return error("Circular edge is incorrectly meshed");
-
-    myHelper->IsQuadraticSubMesh( aShape );
-
-    map< double, const SMDS_MeshNode* >::iterator itn = theNodes.begin();
-    CNodes.clear();
-    CNodes.push_back( itn->second );
-    double fang = (*itn).first;
-    itn++;
-    for(; itn != theNodes.end(); itn++ ) {
-      CNodes.push_back( (*itn).second );
-      double ang = (*itn).first - fang;
-      if( ang>M_PI ) ang = ang - 2.*M_PI;
-      if( ang<-M_PI ) ang = ang + 2.*M_PI;
-      Angles.Append( ang );
+    // eliminate INTERNAL orientation
+    list< TopoDS_Edge > edges;
+    for ( int iE = 0; iE < linSide1->NbEdges(); ++iE )
+    {
+      edges.push_back( linSide1->Edge( iE ));
+      edges.back().Orientation( TopAbs_FORWARD );
     }
-    const SMDS_MeshNode* NF = theNodes.begin()->second;
-    const SMDS_MeshNode* NL = theNodes.rbegin()->second;
-    P1 = gp_Pnt( NF->X(), NF->Y(), NF->Z() );
-    gp_Pnt P2( NL->X(), NL->Y(), NL->Z() );
-    P0 = aCirc->Location();
-
-    bool linEdgeComputed;
-    if ( !computeLayerPositions(P0,P1,LinEdge1,&linEdgeComputed))
+
+    // orient the internal side
+    bool isVIn0Shared = false;
+    TopoDS_Vertex vIn0 = myHelper->IthVertex( 0, edges.front() );
+    for ( int iE = 0; iE < circSide->NbEdges() && !isVIn0Shared; ++iE )
+      isVIn0Shared = vIn0.IsSame( circSide->FirstVertex( iE ));
+
+    linSide1 = StdMeshers_FaceSide::New( F, edges, &aMesh,
+                                         /*isFrw=*/isVIn0Shared, /*skipMedium=*/true );
+
+    int nbMeshedEdges;
+    if ( !computeLayerPositions( linSide1, layerPositions, &nbMeshedEdges ))
       return false;
 
-    if ( linEdgeComputed )
-    {
-      if (!GetSortedNodesOnEdge(aMesh.GetMeshDS(),LinEdge1,true,theNodes))
-        return error("Invalid mesh on a straight edge");
-
-      Nodes1.resize( myLayerPositions.size()+1 );
-      Nodes2.resize( myLayerPositions.size()+1 );
-      vector< const SMDS_MeshNode* > *pNodes1 = &Nodes1, *pNodes2 = &Nodes2;
-      bool nodesFromP0ToP1 = ( theNodes.rbegin()->second == NF );
-      if ( !nodesFromP0ToP1 ) std::swap( pNodes1, pNodes2 );
-
-      map< double, const SMDS_MeshNode* >::reverse_iterator ritn = theNodes.rbegin();
-      itn = theNodes.begin();
-      for ( int i = Nodes1.size()-1; i > -1; ++itn, ++ritn, --i )
-      {
-        (*pNodes1)[i] = ritn->second;
-        (*pNodes2)[i] =  itn->second;
-        Points.Prepend( gpXYZ( Nodes1[i]));
-        Pnts2d1.Prepend( myHelper->GetNodeUV( F, Nodes1[i]));
-      }
-      NC = const_cast<SMDS_MeshNode*>( itn->second );
-      Points.Remove( Nodes1.size() );
-    }
+    // merge existing nodes with new nodes at layerPositions into a UVPtStructVec
+    UVPtStructVec nodes;
+    if ( nbMeshedEdges != linSide1->NbEdges() )
+      makeMissingMesh( linSide1, nodes, layerPositions, myHelper );
     else
+      nodes = linSide1->GetUVPtStruct();
+
+    linSide1 = StdMeshers_FaceSide::New( nodes );
+    linSide2 = StdMeshers_FaceSide::New( nodes );
+
+    centerNode = nodes.back().node;
+    centerUV   = nodes.back().UV();
+  }
+  // ------------------------------------------------------------------------------------------
+  else if ( nbSides == 2 )
+  {
+    // find positions of layers for the first half of linSide1
+    int nbMeshedEdges;
+    if ( !computeLayerPositions( linSide1, layerPositions, &nbMeshedEdges, /*useHalf=*/true ))
+      return false;
+
+    // make positions for the whole linSide1
+    for ( size_t i = 0; i < layerPositions.size(); ++i )
     {
-      gp_Vec aVec(P0,P1);
-      int edgeID = meshDS->ShapeToIndex(LinEdge1);
-      // check orientation
-      Handle(Geom_Curve) Crv = BRep_Tool::Curve(LinEdge1,fp,lp);
-      gp_Pnt Ptmp;
-      Crv->D0(fp,Ptmp);
-      bool ori = true;
-      if( P1.Distance(Ptmp) > Precision::Confusion() )
-        ori = false;
-      // get UV points for edge
-      gp_Pnt2d PF,PL;
-      BRep_Tool::UVPoints( LinEdge1, TopoDS::Face(aShape), PF, PL );
-      PC = gp_Pnt2d( (PF.X()+PL.X())/2, (PF.Y()+PL.Y())/2 );
-      gp_Vec2d V2d;
-      if(ori) V2d = gp_Vec2d(PC,PF);
-      else V2d = gp_Vec2d(PC,PL);
-      // add nodes on edge
-      double cp = (fp+lp)/2;
-      double dp2 = (lp-fp)/2;
-      NC = meshDS->AddNode(P0.X(), P0.Y(), P0.Z());
-      meshDS->SetNodeOnEdge(NC, edgeID, cp);
-      Nodes1.resize( myLayerPositions.size()+1 );
-      Nodes2.resize( myLayerPositions.size()+1 );
-      size_t i = 0;
-      for(; i<myLayerPositions.size(); i++) {
-        gp_Pnt P( P0.X() + aVec.X()*myLayerPositions[i],
-                  P0.Y() + aVec.Y()*myLayerPositions[i],
-                  P0.Z() + aVec.Z()*myLayerPositions[i] );
-        Points.Append(P);
-        SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
-        Nodes1[i] = node;
-        double param;
-        if(ori)
-          param = fp + dp2*(1-myLayerPositions[i]);
-        else
-          param = cp + dp2*myLayerPositions[i];
-        meshDS->SetNodeOnEdge(node, edgeID, param);
-        P = gp_Pnt( P0.X() - aVec.X()*myLayerPositions[i],
-                    P0.Y() - aVec.Y()*myLayerPositions[i],
-                    P0.Z() - aVec.Z()*myLayerPositions[i] );
-        node = meshDS->AddNode(P.X(), P.Y(), P.Z());
-        Nodes2[i] = node;
-        if(!ori)
-          param = fp + dp2*(1-myLayerPositions[i]);
-        else
-          param = cp + dp2*myLayerPositions[i];
-        meshDS->SetNodeOnEdge(node, edgeID, param);
-        // parameters on face
-        gp_Pnt2d P2d( PC.X() + V2d.X()*myLayerPositions[i],
-                      PC.Y() + V2d.Y()*myLayerPositions[i] );
-        Pnts2d1.Append(P2d);
-      }
-      Nodes1[ myLayerPositions.size() ] = NF;
-      Nodes2[ myLayerPositions.size() ] = NL;
-      // create 1D elements on edge
-      vector< const SMDS_MeshNode* > tmpNodes;
-      tmpNodes.resize(2*Nodes1.size()+1);
-      for(i=0; i<Nodes2.size(); i++)
-        tmpNodes[Nodes2.size()-i-1] = Nodes2[i];
-      tmpNodes[Nodes2.size()] = NC;
-      for(i=0; i<Nodes1.size(); i++)
-        tmpNodes[Nodes2.size()+1+i] = Nodes1[i];
-      for(i=1; i<tmpNodes.size(); i++) {
-        SMDS_MeshEdge* ME = myHelper->AddEdge( tmpNodes[i-1], tmpNodes[i] );
-        if(ME) meshDS->SetMeshElementOnShape(ME, edgeID);
-      }
-      markEdgeAsComputedByMe( LinEdge1, aMesh.GetSubMesh( F ));
+      layerPositions[i] *= 0.5;
     }
+    layerPositions.reserve( layerPositions.size() * 2 );
+    for ( int nb = layerPositions.size()-1; nb > 0; --nb )
+      layerPositions.push_back( layerPositions.back() + layerPositions[nb] - layerPositions[nb-1] );
+
+    // merge existing nodes with new nodes at layerPositions into a UVPtStructVec
+    UVPtStructVec nodes;
+    if ( nbMeshedEdges != linSide1->NbEdges() )
+      makeMissingMesh( linSide1, nodes, layerPositions, myHelper );
+    else
+      nodes = linSide1->GetUVPtStruct();
+
+    // find a central node
+    size_t i = 0;
+    while ( nodes[ i ].normParam < 0.5 ) ++i;
+    if (( nodes[ i ].normParam - 0.5 ) > ( 0.5 - nodes[ i-1 ].normParam )) --i;
+
+    // distribute nodes between two linear sides
+    UVPtStructVec nodes2( nodes.rbegin(), nodes.rbegin() + nodes.size() - i );
+    nodes.resize( i + 1 );
+
+    linSide1 = StdMeshers_FaceSide::New( nodes );
+    linSide2 = StdMeshers_FaceSide::New( nodes2 );
+
+    centerNode = nodes.back().node;
+    centerUV   = nodes.back().UV();
   }
-  else // nbe==3 or ( nbe==2 && linEdge is INTERNAL )
+  // ------------------------------------------------------------------------------------------
+  else // nbSides == 3 
   {
-    if (nbe==2 && LinEdge1.Orientation() == TopAbs_INTERNAL )
-      LinEdge2 = LinEdge1;
-
-    // one curve must be a part of circle and other curves must be
-    // segments of line
-    double fp, lp;
-    Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge ));
-    Handle(Geom_Line)  aLine1 = Handle(Geom_Line  )::DownCast( getCurve( LinEdge1 ));
-    Handle(Geom_Line)  aLine2 = Handle(Geom_Line  )::DownCast( getCurve( LinEdge2 ));
-    if ( aCirc.IsNull() || aLine1.IsNull() || aLine2.IsNull() )
-      return error(COMPERR_BAD_SHAPE);
-    if ( !isCornerInsideCircle( CircEdge, LinEdge1, LinEdge2 ))
-      return error(COMPERR_BAD_SHAPE);
-
-    if ( !algo1d->ComputeCircularEdge( aMesh, CircEdge ))
-      return error( algo1d->GetComputeError() );
-    map< double, const SMDS_MeshNode* > theNodes;
-    if ( !GetSortedNodesOnEdge( aMesh.GetMeshDS(), CircEdge, true, theNodes ))
-      return error("Circular edge is incorrectly meshed");
-
-    myHelper->IsQuadraticSubMesh( aShape );
-
-    const SMDS_MeshNode* NF = theNodes.begin()->second;
-    const SMDS_MeshNode* NL = theNodes.rbegin()->second;
-    CNodes.clear();
-    CNodes.push_back( NF );
-    map< double, const SMDS_MeshNode* >::iterator itn = theNodes.begin();
-    double fang = (*itn).first;
-    itn++;
-    for(; itn != theNodes.end(); itn++ ) {
-      CNodes.push_back( (*itn).second );
-      double ang = (*itn).first - fang;
-      if( ang>M_PI ) ang = ang - 2.*M_PI;
-      if( ang<-M_PI ) ang = ang + 2.*M_PI;
-      Angles.Append( ang );
-    }
-    P1 = gp_Pnt( NF->X(), NF->Y(), NF->Z() );
-    gp_Pnt P2( NL->X(), NL->Y(), NL->Z() );
-    P0 = aCirc->Location();
-
-    // make P1 belong to LinEdge1
-    TopoDS_Vertex V1 = myHelper->IthVertex( 0, LinEdge1 );
-    TopoDS_Vertex V2 = myHelper->IthVertex( 1, LinEdge1 );
-    gp_Pnt PE1 = BRep_Tool::Pnt(V1);
-    gp_Pnt PE2 = BRep_Tool::Pnt(V2);
-    if( ( P1.Distance(PE1) > Precision::Confusion() ) &&
-        ( P1.Distance(PE2) > Precision::Confusion() ) )
-      std::swap( LinEdge1, LinEdge2 );
-
-    bool linEdge1Computed, linEdge2Computed;
-    if ( !computeLayerPositions(P0,P1,LinEdge1,&linEdge1Computed))
-      return false;
+    // one curve must be a part of ellipse and 2 other curves must be segments of line
 
-    Nodes1.resize( myLayerPositions.size()+1 );
-    Nodes2.resize( myLayerPositions.size()+1 );
+    int nbMeshedEdges1, nbMeshedEdges2;
+    vector< double > layerPositions2;
+    bool ok1 = computeLayerPositions( linSide1, layerPositions,  &nbMeshedEdges1 );
+    bool ok2 = computeLayerPositions( linSide2, layerPositions2, &nbMeshedEdges2 );
+    if ( !ok1 && !ok2 )
+      return false;
 
-    // check that both linear edges have same hypotheses
-    if ( !computeLayerPositions(P0,P2,LinEdge2, &linEdge2Computed))
-         return false;
-    if ( Nodes1.size() != myLayerPositions.size()+1 )
-      return error("Different hypotheses apply to radial edges");
+    bool linSide1Computed = ( nbMeshedEdges1 == linSide1->NbEdges() );
+    bool linSide2Computed = ( nbMeshedEdges2 == linSide2->NbEdges() );
 
-    // find the central vertex
-    TopoDS_Vertex VC = V2;
-    if( ( P1.Distance(PE1) > Precision::Confusion() ) &&
-        ( P2.Distance(PE1) > Precision::Confusion() ) )
-      VC = V1;
-    int vertID = meshDS->ShapeToIndex(VC);
+    UVPtStructVec nodes;
 
-    // LinEdge1
-    if ( linEdge1Computed )
-    {
-      if (!GetSortedNodesOnEdge(aMesh.GetMeshDS(),LinEdge1,true,theNodes))
-        return error("Invalid mesh on a straight edge");
-
-      bool nodesFromP0ToP1 = ( theNodes.rbegin()->second == NF );
-      NC = const_cast<SMDS_MeshNode*>
-        ( nodesFromP0ToP1 ? theNodes.begin()->second : theNodes.rbegin()->second );
-      size_t i = 0, ir = Nodes1.size()-1;
-      size_t * pi = nodesFromP0ToP1 ? &i : &ir;
-      itn = theNodes.begin();
-      if ( nodesFromP0ToP1 ) ++itn;
-      for ( ; i < Nodes1.size(); ++i, --ir, ++itn )
-      {
-        Nodes1[*pi] = itn->second;
-      }
-      for ( i = 0; i < Nodes1.size()-1; ++i )
-      {
-        Points.Append( gpXYZ( Nodes1[i]));
-        Pnts2d1.Append( myHelper->GetNodeUV( F, Nodes1[i]));
-      }
-    }
-    else
+    if ( linSide1Computed && !linSide2Computed )
     {
-      int edgeID = meshDS->ShapeToIndex(LinEdge1);
-      gp_Vec aVec(P0,P1);
-      // check orientation
-      Handle(Geom_Curve) Crv = BRep_Tool::Curve(LinEdge1,fp,lp);
-      gp_Pnt Ptmp = Crv->Value(fp);
-      bool ori = false;
-      if( P1.Distance(Ptmp) > Precision::Confusion() )
-        ori = true;
-      // get UV points for edge
-      gp_Pnt2d PF,PL;
-      BRep_Tool::UVPoints( LinEdge1, TopoDS::Face(aShape), PF, PL );
-      gp_Vec2d V2d;
-      if(ori) {
-        V2d = gp_Vec2d(PF,PL);
-        PC = PF;
-      }
-      else {
-        V2d = gp_Vec2d(PL,PF);
-        PC = PL;
-      }
-      NC = const_cast<SMDS_MeshNode*>( VertexNode( VC, meshDS ));
-      if ( !NC )
-      {
-        NC = meshDS->AddNode(P0.X(), P0.Y(), P0.Z());
-        meshDS->SetNodeOnVertex(NC, vertID);
-      }
-      double dp = lp-fp;
-      size_t i = 0;
-      for ( ; i < myLayerPositions.size(); i++ ) {
-        gp_Pnt P( P0.X() + aVec.X()*myLayerPositions[i],
-                  P0.Y() + aVec.Y()*myLayerPositions[i],
-                  P0.Z() + aVec.Z()*myLayerPositions[i] );
-        Points.Append(P);
-        SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
-        Nodes1[i] = node;
-        double param;
-        if ( !ori )
-          param = fp + dp*(1-myLayerPositions[i]);
-        else
-          param = fp + dp*myLayerPositions[i];
-        meshDS->SetNodeOnEdge(node, edgeID, param);
-        // parameters on face
-        gp_Pnt2d P2d( PC.X() + V2d.X()*myLayerPositions[i],
-                      PC.Y() + V2d.Y()*myLayerPositions[i] );
-        Pnts2d1.Append(P2d);
-      }
-      Nodes1[ myLayerPositions.size() ] = NF;
-      // create 1D elements on edge
-      SMDS_MeshEdge* ME = myHelper->AddEdge( NC, Nodes1[0] );
-      if(ME) meshDS->SetMeshElementOnShape(ME, edgeID);
-      for ( i = 1; i < Nodes1.size(); i++ ) {
-        ME = myHelper->AddEdge( Nodes1[i-1], Nodes1[i] );
-        if(ME) meshDS->SetMeshElementOnShape(ME, edgeID);
-      }
-      if ( nbe == 2 && LinEdge1.Orientation() == TopAbs_INTERNAL )
-        Nodes2 = Nodes1;
+      // use layer positions of linSide1 to mesh linSide2
+      makeMissingMesh( linSide2, nodes, layerPositions, myHelper );
+      linSide2 = StdMeshers_FaceSide::New( nodes );
     }
-    markEdgeAsComputedByMe( LinEdge1, aMesh.GetSubMesh( F ));
-
-    // LinEdge2
-    if ( linEdge2Computed )
+    else if ( linSide2Computed && !linSide1Computed )
     {
-      if (!GetSortedNodesOnEdge(aMesh.GetMeshDS(),LinEdge2,true,theNodes))
-        return error("Invalid mesh on a straight edge");
-
-      bool nodesFromP0ToP2 = ( theNodes.rbegin()->second == NL );
-      size_t i = 0, ir = Nodes1.size()-1;
-      size_t * pi = nodesFromP0ToP2 ? &i : &ir;
-      itn = theNodes.begin();
-      if ( nodesFromP0ToP2 ) ++itn;
-      for ( ; i < Nodes2.size(); ++i, --ir, ++itn )
-        Nodes2[*pi] = itn->second;
+      // use layer positions of linSide2 to mesh linSide1
+      makeMissingMesh( linSide1, nodes, layerPositions2, myHelper );
+      linSide1 = StdMeshers_FaceSide::New( nodes );
     }
-    else
+    else if ( !linSide2Computed && !linSide1Computed )
     {
-      int edgeID = meshDS->ShapeToIndex(LinEdge2);
-      gp_Vec aVec = gp_Vec(P0,P2);
-      // check orientation
-      Handle(Geom_Curve) Crv = BRep_Tool::Curve(LinEdge2,fp,lp);
-      gp_Pnt Ptmp = Crv->Value(fp);
-      bool ori = false;
-      if( P2.Distance(Ptmp) > Precision::Confusion() )
-        ori = true;
-      // get UV points for edge
-      gp_Pnt2d PF,PL;
-      BRep_Tool::UVPoints( LinEdge2, TopoDS::Face(aShape), PF, PL );
-      gp_Vec2d V2d;
-      if(ori) {
-        V2d = gp_Vec2d(PF,PL);
-        PC = PF;
-      }
-      else {
-        V2d = gp_Vec2d(PL,PF);
-        PC = PL;
-      }
-      double dp = lp-fp;
-      for ( size_t i = 0; i < myLayerPositions.size(); i++ ) {
-        gp_Pnt P( P0.X() + aVec.X()*myLayerPositions[i],
-                  P0.Y() + aVec.Y()*myLayerPositions[i],
-                  P0.Z() + aVec.Z()*myLayerPositions[i] );
-        SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
-        Nodes2[i] = node;
-        double param;
-        if(!ori)
-          param = fp + dp*(1-myLayerPositions[i]);
-        else
-          param = fp + dp*myLayerPositions[i];
-        meshDS->SetNodeOnEdge(node, edgeID, param);
-        // parameters on face
-        gp_Pnt2d P2d( PC.X() + V2d.X()*myLayerPositions[i],
-                      PC.Y() + V2d.Y()*myLayerPositions[i] );
-      }
-      Nodes2[ myLayerPositions.size() ] = NL;
-      // create 1D elements on edge
-      SMDS_MeshEdge* ME = myHelper->AddEdge( NC, Nodes2[0] );
-      if ( ME ) meshDS->SetMeshElementOnShape(ME, edgeID);
-      for ( size_t i = 1; i < Nodes2.size(); i++ ) {
-        ME = myHelper->AddEdge( Nodes2[i-1], Nodes2[i] );
-        if(ME) meshDS->SetMeshElementOnShape(ME, edgeID);
-      }
-    }
-    markEdgeAsComputedByMe( LinEdge2, aMesh.GetSubMesh( F ));
-  }
-  markEdgeAsComputedByMe( CircEdge, aMesh.GetSubMesh( F ));
-
-  // orientation
-  bool IsForward = ( CircEdge.Orientation()==TopAbs_FORWARD );
-  const double angleSign = ( F.Orientation() == TopAbs_REVERSED ? -1.0 : 1.0 );
-
-  // create nodes and mesh elements on face
-  // find axis of rotation
-  gp_Pnt P2 = gp_Pnt( CNodes[1]->X(), CNodes[1]->Y(), CNodes[1]->Z() );
-  gp_Vec Vec1(P0,P1);
-  gp_Vec Vec2(P0,P2);
-  gp_Vec Axis = Vec1.Crossed(Vec2);
-  // create elements
-  int i = 1;
-  //cout<<"Angles.Length() = "<<Angles.Length()<<"   Points.Length() = "<<Points.Length()<<endl;
-  //cout<<"Nodes1.size() = "<<Nodes1.size()<<"   Pnts2d1.Length() = "<<Pnts2d1.Length()<<endl;
-  for(; i<Angles.Length(); i++) {
-    vector< const SMDS_MeshNode* > tmpNodes;
-    gp_Trsf aTrsf;
-    gp_Ax1 theAxis(P0,gp_Dir(Axis));
-    aTrsf.SetRotation( theAxis, Angles.Value(i) );
-    gp_Trsf2d aTrsf2d;
-    aTrsf2d.SetRotation( PC, Angles.Value(i) * angleSign );
-    // create nodes
-    int j = 1;
-    for(; j<=Points.Length(); j++) {
-      double cx,cy,cz;
-      Points.Value(j).Coord( cx, cy, cz );
-      aTrsf.Transforms( cx, cy, cz );
-      SMDS_MeshNode* node = myHelper->AddNode( cx, cy, cz );
-      // find parameters on face
-      Pnts2d1.Value(j).Coord( cx, cy );
-      aTrsf2d.Transforms( cx, cy );
-      // set node on face
-      meshDS->SetNodeOnFace( node, faceID, cx, cy );
-      tmpNodes.push_back(node);
+      // use layer positions of a longer side to mesh the shorter side
+      vector< double >& lp =
+        ( linSide1->Length() > linSide2->Length() ) ? layerPositions : layerPositions2;
+
+      makeMissingMesh( linSide1, nodes, lp, myHelper );
+      linSide1 = StdMeshers_FaceSide::New( nodes );
+      makeMissingMesh( linSide2, nodes, lp, myHelper );
+      linSide2 = StdMeshers_FaceSide::New( nodes );
     }
-    // create faces
-    tmpNodes.push_back( CNodes[i] );
-    // quad
-    for ( j = 0; j < (int)Nodes1.size() - 1; j++ ) {
-      SMDS_MeshFace* MF;
-      if(IsForward)
-        MF = myHelper->AddFace( tmpNodes[j], Nodes1[j],
-                                Nodes1[j+1], tmpNodes[j+1] );
-      else
-        MF = myHelper->AddFace( tmpNodes[j], tmpNodes[j+1],
-                                Nodes1[j+1], Nodes1[j] );
-      if(MF) meshDS->SetMeshElementOnShape(MF, faceID);
-    }
-    // tria
-    SMDS_MeshFace* MF;
-    if(IsForward)
-      MF = myHelper->AddFace( NC, Nodes1[0], tmpNodes[0] );
-    else
-      MF = myHelper->AddFace( NC, tmpNodes[0], Nodes1[0] );
-    if ( MF ) meshDS->SetMeshElementOnShape(MF, faceID);
-    for ( j = 0; j < (int) Nodes1.size(); j++ ) {
-      Nodes1[j] = tmpNodes[j];
-    }
-  }
-  // create last faces
-  // quad
-  for ( i = 0; i < (int)Nodes1.size()-1; i++ ) {
-    SMDS_MeshFace* MF;
-    if(IsForward)
-      MF = myHelper->AddFace( Nodes2[i], Nodes1[i],
-                              Nodes1[i+1], Nodes2[i+1] );
-    else
-      MF = myHelper->AddFace( Nodes2[i],  Nodes2[i+1],
-                              Nodes1[i+1], Nodes1[i] );
-    if(MF) meshDS->SetMeshElementOnShape(MF, faceID);
+
+    const UVPtStructVec& nodes2 = linSide2->GetUVPtStruct();
+    centerNode = nodes2.back().node;
+    centerUV   = nodes2.back().UV();
   }
-  // tria
-  SMDS_MeshFace* MF;
-  if(IsForward)
-    MF = myHelper->AddFace( NC, Nodes1[0], Nodes2[0] );
+
+  list< TopoDS_Edge >::iterator ee = emptyEdges.begin();
+  for ( ; ee != emptyEdges.end(); ++ee )
+    markEdgeAsComputedByMe( *ee, aMesh.GetSubMesh( F ));
+
+  circSide->GetUVPtStruct(); // let sides take into account just computed nodes
+  linSide1->GetUVPtStruct();
+  linSide2->GetUVPtStruct();
+
+  FaceQuadStruct::Ptr quad( new FaceQuadStruct );
+  quad->side.resize( 4 );
+  quad->side[0] = circSide;
+  quad->side[1] = linSide1;
+  quad->side[2] = StdMeshers_FaceSide::New( circSide.get(), centerNode, &centerUV );
+  quad->side[3] = linSide2;
+
+  myQuadList.push_back( quad );
+
+  // create quadrangles
+  bool ok;
+  if ( linSide1->NbPoints() == linSide2->NbPoints() )
+    ok = StdMeshers_Quadrangle_2D::computeQuadDominant( aMesh, F, quad );
   else
-    MF = myHelper->AddFace( NC, Nodes2[0], Nodes1[0] );
-  if(MF) meshDS->SetMeshElementOnShape(MF, faceID);
+    ok = StdMeshers_Quadrangle_2D::computeTriangles( aMesh, F, quad );
 
-  return true;
+  StdMeshers_Quadrangle_2D::myHelper = 0;
+
+  return ok;
 }
 
 //================================================================================
 /*!
- * \brief Compute positions of nodes on the radial edge
-  * \retval bool - is a success
+ * \brief Compute nodes on the radial edge
+ * \retval int - nb of segments on the linSide
  */
 //================================================================================
 
-bool StdMeshers_RadialQuadrangle_1D2D::computeLayerPositions(const gp_Pnt&      p1,
-                                                             const gp_Pnt&      p2,
-                                                             const TopoDS_Edge& linEdge,
-                                                             bool*              linEdgeComputed)
+int StdMeshers_RadialQuadrangle_1D2D::computeLayerPositions(StdMeshers_FaceSidePtr linSide,
+                                                            vector< double > &     positions,
+                                                            int*                   nbMeshedEdges,
+                                                            bool                   useHalf)
 {
   // First, try to compute positions of layers
 
-  myLayerPositions.clear();
+  positions.clear();
 
   SMESH_Mesh * mesh = myHelper->GetMesh();
 
@@ -1022,98 +994,70 @@ bool StdMeshers_RadialQuadrangle_1D2D::computeLayerPositions(const gp_Pnt&
   if ( !hyp1D && !nbLayers )
   {
     // No own algo hypotheses assigned, so first try to find any 1D hypothesis.
-    // We need some edge
-    TopoDS_Shape edge = linEdge;
-    if ( edge.IsNull() && !myHelper->GetSubShape().IsNull())
-      for ( TopExp_Explorer e(myHelper->GetSubShape(), TopAbs_EDGE); e.More(); e.Next())
-        edge = e.Current();
-    if ( !edge.IsNull() )
-    {
-      // find a hyp usable by TNodeDistributor
-      const SMESH_HypoFilter* hypKind =
-        TNodeDistributor::GetDistributor(*mesh)->GetCompatibleHypoFilter(/*ignoreAux=*/true);
-      hyp1D = mesh->GetHypothesis( edge, *hypKind, /*fromAncestors=*/true);
-    }
+    // find a hyp usable by TNodeDistributor
+    TopoDS_Shape edge = linSide->Edge(0);
+    const SMESH_HypoFilter* hypKind =
+      TNodeDistributor::GetDistributor(*mesh)->GetCompatibleHypoFilter(/*ignoreAux=*/true);
+    hyp1D = mesh->GetHypothesis( edge, *hypKind, /*fromAncestors=*/true);
   }
   if ( hyp1D ) // try to compute with hyp1D
   {
-    if ( !TNodeDistributor::GetDistributor(*mesh)->Compute( myLayerPositions,p1,p2,*mesh,hyp1D )) {
+    BRepAdaptor_CompCurve* curve = linSide->GetCurve3d();
+    SMESHUtils::Deleter< BRepAdaptor_CompCurve > delCurve( curve );
+    double f = curve->FirstParameter();
+    double l = curve->LastParameter();
+
+    if ( useHalf )
+      l = 0.5 * ( f + l ); // first part of linSide is used
+
+    if ( !TNodeDistributor::GetDistributor(*mesh)->Compute( positions, linSide->Edge(0),
+                                                            *curve, f, l, *mesh, hyp1D ))
+    {
       if ( myDistributionHypo ) { // bad hyp assigned 
         return error( TNodeDistributor::GetDistributor(*mesh)->GetComputeError() );
       }
       else {
-        // bad hyp found, its Ok, lets try with default nb of segnents
+        // bad hyp found, its Ok, lets try with default nb of segments
       }
     }
   }
   
-  if ( myLayerPositions.empty() ) // try to use nb of layers
+  if ( positions.empty() ) // try to use nb of layers
   {
     if ( !nbLayers )
       nbLayers = _gen->GetDefaultNbSegments();
 
     if ( nbLayers )
     {
-      myLayerPositions.resize( nbLayers - 1 );
-      for ( int z = 1; z < nbLayers; ++z )
-        myLayerPositions[ z - 1 ] = double( z )/ double( nbLayers );
+      positions.resize( nbLayers + 1 );
+      for ( int z = 0; z < nbLayers; ++z )
+        positions[ z ] = double( z )/ double( nbLayers );
+      positions.back() = 1;
     }
   }
 
-  // Second, check presence of a mesh built by other algo on linEdge
-  // and mesh conformity to my hypothesis
+  // Second, check presence of a mesh built by other algo on linSide
 
-  bool meshComputed = (!linEdge.IsNull() && !mesh->GetSubMesh(linEdge)->IsEmpty() );
-  if ( linEdgeComputed ) *linEdgeComputed = meshComputed;
+  int nbEdgesComputed = 0;
+  for ( int i = 0; i < linSide->NbEdges(); ++i )
+  {
+    nbEdgesComputed += ( !mesh->GetSubMesh( linSide->Edge(i))->IsEmpty() );
+  }
 
-  if ( meshComputed )
+  if ( nbEdgesComputed == linSide->NbEdges() )
   {
-    vector< double > nodeParams;
-    GetNodeParamOnEdge( mesh->GetMeshDS(), linEdge, nodeParams );
-
-    // nb of present nodes must be different in cases of 1 and 2 straight edges
-
-    TopoDS_Vertex VV[2];
-    TopExp::Vertices( linEdge, VV[0], VV[1]);
-    const gp_Pnt* points[] = { &p1, &p2 };
-    gp_Pnt       vPoints[] = { BRep_Tool::Pnt(VV[0]), BRep_Tool::Pnt(VV[1]) };
-    const double     tol[] = { BRep_Tool::Tolerance(VV[0]), BRep_Tool::Tolerance(VV[1]) };
-    bool pointsAreOnVertices = true;
-    for ( int iP = 0; iP < 2 && pointsAreOnVertices; ++iP )
-      pointsAreOnVertices = ( points[iP]->Distance( vPoints[0] ) < tol[0] ||
-                              points[iP]->Distance( vPoints[1] ) < tol[1] );
-
-    int nbNodes = nodeParams.size() - 2; // 2 straight edges
-    if ( !pointsAreOnVertices )
-      nbNodes = ( nodeParams.size() - 3 ) / 2; // 1 straight edge
-
-    if ( myLayerPositions.empty() )
+    const UVPtStructVec& points = linSide->GetUVPtStruct();
+    if ( points.size() >= 2 )
     {
-      myLayerPositions.resize( nbNodes );
-    }
-    else if ( myDistributionHypo || myNbLayerHypo )
-    {
-      // linEdge is computed by other algo. Check if there is a meshed face
-      // using nodes on linEdge
-      bool nodesAreUsed = false;
-      TopTools_ListIteratorOfListOfShape ancestIt = mesh->GetAncestors( linEdge );
-      for ( ; ancestIt.More() && !nodesAreUsed; ancestIt.Next() )
-        if ( ancestIt.Value().ShapeType() == TopAbs_FACE )
-          nodesAreUsed = (!mesh->GetSubMesh( ancestIt.Value() )->IsEmpty());
-      if ( !nodesAreUsed ) {
-        // rebuild them
-        mesh->GetSubMesh( linEdge )->ComputeStateEngine( SMESH_subMesh::CLEAN );
-        if ( linEdgeComputed ) *linEdgeComputed = false;
-      }
-      else {
-        
-        if ((int) myLayerPositions.size() != nbNodes )
-          return error("Radial edge is meshed by other algorithm");
-      }
+      positions.resize( points.size() );
+      for ( size_t i = 0; i < points.size(); ++i )
+        positions[ i ] = points[i].normParam;
     }
   }
 
-  return !myLayerPositions.empty();
+  if ( nbMeshedEdges ) *nbMeshedEdges = nbEdgesComputed;
+
+  return positions.size();
 }
 
 
@@ -1122,9 +1066,9 @@ bool StdMeshers_RadialQuadrangle_1D2D::computeLayerPositions(const gp_Pnt&
 //purpose  : 
 //=======================================================================
 
-bool StdMeshers_RadialQuadrangle_1D2D::Evaluate(SMESH_Mesh& aMesh,
+bool StdMeshers_RadialQuadrangle_1D2D::Evaluate(SMESH_Mesh&         aMesh,
                                                 const TopoDS_Shape& aShape,
-                                                MapShapeNbElems& aResMap)
+                                                MapShapeNbElems&    aResMap)
 {
   if( aShape.ShapeType() != TopAbs_FACE ) {
     return false;
@@ -1138,190 +1082,112 @@ bool StdMeshers_RadialQuadrangle_1D2D::Evaluate(SMESH_Mesh& aMesh,
 
   myHelper = new SMESH_MesherHelper( aMesh );
   myHelper->SetSubShape( aShape );
-  auto_ptr<SMESH_MesherHelper> helperDeleter( myHelper );
+  SMESHUtils::Deleter<SMESH_MesherHelper> helperDeleter( myHelper );
 
   TNodeDistributor* algo1d = TNodeDistributor::GetDistributor(aMesh);
 
-  TopoDS_Edge CircEdge, LinEdge1, LinEdge2;
-  int nbe = analyseFace( aShape, CircEdge, LinEdge1, LinEdge2 );
-  if( nbe>3 || nbe < 1 || CircEdge.IsNull() )
+  StdMeshers_FaceSidePtr circSide, linSide1, linSide2;
+  int nbSides = analyseFace( aShape, &aMesh, circSide, linSide1, linSide2 );
+  if( nbSides > 3 || nbSides < 1 )
     return false;
 
-  Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge ));
-  if( aCirc.IsNull() )
-    return error(COMPERR_BAD_SHAPE);
+  if ( algo1d->EvaluateCircularEdge( aMesh, circSide, aResMap ))
+    return false;
 
-  gp_Pnt P0 = aCirc->Location();
-  gp_Pnt P1 = aCirc->Value(0.);
-  computeLayerPositions( P0, P1, LinEdge1 );
+  vector< double > layerPositions; // [0,1]
 
-  int nb0d=0, nb2d_tria=0, nb2d_quad=0;
-  bool isQuadratic = false, ok = true;
-  if(nbe==1)
+  // ------------------------------------------------------------------------------------------
+  if ( nbSides == 1 )
   {
-    // C1 must be a circle
-    ok = algo1d->EvaluateCircularEdge( aMesh, CircEdge, aResMap );
-    if(ok) {
-      const vector<int>& aVec = aResMap[aMesh.GetSubMesh(CircEdge)];
-      isQuadratic = aVec[SMDSEntity_Quad_Edge]>aVec[SMDSEntity_Edge];
-      if(isQuadratic) {
-        // main nodes
-        nb0d = (aVec[SMDSEntity_Node]+1) * myLayerPositions.size();
-        // radial medium nodes
-        nb0d += (aVec[SMDSEntity_Node]+1) * (myLayerPositions.size()+1);
-        // other medium nodes
-        nb0d += (aVec[SMDSEntity_Node]+1) * myLayerPositions.size();
-      }
-      else {
-        nb0d = (aVec[SMDSEntity_Node]+1) * myLayerPositions.size();
-      }
-      nb2d_tria = aVec[SMDSEntity_Node] + 1;
-      nb2d_quad = nb0d;
-    }
+    const TopoDS_Face& F = TopoDS::Face( aShape );
+
+    const SMDS_MeshNode* circNode;
+    TopoDS_Edge linEdge = makeEdgeToCenter( circSide, F, circNode );
+
+    StdMeshers_FaceSidePtr tmpSide =
+      StdMeshers_FaceSide::New( F, linEdge, &aMesh, /*isFrw=*/true, /*skipMedium=*/true );
+
+    if ( !computeLayerPositions( tmpSide, layerPositions ))
+      return false;
   }
-  else if(nbe==2 && LinEdge1.Orientation() != TopAbs_INTERNAL)
+  // ------------------------------------------------------------------------------------------
+  else if ( nbSides == 2 && linSide1->Edge(0).Orientation() == TopAbs_INTERNAL )
   {
-    // one curve must be a half of circle and other curve must be
-    // a segment of line
-    double fp, lp;
-    Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge, &fp, &lp ));
-    if( fabs(fabs(lp-fp)-M_PI) > Precision::Confusion() ) {
-      // not half of circle
-      return error(COMPERR_BAD_SHAPE);
-    }
-    Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast( getCurve( LinEdge1 ));
-    if( aLine.IsNull() ) {
-      // other curve not line
-      return error(COMPERR_BAD_SHAPE);
-    }
-    ok = !aResMap.count( aMesh.GetSubMesh(LinEdge1) );
-    if ( !ok ) {
-      const vector<int>& aVec = aResMap[ aMesh.GetSubMesh(LinEdge1) ];
-      ok = ( aVec[SMDSEntity_Node] == (int) myLayerPositions.size() );
-    }
-    if(ok) {
-      ok = algo1d->EvaluateCircularEdge( aMesh, CircEdge, aResMap );
-    }
-    if(ok) {
-      const vector<int>& aVec = aResMap[ aMesh.GetSubMesh(CircEdge) ];
-      isQuadratic = aVec[SMDSEntity_Quad_Edge] > aVec[SMDSEntity_Edge];
-      if(isQuadratic) {
-        // main nodes
-        nb0d = aVec[SMDSEntity_Node] * myLayerPositions.size();
-        // radial medium nodes
-        nb0d += aVec[SMDSEntity_Node] * (myLayerPositions.size()+1);
-        // other medium nodes
-        nb0d += (aVec[SMDSEntity_Node]+1) * myLayerPositions.size();
-      }
-      else {
-        nb0d = aVec[SMDSEntity_Node] * myLayerPositions.size();
-      }
-      nb2d_tria = aVec[SMDSEntity_Node] + 1;
-      nb2d_quad = nb2d_tria * myLayerPositions.size();
-      // add evaluation for edges
-      vector<int> aResVec(SMDSEntity_Last,0);
-      if(isQuadratic) {
-        aResVec[SMDSEntity_Node] = 4*myLayerPositions.size() + 3;
-        aResVec[SMDSEntity_Quad_Edge] = 2*myLayerPositions.size() + 2;
-      }
-      else {
-        aResVec[SMDSEntity_Node] = 2*myLayerPositions.size() + 1;
-        aResVec[SMDSEntity_Edge] = 2*myLayerPositions.size() + 2;
-      }
-      aResMap[ aMesh.GetSubMesh(LinEdge1) ] = aResVec;
-    }
+    if ( !computeLayerPositions( linSide1, layerPositions ))
+      return false;
   }
-  else  // nbe==3 or ( nbe==2 && linEdge is INTERNAL )
+  // ------------------------------------------------------------------------------------------
+  else if ( nbSides == 2 )
   {
-    if (nbe==2 && LinEdge1.Orientation() == TopAbs_INTERNAL )
-      LinEdge2 = LinEdge1;
-
-    // one curve must be a part of circle and other curves must be
-    // segments of line
-    Handle(Geom_Line)  aLine1 = Handle(Geom_Line)::DownCast( getCurve( LinEdge1 ));
-    Handle(Geom_Line)  aLine2 = Handle(Geom_Line)::DownCast( getCurve( LinEdge2 ));
-    if( aLine1.IsNull() || aLine2.IsNull() ) {
-      // other curve not line
-      return error(COMPERR_BAD_SHAPE);
-    }
-    size_t nbLayers = myLayerPositions.size();
-    computeLayerPositions( P0, P1, LinEdge2 );
-    if ( nbLayers != myLayerPositions.size() )
-      return error("Different hypotheses apply to radial edges");
-      
-    bool ok = !aResMap.count( aMesh.GetSubMesh(LinEdge1));
-    if ( !ok ) {
-      if ( myDistributionHypo || myNbLayerHypo )
-        ok = true; // override other 1d hyps
-      else {
-        const vector<int>& aVec = aResMap[ aMesh.GetSubMesh(LinEdge1) ];
-        ok = ( aVec[SMDSEntity_Node] == (int) myLayerPositions.size() );
-      }
-    }
-    if( ok && aResMap.count( aMesh.GetSubMesh(LinEdge2) )) {
-      if ( myDistributionHypo || myNbLayerHypo )
-        ok = true; // override other 1d hyps
-      else {
-        const vector<int>& aVec = aResMap[ aMesh.GetSubMesh(LinEdge2) ];
-        ok = ( aVec[SMDSEntity_Node] == (int) myLayerPositions.size() );
-      }
-    }
-    if(ok) {
-      ok = algo1d->EvaluateCircularEdge( aMesh, CircEdge, aResMap );
-    }
-    if(ok) {
-      const vector<int>& aVec = aResMap[ aMesh.GetSubMesh(CircEdge) ];
-      isQuadratic = aVec[SMDSEntity_Quad_Edge]>aVec[SMDSEntity_Edge];
-      if(isQuadratic) {
-        // main nodes
-        nb0d = aVec[SMDSEntity_Node] * myLayerPositions.size();
-        // radial medium nodes
-        nb0d += aVec[SMDSEntity_Node] * (myLayerPositions.size()+1);
-        // other medium nodes
-        nb0d += (aVec[SMDSEntity_Node]+1) * myLayerPositions.size();
-      }
-      else {
-        nb0d = aVec[SMDSEntity_Node] * myLayerPositions.size();
-      }
-      nb2d_tria = aVec[SMDSEntity_Node] + 1;
-      nb2d_quad = nb2d_tria * myLayerPositions.size();
-      // add evaluation for edges
-      vector<int> aResVec(SMDSEntity_Last, 0);
-      if(isQuadratic) {
-        aResVec[SMDSEntity_Node] = 2*myLayerPositions.size() + 1;
-        aResVec[SMDSEntity_Quad_Edge] = myLayerPositions.size() + 1;
-      }
-      else {
-        aResVec[SMDSEntity_Node] = myLayerPositions.size();
-        aResVec[SMDSEntity_Edge] = myLayerPositions.size() + 1;
-      }
-      sm = aMesh.GetSubMesh(LinEdge1);
-      aResMap[sm] = aResVec;
-      sm = aMesh.GetSubMesh(LinEdge2);
-      aResMap[sm] = aResVec;
-    }
+    // find positions of layers for the first half of linSide1
+    if ( !computeLayerPositions( linSide1, layerPositions, 0, /*useHalf=*/true ))
+      return false;
+  }
+  // ------------------------------------------------------------------------------------------
+  else // nbSides == 3 
+  {
+    if ( !computeLayerPositions(( linSide1->Length() > linSide2->Length() ) ? linSide1 : linSide2,
+                                 layerPositions ))
+      return false;
+  }
+
+  bool isQuadratic = false;
+  for ( TopExp_Explorer edge( aShape, TopAbs_EDGE ); edge.More() &&  !isQuadratic ; edge.Next() )
+  {
+    sm = aMesh.GetSubMesh( edge.Current() );
+    vector<int>& nbElems = aResMap[ sm ];
+    if ( SMDSEntity_Quad_Edge < (int) nbElems.size() )
+      isQuadratic = nbElems[ SMDSEntity_Quad_Edge ];
+  }
+
+  int nbCircSegments = 0;
+  for ( int iE = 0; iE < circSide->NbEdges(); ++iE )
+  {
+    sm = aMesh.GetSubMesh( circSide->Edge( iE ));
+    vector<int>& nbElems = aResMap[ sm ];
+    if ( SMDSEntity_Quad_Edge < (int) nbElems.size() )
+      nbCircSegments += ( nbElems[ SMDSEntity_Edge ] + nbElems[ SMDSEntity_Quad_Edge ]);
+  }
+  
+  int nbQuads = nbCircSegments * ( layerPositions.size() - 1 );
+  int nbTria  = nbCircSegments;
+  int nbNodes = ( nbCircSegments - 1 ) * ( layerPositions.size() - 2 );
+  if ( isQuadratic )
+  {
+    nbNodes += (( nbCircSegments - 1 ) * ( layerPositions.size() - 1 ) + // radial
+                ( nbCircSegments     ) * ( layerPositions.size() - 2 )); // circular
+    aResVec[SMDSEntity_Quad_Triangle  ] = nbTria;
+    aResVec[SMDSEntity_Quad_Quadrangle] = nbQuads;
+  }
+  else
+  {
+    aResVec[SMDSEntity_Triangle  ] = nbTria;
+    aResVec[SMDSEntity_Quadrangle] = nbQuads;
   }
+  aResVec[SMDSEntity_Node] = nbNodes;
 
-  if(nb0d>0) {
-    aResVec[0] = nb0d;
-    if(isQuadratic) {
-      aResVec[SMDSEntity_Quad_Triangle] = nb2d_tria;
-      aResVec[SMDSEntity_Quad_Quadrangle] = nb2d_quad;
+  if ( linSide1 )
+  {
+    // evaluation for linSides
+    vector<int> aResVec(SMDSEntity_Last, 0);
+    if ( isQuadratic ) {
+      aResVec[SMDSEntity_Node     ] = 2 * ( layerPositions.size() - 1 ) + 1;
+      aResVec[SMDSEntity_Quad_Edge] = layerPositions.size() - 1;
     }
     else {
-      aResVec[SMDSEntity_Triangle] = nb2d_tria;
-      aResVec[SMDSEntity_Quadrangle] = nb2d_quad;
+      aResVec[SMDSEntity_Node] = layerPositions.size() - 2;
+      aResVec[SMDSEntity_Edge] = layerPositions.size() - 1;
+    }
+    sm = aMesh.GetSubMesh( linSide1->Edge(0) );
+    aResMap[sm] = aResVec;
+    if ( linSide2 )
+    {
+      sm = aMesh.GetSubMesh( linSide2->Edge(0) );
+      aResMap[sm] = aResVec;
     }
-    return true;
   }
 
-  // invalid case
-  sm = aMesh.GetSubMesh(aShape);
-  SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
-  smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,
-                                        "Submesh can not be evaluated",this));
-  return false;
-
+  return true;
 }
 
 //================================================================================
@@ -1335,11 +1201,10 @@ bool StdMeshers_RadialQuadrangle_1D2D::IsApplicable( const TopoDS_Shape & aShape
   int nbFoundFaces = 0;
   for (TopExp_Explorer exp( aShape, TopAbs_FACE ); exp.More(); exp.Next(), ++nbFoundFaces )
   {
-    TopoDS_Edge CircEdge, LinEdge1, LinEdge2;
-    int nbe = analyseFace( exp.Current(), CircEdge, LinEdge1, LinEdge2 );
-    Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge ));
-    bool ok = ( nbe <= 3 && nbe >= 1 && !aCirc.IsNull() &&
-                isCornerInsideCircle( CircEdge, LinEdge1, LinEdge2 ));
+    StdMeshers_FaceSidePtr circSide, linSide1, linSide2;
+    int nbSides = analyseFace( exp.Current(), NULL, circSide, linSide1, linSide2 );
+    bool ok = ( 0 < nbSides && nbSides <= 3 &&
+                isCornerInsideCircle( circSide, linSide1, linSide2 ));
     if( toCheckAll  && !ok ) return false;
     if( !toCheckAll && ok  ) return true;
   }
index a234f04636b0dc9c4acd3186743c346c49b25510..7270cba40d28c67a3d7340c6c30c7a7709052eaa 100644 (file)
 #ifndef _SMESH_RadialQuadrangle_1D2D_HXX_
 #define _SMESH_RadialQuadrangle_1D2D_HXX_
 
-#include "SMESH_StdMeshers.hxx"
-
-#include "SMESH_Algo.hxx"
-
-#include <TopoDS_Edge.hxx>
+#include "StdMeshers_Quadrangle_2D.hxx"
 
 #include <vector>
 
 class StdMeshers_NumberOfLayers;
 class StdMeshers_LayerDistribution;
-class SMESH_MesherHelper;
-class gp_Pnt;
 
-class STDMESHERS_EXPORT StdMeshers_RadialQuadrangle_1D2D: public SMESH_2D_Algo
+/*!
+ * \brief Algorithm generating quadrangles on a full or a part of an elliptic face.
+ *        Elements around an ellipse center are triangles.
+ */
+
+class STDMESHERS_EXPORT StdMeshers_RadialQuadrangle_1D2D: public StdMeshers_Quadrangle_2D
 {
 public:
   StdMeshers_RadialQuadrangle_1D2D(int hypId, int studyId, SMESH_Gen* gen);
@@ -63,16 +62,14 @@ public:
 
 protected:
 
-  bool computeLayerPositions(const gp_Pnt&      p1,
-                             const gp_Pnt&      p2,
-                             const TopoDS_Edge& linEdge=TopoDS_Edge(),
-                             bool*              linEdgeComputed = 0);
+  int computeLayerPositions(StdMeshers_FaceSidePtr linSide,
+                            std::vector< double >& positions,
+                            int*                   nbEdgesComputed = 0,
+                            bool                   useHalf = false);
 
 
   const StdMeshers_NumberOfLayers*    myNbLayerHypo;
   const StdMeshers_LayerDistribution* myDistributionHypo;
-  SMESH_MesherHelper*                 myHelper;
-  std::vector< double >               myLayerPositions;
 };
 
 #endif
index 426467ef4351d3380656ef528ee70de52fc34016..45115e68dfdcac3239f33184f93351e92fb1e196 100644 (file)
@@ -108,7 +108,7 @@ class MonViewText(Ui_ViewExe, QDialog):
 
     def readFromStdOut(self) :
         a=self.monExe.readAllStandardOutput()
-        aa=unicode(a.data(),len(a))
+        aa=unicode(a.data())
         self.TB_Exe.append(aa)
         if "END_OF_MGSurfOpt" in aa:
           self.parent().enregistreResultat()
index 292bbe985d223b6f943cbb62302655030b51c7a5..20eea53c69511b767ef3f6a63d4e6275f25983fb 100755 (executable)
@@ -37,7 +37,7 @@ def YamsLct(context):
       os.environ['DISTENE_LICENSE_FILE']
   except:
       QMessageBox.warning(None,"Products","""\
-Distene's product MeshGem SurfOpt (formerly Yams) is not installed.
+Distene's product MeshGem SurfOpt is not installed.
 required environment variable:
 DISTENE_LICENSE_FILE='.../dlim8.var.sh'""")
       return
index 52a886f3c8bfc48b6d9d1806e765da66cffdb1ae..3c81d72fa64e98559c8ec7cfc85c354440c5f0da 100644 (file)
@@ -42,11 +42,11 @@ except:
 
 try:
   from yamsplug_plugin import YamsLct
-  salome_pluginsmanager.AddFunction('ReMesh with MGSurfOpt ( formerly Yams )',
+  salome_pluginsmanager.AddFunction('ReMesh with MGSurfOpt',
                                     'Run Yams',
                                     YamsLct)
 except:
-  salome_pluginsmanager.logger.info('ERROR: MGSurfOpt (Yams) plug-in is unavailable')
+  salome_pluginsmanager.logger.info('ERROR: MGSurfOpt plug-in is unavailable')
   pass
 
 try: