]> SALOME platform Git repositories - plugins/ghs3dplugin.git/commitdiff
Salome HOME
#17784 [EDF] MESH-GEMS-2.9.6 Meshers options
authoreap <eap@opencascade.com>
Wed, 9 Oct 2019 12:45:33 +0000 (15:45 +0300)
committereap <eap@opencascade.com>
Wed, 9 Oct 2019 12:45:33 +0000 (15:45 +0300)
20 files changed:
doc/salome/gui/GHS3DPLUGIN/images/ghs3d_parameters_advanced.png
doc/salome/gui/GHS3DPLUGIN/images/ghs3d_parameters_basic.png
doc/salome/gui/GHS3DPLUGIN/input/ghs3d_hypo.doc
doc/salome/gui/GHS3DPLUGIN/input/optimization_hypo.doc
idl/GHS3DPlugin_Algorithm.idl
src/GHS3DPlugin/GHS3DPluginBuilder.py
src/GHS3DPlugin/GHS3DPlugin_Hypothesis.cxx
src/GHS3DPlugin/GHS3DPlugin_Hypothesis.hxx
src/GHS3DPlugin/GHS3DPlugin_Hypothesis_i.cxx
src/GHS3DPlugin/GHS3DPlugin_Hypothesis_i.hxx
src/GHS3DPlugin/GHS3DPlugin_OptimizerHypothesis.cxx
src/GUI/CMakeLists.txt
src/GUI/GHS3DPluginGUI_AdvWidget.cxx
src/GUI/GHS3DPluginGUI_AdvWidget_QTD.ui
src/GUI/GHS3DPluginGUI_Dlg.h
src/GUI/GHS3DPluginGUI_HypothesisCreator.cxx
src/GUI/GHS3DPluginGUI_HypothesisCreator.h
src/GUI/GHS3DPluginGUI_TreeWidget.cxx [new file with mode: 0644]
src/GUI/GHS3DPluginGUI_TreeWidget.h [new file with mode: 0644]
src/GUI/GHS3DPlugin_msg_en.ts

index 4372e3cc5458cec803efcd51ff0416d00d4778b6..a0bca6ada0636b84e2c24f4269055c1850a58092 100644 (file)
Binary files a/doc/salome/gui/GHS3DPLUGIN/images/ghs3d_parameters_advanced.png and b/doc/salome/gui/GHS3DPLUGIN/images/ghs3d_parameters_advanced.png differ
index 8963bd09e7a266281b0d835cf4397b971a8728bc..3ecb4f2c4c8321af4e8d2c9c8342e8ad5ac848c3 100644 (file)
Binary files a/doc/salome/gui/GHS3DPLUGIN/images/ghs3d_parameters_basic.png and b/doc/salome/gui/GHS3DPLUGIN/images/ghs3d_parameters_basic.png differ
index 9e29026dac10e829abd65a1f3ab522603530b632..af2ab1915948d988c9c7460a27cff458b0f9e95b 100644 (file)
@@ -17,15 +17,6 @@ To get a license, visit http://www.meshgems.com/meshgems-products.html
 - <b>Name</b> - allows to define the name of the hypothesis (MG-Tetra
 Parameters by default).
 
-- <b>Mesh holes</b> - if checked, the algorithm will 
-create mesh in the holes inside a solid shape, else only the outermost
-shape will be meshed. Volumic elements created within holes are bound
-to the solid.
-
-- <b>Make groups of domains</b> - if checked, the algorithm will
-create groups of just generated elements corresponding to each mesh
-domain.<br>
-
 - <b>Optimization level</b> - allows choosing the required
 optimization level (higher level of optimization provides better mesh,
 but can be time-consuming):
@@ -40,12 +31,168 @@ but can be time-consuming):
 
   - strong
 
+- <b>Minimal size</b> - sets the minimum edge size in the generated mesh.
+
+- <b>Maximal size</b> - sets the maximum edge size in the generated mesh.
+
+- <b>Volumic gradation</b> - Defines the volumic ratio between 2 consecutive elements.
+WARNING: Changing the default value of this parameter may dramatically
+decrease the quality of the resulting mesh.
+
+- <b>Use volume proximity</b> - activates consideration of distance between opposite surfaces.
+
+    - <b>Number of layers</b> - asks for at least given number of layers of tets between opposite surfaces.
+
+- <b>Mesh holes</b> - if checked, the algorithm will 
+create mesh in the holes inside a solid shape, else only the outermost
+shape will be meshed. Volumic elements created within holes are bound
+to the solid.
+
+- <b>Make groups of domains</b> - if checked, the algorithm will
+create groups of just generated elements corresponding to each mesh
+domain.<br>
+
 \ref ghs3d_top "Back to top"
 
 \section ghs3d_advanced_parameters Advanced parameters
 
 \image html ghs3d_parameters_advanced.png
 
+\subsection advanced_meshing_options Advanced meshing options
+
+Advanced page tab expose mostly useful advanced options. Initially,
+default values of the options are displayed and they are not
+modifiable. If an option is activated using a check-box, its value
+becomes modifiable.
+
+<b>Add option</b> button adds a line to the table where you can type
+an option and its value as text. A check box in the first column
+activates/deactivates the option of the current row. A deactivated
+option will be erased upon pressing \a Ok.
+
+- <b>Gradation on skin</b> - This option set or not the gradation
+  value on the initial size of the skin vertices.
+
+     - <b>no</b> the gradation is not applied on the skin vertices.
+       In this case the initial size of a vertex is the average edges 
+       lenght which belong the vertex.
+
+     - <b>yes</b> the gradation is applied on the skin vertices. In
+       this case the initial size of a vertex is the average edges
+       lenght which belong the vertex multiplied by the gradation.
+
+
+- <b>Boundary regeneration</b> - defines the boundary regeneration mode.
+  MeshGems-Tetra uses alternative strategies for boundary regeneration.
+
+     - <b>standard</b> means that the standard boundary regeneration algorithm is used.
+
+     - <b>safe</b> means that various methods are tried as long as
+        the regeneration phase fails (including the alternate boundary
+        recovery mode), can be time consuming and can fail in very
+        difficult cases.
+
+     - <b>recovery</b> means that the alternate boundary recovery
+       version is activated. Check <b>Using MeshGems-Tetra with the
+       boundary recovery module</b> chapter of MG-Tetra User Manual.
+
+- <b>Force maximum edge size</b> - This option can be used to force
+  the desired maximum edge size in the generated mesh given by
+  the <b>Max Size</b> parameter. The default value is no, meaning that
+  the maximum edge length can be greater than the given value of
+  the <b>Max Size</b> parameter.
+
+- <b>Force quadratic mesh</b> - This option permits to write or not an
+  output mesh file in case of negative Jacobians when generating a
+  quadratic mesh. Refer to section 4.6.3 for more details. 
+
+     - <b>no</b> means that no output is written (this is the default);
+     - <b>yes</b> means that an output is written even in case of negative Jacobians.
+
+- <b>Respect surface mesh</b> - This option forbids or not the
+  correction of input triangles and enforced edges mid-nodes to make
+  the element Jacobian strictly positive when generating a quadratic
+  mesh.
+
+     - <b>yes</b> means that the input triangles and edges mid-nodes
+       are unchanged, the correction of nodes is only applied in the volume.
+
+     - <b>no</b> means that the input triangles and edges mid-nodes
+       can be moved. The correction of nodes is applied in the volume
+       and the mid-nodes correction can be applied on the input
+       triangles and edges mid-nodes. The corrected surface mid-nodes
+       are approximated on the surface first, or put on the linear
+       edges; The corrected edges mid-nodes can be put on the linear
+       edges.
+
+- <b>Max number of errors</b> - the error messages will be printed up
+  to a given maximum number of errors. At least 1 error is printed and
+  at most 100 errors are printed to prevent infinite loops.
+
+- <b>Maximal number of threads</b> - This allows to set the maximal
+  number of threads the software can use in parallel for the
+  multi-threading optimization mode.
+
+- <b>No central point</b> - <b>yes</b> prevents adding an internal point at the
+   centre of gravity of the bounding box that MeshGems-Tetra uses by
+   default in order to speed up and to simplify the meshing
+   process. This option can be particularly useful to:
+
+      -  generate a volume mesh without internal points at all;
+
+      - in some rare cases, help the boundary regeneration phase when
+        it failed with the standard options (for example when one
+        dimension of the domain is large compared to the other two with
+        a ratio of 20 or more). Use this option when the boundary
+        regeneration failed with the standard parameters and before
+        using the recovery version.
+
+- <b>Optimise worst elements</b> - Applies an optimization processing
+  to improve the worst quality elements whenever possible. 
+
+- <b>Mode of pthreads</b> - This option sets the optimization mode
+  when using multithread capabilities. By default, this option is not
+  activated which means that only a sequential optimization is
+  performed.
+
+  - <b>safe</b> is slower than the sequential mode, but the
+    quality of the mesh can only improve;
+
+  - <b>aggressive</b> - is faster than the sequential mode, but
+    the quality of the resulting mesh may altered compared to the sequential mode.
+
+- <b>Rectify jacobian</b> - This option activates correction of some
+  nodes so as to make the Jacobian of element strictly positive when
+  generating a quadratic mesh.
+
+- <b>Sliver angle</b> - This options can be used to specify to
+  MeshGems-Tetra what is considered as a sliver and what is not. The
+  user has the possibility to specify an angle (in degrees), which
+  caracterizes a sliver : any tetrahedron which has at least an angle
+  below this value will be considered as a sliver.
+
+- <b>Remove overconstrained tetrahedra</b> - This option can be used
+  to only split the tetrahadra which have at least two facets that
+  belong to the surface mesh. It will not split the overconstrained
+  edges in the mesh. The overconstrained tetrahedra are splitting,
+  whenever possible, which ensures that no tetrahedron has no more
+  than one boundary facet.
+
+  - <b>no</b> means that no correction is applied;
+
+  - <b>yes</b> means that the correction is applied after mesh generation;
+
+  - <b>only</b> means only correction is applied to an existing mesh.
+
+- <b>Target quality</b> - Sets the desired maximum target of worst
+  quality acceptable for the volume mesh used during optimisation
+  phase. When defined, an optimization processing is applied to
+  improve the quality until the given target is reached whenever
+  possible. By default, this option is not activated which means that
+  only the standard optimisations are performed (the quality target is
+  the target quality computed by the program).
+
 \subsection memory_settings Memory settings
 
 - <b>Maximum memory size</b> - launches MG-Tetra software with
@@ -86,54 +233,6 @@ is enabled (there must be a log file to delete it) and <b>Keep all working files
 of MG-Tetra software, while usually these files are removed after the
 launch of the mesher. The log file (if any) is also kept if this option is checked.
 
-\subsection advanced_meshing_options Advanced meshing options
-
-- <b>Create new nodes</b> - if this option is checked off, MG-Tetra
-tries to create tetrahedrons using only the nodes of the 2D mesh.
-
-- <b>Remove the initial central point</b> MG-Tetra adds an internal point 
-at the gravity center of the bounding box to speed up and to simplify 
-the meshing process. However, it is possible to refrain from creating 
-this point by using the command line option -no initial central point. This can be
-particularly useful to generate a volume mesh without internal points at all and in some rare cases
-at the boundary regeneration phase when it is impossible to proceed
-with the standard options
-(for example, when one dimension of the domain is more than 20 times greater than the other two).
-Use this option if the boundary regeneration has failed with the standard parameters and before using
-the recovery version (command line option -C).
-Note: when using this option, the speed of the meshing process may
-decrease, and the quality may change.
-Note: the boundary regeneration may fail with this option, in some rare cases.
-
-- <b>Use boundary recovery version</b> - enables using a
-boundary recovery module which tries to
-create volume meshes starting from very poor quality surface meshes
-(almost flat triangles on the surface, high density propagation,
-extreme aspect ratios, etc.) which fails with the standard version. The
-resulting volume mesh will however most likely have a very poor
-quality (poor aspect ratio of elements, tetrahedra with a very small
-positive volume).
-
-- <b>Use FEM correction</b> - Applies finite-element correction by 
-replacing overconstrained elements where it is possible. At first the process 
-slices the overconstrained edges and at second the overconstrained 
-facets. This ensures that there are no edges with two boundary
-vertices and that there are no facets with three boundary vertices. MG-Tetra gives the initial 
-and final overconstrained edges and facets. It also gives the facets
-which have three edges on the boundary.
-Note: when using this option, the speed of the meshing process may 
-decrease, quality may change, and the smallest volume may be smaller.
-By default, the FEM correction is not used.
-
-- <b>Volumic gradation</b> - Defines the volumic ratio between 2 consecutive elements.
-WARNING: Changing the default value of this parameter may dramatically decrease the quality of the resulting mesh.
-
-- A table at the page bottom allows to input in the command line any text
-for MG-Tetra, for example, advanced options. <br> 
-<b>Add option</b> - adds a line to the table where you can type an option and its value as text.
-A check box in the first column activates/deactivates the option of the current row. A deactivated option will be erased upon pressing \a Ok.
-
-
 \ref ghs3d_top "Back to top"
 
 \section ghs3d_enforced_vertices Enforced vertices
index e1868b526d107acbc6ba0d17ad2f74f53e16c69b..a87bc556c2d0bbe04d5eab025cc598eb540c7ca8 100644 (file)
@@ -57,11 +57,11 @@ elements as much as possible.
 \ref optimization_top "Back to top"
 
 
-\section ghs3d_advanced_parameters Advanced parameters
+\section mgtetra_optim_advanced_parameters Advanced parameters
 
 \image html mgtetra_optim_adv_params.png
 
-\subsection memory_settings Memory settings
+\subsection mgtetra_optim_memory_settings Memory settings
 
 - <b>Initial memory size</b> - starts MG-Tetra software with
 the specified amount of work space, in Mbytes. If this option is checked off, the
@@ -71,7 +71,7 @@ software will be started with 100 Megabytes of working space.
 work space limited to the specified amount of RAM, in Mbytes. If this option is
 checked off, the software will be launched with 7O% of the total RAM space.
 
-\subsection log Logs and debug
+\subsection mgtetra_optim_log Logs and debug
 
 - <b>Working directory</b> - allows defining the folder for input and output
 files of MG-Tetra software, which are the files starting with "GHS3D_" prefix.
@@ -104,7 +104,7 @@ files of MG-Tetra software, while usually these files are removed
 after the launch of the mesher. The log file (if any) is also kept if
 this option is checked.
 
-\subsection advanced_meshing_options Advanced meshing options
+\subsection mgtetra_optim_advanced_meshing_options Advanced meshing options
 
 - A table allows to input in the command line any text for MG-Tetra,
 for example, advanced options.<br> 
index bae1d03f987518509f27d7b8540557cb3b70edcb..752f9e69e5d21d52f931d0c2d972112e95cfbb43 100644 (file)
@@ -32,6 +32,8 @@
  */
 module GHS3DPlugin
 {
+  typedef sequence<string> string_array;
+
   typedef sequence<double,3> TCoords;
   struct GHS3DEnforcedVertex {
     string name;
@@ -71,6 +73,26 @@ module GHS3DPlugin
      */
     void SetToMeshHoles(in boolean toMesh);
     boolean GetToMeshHoles();
+    /*!
+     *Set lower boundary of mesh element size
+     */
+    void SetMinSize(in double theMinSize);
+    double GetMinSize();
+    /*!
+     *Set upper boundary of mesh element size
+     */
+    void SetMaxSize(in double theMaxSize);
+    double GetMaxSize();
+    /*!
+     *  Activate/deactivate volume proximity computation
+     */
+    void SetVolumeProximity( in boolean toUse );
+    boolean GetVolumeProximity();
+    /*!
+     * Set number of surface element layers to be generated due to volume proximity
+     */
+    void SetNbVolumeProximityLayers( in short nbLayers );
+    short GetNbVolumeProximityLayers();
     /*!
      * To make groups of volumes of different domains when mesh is generated from skin.
      * Default is to make groups.
@@ -142,13 +164,6 @@ module GHS3DPlugin
      */
     void SetToRemoveCentralPoint(in boolean toRemove);
     boolean GetToRemoveCentralPoint();
-    /*!
-     * To set hiden/undocumented/advanced options
-     */
-    void SetAdvancedOption(in string option);
-    string GetAdvancedOption();
-    void SetTextOption(in string option); // obsolete
-    string GetTextOption();
     /*!
      * To define the volumic gradation
      */
@@ -164,6 +179,39 @@ module GHS3DPlugin
     */
     void SetRemoveLogOnSuccess(in boolean removeLogOnSuccess);
     boolean GetRemoveLogOnSuccess();
+    /*!
+     * Set advanced option value
+     */
+    void SetOptionValue(in string optionName,
+                        in string optionValue) raises (SALOME::SALOME_Exception);
+    string GetOptionValue(in string optionName) raises (SALOME::SALOME_Exception);
+    void UnsetOption(in string optionName);
+    /*!
+     * Adds custom advanced option and its value
+     */
+    void SetAdvancedOption(in string optionsAndValues) // in a form "option_1 v1 option_2 v2'"
+      raises (SALOME::SALOME_Exception);
+    string GetAdvancedOption();
+    void AddOption(in string optionName, in string optionValue);
+    string GetOption(in string optionName);
+    void SetTextOption(in string option); // obsolete
+    string GetTextOption(); // obsolete
+    /*!
+     * Return array of strings each of which is option name concatenated
+     * with option value devided by semicolon - "option_name:option_value:option_type".
+     * Option value is empty if an option is not set.
+     * option_type: 1 if user-define, 0 if default
+     * Note: the method is mostly for interaction with GUI.
+     */
+    string_array GetOptionValues();
+    string_array GetAdvancedOptionValues();
+    /*!
+     * Set option values each in the form "option_name[:option_value][:option_type]".
+     * Note: the method is mostly for interaction with GUI.
+     */
+    void SetOptionValues(in string_array options) raises (SALOME::SALOME_Exception);
+    void SetAdvancedOptionValues(in string_array options);
+
     /*!
      * To set an enforced vertex
      */
@@ -201,6 +249,11 @@ module GHS3DPlugin
     * Set/get/unset an enforced vertex (private method for GUI)
     */
     boolean p_SetEnforcedMesh(in SMESH::SMESH_IDSource theSource, in SMESH::ElementType elementType, in string name, in string groupName) raises (SALOME::SALOME_Exception);
+
+    // GUI methods
+    double GetMaxSizeDefault();
+    double GetMinSizeDefault();
+    void SetMinMaxSizeDefault( in double theMinSize, in double theMaxSize );
   };
 
   /*!
index c1b710f6981b1c91326da3506abc61ad7255dee2..1c58b892c18ebf8cfa166410f576e0383f6d0f30 100644 (file)
@@ -88,6 +88,30 @@ class GHS3D_Algorithm(Mesh_Algorithm):
             pass
         return self.params
 
+    ## Set lower boundary of mesh element size
+    #  Set it to zero to deactivate this option
+    def SetMinSize(self, theMinSize):
+        self.Parameters().SetMinSize(theMinSize)
+        return
+
+    ## Set upper boundary of mesh element size
+    #  Set it to zero to deactivate this option
+    def SetMaxSize(self, theMaxSize):
+        self.Parameters().SetMaxSize(theMaxSize)
+        return
+
+    ## Activate/deactivate volume proximity computation
+    #
+    def SetVolumeProximity(self, toUse ):
+        self.Parameters().SetVolumeProximity(toUse)
+        return
+
+    ## Set number of surface element layers to be generated due to volume proximity
+    #
+    def SetNbVolumeProximityLayers(self, nbLayers ):
+        self.Parameters().SetNbVolumeProximityLayers(nbLayers)
+        return
+
     ## To mesh "holes" in a solid or not. Default is to mesh.
     #  @param toMesh "mesh holes" flag value
     def SetToMeshHoles(self, toMesh):
@@ -264,15 +288,22 @@ class GHS3D_Algorithm(Mesh_Algorithm):
             pass
         pass
 
-    ## Sets command line option as text.
-    #  @param option command line option
-    def SetTextOption(self, option):
-        self.Parameters().SetAdvancedOption(option)
+    ## Set advanced option value
+    #  @param optionName option name
+    #  @param optionValue option value
+    def SetOptionValue(self, optionName, optionValue):
+        self.Parameters().SetOptionValue( optionName, optionValue )
         pass
     
     ## Sets command line option as text.
+    #  @param optionAndValue command line option in a form "option value"
+    def SetAdvancedOption(self, optionAndValue):
+        self.Parameters().SetAdvancedOption(optionAndValue)
+        pass
+    
+    ## OBSOLETE Sets command line option as text.
     #  @param option command line option
-    def SetAdvancedOption(self, option):
+    def SetTextOption(self, option):
         self.Parameters().SetAdvancedOption(option)
         pass
     
index 892aa701dcfb683be071725bd8ba15964be0921b..705c3e4da4e9bb096d51bd6710e2283117ec4891 100644 (file)
 
 using namespace std;
 
+namespace
+{
+  struct GET_DEFAULT // struct used to get default value from GetOptionValue()
+  {
+    bool isDefault;
+    operator bool* () { return &isDefault; }
+  };
+}
+
 //=======================================================================
 //function : GHS3DPlugin_Hypothesis
 //=======================================================================
@@ -57,21 +66,84 @@ GHS3DPlugin_Hypothesis::GHS3DPlugin_Hypothesis(int hypId, SMESH_Gen * gen)
     myLogInStandardOutput(DefaultStandardOutputLog()),
     myRemoveLogOnSuccess( DefaultRemoveLogOnSuccess() ),
     myGradation(DefaultGradation()),
-    _enfVertexList(DefaultGHS3DEnforcedVertexList()),
-    _enfVertexCoordsSizeList(DefaultGHS3DEnforcedVertexCoordsValues()),
-    _enfVertexEntrySizeList(DefaultGHS3DEnforcedVertexEntryValues()),
-    _coordsEnfVertexMap(DefaultCoordsGHS3DEnforcedVertexMap()),
-    _geomEntryEnfVertexMap(DefaultGeomEntryGHS3DEnforcedVertexMap()),
-    _enfMeshList(DefaultGHS3DEnforcedMeshList()),
-    _entryEnfMeshMap(DefaultEntryGHS3DEnforcedMeshListMap()),
-    _enfNodes(TIDSortedNodeGroupMap()),
-    _enfEdges(TIDSortedElemGroupMap()),
-    _enfTriangles(TIDSortedElemGroupMap()),
-    _nodeIDToSizeMap(DefaultID2SizeMap()),
-    _groupsToRemove(DefaultGroupsToRemove())
+    myUseVolumeProximity(DefaultUseVolumeProximity()),
+    myNbVolumeProximityLayers(DefaultNbVolumeProximityLayers()),
+    myMinSize(0),
+    myMinSizeDefault(0),
+    myMaxSize(0),
+    myMaxSizeDefault(0)
 {
   _name = GetHypType();
   _param_algo_dim = 3;
+
+  const char* boolOptionNames[] = { "no_initial_central_point",                          // no
+                                    "force_max_size",                                    // no
+                                    "apply_gradation_on_skin_vertex_sizes",              // yes
+                                    "optimise_worst_elements",                           // no
+                                    "force_output_quadratic_mesh",                       // no
+                                    "rectify_jacobian",                                  // yes
+                                    "jacobian_rectification_respect_input_surface_mesh", // yes
+                                    "" // mark of end
+  };
+  const char* intOptionNames[] = { "max_number_of_errors_printed", // 1
+                                   "max_number_of_threads",        // 4
+                                   "" // mark of end
+  };
+  const char* doubleOptionNames[] = { "target_quality",  // 0
+                                      "sliver_angle",    // 5
+                                      "" // mark of end
+  };
+  const char* charOptionNames[] = { "pthreads_mode",                    // ""
+                                    "boundary_regeneration",            // standard
+                                    "split_overconstrained_tetrahedra", // no
+                                    "" // mark of end
+  };
+
+  int i = 0;
+  while (boolOptionNames[i][0])
+  {
+    _boolOptions.insert( boolOptionNames[i] );
+    _option2value[boolOptionNames[i++]].clear();
+  }
+  i = 0;
+  while (intOptionNames[i][0])
+    _option2value[intOptionNames[i++]].clear();
+  
+  i = 0;
+  while (doubleOptionNames[i][0]) {
+    _doubleOptions.insert(doubleOptionNames[i]);
+    _option2value[doubleOptionNames[i++]].clear();
+  }
+  i = 0;
+  while (charOptionNames[i][0]) {
+    _charOptions.insert(charOptionNames[i]);
+    _option2value[charOptionNames[i++]].clear();
+  }
+
+  // default values to be used while MG meshing
+
+  _defaultOptionValues["no_initial_central_point"                         ] = "no";
+  _defaultOptionValues["force_max_size"                                   ] = "no";
+  _defaultOptionValues["apply_gradation_on_skin_vertex_sizes"             ] = "yes";
+  _defaultOptionValues["optimise_worst_elements"                          ] = "no";
+  _defaultOptionValues["force_output_quadratic_mesh"                      ] = "no";
+  _defaultOptionValues["rectify_jacobian"                                 ] = "yes";
+  _defaultOptionValues["jacobian_rectification_respect_input_surface_mesh"] = "yes";
+  _defaultOptionValues["max_number_of_errors_printed"                     ] = "1";
+  _defaultOptionValues["max_number_of_threads"                            ] = "4";
+  _defaultOptionValues["target_quality"                                   ] = "";//NoValue();
+  _defaultOptionValues["sliver_angle"                                     ] = "5";
+  _defaultOptionValues["pthreads_mode"                                    ] = "";//NoValue();
+  _defaultOptionValues["boundary_regeneration"                            ] = "standard";
+  _defaultOptionValues["split_overconstrained_tetrahedra"                 ] = "no";
+
+#ifdef _DEBUG_
+  // check validity of option names of _defaultOptionValues
+  TOptionValues::iterator n2v = _defaultOptionValues.begin();
+  for ( ; n2v != _defaultOptionValues.end(); ++n2v )
+    ASSERT( _option2value.count( n2v->first ));
+  ASSERT( _option2value.size() == _defaultOptionValues.size() );
+#endif
 }
 
 //=======================================================================
@@ -92,11 +164,17 @@ void GHS3DPlugin_Hypothesis::SetToMeshHoles(bool toMesh)
 
 bool GHS3DPlugin_Hypothesis::GetToMeshHoles(bool checkFreeOption) const
 {
-  if (checkFreeOption && !myTextOption.empty()) {
-    if ( myTextOption.find("--components all"))
-      return true;
-    if ( myTextOption.find("--components outside_components"))
-      return false;
+  if ( checkFreeOption )
+  {
+    std::string optionName = "components";
+    TOptionValues::const_iterator op_val = _customOption2value.find(optionName);
+    if ( op_val != _customOption2value.end())
+    {
+      if ( op_val->second.find("all"))
+        return true;
+      if ( op_val->second.find("outside_components"))
+        return false;
+    }
   }
   return myToMeshHoles;
 }
@@ -330,10 +408,8 @@ bool GHS3DPlugin_Hypothesis::GetFEMCorrection() const
 
 void GHS3DPlugin_Hypothesis::SetToRemoveCentralPoint(bool toRemove)
 {
-  if ( myToRemoveCentralPoint != toRemove ) {
-    myToRemoveCentralPoint = toRemove;
-    NotifySubMeshesHypothesisModification();
-  }
+  SetOptionValue( "no_initial_central_point", toRemove ? "yes" : "no" );
+  myToRemoveCentralPoint = toRemove;
 }
 
 //=======================================================================
@@ -351,9 +427,16 @@ bool GHS3DPlugin_Hypothesis::GetToRemoveCentralPoint() const
 
 void GHS3DPlugin_Hypothesis::SetAdvancedOption(const std::string& option)
 {
-  if ( myTextOption != option ) {
-    myTextOption = option;
-    NotifySubMeshesHypothesisModification();
+  size_t wsPos = option.find(' ');
+  if ( wsPos == string::npos )
+  {
+    SetOptionValue( option, "" );
+  }
+  else
+  {
+    std::string opt( option, 0, wsPos );
+    std::string val( option, wsPos + 1 );
+    SetOptionValue( opt, val );
   }
 }
 
@@ -363,7 +446,23 @@ void GHS3DPlugin_Hypothesis::SetAdvancedOption(const std::string& option)
 
 std::string GHS3DPlugin_Hypothesis::GetAdvancedOption() const
 {
-  return myTextOption;
+  SMESH_Comment txt;
+
+  TOptionValues::const_iterator o2v = _option2value.begin();
+  for ( ; o2v != _option2value.end(); ++o2v )
+    if ( !o2v->second.empty() )
+    {
+      if ( !txt.empty() )
+        txt << " ";
+      txt << o2v->first << " " << o2v->second;
+    }
+  for ( o2v = _customOption2value.begin(); o2v != _customOption2value.end(); ++o2v )
+  {
+    if ( !txt.empty() )
+      txt << " ";
+    txt << o2v->first << " " << o2v->second;
+  }
+  return txt;
 }
 
 //=======================================================================
@@ -387,6 +486,46 @@ double GHS3DPlugin_Hypothesis::GetGradation() const
   return myGradation;
 }
 
+//=============================================================================
+void GHS3DPlugin_Hypothesis::SetMinSize(double theMinSize)
+{
+  if ( theMinSize != myMinSize )
+  {
+    myMinSize = theMinSize;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+void GHS3DPlugin_Hypothesis::SetMaxSize(double theMaxSize)
+{
+  if ( theMaxSize != myMaxSize )
+  {
+    myMaxSize = theMaxSize;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+void GHS3DPlugin_Hypothesis::SetUseVolumeProximity( bool toUse )
+{
+  if ( myUseVolumeProximity != toUse )
+  {
+    myUseVolumeProximity = toUse;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+void GHS3DPlugin_Hypothesis::SetNbVolumeProximityLayers( int nbLayers )
+{
+  if ( myNbVolumeProximityLayers != nbLayers )
+  {
+    myNbVolumeProximityLayers = nbLayers;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
 //=======================================================================
 //function : SetStandardOutputLog
 //=======================================================================
@@ -983,15 +1122,6 @@ bool GHS3DPlugin_Hypothesis::DefaultToRemoveCentralPoint()
   return false;
 }
 
-//=======================================================================
-//function : DefaultGradation
-//=======================================================================
-
-double GHS3DPlugin_Hypothesis::DefaultGradation()
-{
-  return 1.05;
-}
-
 //=======================================================================
 //function : DefaultStandardOutputLog
 //=======================================================================
@@ -1030,11 +1160,11 @@ std::ostream & GHS3DPlugin_Hypothesis::SaveTo(std::ostream & save)
   save << (int)myToRemoveCentralPoint         << " ";
   save << myGradation                         << " ";
   save << myToMakeGroupsOfDomains             << " ";
-  if (!myTextOption.empty()) {
-    save << "__OPTIONS_BEGIN__ ";
-    save << myTextOption                      << " ";
-    save << "__OPTIONS_END__ ";
-  }
+  // if (!myTextOption.empty()) {
+  //   save << "__OPTIONS_BEGIN__ ";
+  //   save << myTextOption                      << " ";
+  //   save << "__OPTIONS_END__ ";
+  // }
   
 
   TGHS3DEnforcedVertexList::iterator it  = _enfVertexList.begin();
@@ -1104,6 +1234,25 @@ std::ostream & GHS3DPlugin_Hypothesis::SaveTo(std::ostream & save)
     }
     save << " "  << "__ENFORCED_MESHES_END__ ";
   }
+
+  // New options in 2.9.6 (issue #17784)
+
+  save << " " << myUseVolumeProximity;
+  save << " " << myNbVolumeProximityLayers;
+  save << " " << myMinSize;
+  save << " " << myMaxSize;
+  save << " " << myMinSizeDefault;
+  save << " " << myMaxSizeDefault;
+
+  save << " " << _option2value.size();
+  TOptionValues::iterator o2v = _option2value.begin();
+  for ( ; o2v != _option2value.end(); ++o2v )
+    save << " -" << o2v->first << " -" << o2v->second;
+  
+  save << " " << _customOption2value.size();
+  for ( o2v = _customOption2value.begin(); o2v != _customOption2value.end(); ++o2v )
+    save << " -" << o2v->first << " -" << o2v->second;
+
   return save;
 }
 
@@ -1226,15 +1375,15 @@ std::istream & GHS3DPlugin_Hypothesis::LoadFrom(std::istream & load)
       isOK = static_cast<bool>(load >> txt);
       if (isOK) {
         if (txt == "__OPTIONS_END__") {
-          if (!myTextOption.empty()) {
-            // Remove last space
-            myTextOption.erase(myTextOption.end()-1);
-          }
+          // if (!myTextOption.empty()) {
+          //   // Remove last space
+          //   myTextOption.erase(myTextOption.end()-1);
+          // }
           isOK = false;
           break;
         }
-        myTextOption += txt;
-        myTextOption += " ";
+        // myTextOption += txt;
+        // myTextOption += " ";
       }
     }
   }
@@ -1427,6 +1576,39 @@ std::istream & GHS3DPlugin_Hypothesis::LoadFrom(std::istream & load)
     } // while
   } // if
 
+  // New options in 2.9.6 (issue #17784)
+
+  if ( ! hasOptions && ! hasEnforcedVertices && ! hasEnforcedMeshes )
+    myUseVolumeProximity = ( separator == "1" );
+  else if ( static_cast<bool>( load >> i ))
+    myUseVolumeProximity = (bool) i;
+
+  if ( static_cast<bool>( load >> myNbVolumeProximityLayers ))
+  {
+    load >> myMinSize;
+    load >> myMaxSize;
+    load >> myMinSizeDefault;
+    load >> myMaxSizeDefault;
+
+    std::string option, value;
+    if ( static_cast<bool>( load >> i ) && i >= 0 )
+    {
+      for ( int nbRead = 0; nbRead < i; ++nbRead )
+      {
+        load >> option >> value;
+        _option2value[ std::string( option, 1 )] = std::string( value, 1 );
+      }
+    }
+    if ( static_cast<bool>( load >> i ) && i >= 0 )
+    {
+      for ( int nbRead = 0; nbRead < i; ++nbRead )
+      {
+        load >> option >> value;
+        _customOption2value[ std::string( option, 1 )] = std::string( value, 1 );
+      }
+    }
+  }
+
   return load;
 }
 
@@ -1450,6 +1632,11 @@ bool GHS3DPlugin_Hypothesis::SetParametersByDefaults(const TDefaults&  dflts,
                                                      const SMESH_Mesh* /*theMesh*/)
 {
   myToMakeGroupsOfDomains = ( !dflts._shape || dflts._shape->IsNull() );
+
+  double diagonal = dflts._elemLength * _gen->GetBoundaryBoxSegmentation();
+  myMinSizeDefault = 1e-3 * diagonal;
+  myMaxSizeDefault = diagonal / 5.;
+
   return true;
 }
 
@@ -1465,16 +1652,16 @@ std::string GHS3DPlugin_Hypothesis::CommandToRun(const GHS3DPlugin_Hypothesis* h
 {
   std::string cmd = GetExeName();
   // check if any option is overridden by hyp->myTextOption
-  bool max_memory   = hyp ? ( hyp->myTextOption.find("--max_memory")  == std::string::npos ) : true;
-  bool auto_memory   = hyp ? ( hyp->myTextOption.find("--automatic_memory")  == std::string::npos ) : true;
-  bool comp   = hyp ? ( hyp->myTextOption.find("--components")  == std::string::npos ) : true;
-  bool optim_level   = hyp ? ( hyp->myTextOption.find("--optimisation_level")  == std::string::npos ) : true;
-  bool no_int_points  = hyp ? ( hyp->myTextOption.find("--no_internal_points") == std::string::npos ) : true;
-  bool C   = hyp ? ( hyp->myTextOption.find("-C")  == std::string::npos ) : true;
-  bool verbose   = hyp ? ( hyp->myTextOption.find("--verbose")  == std::string::npos ) : true;
-  bool fem = hyp ? ( hyp->myTextOption.find("-FEM")== std::string::npos ) : true;
-  bool rem = hyp ? ( hyp->myTextOption.find("--no_initial_central_point")== std::string::npos ) : true;
-  bool gra = hyp ? ( hyp->myTextOption.find("-Dcpropa")== std::string::npos ) : true;
+  bool max_memory     = hyp ? !hyp->HasOptionDefined("max_memory")               : true;
+  bool auto_memory    = hyp ? !hyp->HasOptionDefined("automatic_memory")         : true;
+  bool comp           = hyp ? !hyp->HasOptionDefined("components")               : true;
+  bool optim_level    = hyp ? !hyp->HasOptionDefined("optimisation_level")       : true;
+  bool no_int_points  = hyp ? !hyp->HasOptionDefined("no_internal_points")       : true;
+  bool C              = hyp ? !hyp->HasOptionDefined("-C")                       : true;
+  bool verbose        = hyp ? !hyp->HasOptionDefined("verbose")                  : true;
+  bool gra            = hyp ? !hyp->HasOptionDefined("-Dcpropa")                 : true;
+  bool rem            = hyp ? !hyp->HasOptionDefined("no_initial_central_point") : true;
+  //bool fem            = hyp ? !hyp->HasOptionDefined("-FEM")                     : true;
 
   // if use boundary recovery version, few options are allowed
   bool useBndRecovery = !C;
@@ -1535,17 +1722,17 @@ std::string GHS3DPlugin_Hypothesis::CommandToRun(const GHS3DPlugin_Hypothesis* h
   }
 
   // boundary recovery version
-  if ( useBndRecovery ) {
-    cmd += " -C";
-  }
+  // if ( useBndRecovery ) {
+  //   cmd += " -C";
+  // }
 
   // to use FEM correction
-  if ( fem && hyp && hyp->myToUseFemCorrection) {
-    cmd += " -FEM";
-  }
+  // if ( fem && hyp && hyp->myToUseFemCorrection) {
+  //   cmd += " -FEM";
+  // }
 
   // to remove initial central point.
-  if ( rem && hyp && hyp->myToRemoveCentralPoint) {
+  if ( rem && hyp && hyp->myToRemoveCentralPoint ) {
     if ( forExecutable )
       cmd += " --no_initial_central_point";
     else
@@ -1553,16 +1740,65 @@ std::string GHS3DPlugin_Hypothesis::CommandToRun(const GHS3DPlugin_Hypothesis* h
   }
 
   // options as text
-  if ( hyp && !hyp->myTextOption.empty() ) {
-    cmd += " " + hyp->myTextOption;
+  // if ( hyp && !hyp->myTextOption.empty() ) {
+  //   cmd += " " + hyp->myTextOption;
+  // }
+
+  // min/max size
+  if ( hyp )
+  {
+    if ( hyp->GetMinSize() > 0 )
+      cmd += " --min_size " + SMESH_Comment( hyp->GetMinSize() );
+    if ( hyp->GetMaxSize() > 0 )
+      cmd += " --max_size " + SMESH_Comment( hyp->GetMaxSize() );
   }
 
   // to define volumic gradation.
-  if ( gra && hyp ) {
-    if ( forExecutable )
-      cmd += " -Dcpropa=" + SMESH_Comment( hyp->myGradation );
-    else
-      cmd += " --gradation " + SMESH_Comment( hyp->myGradation );
+  if ( gra && hyp )
+  {
+    cmd += " --gradation " + SMESH_Comment( hyp->myGradation );
+  }
+
+  if ( hyp )
+  {
+    // proximity
+    if ( hyp->GetUseVolumeProximity() )
+    {
+      cmd += " --volume_proximity_layers " + SMESH_Comment( hyp->GetNbVolumeProximityLayers() );
+    }
+
+    std::string option, value;
+    bool isDefault;
+    const TOptionValues* options[] = { & hyp->_option2value, & hyp->_customOption2value };
+    for ( int iOp = 0; iOp < 2; ++iOp )
+    {
+      TOptionValues::const_iterator o2v = options[iOp]->begin();
+      for ( ; o2v != options[iOp]->end(); ++o2v )
+      {
+        option = o2v->first;
+        value = hyp->GetOptionValue( option, &isDefault );
+
+        if ( isDefault )
+          continue;
+        if ( value.empty() )//value == NoValue() )
+        {
+          if ( hyp->_defaultOptionValues.count( option ))
+            continue; // non-custom option with no value
+          //value.clear();
+        }
+        if ( strncmp( "no", option.c_str(), 2 ) == 0 ) // options w/o values: --no_*
+        {
+          if ( !value.empty() && ToBool( value ) == false )
+            continue;
+          value.clear();
+        }
+        if ( option[0] != '-' )
+          cmd += " --";
+        else
+          cmd += " ";
+        cmd += option + " " + value;
+      }
+    }
   }
 
 #ifdef WIN32
@@ -1616,50 +1852,264 @@ std::string GHS3DPlugin_Hypothesis::GetExeName()
 
 GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexList GHS3DPlugin_Hypothesis::GetEnforcedVertices(const GHS3DPlugin_Hypothesis* hyp)
 {
-  return hyp ? hyp->_GetEnforcedVertices():DefaultGHS3DEnforcedVertexList();
+  return hyp ? hyp->_GetEnforcedVertices(): TGHS3DEnforcedVertexList();
 }
 
 GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues GHS3DPlugin_Hypothesis::GetEnforcedVerticesCoordsSize (const GHS3DPlugin_Hypothesis* hyp)
 {  
-  return hyp ? hyp->_GetEnforcedVerticesCoordsSize(): DefaultGHS3DEnforcedVertexCoordsValues();
+  return hyp ? hyp->_GetEnforcedVerticesCoordsSize(): TGHS3DEnforcedVertexCoordsValues();
 }
 
 GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexEntryValues GHS3DPlugin_Hypothesis::GetEnforcedVerticesEntrySize (const GHS3DPlugin_Hypothesis* hyp)
 {  
-  return hyp ? hyp->_GetEnforcedVerticesEntrySize(): DefaultGHS3DEnforcedVertexEntryValues();
+  return hyp ? hyp->_GetEnforcedVerticesEntrySize(): TGHS3DEnforcedVertexEntryValues();
 }
 
 GHS3DPlugin_Hypothesis::TCoordsGHS3DEnforcedVertexMap GHS3DPlugin_Hypothesis::GetEnforcedVerticesByCoords (const GHS3DPlugin_Hypothesis* hyp)
 {  
-  return hyp ? hyp->_GetEnforcedVerticesByCoords(): DefaultCoordsGHS3DEnforcedVertexMap();
+  return hyp ? hyp->_GetEnforcedVerticesByCoords(): TCoordsGHS3DEnforcedVertexMap();
 }
 
 GHS3DPlugin_Hypothesis::TGeomEntryGHS3DEnforcedVertexMap GHS3DPlugin_Hypothesis::GetEnforcedVerticesByEntry (const GHS3DPlugin_Hypothesis* hyp)
 {  
-  return hyp ? hyp->_GetEnforcedVerticesByEntry(): DefaultGeomEntryGHS3DEnforcedVertexMap();
+  return hyp ? hyp->_GetEnforcedVerticesByEntry(): TGeomEntryGHS3DEnforcedVertexMap();
 }
 
 GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap GHS3DPlugin_Hypothesis::GetEnforcedNodes(const GHS3DPlugin_Hypothesis* hyp)
 {
-  return hyp ? hyp->_GetEnforcedNodes():DefaultIDSortedNodeGroupMap();
+  return hyp ? hyp->_GetEnforcedNodes():TIDSortedNodeGroupMap();
 }
 
 GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap GHS3DPlugin_Hypothesis::GetEnforcedEdges(const GHS3DPlugin_Hypothesis* hyp)
 {
-  return hyp ? hyp->_GetEnforcedEdges():DefaultIDSortedElemGroupMap();
+  return hyp ? hyp->_GetEnforcedEdges():TIDSortedElemGroupMap();
 }
 
 GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap GHS3DPlugin_Hypothesis::GetEnforcedTriangles(const GHS3DPlugin_Hypothesis* hyp)
 {
-  return hyp ? hyp->_GetEnforcedTriangles():DefaultIDSortedElemGroupMap();
+  return hyp ? hyp->_GetEnforcedTriangles():TIDSortedElemGroupMap();
 }
 
 GHS3DPlugin_Hypothesis::TID2SizeMap GHS3DPlugin_Hypothesis::GetNodeIDToSizeMap(const GHS3DPlugin_Hypothesis* hyp)
 {
-  return hyp ? hyp->_GetNodeIDToSizeMap(): DefaultID2SizeMap();
+  return hyp ? hyp->_GetNodeIDToSizeMap(): TID2SizeMap();
 }
 
 GHS3DPlugin_Hypothesis::TSetStrings GHS3DPlugin_Hypothesis::GetGroupsToRemove(const GHS3DPlugin_Hypothesis* hyp)
 {
-  return hyp ? hyp->_GetGroupsToRemove(): DefaultGroupsToRemove();
+  return hyp ? hyp->_GetGroupsToRemove(): TSetStrings();
 }
+
+
+//=============================================================================
+void GHS3DPlugin_Hypothesis::SetOptionValue(const std::string& optionName,
+                                            const std::string& optionValue)
+  throw (std::invalid_argument)
+{
+  TOptionValues::iterator op_val = _option2value.find(optionName);
+  if (op_val == _option2value.end())
+  {
+    op_val = _customOption2value.find( optionName );
+    if ( op_val != _customOption2value.end() && op_val->second != optionValue )
+      NotifySubMeshesHypothesisModification();
+    _customOption2value[ optionName ] = optionValue;
+    return;
+  }
+
+  if (op_val->second != optionValue)
+  {
+    const char* ptr = optionValue.c_str();
+    // strip white spaces
+    while (ptr[0] == ' ')
+      ptr++;
+    int i = strlen(ptr);
+    while (i != 0 && ptr[i - 1] == ' ')
+      i--;
+    // check value type
+    bool typeOk = true;
+    std::string typeName;
+    if (i == 0) {
+      // empty string
+    } else if (_charOptions.count(optionName)) {
+      // do not check strings
+    } else if (_doubleOptions.count(optionName)) {
+      // check if value is double
+      ToDbl(ptr, &typeOk);
+      typeName = "real";
+    } else if (_boolOptions.count(optionName)) {
+      // check if value is bool
+      ToBool(ptr, &typeOk);
+      typeName = "bool";
+    } else {
+      // check if value is int
+      ToInt(ptr, &typeOk);
+      typeName = "integer";
+    }
+    if ( typeOk ) // check some specific values ?
+    {
+    }
+    if ( !typeOk )
+    {
+      std::string msg = "Advanced option '" + optionName + "' = '" + optionValue + "' but must be " + typeName;
+      throw std::invalid_argument(msg);
+    }
+    std::string value( ptr, i );
+    if ( _defaultOptionValues[ optionName ] == value )
+      value.clear();
+
+    op_val->second = value;
+
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+//! Return option value. If isDefault provided, it can be a default value,
+//  then *isDefault == true. If isDefault is not provided, the value will be
+//  empty if it equals a default one.
+std::string GHS3DPlugin_Hypothesis::GetOptionValue(const std::string& optionName,
+                                                   bool*              isDefault) const
+  throw (std::invalid_argument)
+{
+  TOptionValues::const_iterator op_val = _option2value.find(optionName);
+  if (op_val == _option2value.end())
+  {
+    op_val = _customOption2value.find(optionName);
+    if (op_val == _customOption2value.end())
+    {
+      std::string msg = "Unknown MG-Tetra option: <" + optionName + ">";
+      throw std::invalid_argument(msg);
+    }
+  }
+  std::string val = op_val->second;
+  if ( isDefault ) *isDefault = ( val.empty() );
+
+  if ( val.empty() && isDefault )
+  {
+    op_val = _defaultOptionValues.find( optionName );
+    if (op_val != _defaultOptionValues.end())
+      val = op_val->second;
+  }
+  return val;
+}
+
+
+//=============================================================================
+bool GHS3DPlugin_Hypothesis::HasOptionDefined( const std::string& optionName ) const
+{
+  bool isDefault = false;
+  try
+  {
+    GetOptionValue( optionName, &isDefault );
+  }
+  catch ( std::invalid_argument )
+  {
+    return false;
+  }
+  return !isDefault;
+}
+
+//=============================================================================
+void GHS3DPlugin_Hypothesis::ClearOption(const std::string& optionName)
+{
+  TOptionValues::iterator op_val = _customOption2value.find(optionName);
+  if (op_val != _customOption2value.end())
+   _customOption2value.erase(op_val);
+  else {
+    op_val = _option2value.find(optionName);
+    if (op_val != _option2value.end())
+      op_val->second.clear();
+  }
+}
+
+//=============================================================================
+GHS3DPlugin_Hypothesis::TOptionValues GHS3DPlugin_Hypothesis::GetOptionValues() const
+{
+  TOptionValues vals;
+  TOptionValues::const_iterator op_val = _option2value.begin();
+  for ( ; op_val != _option2value.end(); ++op_val )
+    vals.insert( make_pair( op_val->first, GetOptionValue( op_val->first, GET_DEFAULT() )));
+
+  return vals;
+}
+
+//================================================================================
+/*!
+ * \brief Converts a string to a bool
+ */
+//================================================================================
+
+bool GHS3DPlugin_Hypothesis::ToBool(const std::string& str, bool* isOk )
+  throw (std::invalid_argument)
+{
+  std::string s = str;
+  if ( isOk ) *isOk = true;
+
+  for ( size_t i = 0; i <= s.size(); ++i )
+    s[i] = tolower( s[i] );
+
+  if ( s == "1" || s == "true" || s == "active" || s == "yes" )
+    return true;
+
+  if ( s == "0" || s == "false" || s == "inactive" || s == "no" )
+    return false;
+
+  if ( isOk )
+    *isOk = false;
+  else {
+    std::string msg = "Not a Boolean value:'" + str + "'";
+    throw std::invalid_argument(msg);
+  }
+  return false;
+}
+
+//================================================================================
+/*!
+ * \brief Converts a string to a real value
+ */
+//================================================================================
+
+double GHS3DPlugin_Hypothesis::ToDbl(const std::string& str, bool* isOk )
+  throw (std::invalid_argument)
+{
+  if ( str.empty() ) throw std::invalid_argument("Empty value provided");
+
+  char * endPtr;
+  double val = strtod(&str[0], &endPtr);
+  bool ok = (&str[0] != endPtr);
+
+  if ( isOk ) *isOk = ok;
+
+  if ( !ok )
+  {
+    std::string msg = "Not a real value:'" + str + "'";
+    throw std::invalid_argument(msg);
+  }
+  return val;
+}
+
+//================================================================================
+/*!
+ * \brief Converts a string to a integer value
+ */
+//================================================================================
+
+int GHS3DPlugin_Hypothesis::ToInt(const std::string& str, bool* isOk )
+  throw (std::invalid_argument)
+{
+  if ( str.empty() ) throw std::invalid_argument("Empty value provided");
+
+  char * endPtr;
+  int val = (int)strtol( &str[0], &endPtr, 10);
+  bool ok = (&str[0] != endPtr);
+
+  if ( isOk ) *isOk = ok;
+
+  if ( !ok )
+  {
+    std::string msg = "Not an integer value:'" + str + "'";
+    throw std::invalid_argument(msg);
+  }
+  return val;
+}
+
index 77cde27eec240ce6973cf946183638ee6174d28b..667c8ebebf51f607956e3685c36191170e588610 100644 (file)
@@ -119,6 +119,19 @@ public:
   typedef std::set<std::string> TSetStrings;
 
   static const char* GetHypType() { return "MG-Tetra Parameters"; }
+
+  void SetMinSize(double theMinSize);
+  double GetMinSize() const { return myMinSize; }
+
+  void SetMaxSize(double theMaxSize);
+  double GetMaxSize() const { return myMaxSize; }
+
+  void SetUseVolumeProximity( bool toUse );
+  bool GetUseVolumeProximity() const { return myUseVolumeProximity; }
+
+  void SetNbVolumeProximityLayers( int nbLayers );
+  int GetNbVolumeProximityLayers() const { return myNbVolumeProximityLayers; }
+
   /*!
    * To mesh "holes" in a solid or not. Default is to mesh.
    */
@@ -215,6 +228,19 @@ public:
   void SetRemoveLogOnSuccess(bool removeLogOnSuccess);
   bool GetRemoveLogOnSuccess() const ;
     
+
+  typedef std::map< std::string, std::string > TOptionValues;
+  typedef std::set< std::string >              TOptionNames;
+
+  void SetOptionValue(const std::string& optionName,
+                      const std::string& optionValue) throw (std::invalid_argument);
+  std::string GetOptionValue(const std::string& optionName,
+                             bool*              isDefault=0) const throw (std::invalid_argument);
+  bool HasOptionDefined( const std::string& optionName ) const;
+  void ClearOption(const std::string& optionName);
+  TOptionValues        GetOptionValues()       const;
+  const TOptionValues& GetCustomOptionValues() const { return _customOption2value; }
+  //static inline const char* NoValue() { return "_"; }
   
 //   struct TEnforcedEdge {
 //     long ID;
@@ -302,24 +328,15 @@ public:
   static bool   DefaultToRemoveCentralPoint();
   static bool   DefaultStandardOutputLog();
   static bool   DefaultRemoveLogOnSuccess();
-  static double DefaultGradation();
-  
-  static TGHS3DEnforcedVertex DefaultGHS3DEnforcedVertex() {return TGHS3DEnforcedVertex();}
-  static TGHS3DEnforcedVertexList DefaultGHS3DEnforcedVertexList() {return TGHS3DEnforcedVertexList();}
-  static TGHS3DEnforcedVertexCoordsValues DefaultGHS3DEnforcedVertexCoordsValues() {return TGHS3DEnforcedVertexCoordsValues();}
-  static TGHS3DEnforcedVertexEntryValues DefaultGHS3DEnforcedVertexEntryValues() {return TGHS3DEnforcedVertexEntryValues();}
-  static TCoordsGHS3DEnforcedVertexMap DefaultCoordsGHS3DEnforcedVertexMap() {return TCoordsGHS3DEnforcedVertexMap();}
-  static TGeomEntryGHS3DEnforcedVertexMap DefaultGeomEntryGHS3DEnforcedVertexMap() {return TGeomEntryGHS3DEnforcedVertexMap();}
-  static TGroupNameGHS3DEnforcedVertexMap DefaultGroupNameGHS3DEnforcedVertexMap() {return TGroupNameGHS3DEnforcedVertexMap();}
-  
-  static TGHS3DEnforcedMesh         DefaultGHS3DEnforcedMesh() {return TGHS3DEnforcedMesh();}
-  static TGHS3DEnforcedMeshList     DefaultGHS3DEnforcedMeshList() {return TGHS3DEnforcedMeshList();}
-  static TEntryGHS3DEnforcedMeshListMap DefaultEntryGHS3DEnforcedMeshListMap() {return TEntryGHS3DEnforcedMeshListMap();}
-  static TIDSortedNodeGroupMap      DefaultIDSortedNodeGroupMap() {return TIDSortedNodeGroupMap();}
-  static TIDSortedElemGroupMap      DefaultIDSortedElemGroupMap() {return TIDSortedElemGroupMap();}
-  static TID2SizeMap                DefaultID2SizeMap() {return TID2SizeMap();}
-  static TSetStrings                DefaultGroupsToRemove() {return TSetStrings();}
-  
+  static inline double DefaultGradation() { return 1.05; }
+  static bool   DefaultUseVolumeProximity() { return false; }
+  static int    DefaultNbVolumeProximityLayers() { return 2; }
+   
+  void SetMinMaxSizeDefault( double theMinSize, double theMaxSize )
+  { myMinSizeDefault = theMinSize; myMaxSizeDefault = theMaxSize; }
+  double GetMinSizeDefault() const { return myMinSizeDefault; }
+  double GetMaxSizeDefault() const { return myMaxSizeDefault; }
+
   // Persistence
   virtual std::ostream & SaveTo(std::ostream & save);
   virtual std::istream & LoadFrom(std::istream & load);
@@ -334,6 +351,10 @@ public:
    */
   virtual bool SetParametersByDefaults(const TDefaults& dflts, const SMESH_Mesh* theMesh=0);
 
+  static bool  ToBool(const std::string& str, bool* isOk=0) throw (std::invalid_argument);
+  static double ToDbl(const std::string& str, bool* isOk=0) throw (std::invalid_argument);
+  static int    ToInt(const std::string& str, bool* isOk=0) throw (std::invalid_argument);
+
 protected:
 
   bool        myToMeshHoles;
@@ -350,9 +371,17 @@ protected:
   bool        myToRemoveCentralPoint;
   bool        myLogInStandardOutput;
   bool        myRemoveLogOnSuccess;
-  std::string myTextOption;
   double      myGradation;
+  bool        myUseVolumeProximity;
+  int         myNbVolumeProximityLayers;
+  double      myMinSize, myMinSizeDefault;
+  double      myMaxSize, myMaxSizeDefault;
+  //std::string myTextOption;
   
+  TOptionValues _option2value, _customOption2value;         // user defined values
+  TOptionValues _defaultOptionValues;                       // default values
+  TOptionNames  _doubleOptions, _charOptions, _boolOptions; // to find a type of option
+
   TGHS3DEnforcedVertexList         _enfVertexList;
   TGHS3DEnforcedVertexCoordsValues _enfVertexCoordsSizeList;
   TGHS3DEnforcedVertexEntryValues  _enfVertexEntrySizeList;
index b686ff56e9ced1ca79e9f7ad3a3af819e8f7b746..38babcd280bb8e69219b4e4275837c57c35c76bd 100644 (file)
 #include <SMESH_Mesh_i.hxx>
 #include <SMESH_Group_i.hxx>
 #include <SMESH_Gen_i.hxx>
-//#include <SMESH_TypeDefs.hxx>
 #include <SMESHDS_GroupBase.hxx>
 
-// SALOME KERNEL includes
-// #include <SALOMEDSClient.hxx>
-// #include <SALOMEDSClient_definitions.hxx>
 
 using namespace std;
 
@@ -82,6 +78,92 @@ CORBA::Boolean GHS3DPlugin_Hypothesis_i::GetToMeshHoles()
   return this->GetImpl()->GetToMeshHoles();
 }
 
+//=============================================================================
+void GHS3DPlugin_Hypothesis_i::SetMinSize(CORBA::Double theMinSize)
+{
+  if ( GetMinSize() != theMinSize ) {
+    this->GetImpl()->SetMinSize( theMinSize );
+    SMESH::TPythonDump() << _this() << ".SetMinSize( " << theMinSize << " )";
+  }
+}
+
+//=============================================================================
+CORBA::Double GHS3DPlugin_Hypothesis_i::GetMinSize()
+{
+  return this->GetImpl()->GetMinSize();
+}
+
+//=============================================================================
+CORBA::Double GHS3DPlugin_Hypothesis_i::GetMinSizeDefault()
+{
+  return this->GetImpl()->GetMinSizeDefault();
+}
+
+//=============================================================================
+void GHS3DPlugin_Hypothesis_i::SetMaxSize(CORBA::Double theMaxSize)
+{
+  if ( GetMaxSize() != theMaxSize ) {
+    this->GetImpl()->SetMaxSize( theMaxSize );
+    SMESH::TPythonDump() << _this() << ".SetMaxSize( " << theMaxSize << " )";
+  }
+}
+
+//=============================================================================
+CORBA::Double GHS3DPlugin_Hypothesis_i::GetMaxSize()
+{
+  return this->GetImpl()->GetMaxSize();
+}
+
+//=============================================================================
+CORBA::Double GHS3DPlugin_Hypothesis_i::GetMaxSizeDefault()
+{
+  return this->GetImpl()->GetMaxSizeDefault();
+}
+
+//=============================================================================
+void GHS3DPlugin_Hypothesis_i::SetMinMaxSizeDefault( CORBA::Double theMinSize,
+                                                     CORBA::Double theMaxSize )
+{
+  this->GetImpl()->SetMinMaxSizeDefault( theMinSize, theMaxSize );
+}
+
+//=============================================================================
+/*!
+ *  Activate/deactivate volume proximity computation
+ */
+void GHS3DPlugin_Hypothesis_i::SetVolumeProximity( CORBA::Boolean toUse )
+{
+  if ( GetVolumeProximity() != toUse )
+  {
+    this->GetImpl()->SetUseVolumeProximity( toUse );
+    SMESH::TPythonDump() << _this() << ".SetVolumeProximity( " << toUse << " )";
+  }
+}
+
+CORBA::Boolean GHS3DPlugin_Hypothesis_i::GetVolumeProximity()
+{
+  return this->GetImpl()->GetUseVolumeProximity();
+}
+
+
+//=============================================================================
+/*!
+ * Set number of surface element layers to be generated due to volume proximity
+ */
+void GHS3DPlugin_Hypothesis_i::SetNbVolumeProximityLayers( CORBA::Short nbLayers )
+{
+  if ( GetNbVolumeProximityLayers() != nbLayers )
+  {
+    this->GetImpl()->SetNbVolumeProximityLayers( nbLayers );
+    SMESH::TPythonDump() << _this() << ".SetNbVolumeProximityLayers( " << nbLayers << " )";
+  }
+}
+
+CORBA::Short GHS3DPlugin_Hypothesis_i::GetNbVolumeProximityLayers()
+{
+  return this->GetImpl()->GetNbVolumeProximityLayers();
+}
+
 //=======================================================================
 //function : SetToMakeGroupsOfDomains
 //=======================================================================
@@ -349,9 +431,7 @@ CORBA::Boolean GHS3DPlugin_Hypothesis_i::GetToRemoveCentralPoint()
 
 void GHS3DPlugin_Hypothesis_i::SetTextOption(const char* option)
 {
-  ASSERT(myBaseImpl);
-  this->GetImpl()->SetAdvancedOption(option);
-  SMESH::TPythonDump() << _this() << ".SetAdvancedOption( '" << option << "' )";
+  SetAdvancedOption(option);
 }
 
 //=======================================================================
@@ -360,20 +440,19 @@ void GHS3DPlugin_Hypothesis_i::SetTextOption(const char* option)
 
 char* GHS3DPlugin_Hypothesis_i::GetTextOption()
 {
-  ASSERT(myBaseImpl);
-  return CORBA::string_dup( this->GetImpl()->GetAdvancedOption().c_str() );
+  return GetAdvancedOption();
 }
 
 //=======================================================================
 //function : SetAdvancedOption
 //=======================================================================
 
-void GHS3DPlugin_Hypothesis_i::SetAdvancedOption(const char* option)
-{
-  ASSERT(myBaseImpl);
-  this->GetImpl()->SetAdvancedOption(option);
-  SMESH::TPythonDump() << _this() << ".SetAdvancedOption( '" << option << "' )";
-}
+// void GHS3DPlugin_Hypothesis_i::SetAdvancedOption(const char* option)
+// {
+//   ASSERT(myBaseImpl);
+//   this->GetImpl()->SetAdvancedOption(option);
+//   SMESH::TPythonDump() << _this() << ".SetAdvancedOption( '" << option << "' )";
+// }
 
 //=======================================================================
 //function : GetAdvancedOption
@@ -385,8 +464,278 @@ char* GHS3DPlugin_Hypothesis_i::GetAdvancedOption()
   return CORBA::string_dup( this->GetImpl()->GetAdvancedOption().c_str() );
 }
 
+//=============================================================================
+
+void GHS3DPlugin_Hypothesis_i::SetOptionValue(const char* optionName, const char* optionValue)
+  throw (SALOME::SALOME_Exception)
+{
+  ASSERT(myBaseImpl);
+  try {
+    std::string name( optionName );
+    if ( !optionValue || !optionValue[0] )
+      UnsetOption( optionName );
+
+    // basic options (visible in Advanced table)
+
+    else if ( name == "verbose" )
+      SetVerboseLevel( GetImpl()->ToInt( optionValue ));
+
+    else if ( name == "max_memory" )
+      SetMaximumMemory( GetImpl()->ToInt( optionValue ));
+
+    else if ( name == "automatic_memory" )
+      SetInitialMemory( GetImpl()->ToInt( optionValue ));
+
+    else if ( name == "no_initial_central_point" && // optimizer
+              strcmp( GetImpl()->GetName(), ::GHS3DPlugin_Hypothesis::GetHypType() ) != 0 )
+    {
+      //if ( strcmp( optionValue, ::GHS3DPlugin_Hypothesis::NoValue() ) == 0 )
+      if ( !optionValue[0] )
+        SetToRemoveCentralPoint( true );
+      else
+        SetToRemoveCentralPoint( GetImpl()->ToBool( optionValue ));
+    }
+    else if ( name == "no_internal_points"  && // optimizer
+              strcmp( GetImpl()->GetName(), ::GHS3DPlugin_Hypothesis::GetHypType() ) != 0)
+    {
+      //if ( strcmp( optionValue, ::GHS3DPlugin_Hypothesis::NoValue() ) == 0 )
+      if ( !optionValue[0] )
+        SetToRemoveCentralPoint( true );
+      else
+        SetToCreateNewNodes( GetImpl()->ToBool( optionValue ));
+    }
+    else if ( name == "min_size" )
+      SetMinSize( GetImpl()->ToDbl( optionValue ));
+
+    else if ( name == "max_size" )
+      SetMaxSize( GetImpl()->ToDbl( optionValue ));
+
+    else if ( name == "gradation" )
+      SetGradation( GetImpl()->ToDbl( optionValue ));
+
+    else if ( name == "volume_proximity_layers" )
+      SetNbVolumeProximityLayers( GetImpl()->ToInt( optionValue ));
+
+    else if ( name == "components" )
+      SetToMeshHoles( strncmp( "all", optionValue, 3 ) == 0 );
+
+    // advanced options (for backward compatibility)
+    // else if ( name == "create_tag_on_collision" ||
+    //           name == "tiny_edge_respect_geometry" )
+    //   AddOption( optionName, optionValue );
+
+    else {
+      bool valueChanged = true;
+      try {
+        valueChanged = ( this->GetImpl()->GetOptionValue( name ) != optionValue );
+      }
+      catch ( std::invalid_argument ) {
+      }
+      if ( valueChanged )
+      {
+        this->GetImpl()->SetOptionValue(optionName, optionValue);
+        SMESH::TPythonDump() << _this() << ".SetOptionValue( '" << optionName << "', '" << optionValue << "' )";
+      }
+    }
+  } catch (const std::invalid_argument& ex) {
+    THROW_SALOME_CORBA_EXCEPTION( ex.what() ,SALOME::BAD_PARAM );
+  } catch (SALOME_Exception& ex) {
+    THROW_SALOME_CORBA_EXCEPTION( ex.what() ,SALOME::BAD_PARAM );
+  }
+}
+
+//=============================================================================
+
+char* GHS3DPlugin_Hypothesis_i::GetOptionValue(const char* optionName)
+  throw (SALOME::SALOME_Exception)
+{
+  ASSERT(myBaseImpl);
+  try {
+    bool isDefault;
+    return CORBA::string_dup(this->GetImpl()->GetOptionValue(optionName,&isDefault).c_str());
+  } catch (const std::invalid_argument& ex) {
+    THROW_SALOME_CORBA_EXCEPTION( ex.what() ,SALOME::BAD_PARAM );
+  } catch (SALOME_Exception& ex) {
+    THROW_SALOME_CORBA_EXCEPTION( ex.what() ,SALOME::BAD_PARAM );
+  }
+  return 0;
+}
+
+//=============================================================================
+
+void GHS3DPlugin_Hypothesis_i::UnsetOption(const char* optionName) {
+  ASSERT(myBaseImpl);
+  if ( !GetImpl()->GetOptionValue( optionName ).empty() )
+  {
+    this->GetImpl()->ClearOption(optionName);
+    SMESH::TPythonDump() << _this() << ".UnsetOption( '" << optionName << "' )";
+  }
+}
+
+//=============================================================================
+
+GHS3DPlugin::string_array* GHS3DPlugin_Hypothesis_i::GetOptionValues()
+{
+  GHS3DPlugin::string_array_var result = new GHS3DPlugin::string_array();
+
+  const ::GHS3DPlugin_Hypothesis::TOptionValues & opts = this->GetImpl()->GetOptionValues();
+  result->length(opts.size());
+  int i=0;
+
+  bool isDefault;
+  ::GHS3DPlugin_Hypothesis::TOptionValues::const_iterator opIt = opts.begin();
+  for (; opIt != opts.end(); ++opIt, ++i)
+  {
+    string name_value_type = opIt->first;
+    //if (!opIt->second.empty())
+    {
+      name_value_type += ":";
+      name_value_type += GetImpl()->GetOptionValue( opIt->first, &isDefault );
+      name_value_type += isDefault ? ":0" : ":1";
+    }
+    result[i] = CORBA::string_dup(name_value_type.c_str());
+  }
+
+  return result._retn();
+}
+
+//=============================================================================
+
+GHS3DPlugin::string_array* GHS3DPlugin_Hypothesis_i::GetAdvancedOptionValues()
+{
+  GHS3DPlugin::string_array_var result = new GHS3DPlugin::string_array();
+
+  const ::GHS3DPlugin_Hypothesis::TOptionValues & custom_opts = this->GetImpl()->GetCustomOptionValues();
+  result->length(custom_opts.size());
+  int i=0;
+
+  ::GHS3DPlugin_Hypothesis::TOptionValues::const_iterator opIt = custom_opts.begin();
+  for (; opIt != custom_opts.end(); ++opIt, ++i) {
+    string name_value_type = opIt->first;
+    if (!opIt->second.empty()) {
+      name_value_type += ":";
+      name_value_type += opIt->second;
+      name_value_type += ":1"; // user defined
+    }
+    result[i] = CORBA::string_dup(name_value_type.c_str());
+  }
+  return result._retn();
+}
+
+//=============================================================================
+
+void GHS3DPlugin_Hypothesis_i::SetOptionValues(const GHS3DPlugin::string_array& options)
+  throw (SALOME::SALOME_Exception)
+{
+  for (CORBA::ULong i = 0; i < options.length(); ++i)
+  {
+    string name_value_type = options[i].in();
+    if(name_value_type.empty())
+      continue;
+    size_t colonPos = name_value_type.find(':');
+    string name, value;
+    if (colonPos == string::npos) // ':' not found
+      name = name_value_type;
+    else {
+      name = name_value_type.substr(0, colonPos);
+      if (colonPos < name_value_type.size() - 1 && name_value_type[colonPos] != ' ') {
+        string value_type = name_value_type.substr(colonPos + 1);
+        colonPos = value_type.find(':');
+        value = value_type.substr(0, colonPos);
+        if (colonPos < value_type.size() - 1 && value_type[colonPos] != ' ')
+          if ( value_type.substr(colonPos + 1) == "0" ) // is default
+            value.clear();
+      }
+    }
+    SetOptionValue(name.c_str(), value.c_str());
+  }
+}
+
+//=============================================================================
+
+void GHS3DPlugin_Hypothesis_i::SetAdvancedOptionValues(const GHS3DPlugin::string_array& options)
+{
+  SMESH::TPythonDump dump;
+
+  string optionsAndValues;
+  for ( CORBA::ULong i = 0; i < options.length(); ++i) {
+    string name_value_type = options[i].in();
+    if(name_value_type.empty())
+      continue;
+    size_t colonPos = name_value_type.find(':');
+    string name, value;
+    if (colonPos == string::npos) // ':' not found
+      name = name_value_type;
+    else {
+      name = name_value_type.substr(0, colonPos);
+      if (colonPos < name_value_type.size() - 1 && name_value_type[colonPos] != ' ') {
+        string value_type = name_value_type.substr(colonPos + 1);
+        colonPos = value_type.find(':');
+        value = value_type.substr(0, colonPos);
+      }
+    }
+    AddOption(name.c_str(), value.c_str());
+
+    optionsAndValues += name + " " + value + " ";
+  }
+
+  if ( !optionsAndValues.empty() )
+    dump << _this() << ".SetAdvancedOptions( '" << optionsAndValues.c_str() << "' )";
+}
+
+//=============================================================================
+
+void GHS3DPlugin_Hypothesis_i::SetAdvancedOption(const char* optionsAndValues)
+  throw (SALOME::SALOME_Exception)
+{
+  if ( !optionsAndValues ) return;
+
+  SMESH::TPythonDump dump;
+
+  std::istringstream strm( optionsAndValues );
+  std::istream_iterator<std::string> sIt( strm ), sEnd;
+  for ( int nbPairs = 0; sIt != sEnd; ++nbPairs )
+  {
+    std::string option = *sIt;
+    if ( ++sIt != sEnd )
+    {
+      std::string value = *sIt;
+      ++sIt;
+      AddOption( option.c_str(), value.c_str() );
+    }
+    else
+    {
+      if ( nbPairs > 0 )
+        THROW_SALOME_CORBA_EXCEPTION( "Uneven number of options and values" ,SALOME::BAD_PARAM );
+      AddOption( option.c_str(), "" );
+    }
+  }
+  dump << _this() << ".SetAdvancedOption( '" << optionsAndValues << "' )";
+}
+
+//=============================================================================
+
+void GHS3DPlugin_Hypothesis_i::AddOption(const char* optionName, const char* optionValue)
+{
+  ASSERT(myBaseImpl);
+  bool valueChanged = ( !this->GetImpl()->HasOptionDefined(optionName) ||
+                        this->GetImpl()->GetOptionValue(optionName) != optionValue );
+  if (valueChanged) {
+    this->GetImpl()->SetOptionValue(optionName, optionValue);
+    SMESH::TPythonDump() << _this() << ".SetOptionValue( '" << optionName << "', '" << optionValue << "' )";
+  }
+}
+
+//=============================================================================
+
+char* GHS3DPlugin_Hypothesis_i::GetOption(const char* optionName)
+{
+  ASSERT(myBaseImpl);
+  return CORBA::string_dup(this->GetImpl()->GetOptionValue(optionName).c_str());
+}
+
 //=======================================================================
-//function : SetToRemoveCentralPoint
+//function : SetGradation
 //=======================================================================
 
 void GHS3DPlugin_Hypothesis_i::SetGradation(CORBA::Double gradation)
@@ -399,7 +748,7 @@ void GHS3DPlugin_Hypothesis_i::SetGradation(CORBA::Double gradation)
 }
 
 //=======================================================================
-//function : GetToRemoveCentralPoint
+//function : GetGradation
 //=======================================================================
 
 CORBA::Double GHS3DPlugin_Hypothesis_i::GetGradation()
index 286054307cdeee10cb3ff78ed31b7a60c1166d2d..37f1a86edecec0d243283e2a13e7eac41c9a5e37 100644 (file)
@@ -54,6 +54,22 @@ class GHS3DPLUGIN_EXPORT GHS3DPlugin_Hypothesis_i:
    */
   void SetToMeshHoles(CORBA::Boolean toMesh);
   CORBA::Boolean GetToMeshHoles();
+  /*!
+   *  Activate/deactivate volume proximity computation
+   */
+  void SetVolumeProximity( CORBA::Boolean toUse );
+  CORBA::Boolean GetVolumeProximity();
+  /*!
+   * Set number of surface element layers to be generated due to volume proximity
+   */
+  void SetNbVolumeProximityLayers( CORBA::Short nbLayers );
+  CORBA::Short GetNbVolumeProximityLayers();
+
+  void SetMaxSize(CORBA::Double theMaxSize);
+  CORBA::Double GetMaxSize();
+
+  void SetMinSize(CORBA::Double theMinSize);
+  CORBA::Double GetMinSize();
   /*!
    * To make groups of volumes of different domains when mesh is generated from skin.
    * Default is to make groups.
@@ -126,10 +142,23 @@ class GHS3DPLUGIN_EXPORT GHS3DPlugin_Hypothesis_i:
   /*!
    * To set hiden/undocumented/advanced options
    */
-  void SetAdvancedOption(const char* option);
+  void SetAdvancedOption(const char* option) throw (SALOME::SALOME_Exception);
   char* GetAdvancedOption();
   void SetTextOption(const char* option); // obsolete
   char* GetTextOption();
+
+  void SetOptionValue(const char* optionName, const char* optionValue) throw (SALOME::SALOME_Exception);
+  char* GetOptionValue(const char* optionName) throw (SALOME::SALOME_Exception);
+  void UnsetOption(const char* optionName);
+
+  GHS3DPlugin::string_array* GetOptionValues();
+  GHS3DPlugin::string_array* GetAdvancedOptionValues();
+
+  void SetOptionValues(const GHS3DPlugin::string_array& options) throw (SALOME::SALOME_Exception);
+  void SetAdvancedOptionValues(const GHS3DPlugin::string_array& options);
+
+  void AddOption(const char* optionName, const char* optionValue);
+  char* GetOption(const char* optionName);
   /*!
   * To define the volumic gradation
   */
@@ -179,6 +208,11 @@ class GHS3DPLUGIN_EXPORT GHS3DPlugin_Hypothesis_i:
   GHS3DPlugin::GHS3DEnforcedMeshList* GetEnforcedMeshes();
   void ClearEnforcedMeshes();
 
+  // 3 GUI methods
+  CORBA::Double GetMaxSizeDefault();
+  CORBA::Double GetMinSizeDefault();
+  void SetMinMaxSizeDefault( CORBA::Double theMinSize, CORBA::Double theMaxSize );
+
   // Get implementation
   ::GHS3DPlugin_Hypothesis* GetImpl();
   
index 1ad894fdf90f88e6227e8294bd2831e7739a6a95..d4b2961bdf70f1a3c09314d5a96513e01d3d2817 100644 (file)
@@ -195,7 +195,7 @@ std::string GHS3DPlugin_OptimizerHypothesis::CommandToRun(const GHS3DPlugin_Opti
 
     cmd << " --verbose " << hyp->myVerboseLevel;
     
-    cmd << " " << hyp->myTextOption;
+    //cmd << " " << hyp->myTextOption;
   }
 
   return cmd;
index 1665d35ff7adf1e62099158c7be832b0daa6a517..e381f5f705c3138b4e97e451b538c23c0036b2c6 100644 (file)
@@ -33,6 +33,7 @@ INCLUDE_DIRECTORIES(
   ${CMAKE_CURRENT_BINARY_DIR}
   ${PROJECT_BINARY_DIR}/idl
   ${PROJECT_SOURCE_DIR}/src/GHS3DPlugin
+  ${PROJECT_SOURCE_DIR}/src/GUI
 )
 
 # additional preprocessor / compiler flags
@@ -65,6 +66,7 @@ SET(_link_LIBRARIES
 SET(_moc_HEADERS
   GHS3DPluginGUI_HypothesisCreator.h
   GHS3DPluginGUI_Dlg.h
+  GHS3DPluginGUI_TreeWidget.h
 )
 
 # header files / no moc processed
@@ -84,6 +86,7 @@ SET(_other_SOURCES
   GHS3DPluginGUI.cxx
   GHS3DPluginGUI_HypothesisCreator.cxx
   GHS3DPluginGUI_AdvWidget.cxx
+  GHS3DPluginGUI_TreeWidget.cxx
 )
 
 # --- resources ---
index 18a79bf3af73dbc843b4a4b8ac381d521471fdaf..a29f5eb1819470784e6c469d85fb262c33531e97 100644 (file)
 #include <QFileDialog>
 
 #include <iostream>
+#include <GHS3DPlugin_Hypothesis.hxx>
 
+namespace
+{
+  enum { EDITABLE_ROLE = Qt::UserRole + 1, PARAM_NAME,
+         NAME_COL = 0, VALUE_COL };
+
+  class ItemDelegate: public QItemDelegate {
+  public:
+    ItemDelegate(QObject* parent=0): QItemDelegate(parent) {}
+    QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &o, const QModelIndex &index) const
+    {
+      bool editable = index.data( EDITABLE_ROLE ).toInt();
+      return editable ? QItemDelegate::createEditor( parent, o, index ) : 0;
+    }
+  };
+}
 
 //////////////////////////////////////////
 // GHS3DPluginGUI_AdvWidget
@@ -38,9 +54,84 @@ GHS3DPluginGUI_AdvWidget::GHS3DPluginGUI_AdvWidget( QWidget* parent, Qt::WindowF
 : QWidget( parent, f )
 {
   setupUi( this );
-  advOptionTable->layout()->setMargin( 0 );
+  //myOptionTable->layout()->setMargin( 0 );
+  myOptionTable->header()->setSectionResizeMode( QHeaderView::ResizeToContents );
+  myOptionTable->setItemDelegate( new ItemDelegate( myOptionTable ) );
+
+  connect( myOptionTable, SIGNAL( itemChanged(QTreeWidgetItem *, int)), SLOT( itemChanged(QTreeWidgetItem *, int )));
 }
 
 GHS3DPluginGUI_AdvWidget::~GHS3DPluginGUI_AdvWidget()
 {
 }
+
+void GHS3DPluginGUI_AdvWidget::AddOption( const char* option, bool isCustom )
+{
+  QTreeWidget * table = myOptionTable;
+  //table->setExpanded( true );
+
+  QTreeWidgetItem * row = new QTreeWidgetItem( table );
+  row->setData( NAME_COL, EDITABLE_ROLE, int( isCustom && !option ));
+  row->setFlags( row->flags() | Qt::ItemIsEditable );
+
+  QString name, value;
+  bool isDefault = false;
+  if ( option )
+  {
+    QStringList name_value_type = QString(option).split( ":", QString::KeepEmptyParts );
+    if ( name_value_type.size() > 0 )
+      name = name_value_type[0];
+    if ( name_value_type.size() > 1 )
+      value = name_value_type[1];
+    if ( name_value_type.size() > 2 )
+      isDefault = !name_value_type[2].toInt();
+
+    // if ( value == GHS3DPlugin_Hypothesis::NoValue() )
+    //   value.clear();
+  }
+  row->setText( 0, tr( name.toLatin1().constData() ));
+  row->setText( 1, tr( value.toLatin1().constData() ));
+  row->setCheckState( 0, isDefault ? Qt::Unchecked : Qt::Checked);
+  row->setData( NAME_COL, PARAM_NAME, name );
+
+  if ( isCustom )
+  {
+    myOptionTable->scrollToItem( row );
+    myOptionTable->setCurrentItem( row );
+    myOptionTable->editItem( row, NAME_COL );
+  }
+}
+
+void GHS3DPluginGUI_AdvWidget::GetOptionAndValue( QTreeWidgetItem * tblRow,
+                                                  QString&          option,
+                                                  QString&          value,
+                                                  bool&             isDefault)
+{
+  option    = tblRow->data( NAME_COL, PARAM_NAME ).toString();
+  value     = tblRow->text( VALUE_COL );
+  isDefault = ! tblRow->checkState( NAME_COL );
+
+  // if ( value.isEmpty() )
+  //   value = GHS3DPlugin_Hypothesis::NoValue();
+}
+
+
+void GHS3DPluginGUI_AdvWidget::itemChanged(QTreeWidgetItem * tblRow, int column)
+{
+  if ( tblRow )
+  {
+    myOptionTable->blockSignals( true );
+
+    tblRow->setData( VALUE_COL, EDITABLE_ROLE, int( tblRow->checkState( NAME_COL )));
+
+    int c = tblRow->checkState( NAME_COL ) ? 0 : 150;
+    tblRow->setForeground( VALUE_COL, QBrush( QColor( c, c, c )));
+
+    if ( column == NAME_COL && tblRow->data( NAME_COL, EDITABLE_ROLE ).toInt() ) // custom table
+    {
+      tblRow->setData( NAME_COL, PARAM_NAME, tblRow->text( NAME_COL ));
+    }
+
+    myOptionTable->blockSignals( false );
+  }
+}
index e589dc51d9e85b272ff2a16021bcd8174f263be2..dea16fe671407f2470f5409cc56fb311ab4b28e5 100644 (file)
@@ -6,24 +6,67 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>485</width>
-    <height>477</height>
+    <width>337</width>
+    <height>369</height>
    </rect>
   </property>
   <property name="windowTitle">
    <string>Form</string>
   </property>
-  <layout class="QVBoxLayout" name="verticalLayout_2">
-   <property name="leftMargin">
-    <number>0</number>
-   </property>
-   <property name="topMargin">
-    <number>0</number>
-   </property>
-   <property name="rightMargin">
-    <number>0</number>
-   </property>
-   <item>
+  <layout class="QGridLayout" name="gridLayout_4">
+   <item row="0" column="0" colspan="2">
+    <widget class="GHS3DPluginGUI_TreeWidget" name="myOptionTable">
+     <property name="editTriggers">
+      <set>QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed</set>
+     </property>
+     <property name="tabKeyNavigation">
+      <bool>true</bool>
+     </property>
+     <column>
+      <property name="text">
+       <string>OPTION_NAME_COLUMN</string>
+      </property>
+      <property name="font">
+       <font>
+        <weight>50</weight>
+        <bold>false</bold>
+       </font>
+      </property>
+     </column>
+     <column>
+      <property name="text">
+       <string>OPTION_VALUE_COLUMN</string>
+      </property>
+      <property name="font">
+       <font>
+        <weight>50</weight>
+        <bold>false</bold>
+       </font>
+      </property>
+     </column>
+    </widget>
+   </item>
+   <item row="1" column="0">
+    <widget class="QPushButton" name="addBtn">
+     <property name="text">
+      <string>GHS3D_ADD_OPTION</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="1">
+    <spacer name="horizontalSpacer">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>188</width>
+       <height>20</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item row="2" column="0" colspan="2">
     <widget class="QGroupBox" name="memoryGroupBox">
      <property name="title">
       <string>Memory settings</string>
      </layout>
     </widget>
    </item>
-   <item>
+   <item row="3" column="0" colspan="2">
     <widget class="QGroupBox" name="logGroupBox">
      <property name="title">
       <string>Logs and debug</string>
      </layout>
     </widget>
    </item>
-   <item>
-    <widget class="QGroupBox" name="advancedMeshingGroupBox">
-     <property name="title">
-      <string>Advanced meshing options</string>
-     </property>
-     <layout class="QGridLayout" name="gridLayout_4">
-      <item row="1" column="1">
-       <widget class="QCheckBox" name="FEMCorrectionCheck">
-        <property name="text">
-         <string>Use FEM correction</string>
-        </property>
-       </widget>
-      </item>
-      <item row="1" column="0">
-       <widget class="QCheckBox" name="removeInitialCentralPointCheck">
-        <property name="text">
-         <string>Remove initial central point</string>
-        </property>
-       </widget>
-      </item>
-      <item row="6" column="1">
-       <widget class="SMESHGUI_SpinBox" name="gradationSpinBox"/>
-      </item>
-      <item row="6" column="0">
-       <widget class="QLabel" name="gradationLabel">
-        <property name="text">
-         <string>Volumic gradation</string>
-        </property>
-       </widget>
-      </item>
-      <item row="0" column="0">
-       <widget class="QCheckBox" name="createNewNodesCheck">
-        <property name="text">
-         <string>Create new nodes</string>
-        </property>
-       </widget>
-      </item>
-      <item row="0" column="1">
-       <widget class="QCheckBox" name="boundaryRecoveryCheck">
-        <property name="text">
-         <string>Use boundary recovery version</string>
-        </property>
-       </widget>
-      </item>
-      <item row="7" column="0" colspan="2">
-       <widget class="SMESH_AdvOptionsWdg" name="advOptionTable" native="true"/>
-      </item>
-     </layout>
-    </widget>
-   </item>
   </layout>
  </widget>
  <customwidgets>
    <header location="global">SMESHGUI_SpinBox.h</header>
   </customwidget>
   <customwidget>
-   <class>SMESH_AdvOptionsWdg</class>
-   <extends>QWidget</extends>
-   <header location="global">SMESH_AdvOptionsWdg.h</header>
-   <container>1</container>
+   <class>GHS3DPluginGUI_TreeWidget</class>
+   <extends>QTreeWidget</extends>
+   <header location="global">GHS3DPluginGUI_TreeWidget.h</header>
   </customwidget>
  </customwidgets>
  <resources/>
index a647e3d49809b78ace4f23c3fd7bd6828bb174e1..dbd491ddfb049993d4eb7607b80c49e6f78469f6 100644 (file)
 #ifndef GHS3DPLUGINGUI_H
 #define GHS3DPLUGINGUI_H
 
+enum {
+  OPTION_ID_COLUMN = 0,
+  OPTION_TYPE_COLUMN,
+  OPTION_NAME_COLUMN = 0,
+  OPTION_VALUE_COLUMN,
+  NB_COLUMNS,
+};
+
 //////////////////////////////////////////
 // GHS3DPluginGUI_AdvWidget
 //////////////////////////////////////////
@@ -38,6 +46,13 @@ class GHS3DPLUGINGUI_EXPORT GHS3DPluginGUI_AdvWidget : public QWidget,
 public:
   GHS3DPluginGUI_AdvWidget( QWidget* = 0, Qt::WindowFlags = 0 );
   ~GHS3DPluginGUI_AdvWidget();
+
+  void AddOption( const char* name_value_type, bool isCustom = false );
+  void GetOptionAndValue( QTreeWidgetItem * tblRow, QString& option, QString& value, bool& dflt );
+
+public slots:
+
+  void itemChanged(QTreeWidgetItem * tblRow, int column);
 };
 
 #endif
index 452397b4c50554ab6785ca5685eb23e53884aaf8..2183f96a0fb3d613b9d3356076453aa1bd9794b6 100644 (file)
@@ -294,7 +294,25 @@ void EnforcedMeshTableWidgetDelegate::updateEditorGeometry(QWidget *editor,
 
 
 GHS3DPluginGUI_HypothesisCreator::GHS3DPluginGUI_HypothesisCreator( const QString& theHypType )
-  : SMESHGUI_GenericHypothesisCreator( theHypType )
+  : SMESHGUI_GenericHypothesisCreator( theHypType ),
+    myName(0),
+    myOptimizationLevelCombo(0),
+    myMinSizeCheck(0),
+    myMaxSizeCheck(0),
+    myMinSizeSpin(0),
+    myMaxSizeSpin(0),
+    myGradationCheck(0),
+    myGradationSpin(0),
+    myUseProximityGroup(0),
+    myNbProximityLayers(0),
+    myToMakeGroupsOfDomains(0),
+    myToMeshHolesCheck(0),
+    myOptimizationCombo(0),
+    mySplitOverConstrainedCombo(0),
+    myPThreadsModeCombo(0),
+    myNumberOfThreadsSpin(0),
+    mySmoothOffSliversCheck(0),
+    myCreateNewNodesCheck(0)
 {
   GeomToolSelected = NULL;
   GeomToolSelected = getGeomSelectionTool();
@@ -354,73 +372,127 @@ QFrame* GHS3DPluginGUI_HypothesisCreator::buildFrame()
   aStdLayout->setMargin( 11 );
 
   int row = 0;
-  myName = 0;
   if ( isCreation() )
   {
     aStdLayout->addWidget( new QLabel( tr( "SMESH_NAME" ), myStdGroup ), row, 0, 1, 1 );
     myName = new QLineEdit( myStdGroup );
     aStdLayout->addWidget( myName, row++, 1, 1, 1 );
   }
-
-  myToMeshHolesCheck = new QCheckBox( tr( "GHS3D_TO_MESH_HOLES" ), myStdGroup );
-  aStdLayout->addWidget( myToMeshHolesCheck, row, 0, 1, 1 );
-  myToMakeGroupsOfDomains = new QCheckBox( tr( "GHS3D_TO_MAKE_DOMAIN_GROUPS" ), myStdGroup );
-  aStdLayout->addWidget( myToMakeGroupsOfDomains, row++, 1, 1, 1 );
-
-  QLabel* optimizationLbl = new QLabel( tr( "GHS3D_OPTIMIZATION" ), myStdGroup );
-  aStdLayout->addWidget( optimizationLbl, row, 0, 1, 1 );
-  myOptimizationCombo = getModeCombo( myStdGroup, false );
-  aStdLayout->addWidget( myOptimizationCombo, row++, 1, 1, 1 );
-
-  QLabel* optimizatiolLevelLbl = new QLabel( tr( "GHS3D_OPTIMIZATIOL_LEVEL" ), myStdGroup );
-  aStdLayout->addWidget( optimizatiolLevelLbl, row, 0, 1, 1 );
-  myOptimizationLevelCombo = new QComboBox( myStdGroup );
-  aStdLayout->addWidget( myOptimizationLevelCombo, row++, 1, 1, 1 );
-
-  QLabel* splitOverconstrainedLbl = new QLabel( tr("GHS3D_SPLIT_OVERCONSTRAINED"), myStdGroup );
-  aStdLayout->addWidget( splitOverconstrainedLbl, row, 0, 1, 1 );
-  mySplitOverConstrainedCombo = getModeCombo( myStdGroup, false );
-  aStdLayout->addWidget( mySplitOverConstrainedCombo, row++, 1, 1, 1 );
-
-  QLabel* pthreadsModeLbl = new QLabel( tr( "GHS3D_PTHREADS_MODE" ), myStdGroup);
-  aStdLayout->addWidget( pthreadsModeLbl, row, 0, 1, 1 );
-  myPThreadsModeCombo = getModeCombo( myStdGroup, true );
-  aStdLayout->addWidget( myPThreadsModeCombo, row++, 1, 1, 1 );
-
-  QLabel* nbThreadsLbl = new QLabel( tr( "GHS3D_NB_THREADS" ), myStdGroup);
-  aStdLayout->addWidget( nbThreadsLbl, row, 0, 1, 1 );
-  myNumberOfThreadsSpin = new SalomeApp_IntSpinBox( 0, 1000, 1, myStdGroup );
-  aStdLayout->addWidget( myNumberOfThreadsSpin, row++, 1, 1, 1 );
-
-  mySmoothOffSliversCheck = new QCheckBox( tr( "GHS3D_SMOOTH_OFF_SLIVERS" ), myStdGroup );
-  aStdLayout->addWidget( mySmoothOffSliversCheck, row, 0, 1, 1 );
-  myCreateNewNodesCheck = new QCheckBox( tr( "TO_ADD_NODES" ), myStdGroup );
-  aStdLayout->addWidget( myCreateNewNodesCheck, row++, 1, 1, 1 );
-
-  myOptimizationLevelCombo->addItems( QStringList()
-                                      << tr( "LEVEL_NONE" )   << tr( "LEVEL_LIGHT" )
-                                      << tr( "LEVEL_MEDIUM" ) << tr( "LEVEL_STANDARDPLUS" )
-                                      << tr( "LEVEL_STRONG" ));
-  aStdLayout->setRowStretch( row, 10 );
-
   if ( isOptimization() )
   {
-    myToMeshHolesCheck->hide();
-    myToMakeGroupsOfDomains->hide();
+    myToMeshHolesCheck = new QCheckBox( tr( "GHS3D_TO_MESH_HOLES" ), myStdGroup );
+    aStdLayout->addWidget( myToMeshHolesCheck, row, 0, 1, 1 );
+    myToMakeGroupsOfDomains = new QCheckBox( tr( "GHS3D_TO_MAKE_DOMAIN_GROUPS" ), myStdGroup );
+    aStdLayout->addWidget( myToMakeGroupsOfDomains, row++, 1, 1, 1 );
+
+    QLabel* optimizationLbl = new QLabel( tr( "GHS3D_OPTIMIZATION" ), myStdGroup );
+    aStdLayout->addWidget( optimizationLbl, row, 0, 1, 1 );
+    myOptimizationCombo = getModeCombo( myStdGroup, false );
+    aStdLayout->addWidget( myOptimizationCombo, row++, 1, 1, 1 );
+
+    QLabel* optimizatiolLevelLbl = new QLabel( tr( "GHS3D_OPTIMIZATIOL_LEVEL" ), myStdGroup );
+    aStdLayout->addWidget( optimizatiolLevelLbl, row, 0, 1, 1 );
+    myOptimizationLevelCombo = new QComboBox( myStdGroup );
+    aStdLayout->addWidget( myOptimizationLevelCombo, row++, 1, 1, 1 );
+
+    QLabel* splitOverconstrainedLbl = new QLabel( tr("GHS3D_SPLIT_OVERCONSTRAINED"), myStdGroup );
+    aStdLayout->addWidget( splitOverconstrainedLbl, row, 0, 1, 1 );
+    mySplitOverConstrainedCombo = getModeCombo( myStdGroup, false );
+    aStdLayout->addWidget( mySplitOverConstrainedCombo, row++, 1, 1, 1 );
+
+    QLabel* pthreadsModeLbl = new QLabel( tr( "GHS3D_PTHREADS_MODE" ), myStdGroup);
+    aStdLayout->addWidget( pthreadsModeLbl, row, 0, 1, 1 );
+    myPThreadsModeCombo = getModeCombo( myStdGroup, true );
+    aStdLayout->addWidget( myPThreadsModeCombo, row++, 1, 1, 1 );
+
+    QLabel* nbThreadsLbl = new QLabel( tr( "GHS3D_NB_THREADS" ), myStdGroup);
+    aStdLayout->addWidget( nbThreadsLbl, row, 0, 1, 1 );
+    myNumberOfThreadsSpin = new SalomeApp_IntSpinBox( 0, 1000, 1, myStdGroup );
+    aStdLayout->addWidget( myNumberOfThreadsSpin, row++, 1, 1, 1 );
+
+    mySmoothOffSliversCheck = new QCheckBox( tr( "GHS3D_SMOOTH_OFF_SLIVERS" ), myStdGroup );
+    aStdLayout->addWidget( mySmoothOffSliversCheck, row, 0, 1, 1 );
+    myCreateNewNodesCheck = new QCheckBox( tr( "TO_ADD_NODES" ), myStdGroup );
+    aStdLayout->addWidget( myCreateNewNodesCheck, row++, 1, 1, 1 );
   }
   else
   {
-    optimizationLbl->hide();
-    myOptimizationCombo->hide();
-    splitOverconstrainedLbl->hide();
-    mySplitOverConstrainedCombo->hide();
-    pthreadsModeLbl->hide();
-    myPThreadsModeCombo->hide();
-    nbThreadsLbl->hide();
-    myNumberOfThreadsSpin->hide();
-    mySmoothOffSliversCheck->hide();
-    myCreateNewNodesCheck->hide();
+    // Main parameters
+
+    QGroupBox* mainGroup = new QGroupBox( tr("GHS3D_MAIN_PARAMS"), myStdGroup );
+    QLabel* optimizatiolLevelLbl = new QLabel( tr( "GHS3D_OPTIMIZATIOL_LEVEL" ), mainGroup );
+    myOptimizationLevelCombo = new QComboBox( mainGroup );
+    myMinSizeCheck = new QCheckBox( tr("GHS3D_MIN_SIZE"), mainGroup );
+    myMaxSizeCheck = new QCheckBox( tr("GHS3D_MAX_SIZE"), mainGroup );
+    myMinSizeSpin  = new SMESHGUI_SpinBox( mainGroup );
+    myMaxSizeSpin  = new SMESHGUI_SpinBox( mainGroup );
+    myMinSizeCheck->setChecked( false );
+    myMaxSizeCheck->setChecked( false );
+    myMinSizeSpin->RangeStepAndValidator(0, COORD_MAX, 10.0, "length_precision");
+    myMaxSizeSpin->RangeStepAndValidator(0, COORD_MAX, 10.0, "length_precision");
+    myMinSizeSpin->setEnabled( false );
+    myMaxSizeSpin->setEnabled( false );
+    connect( myMinSizeCheck, SIGNAL( toggled(bool)), myMinSizeSpin, SLOT( setEnabled(bool)));
+    connect( myMaxSizeCheck, SIGNAL( toggled(bool)), myMaxSizeSpin, SLOT( setEnabled(bool)));
+
+    QGridLayout* mainLayout = new QGridLayout( mainGroup );
+    mainLayout->setSpacing( 6 );
+    mainLayout->setMargin( 11 );
+    mainLayout->addWidget( optimizatiolLevelLbl,     0, 0, 1, 1 );
+    mainLayout->addWidget( myOptimizationLevelCombo, 0, 1, 1, 1 );
+    mainLayout->addWidget( myMinSizeCheck,           1, 0, 1, 1 );
+    mainLayout->addWidget( myMinSizeSpin,            1, 1, 1, 1 );
+    mainLayout->addWidget( myMaxSizeCheck,           2, 0, 1, 1 );
+    mainLayout->addWidget( myMaxSizeSpin,            2, 1, 1, 1 );
+
+    // Volume proximity
+
+    QGroupBox* proxyGroup = new QGroupBox( tr("GHS3D_VOLUME_PROXIMITY"), myStdGroup );
+    myGradationCheck = new QCheckBox( tr("GHS3D_GRADATION"), proxyGroup );
+    myGradationSpin  = new SMESHGUI_SpinBox( proxyGroup );
+    myGradationSpin->RangeStepAndValidator(1, COORD_MAX, 0.1, "length_precision");
+    myGradationSpin->setEnabled( false );
+    connect( myGradationCheck, SIGNAL( toggled(bool)), myGradationSpin, SLOT( setEnabled(bool)));
+    myUseProximityGroup = new QGroupBox( tr("GHS3D_USE_VOLUME_PROXIMITY"), proxyGroup );
+    myUseProximityGroup->setCheckable( true );
+    //myUseProximityGroup->setChecked( false );
+    QLabel* nbProximityLayersLabel = new QLabel( tr("GHS3D_NB_LAYERS"));
+    myNbProximityLayers = new SalomeApp_IntSpinBox( 2, 1e6, 1, proxyGroup );
+
+    QHBoxLayout* useProxyLayout = new QHBoxLayout( myUseProximityGroup );
+    useProxyLayout->addWidget( nbProximityLayersLabel );
+    useProxyLayout->addWidget( myNbProximityLayers );
+
+    QGridLayout* proxyLayout = new QGridLayout( proxyGroup );
+    proxyLayout->setSpacing( 6 );
+    proxyLayout->setMargin( 11 );
+    proxyLayout->addWidget( myGradationCheck,    0, 0, 1, 1 );
+    proxyLayout->addWidget( myGradationSpin,     0, 1, 1, 1 );
+    proxyLayout->addWidget( myUseProximityGroup, 1, 0, 1, 2 );
+
+    // Other parameters
+
+    QGroupBox* otherGroup = new QGroupBox( tr("GHS3D_OTHER_PARAMETERS"), myStdGroup );
+    myToMeshHolesCheck = new QCheckBox( tr( "GHS3D_TO_MESH_HOLES" ), otherGroup );
+    myToMakeGroupsOfDomains = new QCheckBox( tr( "GHS3D_TO_MAKE_DOMAIN_GROUPS" ), otherGroup );
+
+    QGridLayout* otherLayout = new QGridLayout( otherGroup );
+    otherLayout->setSpacing( 6 );
+    otherLayout->setMargin( 11 );
+    otherLayout->addWidget( myToMeshHolesCheck,      0, 0 );
+    otherLayout->addWidget( myToMakeGroupsOfDomains, 1, 0 );
+
+
+    aStdLayout->addWidget( mainGroup,  row++, 0, 1, 2 );
+    aStdLayout->addWidget( proxyGroup, row++, 0, 1, 2 );
+    aStdLayout->addWidget( otherGroup, row++, 0, 1, 2 );
   }
+  aStdLayout->setRowStretch( row, 10 );
+
+  myOptimizationLevelCombo->addItems( QStringList()
+                                      << tr( "LEVEL_NONE" )   << tr( "LEVEL_LIGHT" )
+                                      << tr( "LEVEL_MEDIUM" ) << tr( "LEVEL_STANDARDPLUS" )
+                                      << tr( "LEVEL_STRONG" ));
 
   // advanced parameters
   myAdvGroup = new QWidget();
@@ -451,24 +523,24 @@ QFrame* GHS3DPluginGUI_HypothesisCreator::buildFrame()
   
   myAdvWidget->memoryGroupBox                ->setTitle(tr( "MEMORY_GROUP_TITLE" ));
   myAdvWidget->logGroupBox                   ->setTitle(tr( "LOG_GROUP_TITLE" ));
-  myAdvWidget->advancedMeshingGroupBox       ->setTitle(tr( "ADVANCED_MESHING_GROUP_TITLE" ));
+  //myAdvWidget->advancedMeshingGroupBox       ->setTitle(tr( "ADVANCED_MESHING_GROUP_TITLE" ));
   
-  myAdvWidget->createNewNodesCheck           ->setText (tr( "TO_ADD_NODES" ));
-  myAdvWidget->removeInitialCentralPointCheck->setText (tr( "NO_INITIAL_CENTRAL_POINT" ));
-  myAdvWidget->boundaryRecoveryCheck         ->setText (tr( "RECOVERY_VERSION" ));
-  myAdvWidget->FEMCorrectionCheck            ->setText (tr( "FEM_CORRECTION" ));
-  myAdvWidget->gradationLabel                ->setText (tr( "GHS3D_GRADATION" ));
-  myAdvWidget->gradationSpinBox->RangeStepAndValidator(0.0, 5.0, 0.05, "length_precision");
-
-  if ( isOptimization() )
-  {
-    myAdvWidget->createNewNodesCheck->hide();
-    myAdvWidget->removeInitialCentralPointCheck->hide();
-    myAdvWidget->boundaryRecoveryCheck->hide();
-    myAdvWidget->FEMCorrectionCheck->hide();
-    myAdvWidget->gradationLabel->hide();
-    myAdvWidget->gradationSpinBox->hide();
-  }
+  // myAdvWidget->createNewNodesCheck           ->setText (tr( "TO_ADD_NODES" ));
+  // myAdvWidget->removeInitialCentralPointCheck->setText (tr( "NO_INITIAL_CENTRAL_POINT" ));
+  // myAdvWidget->boundaryRecoveryCheck         ->setText (tr( "RECOVERY_VERSION" ));
+  // myAdvWidget->FEMCorrectionCheck            ->setText (tr( "FEM_CORRECTION" ));
+  // myAdvWidget->gradationLabel                ->setText (tr( "GHS3D_GRADATION" ));
+  // myAdvWidget->gradationSpinBox->RangeStepAndValidator(0.0, 5.0, 0.05, "length_precision");
+
+  // if ( isOptimization() )
+  // {
+  //   myAdvWidget->createNewNodesCheck->hide();
+  //   myAdvWidget->removeInitialCentralPointCheck->hide();
+  //   myAdvWidget->boundaryRecoveryCheck->hide();
+  //   myAdvWidget->FEMCorrectionCheck->hide();
+  //   myAdvWidget->gradationLabel->hide();
+  //   myAdvWidget->gradationSpinBox->hide();
+  // }
 
   // Enforced vertices parameters
   myEnfGroup = new QWidget();
@@ -619,10 +691,10 @@ QFrame* GHS3DPluginGUI_HypothesisCreator::buildFrame()
 
   connect( myAdvWidget->maxMemoryCheck,             SIGNAL( toggled( bool ) ), this, SLOT( updateWidgets() ) );
   connect( myAdvWidget->initialMemoryCheck,         SIGNAL( toggled( bool ) ), this, SLOT( updateWidgets() ) );
-  connect( myAdvWidget->boundaryRecoveryCheck,      SIGNAL( toggled( bool ) ), this, SLOT( updateWidgets() ) );
   connect( myAdvWidget->logInFileCheck,             SIGNAL( toggled( bool ) ), this, SLOT( updateWidgets() ) );
   connect( myAdvWidget->keepWorkingFilesCheck,      SIGNAL( toggled( bool ) ), this, SLOT( updateWidgets() ) );
   connect( myAdvWidget->workingDirectoryPushButton, SIGNAL( clicked() ),       this, SLOT( onDirBtnClicked() ) );
+  connect( myAdvWidget->addBtn,                     SIGNAL( clicked() ),       this, SLOT( onAddOption() ) );
   
   connect( myEnforcedTableWidget,   SIGNAL( itemClicked(QTableWidgetItem *)), this, SLOT( synchronizeCoords() ) );
   connect( myEnforcedTableWidget,   SIGNAL( itemChanged(QTableWidgetItem *)), this, SLOT( updateEnforcedVertexValues(QTableWidgetItem *) ) );
@@ -769,12 +841,12 @@ void GHS3DPluginGUI_HypothesisCreator::onSelectEnforcedVertex()
     myEnfVertex = myEnfVertexWdg->GetObject< GEOM::GEOM_Object >(nbSelEnfVertex-1);
     if (myEnfVertex == GEOM::GEOM_Object::_nil())
       return;
-    if (myEnfVertex->GetShapeType() == GEOM::VERTEX) {
-      GHS3DPluginGUI_HypothesisCreator* that = (GHS3DPluginGUI_HypothesisCreator*)this;
+    if (myEnfVertex->GetShapeType() == GEOM::VERTEX)
+    {
       GEOM::GEOM_IMeasureOperations_var measureOp = getGeomEngine()->GetIMeasureOperations( );
       if (CORBA::is_nil(measureOp))
         return;
-      
+
       CORBA::Double x,y,z;
       measureOp->PointCoordinates (myEnfVertex, x, y, z);
       if ( measureOp->IsDone() )
@@ -1309,15 +1381,14 @@ void GHS3DPluginGUI_HypothesisCreator::updateWidgets()
 {
   //myToMakeGroupsOfDomains->setEnabled( myToMeshHolesCheck->isChecked() );
   myAdvWidget->maxMemorySpin->setEnabled( myAdvWidget->maxMemoryCheck->isChecked() );
-  myAdvWidget->initialMemoryCheck->setEnabled( !myAdvWidget->boundaryRecoveryCheck->isChecked() );
-  myAdvWidget->initialMemorySpin->setEnabled( myAdvWidget->initialMemoryCheck->isChecked() && !myAdvWidget->boundaryRecoveryCheck->isChecked() );
-  myOptimizationLevelCombo->setEnabled( !myAdvWidget->boundaryRecoveryCheck->isChecked() );
+  //myAdvWidget->initialMemoryCheck->setEnabled( !myAdvWidget->boundaryRecoveryCheck->isChecked() );
+  myAdvWidget->initialMemorySpin->setEnabled( myAdvWidget->initialMemoryCheck->isChecked() /*&& !myAdvWidget->boundaryRecoveryCheck->isChecked()*/ );
+  //myOptimizationLevelCombo->setEnabled( !myAdvWidget->boundaryRecoveryCheck->isChecked() );
   if ( sender() == myAdvWidget->logInFileCheck ||
        sender() == myAdvWidget->keepWorkingFilesCheck )
   {
-    bool logFileRemovable = myAdvWidget->logInFileCheck->isChecked() &&
-      !myAdvWidget->keepWorkingFilesCheck->isChecked();
-
+    bool logFileRemovable = ( myAdvWidget->logInFileCheck->isChecked() &&
+                              !myAdvWidget->keepWorkingFilesCheck->isChecked() );
     myAdvWidget->removeLogOnSuccessCheck->setEnabled( logFileRemovable );
   }
 }
@@ -1331,7 +1402,43 @@ bool GHS3DPluginGUI_HypothesisCreator::checkParams(QString& msg) const
     return false;
   }
 
-  return true;
+  GHS3DPlugin::GHS3DPlugin_Hypothesis_var h =
+    GHS3DPlugin::GHS3DPlugin_Hypothesis::_narrow( hypothesis() );
+
+  myAdvWidget->myOptionTable->setFocus();
+  QApplication::instance()->processEvents();
+
+  QString name, value;
+  bool isDefault, ok = true;
+  int iRow = 0, nbRows = myAdvWidget->myOptionTable->topLevelItemCount();
+  for ( ; iRow < nbRows; ++iRow )
+  {
+    QTreeWidgetItem* row = myAdvWidget->myOptionTable->topLevelItem( iRow );
+    myAdvWidget->GetOptionAndValue( row, name, value, isDefault );
+
+    if ( name.simplified().isEmpty() )
+      continue; // invalid custom option
+
+    if ( isDefault ) // not selected option
+      value.clear();
+
+    try {
+      h->SetOptionValue( name.toLatin1().constData(), value.toLatin1().constData() );
+    }
+    catch ( const SALOME::SALOME_Exception& ex )
+    {
+      msg = ex.details.text.in();
+      ok = false;
+      break;
+    }
+  }
+
+  if ( !ok )
+  {
+    h->SetOptionValues( myOptions ); // restore values
+  }
+
+  return ok;
 }
 
 void GHS3DPluginGUI_HypothesisCreator::retrieveParams() const
@@ -1351,31 +1458,49 @@ void GHS3DPluginGUI_HypothesisCreator::retrieveParams() const
   myToMeshHolesCheck                          ->setChecked    ( data.myToMeshHoles );
   myToMakeGroupsOfDomains                     ->setChecked    ( data.myToMakeGroupsOfDomains );
   myOptimizationLevelCombo                    ->setCurrentIndex( data.myOptimizationLevel );
-  myOptimizationCombo                         ->setCurrentIndex( data.myOptimization );
-  mySplitOverConstrainedCombo                 ->setCurrentIndex( data.mySplitOverConstrained );
-  myPThreadsModeCombo                         ->setCurrentIndex( data.myPThreadsMode );
-  myNumberOfThreadsSpin                       ->setValue      ( data.myNumberOfThreads );
-  mySmoothOffSliversCheck                     ->setChecked    ( data.mySmoothOffSlivers );
-  myCreateNewNodesCheck                       ->setChecked    ( data.myToCreateNewNodes );
-
+  if ( myOptimizationCombo ) // optimizer
+  {
+    myOptimizationCombo                         ->setCurrentIndex( data.myOptimization );
+    mySplitOverConstrainedCombo                 ->setCurrentIndex( data.mySplitOverConstrained );
+    myPThreadsModeCombo                         ->setCurrentIndex( data.myPThreadsMode );
+    myNumberOfThreadsSpin                       ->setValue      ( data.myNumberOfThreads );
+    mySmoothOffSliversCheck                     ->setChecked    ( data.mySmoothOffSlivers );
+    myCreateNewNodesCheck                       ->setChecked    ( data.myToCreateNewNodes );
+  }
+  else
+  {
+    myMinSizeSpin->setValue( data.myMinSize );
+    myMinSizeCheck->setChecked( data.myUseMinSize );
+    myMaxSizeSpin->setValue( data.myMaxSize );
+    myMaxSizeCheck->setChecked( data.myUseMaxSize );
+    myGradationCheck->setChecked( data.myUseGradation );
+    myGradationSpin->setValue( data.myUseGradation ? data.myGradation : GHS3DPlugin_Hypothesis::DefaultGradation() );
+    myUseProximityGroup->setChecked( data.myUseProximity );
+    myNbProximityLayers->setValue( data.myNbProximityLayers );
+  }
   myAdvWidget->maxMemoryCheck                 ->setChecked    ( data.myMaximumMemory > 0 );
-  myAdvWidget->maxMemorySpin                  ->setValue      ( qMax( data.myMaximumMemory,
-                                                                      (float)myAdvWidget->maxMemorySpin->minimum() ));
+  myAdvWidget->maxMemorySpin                  ->setValue
+    ( qMax( data.myMaximumMemory, (float)myAdvWidget->maxMemorySpin->minimum() ));
   myAdvWidget->initialMemoryCheck             ->setChecked    ( data.myInitialMemory > 0 );
-  myAdvWidget->initialMemorySpin              ->setValue      ( qMax( data.myInitialMemory,
-                                                                      (float)myAdvWidget->initialMemorySpin->minimum() ));
+  myAdvWidget->initialMemorySpin              ->setValue
+    ( qMax( data.myInitialMemory, (float)myAdvWidget->initialMemorySpin->minimum() ));
   myAdvWidget->workingDirectoryLineEdit       ->setText       ( data.myWorkingDir );
   myAdvWidget->keepWorkingFilesCheck           ->setChecked    ( data.myKeepFiles );
   myAdvWidget->verboseLevelSpin               ->setValue      ( data.myVerboseLevel );
-  myAdvWidget->createNewNodesCheck            ->setChecked    ( data.myToCreateNewNodes );
-  myAdvWidget->removeInitialCentralPointCheck ->setChecked    ( data.myRemoveInitialCentralPoint );
-  myAdvWidget->boundaryRecoveryCheck          ->setChecked    ( data.myBoundaryRecovery );
-  myAdvWidget->FEMCorrectionCheck             ->setChecked    ( data.myFEMCorrection );
-  myAdvWidget->gradationSpinBox               ->setValue      ( data.myGradation );
-  myAdvWidget->advOptionTable                 ->SetCustomOptions( data.myTextOption );
   myAdvWidget->logInFileCheck                 ->setChecked    ( !data.myLogInStandardOutput );
   myAdvWidget->removeLogOnSuccessCheck        ->setChecked    ( data.myRemoveLogOnSuccess );
 
+  if ( myOptions.operator->() ) {
+    for ( int i = 0, nb = myOptions->length(); i < nb; ++i )
+      myAdvWidget->AddOption( that->myOptions[i].in() );
+  }
+  if ( myCustomOptions.operator->() ) {
+    for ( int i = 0, nb = myCustomOptions->length(); i < nb; ++i )
+      myAdvWidget->AddOption( that->myCustomOptions[i].in() );
+  }
+  myAdvWidget->myOptionTable->resizeColumnToContents( OPTION_NAME_COLUMN );
+
+
   TEnfVertexList::const_iterator it;
   int rowCount = 0;
   myEnforcedTableWidget->clearContents();
@@ -1535,20 +1660,17 @@ QString GHS3DPluginGUI_HypothesisCreator::storeParams() const
   if ( data.myRemoveInitialCentralPoint )
     valStr += " --no_initial_central_point";
     
-  if ( data.myBoundaryRecovery )
-    valStr += " -C";
+  // if ( data.myBoundaryRecovery )
+  //   valStr += " -C";
     
-  if ( data.myFEMCorrection )
-    valStr += " -FEM";
+  // if ( data.myFEMCorrection )
+  //   valStr += " -FEM";
     
   if ( data.myGradation != 1.05 ) {
     valStr += " -Dcpropa=";
     valStr += QString::number( data.myGradation );
   }
     
-  valStr += " ";
-  valStr += data.myTextOption;
-
   return valStr;
 }
 
@@ -1570,31 +1692,47 @@ bool GHS3DPluginGUI_HypothesisCreator::readParamsFromHypo( GHS3DHypothesisData&
     h_data.myNumberOfThreads      = opt->GetMaximalNumberOfThreads();
     h_data.mySmoothOffSlivers     = opt->GetSmoothOffSlivers();
   }
-  else // avoid "Conditional jump or move depends on uninitialised value" error
+  else
   {
+    // avoid "Conditional jump or move depends on uninitialised value" error
     h_data.myOptimization         = 1;
     h_data.mySplitOverConstrained = 1;
     h_data.myPThreadsMode         = 1;
     h_data.myNumberOfThreads      = 1;
     h_data.mySmoothOffSlivers     = 1;
   }
+  h_data.myOptimizationLevel          = h->GetOptimizationLevel();
+  h_data.myMinSize                    = h->GetMinSize();
+  h_data.myMaxSize                    = h->GetMaxSize();
+  this->myMinSizeDefault              = h->GetMinSizeDefault();
+  this->myMaxSizeDefault              = h->GetMaxSizeDefault();
+  if ( ! ( h_data.myUseMinSize        = h_data.myMinSize > 0 ))
+    h_data.myMinSize                  = this->myMinSizeDefault;
+  if ( ! ( h_data.myUseMaxSize        = h_data.myMaxSize > 0 ))
+    h_data.myMaxSize                  = this->myMaxSizeDefault;
+  h_data.myNbProximityLayers          = h->GetNbVolumeProximityLayers();
+  h_data.myUseGradation               = h->GetGradation() != GHS3DPlugin_Hypothesis::DefaultGradation();
+  h_data.myUseProximity               = h->GetVolumeProximity();
   h_data.myToMeshHoles                = h->GetToMeshHoles();
   h_data.myToMakeGroupsOfDomains      = h->GetToMakeGroupsOfDomains();
   h_data.myMaximumMemory              = h->GetMaximumMemory();
   h_data.myInitialMemory              = h->GetInitialMemory();
   h_data.myInitialMemory              = h->GetInitialMemory();
-  h_data.myOptimizationLevel          = h->GetOptimizationLevel();
   h_data.myKeepFiles                  = h->GetKeepFiles();
   h_data.myWorkingDir                 = h->GetWorkingDirectory();
   h_data.myVerboseLevel               = h->GetVerboseLevel();
   h_data.myToCreateNewNodes           = h->GetToCreateNewNodes();
-  h_data.myRemoveInitialCentralPoint  = h->GetToRemoveCentralPoint();
-  h_data.myBoundaryRecovery           = h->GetToUseBoundaryRecoveryVersion();
-  h_data.myFEMCorrection              = h->GetFEMCorrection();
+  //h_data.myRemoveInitialCentralPoint  = h->GetToRemoveCentralPoint();
+  //h_data.myBoundaryRecovery           = h->GetToUseBoundaryRecoveryVersion();
+  //h_data.myFEMCorrection              = h->GetFEMCorrection();
   h_data.myGradation                  = h->GetGradation();
-  h_data.myTextOption                 = h->GetAdvancedOption();
+  //h_data.myTextOption                 = h->GetAdvancedOption();
   h_data.myLogInStandardOutput        = h->GetStandardOutputLog();
   h_data.myRemoveLogOnSuccess         = h->GetRemoveLogOnSuccess();
+
+  GHS3DPluginGUI_HypothesisCreator* that = (GHS3DPluginGUI_HypothesisCreator*)this;
+  that->myOptions       = h->GetOptionValues();
+  that->myCustomOptions = h->GetAdvancedOptionValues();
   
   GHS3DPlugin::GHS3DEnforcedVertexList_var vertices = h->GetEnforcedVertices();
   h_data.myEnforcedVertices.clear();
@@ -1651,43 +1789,31 @@ bool GHS3DPluginGUI_HypothesisCreator::storeParamsToHypo( const GHS3DHypothesisD
     if( isCreation() )
       SMESH::SetName( SMESH::FindSObject( h ), h_data.myName.toLatin1().constData() );
 
-    if ( h->GetToMeshHoles() != h_data.myToMeshHoles ) // avoid duplication of DumpPython commands
-      h->SetToMeshHoles      ( h_data.myToMeshHoles       );
-    if ( h->GetToMakeGroupsOfDomains() != h_data.myToMakeGroupsOfDomains )
-      h->SetToMakeGroupsOfDomains( h_data.myToMakeGroupsOfDomains );
-    if ( h->GetMaximumMemory() != h_data.myMaximumMemory )
-      h->SetMaximumMemory    ( h_data.myMaximumMemory     );
-    if ( h->GetInitialMemory() != h_data.myInitialMemory )
-      h->SetInitialMemory    ( h_data.myInitialMemory     );
-    if ( h->GetInitialMemory() != h_data.myInitialMemory )
-      h->SetInitialMemory    ( h_data.myInitialMemory     );
-    if ( h->GetOptimizationLevel() != h_data.myOptimizationLevel )
-      h->SetOptimizationLevel( h_data.myOptimizationLevel );
-    if ( h->GetKeepFiles() != h_data.myKeepFiles         )
-      h->SetKeepFiles        ( h_data.myKeepFiles         );
-    if ( h->GetWorkingDirectory() != h_data.myWorkingDir )
-      h->SetWorkingDirectory ( h_data.myWorkingDir.toLatin1().constData() );
-    if ( h->GetVerboseLevel() != h_data.myVerboseLevel   )
-      h->SetVerboseLevel     ( h_data.myVerboseLevel      );
-    if ( h->GetToCreateNewNodes() != h_data.myToCreateNewNodes )
-      h->SetToCreateNewNodes( h_data.myToCreateNewNodes   );
-    if ( h->GetToRemoveCentralPoint() != h_data.myRemoveInitialCentralPoint )
-      h->SetToRemoveCentralPoint( h_data.myRemoveInitialCentralPoint );
-    if ( h->GetToUseBoundaryRecoveryVersion() != h_data.myBoundaryRecovery )
-      h->SetToUseBoundaryRecoveryVersion( h_data.myBoundaryRecovery );
-    if ( h->GetFEMCorrection() != h_data.myFEMCorrection )
-      h->SetFEMCorrection    ( h_data.myFEMCorrection     );
-    if ( h->GetGradation() != h_data.myGradation         )
-      h->SetGradation        ( h_data.myGradation         );
-    if ( h->GetAdvancedOption() != h_data.myTextOption       )
-      h->SetAdvancedOption       ( h_data.myTextOption.toLatin1().constData() );
-    if ( h->GetStandardOutputLog() != h_data.myLogInStandardOutput   )
-      h->SetStandardOutputLog( h_data.myLogInStandardOutput  );
-    if ( h->GetRemoveLogOnSuccess() != h_data.myRemoveLogOnSuccess   )
-      h->SetRemoveLogOnSuccess( h_data.myRemoveLogOnSuccess  );
+    h->SetOptimizationLevel           ( h_data.myOptimizationLevel );
+    h->SetMinSize                     ( h_data.myUseMinSize ? h_data.myMinSize : 0 );
+    h->SetMaxSize                     ( h_data.myUseMaxSize ? h_data.myMaxSize : 0 );
+    h->SetMinMaxSizeDefault           ( this->myMinSizeDefault, this->myMaxSizeDefault );
+    h->SetGradation                   ( h_data.myGradation         );
+    h->SetVolumeProximity             ( h_data.myUseProximity      );
+    h->SetNbVolumeProximityLayers     ( h_data.myNbProximityLayers );
+    h->SetToMeshHoles                 ( h_data.myToMeshHoles       );
+    h->SetToMakeGroupsOfDomains       ( h_data.myToMakeGroupsOfDomains );
+
+    h->SetMaximumMemory               ( h_data.myMaximumMemory     );
+    h->SetInitialMemory               ( h_data.myInitialMemory     );
+    h->SetInitialMemory               ( h_data.myInitialMemory     );
+    h->SetKeepFiles                   ( h_data.myKeepFiles         );
+    h->SetWorkingDirectory            ( h_data.myWorkingDir.toLatin1().constData() );
+    h->SetVerboseLevel                ( h_data.myVerboseLevel      );
+    //h->SetToRemoveCentralPoint        ( h_data.myRemoveInitialCentralPoint );
+    //h->SetToUseBoundaryRecoveryVersion( h_data.myBoundaryRecovery  );
+    //h->SetFEMCorrection               ( h_data.myFEMCorrection     );
+    h->SetStandardOutputLog           ( h_data.myLogInStandardOutput );
+    h->SetRemoveLogOnSuccess          ( h_data.myRemoveLogOnSuccess  );
 
     if ( !opt->_is_nil() )
     {
+      opt->SetToCreateNewNodes      ( h_data.myToCreateNewNodes  );
       opt->SetOptimization          ( (GHS3DPlugin::Mode) h_data.myOptimization );
       opt->SetSplitOverConstrained  ( (GHS3DPlugin::Mode) h_data.mySplitOverConstrained );
       opt->SetPThreadsMode          ( (GHS3DPlugin::PThreadsMode) h_data.myPThreadsMode );
@@ -1750,7 +1876,7 @@ bool GHS3DPluginGUI_HypothesisCreator::storeParamsToHypo( const GHS3DHypothesisD
       default:
         break;
       }
-    
+
       ok = h->p_SetEnforcedMesh(theSource, elementType, enfMesh->name.c_str(), enfMesh->groupName.c_str());
     } // for
   } // try
@@ -1764,32 +1890,38 @@ bool GHS3DPluginGUI_HypothesisCreator::storeParamsToHypo( const GHS3DHypothesisD
 
 bool GHS3DPluginGUI_HypothesisCreator::readParamsFromWidgets( GHS3DHypothesisData& h_data ) const
 {
-  h_data.myName                       = myName ? myName->text() : "";
-  h_data.myToMeshHoles                = myToMeshHolesCheck->isChecked();
-  h_data.myToMakeGroupsOfDomains      = myToMakeGroupsOfDomains->isChecked();
-  h_data.myOptimization               = myOptimizationCombo->currentIndex();
-  h_data.myOptimizationLevel          = myOptimizationLevelCombo->currentIndex();
-  h_data.mySplitOverConstrained       = mySplitOverConstrainedCombo->currentIndex();
-  h_data.myPThreadsMode               = myPThreadsModeCombo->currentIndex();
-  h_data.myNumberOfThreads            = myNumberOfThreadsSpin->value();
-  h_data.mySmoothOffSlivers           = mySmoothOffSliversCheck->isChecked();
-  h_data.myMaximumMemory              = myAdvWidget->maxMemoryCheck->isChecked() ? myAdvWidget->maxMemorySpin->value() : -1;
-  h_data.myInitialMemory              = myAdvWidget->initialMemoryCheck->isChecked() ? myAdvWidget->initialMemorySpin->value() : -1;
-  h_data.myKeepFiles                  = myAdvWidget->keepWorkingFilesCheck->isChecked();
-  h_data.myWorkingDir                 = myAdvWidget->workingDirectoryLineEdit->text().trimmed();
-  h_data.myVerboseLevel               = myAdvWidget->verboseLevelSpin->value();
-  h_data.myRemoveInitialCentralPoint  = myAdvWidget->removeInitialCentralPointCheck->isChecked();
-  h_data.myBoundaryRecovery           = myAdvWidget->boundaryRecoveryCheck->isChecked();
-  h_data.myFEMCorrection              = myAdvWidget->FEMCorrectionCheck->isChecked();
-  h_data.myGradation                  = myAdvWidget->gradationSpinBox->value();
-  h_data.myTextOption                 = myAdvWidget->advOptionTable->GetCustomOptions();
-  h_data.myLogInStandardOutput        = !myAdvWidget->logInFileCheck->isChecked();
-  h_data.myRemoveLogOnSuccess         = myAdvWidget->removeLogOnSuccessCheck->isChecked();
-  if ( isOptimization() )
-    h_data.myToCreateNewNodes         = myCreateNewNodesCheck->isChecked();
+  h_data.myName                    = myName ? myName->text() : "";
+  h_data.myOptimizationLevel       = myOptimizationLevelCombo->currentIndex();
+  if ( mySplitOverConstrainedCombo ) // optimizer
+  {
+    h_data.myToCreateNewNodes      = myCreateNewNodesCheck->isChecked();
+    h_data.myOptimization          = myOptimizationCombo->currentIndex();
+    h_data.mySplitOverConstrained  = mySplitOverConstrainedCombo->currentIndex();
+    h_data.myPThreadsMode          = myPThreadsModeCombo->currentIndex();
+    h_data.myNumberOfThreads       = myNumberOfThreadsSpin->value();
+    h_data.mySmoothOffSlivers      = mySmoothOffSliversCheck->isChecked();
+  }
   else
-    h_data.myToCreateNewNodes         = myAdvWidget->createNewNodesCheck->isChecked();
-  
+  {
+    h_data.myMinSize               = myMinSizeSpin->value();
+    h_data.myMaxSize               = myMaxSizeSpin->value();
+    h_data.myUseMinSize            = myMinSizeCheck->isChecked();
+    h_data.myUseMaxSize            = myMaxSizeCheck->isChecked();
+    h_data.myGradation             = myGradationSpin->value();
+    h_data.myUseGradation          = myGradationCheck->isChecked();
+    h_data.myUseProximity          = myUseProximityGroup->isChecked();
+    h_data.myNbProximityLayers     = myNbProximityLayers->value();
+    h_data.myToMeshHoles           = myToMeshHolesCheck->isChecked();
+    h_data.myToMakeGroupsOfDomains = myToMakeGroupsOfDomains->isChecked();
+  }
+  h_data.myMaximumMemory           = myAdvWidget->maxMemoryCheck->isChecked() ? myAdvWidget->maxMemorySpin->value() : -1;
+  h_data.myInitialMemory           = myAdvWidget->initialMemoryCheck->isChecked() ? myAdvWidget->initialMemorySpin->value() : -1;
+  h_data.myKeepFiles               = myAdvWidget->keepWorkingFilesCheck->isChecked();
+  h_data.myWorkingDir              = myAdvWidget->workingDirectoryLineEdit->text().trimmed();
+  h_data.myVerboseLevel            = myAdvWidget->verboseLevelSpin->value();
+  h_data.myLogInStandardOutput     = !myAdvWidget->logInFileCheck->isChecked();
+  h_data.myRemoveLogOnSuccess      = myAdvWidget->removeLogOnSuccessCheck->isChecked();
+
   // Enforced vertices
   h_data.myEnforcedVertices.clear();
   QVariant valueX, valueY, valueZ;
@@ -1848,3 +1980,8 @@ QString GHS3DPluginGUI_HypothesisCreator::helpPage() const
 {
   return isOptimization() ? "optimization_page.html" : "ghs3d_hypo_page.html";
 }
+
+void GHS3DPluginGUI_HypothesisCreator::onAddOption()
+{
+  myAdvWidget->AddOption( NULL, true );
+}
index 4f979dce8c9d15eaa3734742e3aada959843c898..6437f418cbdbd77f2f1699480ef6ed684f4e35ef 100644 (file)
@@ -56,6 +56,7 @@ class QSpinBox;
 class QTableWidget;
 class QTableWidgetItem;
 class QHeaderView;
+class QGroupBox;
 
 class GHS3DPluginGUI_AdvWidget;
 class LightApp_SelectionMgr;
@@ -142,13 +143,16 @@ typedef std::set< TEnfMesh*, CompareEnfMeshes > TEnfMeshList;
 
 typedef struct
 {
-  bool    myToMeshHoles,myToMakeGroupsOfDomains,myKeepFiles,myToCreateNewNodes,myBoundaryRecovery,myFEMCorrection,myRemoveInitialCentralPoint,
-          myLogInStandardOutput, myRemoveLogOnSuccess;
-  float   myMaximumMemory;
-  float   myInitialMemory;
   int     myOptimizationLevel;
-  QString myName,myWorkingDir,myTextOption;
+  double  myMinSize, myMaxSize, myMinSizeDefault, myMaxSizeDefault;
   double  myGradation;
+  int     myNbProximityLayers;
+  bool    myUseMinSize, myUseMaxSize, myUseGradation, myUseProximity;
+  bool    myToMeshHoles, myToMakeGroupsOfDomains;
+  bool    myToCreateNewNodes,myBoundaryRecovery,myFEMCorrection,myRemoveInitialCentralPoint,
+          myKeepFiles,myLogInStandardOutput, myRemoveLogOnSuccess;
+  float   myInitialMemory, myMaximumMemory;
+  QString myName,myWorkingDir;
   short   myVerboseLevel;
   TEnfVertexList myEnforcedVertices;
   TEnfMeshList myEnforcedMeshes;
@@ -182,6 +186,7 @@ protected:
   virtual QString  type() const;
 
 protected slots:
+  void                onAddOption();
   void                onToMeshHoles(bool);
   void                onDirBtnClicked();
   void                updateWidgets();
@@ -219,9 +224,21 @@ private:
 private:
   QWidget*              myStdGroup;
   QLineEdit*            myName;
-  QCheckBox*            myToMeshHolesCheck;
-  QCheckBox*            myToMakeGroupsOfDomains;
+  // main
   QComboBox*            myOptimizationLevelCombo;
+  QCheckBox*            myMinSizeCheck;
+  QCheckBox*            myMaxSizeCheck;
+  SMESHGUI_SpinBox*     myMinSizeSpin;
+  SMESHGUI_SpinBox*     myMaxSizeSpin;
+  mutable double        myMinSizeDefault, myMaxSizeDefault;
+  // proximity
+  QCheckBox*            myGradationCheck;
+  SMESHGUI_SpinBox*     myGradationSpin;
+  QGroupBox*            myUseProximityGroup;
+  SalomeApp_IntSpinBox* myNbProximityLayers;
+  // other
+  QCheckBox*            myToMakeGroupsOfDomains;
+  QCheckBox*            myToMeshHolesCheck;
 
   QComboBox*            myOptimizationCombo;
   QComboBox*            mySplitOverConstrainedCombo;
@@ -232,6 +249,8 @@ private:
 
   QWidget*                  myAdvGroup;
   GHS3DPluginGUI_AdvWidget* myAdvWidget;
+  mutable GHS3DPlugin::string_array_var myOptions, myCustomOptions;
+
   
   QWidget*              myEnfGroup;
   QPixmap               iconVertex, iconCompound;
diff --git a/src/GUI/GHS3DPluginGUI_TreeWidget.cxx b/src/GUI/GHS3DPluginGUI_TreeWidget.cxx
new file mode 100644 (file)
index 0000000..8511275
--- /dev/null
@@ -0,0 +1,91 @@
+// Copyright (C) 2007-2019  CEA/DEN, EDF R&D
+//
+// 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
+//
+
+#include "GHS3DPluginGUI_TreeWidget.h"
+#include <QKeyEvent>
+
+namespace
+{
+  bool isEditable( const QModelIndex& index )
+  {
+    return index.isValid() &&
+      index.flags() & Qt::ItemIsEditable && 
+      index.flags() & Qt::ItemIsEnabled &&
+      ( !index.data( Qt::UserRole + 1 ).isValid() || index.data( Qt::UserRole + 1 ).toInt() != 0 );
+  }
+}
+
+GHS3DPluginGUI_TreeWidget::GHS3DPluginGUI_TreeWidget( QWidget* parent )
+  : QTreeWidget( parent )
+{
+}
+
+QModelIndex GHS3DPluginGUI_TreeWidget::moveCursor( CursorAction action, Qt::KeyboardModifiers modifiers )
+{
+  QModelIndex current = currentIndex();
+  int column = current.column();
+  if ( action == MoveNext ) {
+    if ( column < columnCount()-1 ) {
+      QModelIndex next = current.sibling( current.row(), column+1 );
+      if ( isEditable( next ) )
+        return next;
+    }
+    else {
+      QModelIndex next = current.sibling( current.row()+1, 0 );
+      if ( isEditable( next ) )
+        return next;
+    }
+  }
+  else if ( action == MovePrevious ) {
+    if ( column == 0 ) {
+      QModelIndex next = current.sibling( current.row()-1, columnCount()-1 );
+      if ( isEditable( next ) )
+        return next;
+    }
+    else {
+      QModelIndex next = current.sibling( current.row(), column-1 );
+      if ( isEditable( next ) )
+        return next;
+    }
+  }
+  return QTreeWidget::moveCursor( action, modifiers );
+}
+
+void GHS3DPluginGUI_TreeWidget::keyPressEvent( QKeyEvent* e )
+{
+  switch ( e->key() ) {
+  case Qt::Key_F2:
+    {
+      QModelIndex index = currentIndex();
+      if ( !isEditable( index ) ) {
+        for ( int i = 0; i < columnCount(); i++ ) {
+          QModelIndex sibling = index.sibling( index.row(), i );
+          if ( isEditable( sibling ) ) {
+            if ( !edit( sibling, EditKeyPressed, e ) )
+              e->ignore();
+          }
+        }
+      }
+    }
+    break;
+  default:
+    break;
+  }
+  QTreeWidget::keyPressEvent( e );
+}
diff --git a/src/GUI/GHS3DPluginGUI_TreeWidget.h b/src/GUI/GHS3DPluginGUI_TreeWidget.h
new file mode 100644 (file)
index 0000000..e80b3e2
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright (C) 2007-2019  CEA/DEN, EDF R&D
+//
+// 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
+//
+
+#if !defined(GHS3DPluginGUI_TreeWidget_H)
+#define GHS3DPluginGUI_TreeWidget_H
+
+#include <QTreeWidget>
+
+class GHS3DPluginGUI_TreeWidget : public QTreeWidget
+{
+  Q_OBJECT
+public:
+  GHS3DPluginGUI_TreeWidget( QWidget* );
+
+protected:
+  QModelIndex moveCursor( CursorAction, Qt::KeyboardModifiers );
+  void keyPressEvent( QKeyEvent* );
+};
+
+#endif // GHS3DPluginGUI_TreeWidget_H
index b90dc6d54f96fe7f1b76ddf0eea5b24e83ab1214..52714931a741d43d2b3f8b4be560eb296abf37c0 100644 (file)
         <source>GHS3D_SMOOTH_OFF_SLIVERS</source>
         <translation>Smooth off sliver elements</translation>
     </message>
+    <message>
+        <source>OPTION_TYPE_COLUMN</source>
+        <translation>Type</translation>
+    </message>
+    <message>
+        <source>OPTION_NAME_COLUMN</source>
+        <translation>Option</translation>
+    </message>
+    <message>
+        <source>OPTION_VALUE_COLUMN</source>
+        <translation>Value</translation>
+    </message>
+    <message>
+        <source>GHS3D_ADD_OPTION</source>
+        <translation>Add option</translation>
+    </message>
+    <message>
+        <source>GHS3D_MAIN_PARAMS</source>
+        <translation>Main parameters</translation>
+    </message>
+    <message>
+        <source>GHS3D_MIN_SIZE</source>
+        <translation>Minimal size</translation>
+    </message>
+    <message>
+        <source>GHS3D_MAX_SIZE</source>
+        <translation>Maximal size</translation>
+    </message>
+    <message>
+        <source>GHS3D_VOLUME_PROXIMITY</source>
+        <translation>Volume proximity</translation>
+    </message>
+    <message>
+        <source>GHS3D_USE_VOLUME_PROXIMITY</source>
+        <translation>Use volume proximity</translation>
+    </message>
+    <message>
+        <source>GHS3D_NB_LAYERS</source>
+        <translation>Number of layers</translation>
+    </message>
+    <message>
+        <source>GHS3D_OTHER_PARAMETERS</source>
+        <translation>Other parameters</translation>
+    </message>
+    <message>
+        <source>no_initial_central_point</source>
+        <translation>No central point</translation>
+    </message>
+    <message>
+        <source>force_max_size</source>
+        <translation>Force maximum edge size</translation>
+    </message>
+    <message>
+        <source>apply_gradation_on_skin_vertex_sizes</source>
+        <translation>Gradation on skin</translation>
+    </message>
+    <message>
+        <source>optimise_worst_elements</source>
+        <translation>Optimise worst elements</translation>
+    </message>
+    <message>
+        <source>force_output_quadratic_mesh</source>
+        <translation>Force quadratic mesh</translation>
+    </message>
+    <message>
+        <source>rectify_jacobian</source>
+        <translation>Rectify jacobian</translation>
+    </message>
+    <message>
+        <source>jacobian_rectification_respect_input_surface_mesh</source>
+        <translation>Respect surface mesh</translation>
+    </message>
+    <message>
+        <source>max_number_of_errors_printed</source>
+        <translation>Max number of errors</translation>
+    </message>
+    <message>
+        <source>max_number_of_threads</source>
+        <translation>Maximal number of threads</translation>
+    </message>
+    <message>
+        <source>target_quality</source>
+        <translation>Target quality</translation>
+    </message>
+    <message>
+        <source>sliver_angle</source>
+        <translation>Sliver angle</translation>
+    </message>
+    <message>
+        <source>pthreads_mode</source>
+        <translation>Mode of pthreads</translation>
+    </message>
+    <message>
+        <source>boundary_regeneration</source>
+        <translation>Boundary regeneration</translation>
+    </message>
+    <message>
+        <source>split_overconstrained_tetrahedra</source>
+        <translation>Remove overconstrained tetrahedra</translation>
+    </message>
+    <message>
+        <source>_</source>
+        <translation> </translation>
+    </message>
 </context>
 </TS>